Whole new paramcontrol package

This commit is contained in:
Marcel Kronfeld 2011-05-03 12:34:33 +00:00
parent 0438ee5055
commit 7938b4e8ac
16 changed files with 992 additions and 21 deletions

View File

@ -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<vals.length; i++) {
// vals[i]=calcValueForParam(i, iteration, maxIteration);
// }
// return vals;
// }
// }
//
// /**
// * Perform the adaption calculation per parameter and type.
// *
// * @param i
// * @param iteration
// * @param maxIteration
// * @param paramOne
// * @param paramTwo
// * @return
// */
// private Object calcValueForParam(int i, int iteration, int maxIteration) {
// switch (getAdaptivityType(i)) {
// case linear:
// return Mathematics.linearInterpolation(iteration, 0, maxIteration, getAdaptionParameter(i, 0), getAdaptionParameter(i, 1));
// case halvingTime:
// return getAdaptionParameter(i, 0)*Math.pow(0.5, (iteration/(double)maxIteration)*100/getAdaptionParameter(i, 1));
// }
// System.err.println("Error, invalid adaptivity Type");
// return null;
// }
//
// /**
// * Each adaptivity type requires a number of parameters,
// * e.g. start and end value for linear adaption.
// *
// * @param i
// * @return
// */
// public abstract double getAdaptionParameter(int controlledIndex, int paramIndex);
//}

View File

@ -33,6 +33,9 @@ public abstract class AbstractLinearParamAdaption implements ParamAdaption, Seri
}
public abstract String getControlledParam();
public String controlledParamTipText() {
return "The name of the parameter to be controlled by this adaption scheme.";
}
public void init(Object obj, Population pop, Object[] initialValues) {
BeanInspector.setMem(obj, getControlledParam(), startV);
@ -42,18 +45,22 @@ public abstract class AbstractLinearParamAdaption implements ParamAdaption, Seri
public double getStartV() {
return startV;
}
public void setStartV(double startV) {
this.startV = startV;
}
public String startVTipText() {
return "The initial value.";
}
public double getEndV() {
return endV;
}
public void setEndV(double endV) {
this.endV = endV;
}
public String endVTipText() {
return "The final value.";
}
public String getName() {
return "Lin.adpt." + getControlledParam() + "(" + startV + "-" + endV + ")";

View File

@ -0,0 +1,11 @@
//package eva2.server.go.operators.paramcontrol;
//
///**
// * An enum defining possible adaption types.
// *
// * @author mkron
// *
// */
//public enum AdaptivityEnum {
// linear, halvingTime;
//}

View File

@ -0,0 +1,146 @@
package eva2.server.go.operators.paramcontrol;
import java.io.Serializable;
import eva2.server.go.populations.Population;
import eva2.server.go.strategies.CBNPSO;
/**
* We want to be better than a fitness threshold. We expect a change of a certain value increases
* the chance to be better than a fitness threshold.
*
* @author mkron
*
*/
public class CbpsoFitnessThresholdBasedAdaption implements ParamAdaption, GenericParamAdaption, Serializable {
private double initialVal=10000, lowerBnd = 1000, upperBnd=15000;
private double currentVal=initialVal;
private double incFact=1.2;
private double decFact=1./incFact;
private int adptIntervalGenerations = 10;
private int lastAdaption = -1;
private String paramName = "sigmaAdaptionPeriod";
private double minInterestingRatio = 0.5;
private double maxInterestingRatio = 0.8;
public CbpsoFitnessThresholdBasedAdaption() {}
public CbpsoFitnessThresholdBasedAdaption(int initialV, int minV, int maxV, double incFact, int generationInterval, double minIntRatio, double maxIntRatio) {
initialVal = initialV;
lowerBnd = minV;
upperBnd = maxV;
currentVal = initialVal;
this.incFact = incFact;
decFact = 1./incFact;
adptIntervalGenerations = generationInterval;
lastAdaption = -1;
minInterestingRatio = minIntRatio;
maxInterestingRatio = maxIntRatio;
}
public CbpsoFitnessThresholdBasedAdaption(CbpsoFitnessThresholdBasedAdaption o) {
initialVal = o.initialVal;
lowerBnd = o.lowerBnd;
upperBnd = o.upperBnd;
currentVal = o.currentVal;
incFact = o.incFact;
decFact = o.decFact;
paramName = o.paramName;
adptIntervalGenerations = o.adptIntervalGenerations;
lastAdaption = o.lastAdaption;
minInterestingRatio = o.minInterestingRatio;
maxInterestingRatio = o.maxInterestingRatio;
}
@Override
public Object clone() {
return new CbpsoFitnessThresholdBasedAdaption(this);
}
@Override
public Object calcValue(Object obj, Population pop, int iteration,
int maxIteration) {
if (obj instanceof CBNPSO) {
CBNPSO cbpso = (CBNPSO)obj;
checkForAdaption(cbpso, pop, iteration, maxIteration);
} else {
System.err.println("Invalid object!");
}
// System.out.println("current val is " + currentVal);
return currentVal;
}
private void checkForAdaption(CBNPSO cbpso, Population pop,
int iteration, int maxIteration) {
// How to find out if we are in need of improvement?
double oldVal = currentVal;
if (isPossibleAdaptionTime(pop)) {
double interestingRatio = cbpso.getInterestingSolutionRatio();
if (interestingRatio >= 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;
}
}

View File

@ -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<Boolean> lastBestSatisfactionState = new LinkedList<Boolean>();
// 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<minPenalty) {
currentFactor = minPenalty/initialPenalty;
curPen=minPenalty;
} else 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";
}
}

View File

@ -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;
@ -71,4 +84,22 @@ public class ExponentialDecayAdaption implements GenericParamAdaption, Serializa
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; i<maxIt; i+=10) {
System.out.println(i + " " + eda.calcValue(null, null, i, maxIt));
}
}
public void setSaturation(double saturation) {
this.saturation = saturation;
}
public double getSaturation() {
return saturation;
}
public String saturationTipText() {
return "Saturation value of the value (y-offset of the exponential).";
}
}

