package org.freehep.math.minuit;
/**
*
* @version $Id: MnPosDef.java 8584 2006-08-10 23:06:37Z duns $
*/
abstract class MnPosDef
{
static MinimumState test(MinimumState st, MnMachinePrecision prec)
{
MinimumError err = test(st.error(), prec);
return new MinimumState(st.parameters(), err, st.gradient(), st.edm(), st.nfcn());
}
static MinimumError test(MinimumError e, MnMachinePrecision prec)
{
MnAlgebraicSymMatrix err = e.invHessian().clone();
if(err.size() == 1 && err.get(0,0) < prec.eps())
{
err.set(0,0,1.);
return new MinimumError(err, new MinimumError.MnMadePosDef());
}
if(err.size() == 1 && err.get(0,0) > prec.eps())
{
return e;
}
// std::cout<<"MnPosDef init matrix= "<<err<<std::endl;
double epspdf = Math.max(1.e-6, prec.eps2());
double dgmin = err.get(0,0);
for(int i = 0; i < err.nrow(); i++)
{
if(err.get(i,i) < prec.eps2()) System.err.println("negative or zero diagonal element "+i+" in covariance matrix");
if(err.get(i,i) < dgmin) dgmin = err.get(i,i);
}
double dg = 0.;
if(dgmin < prec.eps2())
{
dg = 1. + epspdf - dgmin;
// dg = 0.5*(1. + epspdf - dgmin);
System.err.println("added "+dg+" to diagonal of error matrix");
}
MnAlgebraicVector s = new MnAlgebraicVector(err.nrow());
MnAlgebraicSymMatrix p = new MnAlgebraicSymMatrix(err.nrow());
for(int i = 0; i < err.nrow(); i++)
{
err.set(i,i,err.get(i,i)+dg);
if(err.get(i,i) < 0.) err.set(i,i,1.);
s.set(i,1./Math.sqrt(err.get(i,i)));
for(int j = 0; j <= i; j++)
{
p.set(i,j, err.get(i,j)*s.get(i)*s.get(j));
}
}
// std::cout<<"MnPosDef p: "<<p<<std::endl;
MnAlgebraicVector eval = p.eigenvalues();
double pmin = eval.get(0);
double pmax = eval.get(eval.size() - 1);
// std::cout<<"pmin= "<<pmin<<" pmax= "<<pmax<<std::endl;
pmax = Math.max(Math.abs(pmax), 1.);
if(pmin > epspdf*pmax) return e;
double padd = 0.001*pmax - pmin;
System.err.println("eigenvalues: ");
for(int i = 0; i < err.nrow(); i++)
{
err.set(i,i,err.get(i,i) * (1. + padd));
System.err.println(eval.get(i));
}
// std::cout<<"MnPosDef final matrix: "<<err<<std::endl;
System.err.println("matrix forced pos-def by adding "+padd+" to diagonal");
// std::cout<<"eigenvalues: "<<eval<<std::endl;
return new MinimumError(err, new MinimumError.MnMadePosDef());
}
}