/* * Copyright (C) 2015 Martin Berger * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.conrad.optimization; import edu.stanford.rsl.jpop.GradientOptimizableFunction; /** * This class wraps an arbitrary number of jpop cost-functions into a combined cost-function value. * It uses Lagrange multipliers that can be set for each function individually. * Combining analytic gradients is also supported in case all functions provide an analytic gradient. * @author Martin Berger */ public class CombinedGradientOptimizableFunction implements GradientOptimizableFunction { GradientOptimizableFunction[] stackedFunctions; double[] lambdas; @Override public void setNumberOfProcessingBlocks(int number) { for(GradientOptimizableFunction f : stackedFunctions) f.setNumberOfProcessingBlocks(number); } @Override public int getNumberOfProcessingBlocks() { return stackedFunctions[0].getNumberOfProcessingBlocks(); } @Override public double evaluate(double[] x, int block) { double result = 0; for (int i = 0; i < stackedFunctions.length; i++) { if(lambdas[i]!=0) result += lambdas[i]*stackedFunctions[i].evaluate(x, block); } return result; } @Override public double[] gradient(double[] x, int block) { double[] grads = null; for (int i = 0; i < this.stackedFunctions.length; i++) { if (lambdas[i]!=0){ double[] res = stackedFunctions[i].gradient(x, block); if (res!=null){ if(grads==null) grads = new double[x.length]; for (int j = 0; j < grads.length; j++) { grads[j]+=lambdas[i]*res[j]; } }else return null; } } return grads; } public GradientOptimizableFunction[] getStackedFunctions() { return stackedFunctions; } public void setStackedFunctions( GradientOptimizableFunction[] stackedFunctions) { this.stackedFunctions = stackedFunctions; } public double[] getLambdas() { return lambdas; } public void setLambdas(double[] lambdas) { this.lambdas = lambdas; } }