예제 #1
0
/////////////////////////////////////////////////////////////////////////////
// Steepest descent
/////////////////////////////////////////////////////////////////////////////
void CDiffFunction::SteepestDescent(std::vector<double> &vMax, bool fTrace)
{
 const std::vector<double> &vG = GetGradient();
 int n = GetDimensions();

 //
 // Loop of iterations
 //
 for (int Iteration = MaxSDIterations; --Iteration >= 0;)
 {
  GetOutput(&vMax[0]);
  ComputeGradient();

  //
  // Maximize in gradient direction
  //
  vGCopy = vG;
  double x = LineOpt(&vMax[0], &vGCopy[0], fTrace);

  double Delta2 = 0.0;

  for (int i = n; --i >= 0;)
  {
   double New = Normalize(vMax[i] + x * vGCopy[i]);
   double Delta = New - vMax[i];
   vMax[i] = New;
   Delta2 += Delta * Delta;
  }

  if (Delta2 < CGEpsilon)
   break;
 }
}
예제 #2
0
template <class T> bool
karbtest (Connector<T>* rc) {

	GradientParams gp;

	std::string in_file;// = std::string (base + "/" + std::string(rc->GetElement("/config/data-in")->Attribute("fname")));
	std::string out_file;// = std::string (base + "/" + rc->GetElement("/config/data-out")->Attribute("fname"));

	bool   simann  = false;
	size_t hpoints = 1;
	rc->Attribute ("simann",   &simann);
	rc->Attribute ("hpoints",  &hpoints);

	if (simann) {

		double coolrate, startt, finalt;
		size_t coolit;
		bool   verbose, exchange;
		
		rc->Attribute ("coolrate", &coolrate);
		rc->Attribute ("startt",   &startt);
		rc->Attribute ("finalt",   &finalt);
		rc->Attribute ("coolit",   &coolit);
		rc->Attribute ("verbose",  &verbose);
		rc->Attribute ("exchange", &exchange);
		
		SimulatedAnnealing sa (gp.k, coolit, startt, finalt, coolrate, verbose, exchange);
		sa.Cool();
		gp.k = sa.GetSolution();
		
	}
	
	rc->Attribute ("maxgrad", &(gp.mgr));
	rc->Attribute ("maxslew", &(gp.msr));
	rc->Attribute ("dt",      &(gp.dt));
	
	rc->Attribute ("gunits",  &(gp.gunits));
	rc->Attribute ("lunits",  &(gp.lunits));
	
	Matrix<double> x  = linspace<double> (0.0,1.0,size(gp.k,0));
	Matrix<double> xi = linspace<double> (0.0,1.0,size(gp.k,0)*hpoints);

	gp.k = interp1 (x, gp.k, xi, INTERP::AKIMA);

	printf ("\nComputing trajectory for ... \n");
	printf ("    [maxgrad: %.2f, maxslew: %.2f, dt: %.2e]\n\n", gp.mgr, gp.msr, gp.dt);
	
    SimpleTimer st ("VD spiral design");
	Solution s = ComputeGradient (gp);
    st.Stop();
	
    IOContext f = fopen (out_file.c_str(), WRITE);
    s.dump (f);
    fclose (f);
	

	return true;

}
bool
PotentialFieldSolver::m_ComputeGradient()
{
	m_grid_gradPhi->memset(make_double3(0,0,0));
	ComputeGradient(m_grid_phi->getDevicePtr(),m_grid_gradPhi->getDevicePtr(),
		m_SpatialHasher_mass.getCellSize().x,1.0,m_gridx,m_gridy,m_gridz);

	return true;
}
예제 #4
0
파일: VDSpiral.hpp 프로젝트: kvahed/codeare
Solution VDSpiral (SpiralParams& sp) {

	GradientParams gp;

	Matrix<double>& fov = sp.fov; 
	Matrix<double>& rad = sp.rad; 
	double k_max, fov_max, dr;
	Matrix<double> r, theta;
	long n = 0;

	assert (numel(rad) >= 2);
	assert (isvec(rad) == isvec(fov));
	assert (numel(rad) == numel(fov));

	k_max   = 5.0 / sp.res;
	fov_max = m_max(fov);

	dr  = sp.shots / (fov_max);
	n   = size(fov,1)*100;
	r   = linspace<double> (0.0, k_max, n);
	
	Matrix<double> x = k_max*rad;
	fov = interp1 (x, fov, r, INTERP::LINEAR);

	dr  = sp.shots / (1500.0 * fov_max);
	n   = ceil (k_max/dr);
	x   = r;
	r   = linspace<double> (0.0, k_max, n);

	fov = interp1 (x, fov, r, INTERP::AKIMA);

	theta = cumsum ((2 * PI * dr / sp.shots) * fov);

	gp.k = Matrix<double> (numel(r), 3);

	for (size_t i = 0; i < numel(r); i++) {
		gp.k(i,0) = r[i] * cos (theta[i]);
		gp.k(i,1) = r[i] * sin (theta[i]);
	}

	gp.mgr     = sp.mgr;
	gp.msr     = sp.msr;
	gp.dt      = sp.dt;
	gp.gunits  = sp.gunits;
	gp.lunits  = sp.lunits;

	Solution s = ComputeGradient (gp);
	
	return s;

}
예제 #5
0
vec4 RenderVectorGraphics( vec2 vertexPosition, vec3 bezierKLM, vec2 texUV, float pathOffset ) \n\
{ \n\
	float alphaBlending2 = alphaBlending; \n\
	vec4 fragColor = brushColor; \n\
	// switch-case not working with intel graphics cards? \n\
	//switch( gradientType ){ \n\
	//case 0: break; \n\
	//case 1: fragColor = ComputeLinearGradient( vertexPosition ); break; \n\
	//case 2: fragColor = ComputeRadialGradient( vertexPosition ); break; \n\
	//} \n\
	if( dashCount > 0 ) alphaBlending2 *= HandleDash( pathOffset ); \n\
	if( gradientType > 0 ) fragColor = ComputeGradient( vertexPosition, pathOffset ); \n\
	if( textureCount > 0 ) fragColor = texture( textures[0], texUV ); \n\
	float klm = abs( bezierKLM[0] ) + abs( bezierKLM[1] ) + abs( bezierKLM[2] ); \n\
	if( klm > 1E-16 ) fragColor = ComputeCubicBezier( bezierKLM, fragColor ); \n\
	//fragColor = ComputeQuadraticBezier( vec2( texcoord ), fragColor ); \n\
	fragColor.a *= alphaBlending2; \n\
	return fragColor; \n\
}";
예제 #6
0
/////////////////////////////////////////////////////////////////////////////
// Newton-Raphson's method
/////////////////////////////////////////////////////////////////////////////
void CDiffFunction::Newton(std::vector<double> &vMax, bool fTrace)
{
 const std::vector<double> &vG = GetGradient();
 const std::vector<double> &vH = GetHessian();
 int n = GetDimensions();

 if (fTrace)
  std::cout << '\n';

 for (int Iterations = MaxNewtonIterations; --Iterations >= 0;)
 {
  double L = GetOutput(&vMax[0]);
  ComputeGradient();
  ComputeHessian();

  if (fTrace)
  {
   std::cout << std::setw(5) << Iterations;
   std::cout << std::setw(12) << vMax[0];
   std::cout << std::setw(12) << L;
   std::cout << std::setw(12) << vG[0];
   std::cout << std::setw(12) << vH[0];
   std::cout << '\n';
  }

  //
  // Compute Gradient multiplied by inverse of opposite of Hessian
  //
  vStep = vG;
  if (CMatrixOperations::Cholesky(&vH[0], &vCholesky[0], n))
   CMatrixOperations::Solve(&vCholesky[0], &vStep[0], n);

  //
  // If the Hessian is not definite negative, CG
  //
  else
  {
   CG(&vMax[0], fTrace);
   return;
  }

  //
  // Apply change
  //
  for (int i = n; --i >= 0;)
   vxTemp[i] = Normalize(vMax[i] + vStep[i]);

  //
  // If probability did not improve, use CG
  //
  double LNew = GetOutput(&vxTemp[0]);
  double NewtonStep = 1.0;

  if ((LNew != LNew || LNew < L) && NewtonStep > MinNewtonStep)
  {
   CG(&vMax[0], fTrace);
   return;
  }

  //
  // Stop looping if small improvement
  //
  vMax = vxTemp;
  if (LNew - L < NewtonThreshold) 
   return;
 }

 //std::cerr << "warning: reached MaxNewtonIterations\n";
}
예제 #7
0
/////////////////////////////////////////////////////////////////////////////
// Conjugate Gradient
/////////////////////////////////////////////////////////////////////////////
void CDiffFunction::CG(double vMax[], bool fTrace)
{
 const std::vector<double> &vG = GetGradient();
 std::vector<double> vPrevG;
 std::vector<double> vD;

 const int Cycles = GetDimensions();

 //
 // Loop of iterations
 //
 for (int Iteration = 0; Iteration < MaxCGIterations; Iteration++)
 {
  //
  // Compute output and gradient at current point
  //
  GetOutput(&vMax[0]);
  ComputeGradient();

  //
  // At the beginning of a cycle, go in the gradient direction
  //
  int Cycle = Iteration % Cycles;
  if (Cycle == 0)
  {
   vPrevG = vG;
   vD = vG;
  }

  //
  // Otherwise, compute conjugate direction
  //
  else
  {
   double Num = 0;
   double Den = 0;

   for (int i = GetDimensions(); --i >= 0;)
   {
    Num += vG[i] * (vG[i] - vPrevG[i]);
    Den += vPrevG[i] * vPrevG[i];
   }

   double Beta = Num / Den;

   if (Den == 0 || Beta > MaxBeta)
    Beta = MaxBeta;

   for (int i = GetDimensions(); --i >= 0;)
   {
    vD[i] = vG[i] + Beta * vD[i];
    vPrevG[i] = vG[i];
   }
  }

  //
  // Trick to avoid getting stuck at a minimum
  //
  {
   int x = Iteration % GetDimensions();
   if (vD[x] * vD[x] == 0.0)
   {
    if (vD[x] >= 0)
     vD[x] = 1.0;
    else
     vD[x] = -1.0;
   }
  }
 
  //
  // Perform line optimization
  //
  double x = LineOpt(vMax, &vD[0], fTrace);

  double Delta2 = 0.0;
  for (int i = GetDimensions(); --i >= 0;)
  {
   double New = Normalize(vMax[i] + x * vD[i]);
   double Delta = New - vMax[i];
   vMax[i] = New;
   Delta2 += Delta * Delta;
  }

  if (Cycle == 0 && Delta2 < CGEpsilon)
   return;
 }

 // std::cerr << "warning: reached MaxCGIterations\n";
}
예제 #8
0
// Adds sub-pixel resolution EdgeOffsets for the outline if the supplied
// pix is 8-bit. Does nothing otherwise.
// Operation: Consider the following near-horizontal line:
// _________
//          |________
//                   |________
// At *every* position along this line, the gradient direction will be close
// to vertical. Extrapoaltion/interpolation of the position of the threshold
// that was used to binarize the image gives a more precise vertical position
// for each horizontal step, and the conflict in step direction and gradient
// direction can be used to ignore the vertical steps.
void C_OUTLINE::ComputeEdgeOffsets(int threshold, Pix* pix) {
  if (pixGetDepth(pix) != 8) return;
  const l_uint32* data = pixGetData(pix);
  int wpl = pixGetWpl(pix);
  int width = pixGetWidth(pix);
  int height = pixGetHeight(pix);
  bool negative = flag(COUT_INVERSE);
  delete [] offsets;
  offsets = new EdgeOffset[stepcount];
  ICOORD pos = start;
  ICOORD prev_gradient;
  ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
                  &prev_gradient);
  for (int s = 0; s < stepcount; ++s) {
    ICOORD step_vec = step(s);
    TPOINT pt1(pos);
    pos += step_vec;
    TPOINT pt2(pos);
    ICOORD next_gradient;
    ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
                    &next_gradient);
    // Use the sum of the prev and next as the working gradient.
    ICOORD gradient = prev_gradient + next_gradient;
    // best_diff will be manipulated to be always positive.
    int best_diff = 0;
    // offset will be the extrapolation of the location of the greyscale
    // threshold from the edge with the largest difference, relative to the
    // location of the binary edge.
    int offset = 0;
    if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) {
      // Horizontal step. diff_sign == 1 indicates black above.
      int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1;
      int x = MIN(pt1.x, pt2.x);
      int y = height - pt1.y;
      int best_sum = 0;
      int best_y = y;
      EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height,
                           &best_diff, &best_sum, &best_y);
      // Find the strongest edge.
      int test_y = y;
      do {
        ++test_y;
      } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
                                    &best_diff, &best_sum, &best_y));
      test_y = y;
      do {
        --test_y;
      } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
                                    &best_diff, &best_sum, &best_y));
      offset = diff_sign * (best_sum / 2 - threshold) +
          (y - best_y) * best_diff;
    } else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) {
      // Vertical step. diff_sign == 1 indicates black on the left.
      int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1;
      int x = pt1.x;
      int y = height - MAX(pt1.y, pt2.y);
      const l_uint32* line = pixGetData(pix) + y * wpl;
      int best_sum = 0;
      int best_x = x;
      EvaluateHorizontalDiff(line, diff_sign, x, width,
                             &best_diff, &best_sum, &best_x);
      // Find the strongest edge.
      int test_x = x;
      do {
        ++test_x;
      } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
                                      &best_diff, &best_sum, &best_x));
      test_x = x;
      do {
        --test_x;
      } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
                                      &best_diff, &best_sum, &best_x));
      offset = diff_sign * (threshold - best_sum / 2) +
          (best_x - x) * best_diff;
    }
    offsets[s].offset_numerator =
        static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
    offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
                                                           MAX_UINT8));
    if (negative) gradient = -gradient;
    // Compute gradient angle quantized to 256 directions, rotated by 64 (pi/2)
    // to convert from gradient direction to edge direction.
    offsets[s].direction =
        Modulo(FCOORD::binary_angle_plus_pi(gradient.angle()) + 64, 256);
    prev_gradient = next_gradient;
  }
}
예제 #9
0
//All the *_grad is the gradient of pos_score - neg_score w.r.t. the parameter *
void CRelation::TrainRelatTriple(int head, bool head_is_word, int r, int tail)
{
	real head_grads[MAX_EMBEDDING_SIZE], tail_grads[MAX_EMBEDDING_SIZE], grads_tmp[MAX_EMBEDDING_SIZE], relat_grads[MAX_EMBEDDING_SIZE], negh_grads[MAX_EMBEDDING_SIZE], negt_grads[MAX_EMBEDDING_SIZE], negr_grads[MAX_EMBEDDING_SIZE];
	real head_left_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK], head_right_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK], tail_left_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK], tail_right_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK];
	real negr_head_left_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK], negr_head_right_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK], negr_tail_left_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK], negr_tail_right_mat_grads[MAX_EMBEDDING_SIZE * MAX_RELAT_RANK];
	
	real head_mat_grads[MAX_RELAT_RANK], tail_mat_grads[MAX_RELAT_RANK]; 
	real negr_head_mat_grads[MAX_RELAT_RANK], negr_tail_mat_grads[MAX_RELAT_RANK]; //Used for the diag case

	real off_vec[MAX_EMBEDDING_SIZE], neg_off_vec[MAX_EMBEDDING_SIZE];
	real Qh_h[MAX_RELAT_RANK], Qh_negh[MAX_RELAT_RANK], Qt_t[MAX_RELAT_RANK], Qt_negt[MAX_RELAT_RANK];
	real PhT_offvec[MAX_RELAT_RANK], PtT_offvec[MAX_RELAT_RANK];
	
	memset(head_grads, 0, sizeof(real)* Opt::embeding_size);
	memset(tail_grads, 0, sizeof(real)* Opt::embeding_size);
	memset(relat_grads, 0, sizeof(real)* Opt::embeding_size);
	memset(negh_grads, 0, sizeof(real)* Opt::embeding_size);
	memset(negt_grads, 0, sizeof(real)* Opt::embeding_size);
	memset(negr_grads, 0, sizeof(real)* Opt::embeding_size);

	if (Opt::update_mat && !Opt::is_diag)
	{
		memset(head_left_mat_grads, 0, sizeof(real)* Opt::head_relat_rank * Opt::embeding_size);
		memset(head_right_mat_grads, 0, sizeof(real)* Opt::head_relat_rank * Opt::embeding_size);

		if (Opt::use_tail_mat)
		{
			memset(tail_left_mat_grads, 0, sizeof(real)* Opt::embeding_size * Opt::tail_relat_rank);
			memset(tail_right_mat_grads, 0, sizeof(real)* Opt::tail_relat_rank * Opt::embeding_size);
		}

		memset(negr_head_left_mat_grads, 0, sizeof(real)* Opt::embeding_size * Opt::head_relat_rank);
		memset(negr_head_right_mat_grads, 0, sizeof(real)* Opt::embeding_size * Opt::head_relat_rank);

		if (Opt::use_tail_mat)
		{
			memset(negr_tail_left_mat_grads, 0, sizeof(real)* Opt::embeding_size * Opt::tail_relat_rank);
			memset(negr_tail_right_mat_grads, 0, sizeof(real)* Opt::embeding_size * Opt::tail_relat_rank);
		}
	}

	if (Opt::update_mat && Opt::is_diag)
	{
		memset(head_mat_grads, 0, sizeof(real)* Opt::embeding_size);
		memset(tail_mat_grads, 0, sizeof(real)* Opt::embeding_size);
		memset(negr_head_mat_grads, 0, sizeof(real)* Opt::embeding_size);
		memset(negr_tail_mat_grads, 0, sizeof(real)* Opt::embeding_size);
	}

	//Sample neg head word and neg tail word
	int neg_head, neg_tail, neg_r;
	do
	{
		neg_head = SampleWordIdx();
	} while (neg_head == head || neg_head == tail);

	do
	{
		neg_tail = SampleWordIdx();
	} while (neg_tail == head || neg_tail == tail);

	do
	{
		neg_r = SampleRelatIdx();
	} while (neg_r == r);

	real* head_embedding = WordParams::p_embedding[head];
	real* tail_embedding = WordParams::p_embedding[tail];
	real* relat_embedding = p_relat_emb[r];
	real* relat_act_embedding = Opt::act_relat ? p_relat_act_emb[r] : NULL;

	real* neg_head_embedding = WordParams::p_embedding[neg_head];
	real* neg_tail_embedding = WordParams::p_embedding[neg_tail];
	real* neg_r_embedding = p_relat_emb[neg_r];
	real* neg_r_act_embedding = Opt::act_relat ? p_relat_act_emb[neg_r] : NULL;

	real pos_score = ComputeScore(head, r, tail, Qh_h, Qt_t, off_vec); 
	real negh_score = ComputeScore(neg_head, r, tail, Qh_negh, Qt_t, neg_off_vec);
	
	real hgap;
	bool is_negh_margin_satisfied;

	hgap = negh_score - pos_score;
	is_negh_margin_satisfied = hgap > Opt::margin;
	if (!is_negh_margin_satisfied) //margin is not satisfied
		ComputeGradient(1, Opt::relat_neg_weight, r, grads_tmp, negh_grads, tail_grads, relat_grads,
			head_left_mat_grads, head_right_mat_grads, tail_left_mat_grads, tail_right_mat_grads,
			neg_off_vec, Qh_negh, Qt_t, PhT_offvec, PtT_offvec, neg_head_embedding, tail_embedding,
			head_mat_grads, tail_mat_grads);
	
	//Begin updating the loss and grads for ||LR(h - t)||_2^2 - ||LR(h - negt)||_2^2
	real negt_score = ComputeScore(head, r, neg_tail, Qh_h, Qt_negt, neg_off_vec);
	real tgap;
	bool is_negt_margin_satisfied;

	tgap = negt_score - pos_score;
	is_negt_margin_satisfied = tgap > Opt::margin;
	if (!is_negt_margin_satisfied)
		ComputeGradient(1, Opt::relat_neg_weight, r, grads_tmp, head_grads, negt_grads, relat_grads,
			head_left_mat_grads, head_right_mat_grads, tail_left_mat_grads, tail_right_mat_grads, neg_off_vec,
			Qh_h, Qt_negt, PhT_offvec, PtT_offvec, head_embedding, neg_tail_embedding,
			head_mat_grads, tail_mat_grads);
	
	real negr_score = ComputeScore(head, neg_r, tail, Qh_negh, Qt_negt, neg_off_vec);
	real rgap;
	bool is_negr_margin_satisfied = true;;
	
	rgap = negr_score - pos_score;
	is_negr_margin_satisfied = rgap > Opt::margin;
	if (!is_negr_margin_satisfied)
		ComputeGradient(1, Opt::relat_neg_weight, neg_r, grads_tmp, head_grads, tail_grads, negr_grads,
			negr_head_left_mat_grads, negr_head_right_mat_grads, negr_tail_left_mat_grads, negr_tail_right_mat_grads, neg_off_vec,
			Qh_negh, Qt_negt, PhT_offvec, PtT_offvec, head_embedding, tail_embedding,
			negr_head_mat_grads, negr_tail_mat_grads);
	
	if (!Opt::sig_relat && is_negh_margin_satisfied && is_negt_margin_satisfied && is_negr_margin_satisfied)
		return;

	int effect_cnt = (is_negh_margin_satisfied ? 0 : 1) + (is_negt_margin_satisfied ? 0 : 1) + (is_negr_margin_satisfied ? 0 : 1);
	ComputeGradient(-1, effect_cnt, r, grads_tmp, head_grads, tail_grads, relat_grads,
		head_left_mat_grads, head_right_mat_grads, tail_left_mat_grads, tail_right_mat_grads, off_vec,
		Qh_h, Qt_t, PhT_offvec, PtT_offvec, head_embedding, tail_embedding,
		head_mat_grads, tail_mat_grads);

	//Gradient Checking
	/*real gap = (is_negh_margin_satisfied ? 0 : negh_score - pos_score) + (is_negt_margin_satisfied ? 0 : negt_score - pos_score) + (is_negr_margin_satisfied ? 0 : negr_score - pos_score);

	
	if (rand() < 20)
	{
		const double epsilon = 1e-6;
		//head_embedding[idx] += epsilon;
		//p_head_left_mat[r][idx] += epsilon;
		//p_tail_right_mat[r][idx] += epsilon;
		//tail_embedding[idx] += epsilon;
		//p_actual_left_mat[r][idx] = 2 * Util::Sigmoid(p_left_mat[r][41]) - 1;
		//p_tail_left_mat[r][idx] += epsilon;
		//p_head_left_mat[neg_r][idx] += epsilon;
		//p_actual_right_mat[r][idx] = 2 * Util::Sigmoid(p_right_mat[r][idx]) - 1;
		//p_relat_emb[neg_r][idx] += epsilon;
		//p_relat_act_emb[neg_r][idx] = 2 * Util::Sigmoid(p_relat_emb[neg_r][idx]) - 1;

		idx = -1;
		for (auto x : tail_diag_mat_ele[r])
			idx = x.first;

		printf("\n");

		tail_diag_mat_ele[neg_r][idx] += epsilon;
		
		real new_gap = 0, pos_score = ComputeLoss(head, tail, r);
		//ComputeLoss(head, tail, neg_r) - ComputeLoss(head, tail, r);
		real neg_gap = ComputeLoss(neg_head, tail, r) - pos_score;
		if (neg_gap <= Opt::margin)
			new_gap += neg_gap;
		neg_gap = ComputeLoss(head, neg_tail, r) - pos_score;
		if (neg_gap <= Opt::margin)
			new_gap += neg_gap;
		neg_gap = ComputeLoss(head, tail, neg_r) - pos_score;
		if (neg_gap <= Opt::margin)
			new_gap += neg_gap;

		printf("real gradient: %.5f, our gradient %.5f, idx:%d\n", (new_gap - gap) / epsilon, negr_tail_mat_grads[idx], idx);
		//p_tail_right_mat[r][idx] -= epsilon;
		//p_head_left_mat[neg_r][idx] -= epsilon;
		//tail_embedding[idx] -= epsilon;
		//p_actual_right_mat[r][idx] = 2 * Util::Sigmoid(p_right_mat[r][idx]) - 1;
		//head_embedding[idx] -= epsilon;
		//p_relat_emb[neg_r][idx] -= epsilon;
		//p_relat_act_emb[neg_r][idx] = 2 * Util::Sigmoid(p_relat_emb[neg_r][idx]) - 1;
		//p_actual_left_mat[neg_r][idx] = 2 * Util::Sigmoid(p_left_mat[r][41]) - 1;
		tail_diag_mat_ele[neg_r][idx] -= epsilon;
	}*/

	double step_size = GetStepSize(head, r, tail);
	step_size /= effect_cnt;

	Util::MatPlusMat(relat_embedding, relat_grads, step_size, Opt::embeding_size, 1);
	
	Util::MatPlusMat(head_embedding, head_grads, step_size, Opt::embeding_size, 1);
	
	Util::MatPlusMat(tail_embedding, tail_grads, step_size, Opt::embeding_size, 1);

	if (!is_negt_margin_satisfied)
		Util::MatPlusMat(neg_tail_embedding, negt_grads, step_size, Opt::embeding_size, 1);

	if (!is_negh_margin_satisfied)
		Util::MatPlusMat(neg_head_embedding, negh_grads, step_size, Opt::embeding_size, 1);

	if (!is_negr_margin_satisfied)
		Util::MatPlusMat(neg_r_embedding, negr_grads, step_size, Opt::embeding_size, 1);

	if (Opt::update_mat && !Opt::is_diag)
	{
		Util::MatPlusMat(p_head_left_mat[r], head_left_mat_grads, step_size, Opt::embeding_size, Opt::head_relat_rank);
		Util::MatPlusMat(p_head_right_mat[r], head_right_mat_grads, step_size, Opt::head_relat_rank, Opt::embeding_size);
		if (Opt::use_tail_mat)
		{
			Util::MatPlusMat(p_tail_left_mat[r], tail_left_mat_grads, step_size, Opt::embeding_size, Opt::tail_relat_rank);
			Util::MatPlusMat(p_tail_right_mat[r], tail_right_mat_grads, step_size, Opt::tail_relat_rank, Opt::embeding_size);
		}

		if (!is_negr_margin_satisfied)
		{
			Util::MatPlusMat(p_head_left_mat[neg_r], negr_head_left_mat_grads, step_size, Opt::embeding_size, Opt::head_relat_rank);
			Util::MatPlusMat(p_head_right_mat[neg_r], negr_head_right_mat_grads, step_size, Opt::embeding_size, Opt::head_relat_rank);
			if (Opt::use_tail_mat)
			{
				Util::MatPlusMat(p_tail_left_mat[neg_r], negr_tail_left_mat_grads, step_size, Opt::embeding_size, Opt::tail_relat_rank);
				Util::MatPlusMat(p_tail_right_mat[neg_r], negr_tail_right_mat_grads, step_size, Opt::embeding_size, Opt::tail_relat_rank);
			}
		}
	}
	else if (Opt::update_mat && Opt::is_diag)
	{
		for (auto x : head_diag_mat_ele[r])
			head_diag_mat_ele[r][x.first] += step_size *  head_mat_grads[x.first];
		if (Opt::use_tail_mat)
			for (auto x : tail_diag_mat_ele[r])
				tail_diag_mat_ele[r][x.first] += step_size * tail_mat_grads[x.first];
		if (!is_negr_margin_satisfied)
		{
			for (auto x : head_diag_mat_ele[neg_r])
				head_diag_mat_ele[neg_r][x.first] += step_size *  negr_head_mat_grads[x.first];
			if (Opt::use_tail_mat)
				for (auto x : tail_diag_mat_ele[neg_r])
					tail_diag_mat_ele[neg_r][x.first] += step_size * negr_tail_mat_grads[x.first];
		}
	}

	ConstrainParameters(r);
	if (!is_negr_margin_satisfied)
		ConstrainParameters(neg_r);
}
void RemoveNegativeNodes( GPU::Classes::GCAmorphGPU& gcam,
                          const GPU::Classes::MRIframeGPU<T>& mri,
                          GCA_MORPH_PARMS *parms ) {
  /*!
    Implementation of gcamRemoveNegativeNodes for the GPU
    pipeline
  */
  GCA_MORPH_PARMS saved_parms = *parms;
  double min_dt, orig_dt = parms->orig_dt, rms, last_rms, pct_change;
  int old_neg, new_neg, i;
  GPU::Algorithms::GCAmorphEnergy gcamEnergy;

  if( gcam.neg <=0 ) {
    return;
  }

  // Try simple removal
  gcam.RemoveSingularities();
  if( gcam.neg <= 0 ) {
    return;
  }

  parms->noneg = 0 ;
  parms->l_distance
    = parms->l_log_likelihood
    = parms->l_binary
    = parms->l_multiscale
    = parms->l_spring
    = parms->l_area
    = parms->l_smoothness
    = parms->l_label = 0;
  parms->navgs = 0;
  parms->l_area = 0.0;
  parms->l_jacobian = 1;
  parms->dt = 0.1;
  parms->tol = 0.01;

  last_rms = rms = gcamEnergy.ComputeRMS( gcam, mri, parms );
  new_neg = gcam.neg;
  i = 0;

  do {
    old_neg = new_neg;

    ComputeGradient( gcam, mri, mri, parms );

    min_dt = FindOptimalTimestep( gcam, parms, mri );

    parms->dt = min_dt;

    gcam.ApplyGradient( parms );

    last_rms = rms;
    rms = gcamEnergy.ComputeRMS( gcam, mri, parms );

    parms->dt = orig_dt;
    new_neg = gcam.neg;
    pct_change = 100.0*(last_rms-rms)/(last_rms);

    printf( "iter %d, dt=%2.6f: new neg %d, old_neg %d, delta %d, rms=%2.3f\n",
            ++i, min_dt, new_neg, old_neg, old_neg-new_neg, rms, pct_change );
  }
  while( (new_neg>0) && (pct_change > parms->tol) && (i < kMaxNegIter) );

  *parms = saved_parms;
}