protected double[] evaluateGradient(double[] x){
      double[] grad = new double[x.length];
      for(int i=0; i<m_Classes.length; i++){ // ith bag
        int nI = m_Data[i][0].length; // numInstances in ith bag 

        double denom=0.0;	
        double[] numrt = new double[x.length];

        for(int j=0; j<nI; j++){
          double exp=0.0;
          for(int k=0; k<m_Data[i].length; k++)
            exp += (m_Data[i][k][j]-x[k*2])*(m_Data[i][k][j]-x[k*2])
              *x[k*2+1]*x[k*2+1];			
          exp = Math.exp(-exp);
          exp = 1.0-exp;
          if(m_Classes[i]==1)
            denom += Math.log(exp);		   		    

          if(exp<=m_Zero) exp=m_Zero;
          // Instance-wise update
          for(int p=0; p<m_Data[i].length; p++){  // pth variable
            numrt[2*p] += (1.0-exp)*2.0*(x[2*p]-m_Data[i][p][j])*x[p*2+1]*x[p*2+1]
              /exp;
            numrt[2*p+1] += 2.0*(1.0-exp)*(x[2*p]-m_Data[i][p][j])*(x[2*p]-m_Data[i][p][j])
              *x[p*2+1]/exp;
          }					    
        }		    

        // Bag-wise update 
        denom = 1.0-Math.exp(denom);
        if(denom <= m_Zero) denom = m_Zero;
        for(int q=0; q<m_Data[i].length; q++){
          if(m_Classes[i]==1){
            grad[2*q] += numrt[2*q]*(1.0-denom)/denom;
            grad[2*q+1] += numrt[2*q+1]*(1.0-denom)/denom;
          }else{
            grad[2*q] -= numrt[2*q];
            grad[2*q+1] -= numrt[2*q+1];
          }
        }
      } // one bag

      return grad;
    }