From e57a2eaea2822a725b6b904711cb136f8641992b Mon Sep 17 00:00:00 2001 From: Marcel Kronfeld Date: Tue, 28 Sep 2010 12:57:38 +0000 Subject: [PATCH] Some extensions to the ExternalRuntimeProblem. Changed PropertyDoubleArray and its generic editor to work with multi-dim. arrays (type double[][]). --- src/eva2/gui/GenericDoubleArrayEditor.java | 179 +++++++++----- src/eva2/gui/PropertyDoubleArray.java | 185 ++++++++++++-- src/eva2/gui/PropertySheetPanel.java | 2 +- src/eva2/server/go/MOCCOStandalone.java | 7 +- .../individuals/ESIndividualDoubleData.java | 6 +- .../server/go/mocco/MOCCOParameterizeGDF.java | 2 +- .../operators/archiving/ArchivingNSGAII.java | 15 +- .../migration/MOClusteringSeparation.java | 2 +- .../migration/MOXMeansSeparation.java | 2 +- .../operators/moso/MOSOGoalProgramming.java | 6 +- .../go/operators/moso/MOSOLpMetric.java | 17 +- .../go/operators/moso/MOSORankbased.java | 2 +- .../operators/moso/MOSOWeightedFitness.java | 25 +- .../SelectMONSGAIICrowedTournament.java | 2 +- ...ntNondominatedSortingDistanceCrowding.java | 2 +- .../server/go/populations/Population.java | 4 +- ...ractMultiObjectiveOptimizationProblem.java | 13 +- .../go/problems/ExternalRuntimeProblem.java | 234 ++++++++++++------ src/eva2/server/go/problems/TF1Problem.java | 6 +- .../go/strategies/MultiObjectiveCMAES.java | 4 +- .../go/strategies/MultiObjectiveEA.java | 7 +- src/eva2/server/modules/GOParameters.java | 9 +- .../server/stat/StatisticsStandalone.java | 3 +- src/eva2/tools/BasicResourceLoader.java | 21 +- src/eva2/tools/math/Mathematics.java | 71 ++++++ 25 files changed, 615 insertions(+), 211 deletions(-) diff --git a/src/eva2/gui/GenericDoubleArrayEditor.java b/src/eva2/gui/GenericDoubleArrayEditor.java index f3cb134d..d74d6941 100644 --- a/src/eva2/gui/GenericDoubleArrayEditor.java +++ b/src/eva2/gui/GenericDoubleArrayEditor.java @@ -1,26 +1,58 @@ package eva2.gui; -import javax.swing.*; -import java.beans.PropertyEditor; -import java.beans.PropertyChangeSupport; -import java.beans.PropertyChangeListener; -import java.awt.*; -import java.awt.event.ActionListener; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.Window; import java.awt.event.ActionEvent; -import java.awt.event.KeyListener; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; import java.awt.event.KeyEvent; -import java.io.File; +import java.awt.event.KeyListener; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyEditor; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; /** - * Created by IntelliJ IDEA. - * User: streiche - * Date: 05.03.2004 - * Time: 13:51:14 - * To change this template use File | Settings | File Templates. + * A simple focus listener with an object ID and callback. + * + * @author mkron + * + */ +class MyFocusListener implements FocusListener { + private int myID = -1; + private GenericDoubleArrayEditor arrEditor = null; + + public MyFocusListener(int id, GenericDoubleArrayEditor gdae) { + myID = id; + this.arrEditor = gdae; + } + + @Override + public void focusLost(FocusEvent e) { } + + @Override + public void focusGained(FocusEvent e) { arrEditor.notifyFocusID(myID);}; +}; + + +/** + * A generic editor for PropertyDoubleArray. */ public class GenericDoubleArrayEditor extends JPanel implements PropertyEditor { - /** Handles property change notification */ + private static final long serialVersionUID = 7749892624600018812L; + /** Handles property change notification */ private PropertyChangeSupport m_Support = new PropertyChangeSupport(this); /** The label for when we can't edit that type */ private JLabel m_Label = new JLabel("Can't edit", SwingConstants.CENTER); @@ -29,9 +61,11 @@ public class GenericDoubleArrayEditor extends JPanel implements PropertyEditor { /** The gaphix stuff */ private JPanel m_CustomEditor, m_DataPanel, m_ButtonPanel; - private JTextField[] m_InputTextField; + private JTextField[][] m_InputTextFields; private JButton m_OKButton, m_AddButton, m_DeleteButton, m_NormalizeButton; - + + /** Which columns has the focus? **/ + private int lastFocussedRow = -1; public GenericDoubleArrayEditor() { // compiled code } @@ -56,7 +90,7 @@ public class GenericDoubleArrayEditor extends JPanel implements PropertyEditor { this.m_DeleteButton = new JButton("Delete"); this.m_DeleteButton.addActionListener(this.deleteAction); this.m_NormalizeButton = new JButton("Normalize"); - this.m_NormalizeButton.addActionListener(this.mormalizeAction); + this.m_NormalizeButton.addActionListener(this.normalizeAction); this.m_OKButton = new JButton("OK"); this.m_OKButton.setEnabled(true); this.m_OKButton.addActionListener(new ActionListener() { @@ -80,71 +114,64 @@ public class GenericDoubleArrayEditor extends JPanel implements PropertyEditor { */ ActionListener addAction = new ActionListener() { public void actionPerformed(ActionEvent event) { - double[] tmpD = m_DoubleArray.getDoubleArray(); - double[] newD = new double[tmpD.length+1]; - - for (int i = 0; i < newD.length; i++) newD[i] = 1.0; - for (int i = 0; i < tmpD.length; i++) newD[i] = tmpD[i]; - m_DoubleArray.setDoubleArray(newD); + m_DoubleArray.addRowCopy(lastFocussedRow); // copy the last focussed row updateEditor(); } }; - /** This action listener removes an element to DoubleArray + + /** This action listener removes an element from the DoubleArray. */ ActionListener deleteAction = new ActionListener() { public void actionPerformed(ActionEvent event) { - double[] tmpD = m_DoubleArray.getDoubleArray(); - double[] newD = new double[tmpD.length-1]; - - for (int i = 0; i < newD.length; i++) newD[i] = tmpD[i]; - m_DoubleArray.setDoubleArray(newD); + if (!m_DoubleArray.isValidRow(lastFocussedRow)) { + m_DoubleArray.deleteRow(m_DoubleArray.getNumRows()-1); + } else { + m_DoubleArray.deleteRow(lastFocussedRow); + } updateEditor(); } }; - /** This action listener nomalizes the values of the DoubleArray + + /** + * This action listener nomalizes each columng of the values of the DoubleArray. */ - ActionListener mormalizeAction = new ActionListener() { + ActionListener normalizeAction = new ActionListener() { public void actionPerformed(ActionEvent event) { - double[] tmpD = m_DoubleArray.getDoubleArray(); - double sum = 0; - - for (int i = 0; i < tmpD.length; i++) sum += tmpD[i]; - if (sum == 0) return; - for (int i = 0; i < tmpD.length; i++) tmpD[i] = tmpD[i]/sum; - m_DoubleArray.setDoubleArray(tmpD); + m_DoubleArray.normalizeColumns(); updateEditor(); } }; - + /** This action listener reads all values */ KeyListener readDoubleArrayAction = new KeyListener() { - public void keyPressed(KeyEvent event) { + public void keyPressed(KeyEvent event) { } public void keyTyped(KeyEvent event) { } public void keyReleased(KeyEvent event) { - double[] tmpD = new double[m_InputTextField.length]; + double[][] tmpDD = new double[m_InputTextFields.length][m_InputTextFields[0].length]; - for (int i = 0; i < tmpD.length; i++) { - - try { - double d = 0; - d = new Double(m_InputTextField[i].getText()).doubleValue(); - tmpD[i] = d; - } catch (Exception e) { - - } + for (int i = 0; i < tmpDD.length; i++) { + for (int j=0; j< tmpDD[0].length; j++) { + try { + double d = 0; + d = new Double(m_InputTextFields[i][j].getText()).doubleValue(); + tmpDD[i][j] = d; + } catch (Exception e) { + } + } //tmpD[i] = new Double(m_InputTextField[i].getText()).doubleValue(); } - m_DoubleArray.setDoubleArray(tmpD); + m_DoubleArray.setDoubleArray(tmpDD); //updateEditor(); } }; - /** The object may have changed update the editor. + + /** The object may have changed update the editor. */ private void updateEditor() { if (this.m_CustomEditor != null) { @@ -154,24 +181,50 @@ public class GenericDoubleArrayEditor extends JPanel implements PropertyEditor { } } +// /** This method updates the data panel +// */ +// private void updateDataPanelOrig() { +// double[] tmpD = this.m_DoubleArray.getDoubleArray(); +// +// this.m_DataPanel.removeAll(); +// this.m_DataPanel.setLayout(new GridLayout(tmpD.length, 2)); +// this.m_InputTextField = new JTextField[tmpD.length]; +// for (int i = 0; i < tmpD.length; i++) { +// JLabel label = new JLabel("Value X"+i+": "); +// this.m_DataPanel.add(label); +// this.m_InputTextField[i] = new JTextField(); +// this.m_InputTextField[i].setText(""+tmpD[i]); +// this.m_InputTextField[i].addKeyListener(this.readDoubleArrayAction); +// this.m_DataPanel.add(this.m_InputTextField[i]); +// } +// } + /** This method updates the data panel */ private void updateDataPanel() { - double[] tmpD = this.m_DoubleArray.getDoubleArray(); - + int numRows = m_DoubleArray.getNumRows(); + int numCols = m_DoubleArray.getNumCols(); this.m_DataPanel.removeAll(); - this.m_DataPanel.setLayout(new GridLayout(tmpD.length, 2)); - this.m_InputTextField = new JTextField[tmpD.length]; - for (int i = 0; i < tmpD.length; i++) { + this.m_DataPanel.setLayout(new GridLayout(numRows, numCols+1)); + this.m_InputTextFields = new JTextField[numRows][numCols]; + for (int i = 0; i < numRows; i++) { JLabel label = new JLabel("Value X"+i+": "); this.m_DataPanel.add(label); - this.m_InputTextField[i] = new JTextField(); - this.m_InputTextField[i].setText(""+tmpD[i]); - this.m_InputTextField[i].addKeyListener(this.readDoubleArrayAction); - this.m_DataPanel.add(this.m_InputTextField[i]); + for (int j=0; j0 && cols>0) this.m_DoubleArray = new double[rows][cols]; + else this.m_DoubleArray=null; + this.m_numCols=cols; + int index=0; + for (int i=0; i=d.length) index=0; + } + } + } + + public Object clone() { return (Object) new PropertyDoubleArray(this); } @@ -27,14 +50,138 @@ public class PropertyDoubleArray implements java.io.Serializable { * @param d The double[] */ public void setDoubleArray(double[] d) { - this.m_DoubleArray = d; + this.m_DoubleArray = new double[d.length][1]; + for (int i=0; i0) m_numCols=d[0].length; + else m_numCols=1; + } + + /** + * @return the double array itself (no clone) + */ + public double[][] getDoubleArrayShallow() { + return this.m_DoubleArray; + } + + /** + * Return a column as a vector (in copy) + * @return a column as a vector (in copy) + */ + public double[] getDoubleColumnAsVector(int col) { + if (col>=m_numCols) { + throw new IllegalArgumentException("Error, invalid column selected, " + col + " of " + m_numCols); + } + double[] ret = new double[m_DoubleArray.length]; + for (int i=0; i=getNumRows()) || (j>=getNumCols())) { + throw new IllegalArgumentException("Error, invalid access to double array: " + i + "," + j + " within " + getNumRows() + ","+getNumCols()); + } + return m_DoubleArray[i][j]; } - /** This method will return the complete name of the file - * which filepath - * @return The complete filename with path. - */ - public double[] getDoubleArray() { - return this.m_DoubleArray; - } + public void adaptRowCount(int k) { + if (k!=m_DoubleArray.length) { + double[][] newDD = new double[k][m_numCols]; + for (int i=0; i=getNumRows()) throw new IllegalArgumentException("Invalid index to deleteRow: " + k + " is not a valid row."); + double[][] newDD = new double[getNumRows()-1][getNumCols()]; + int inc=0; + for (int i = 0; i < newDD.length; i++) { + if (i==k) inc=1; + for (int j=0; j= getNumRows()) k=getNumRows()-1; + double[][] newDD = new double[getNumRows()+1][getNumCols()]; + + for (int i = 0; i < getNumRows(); i++) + for (int j=0; j=0) for (int j=0; j=0) && (k= 1) { // standard Lp Metric resultFit[0] = 0; - for (int i = 0; (i < this.m_Reference.m_DoubleArray.length) && (i < tmpFit.length); i++) { - resultFit[0] += Math.pow(Math.abs(tmpFit[i]-this.m_Reference.m_DoubleArray[i]), this.m_P); + for (int i = 0; (i < this.m_Reference.getNumRows()) && (i < tmpFit.length); i++) { + resultFit[0] += Math.pow(Math.abs(tmpFit[i]-this.m_Reference.getValue(i,0)), this.m_P); } resultFit[0] = Math.pow(resultFit[0], 1/((double)this.m_P)); } else { // Tchebycheff metric resultFit[0] = Double.NEGATIVE_INFINITY; - for (int i = 0; (i < this.m_Reference.m_DoubleArray.length) && (i < tmpFit.length); i++) { - resultFit[0] += Math.max(Math.abs(tmpFit[i]-this.m_Reference.m_DoubleArray[i]), resultFit[0]); + for (int i = 0; (i < this.m_Reference.getNumRows()) && (i < tmpFit.length); i++) { + resultFit[0] += Math.max(Math.abs(tmpFit[i]-this.m_Reference.getValue(i,0)), resultFit[0]); } } @@ -80,7 +80,7 @@ public class MOSOLpMetric implements InterfaceMOSOConverter, java.io.Serializabl double[] newWeights = new double[dim]; for (int i = 0; i < newWeights.length; i++) newWeights[i] = 0.0; - for (int i = 0; (i < this.m_Reference.m_DoubleArray.length) && (i < newWeights.length); i++) newWeights[i] = this.m_Reference.m_DoubleArray[i]; + for (int i = 0; (i < this.m_Reference.getNumRows()) && (i < newWeights.length); i++) newWeights[i] = this.m_Reference.getValue(i,0); this.m_Reference.setDoubleArray(newWeights); } @@ -92,10 +92,9 @@ public class MOSOLpMetric implements InterfaceMOSOConverter, java.io.Serializabl String result = "Lp Metric\n"; result += " P = "+this.m_P+"\n"; result += " Ref.Fitness = ("; - double[] p = this.m_Reference.m_DoubleArray; - for (int i = 0; i < p.length; i++) { - result += p[i]; - if (i < (p.length-1)) result += "; "; + for (int i = 0; i < m_Reference.getNumRows(); i++) { + result += m_Reference.getValue(i,0); + if (i < (m_Reference.getNumRows()-1)) result += "; "; } result += ")\n"; return result; diff --git a/src/eva2/server/go/operators/moso/MOSORankbased.java b/src/eva2/server/go/operators/moso/MOSORankbased.java index fc380b3a..e06cbb95 100644 --- a/src/eva2/server/go/operators/moso/MOSORankbased.java +++ b/src/eva2/server/go/operators/moso/MOSORankbased.java @@ -31,7 +31,7 @@ public class MOSORankbased implements InterfaceMOSOConverter, java.io.Serializab */ public void convertMultiObjective2SingleObjective(Population pop) { ArchivingNSGAII arch = new ArchivingNSGAII(); - arch.getNonDomiatedSortedFronts(pop); + arch.getNonDominatedSortedFronts(pop); for (int i = 0; i < pop.size(); i++) { this.convertSingleIndividual((AbstractEAIndividual)pop.get(i)); } diff --git a/src/eva2/server/go/operators/moso/MOSOWeightedFitness.java b/src/eva2/server/go/operators/moso/MOSOWeightedFitness.java index 80e5f8b3..c9bce894 100644 --- a/src/eva2/server/go/operators/moso/MOSOWeightedFitness.java +++ b/src/eva2/server/go/operators/moso/MOSOWeightedFitness.java @@ -16,16 +16,23 @@ public class MOSOWeightedFitness implements InterfaceMOSOConverter, java.io.Seri private PropertyDoubleArray m_Weights = null; public MOSOWeightedFitness() { - double[] tmpD = new double[2]; - for (int i = 0; i < tmpD.length; i++) tmpD[i] = 1.0; + double[][] tmpD = new double[2][1]; + for (int i = 0; i < tmpD.length; i++) tmpD[i][0] = 1.0; this.m_Weights = new PropertyDoubleArray(tmpD); - for (int i = 0; i < this.m_Weights.m_DoubleArray.length; i++) this.m_Weights.m_DoubleArray[i] = 1/((double)this.m_Weights.m_DoubleArray.length); + for (int i = 0; i < this.m_Weights.getNumRows(); i++) this.m_Weights.normalizeColumns(); } + + public MOSOWeightedFitness(double[][] weights) { + this(); + setWeights(new PropertyDoubleArray(weights)); + } + public MOSOWeightedFitness(MOSOWeightedFitness b) { if (b.m_Weights != null) { this.m_Weights = (PropertyDoubleArray)b.m_Weights; } } + public Object clone() { return (Object) new MOSOWeightedFitness(this); } @@ -52,16 +59,16 @@ public class MOSOWeightedFitness implements InterfaceMOSOConverter, java.io.Seri tmpFit = indy.getFitness(); indy.putData("MOFitness", tmpFit); - for (int i = 0; (i < this.m_Weights.m_DoubleArray.length) && (i < tmpFit.length) ; i++) - resultFit[0] += tmpFit[i]*this.m_Weights.m_DoubleArray[i]; + for (int i = 0; (i < this.m_Weights.getNumRows()) && (i < tmpFit.length) ; i++) + resultFit[0] += tmpFit[i]*this.m_Weights.getValue(i,0); indy.SetFitness(resultFit); } private void checkingWeights() { String s = "Using Weights: {"; - for (int i = 0; i < this.m_Weights.m_DoubleArray.length; i++) { - s += this.m_Weights.m_DoubleArray[i]; - if (i < this.m_Weights.m_DoubleArray.length-1) s+= "; "; + for (int i = 0; i < this.m_Weights.getNumRows(); i++) { + s += this.m_Weights.getValue(i,0); + if (i < this.m_Weights.getNumRows()-1) s+= "; "; } System.out.println(s+"}"); } @@ -75,7 +82,7 @@ public class MOSOWeightedFitness implements InterfaceMOSOConverter, java.io.Seri double[] newWeights = new double[dim]; for (int i = 0; i < newWeights.length; i++) newWeights[i] = 1; - for (int i = 0; (i < this.m_Weights.m_DoubleArray.length) && (i < newWeights.length); i++) newWeights[i] = this.m_Weights.m_DoubleArray[i]; + for (int i = 0; (i < this.m_Weights.getNumRows()) && (i < newWeights.length); i++) newWeights[i] = this.m_Weights.getValue(i,0); this.m_Weights.setDoubleArray(newWeights); } diff --git a/src/eva2/server/go/operators/selection/SelectMONSGAIICrowedTournament.java b/src/eva2/server/go/operators/selection/SelectMONSGAIICrowedTournament.java index e6e4a521..517937f3 100644 --- a/src/eva2/server/go/operators/selection/SelectMONSGAIICrowedTournament.java +++ b/src/eva2/server/go/operators/selection/SelectMONSGAIICrowedTournament.java @@ -41,7 +41,7 @@ public class SelectMONSGAIICrowedTournament implements InterfaceSelection, java. * @param population The population that is to be processed. */ public void prepareSelection(Population population) { - this.m_Fronts = this.m_NSGAII.getNonDomiatedSortedFronts(population); + this.m_Fronts = this.m_NSGAII.getNonDominatedSortedFronts(population); this.m_NSGAII.calculateCrowdingDistance(this.m_Fronts); } diff --git a/src/eva2/server/go/operators/selection/replacement/ReplacementNondominatedSortingDistanceCrowding.java b/src/eva2/server/go/operators/selection/replacement/ReplacementNondominatedSortingDistanceCrowding.java index 0d1699da..c553c72b 100644 --- a/src/eva2/server/go/operators/selection/replacement/ReplacementNondominatedSortingDistanceCrowding.java +++ b/src/eva2/server/go/operators/selection/replacement/ReplacementNondominatedSortingDistanceCrowding.java @@ -65,7 +65,7 @@ public class ReplacementNondominatedSortingDistanceCrowding implements Interface pop.add(indy); - Population []store=dummyArchive.getNonDomiatedSortedFronts(pop); + Population []store=dummyArchive.getNonDominatedSortedFronts(pop); dummyArchive.calculateCrowdingDistance(store);//TODO die f�r das gesamte Archiv am St�ck berechnen und nicht f�r die Einzelfronten! for(int i=0;i 1. * Notice that it might slightly disturb notification if a notifyEvalInterval is set. * - * @param d The number of function calls to increment. + * @param d The number of function calls to increment by. */ public void incrFunctionCallsBy(int d) { if (doEvalNotify()) { @@ -1063,7 +1063,7 @@ public class Population extends ArrayList implements PopulationInterface, Clonea * @param n number of individuals to look out for * @param bBestOrWorst if true, the best n are returned, else the worst n individuals * @param res sorted result population, will be cleared - * @param comparator the Comparator to use with individuals + * @param comp the Comparator to use with individuals * @return The m sorted best or worst individuals, where m <= n * */ diff --git a/src/eva2/server/go/problems/AbstractMultiObjectiveOptimizationProblem.java b/src/eva2/server/go/problems/AbstractMultiObjectiveOptimizationProblem.java index 24b5edd5..2cd099b8 100644 --- a/src/eva2/server/go/problems/AbstractMultiObjectiveOptimizationProblem.java +++ b/src/eva2/server/go/problems/AbstractMultiObjectiveOptimizationProblem.java @@ -317,6 +317,7 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract for (int i = 0; i < archive.size(); i++) { icon = new Chart2DDPointIconCircle(); tmpD = ((AbstractEAIndividual)archive.get(i)).getFitness(); + if (tmpD.length<2) throw new RuntimeException("Error, problem seems not to be multi-objective, pareto front plot not possible!"); myPoint = new DPoint(tmpD[0], tmpD[1]); if (((AbstractEAIndividual)archive.get(i)).getConstraintViolation() > 0) { icon.setBorderColor(Color.RED); @@ -496,9 +497,13 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract @Override public Object[] getAdditionalFileStringValue(PopulationInterface pop) { - Object[] result = new Object[2]; - result[0] = this.calculateMetric((Population)pop); - result[1] = this.calculateMetric(getLocalParetoFront()); + Object[] result = new Object[2]; + if (m_MOSOConverter!=null && !(m_MOSOConverter instanceof MOSONoConvert)) { + result[0]=Double.NaN; result[1]=Double.NaN; + } else { + result[0] = this.calculateMetric((Population)pop); + result[1] = this.calculateMetric(getLocalParetoFront()); + } return ToolBox.appendArrays(result, super.getAdditionalFileStringValue(pop)); } @@ -510,7 +515,7 @@ public abstract class AbstractMultiObjectiveOptimizationProblem extends Abstract public String[] getAdditionalFileStringInfo() { String[] superInfo = super.getAdditionalFileStringInfo(); return ToolBox.appendArrays(new String[]{"Pareto metric on the current population (per generation)", - "Pareto metric on the collected pareto front"}, superInfo); + "Pareto metric on the collected pareto front"}, superInfo); } /* diff --git a/src/eva2/server/go/problems/ExternalRuntimeProblem.java b/src/eva2/server/go/problems/ExternalRuntimeProblem.java index 9a91b6f6..4c76dd50 100644 --- a/src/eva2/server/go/problems/ExternalRuntimeProblem.java +++ b/src/eva2/server/go/problems/ExternalRuntimeProblem.java @@ -2,8 +2,8 @@ package eva2.server.go.problems; import java.io.BufferedInputStream; import java.io.BufferedReader; -import java.io.IOException; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; @@ -13,27 +13,30 @@ import java.util.ArrayList; import java.util.List; import eva2.gui.BeanInspector; +import eva2.gui.PropertyDoubleArray; import eva2.server.go.individuals.AbstractEAIndividual; import eva2.server.go.individuals.ESIndividualDoubleData; import eva2.server.go.individuals.InterfaceDataTypeDouble; +import eva2.server.go.operators.moso.InterfaceMOSOConverter; +import eva2.server.go.operators.moso.MOSONoConvert; import eva2.server.go.populations.Population; import eva2.server.go.strategies.InterfaceOptimizer; - - - -import eva2.server.go.problems.Interface2DBorderProblem; import eva2.tools.math.Mathematics; -public class ExternalRuntimeProblem extends AbstractOptimizationProblem implements Interface2DBorderProblem, InterfaceProblemDouble { +public class ExternalRuntimeProblem extends AbstractOptimizationProblem +implements Interface2DBorderProblem, InterfaceProblemDouble, InterfaceHasInitRange { protected AbstractEAIndividual m_OverallBest = null; protected int m_ProblemDimension = 10; // protected boolean m_UseTestConstraint = false; protected String m_Command = ""; protected String m_WorkingDir = ""; - protected double m_upperBound = 10; - protected double m_lowerBound = 0; +// protected double m_upperBound = 10; +// protected double m_lowerBound = 0; + PropertyDoubleArray m_Range = new PropertyDoubleArray(m_ProblemDimension, 2, -10,10); + PropertyDoubleArray m_initRange = new PropertyDoubleArray(m_ProblemDimension, 2, -10,10); private String additionalArg=""; + protected InterfaceMOSOConverter m_MosoConverter = new MOSONoConvert(); // Private Subclass to redirect Streams within an extra Thread to avoid dead // locks @@ -56,24 +59,26 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen } // System.out.println("monitor-thread finished!"); } catch (IOException ioe) { + System.err.println("IOException in MonitorInputStreamThread/ExternalRuntimeProblem: " + ioe.getMessage()); ioe.printStackTrace(System.err); } finally { try { reader.close(); writer.close(); } catch (IOException e) { - // TODO Auto-generated catch block + System.err.println("IOException in MonitorInputStreamThread/ExternalRuntimeProblem: " + e.getMessage()); e.printStackTrace(); } } } } - + public ExternalRuntimeProblem() { this.m_Template = new ESIndividualDoubleData(); ((ESIndividualDoubleData)this.m_Template).setDoubleDataLength(m_ProblemDimension); ((ESIndividualDoubleData)this.m_Template).SetDoubleRange(makeRange()); } + public ExternalRuntimeProblem(ExternalRuntimeProblem b) { //AbstractOptimizationProblem if (b.m_Template != null) @@ -82,10 +87,15 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen if (b.m_OverallBest != null) this.m_OverallBest = (AbstractEAIndividual)((AbstractEAIndividual)b.m_OverallBest).clone(); this.m_ProblemDimension = b.m_ProblemDimension; -// this.m_UseTestConstraint = b.m_UseTestConstraint; m_Command = b.m_Command; - m_lowerBound = b.m_lowerBound; - m_upperBound = b.m_upperBound; + if (b.m_Range!=null) this.m_Range = (PropertyDoubleArray)b.m_Range.clone(); + else this.m_Range=null; + + if (b.m_initRange!=null) this.m_initRange = (PropertyDoubleArray)b.m_initRange.clone(); + else this.m_initRange=null; + + if (b.m_MosoConverter!=null) this.m_MosoConverter=(InterfaceMOSOConverter)b.m_MosoConverter.clone(); + else this.m_MosoConverter=null; } @@ -115,26 +125,42 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen } public double[][] makeRange() { - double[][] range = new double[this.m_ProblemDimension][2]; - for (int i = 0; i < range.length; i++) { - range[i][0] = getRangeLowerBound(i); - range[i][1] = getRangeUpperBound(i); - } - return range; + if (m_Range==null) { + System.err.println("Warning, range not set ExternalRuntimeProblem.makeRange!"); + } + if (m_Range.getNumRows()!=getProblemDimension()) System.err.println("Warning, problem dimension and range dimension dont match in ExternalRuntimeProblem.makeRange!"); + return m_Range.getDoubleArrayShallow().clone(); } - - public double getRangeLowerBound(int dim) { - return m_lowerBound; + + public void setRange(double[][] range) { + PropertyDoubleArray pRange = new PropertyDoubleArray(range); + this.setRange(pRange); + } + + /** + * Set the internal problem range to the given array. + * @param range + */ + public void setRange(PropertyDoubleArray range) { + if (range.getNumRows() runProcess(List parameters, String workingDir) { + String colSepRegExp= "[\\s;:|]"; // \s for whitespaces, double quoting necessary! Process process; ProcessBuilder pb; List results = new ArrayList(); @@ -184,19 +225,18 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen String line; while ((line = br.readLine()) != null) { line = line.trim(); - if (line.contains(" ")) { - String[] parts = line.split(" "); - for (String str : parts) { - results.add(str); - } - } else { - results.add(line); + String[] parts = line.split(colSepRegExp); + for (String str : parts) { + results.add(str); } +// results.add(line); } br.close(); } catch (IOException e) { - System.err.println("IO Error when calling external command!"); + String msg="IO Error when calling external command! Invalid command for ExternalRuntimeProblem?"; + System.err.println(msg); e.printStackTrace(); + throw new RuntimeException(msg); } return results; } @@ -272,19 +312,27 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen public static String globalInfo() { return "Use an external command as target function."; } + + public String[] getGOEPropertyUpdateLinks() { + return new String[] {"problemDimension", "initialRange", "problemDimension", "range"}; + } - - /** Length of the x vector at is to be optimized - * @param t Length of the x vector at is to be optimized + /** + * Length of the x vector that is to be optimized. Be sure to keep + * the ranges fit in length. + * + * @param t Length of the x vector that is to be optimized */ public void setProblemDimension(int t) { this.m_ProblemDimension = t; + this.m_Range.adaptRowCount(t); + this.m_initRange.adaptRowCount(t); } public int getProblemDimension() { return this.m_ProblemDimension; } public String problemDimensionTipText() { - return "Length of the x vector at is to be optimized."; + return "Domain dimension of the problem"; } /** Length of the x vector at is to be optimized @@ -326,7 +374,17 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen // return "Just a simple test constraint of x[0] >= 1."; // } - /** This method allows you to choose the EA individual + public InterfaceMOSOConverter getMosoConverter() { + return m_MosoConverter; + } + public void setMosoConverter(InterfaceMOSOConverter mMosoConverter) { + m_MosoConverter = mMosoConverter; + } + public String mosoConverterTipText() { + return "Possible conversion of multi-objective fitness to single objective fitness."; + } + + /** This method allows you to choose the EA individual * @param indy The EAIndividual type */ public void setEAIndividual(InterfaceDataTypeDouble indy) { @@ -342,41 +400,41 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen return Mathematics.expandVector(point, getProblemDimension(), 0.); } public double[][] get2DBorder() { - return getDoubleRange(); + return getRange().getDoubleArrayShallow(); } - /** - * @return the m_upperBound - */ - public double getRangeUpperBound() { - return m_upperBound; - } - /** - * @param bound the m_upperBound to set - */ - public void setRangeUpperBound(double bound) { - m_upperBound = bound; - } - - public String rangeUpperBoundTipText() { - return "Upper bound of the search space in any dimension."; - } - /** - * @return the m_lowerBound - */ - public double getRangeLowerBound() { - return m_lowerBound; - } - /** - * @param bound the m_lowerBound to set - */ - public void setRangeLowerBound(double bound) { - m_lowerBound = bound; - } - - public String rangeLowerBoundTipText() { - return "Lower bound of the search space in any dimension."; - } +// /** +// * @return the m_upperBound +// */ +// public double getRangeUpperBound() { +// return m_upperBound; +// } +// /** +// * @param bound the m_upperBound to set +// */ +// public void setRangeUpperBound(double bound) { +// m_upperBound = bound; +// } +// +// public String rangeUpperBoundTipText() { +// return "Upper bound of the search space in any dimension."; +// } +// /** +// * @return the m_lowerBound +// */ +// public double getRangeLowerBound() { +// return m_lowerBound; +// } +// /** +// * @param bound the m_lowerBound to set +// */ +// public void setRangeLowerBound(double bound) { +// m_lowerBound = bound; +// } +// +// public String rangeLowerBoundTipText() { +// return "Lower bound of the search space in any dimension."; +// } public String additionalArgumentTipText() { return "Optionally define an additional (first) argument for the command line command."; @@ -388,4 +446,34 @@ public class ExternalRuntimeProblem extends AbstractOptimizationProblem implemen public void setAdditionalArgument(String additionalArg) { this.additionalArg = additionalArg; } + +// @Override + public Object getInitRange() { + if (m_initRange==null) { + if (m_Range==null) System.err.println("Warning, neither range nor initRange has been set in ExternalRuntimeProblem!"); + return m_Range.getDoubleArrayShallow(); + } else { + return m_initRange.getDoubleArrayShallow(); + } + } + public void setInitialRange(double[][] range) { + PropertyDoubleArray pRange = new PropertyDoubleArray(range); + this.setInitialRange(pRange); + } + + public void setInitialRange(PropertyDoubleArray range) { + if (range.getNumRows()=entries.length) || (entries[i]==null || (entries[i].length()==0))) dest[lineCnt][i]=Double.NaN; + else dest[lineCnt][i] = Double.valueOf(entries[i]); } catch(NumberFormatException ex) { System.err.println("Invalid Double format in line " + lineCnt + ", data was " + entries[i]); + dest[lineCnt][i]=Double.NaN; } } } else { for (int i=0; i=entries.length) || (entries[cols[i]]==null || (entries[cols[i]].length()==0))) dest[lineCnt][i]=Double.NaN; + else dest[lineCnt][i] = Double.valueOf(entries[cols[i]]); } catch(NumberFormatException ex) { System.err.println("Invalid Double format in line " + lineCnt + ", data was " + entries[cols[i]]); + dest[lineCnt][i]=Double.NaN; } } } diff --git a/src/eva2/tools/math/Mathematics.java b/src/eva2/tools/math/Mathematics.java index 7433e777..7869d4bb 100644 --- a/src/eva2/tools/math/Mathematics.java +++ b/src/eva2/tools/math/Mathematics.java @@ -1,5 +1,6 @@ package eva2.tools.math; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -379,6 +380,20 @@ public class Mathematics { return (!Double.isInfinite(v) && !Double.isNaN(v)); } + /** + * Check if all numbers are valid (not NaN) and finite. Returns + * -1 if this is the case or the index of the first row with an invalid number. + * + * @param v + * @return + */ + public static int areFinite(double[][] v) { + for (int i=0; i=0) return i; + } + return -1; + } + /** * Check if all numbers are valid (not NaN) and finite. Returns * -1 if this is the case or the index of the first invalid number. @@ -422,6 +437,19 @@ public class Mathematics { return true; } + /** + * Returns false if a column vector contains NaN, its squared sum is NaN or the + * absolute sum is smaller than 10^-18. + * + * @param d + * @return + */ + public static boolean isValidVec(double[][] d) { + for (int i=0; i= dat[0].length) { + System.err.println("Error, invalid column index " + i + " for data array with " + dat[0].length + " columns!"); + } + ArrayList matching = new ArrayList(5); + for (double[] row : dat) { + if (row[i]<=upper && row[i]>=lower) matching.add(row); + } + + return matching.toArray(new double[matching.size()][dat[0].length]); + } + + /** + * Retrieve a given number of columns from a double matrix. The given + * data array must have valid matrix dimensions (equal number of columns per row). + * + * @param filtered + * @param i + * @param j + * @return + */ + public static double[][] getCols(double[][] data, int ... cols) { + if (data==null || (data[0]==null)) return null; + int nCols = cols.length; + if (nCols>data[0].length) System.err.println("Error, mismatching column count in Mathematics.getCols!"); + double[][] ret = new double[data.length][cols.length]; + for (int i=0; i