diff --git a/src/eva2/server/go/operators/paramcontrol/AbstractAdaptiveParameters.java b/src/eva2/server/go/operators/paramcontrol/AbstractAdaptiveParameters.java new file mode 100644 index 00000000..a66fb88f --- /dev/null +++ b/src/eva2/server/go/operators/paramcontrol/AbstractAdaptiveParameters.java @@ -0,0 +1,84 @@ +//package eva2.server.go.operators.paramcontrol; +// +//import java.io.Serializable; +// +//import eva2.tools.Mathematics; +// +///** +// * Generically adapted parameters. Currently, linear and exponential decrease is supported. Each type +// * of adaptivity uses the parameters in each context: +// * - linear: parameter 0 is start value, parameter 1 is end value. +// * - halvingTime: param. 0 is start value (t=0), param. 1 is the half-value time expressed in percent of the full run. +// * @author mkron +// * +// */ +//public abstract class AbstractAdaptiveParameters extends AbstractParameterControl implements Serializable { +// +// public AbstractAdaptiveParameters(AbstractParameterControl o) { +// super(o); +// } +// +// public AbstractAdaptiveParameters() { +// } +// +// /** +// * Return the number of parameters under adaptive control. +// * +// * @return +// */ +// protected int getNumParams() { +// String[] params = getControlledParameters(); +// return params.length; +// } +// +// /** +// * For the controlled parameter at index i return the type of adaptivitiy. +// * +// * @param p +// * @return +// */ +// protected abstract AdaptivityEnum getAdaptivityType(int p); +// +// public Object[] getValues(Object obj, int iteration, int maxIteration) { +// if (maxIteration < 0) { // there is no maxIteration known +// System.err.println("Not changing parameters - missing iteration information!"); +// return null; +// } else { +// Object[] vals=new Object[getNumParams()]; +// for (int i=0; i= 0 && (interestingRatio < minInterestingRatio)) { // performance too bad + // reduce period --> increase frequency + adaptValue(decFact, pop); + } else if (interestingRatio > maxInterestingRatio) { // performance is too good + // increase period --> decrease frequency + adaptValue(incFact, pop); + } + if (oldVal!=currentVal) { +// System.out.println("++ Changed period at it." + iteration +// + ", ratio " + interestingRatio + " from " + oldVal + " to " + currentVal); + setShift(cbpso, pop, oldVal, currentVal); + } + } + } + + private void setShift(CBNPSO cbpso, Population pop, double oldVal, double currentVal2) { + double k = pop.getFunctionCalls()/currentVal; + int diff = (int) (pop.getFunctionCalls()-(((int)k)*currentVal)); + + cbpso.setSigmaAdaptionShift(diff); + + } + + private void adaptValue(double fact, Population pop) { + currentVal *= fact; + currentVal = Math.max(lowerBnd, Math.min(upperBnd, currentVal)); + lastAdaption = pop.getGeneration(); + adptIntervalGenerations = (int)(currentVal/pop.getTargetSize()); + } + + private boolean isPossibleAdaptionTime(Population pop) { + if (lastAdaption+adptIntervalGenerations>pop.getGeneration()) return false; + else return true; + } + + @Override + public void finish(Object obj, Population pop) { + + } + + @Override + public String getControlledParam() { + return paramName; + } + + @Override + public void init(Object obj, Population pop, Object[] initialValues) { + currentVal=initialVal; + lastAdaption=0; + adptIntervalGenerations = (int)(currentVal/pop.getTargetSize()); + } + + @Override + public void setControlledParam(String prm) { + paramName = prm; + } + + public void setInitialVal(double initialVal) { + this.initialVal = initialVal; + } + + public double getInitialVal() { + return initialVal; + } + +} diff --git a/src/eva2/server/go/operators/paramcontrol/ConstraintBasedAdaption.java b/src/eva2/server/go/operators/paramcontrol/ConstraintBasedAdaption.java new file mode 100644 index 00000000..d71ac957 --- /dev/null +++ b/src/eva2/server/go/operators/paramcontrol/ConstraintBasedAdaption.java @@ -0,0 +1,180 @@ +package eva2.server.go.operators.paramcontrol; + +import java.io.Serializable; +import java.util.LinkedList; + +import eva2.server.go.individuals.InterfaceDataTypeDouble; +import eva2.server.go.operators.constraint.AbstractConstraint; +import eva2.server.go.populations.Population; +import eva2.tools.math.Mathematics; + +/** + * Simple penalty factor adaption for contraints with fitness based penalty after Bean and Hadj-Alouane 1992/1997. + * If the best individual was always feasible for k generations, the penalty factor is decreased, + * if it was always infeasible, the penalty factor is increased. For other cases, the penalty remains the same. + * This is plausible for the typical case that the optimum lies near the constraint boundary, however it makes + * the fitness function change dynamically based only on the positions of last best indidivuals. + * + * The authors advise to select betaInc != 1./betaDec to avoid cycling. + * @author mkron + * + */ +public class ConstraintBasedAdaption implements ParamAdaption, Serializable { + private double betaInc=1.5; + private double betaDec=0.7; + private double initialPenalty = 1.; + private double minPenalty=0.01; + private double maxPenalty=100.; + private double currentFactor = 1.; + private int genGap=5; + + LinkedList lastBestSatisfactionState = new LinkedList(); + +// private double endAct=0; +// private double deltaInertness = 0.1; + private static boolean TRACE=false; + + private static String target = "penaltyFactor"; + + public ConstraintBasedAdaption() {}; + + public ConstraintBasedAdaption( + ConstraintBasedAdaption o) { + betaInc = o.betaInc; + betaDec = o.betaDec; + genGap = o.genGap; +// endAct = o.endAct; +// deltaInertness = o.deltaInertness; + } + + public Object clone() { + return new ConstraintBasedAdaption(this); + } + + public Object calcValue(Object obj, Population pop, int iteration, int maxIteration) { + boolean changed = false; + if (!(obj instanceof AbstractConstraint)) System.err.println(this.getClass().getSimpleName() + " cant control " + obj.getClass().getSimpleName() + " ! "); + else { + if (TRACE) System.out.println("calc value at it " + iteration + " of " + maxIteration); + if (lastBestSatisfactionState.size()==genGap) lastBestSatisfactionState.poll(); + boolean bestIsFeasible = ((AbstractConstraint)obj).isSatisfied(((InterfaceDataTypeDouble)pop.getBestEAIndividual()).getDoubleDataWithoutUpdate()); + if (!lastBestSatisfactionState.offer(bestIsFeasible)) System.err.println("Error, could not push best indy state!"); + + changed=maybeAdaptFactor((AbstractConstraint)obj); + } + double curPen = initialPenalty * currentFactor; + if (curPen maxPenalty) { + currentFactor = maxPenalty/initialPenalty; + curPen=maxPenalty; + } + if (TRACE && changed) System.out.println("NEW penalty: " + curPen); + return curPen; + } + + private boolean maybeAdaptFactor(AbstractConstraint constr) { + boolean changed = false; + if (lastBestSatisfactionState.size() >= genGap) { + boolean allValid=true; + boolean allInvalid=true; + for (Boolean isFeasible : lastBestSatisfactionState) { + if (isFeasible) allInvalid=false; + else allValid=false; + } + if (allValid) { + currentFactor*=betaDec; + changed=true; + if (TRACE) System.out.println("all valid, new fact is " + currentFactor + " times " + initialPenalty); + } else if (allInvalid) { + changed=true; + currentFactor*=betaInc; + if (TRACE) System.out.println("all invalid, new fact is " + currentFactor + " times " + initialPenalty); + } + } else if (TRACE) System.out.println("not yet looking at " + genGap + " individuals..."); + return changed; + } + + public String getControlledParam() { + return target; + } + + public double getBetaInc() { + return betaInc; + } + public void setBetaInc(double d) { + this.betaInc = d; + } + public String betaIncTipText() { + return "The increase factor for the penalty."; + } + + public double getBetaDec() { + return betaDec; + } + public void setBetaDec(double d) { + this.betaDec = d; + } + public String betaDecTipText() { + return "The decrease factor for the penalty."; + } + + public int getGenGap() { + return genGap; + } + public void setGenGap(int v) { + this.genGap = v; + } + public String genGapTipText() { + return "The number of generations regarded."; + } + + public static String globalInfo() { + return "Adapt a constraint's penalty factor (esp. fitness based) if the population contained only valid or only invalid individuals for some generations."; + } + + public void finish(Object obj, Population pop) { + lastBestSatisfactionState.clear(); + ((AbstractConstraint) obj).setPenaltyFactor(initialPenalty); + } + + public void init(Object obj, Population pop, Object[] initialValues) { + initialPenalty = ((AbstractConstraint) obj).getPenaltyFactor(); + if (minPenalty > maxPenalty) { + System.err.println("Error in " + this.getClass().getSimpleName() + ", inconsistent penalty factor restrictions!"); + } + initialPenalty = Mathematics.projectValue(initialPenalty, minPenalty, maxPenalty); + lastBestSatisfactionState.clear(); + currentFactor=1.; + } + + public double getMinPenalty() { + return minPenalty; + } + + public void setMinPenalty(double minPenalty) { + this.minPenalty = minPenalty; + } + + public String minPenaltyTipText() { + return "The minimum penalty factor."; + } + + public double getMaxPenalty() { + return maxPenalty; + } + + public void setMaxPenalty(double maxPenalty) { + this.maxPenalty = maxPenalty; + } + + public String maxPenaltyTipText() { + return "The maximum penalty factor."; + } + + public String getName() { + return "Adaptive penalty factor"; + } + +} diff --git a/src/eva2/server/go/operators/paramcontrol/ExponentialDecayAdaption.java b/src/eva2/server/go/operators/paramcontrol/ExponentialDecayAdaption.java index eeec26e7..983277dc 100644 --- a/src/eva2/server/go/operators/paramcontrol/ExponentialDecayAdaption.java +++ b/src/eva2/server/go/operators/paramcontrol/ExponentialDecayAdaption.java @@ -10,14 +10,22 @@ import eva2.server.go.populations.Population; * @author mkron * */ -public class ExponentialDecayAdaption implements GenericParamAdaption, Serializable { - double startValue=0.2, halvingTimePerCent=50; - String target = "undefinedParameter"; +public class ExponentialDecayAdaption implements ParamAdaption, GenericParamAdaption, Serializable { + private double startValue=0.2, halvingTimePerCent=50; + private double saturation=0.; + private String target = "undefinedParameter"; public ExponentialDecayAdaption() { - startValue=0.2; - halvingTimePerCent=50; - target="undefinedParameter"; + } + + public ExponentialDecayAdaption(double startV, double halvingTimePC, String param) { + this(startV, halvingTimePC, 0., param); + } + public ExponentialDecayAdaption(double startV, double halvingTimePC, double offset, String param) { + this.setSaturation(offset); + startValue = startV; + halvingTimePerCent = halvingTimePC; + target = param; } public ExponentialDecayAdaption( @@ -25,6 +33,7 @@ public class ExponentialDecayAdaption implements GenericParamAdaption, Serializa startValue = o.startValue; halvingTimePerCent = o.halvingTimePerCent; target = o.target; + setSaturation(o.getSaturation()); } public Object clone() { @@ -32,9 +41,9 @@ public class ExponentialDecayAdaption implements GenericParamAdaption, Serializa } public Object calcValue(Object obj, Population pop, int iteration, int maxIteration) { - return startValue*Math.pow(0.5, (iteration/(double)maxIteration)*100/halvingTimePerCent); + return getSaturation()+(startValue-getSaturation())*Math.pow(0.5, (iteration/(double)maxIteration)*100/halvingTimePerCent); +// return startValue*Math.pow(0.5, (iteration/(double)maxIteration)*100/halvingTimePerCent); } - public String getControlledParam() { return target; } @@ -42,18 +51,22 @@ public class ExponentialDecayAdaption implements GenericParamAdaption, Serializa public double getStartValue() { return startValue; } - public void setStartValue(double startValue) { this.startValue = startValue; } + public String startValueTipText() { + return "The initial starting value at generation zero."; + } public double getHalvingTimePerCent() { return halvingTimePerCent; } - public void setHalvingTimePerCent(double halvingTimePerCent) { this.halvingTimePerCent = halvingTimePerCent; } + public String halvingTimePerCentTipText() { + return "The number of iterations (usually generations) within which the respecitve value will be halved."; + } public void setControlledParam(String target) { this.target = target; @@ -70,5 +83,23 @@ public class ExponentialDecayAdaption implements GenericParamAdaption, Serializa public void finish(Object obj, Population pop) {} public void init(Object obj, Population pop, Object[] initialValues) {} + + public static void main(String[] args) { + ExponentialDecayAdaption eda = new ExponentialDecayAdaption(1, 20, 0.05, ""); + int maxIt = 1000; + for (int i=0; igetStartV()) { // end value is larger + if (u listOfControllables( Object target) { - Pair propsNamesVals = BeanInspector.getPublicPropertiesOf(target, true); + Pair propsNamesVals = BeanInspector.getPublicPropertiesOf(target, true, true); ArrayList controllables = new ArrayList(); +// Object ownParamCtrl = BeanInspector.callIfAvailable(target, "getParameterControl", null); // if the target itself has a ParameterControlManager, add it to the list of controllables. +// if (ownParamCtrl!=null) controllables.add(ownParamCtrl); Object[] objs = propsNamesVals.tail; for (int i=0; i sin(-1+(t+1)^d)"; + } + + /** + * Calculate sub-linear t as -1+(t+1)^dampeningExp + * @param t + * @param dampeningExp + * @return + */ + private static double dampen(double t, double dampeningExp) { + return Math.pow(t+1, dampeningExp)-1; + } + + public Object clone() { + return new SinusoidalParamAdaption(this); + } + + public void finish(Object obj, Population pop) { + } + + public String getControlledParam() { + return paramName ; + } + + public void init(Object obj, Population pop, Object[] initialValues) { + } + public void setControlledParam(String prm) { + paramName = prm; + } + public String controlledParamTipText() { + return "The name of the generic parameter to be adapted."; + } + +// public ParameterControlManager getParamControl() { +// return paramControl; +// } +// public static void main(String[] args) { +// SinusoidalParamAdaption spa = new SinusoidalParamAdaption(1, 2, 100, 0, "asdf"); +// SinusoidalParamAdaption spa9 = new SinusoidalParamAdaption(spa); +// spa9.dampening=0.9; +// SinusoidalParamAdaption spa11 = new SinusoidalParamAdaption(spa); +// spa11.dampening=1.1; +// for (int i=0; i<1000; i++) { +// double t = i; +// System.out.println(t + " " + spa.calcValue(null, null, i, 1000) + " " + spa9.calcValue(null, null, i, 1000) + " " + spa11.calcValue(null, null, i, 1000)); +// } +// } + + public double getUpperBnd() { + return upperBnd; + } + public void setUpperBnd(double upperBnd) { + this.upperBnd = upperBnd; + updateMed(); + } + public void SetUpperBnd(double u) { + this.setUpperBnd(u); + } + public String upperBndTipText() { + return "The upper deviation of the oscillation."; + } + + public double getLowerBnd() { + return lowerBnd; + } + public void setLowerBnd(double lowerBnd) { + this.lowerBnd = lowerBnd; + updateMed(); + } + private void updateMed() { + medVal = 0.5*(upperBnd + lowerBnd); + } + + public String lowerBndTipText() { + return "The lower deviation of the oscillation."; + } + + public int getIterationPeriod() { + return iterationPeriod; + } + public void setIterationPeriod(int iterationPeriod) { + this.iterationPeriod = iterationPeriod; + } + public String iterationPeriodTipText() { + return "The period length of the oscillation, in iterations."; + } + + public int getInitialShift() { + return initialShift; + } + public void setInitialShift(int initialShift) { + this.initialShift = initialShift; + } + public String initialShiftTipText() { + return "The initial phase shift of the sinusoidal, in iterations."; + } + + public double getDampening() { + return dampening; + } + public void setDampening(double dampening) { + this.dampening = dampening; + } + public String dampeningTipText() { + return "Dampening exponent for frequency variation: values above 1 increase frequency with time, values below dampen it."; + } +// +// public void setBeatFreq(boolean beatFreq) { +// this.beatFreq = beatFreq; +// if (this.beatFreq) { +// paramControl.setSingleAdapters(new ParamAdaption[]{new SinusoidalParamAdaption(1000, 10000, 50000, 1000, "iterationPeriod")}); +// } else { +// paramControl.setSingleAdapters(null); +// } +// } +// +// public boolean isBeatFreq() { +// return beatFreq; +// } + +} diff --git a/src/eva2/server/go/operators/paramcontrol/SuccessBasedAdaption.java b/src/eva2/server/go/operators/paramcontrol/SuccessBasedAdaption.java new file mode 100644 index 00000000..98840333 --- /dev/null +++ b/src/eva2/server/go/operators/paramcontrol/SuccessBasedAdaption.java @@ -0,0 +1,102 @@ +package eva2.server.go.operators.paramcontrol; + +import java.io.Serializable; + +import eva2.server.go.populations.Population; +import eva2.server.go.populations.SolutionSet; +import eva2.server.go.strategies.InterfaceOptimizer; + +public class SuccessBasedAdaption implements ParamAdaption, InterfaceHasUpperDoubleBound, +GenericParamAdaption, Serializable { + private double fitThreshold; +// private double lastSuccRate=-1; + private int fitCrit=0; + private double targetRate = 0.75; + private String paramStr = "unnamedParameter"; + private double lowerBnd=0.1; + private double upperBnd=2; + private double curValue; + private double incFact = 1.05; + + public SuccessBasedAdaption() {} + + public SuccessBasedAdaption(double thresh, int crit, double rate) { + setFitThreshold(thresh); + fitCrit = crit; + targetRate = rate; + } + + public SuccessBasedAdaption(SuccessBasedAdaption successBasedAdaption) { + // TODO Auto-generated constructor stub + } + + public Object clone() { + return new SuccessBasedAdaption(this); + } + + public Object calcValue(Object obj, Population pop, int iteration, + int maxIteration) { + if (obj instanceof InterfaceOptimizer) { + SolutionSet sols = (SolutionSet) ((InterfaceOptimizer)obj).getAllSolutions(); + double curSuccRate = getSuccessRate(sols.getSolutions()); + if (curSuccRate