Exemple #1
0
bool MatrixEquation::Solve_Cholesky(Vector& x) const
{
  if(!IsValid() || !A.isSquare()) {
    cout<<"Invalid dimensions in Solve_Cholesky"<<endl;
    return false;
  }
  LDLDecomposition<Real> chol;
  chol.set(A);
  return chol.backSub(b,x);
}
Exemple #2
0
ConvergenceResult MinimizationProblem::SolveLM(int& iters,Real lambda0,Real lambdaScale)
{
  Real lambda=lambda0;
  grad.resize(x.n);
  H.resize(x.n,x.n);
  dx.resize(x.n);
  Vector x0,diagH;
  LDLDecomposition<Real> ldl;
  Real fx0;
  fx = (*f)(x);
  bool tookStep=true;
  int maxIters=iters;
  for(iters=0;iters<maxIters;iters++) {
    if(tookStep) {
      f->Gradient(x,grad);
      f->Hessian(x,H);
      H.getDiagCopy(0,diagH);
    }
    for(int i=0;i<x.n;i++) H(i,i) += Max((Real)1e-4,diagH(i))*lambda;

    ldl.set(H);
    Vector d; ldl.LDL.getDiagRef(0,d);
    for(int i=0;i<x.n;i++) {
      if(d(i) <= 1e-3) { //non-PD or nearly non-PD (adjust lambda?)
	d(i) = 1e-3;
      }
    }
    fx0 = fx;
    x0 = x;
    ldl.backSub(grad,dx);
    dx.inplaceNegative();
    x += dx;

    //check if the step works or not
    fx = (*f)(x);
    if(Abs(fx0 - fx) < tolf) return ConvergenceF;
    if(grad.maxAbsElement() < tolgrad) return ConvergenceF;
    if(dx.maxAbsElement() < tolx) return ConvergenceX;
    if(fx < fx0) {
      tookStep=true;
      lambda /= lambdaScale;
    }
    else {
      tookStep=false;
      x = x0;
      fx = fx0;
      H.copyDiag(0,diagH); 
      lambda *= lambdaScale;
    }
  }
  return MaxItersReached;
}
Exemple #3
0
ConvergenceResult ConstrainedMinimizationProblem::SolveNewton(int& iters)
{
  if(!CheckPoint(x)) return ConvergenceError;

  Vector dx;
  fx=(*f)(x);
  grad.resize(x.n);
  H.resize(x.n,x.n);
  LDLDecomposition<Real> ldl;
  int maxIters=iters;
  for(iters=0;iters<maxIters;iters++) {
    f->Gradient(x,grad);
    f->Hessian(x,H);
    ldl.set(H);
    Vector d;
    ldl.LDL.getDiagRef(0,d);
    if(d.minElement() < 0) {
      if(verbose>=1) cout<<"Warning, hessian is not positive definite"<<endl;
      for(int i=0;i<d.n;i++)
	if(d(i) < 1e-4) d(i) = 1e-4;
      //return ConvergenceError;
    }
    ldl.backSub(grad,dx);
    if(dot(dx,grad) < Zero) {
      if(verbose>=1) cout<<"ConstrainedMinimizationProblem::SolveNewton(): Warning, hessian direction opposes gradient on step "<<iters<<endl;
      //dx.setNegative(grad);
    }
    dx.inplaceNegative();

    Real dxnorm0 = dx.maxAbsElement();
    NullspaceProjection(x,dx);
    Real dxnorm = dx.maxAbsElement();
    Real alpha0 = Min(dxnorm0/dxnorm,(Real)10);
    ConvergenceResult res=LineMinimizationStep(dx,alpha0);
    if(res != MaxItersReached) return res;
  }
  if(verbose>=1) cout<<"ConstrainedMinimzationProblem::Solve(): Max iters reached "<<iters<<"."<<endl;
  return MaxItersReached;
}
Exemple #4
0
bool LeastSquares(const Matrix& data,const Vector& outcome,
		  Vector& coeffs,Real& offset)
{
  assert(outcome.n == data.m);
  //solve for vector (coeffs,offset) using normal equations
  Matrix A(data.n+1,data.n+1);
  Vector b(data.n+1),c(data.n+1);
  Vector xi,xj;
  for(int i=0;i<data.n;i++) {
    data.getColRef(i,xi);
    for(int j=i;j<data.n;j++) {
      data.getColRef(j,xj);
      A(j,i) = A(i,j) = xi.dot(xj);
    }
    b(i) = xi.dot(outcome);
  }
  for(int i=0;i<data.n;i++) {
    data.getColRef(i,xi);
    A(data.n,i) = A(i,data.n) = Sum(xi);
  }
  A(data.n,data.n) = (Real)data.m;
  b(data.n) = Sum(outcome);

  //Solve Ac=b for coefficients c;
  LDLDecomposition<Real> ldl;
  ldl.set(A);
  ldl.backSub(b,c);
  /*  {
    cout<<"Cholesky didn't succeed!"<<endl;
    cout<<"Matrix: "<<endl<<MatrixPrinter(A)<<endl;
    return false;
  }
  */
  coeffs.resize(data.n);
  c.getSubVectorCopy(0,coeffs);
  offset = c(data.n);

  return true;
}
Exemple #5
0
ConvergenceResult BCMinimizationProblem::SolveNewton(int& iters)
{
  grad.resize(x.n);
  H.resize(x.n,x.n);
  Vector dx(x.n);
  LDLDecomposition<Real> ldl;
  fx = (*f)(x);
  int maxIters=iters;
  for(iters=0;iters<maxIters;iters++) {
    f->Gradient(x,grad);
    f->Hessian(x,H);

    //f(dx + x0) ~= f(x0) + grad_f*dx + 1/2 dx'*H_f*dx 
    //grad(f)(x+dx) ~= grad_f + 1/2*H_f*dx + O(dx^2)
    //setting = grad_f(x+dx) = 0, we see dx ~= -H_f^-1 grad_f
    //use that as the backtracking search direction (if it's in same direction as grad)
    ldl.set(H);
    Vector d;
    ldl.LDL.getDiagRef(0,d);
    if(d.minElement() < 0) {
      if(verbose>=1) cout<<"Warning, hessian is not positive definite"<<endl;
      for(int i=0;i<d.n;i++)
	if(d(i) < 1e-4) d(i) = 1e-4;
      //return ConvergenceError;
    }
    ldl.backSub(grad,dx);
    if(dot(dx,grad) < Zero) {
      if(verbose>=1) cout<<"BCMinimizationProblem::SolveNewton(): Warning, hessian direction opposes gradient on step "<<iters<<endl;
      //dx.setNegative(grad);
    }
    dx.inplaceNegative();

    Real alpha0 = 1;
    ConvergenceResult res = LineMinimizationStep(dx,alpha0);
    if(res != MaxItersReached) return res;
  }
  return MaxItersReached;
}
Exemple #6
0
ConvergenceResult BCMinimizationProblem::SolveQuasiNewton(int& iters)
{
  Assert(H.m == x.n && H.n == x.n);
  grad.resize(x.n);
  Vector x0,grad0,s,q,upd,temp,dx(x.n);
  LDLDecomposition<Real> ldl;
  ldl.set(H);
  fx = (*f)(x);
  f->Gradient(x,grad);
  int maxIters=iters;
  for(iters=0;iters<maxIters;iters++) {
    ldl.backSub(grad,dx);
    if(dot(dx,grad) < Zero) {
      if(verbose>=1) cout<<"BCMinimizationProblem::SolveQuasiNewton(): Warning, hessian direction opposes gradient on step "<<iters<<endl;
      //dx.setNegative(grad);
    }
    grad.inplaceNegative();

    x0 = x;
    grad0 = grad;

    Real alpha0=1.0;
    ConvergenceResult res = LineMinimizationStep(dx,alpha0);
    if(res != MaxItersReached) return res;

    //update the gradient
    f->Gradient(x,grad);
    //Hessian update step
    //BFGS has H' = H + q*qt / qt*s - Ht*s*st*H/st*H*s
    //where s = x - x0
    //q = grad - grad0
    s.sub(x,x0);
    q.sub(grad,grad0);
    //first part
    Real qdots = q.dot(s);
    if(qdots <= 0) {
      if(verbose >= 2) printf("BCMinimizationProblem: Warning, gradient update is in wrong direction\n");
      //revert to identity
      ldl.LDL.setIdentity();
      continue;
    }
    else {
      upd.div(q,Sqrt(qdots));
      ldl.update(upd);
    }

    //second part
    //multiply s by H => upd
    ldl.mulLT(s,temp);
    ldl.mulD(temp,temp);
    ldl.mulL(temp,upd);
    Real sHs = upd.dot(s);
    Assert(sHs > 0);
    upd /= Sqrt(sHs);
    if(!ldl.downdate(upd)) {
      if(verbose>=1) cout<<"Unable to maintain strict positive definiteness of hessian!"<<endl;
      //revert to identity
      ldl.LDL.setIdentity();
      continue;
      //TODO: fix the downdate
      //return ConvergenceError;
    }
    Vector d;
    ldl.LDL.getDiagRef(0,d);
    if(d.minElement() <= 0) {
      if(verbose>=1) cout<<"Unable to maintain positive definiteness of hessian!"<<endl;
      return ConvergenceError;
    }
  }
  return MaxItersReached;
}