package org.freehep.math.minuit; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; /** knows how to transform between user specified parameters (external) and * internal parameters used for minimization * @version $Id: MnUserTransformation.java 8584 2006-08-10 23:06:37Z duns $ */ class MnUserTransformation { private MnMachinePrecision thePrecision; private List<MinuitParameter> theParameters; private List<Integer> theExtOfInt; private Map<String, Integer> nameMap = new HashMap<String, Integer>(); private SinParameterTransformation theDoubleLimTrafo; private SqrtUpParameterTransformation theUpperLimTrafo; private SqrtLowParameterTransformation theLowerLimTrafo; private List<Double> theCache; MnUserTransformation() { thePrecision = new MnMachinePrecision(); theParameters = new ArrayList<MinuitParameter>(); theExtOfInt = new ArrayList<Integer>(); theDoubleLimTrafo = new SinParameterTransformation(); theUpperLimTrafo = new SqrtUpParameterTransformation(); theLowerLimTrafo = new SqrtLowParameterTransformation(); theCache = new ArrayList<Double>(0); } protected MnUserTransformation clone() { return new MnUserTransformation(this); } private MnUserTransformation(MnUserTransformation other) { thePrecision = other.thePrecision; theParameters = new ArrayList<MinuitParameter>(other.theParameters.size()); for (MinuitParameter par : other.theParameters) theParameters.add(par.clone()); theExtOfInt = new ArrayList<Integer>(other.theExtOfInt); theDoubleLimTrafo = new SinParameterTransformation(); theUpperLimTrafo = new SqrtUpParameterTransformation(); theLowerLimTrafo = new SqrtLowParameterTransformation(); theCache = new ArrayList<Double>(other.theCache); } MnAlgebraicVector transform(MnAlgebraicVector pstates) { // FixMe: Worry about efficiency here MnAlgebraicVector result = new MnAlgebraicVector(theCache.size()); for (int i=0; i<result.size();i++) result.set(i,theCache.get(i)); for(int i = 0; i < pstates.size(); i++) { if(theParameters.get(theExtOfInt.get(i)).hasLimits()) { result.set(theExtOfInt.get(i) , int2ext(i, pstates.get(i))); } else { result.set(theExtOfInt.get(i) , pstates.get(i)); } } return result; } MnUserTransformation(double[] par, double[] err) { thePrecision = new MnMachinePrecision(); theDoubleLimTrafo = new SinParameterTransformation(); theUpperLimTrafo = new SqrtUpParameterTransformation(); theLowerLimTrafo = new SqrtLowParameterTransformation(); theParameters = new ArrayList<MinuitParameter>(par.length); theExtOfInt = new ArrayList<Integer>(par.length); theCache = new ArrayList<Double>(par.length); for (int i = 0; i < par.length; i++) { add("p"+i, par[i], err[i]); } } //forwarded interface MnMachinePrecision precision() { return thePrecision; } void setPrecision(double eps) { thePrecision.setPrecision(eps); } List<MinuitParameter> parameters() { return theParameters; } int variableParameters() { return theExtOfInt.size(); } //access to parameters and errors in column-wise representation double[] params() { double[] result = new double[theParameters.size()]; int i = 0; for (MinuitParameter parameter : theParameters) { result[i++] = parameter.value(); } return result; } double[] errors() { double[] result = new double[theParameters.size()]; int i = 0; for (MinuitParameter parameter : theParameters) { result[i++] = parameter.error(); } return result; } /** access to single parameter */ MinuitParameter parameter(int index) { return theParameters.get(index); } /** add free parameter */ void add(String name, double val, double err) { if (nameMap.containsKey(name)) throw new IllegalArgumentException("duplicate name: "+name); nameMap.put(name,theParameters.size()); theExtOfInt.add(theParameters.size()); theCache.add(val); theParameters.add(new MinuitParameter(theParameters.size(), name, val, err)); } /** add limited parameter */ void add(String name, double val, double err, double low, double up) { if (nameMap.containsKey(name)) throw new IllegalArgumentException("duplicate name: "+name); nameMap.put(name,theParameters.size()); theExtOfInt.add(theParameters.size()); theCache.add(val); theParameters.add(new MinuitParameter(theParameters.size(), name, val, err, low, up)); } /** add parameter */ void add(String name, double val) { if (nameMap.containsKey(name)) throw new IllegalArgumentException("duplicate name: "+name); nameMap.put(name,theParameters.size()); theCache.add(val); theParameters.add(new MinuitParameter(theParameters.size(), name, val)); } /** interaction via external number of parameter */ void fix(int index) { int iind = intOfExt(index); theExtOfInt.remove(iind); theParameters.get(index).fix(); } void release(int index) { if (theExtOfInt.contains(index)) throw new IllegalArgumentException("index="+index); theExtOfInt.add(index); Collections.sort(theExtOfInt); theParameters.get(index).release(); } void setValue(int index, double val) { theParameters.get(index).setValue(val); theCache.set(index,val); } void setError(int index, double err) { theParameters.get(index).setError(err); } void setLimits(int index, double low, double up) { theParameters.get(index).setLimits(low, up); } void setUpperLimit(int index, double up) { theParameters.get(index).setUpperLimit(up); } void setLowerLimit(int index, double low) { theParameters.get(index).setLowerLimit(low); } void removeLimits(int index) { theParameters.get(index).removeLimits(); } double value(int index) { return theParameters.get(index).value(); } double error(int index) { return theParameters.get(index).error(); } /** interaction via name of parameter */ void fix(String name) { fix(index(name)); } void release(String name) { release(index(name)); } void setValue(String name, double val) { setValue(index(name), val); } void setError(String name, double err) { setError(index(name), err); } void setLimits(String name, double low, double up) { setLimits(index(name), low, up); } void setLowerLimit(String name, double low) { setLowerLimit(index(name), low); } void setUpperLimit(String name, double up) { setUpperLimit(index(name), up); } void removeLimits(String name) { removeLimits(index(name)); } double value(String name) { return value(index(name)); } double error(String name) { return error(index(name)); } /** convert name into external number of parameter */ int index(String name) { return nameMap.get(name); } /** convert external number into name of parameter */ String name(int index) { return theParameters.get(index).name(); } double int2ext(int i, double val) { MinuitParameter parm = theParameters.get(theExtOfInt.get(i)); if(parm.hasLimits()) { if(parm.hasUpperLimit() && parm.hasLowerLimit()) return theDoubleLimTrafo.int2ext(val, parm.upperLimit(), parm.lowerLimit()); else if(parm.hasUpperLimit() && !parm.hasLowerLimit()) return theUpperLimTrafo.int2ext(val, parm.upperLimit()); else return theLowerLimTrafo.int2ext(val, parm.lowerLimit()); } return val; } double int2extError(int i, double val, double err) { double dx = err; MinuitParameter parm = theParameters.get(theExtOfInt.get(i)); if(parm.hasLimits()) { double ui = int2ext(i, val); double du1 = int2ext(i, val+dx) - ui; double du2 = int2ext(i, val-dx) - ui; if(parm.hasUpperLimit() && parm.hasLowerLimit()) { if(dx > 1.) du1 = parm.upperLimit() - parm.lowerLimit(); dx = 0.5*(Math.abs(du1) + Math.abs(du2)); } else { dx = 0.5*(Math.abs(du1) + Math.abs(du2)); } } return dx; } MnUserCovariance int2extCovariance(MnAlgebraicVector vec, MnAlgebraicSymMatrix cov) { MnUserCovariance result = new MnUserCovariance(cov.nrow()); for(int i = 0; i < vec.size(); i++) { double dxdi = 1.; if (theParameters.get(theExtOfInt.get(i)).hasLimits()) { dxdi = dInt2Ext(i, vec.get(i)); } for(int j = i; j < vec.size(); j++) { double dxdj = 1.; if(theParameters.get(theExtOfInt.get(j)).hasLimits()) { dxdj = dInt2Ext(j, vec.get(j)); } result.set(i,j,dxdi*cov.get(i,j)*dxdj); } } return result; } double ext2int(int i, double val) { MinuitParameter parm = theParameters.get(i); if(parm.hasLimits()) { if(parm.hasUpperLimit() && parm.hasLowerLimit()) return theDoubleLimTrafo.ext2int(val, parm.upperLimit(), parm.lowerLimit(), precision()); else if(parm.hasUpperLimit() && !parm.hasLowerLimit()) return theUpperLimTrafo.ext2int(val, parm.upperLimit(), precision()); else return theLowerLimTrafo.ext2int(val, parm.lowerLimit(), precision()); } return val; } double dInt2Ext(int i, double val) { double dd = 1.; MinuitParameter parm = theParameters.get(theExtOfInt.get(i)); if(parm.hasLimits()) { if(parm.hasUpperLimit() && parm.hasLowerLimit()) dd = theDoubleLimTrafo.dInt2Ext(val, parm.upperLimit(), parm.lowerLimit()); else if(parm.hasUpperLimit() && !parm.hasLowerLimit()) dd = theUpperLimTrafo.dInt2Ext(val, parm.upperLimit()); else dd = theLowerLimTrafo.dInt2Ext(val, parm.lowerLimit()); } return dd; } int intOfExt(int ext) { for (int iind = 0; iind < theExtOfInt.size(); iind++) { if (ext == theExtOfInt.get(iind)) return iind; } throw new IllegalArgumentException("ext="+ext); } int extOfInt(int internal) { return theExtOfInt.get(internal); } }