Changes from MK rev. 255, update to ParticleFilter, and tool tips dont break at points.

This commit is contained in:
Marcel Kronfeld 2009-03-18 11:10:02 +00:00
parent 6592ed69f2
commit 49f893e899
5 changed files with 448 additions and 19 deletions

View File

@ -36,7 +36,6 @@ import java.beans.PropertyVetoException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
@ -45,6 +44,7 @@ import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import eva2.gui.GenericObjectEditor.GOEPanel;
import eva2.tools.EVAHELP;
import eva2.tools.StringTools;
/*==========================================================================*
@ -91,6 +91,9 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
private PropertyChangeSupport m_support = new PropertyChangeSupport(this);
/** set true to use the GOE by default if no other editor is registered **/
// If true, tool tips are used up to the first point only.
boolean stripToolTipToFirstPoint=false;
/** Creates the property sheet panel.
*/
public PropertySheetPanel() {
@ -105,6 +108,9 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
*/
public void propertyChange(PropertyChangeEvent evt) {
if (TRACE) System.out.println("PropertySheetPanel.propertyChange() "+m_Target.getClass()+": calling wasModified");
// GOEPanel gp=(GOEPanel)this.getParent();
// gp.validateTarget(this); // Once trying to find an irreproducible bug
wasModified(evt); // Let our panel update before guys downstream
m_support.removePropertyChangeListener(this);
m_support.firePropertyChange("", null, m_Target);
@ -841,9 +847,11 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
try {
Object args[] = { };
String tempTip = (String)(meth.invoke(target, args));
int ci = tempTip.indexOf('.');
if (ci < 0) result = tempTip;
else result = tempTip.substring(0, ci);
result = tempTip;
if (stripToolTipToFirstPoint) {
int ci = tempTip.indexOf('.');
if (ci > 0) result = tempTip.substring(0, ci);
}
} catch (Exception ex) {
}
break;

View File

@ -0,0 +1,51 @@
package eva2.server.go.operators.distancemetric;
import eva2.server.go.individuals.AbstractEAIndividual;
/**
* The Euclidean metric just measures the Euclidean distance based on the default double representation
* as given by AbstractEAIndividual.getDoublePosition(AbstractEAIndividual).
*
* @see AbstractEAIndividual.getDoublePosition(AbstractEAIndividual)
* @author mkron
*
*/
public class EuclideanMetric implements InterfaceDistanceMetric {
public Object clone() {
return (Object) new EuclideanMetric(this);
}
public EuclideanMetric(EuclideanMetric a) {
}
public EuclideanMetric() {
}
public double distance(AbstractEAIndividual indy1, AbstractEAIndividual indy2) {
double[] dIndy1, dIndy2;
double result = 0;
dIndy1 = AbstractEAIndividual.getDoublePosition(indy1);
dIndy2 = AbstractEAIndividual.getDoublePosition(indy2);
for (int i = 0; (i < dIndy1.length) && (i < dIndy2.length); i++) {
result += Math.pow((dIndy1[i] - dIndy2[i]), 2);
}
return Math.sqrt(result);
}
/** This method returns a global info string
* @return description
*/
public String globalInfo() {
return "The euclidean metric calculates euclidian distances for individuals which have a real valued interpretation.";
}
/** This method will return a naming String
* @return The name of the algorithm
*/
public String getName() {
return "Euclidean Metric";
}
}

View File

@ -0,0 +1,259 @@
package eva2.server.go.operators.mutation;
import java.util.ArrayList;
import eva2.gui.BeanInspector;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceESIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceOptimizationProblem;
import wsi.ra.math.RNG;
import eva2.tools.Mathematics;
import eva2.tools.SelectedTag;
/**
* The correlated vector mutations stores a "velocity" vector for each individual,
* updates the velocity by rotation and scaling, and then mutates the individual
* by adding the velocity. This was used for a particle filter localization problem
* and is less useful in general.
*
* Rotation vectors are normal distributed with mean zero, scaling factors are
* log-normally distributed around mean 1. This means that the averaged expected change
* of the mutation vector is zero. The smaller the deviations, the higher the correlations
* between successive mutation steps.
*/
public class MutateESCorrVector implements InterfaceMutation, java.io.Serializable {
protected double m_scalingDev = 0.05;
protected double m_initialVelocity = 0.02;
protected double m_LowerLimitStepSize = 0.0000001;
protected double m_UpperLimitStepSize = 0.5;
protected double m_rotationDev = 15.;
protected boolean m_checkConstraints = true;
public static final String vectorKey = "MutateESCorrVectorVector";
public static final boolean TRACE = false;
public MutateESCorrVector() {
}
public MutateESCorrVector(double scalingDev) {
setScalingDev(scalingDev);
}
public MutateESCorrVector(double scalingDev, double initialVelocity) {
setScalingDev(scalingDev);
setInitialVelocity(initialVelocity);
}
public MutateESCorrVector(double scalingDev, double initialVelocity, double rotDev) {
setScalingDev(scalingDev);
setInitialVelocity(initialVelocity);
setRotationDev(rotDev);
}
public MutateESCorrVector(MutateESCorrVector mutator) {
this.m_scalingDev = mutator.m_scalingDev;
this.m_initialVelocity = mutator.m_initialVelocity;
this.m_LowerLimitStepSize = mutator.m_LowerLimitStepSize;
this.m_rotationDev = mutator.m_rotationDev;
}
/** This method will enable you to clone a given mutation operator
* @return The clone
*/
public Object clone() {
return new MutateESCorrVector(this);
}
/** This method allows you to evaluate wether two mutation operators
* are actually the same.
* @param mutator The other mutation operator
*/
public boolean equals(Object mutator) {
if (mutator instanceof MutateESCorrVector) {
MutateESCorrVector mut = (MutateESCorrVector)mutator;
if (this.m_scalingDev != mut.m_scalingDev) return false;
if (this.m_initialVelocity != m_initialVelocity) return false;
if (this.m_LowerLimitStepSize != mut.m_LowerLimitStepSize) return false;
return true;
} else return false;
}
/** This method allows you to init the mutation operator
* @param individual The individual that will be mutated.
* @param opt The optimization problem.
*/
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt) {
double[] initVelocity = calcInitialVel(m_initialVelocity, ((InterfaceESIndividual)individual).getDoubleRange());
individual.putData(vectorKey, initVelocity);
}
/**
* Create a random vector of length relative to the given range given by the velocity parameter.
*
* @param velocity
* @param doubleRange
* @return
*/
private double[] calcInitialVel(double velocity, double[][] doubleRange) {
double[] initVelocity = Mathematics.randomVector(doubleRange.length, 1.0);
double nrm=Mathematics.norm(initVelocity);
double[] shiftedRange=Mathematics.shiftRange(doubleRange);
// normalize to speed
Mathematics.svMult(velocity/nrm, initVelocity, initVelocity);
// and scale by ranges
Mathematics.vvMultCw(shiftedRange, initVelocity, initVelocity);
// System.out.println(Mathematics.getRelativeLength(initVelocity, doubleRange));
return initVelocity;
}
/** This method will mutate a given AbstractEAIndividual. If the individual
* doesn't implement InterfaceESIndividual nothing happens.
* @param individual The individual that is to be mutated
*/
public void mutate(AbstractEAIndividual individual) {
// if (TRACE) System.out.println("Before Mutate: " + AbstractEAIndividual.getDefaultDataString(individual));
if (individual instanceof InterfaceESIndividual) {
double[] genes = ((InterfaceESIndividual)individual).getDGenotype();
double[][] range = ((InterfaceESIndividual)individual).getDoubleRange();
double[] vel = (double[])individual.getData(vectorKey);
// mutate the velocity vector and write it back
if ((m_scalingDev > 0) || (m_rotationDev > 0)) {
// for (int i = 0; i < vel.length; i++) {
// vel[i] += ((range[i][1] -range[i][0])/2)*RNG.gaussianDouble(this.m_MutationStepSize);
// }
double rotateRad = m_rotationDev*(Math.PI/360.)*RNG.gaussianDouble(1.);
// rotate with a gaussian distribution of deviation rotationDeg
Mathematics.rotateAllAxes(vel, rotateRad, false); // rotate
double rScale=Math.exp(RNG.gaussianDouble(m_scalingDev));
if ((m_LowerLimitStepSize > 0) || (m_UpperLimitStepSize > 0) ) {
double stepLen=Mathematics.norm(vel);
if (m_LowerLimitStepSize > 0) rScale=Math.max(rScale, m_LowerLimitStepSize/stepLen);
if (m_UpperLimitStepSize > 0) rScale=Math.min(rScale, m_UpperLimitStepSize/stepLen);
}
Mathematics.svMult(rScale, vel, vel); // mutate speed
individual.putData(vectorKey, vel);
if (TRACE) System.out.println("rotated by " + rotateRad + ", scaled by " + rScale);
if (TRACE) System.out.println("-- dir is " + BeanInspector.toString(vel));
}
// add velocity to the individual
Mathematics.vvAdd(genes, vel, genes);
// check the range
if (m_checkConstraints) Mathematics.projectToRange(genes, range);
// write genotype back
((InterfaceESIndividual)individual).SetDGenotype(genes);
}
// if (TRACE) System.out.println("After Mutate: " + AbstractEAIndividual.getDefaultDataString(individual));
}
/** This method allows you to perform either crossover on the strategy parameters
* or to deal in some other way with the crossover event.
* @param indy1 The original mother
* @param partners The original partners
*/
public void crossoverOnStrategyParameters(AbstractEAIndividual indy1, Population partners) {
ArrayList<Double> tmpList = new ArrayList<Double>();
if (indy1.getMutationOperator() instanceof MutateESCorrVector) tmpList.add(new Double(((MutateESCorrVector)indy1.getMutationOperator()).m_scalingDev));
for (int i = 0; i < partners.size(); i++) {
if (((AbstractEAIndividual)partners.get(i)).getMutationOperator() instanceof MutateESCorrVector) tmpList.add(new Double(((MutateESCorrVector)((AbstractEAIndividual)partners.get(i)).getMutationOperator()).m_scalingDev));
}
double[] list = new double[tmpList.size()];
for (int i = 0; i < tmpList.size(); i++) list[i] = ((Double)tmpList.get(i)).doubleValue();
if (list.length <= 1) return;
// discreete mutation for step size
this.m_scalingDev = list[RNG.randomInt(0, list.length-1)];
}
/** This method allows you to get a string representation of the mutation
* operator
* @return A descriptive string.
*/
public String getStringRepresentation() {
return "ES global mutation";
}
/**********************************************************************************************************************
* These are for GUI
*/
/** This method allows the CommonJavaObjectEditorPanel to read the
* name to the current object.
* @return The name.
*/
public String getName() {
return "ES correlated vector mutation";
}
/** This method returns a global info string
* @return description
*/
public String globalInfo() {
return "The correlated vector mutation stores a specific mutation vector per individual.";
}
/** Set the initial mutation step size with this method.
* @param d The mutation operator.
*/
public void setScalingDev(double d) {
this.m_scalingDev = d;
}
public double getScalingDev() {
return this.m_scalingDev;
}
public String scalingDevTipText() {
return "Choose the devation of lognormal vector scaling.";
}
/** Set the lower limit for the mutation step size with this method.
* @param d The mutation operator.
*/
public void setLowerLimitStepSize(double d) {
if (d < 0) d = 0;
this.m_LowerLimitStepSize = d;
}
public double getLowerLimitStepSize() {
return this.m_LowerLimitStepSize;
}
public String lowerLimitStepSizeTipText() {
return "Set the lower limit for the mutation step.";
}
public double getRotationDev() {
return m_rotationDev;
}
public void setRotationDev(double rotationDeg) {
this.m_rotationDev = rotationDeg;
}
public String rotationDevTipText() {
return "Std deviation of the rotation angle distribution";
}
public double getInitialVelocity() {
return m_initialVelocity;
}
public void setInitialVelocity(double velocity) {
m_initialVelocity = velocity;
}
public double getUpperLimitStepSize() {
return m_UpperLimitStepSize;
}
public void setUpperLimitStepSize(double upperLimitStepSize) {
m_UpperLimitStepSize = upperLimitStepSize;
}
public String upperLimitStepSizeTipText() {
return "Set the upper limit for the mutation step.";
}
}

View File

@ -4,6 +4,7 @@ import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.operators.selection.probability.InterfaceSelectionProbability;
import eva2.server.go.operators.selection.probability.SelProbBoltzman;
import eva2.server.go.operators.selection.probability.SelProbStandard;
import eva2.server.go.operators.selection.probability.SelProbStandardScaling;
import eva2.server.go.populations.Population;
import wsi.ra.math.RNG;
@ -29,6 +30,14 @@ public class SelectParticleWheel implements InterfaceSelection, java.io.Serializ
public SelectParticleWheel() {
}
public SelectParticleWheel(double scalingProb) {
m_SelProbCalculator = new SelProbStandardScaling(scalingProb);
}
public SelectParticleWheel(InterfaceSelectionProbability selProb) {
m_SelProbCalculator = selProb;
}
public SelectParticleWheel(SelectParticleWheel a) {
this.m_SelProbCalculator = (InterfaceSelectionProbability)a.m_SelProbCalculator.clone();

View File

@ -1,11 +1,14 @@
package eva2.server.go.strategies;
import eva2.gui.BeanInspector;
import eva2.gui.GenericObjectEditor;
import eva2.gui.Plot;
import eva2.server.go.InterfacePopulationChangedEventListener;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.individuals.InterfaceDataTypeDouble;
import eva2.server.go.individuals.InterfaceESIndividual;
import eva2.server.go.operators.distancemetric.EuclideanMetric;
import eva2.server.go.operators.mutation.MutateESCorrVector;
import eva2.server.go.operators.mutation.MutateESFixedStepSize;
import eva2.server.go.operators.selection.InterfaceSelection;
import eva2.server.go.operators.selection.SelectParticleWheel;
@ -16,7 +19,8 @@ import eva2.server.go.problems.AbstractOptimizationProblem;
import eva2.server.go.problems.F1Problem;
import eva2.server.go.problems.InterfaceOptimizationProblem;
/** This is a Particle Filter implemented by Frank Senke, only some documentation
/**
* This is a Particle Filter implemented by Frank Senke, only some documentation
* here and not completely checked whether this works on arbitrary problem
* instances. MK did some adaptations, this should work on real valued problems now.
*
@ -37,23 +41,37 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
private static final long serialVersionUID = 1L;
private Population m_Population = new Population();
private InterfaceOptimizationProblem m_Problem = new F1Problem();
private InterfaceSelection m_ParentSelection = new SelectParticleWheel();
private InterfaceSelection m_ParentSelection = new SelectParticleWheel(0.5);
//private boolean m_UseElitism = true;
private String m_Identifier = "";
private boolean withShow = false;
private double mutationSigma = 0.05;
private double mutationSigma = 0.01;
private double randomImmigrationQuota = 0.05;
private double initialVelocity = 0.02;
private double rotationDeg = 20.;
private int popSize = 300;
private int sleepTime = 0;
transient private int indCount = 0;
transient private InterfacePopulationChangedEventListener m_Listener;
transient Plot myPlot = null;
public static final boolean TRACE = false;
public ParticleFilterOptimization() {
if (withShow) setWithShow(true);
}
public ParticleFilterOptimization(double vInit, double mute, double immiQuote, double rotDeg, double selScaling) {
mutationSigma = mute;
initialVelocity = vInit;
randomImmigrationQuota = immiQuote;
rotationDeg = rotDeg;
m_ParentSelection = new SelectParticleWheel(selScaling);
if (withShow) setWithShow(true);
}
public ParticleFilterOptimization(ParticleFilterOptimization a) {
this.m_Population = (Population)a.m_Population.clone();
this.m_Problem = (InterfaceOptimizationProblem)a.m_Problem.clone();
@ -65,19 +83,28 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
if (a.withShow) setWithShow(true);
}
public void hideHideable() {
GenericObjectEditor.setHideProperty(this.getClass(), "population", true);
}
public Object clone() {
return (Object) new ParticleFilterOptimization(this);
}
public void init() {
this.m_Problem.initPopulation(this.m_Population);
//System.out.println("popsize is " + m_Population.size());
//System.out.println("pops targ is " + m_Population.getPopulationSize());
for (int i=0; i<m_Population.size(); i++) {
((AbstractEAIndividual)m_Population.getIndividual(i)).setMutationOperator(new MutateESFixedStepSize(mutationSigma));
}
if (initialVelocity <= 0.) {
(((AbstractOptimizationProblem)m_Problem).getIndividualTemplate()).setMutationOperator(new MutateESFixedStepSize(mutationSigma));
} else {
(((AbstractOptimizationProblem)m_Problem).getIndividualTemplate()).setMutationOperator(new MutateESCorrVector(mutationSigma, initialVelocity, rotationDeg));
}
m_Population.setPopSize(popSize);
this.m_Problem.initPopulation(this.m_Population);
setWithShow(withShow);
this.evaluatePopulation(this.m_Population);
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
}
@ -111,12 +138,37 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
*/
protected Population resample(Population pop) {
Population parents;
boolean doImmigr=false;
this.m_ParentSelection.prepareSelection(pop);
// Generate a Population of Parents with Parantselectionmethod.
// DONT forget cloning -> selection does only shallow copies!
parents = (Population)(this.m_ParentSelection.selectFrom(pop, this.m_Population.getPopulationSize())).clone();
int targetSize = this.m_Population.getPopulationSize();
if (randomImmigrationQuota>0) {
if (randomImmigrationQuota>1.) System.err.println("Error, invalid immigration quota!");
else {
targetSize = (int)(this.m_Population.getPopulationSize() * (1.-randomImmigrationQuota));
targetSize = Math.max(1, targetSize); // guarantee at least one to be selected
if (targetSize < this.m_Population.getPopulationSize()) doImmigr=true;
}
}
parents = (Population)(this.m_ParentSelection.selectFrom(pop, targetSize)).clone();
if (doImmigr) {
// add immigrants
AbstractEAIndividual immi;
int i;
for (i=0; (i+parents.getPopulationSize())<pop.getPopulationSize(); i++) {
immi = (AbstractEAIndividual)pop.getEAIndividual(0).clone();
immi.init(getProblem());
parents.add(immi);
}
parents.synchSize();
if (TRACE) System.out.println("Added " + i + " random individuals");
}
parents.SetFunctionCalls(pop.getFunctionCalls());
parents.setGenerationTo(pop.getGeneration());
@ -146,7 +198,12 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
if (useCircles) myPlot.getFunctionArea().drawCircle("", curPosition, graphLabel);
else myPlot.setUnconnectedPoint(curPosition[0], curPosition[1], graphLabel);
// myPlot.setConnectedPoint(curPosition[0], curPosition[1], graphLabel);
// if ( !useCircles && (pop.getEAIndividual(i).hasData(MutateESCorrVector.vectorKey))) {
// double[] v=(double[])pop.getEAIndividual(i).getData(MutateESCorrVector.vectorKey);
// myPlot.setConnectedPoint(curPosition[0], curPosition[1], graphLabel+5);
// curPosition=Mathematics.vvAdd(v, curPosition);
// myPlot.setConnectedPoint(curPosition[0], curPosition[1], graphLabel+5);
// }
}
}
}
@ -154,7 +211,7 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
protected void applyMotionModel(AbstractEAIndividual indy, double noise) {
// this currently only performs a mutation
indy.mutate();
indy.SetFitness(0, 0);
indy.resetFitness(0);
}
/**
@ -173,6 +230,7 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
// predict step
predict(nextGeneration);
if (TRACE) System.out.println("Speed is " + BeanInspector.toString(ParticleSwarmOptimization.getPopulationVelSpeed(m_Population, 3, MutateESCorrVector.vectorKey, null, null)) + " popM " + BeanInspector.toString(m_Population.getPopulationMeasures(new EuclideanMetric())));
m_Population = evaluatePopulation(nextGeneration);
@ -266,7 +324,6 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
return this.m_Population;
}
public void setPopulation(Population pop){
// if (pop.size()!=pop.getPopulationSize()) pop.fitToSize();
this.m_Population = pop;
}
public String populationTipText() {
@ -296,6 +353,10 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
return withShow;
}
public Plot getPlot() {
return myPlot;
}
protected void clearPlot() {
if (myPlot!=null) {
myPlot.clearAll();
@ -356,6 +417,47 @@ public class ParticleFilterOptimization implements InterfaceOptimizer, java.io.S
}
public String mutationSigmaTipText() {
return "The mutation step for the gaussian motion model";
return "The (fixed) mutation step for the gaussian motion model";
}
public double getRndImmigrQuota() {
return randomImmigrationQuota;
}
public void setRndImmigrQuota(double randomImmigrationQuota) {
this.randomImmigrationQuota = randomImmigrationQuota;
}
public String rndImmigrQuotaTipText() {
return "The give ratio of the population will be reinitialized randomly in every iteration.";
}
public double getInitialVelocity() {
return initialVelocity;
}
public void setInitialVelocity(double initialVelocity) {
this.initialVelocity = initialVelocity;
}
public String initialVelocityTipText() {
return "If > 0, a linear motion model will be applied, otherwise the gaussian model";
}
public double getRotationDeg() {
return rotationDeg;
}
public void setRotationDeg(double rotationDeg) {
this.rotationDeg = rotationDeg;
}
public int getPopSize() {
return popSize;
}
public void setPopSize(int popSize) {
this.popSize = popSize;
m_Population.setPopSize(popSize);
}
}