package org.freehep.math.minuit; import java.util.ArrayList; import java.util.List; /** * The class MnUserParameterState contains the MnUserParameters and the MnUserCovariance. * It can be created on input by the user, or by MINUIT itself as user * representable format of the result of the minimization. * @version $Id: MnUserParameterState.java 8584 2006-08-10 23:06:37Z duns $ */ public class MnUserParameterState { private boolean theValid; private boolean theCovarianceValid; private boolean theGCCValid; private double theFVal; private double theEDM; private int theNFcn; private MnUserParameters theParameters; private MnUserCovariance theCovariance; private MnGlobalCorrelationCoeff theGlobalCC; private List<Double> theIntParameters; private MnUserCovariance theIntCovariance; MnUserParameterState() { theValid = false; theCovarianceValid = false; theParameters = new MnUserParameters(); theCovariance = new MnUserCovariance(); theIntParameters = new ArrayList<Double>(); theIntCovariance = new MnUserCovariance(); } protected MnUserParameterState clone() { return new MnUserParameterState(this); } private MnUserParameterState(MnUserParameterState other) { theValid = other.theValid; theCovarianceValid = other.theCovarianceValid; theGCCValid = other.theGCCValid; theFVal = other.theFVal; theEDM = other.theEDM; theNFcn = other.theNFcn; theParameters = other.theParameters.clone(); theCovariance = other.theCovariance; theGlobalCC = other.theGlobalCC; theIntParameters = new ArrayList<Double>(other.theIntParameters); theIntCovariance = other.theIntCovariance.clone(); } /** construct from user parameters (before minimization) */ MnUserParameterState(double[] par, double[] err) { theValid = true; theParameters = new MnUserParameters(par, err); theCovariance = new MnUserCovariance(); theGlobalCC = new MnGlobalCorrelationCoeff(); theIntParameters = new ArrayList<Double>(par.length); for (int i=0; i<par.length; i++) theIntParameters.add(par[i]); theIntCovariance = new MnUserCovariance(); } MnUserParameterState(MnUserParameters par) { theValid = true; theParameters = par; theCovariance = new MnUserCovariance(); theGlobalCC = new MnGlobalCorrelationCoeff(); theIntParameters = new ArrayList<Double>(par.variableParameters()); theIntCovariance = new MnUserCovariance(); int i = 0; for (MinuitParameter ipar : par.parameters()) { if (ipar.isConst() || ipar.isFixed()) continue; if (ipar.hasLimits()) theIntParameters.add(ext2int(ipar.number(),ipar.value())); else theIntParameters.add(ipar.value()); } } /** construct from user parameters + covariance (before minimization) */ MnUserParameterState(double[] par, double[] cov, int nrow) { theValid = true; theCovarianceValid = true; theCovariance = new MnUserCovariance(cov, nrow); theGlobalCC = new MnGlobalCorrelationCoeff(); theIntParameters = new ArrayList<Double>(par.length); theIntCovariance = new MnUserCovariance(cov, nrow); double[] err = new double[par.length]; for (int i = 0; i < par.length; i++) { assert(theCovariance.get(i,i) > 0.); err[i] = Math.sqrt(theCovariance.get(i,i)); theIntParameters.add(par[i]); } theParameters = new MnUserParameters(par, err); assert(theCovariance.nrow() == variableParameters()); } MnUserParameterState(double[] par, MnUserCovariance cov) { theValid = true; theCovarianceValid = true; theCovariance = cov; theGlobalCC = new MnGlobalCorrelationCoeff(); theIntParameters = new ArrayList<Double>(par.length); theIntCovariance = cov.clone(); if (theCovariance.nrow() != variableParameters()) throw new IllegalArgumentException("Bad covariance size"); double[] err = new double[par.length]; for (int i = 0; i < par.length; i++) { if (theCovariance.get(i,i) <= 0.) throw new IllegalArgumentException("Bad covariance"); err[i] = Math.sqrt(theCovariance.get(i,i)); theIntParameters.add(par[i]); } theParameters = new MnUserParameters(par, err); } MnUserParameterState(MnUserParameters par, MnUserCovariance cov) { theValid = true; theCovarianceValid = true; theParameters = par; theCovariance = cov; theGlobalCC = new MnGlobalCorrelationCoeff(); theIntParameters = new ArrayList<Double>(); theIntCovariance = cov.clone(); theIntCovariance.scale(0.5); int i = 0; for (MinuitParameter ipar : par.parameters()) { if(ipar.isConst() || ipar.isFixed()) continue; if(ipar.hasLimits()) theIntParameters.add(ext2int(ipar.number(), ipar.value())); else theIntParameters.add(ipar.value()); } assert(theCovariance.nrow() == variableParameters()); } /** construct from internal parameters (after minimization) */ MnUserParameterState(MinimumState st, double up, MnUserTransformation trafo) { theValid = st.isValid(); theCovarianceValid = false; theGCCValid = false; theFVal = st.fval(); theEDM = st.edm(); theNFcn = st.nfcn(); theParameters = new MnUserParameters(); theCovariance = new MnUserCovariance(); theGlobalCC = new MnGlobalCorrelationCoeff(); theIntParameters = new ArrayList<Double>(); theIntCovariance = new MnUserCovariance(); for (MinuitParameter ipar : trafo.parameters()) { if(ipar.isConst()) { add(ipar.name(), ipar.value()); } else if(ipar.isFixed()) { add(ipar.name(), ipar.value(), ipar.error()); if(ipar.hasLimits()) { if(ipar.hasLowerLimit() && ipar.hasUpperLimit()) setLimits(ipar.name(), ipar.lowerLimit(),ipar.upperLimit()); else if(ipar.hasLowerLimit() && !ipar.hasUpperLimit()) setLowerLimit(ipar.name(), ipar.lowerLimit()); else setUpperLimit(ipar.name(), ipar.upperLimit()); } fix(ipar.name()); } else if(ipar.hasLimits()) { int i = trafo.intOfExt(ipar.number()); double err = st.hasCovariance() ? Math.sqrt(2.*up*st.error().invHessian().get(i,i)) : st.parameters().dirin().get(i); add(ipar.name(), trafo.int2ext(i, st.vec().get(i)), trafo.int2extError(i, st.vec().get(i), err)); if(ipar.hasLowerLimit() && ipar.hasUpperLimit()) setLimits(ipar.name(), ipar.lowerLimit(), ipar.upperLimit()); else if(ipar.hasLowerLimit() && !ipar.hasUpperLimit()) setLowerLimit(ipar.name(), ipar.lowerLimit()); else setUpperLimit(ipar.name(), ipar.upperLimit()); } else { int i = trafo.intOfExt(ipar.number()); double err = st.hasCovariance() ? Math.sqrt(2.*up*st.error().invHessian().get(i,i)) : st.parameters().dirin().get(i); add(ipar.name(), st.vec().get(i), err); } } theCovarianceValid = st.error().isValid(); if(theCovarianceValid) { theCovariance = trafo.int2extCovariance(st.vec(), st.error().invHessian()); theIntCovariance = new MnUserCovariance(st.error().invHessian().data().clone(), st.error().invHessian().nrow()); theCovariance.scale(2.*up); theGlobalCC = new MnGlobalCorrelationCoeff(st.error().invHessian()); theGCCValid = true; assert(theCovariance.nrow() == variableParameters()); } } //user external representation MnUserParameters parameters() { return theParameters; } MnUserCovariance covariance() { return theCovariance; } MnGlobalCorrelationCoeff globalCC() { return theGlobalCC; } /** Minuit internal representation */ List<Double> intParameters() { return theIntParameters; } MnUserCovariance intCovariance() { return theIntCovariance; } /** transformation internal <-> external */ MnUserTransformation trafo() { return theParameters.trafo(); } /** * Returns <CODE>true</CODE> if the the state is valid, <CODE>false</CODE> if not */ public boolean isValid() { return theValid; } /** * Returns <CODE>true</CODE> * if the the state has a valid covariance, <CODE>false</CODE> otherwise. */ public boolean hasCovariance() { return theCovarianceValid; } public boolean hasGlobalCC() { return theGCCValid; } /** * returns the function value at the minimum */ public double fval() { return theFVal; } /** * Returns the expected vertival distance to the minimum (EDM) */ public double edm() { return theEDM; } /** * Returns the number of function calls during the minimization. */ public int nfcn() { return theNFcn; } // facade: forward interface of MnUserParameters and MnUserTransformation /** access to parameters (row-wise) */ List<MinuitParameter> minuitParameters() { return theParameters.parameters(); } /** access to parameters and errors in column-wise representation */ public double[] params() { return theParameters.params(); } public double[] errors() { return theParameters.errors(); } MinuitParameter parameter(int i) { return theParameters.parameter(i); } /** add free parameter name, value, error */ public void add(String name, double val, double err) { theParameters.add(name, val, err); theIntParameters.add(val); theCovarianceValid = false; theGCCValid = false; theValid = true; } /** add limited parameter name, value, lower bound, upper bound */ public void add(String name, double val, double err, double low, double up) { theParameters.add(name, val, err, low, up); theCovarianceValid = false; theIntParameters.add(ext2int(index(name), val)); theGCCValid = false; theValid = true; } /** add const parameter name, value */ public void add(String name, double val) { theParameters.add(name, val); theValid = true; } /// interaction via external number of parameter public void fix(int e) { int i = intOfExt(e); if(theCovarianceValid) { theCovariance = MnCovarianceSqueeze.squeeze(theCovariance, i); theIntCovariance = MnCovarianceSqueeze.squeeze(theIntCovariance, i); } theIntParameters.remove(i); theParameters.fix(e); theGCCValid = false; } public void release(int e) { theParameters.release(e); theCovarianceValid = false; theGCCValid = false; int i = intOfExt(e); if(parameter(e).hasLimits()) theIntParameters.add(i, ext2int(e, parameter(e).value())); else theIntParameters.add(i, parameter(e).value()); } public void setValue(int e, double val) { theParameters.setValue(e, val); if(!parameter(e).isFixed() && !parameter(e).isConst()) { int i = intOfExt(e); if(parameter(e).hasLimits()) theIntParameters.set(i,ext2int(e, val)); else theIntParameters.set(i,val); } } public void setError(int e, double err) { theParameters.setError(e, err); } public void setLimits(int e, double low, double up) { theParameters.setLimits(e, low, up); theCovarianceValid = false; theGCCValid = false; if(!parameter(e).isFixed() && !parameter(e).isConst()) { int i = intOfExt(e); if(low < theIntParameters.get(i) && theIntParameters.get(i) < up) theIntParameters.set(i,ext2int(e, theIntParameters.get(i))); else theIntParameters.set(i,ext2int(e, 0.5*(low+up))); } } public void setUpperLimit(int e, double up) { theParameters.setUpperLimit(e, up); theCovarianceValid = false; theGCCValid = false; if(!parameter(e).isFixed() && !parameter(e).isConst()) { int i = intOfExt(e); if(theIntParameters.get(i) < up) theIntParameters.set(i,ext2int(e, theIntParameters.get(i))); else theIntParameters.set(i,ext2int(e, up - 0.5*Math.abs(up + 1.))); } } public void setLowerLimit(int e, double low) { theParameters.setLowerLimit(e, low); theCovarianceValid = false; theGCCValid = false; if(!parameter(e).isFixed() && !parameter(e).isConst()) { int i = intOfExt(e); if(low < theIntParameters.get(i)) theIntParameters.set(i,ext2int(e, theIntParameters.get(i))); else theIntParameters.set(i,ext2int(e, low + 0.5*Math.abs(low + 1.))); } } public void removeLimits(int e) { theParameters.removeLimits(e); theCovarianceValid = false; theGCCValid = false; if(!parameter(e).isFixed() && !parameter(e).isConst()) theIntParameters.set(intOfExt(e),value(e)); } public double value(int index) { return theParameters.value(index); } public double error(int index) { return theParameters.error(index); } /// interaction via name of parameter public void fix(String name) { fix(index(name)); } public void release(String name) { release(index(name)); } public void setValue(String name, double val) { setValue(index(name), val);; } public void setError(String name, double err) { setError(index(name), err); } public void setLimits(String name, double low, double up) { setLimits(index(name), low, up); } public void setUpperLimit(String name, double up) { setUpperLimit(index(name), up); } public void setLowerLimit(String name, double low) { setLowerLimit(index(name), low); } public void removeLimits(String name) { removeLimits(index(name)); } public double value(String name) { return value(index(name)); } public double error(String name) { return error(index(name)); } /** convert name into external number of parameter */ public int index(String name) { return theParameters.index(name); } /** convert external number into name of parameter */ public String name(int index) { return theParameters.name(index); } // transformation internal <-> external double int2ext(int i, double val) { return theParameters.trafo().int2ext(i,val); } double ext2int(int i, double val) { return theParameters.trafo().ext2int(i,val); } int intOfExt(int ext) { return theParameters.trafo().intOfExt(ext); } public int extOfInt(int internal) { return theParameters.trafo().extOfInt(internal); } public int variableParameters() { return theParameters.variableParameters(); } public MnMachinePrecision precision() { return theParameters.precision(); } public void setPrecision(double eps) { theParameters.setPrecision(eps); } public String toString() { return MnPrint.toString(this); } }