View File

@ -0,0 +1,13 @@
package eva2.server.go.operators.paramcontrol;
/**
* Interface for an instance which has a real valued upper bound of some kind which
* can be mutated.
*
* @author mkron
*
*/
public interface InterfaceHasUpperDoubleBound {
public double getUpperBnd();
public void SetUpperBnd(double u);
}

View File

@ -0,0 +1,13 @@
package eva2.server.go.operators.paramcontrol;
/**
* An object which may be "controlled" dynamically using a String for access.
* @author mkron
*
*/
public interface InterfaceParamControllable {
public void notifyParamChanged(String member, Object oldVal, Object newVal);
public Object[] getParamControl();
public void addChangeListener(ParamChangeListener l);
public void removeChangeListener(ParamChangeListener l);
}

View File

@ -10,7 +10,8 @@ import eva2.tools.math.Mathematics;
* @author mkron
*
*/
public class LinearParamAdaption extends AbstractLinearParamAdaption implements GenericParamAdaption, Serializable {
public class LinearParamAdaption extends AbstractLinearParamAdaption
implements InterfaceHasUpperDoubleBound, GenericParamAdaption, Serializable {
String target = "undefinedParameter";
public LinearParamAdaption() {
@ -35,7 +36,6 @@ public class LinearParamAdaption extends AbstractLinearParamAdaption implements
public String getControlledParam() {
return target;
}
public void setControlledParam(String target) {
this.target = target;
}
@ -43,4 +43,36 @@ public class LinearParamAdaption extends AbstractLinearParamAdaption implements
public static String globalInfo() {
return "Simple linear parameter adaption.";
}
public String[] customPropertyOrder() {
return new String[] {"startV", "endV"};
}
/**
* Return the larger value of the start and end value.
*
* @return
*/
public double getUpperBnd() {
return Math.max(getEndV(), getStartV());
}
/**
* Set the larger one of start- or end-value to the given value. If they are
* equal, both are set.
*
* @param u
*/
public void SetUpperBnd(double u) {
if (getEndV()==getStartV()) {
setEndV(u);
setStartV(u);
} else if (getEndV()>getStartV()) { // end value is larger
if (u<getStartV()) System.err.println("Warning, changing direction of linear adaption!");
setEndV(u);
} else { // start value is larger
if (u<getEndV()) System.err.println("Warning, changing direction of linear adaption!");
setStartV(u);
}
}
}

View File

@ -26,9 +26,10 @@ public class PSOActivityFeedbackControl implements ParamAdaption, Serializable {
private double minInert=0.5;
private double maxInert=1;
private double startAct=0.17;
private double endAct=0;
private double endAct=0.01;
private double deltaInertness = 0.1;
private static boolean TRACE=false;
private boolean exponentialSchedule = true;
private static String target = "inertnessOrChi";
@ -76,7 +77,8 @@ public class PSOActivityFeedbackControl implements ParamAdaption, Serializable {
}
private double desiredActivity(int iteration, int maxIteration) {
return Mathematics.linearInterpolation(iteration, 0, maxIteration, startAct, endAct);
if (exponentialSchedule) return startAct*Math.pow(endAct/startAct, iteration/(double)maxIteration);
else return Mathematics.linearInterpolation(iteration, 0, maxIteration, startAct, endAct);
}
private double calculateActivity(ParticleSwarmOptimization pso) {
@ -118,6 +120,7 @@ public class PSOActivityFeedbackControl implements ParamAdaption, Serializable {
}
public void setFinalActivity(double endAct) {
this.endAct = endAct;
if (endAct==0 && isExponentialSchedule()) System.err.println("Warning: zero final activity will not work with exponential schedule, set it to small epsilon!");
}
public String finalActivityTipText() {
return "The final target activity (relative to the range), should be close to zero.";
@ -140,4 +143,17 @@ public class PSOActivityFeedbackControl implements ParamAdaption, Serializable {
public void finish(Object obj, Population pop) {}
public void init(Object obj, Population pop, Object[] initialValues) {}
public boolean isExponentialSchedule() {
return exponentialSchedule;
}
public void setExponentialSchedule(boolean exponentialSchedule) {
this.exponentialSchedule = exponentialSchedule;
if (getFinalActivity()==0) System.err.println("Warning: zero final activity will not work with exponential schedule, set it to small epsilon!");
}
public String exponentialScheduleTipText() {
return "Use linear or exponential activity decrease schedule.";
}
}

View File

@ -16,7 +16,7 @@ public interface ParamAdaption {
/**
* Perform the adaption.
*
* @param iteration
* @param iteration iteration count at the time of the call, evaluations or generations, depending on the terminator
* @param maxIteration
* @return
*/

View File

@ -0,0 +1,5 @@
package eva2.server.go.operators.paramcontrol;
public interface ParamChangeListener {
public void notifyChange(InterfaceParamControllable controllable, Object oldVal, Object newVal, String msg);
}

View File

@ -2,6 +2,7 @@ package eva2.server.go.operators.paramcontrol;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import eva2.gui.BeanInspector;
@ -61,6 +62,18 @@ public class ParameterControlManager implements InterfaceParameterControl, Seria
}
for (ParamAdaption prm : singleAdapters) {
prm.init(obj, initialPop, initialValues);
// check if the prm itself has a ParameterControlManager:
tryRecursive(prm, "init", new Object[]{initialPop});
}
}
protected void tryRecursive(ParamAdaption prm, String method, Object[] args) {
Object subManager=null;
if ((subManager=BeanInspector.callIfAvailable(prm, "getParamControl", null))!=null) {
if (subManager instanceof ParameterControlManager) {
BeanInspector.callIfAvailable(subManager, method, args);
// ((ParameterControlManager)subManager).init(prm, initialPop);
}
}
}
@ -68,6 +81,7 @@ public class ParameterControlManager implements InterfaceParameterControl, Seria
String[] params = getControlledParameters();
for (ParamAdaption prm : singleAdapters) {
prm.finish(obj, finalPop);
tryRecursive(prm, "finish", new Object[]{finalPop});
}
if (params != null) {
for (int i=0; i<params.length; i++) BeanInspector.setMem(obj, params[i], initialValues[i]);
@ -90,6 +104,11 @@ public class ParameterControlManager implements InterfaceParameterControl, Seria
// }
}
}
Object[] args = new Object[] {null, pop, iteration, maxIteration};
for (ParamAdaption prm: singleAdapters) {
args[0]=prm;
tryRecursive(prm, "updateParameters", args);
}
}
public void updateParameters(Object obj) {
@ -139,6 +158,21 @@ public class ParameterControlManager implements InterfaceParameterControl, Seria
this.singleAdapters = singleAdapters;
}
/**
* Add a single ParamAdaption instance to the manager.
*
* @param pa
*/
public void addSingleAdapter(ParamAdaption pa) {
if (singleAdapters==null) setSingleAdapters(new ParamAdaption[]{pa});
else {
ParamAdaption[] newP = new ParamAdaption[singleAdapters.length+1];
for (int i=0; i<singleAdapters.length; i++) newP[i]=singleAdapters[i];
newP[newP.length-1] = pa;
setSingleAdapters(newP);
}
}
public static String globalInfo() {
return "Define a list of dynamically adapted parameters.";
}
@ -155,10 +189,12 @@ public class ParameterControlManager implements InterfaceParameterControl, Seria
* @param target
* @return
*/
public static Object[] arrayOfControllables(
public static List<Object> listOfControllables(
Object target) {
Pair<String[],Object[]> propsNamesVals = BeanInspector.getPublicPropertiesOf(target, true);
Pair<String[],Object[]> propsNamesVals = BeanInspector.getPublicPropertiesOf(target, true, true);
ArrayList<Object> controllables = new ArrayList<Object>();
// 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<objs.length; i++) {
if (objs[i]!=null) {
@ -166,6 +202,6 @@ public class ParameterControlManager implements InterfaceParameterControl, Seria
if (BeanInspector.hasMethod(objs[i], "getParamControl", null)!=null) controllables.add(objs[i]);
}
}
return controllables.toArray(new Object[controllables.size()]);
return controllables;
}
}

View File

@ -0,0 +1,97 @@
//package eva2.server.go.operators.paramcontrol;
//
//import java.io.Serializable;
//
//import eva2.tools.Mathematics;
//
///**
// * Adapt an instance parameter by time, from given start to end value.
// * This only works if iterations are known. The new variant allows exponential adaption,
// * where the second parameter (endV) is interpreted as halfing time in percent of the
// * full run.
// *
// * @author mkron
// *
// */
//public class SingleParamAdaption extends AbstractAdaptiveParameters implements Serializable {
// protected String[] params = null;
// private double startV;
// private double endV;
// private AdaptivityEnum adpType = AdaptivityEnum.linear;
// public static boolean hideFromGOE = true;
//
// public SingleParamAdaption(String paramName, double startValue, double endValue) {
// super();
// params = new String[]{paramName};
// startV=startValue;
// endV=endValue;
// }
//
// public SingleParamAdaption(SingleParamAdaption o) {
// super(o);
// startV=o.startV;
// endV=o.endV;
// adpType=o.adpType;
// params=o.params.clone();
// }
//
// @Override
// public Object clone() {
// return new SingleParamAdaption(this);
// }
//
// public String[] getControlledParameters() {
// return params;
// }
//
// public String startValTipText() {
// return "Start value for the parameter";
// }
//
// public String endValTipText() {
// return "End value for the parameter";
// }
//
// @Override
// protected AdaptivityEnum getAdaptivityType(int p) {
// return adpType;
// }
//
// public double getStartV() {
// return startV;
// }
//
// public void setStartV(double startV) {
// this.startV = startV;
// }
//
// public double getEndV() {
// return endV;
// }
//
// public void setEndV(double endV) {
// this.endV = endV;
// }
//
// public AdaptivityEnum getAdpType() {
// return adpType;
// }
//
// public void setAdpType(AdaptivityEnum adpType) {
// this.adpType = adpType;
// }
//
// public String adpTypeTipText() {
// return "Select type of adaption.";
// }
//
// public static String globalInfo() {
// return "A single parameter may be adapted using linear interpolation or exponential decrease.";
// }
//
// @Override
// public double getAdaptionParameter(int controlledIndex, int paramIndex) {
// if (paramIndex==0) return startV;
// else return endV;
// }
//}

View File

@ -0,0 +1,198 @@
package eva2.server.go.operators.paramcontrol;
import java.io.Serializable;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.AbstractProblemDouble;
/**
* A sinusoidal adaption scheme which can be dampened. The value oscillates between a lower and an upper
* value with a given iteration period. The dampening is integrated as a sub-linear reduction of the
* frequency, turning sin(t) into sin(((t+1)^d)-1) which is linear for d=1. For slightly smaller values,
* the frequency slowly decreases, while for slightly larger values, it slowly increases.
*
* @author mkron
*
*/
public class SinusoidalParamAdaption implements InterfaceHasUpperDoubleBound, ParamAdaption, GenericParamAdaption, Serializable {
private double upperBnd=1;
private double lowerBnd=0;
private int iterationPeriod=1000;
private int initialShift=0;
// protected ParameterControlManager paramControl = new ParameterControlManager();
private boolean beatFreq = false;
private double medVal=0;
private String paramName = "unknownParam";
private double dampening = 1.;
public SinusoidalParamAdaption() {
updateMed();
}
public SinusoidalParamAdaption(double lower, double upper, double dampening, int period, int start, String param) {
upperBnd = upper;
lowerBnd = lower;
iterationPeriod = period;
initialShift = start;
paramName = param;
this.dampening = dampening;
updateMed();
}
public SinusoidalParamAdaption(double lower, double upper, int period, int start, String param) {
this(lower, upper, 1., period, start, param);
}
public SinusoidalParamAdaption(SinusoidalParamAdaption o) {
this.upperBnd=o.upperBnd;
this.lowerBnd=o.lowerBnd;
this.iterationPeriod = o.iterationPeriod;
this.initialShift = o.initialShift;
this.medVal = o.medVal;
this.paramName = o.paramName;
this.dampening = o.dampening;
updateMed();
}
public Object calcValue(Object obj, Population pop, int iteration, int maxIteration) {
double res=0;
double t = (2*Math.PI/iterationPeriod)*(iteration-initialShift);
if (dampening!=1) {
t = SinusoidalParamAdaption.dampen(t, dampening);
}
res = medVal + (upperBnd-lowerBnd) * 0.5* Math.sin(t);
// System.out.println("In " + this + " at " + iteration + ": " + res);
return res;
}
public String getName() {
return "SinAdapt("+getControlledParam()+"_"+lowerBnd+"_"+upperBnd+"_"+iterationPeriod+((dampening!=1) ? ("_dmp-"+dampening):"")+")";
}
public String globalInfo() {
return "Sinusoidally oscillating value, the frequency may be varyied with time. E.g. use dampening 0.9 " +
"for a slightly decreasing frequency, dampening 1.1 for a slight increase. The frequency is modified " +
"in the form sin(t) -> 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;
// }
}

View File

@ -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<targetRate) decrease(); // higher exploitation
else increase(); // higher exploration
System.out.println("Succ rate is " + curSuccRate + ", setting val " + curValue);
return curValue;
} else {
System.err.println("Unknown object to be controlled by " + this.getClass().getName());
return null;
}
}
private void increase() {
curValue = Math.min(upperBnd, incFact*curValue);
}
private void decrease() {
curValue = Math.max(lowerBnd, (1./incFact)*curValue);
}
/**
* The success rate of the given population considering the
* fitness threshold defined in this instance.
*
* @param solutions
* @return
*/
private double getSuccessRate(Population solutions) {
int numSucc = solutions.filterByFitness(getFitThreshold(), fitCrit).size();
return ((double)numSucc)/solutions.size();
}
public void finish(Object obj, Population pop) {}
public String getControlledParam() {
return paramStr;
}
public void init(Object obj, Population pop, Object[] initialValues) {
curValue = 0.5*(upperBnd+lowerBnd);
}
public void setControlledParam(String prm) {
paramStr = prm;
}
public void SetUpperBnd(double u) {
upperBnd = u;
}
public double getUpperBnd() {
return upperBnd;
}
public void setFitThreshold(double fitThreshold) {
this.fitThreshold = fitThreshold;
}
public double getFitThreshold() {
return fitThreshold;
}
}