From 513bf3df7dfed6d7f2475c10f39c6ddbacd652ea Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Tue, 1 Jun 2010 16:24:52 +0000 Subject: [PATCH] Minor fixes, part 2 - some GP adaptions. --- src/eva2/EvAInfo.java | 2 +- src/eva2/gui/PropertySheetPanel.java | 9 +- .../individuals/GPIndividualProgramData.java | 48 ++--- .../codings/gp/AbstractGPNode.java | 11 +- .../go/problems/PSymbolicRegression.java | 173 ++++++++++++++++-- .../problems/regression/RFKoza_GPI_7_3.java | 6 +- .../go/strategies/GeneticAlgorithm.java | 13 +- 7 files changed, 201 insertions(+), 61 deletions(-) diff --git a/src/eva2/EvAInfo.java b/src/eva2/EvAInfo.java index 2d50535d..04172120 100644 --- a/src/eva2/EvAInfo.java +++ b/src/eva2/EvAInfo.java @@ -10,7 +10,7 @@ import eva2.tools.BasicResourceLoader; * * --- Changelog * 2.043: Added proper Population equality predicate. - * 2.042: Some bugfixes. Removing dependecy on sun.beans.editors, replaced non-free jpeg-codec. There should + * 2.042: Some bugfixes. Removing dependency on sun.beans.editors, replaced non-free jpeg-codec. There should * be no more problems on OpenJDK. Added a simple initialization range, especially for use from Matlab. * Some restructurings (RNG and Mathematics is now in eva2.tools.math). Some cleanup. * 2.040: Several updates: The clustering interface has been changed for easier implementation of adaptive clustering diff --git a/src/eva2/gui/PropertySheetPanel.java b/src/eva2/gui/PropertySheetPanel.java index ebdd017b..07dfa615 100644 --- a/src/eva2/gui/PropertySheetPanel.java +++ b/src/eva2/gui/PropertySheetPanel.java @@ -367,18 +367,19 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener * @return */ private PropertyDescriptor[] reorderProperties(Method meth) { - PropertyDescriptor[] oldProps = m_Properties.clone(); - PropertyDescriptor[] newProps = new PropertyDescriptor[oldProps.length]; // Mathematics.revertArray(oldProps, newProps); Object[] args = { }; Object retV=null; + PropertyDescriptor[] newProps = null; try { - retV = meth.invoke(m_Target, args); + retV = meth.invoke(m_Target, args); // should return String[] to be interpreted as a list of ordered properties } catch(Exception ex) {} if (retV!=null) { try { - if (retV.getClass().isArray()) { + if (retV.getClass().isArray()) { // reorder the properties String[] swProps=(String[])retV; + PropertyDescriptor[] oldProps = m_Properties.clone(); + newProps = new PropertyDescriptor[oldProps.length]; //int findFirst=findFirstProp(props[0], oldProps); int firstNonNull=0; for (int i=0; i this.m_TargetDepth) { + if (b > this.m_maxDepth) { System.out.println("Waring Init Depth will be set to Target Depth!"); - b = this.m_TargetDepth; + b = this.m_maxDepth; } this.m_InitDepth = b; } @@ -355,13 +355,17 @@ public class GPIndividualProgramData extends AbstractEAIndividual implements Int /** This method set/get the target depth. * @param b The new target Depth of the GP Tree. */ - public void setTargetDepth(int b) { - this.m_TargetDepth = b; + public void setMaxDepth(int b) { + this.m_maxDepth = b; } - public int getTargetDepth() { - return this.m_TargetDepth; + public int getMaxDepth() { + return this.m_maxDepth; } - public String targetDepthTipText() { - return "The target depth of the GP Tree."; + public String maxDepthTipText() { + return "The maximum depth of the GP tree."; + } + + public String[] customPropertyOrder() { + return new String[] {"initDepth", "checkMaxDepth", "maxDepth"}; } } diff --git a/src/eva2/server/go/individuals/codings/gp/AbstractGPNode.java b/src/eva2/server/go/individuals/codings/gp/AbstractGPNode.java index 73eadb2f..9552626f 100644 --- a/src/eva2/server/go/individuals/codings/gp/AbstractGPNode.java +++ b/src/eva2/server/go/individuals/codings/gp/AbstractGPNode.java @@ -468,8 +468,8 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial */ public void repairMaxDepth(GPArea area, int depth) { if (this.m_Depth == depth-1) { - // in this case i need to check wether or not my - // followup nodes are terminals + // in this case i need to check whether or not my + // follow-up nodes are terminals for (int i = 0; i < this.m_Nodes.length; i++) { if (this.m_Nodes[i].getArity() != 0) { // replace this node with a new node @@ -490,12 +490,6 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial * @param obj The other subtree. * @return boolean if equal true else false. */ -// public abstract boolean equals(Object obj); - /** This method allows you to determine wehter or not two subtrees - * are actually the same. - * @param obj The other subtree. - * @return boolean if equal true else false. - */ public boolean equals(Object obj) { if (obj.getClass().equals(this.getClass())) { AbstractGPNode node = (AbstractGPNode)obj; @@ -509,5 +503,4 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial return false; } } - } diff --git a/src/eva2/server/go/problems/PSymbolicRegression.java b/src/eva2/server/go/problems/PSymbolicRegression.java index 67da1f4d..1a284a19 100644 --- a/src/eva2/server/go/problems/PSymbolicRegression.java +++ b/src/eva2/server/go/problems/PSymbolicRegression.java @@ -1,18 +1,25 @@ package eva2.server.go.problems; +import java.io.Serializable; + import eva2.gui.Plot; +import eva2.server.go.PopulationInterface; import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.GAPIndividualProgramData; import eva2.server.go.individuals.GPIndividualProgramData; import eva2.server.go.individuals.InterfaceDataTypeDouble; import eva2.server.go.individuals.InterfaceDataTypeProgram; +import eva2.server.go.individuals.codings.gp.AbstractGPNode; import eva2.server.go.individuals.codings.gp.GPArea; +import eva2.server.go.individuals.codings.gp.GPNodeAbs; import eva2.server.go.individuals.codings.gp.GPNodeAdd; import eva2.server.go.individuals.codings.gp.GPNodeCos; import eva2.server.go.individuals.codings.gp.GPNodeDiv; import eva2.server.go.individuals.codings.gp.GPNodeExp; import eva2.server.go.individuals.codings.gp.GPNodeInput; import eva2.server.go.individuals.codings.gp.GPNodeMult; +import eva2.server.go.individuals.codings.gp.GPNodeOne; +import eva2.server.go.individuals.codings.gp.GPNodePi; import eva2.server.go.individuals.codings.gp.GPNodePow2; import eva2.server.go.individuals.codings.gp.GPNodePow3; import eva2.server.go.individuals.codings.gp.GPNodeSin; @@ -21,9 +28,10 @@ import eva2.server.go.individuals.codings.gp.GPNodeSub; import eva2.server.go.individuals.codings.gp.InterfaceProgram; import eva2.server.go.populations.Population; import eva2.server.go.problems.regression.InterfaceRegressionFunction; -import eva2.server.go.problems.regression.RFKoza_GPI_10_2; +import eva2.server.go.problems.regression.RFKoza_GPI_7_3; import eva2.server.go.strategies.InterfaceOptimizer; import eva2.tools.EVAERROR; +import eva2.tools.ToolBox; import eva2.tools.math.RNG; /** @@ -33,14 +41,14 @@ import eva2.tools.math.RNG; * Time: 16:44:25 * To change this template use Options | File Templates. */ -public class PSymbolicRegression extends AbstractOptimizationProblem implements InterfaceProgramProblem, java.io.Serializable { +public class PSymbolicRegression extends AbstractOptimizationProblem implements InterfaceProgramProblem, InterfaceAdditionalPopulationInformer, Serializable { private double[] m_X = new double[1]; - private int m_NumberOfConstants = 10; - private double m_LowerBound = 0; - private double m_UpperBound = 10; - private int m_NumberOfCheckPoints = 10; - transient private InterfaceRegressionFunction m_TargetFunction = new RFKoza_GPI_10_2(); + private int m_NumberOfConstants = 3; + private double m_LowerBound = -1; + private double m_UpperBound = 1; + private int m_NumberOfCheckPoints = 20; + transient private InterfaceRegressionFunction m_TargetFunction = new RFKoza_GPI_7_3(); private double[] m_C = new double[m_NumberOfConstants]; private boolean m_UseInnerConst = false; private boolean m_UseLocalHillClimbing = false; @@ -97,7 +105,7 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements /** This method inits the Problem to log multiruns */ public void initProblem() { - if (m_TargetFunction == null) m_TargetFunction = new RFKoza_GPI_10_2(); + if (m_TargetFunction == null) m_TargetFunction = new RFKoza_GPI_7_3(); this.m_OverallBest = null; this.m_C = new double[this.m_NumberOfConstants]; for (int i = 0; i < this.m_C.length; i++) this.m_C[i] = RNG.randomDouble(-10, 10); @@ -113,18 +121,21 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements m_GPArea = new GPArea(); if (m_GPArea.isEmpty()) { + this.m_GPArea.add2CompleteList(new GPNodeOne()); + this.m_GPArea.add2CompleteList(new GPNodePi(), false); this.m_GPArea.add2CompleteList(new GPNodeAdd()); this.m_GPArea.add2CompleteList(new GPNodeSub()); this.m_GPArea.add2CompleteList(new GPNodeDiv()); this.m_GPArea.add2CompleteList(new GPNodeMult()); + this.m_GPArea.add2CompleteList(new GPNodeAbs(), false); this.m_GPArea.add2CompleteList(new GPNodeSin(), false); this.m_GPArea.add2CompleteList(new GPNodeCos(), false); this.m_GPArea.add2CompleteList(new GPNodeExp(), false); + this.m_GPArea.add2CompleteList(new GPNodeSqrt(), false); this.m_GPArea.add2CompleteList(new GPNodePow2(), false); this.m_GPArea.add2CompleteList(new GPNodePow3(), false); - this.m_GPArea.add2CompleteList(new GPNodeSqrt(), false); for (int i = 0; i < this.m_X.length; i++) this.m_GPArea.add2CompleteList(new GPNodeInput("X"+i)); - for (int i = 0; i < this.m_C.length; i++) this.m_GPArea.add2CompleteList(new GPNodeInput("C"+i)); + for (int i = 0; i < this.m_C.length; i++) this.m_GPArea.add2CompleteList(new GPNodeInput("C"+i), false); } if ((oldArea!=null) && (oldArea.getBlackList()!=null) && (oldArea.getBlackList().size()==m_GPArea.getBlackList().size())) { m_GPArea.SetBlackList(oldArea.getBlackList()); @@ -200,7 +211,9 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements } /** - * This method evaluates a single individual and sets the fitness values + * This method evaluates a single individual and sets the fitness values. In this case, + * the averaged square error between represented function and target function per check point is calculated. + * * @param individual The individual that is to be evaluated */ public void evaluate(AbstractEAIndividual individual) { @@ -214,9 +227,8 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements this.m_C = ((GAPIndividualProgramData)tmpIndy).getDoubleData(); fitness = 0; - for (int j = 0; j < this.m_NumberOfCheckPoints; j++) - for (int i = 0; i < this.m_X.length; i++) { - this.m_X[i] = this.m_LowerBound +(j*(this.m_UpperBound-this.m_LowerBound)/this.m_NumberOfCheckPoints); + for (int j = 0; j < this.m_NumberOfCheckPoints; j++) { + setCheckPoint(m_X, j); tmpValue = ((Double)program.evaluate(this)).doubleValue(); fitness += Math.pow((this.m_TargetFunction.evaluateFunction(this.m_X) - ((Double)program.evaluate(this)).doubleValue()), 2); } @@ -233,8 +245,8 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements if (m_Plot==null) this.initEnvironmentPanel(); this.m_Plot.clearAll(); program = ((InterfaceDataTypeProgram)this.m_OverallBest).getProgramData()[0]; - for (double i = 0; i < this.m_NumberOfCheckPoints; i++) { - for (int j = 0; j < this.m_X.length; j++) this.m_X[j] = i ; + for (int i = 0; i < this.m_NumberOfCheckPoints; i++) { + setCheckPoint(m_X, i); tmpValue = ((Double)program.evaluate(this)).doubleValue(); this.m_Plot.setConnectedPoint(this.m_X[0], tmpValue, 0); tmpValue = this.m_TargetFunction.evaluateFunction(this.m_X); @@ -245,6 +257,17 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements } } + /** + * Select a test point - TODO this btw only makes much sense in 1D. + * @param x + * @param j + */ + private void setCheckPoint(double[] x, int j) { + for (int i = 0; i < x.length; i++) { + x[i] = this.m_LowerBound +(j*(this.m_UpperBound-this.m_LowerBound)/(this.m_NumberOfCheckPoints-1)); + } + } + /** This method returns a string describing the optimization problem. * @param opt The Optimizer that is used or had been used. * @return The description. @@ -458,4 +481,122 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements public InterfaceDataTypeProgram getGPIndividual() { return (InterfaceDataTypeProgram)this.m_Template; } + public String GPIndividualTipText() { + return "Modify the properties of the template GP individual such as maximum tree depth etc."; + } + + public double getLowerBound() { + return m_LowerBound; + } + public void setLowerBound(double mLowerBound) { + m_LowerBound = mLowerBound; + } + public String lowerBoundTipText() { + return "The lower bound of the 1D double interval where the target function is sampled."; + } + + public double getUpperBound() { + return m_UpperBound; + } + public void setUpperBound(double mUpperBound) { + m_UpperBound = mUpperBound; + } + public String upperBoundTipText() { + return "The upper bound of the 1D double interval where the target function is sampled."; + } + + public String[] customPropertyOrder() { + return new String[] {"lowerBound", "upperBound"}; + } + + @Override + public String[] getAdditionalFileStringHeader(PopulationInterface pop) { + String[] superHd = super.getAdditionalFileStringHeader(pop); + return ToolBox.appendArrays(new String[]{"bestIndySize","avgIndySize","avgIndyDepth"}, superHd); + } + + @Override + public Object[] getAdditionalFileStringValue(PopulationInterface pop) { + Object[] superDat = super.getAdditionalFileStringValue(pop); + return ToolBox.appendArrays(new Object[]{getBestIndySize(pop), getAvgIndySize(pop), getAvgIndyDepth(pop)}, superDat); + } + + /** + * Get the average tree depth of the given population (for program individuals). + * + * @see #getIndyDepth(AbstractEAIndividual) + * @param pop + * @return + */ + public static double getAvgIndyDepth(PopulationInterface pop) { + Population p = (Population)pop; + double sum=0; + for (int i=0; i