package hep.aida.ref.function;
import hep.aida.IAnnotation;
import hep.aida.IFunction;
import hep.aida.ref.Annotation;
import hep.aida.ref.ManagedObject;
import java.util.ArrayList;
/**
*
* @author The FreeHEP team @ SLAC
*
*/
public class SumOfFunctions extends ManagedObject implements IFunction {
private ArrayList functions;
private boolean hasFunctions = false;
private int dimension;
private Annotation annotation = new Annotation();
private String[] parameters;
private double[] parValues;
private String name;
private String title;
public SumOfFunctions(String name, ArrayList functions) {
super(name);
this.functions = functions;
this.name = name;
updateFunction();
}
void updateFunction() {
if ( nFunctions() > 0 ) {
hasFunctions = true;
dimension = function(0).dimension();
int nPars = function(0).numberOfParameters();
for ( int i = 1; i < nFunctions(); i++ ) {
if ( function(i).dimension() != dimension )
throw new IllegalArgumentException("To be added functions must have the same dimension");
nPars += function(i).numberOfParameters();
}
parameters = new String[nPars];
parValues = new double[nPars];
int count = 0;
for ( int i = 0; i < nFunctions(); i++ ) {
String[] pars = function(i).parameterNames();
for ( int j = 0; j < pars.length; j++ ) {
String parName = pars[j];
for ( int k = 0; k < parameters.length; k++ )
if ( parName.equals( parameters[k] ) )
parName += "_"+indexOfFunction(function(i));
parameters[count++] = parName;
}
}
title = codeletString();
} else {
hasFunctions = false;
parameters = null;
parValues = null;
title = "";
}
}
public IAnnotation annotation() {
return (IAnnotation) annotation;
}
public String normalizationParameter() {
throw new UnsupportedOperationException();
}
public String codeletString() {
if ( hasFunctions ) {
String codelet = FunctionCatalog.prefix+CodeletUtils.modelFromCodelet(function(0).codeletString());
for ( int i = 1; i < nFunctions(); i++ )
codelet +=" + "+CodeletUtils.modelFromCodelet(function(i).codeletString());
codelet += ":catalog";
return codelet;
}
return null;
}
public int dimension() {
return dimension;
}
public double[] gradient(double[] values) {
if ( ! providesGradient() )
throw new IllegalArgumentException("This function does not provide the gradient.");
double[] gradient = function(0).gradient(values);
for ( int i = 1; i < nFunctions(); i++ ) {
double[] tmpGrad = function(i).gradient(values);
for ( int j = 0; j < dimension(); j++ )
gradient[j] += tmpGrad[j];
}
return gradient;
}
public int indexOfParameter(String str) {
for ( int i = 0; i < parameters.length; i++ )
if ( str.equals( parameters[i] ) )
return i;
throw new IllegalArgumentException("Illegal parameter name "+str);
}
public boolean isEqual(hep.aida.IFunction iFunction) {
return false;
}
public int numberOfParameters() {
return parameters.length;
}
public double parameter(String str) {
int index = indexOfParameter(str);
for ( int i = 0; i < nFunctions(); i++ ) {
IFunction func = function(i);
int nPars = func.numberOfParameters();
if ( index > nPars-1 )
index -= nPars;
else
return func.parameter( parameterNames()[index] );
}
throw new IllegalArgumentException("Illegal parameter "+str);
}
public String[] parameterNames() {
return parameters;
}
public double[] parameters() {
int count = 0;
for ( int i = 0; i < nFunctions(); i++ ) {
double[] pars = function(i).parameters();
for ( int j = 0; j < pars.length; j++ )
parValues[count++] = pars[j];
}
return parValues;
}
public boolean providesGradient() {
for ( int i = 0; i < nFunctions(); i++ )
if ( ! function(i).providesGradient() )
return false;
return true;
}
public void setParameter(String str, double param) throws java.lang.IllegalArgumentException {
int index = indexOfParameter(str);
for ( int i = 0; i < nFunctions(); i++ ) {
IFunction func = function(i);
int nPars = func.numberOfParameters();
if ( index > nPars-1 )
index -= nPars;
else {
func.setParameter( func.parameterNames()[index], param );
return;
}
}
}
public void setParameters(double[] values) throws java.lang.IllegalArgumentException {
if ( values.length != numberOfParameters() )
throw new IllegalArgumentException("Illegal size "+values.length+". It has to be equal to the number of parameters "+numberOfParameters()+".");
for ( int i = 0; i < values.length; i++ )
setParameter(parameters[i], values[i]);
}
public void setTitle(String str) throws java.lang.IllegalArgumentException {
this.title = str;
}
public String title() {
return title;
}
public double value(double[] values) {
double result = 0;
for ( int i = 0; i < nFunctions(); i++ )
result += function(i).value(values);
return result;
}
public String variableName(int param) {
return function(0).variableName(param);
}
public String[] variableNames() {
return function(0).variableNames();
}
public void addFunction(IFunction func) {
functions.add(func);
updateFunction();
}
public void removeFunction(IFunction func) {
functions.remove(func);
updateFunction();
}
public void removeAllFunctions() {
functions.clear();
updateFunction();
}
public IFunction function(int index) {
return (IFunction) functions.get(index);
}
public int indexOfFunction(IFunction function) {
return functions.indexOf(function);
}
public int nFunctions() {
return functions.size();
}
public boolean containsFunction(IFunction function) {
return functions.contains(function);
}
}