Пример #1
0
MinimumError MnPosDef::operator()(const MinimumError& e, const MnMachinePrecision& prec) const {

  MnAlgebraicSymMatrix err(e.invHessian());
  if(err.size() == 1 && err(0,0) < prec.eps()) {
    err(0,0) = 1.;
    return MinimumError(err, MinimumError::MnMadePosDef());
  } 
  if(err.size() == 1 && err(0,0) > prec.eps()) {
    return e;
  } 
//   std::cout<<"MnPosDef init matrix= "<<err<<std::endl;

  double epspdf = std::max(1.e-6, prec.eps2());
  double dgmin = err(0,0);

  for(unsigned int i = 0; i < err.nrow(); i++) {
    if(err(i,i) < prec.eps2()) //std::cout<<"negative or zero diagonal element "<<i<<" in covariance matrix"<<std::endl;
    if(err(i,i) < dgmin) dgmin = err(i,i);
  }
  double dg = 0.;
  if(dgmin < prec.eps2()) {
    //dg = 1. + epspdf - dgmin; 
    dg = 0.5 + epspdf - dgmin; 
//     dg = 0.5*(1. + epspdf - dgmin); 
    //std::cout<<"added "<<dg<<" to diagonal of error matrix"<<std::endl;
    //std::cout << "Error matrix " << err << std::endl;
  }

  MnAlgebraicVector s(err.nrow());
  MnAlgebraicSymMatrix p(err.nrow());
  for(unsigned int i = 0; i < err.nrow(); i++) {
    err(i,i) += dg;
    if(err(i,i) < 0.) err(i,i) = 1.;
    s(i) = 1./sqrt(err(i,i));
    for(unsigned int j = 0; j <= i; j++) {
      p(i,j) = err(i,j)*s(i)*s(j);
    }
  }
  
  //std::cout<<"MnPosDef p: "<<p<<std::endl;
  MnAlgebraicVector eval = eigenvalues(p);
  double pmin = eval(0);
  double pmax = eval(eval.size() - 1);
  //std::cout<<"pmin= "<<pmin<<" pmax= "<<pmax<<std::endl;
  pmax = std::max(fabs(pmax), 1.);
  if(pmin > epspdf*pmax) return MinimumError(err, e.dcovar());
  
  double padd = 0.001*pmax - pmin;
  //std::cout<<"eigenvalues: "<<std::endl;
  for(unsigned int i = 0; i < err.nrow(); i++) {
    err(i,i) *= (1. + padd);
    //std::cout<<eval(i)<<std::endl;
  }
//   std::cout<<"MnPosDef final matrix: "<<err<<std::endl;
//  std::cout<<"matrix forced pos-def by adding "<<padd<<" to diagonal"<<std::endl;
//   std::cout<<"eigenvalues: "<<eval<<std::endl;
  return MinimumError(err, MinimumError::MnMadePosDef());
}
Пример #2
0
struct QuantizedValue *FindMatch(uint8 const *sample, int ndims,
								 uint8 *weights, struct QuantizedValue *q)
{
	InitHeap(&TheQueue);
	struct QuantizedValue *bestmatch=0;
	double besterror=1.0e63;
	PUSHNODE(q);
	for(;;)
	{
		struct QuantizedValue *test=(struct QuantizedValue *)
			RemoveHeapItem(&TheQueue);
		if (! test) break;		// heap empty
//    printf("got pop node =%p minerror=%f\n",test,test->MinError);
    
		if (test->MinError>besterror) break;
		if (test->Children[0])
		{
			// it's a parent node. put the children on the queue
			struct QuantizedValue *c1=test->Children[0];
			struct QuantizedValue *c2=test->Children[1];
			c1->MinError=MinimumError(c1,sample,ndims,weights);
			if (c1->MinError < besterror)
				HeapInsert(&TheQueue,&(c1->MinError));
			c2->MinError=MinimumError(c2,sample,ndims,weights);
			if (c2->MinError < besterror)
				HeapInsert(&TheQueue,&(c2->MinError));
		}
		else
		{
			// it's a leaf node. This must be a new minimum or the MinError
			// test would have failed.
			if (test->MinError < besterror)
			{
				bestmatch=test;
				besterror=test->MinError;
			}
		}
	}
	if (bestmatch)
	{
		SquaredError+=besterror;
		bestmatch->NQuant++;
		for(int i=0;i<ndims;i++)
			bestmatch->Sums[i]+=sample[i];
	}
	return bestmatch;
}
Пример #3
0
MnUserParameterState MnHesse::operator()(const FCNBase& fcn, const MnUserParameterState& state, unsigned int maxcalls) const {

  unsigned int n = state.variableParameters();
  MnUserFcn mfcn(fcn, state.trafo());
  MnAlgebraicVector x(n);
  for(unsigned int i = 0; i < n; i++) x(i) = state.intParameters()[i];
  double amin = mfcn(x);
  Numerical2PGradientCalculator gc(mfcn, state.trafo(), theStrategy);
  MinimumParameters par(x, amin);
  FunctionGradient gra = gc(par);
  MinimumState tmp = (*this)(mfcn, MinimumState(par, MinimumError(MnAlgebraicSymMatrix(n), 1.), gra, state.edm(), state.nfcn()), state.trafo(), maxcalls);

  return MnUserParameterState(tmp, fcn.up(), state.trafo());
}
Пример #4
0
MinimumState MnHesse::operator()(const MnFcn& mfcn, const MinimumState& st, const MnUserTransformation& trafo, unsigned int maxcalls) const {

  const MnMachinePrecision& prec = trafo.precision();
  // make sure starting at the right place
  double amin = mfcn(st.vec());
  double aimsag = sqrt(prec.eps2())*(fabs(amin)+mfcn.up());
  
  // diagonal elements first

  unsigned int n = st.parameters().vec().size();
  if(maxcalls == 0) maxcalls = 200 + 100*n + 5*n*n;

  MnAlgebraicSymMatrix vhmat(n);
  MnAlgebraicVector g2 = st.gradient().g2();
  MnAlgebraicVector gst = st.gradient().gstep();
  MnAlgebraicVector grd = st.gradient().grad();
  MnAlgebraicVector dirin = st.gradient().gstep();
  MnAlgebraicVector yy(n);
  if(st.gradient().isAnalytical()) {
    InitialGradientCalculator igc(mfcn, trafo, theStrategy);
    FunctionGradient tmp = igc(st.parameters());
    gst = tmp.gstep();
    dirin = tmp.gstep();
    g2 = tmp.g2();
  }

  MnAlgebraicVector x = st.parameters().vec(); 

  for(unsigned int i = 0; i < n; i++) {

    double xtf = x(i);
    double dmin = 8.*prec.eps2()*(fabs(xtf) + prec.eps2());
    double d = fabs(gst(i));
    if(d < dmin) d = dmin;

    for(unsigned int icyc = 0; icyc < ncycles(); icyc++) {
      double sag = 0.;
      double fs1 = 0.;
      double fs2 = 0.;
      for(unsigned int multpy = 0; multpy < 5; multpy++) {
	x(i) = xtf + d;
	fs1 = mfcn(x);
	x(i) = xtf - d;
	fs2 = mfcn(x);
	x(i) = xtf;
	sag = 0.5*(fs1+fs2-2.*amin);
	if(sag > prec.eps2()) goto L30; // break;
	if(trafo.parameter(i).hasLimits()) {
	  if(d > 0.5) goto L26;
	  d *= 10.;
	  if(d > 0.5) d = 0.51;
	  continue;
	}
	d *= 10.;
      }
      
L26:  
      std::cout<<"MnHesse: 2nd derivative zero for parameter "<<i<<std::endl;
      std::cout<<"MnHesse fails and will return diagonal matrix "<<std::endl;

      for(unsigned int j = 0; j < n; j++) {
	double tmp = g2(j) < prec.eps2() ? 1. : 1./g2(j);
	vhmat(j,j) = tmp < prec.eps2() ? 1. : tmp;
      }

      return MinimumState(st.parameters(), MinimumError(vhmat, MinimumError::MnHesseFailed()), st.gradient(), st.edm(), mfcn.numOfCalls());

L30:      
      double g2bfor = g2(i);
      g2(i) = 2.*sag/(d*d);
      grd(i) = (fs1-fs2)/(2.*d);
      gst(i) = d;
      dirin(i) = d;
      yy(i) = fs1;
      double dlast = d;
      d = sqrt(2.*aimsag/fabs(g2(i)));
      if(trafo.parameter(i).hasLimits()) d = std::min(0.5, d);
      if(d < dmin) d = dmin;

      // see if converged
      if(fabs((d-dlast)/d) < tolerstp()) break;
      if(fabs((g2(i)-g2bfor)/g2(i)) < tolerg2()) break; 
      d = std::min(d, 10.*dlast);
      d = std::max(d, 0.1*dlast);   
    }
    vhmat(i,i) = g2(i);
    if(mfcn.numOfCalls()  > maxcalls) {
      //std::cout<<"maxcalls " << maxcalls << " " << mfcn.numOfCalls() << "  " <<   st.nfcn() << std::endl;
      std::cout<<"MnHesse: maximum number of allowed function calls exhausted."<<std::endl;  
      std::cout<<"MnHesse fails and will return diagonal matrix "<<std::endl;
      for(unsigned int j = 0; j < n; j++) {
	double tmp = g2(j) < prec.eps2() ? 1. : 1./g2(j);
	vhmat(j,j) = tmp < prec.eps2() ? 1. : tmp;
      }
      
      return MinimumState(st.parameters(), MinimumError(vhmat, MinimumError::MnHesseFailed()), st.gradient(), st.edm(), mfcn.numOfCalls());
    }
    
  }

  if(theStrategy.strategy() > 0) {
    // refine first derivative
    HessianGradientCalculator hgc(mfcn, trafo, theStrategy);
    FunctionGradient gr = hgc(st.parameters(), FunctionGradient(grd, g2, gst));
    grd = gr.grad();
  }

  //off-diagonal elements  
  for(unsigned int i = 0; i < n; i++) {
    x(i) += dirin(i);
    for(unsigned int j = i+1; j < n; j++) {
      x(j) += dirin(j);
      double fs1 = mfcn(x);
      double elem = (fs1 + amin - yy(i) - yy(j))/(dirin(i)*dirin(j));
      vhmat(i,j) = elem;
      x(j) -= dirin(j);
    }
    x(i) -= dirin(i);
  }
  
  //verify if matrix pos-def (still 2nd derivative)
  MinimumError tmp = MnPosDef()(MinimumError(vhmat,1.), prec);
  vhmat = tmp.invHessian();
  int ifail = invert(vhmat);
  if(ifail != 0) {
    std::cout<<"MnHesse: matrix inversion fails!"<<std::endl;
    std::cout<<"MnHesse fails and will return diagonal matrix."<<std::endl;

    MnAlgebraicSymMatrix tmpsym(vhmat.nrow());
    for(unsigned int j = 0; j < n; j++) {
      double tmp = g2(j) < prec.eps2() ? 1. : 1./g2(j);
      tmpsym(j,j) = tmp < prec.eps2() ? 1. : tmp;
    }

    return MinimumState(st.parameters(), MinimumError(tmpsym, MinimumError::MnHesseFailed()), st.gradient(), st.edm(), mfcn.numOfCalls());
  }
  
  FunctionGradient gr(grd, g2, gst);

  // needed this ? (if posdef and inversion ok continue. it is like this in the Fortran version
//   if(tmp.isMadePosDef()) {
//     std::cout<<"MnHesse: matrix is invalid!"<<std::endl;
//     std::cout<<"MnHesse: matrix is not pos. def.!"<<std::endl;
//     std::cout<<"MnHesse: matrix was forced pos. def."<<std::endl;
//     return MinimumState(st.parameters(), MinimumError(vhmat, MinimumError::MnMadePosDef()), gr, st.edm(), mfcn.numOfCalls());    
//   }

  //calculate edm
  MinimumError err(vhmat, 0.);
  VariableMetricEDMEstimator estim;
  double edm = estim.estimate(gr, err);

  return MinimumState(st.parameters(), err, gr, edm, mfcn.numOfCalls());
}