package org.freehep.math.minuit;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Result of the minimization.
* <p>
* The FunctionMinimum is the output of the minimizers and contains the minimization result.
* The methods
* <ul>
* <li>userState(),
* <li>userParameters() and
* <li>userCovariance()
* </ul>
* are provided. These can be used as new input to a new minimization after some
* manipulation. The parameters and/or the FunctionMinimum can be printed using
* the toString() method or the MnPrint class.
* @version $Id: FunctionMinimum.java 8584 2006-08-10 23:06:37Z duns $
* @see #userState()
* @see #userParameters()
* @see #userCovariance()
* @see MnPrint
*/
public class FunctionMinimum
{
FunctionMinimum(MinimumSeed seed, double up)
{
theSeed = seed;
theStates = new ArrayList<MinimumState>();
theStates.add(new MinimumState(seed.parameters(), seed.error(), seed.gradient(), seed.parameters().fval(), seed.nfcn()));
theErrorDef = up;
theUserState = new MnUserParameterState();
}
FunctionMinimum(MinimumSeed seed, List<MinimumState> states, double up)
{
theSeed = seed;
theStates = states;
theErrorDef = up;
theUserState = new MnUserParameterState();
}
FunctionMinimum(MinimumSeed seed, List<MinimumState> states, double up, MnReachedCallLimit x)
{
theSeed = seed;
theStates = states;
theErrorDef = up;
theReachedCallLimit = true;
theUserState = new MnUserParameterState();
}
FunctionMinimum(MinimumSeed seed, List<MinimumState> states, double up, MnAboveMaxEdm x)
{
theSeed = seed;
theStates = states;
theErrorDef = up;
theAboveMaxEdm = true;
theReachedCallLimit = false;
theUserState = new MnUserParameterState();
}
// why not
void add(MinimumState state)
{
theStates.add(state);
}
MinimumSeed seed()
{
return theSeed;
}
List<MinimumState> states()
{
return theStates;
}
/** user representation of state at minimum */
public MnUserParameterState userState()
{
if(!theUserState.isValid())
theUserState = new MnUserParameterState(state(), errorDef(), seed().trafo());
return theUserState;
}
public MnUserParameters userParameters()
{
if(!theUserState.isValid())
theUserState = new MnUserParameterState(state(), errorDef(), seed().trafo());
return theUserState.parameters();
}
public MnUserCovariance userCovariance()
{
if(!theUserState.isValid())
theUserState = new MnUserParameterState(state(), errorDef(), seed().trafo());
return theUserState.covariance();
}
private MinimumState lastState()
{
return theStates.get(theStates.size()-1);
}
// forward interface of last state
MinimumState state()
{
return lastState();
}
MinimumParameters parameters()
{
return lastState().parameters();
}
MinimumError error()
{
return lastState().error();
}
FunctionGradient grad()
{
return lastState().gradient();
}
/**
* Returns the function value at the minimum.
*/
public double fval()
{
return lastState().fval();
}
/**
* returns the expected vertical distance to the minimum (EDM)
*/
public double edm()
{
return lastState().edm();
}
/**
* returns the total number of function calls during the minimization.
*/
public int nfcn()
{
return lastState().nfcn();
}
public double errorDef()
{
return theErrorDef;
}
/**
* In general, if this returns <CODE>true</CODE>, the minimizer did find a minimum
* without running into troubles. However, in some cases
* a minimum cannot be found, then the return value will be <CODE>false</CODE>.
* Reasons for the minimization to fail are
* <ul>
* <li>the number of allowed function calls has been exhausted</ul>
* <li>the minimizer could not improve the values of the parameters (and knowing
* that it has not converged yet)</ul>
* <li>a problem with the calculation of the covariance matrix</ul>
* </ul>
* Additional methods for the analysis of the state at the minimum are provided.
*/
public boolean isValid()
{
return state().isValid() && !isAboveMaxEdm() && !hasReachedCallLimit();
}
boolean hasValidParameters()
{
return state().parameters().isValid();
}
boolean hasValidCovariance()
{
return state().error().isValid();
}
boolean hasAccurateCovar()
{
return state().error().isAccurate();
}
boolean hasPosDefCovar()
{
return state().error().isPosDef();
}
boolean hasMadePosDefCovar()
{
return state().error().isMadePosDef();
}
boolean hesseFailed()
{
return state().error().hesseFailed();
}
boolean hasCovariance()
{
return state().error().isAvailable();
}
boolean isAboveMaxEdm()
{
return theAboveMaxEdm;
}
boolean hasReachedCallLimit()
{
return theReachedCallLimit;
}
public String toString()
{
return MnPrint.toString(this);
}
static class MnReachedCallLimit{};
static class MnAboveMaxEdm{};
private MinimumSeed theSeed;
private List<MinimumState> theStates;
private double theErrorDef;
private boolean theAboveMaxEdm;
private boolean theReachedCallLimit;
private MnUserParameterState theUserState;
}