diff --git a/algorithms/java/src/org/openda/algorithms/SimplexCoreOptimizer.java b/algorithms/java/src/org/openda/algorithms/SimplexCoreOptimizer.java index d5acdeca6..98a4eb273 100644 --- a/algorithms/java/src/org/openda/algorithms/SimplexCoreOptimizer.java +++ b/algorithms/java/src/org/openda/algorithms/SimplexCoreOptimizer.java @@ -17,8 +17,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with OpenDA. If not, see . */ + package org.openda.algorithms; +import java.util.ArrayList; +import java.util.List; import org.openda.interfaces.IMatrix; import org.openda.interfaces.IObservationDescriptions; @@ -28,46 +31,43 @@ import org.openda.utils.Results; import org.openda.utils.Vector; -import java.util.ArrayList; -import java.util.List; - public class SimplexCoreOptimizer{ // fields of this class - private IVector pCurrent[] = null; //values under consideration - private double fCurrent[] = null; - private IVector predCurrent[] = null; //predictions for each estimate (in case of LeastSquaresCostFunction) + private IVector[] pCurrent = null; //values under consideration + private double[] fCurrent = null; + private IVector[] predCurrent = null; //predictions for each estimate (in case of LeastSquaresCostFunction) private int nparam=0; - private ICostFunction f = null; + private final ICostFunction f; protected int maxitSimplex = 100; protected double absTolSimplex=0.01; protected double relTolSimplex=0.01; - // required for the additional stopping criteria: - public List stopCriteria = new ArrayList(); - public List stopCriteriaThreshold = new ArrayList(); - public double stopCritThresDefault = 0.01; - public IObservationDescriptions obsDescr=null; - - // constants - private double rconst = -1; // constant for reflection - private double econst = 2.0; // constant for exspansion - private double cconst = .5; // constant for contractions - private double sconst = .5; // constant for scaling + // required for the additional stopping criteria: + public List stopCriteria = new ArrayList<>(); + public List stopCriteriaThreshold = new ArrayList<>(); + public double stopCritThresDefault = 0.01; + public IObservationDescriptions obsDescr; + + // constants + private final double rConst = -1; // constant for reflection + private final double eConst = 2.0; // constant for expansion + private final double cConst = .5; // constant for contractions + private final double sConst = .5; // constant for scaling //stopping - private boolean moreToDo = true; // is this optimization finished - private int imain=0; // main iterations done + private boolean moreToDo = true; // is this optimization finished + private int iMain = 0; // main iterations done private double[] stdValues; /** - * Constructor for Simplex minimization - * @param f : cost function to be minimized - */ - public SimplexCoreOptimizer(ICostFunction f){ - this.f = f; - } + * Constructor for Simplex minimization + * @param f : cost function to be minimized + */ + public SimplexCoreOptimizer(ICostFunction f){ + this.f = f; + } /** * Constructor for Simplex minimization @@ -103,47 +103,46 @@ public void initialize(IVector pInit, double width){ * Initializer for setting the current simplex, e.g. from a restart file * @param pCurrent : Parameters to be restored, for each point of the simplex */ - public void initialize(IVector pCurrent[]){ - this.pCurrent = new IVector[pCurrent.length]; - this.fCurrent = new double[pCurrent.length]; + public void initialize(IVector[] pCurrent){ + this.pCurrent = new IVector[pCurrent.length]; + this.fCurrent = new double[pCurrent.length]; this.predCurrent = new IVector[pCurrent.length]; - for(int i=0;ithis.absTolSimplex) & ((diff)>this.relTolSimplex*Math.abs(costs[0])); + this.moreToDo = (iMainthis.absTolSimplex) & ((diff)>this.relTolSimplex*Math.abs(costs[0])); } /** @@ -151,7 +150,7 @@ private void sortSimplexByCost(){ * @return parameters as Vector */ public IVector getOptimalValue(){ - return this.f.getOptimalParameters(); + return this.f.getOptimalParameters(); } /** @@ -159,7 +158,7 @@ public IVector getOptimalValue(){ * @return cost */ public double getOptimalCost(){ - return this.f.getOptimalCost(); + return this.f.getOptimalCost(); } /** @@ -168,7 +167,7 @@ public double getOptimalCost(){ * @return Vector for parameters at each nod of the simplex (m+1) vectors, where m=length(p) */ public IVector[] getCurrentValues(){ - IVector result[] = new IVector[this.pCurrent.length]; + IVector[] result = new IVector[this.pCurrent.length]; for(int i=0;i=costs[0]) & (cost_r=cost_r){ - flagstep = 1; - sparam[nparam] = sreflect; - costs[nparam] = cost_r; - preds[nparam] = predReflect; - Results.putMessage("REFLECT ALSO!"); - } - } - - //--- CONTRACT: - if ((flagstep==0) & (cost_r>=costs[nparam-1]) & (cost_r=costs[0]) & (cost_r=cost_r){ + flagstep = 1; + sparam[nparam] = sreflect; + costs[nparam] = cost_r; + preds[nparam] = predReflect; + Results.putMessage("REFLECT ALSO!"); + } + } + + //--- CONTRACT: + if ((flagstep==0) & (cost_r>=costs[nparam-1]) & (cost_r=costs[nparam])){ - // inside contraction - //MVL scontract = (1-cconst)*scentroid+cconst*sparam(:,nparam+1); - //scontract = (1-cconst)*scentroid-((1-cconst)/nparam-cconst)*sparam[nparam+1]; - scontract = scentroid.clone(); - scontract.scale(1-cconst); - scontract.axpy(-((1-cconst)/nparam-cconst), sparam[nparam]); - cost_c = this.f.evaluate(scontract,"contract inside"); + if (cost_c<=cost_r){ + flagstep = 1; + sparam[nparam] = scontract; + costs[nparam] = cost_c; + preds[nparam] = predContract; + Results.putMessage("CONTRACT OUTSIDE!"); + } + } + if ((flagstep==0) & (cost_r>=costs[nparam])){ + // inside contraction + //MVL scontract = (1-cConst)*scentroid+cConst*sparam(:,nparam+1); + //scontract = (1-cConst)*scentroid-((1-cConst)/nparam-cConst)*sparam[nparam+1]; + scontract = scentroid.clone(); + scontract.scale(1-cConst); + scontract.axpy(-((1-cConst)/nparam-cConst), sparam[nparam]); + cost_c = this.f.evaluate(scontract,"contract inside"); if(this.f instanceof LeastSquaresCostFunction){ predContract=((LeastSquaresCostFunction)this.f).getLastPredictions(); } - if (cost_cthis.absTolSimplex) & ((diff)>this.relTolSimplex*Math.abs(costs[0])); - Results.putMessage("stop criterion 1, imain > maxit:\t "+imain+" < "+Math.round(this.maxitSimplex)); - Results.putMessage("stop criterion 2, diff < abstol:\t "+diff+" > "+this.absTolSimplex); - Results.putMessage("stop criterion 3, relDiff < reltol:\t "+relDiff+" > "+this.relTolSimplex); + Results.putMessage("SHRINK"); + // Check if "SHRINK" produces better sets of parameter + if (costmaxthis.absTolSimplex) & ((diff)>this.relTolSimplex*Math.abs(costs[0])); + Results.putMessage("stop criterion 1, iMain > maxit:\t "+iMain+" < "+Math.round(this.maxitSimplex)); + Results.putMessage("stop criterion 2, diff < abstol:\t "+diff+" > "+this.absTolSimplex); + Results.putMessage("stop criterion 3, relDiff < reltol:\t "+relDiff+" > "+this.relTolSimplex); } // iteration loop - // additional stop criteria: - if (stopCriteria.size()>0) { - // To do: generalize for non leastsquarecostfunction too! - IVector residual = null; - if(this.f instanceof LeastSquaresCostFunction){ - residual = ((LeastSquaresCostFunction)f).getObservationUncertainty().getExpectations(); - } else { - throw new RuntimeException("Additional stop criterion is only implemented for LeastSquaresCostFunction.."); - } - residual.axpy(-1.0,preds[0]); - boolean isStop = false; - for (int i=0; i0) { + // To do: generalize for non leastsquarecostfunction too! + IVector residual; + if(this.f instanceof LeastSquaresCostFunction){ + residual = ((LeastSquaresCostFunction)f).getObservationUncertainty().getExpectations(); + } else { + throw new RuntimeException("Additional stop criterion is only implemented for LeastSquaresCostFunction.."); + } + residual.axpy(-1.0,preds[0]); + boolean isStop; + for (int i=0; i { public int compare(Object o1, Object o2) { - return new Double(((indexValuePair)o1).value).compareTo(((indexValuePair) o2).value); + return Double.compare(((indexValuePair) o1).value, ((indexValuePair) o2).value); } } int[] result = new int[values.length]; - java.util.ArrayList sortedValues = new java.util.ArrayList(); + java.util.ArrayList sortedValues = new java.util.ArrayList<>(); for(int i=0;i iter = new HashMap(); - - // A list that contains the opened netcdf files: each variable (id), - // needs its own netcdfile. The netcdffile should be opened before/during first writing , - // All netcdf files should be closed together in a finalize call. - - private HashMap idlist = new HashMap(); - - private String netcdfnameprefix = " "; - private int ctaFilehandle = 0; - private int defaultMaxSize = Integer.MAX_VALUE; - - public NetcdfResultWriter(File workingDir, String configString) { - if (configString.startsWith(" iter = new HashMap(); + + // A list that contains the opened netcdf files: each variable (id), + // needs its own netcdfile. The netcdffile should be opened before/during first writing , + // All netcdf files should be closed together in a finalize call. + + private HashMap idlist = new HashMap(); + + private String netcdfnameprefix = " "; + private int ctaFilehandle = 0; + private final int defaultMaxSize = Integer.MAX_VALUE; + + public NetcdfResultWriter(File workingDir, String configString) { + if (configString.startsWith("