package hep.aida.ref.pdf;
import java.util.ArrayList;
/**
*
* @author The FreeHEP team @ SLAC.
*
* A product of PDFs is not a PDF (unless none of the pdf shapres any dependents
* with any other pdf).
*
*/
public class Product extends Function {
private Function[] functions;
public Product(String name, Function f1, Function f2) {
super(name);
functions = new Function[] {f1,f2};
initializeProduct(functions);
}
public Product(String name, ArrayList functionsArray) {
super(name);
initializeProduct(functionsArray);
}
private void initializeProduct(ArrayList functionsArray) {
functions = new Function[functionsArray.size()];
for ( int i = 0; i < functions.length; i++ )
functions[i] = (Function) functionsArray.get(i);
initializeProduct(functions);
}
private void initializeProduct(Function[] functions) {
VariableList list = new VariableList();
int nFunctions = functions.length;
for ( int i = 0; i < nFunctions; i++ ) {
Function f = functions[i];
//When multiplying 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);
}
}
addVariables(list);
}
public double functionValue() {
double val = 1;
for ( int i = 0; i < functions.length; i++ )
val *= functions[i].functionValue();
return val;
}
public boolean hasAnalyticalVariableGradient(Variable var) {
return true;
}
public double evaluateAnalyticalVariableGradient(Variable var) {
double val = 0;
for ( int i = 0; i < functions.length; i++ ) {
Function g = functions[i];
double term = g.evaluateAnalyticalVariableGradient(var);
for ( int j = 0; j < functions.length; j++ ) {
if ( j != i) {
Function f = functions[i];
term *= f.functionValue();
}
}
val += term;
}
return val;
}
public boolean hasAnalyticalNormalization(Dependent dep) {
for ( int i = 0; i < functions.length; i++ ) {
Function f = functions[i];
if ( f.hasDependent(dep) ) {
if ( ! f.hasAnalyticalNormalization(dep) )
return false;
if ( i != functions.length - 1 ) {
for ( int j = i+1; j < functions.length; j++ ) {
Function g = functions[j];
if ( g.hasDependent(dep) )
return false;
}
}
}
}
return false;
}
public double evaluateAnalyticalNormalization(Dependent dep) {
for ( int i = 0; i < functions.length; i++ ) {
Function f = functions[i];
if ( f.hasDependent(dep) )
return f.evaluateAnalyticalNormalization(dep);
}
return 0;
}
protected void updateNormalization() {
for ( int i = 0; i < functions.length; i++ )
functions[i].updateNormalization();
super.updateNormalization();
}
}