package hep.aida.ref.pdf; import java.util.ArrayList; /** * * @author The FreeHEP team @ SLAC. * */ public class Sum extends Function { private Function[] functions; private Parameter[] fractions; private double[] fractionsValue; public Sum(String name, Function f1, Function f2) { this(name, f1, f2, null); } public Sum(String name, Function f1, Function f2, Parameter p) { super(name); functions = new Function[] {f1,f2}; if ( p != null ) fractions = new Parameter[] {p}; else fractions = makeFractions(1); initializeSum(functions, fractions); } public Sum(String name, ArrayList functionsArray) { this(name, functionsArray, null); } public Sum(String name, ArrayList functionsArray, ArrayList fractionsArray) { super(name); initializeSum(functionsArray, fractionsArray); } private Parameter[] makeFractions(int size) { Parameter[] fractions = new Parameter[size]; double val = 1./(size+1); for ( int i = 0; i < size; i++ ) fractions[i] = new Parameter("f"+i,val,0,1); return fractions; } private void initializeSum(ArrayList functionsArray, ArrayList fractionsArray) { functions = new Function[functionsArray.size()]; for ( int i = 0; i < functions.length; i++ ) functions[i] = (Function) functionsArray.get(i); if ( fractionsArray == null ) fractions = makeFractions(functionsArray.size()-1); else { fractions = new Parameter[fractionsArray.size()]; for ( int i = 0; i < fractions.length; i++ ) fractions[i] = (Parameter) fractionsArray.get(i); } initializeSum(functions, fractions); } private void initializeSum(Function[] functions, Parameter[] fractions) { if ( fractions.length != (functions.length-1) ) throw new IllegalArgumentException("Invalid size for the provided objects. The number of fractions parameters should be one unit less than the size of the provided functions"); int nFunctions = functions.length; VariableList list = new VariableList(); for ( int i = 0; i < nFunctions; i++ ) { Function f = functions[i]; //When adding the functions have to be normalized. f.normalize(true); for ( int j = 0; j < f.numberOfDependents(); j++ ) { Dependent dep = f.getDependent(j); if ( ! list.contains(dep) ) list.add(dep); } for ( int j = 0; j < f.numberOfParameters(); j++ ) { Parameter par = f.getParameter(j); if ( ! list.contains(par) ) list.add(par); } if ( i != 0 ) { Parameter fraction = fractions[i-1]; if ( ! list.contains(fraction) ) list.add(fraction); } } fractionsValue = new double[fractions.length+1]; fractionsValue[0] = 1.; addVariables(list); } public void variableChanged(Variable var) { for ( int i = 0; i < fractions.length; i++ ) { if ( var == fractions[i] ) { fractionsValue[0] += fractionsValue[i+1]; fractionsValue[i+1] = var.value(); fractionsValue[0] -= fractionsValue[i+1]; break; } } } public double functionValue() { double val = 0; for ( int i = 0; i < functions.length; i++ ) { val += functions[i].value()*fractionsValue[i]; } return val; } public boolean hasAnalyticalVariableGradient(Variable var) { for ( int i = 0; i < functions.length; i++ ) { if ( ! functions[i].hasAnalyticalVariableGradient(var) ) return false; } return true; } public double evaluateAnalyticalVariableGradient(Variable var) { double val = 0; int index = indexOfFraction(var); for ( int i = 0; i < functions.length; i++ ) { val += functions[i].evaluateAnalyticalVariableGradient(var)*fractionsValue[i]; } if ( index != -1 ) { if ( index == 0 ) throw new IllegalArgumentException(); val += functions[index].value() - functions[0].value(); } return val; } private int indexOfFraction(Variable par) { for ( int i = 0; i < fractions.length; i++ ) if ( fractions[i] == par ) return i+1; return -1; } public boolean hasAnalyticalNormalization(Dependent dep) { for ( int i = 0; i < functions.length; i++ ) { if ( ! functions[i].hasAnalyticalNormalization(dep) ) return false; } return true; } public double evaluateAnalyticalNormalization(Dependent dep) { return 1; } protected void updateNormalization() { for ( int i = 0; i < functions.length; i++ ) functions[i].updateNormalization(); super.updateNormalization(); } public int nAddend() { return functions.length; } public Function addend(int index) { if ( index < 0 || index > functions.length - 1 ) throw new IllegalArgumentException("Illegal index value "+index); return functions[index]; } public double fraction(int index) { if ( index < 0 || index > functions.length - 1 ) throw new IllegalArgumentException("Illegal index value "+index); return fractionsValue[index]; } }