diff --git a/src/eva2/gui/FunctionArea.java b/src/eva2/gui/FunctionArea.java index 0d086cd9..ec29e9b1 100644 --- a/src/eva2/gui/FunctionArea.java +++ b/src/eva2/gui/FunctionArea.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Date; +import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; @@ -57,9 +58,12 @@ public class FunctionArea extends DArea implements Serializable { private ScaledBorder m_Border; private boolean m_log = false; private boolean notifyNegLog = true; + private boolean m_legend = true; private int m_x; private int m_y; + private GraphPointSetLegend legendBox = null; + private DPointIcon m_CurrentPointIcon; /** * @@ -90,6 +94,16 @@ public class FunctionArea extends DArea implements Serializable { notifyNegLog = true; } + /** + * Set a legend for the function area. If null is given, the former legend is deactivated. + * + * @param lBox + */ + protected void setLegend(GraphPointSetLegend lBox) { + legendBox=lBox; + if (lBox!=null && m_legend) repaint(); + } + /** * Plot a circle icon to the function area which is annotated with a char and * a double value. @@ -172,7 +186,7 @@ public class FunctionArea extends DArea implements Serializable { popRep.setIcon(icon); addDElement(popRep); } - + /** * */ @@ -181,8 +195,8 @@ public class FunctionArea extends DArea implements Serializable { if ((m_PointSetContainer == null) || (m_PointSetContainer.size() == 0)) return ret; int minindex = getNearestGraphIndex(x, y); - ret = ((GraphPointSet) (m_PointSetContainer.get(minindex))).getInfoString(); - return ret; + if (minindex>=0) return ((GraphPointSet) (m_PointSetContainer.get(minindex))).getInfoString(); + else return "none"; } /** @@ -196,8 +210,7 @@ public class FunctionArea extends DArea implements Serializable { ret = ((GraphPointSet) (m_PointSetContainer.get(minindex))).isStatisticsGraph(); return ret; } - - + /** * */ @@ -209,20 +222,18 @@ public class FunctionArea extends DArea implements Serializable { DPoint point2 = null; double dist = 0; for (int i = 0; i < m_PointSetContainer.size(); i++) { - if (m_PointSetContainer.get(i)instanceof GraphPointSet) { - GraphPointSet pointset = (GraphPointSet) (m_PointSetContainer.get(i)); - point2 = pointset.getNearestDPoint(point1); - if (point2 == null) - continue; - if (point1 == null) - System.err.println("point1 == null"); + GraphPointSet pointset = m_PointSetContainer.get(i); + point2 = pointset.getNearestDPoint(point1); + if (point2 == null) + continue; + if (point1 == null) + System.err.println("point1 == null"); - dist = (point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y); - //System.out.println("dist="+dist+"i="+i); - if (dist < distmin) { - distmin = dist; - minindex = i; - } + dist = (point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y); + //System.out.println("dist="+dist+"i="+i); + if (dist < distmin) { + distmin = dist; + minindex = i; } } return minindex; @@ -350,7 +361,13 @@ public class FunctionArea extends DArea implements Serializable { } - /** + @Override + public void paint(Graphics g) { + super.paint(g); + if (legendBox!=null && (m_legend)) legendBox.paintIn(g, m_Border.getInnerRect(this)); + } + + /** * */ public void setConnectedPoint(double[] p, int graphLabel) { @@ -428,6 +445,7 @@ public class FunctionArea extends DArea implements Serializable { return; int GraphLabel = ((GraphPointSet) (this.m_PointSetContainer.get(index))).getGraphLabel(); clearGraph(GraphLabel); + updateLegend(); } /** @@ -439,6 +457,7 @@ public class FunctionArea extends DArea implements Serializable { return; int GraphLabel = ((GraphPointSet) (this.m_PointSetContainer.get(index))).getGraphLabel(); changeColorGraph(GraphLabel); + updateLegend(); } /** @@ -589,7 +608,7 @@ public class FunctionArea extends DArea implements Serializable { //setVisibleRectangle( 0.001, 0.001, 100000, 1000 ); setYScale(new Exp()); m_Border.setSrcdY(Math.log(10)); - ((java.text.DecimalFormat) m_Border.format_y).applyPattern("0.###E0"); + m_Border.applyPattern(false, "0.###E0"); m_log = true; } else { m_log = false; @@ -769,6 +788,14 @@ public class FunctionArea extends DArea implements Serializable { } if (FunctionArea.this.m_PointSetContainer.size() > 0) { + JMenuItem togLegend = new JMenuItem("Toggle legend"); + togLegend.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ee) { + toggleLegend(); + } + }); + GraphMenu.add(togLegend); + JMenuItem removeGraph = new JMenuItem("Remove graph"); removeGraph.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ee) { @@ -776,8 +803,7 @@ public class FunctionArea extends DArea implements Serializable { } }); GraphMenu.add(removeGraph); - } - if (FunctionArea.this.m_PointSetContainer.size() > 0) { + JMenuItem changecolorGraph = new JMenuItem("Change color"); changecolorGraph.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ee) { @@ -785,8 +811,7 @@ public class FunctionArea extends DArea implements Serializable { } }); GraphMenu.add(changecolorGraph); - } - if (FunctionArea.this.m_PointSetContainer.size() > 0) { + JMenuItem removePoint = new JMenuItem("Remove point"); removePoint.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ee) { @@ -795,36 +820,13 @@ public class FunctionArea extends DArea implements Serializable { }); GraphMenu.add(removePoint); } -// if (isStatisticsGraph(e.getX(),e.getY())==true) { -// if (getVar(e.getX(),e.getY())==false) { -// JMenuItem showVar = new JMenuItem("Show varianz "); -// showVar.addActionListener(new ActionListener() { -// // -// public void actionPerformed(ActionEvent ee) { -// setVar(m_x,m_y,true); -// } -// }); -// GraphMenu.add(showVar); - -// } -// else { -// JMenuItem hideVar = new JMenuItem("Hide varianz "); -// hideVar.addActionListener(new ActionListener() { -// // -// public void actionPerformed(ActionEvent ee) { -// setVar(m_x,m_y,false); -// } -// }); -// GraphMenu.add(hideVar); -// } -// } GraphMenu.show(FunctionArea.this, e.getX(), e.getY()); } } }); } - /** This method allows to add a selection listner to the PointIcon + /** This method allows to add a selection listener to the PointIcon * it should need more than one listener to this abstruse event * @param a The selection listener */ @@ -832,17 +834,37 @@ public class FunctionArea extends DArea implements Serializable { this.m_RefPointListener = a; } - /** This method returns the selection listner to the PointIcon + /** This method returns the selection listener to the PointIcon * @return InterfaceSelectionListener */ public InterfaceRefPointListener getRefPointSelectionListener() { return this.m_RefPointListener; } - /** This method allows to remove the selection listner to the PointIcon + /** This method allows to remove the selection listener to the PointIcon */ public void removeRefPointSelectionListeners() { this.m_RefPointListener = null; } + /** + * Recreate the legend object with the current point sets. + * + */ + public void updateLegend() { + GraphPointSetLegend lb = new GraphPointSetLegend(m_PointSetContainer); + setLegend(lb); + } + + /** + * Reset the legend clearing all information. + */ + public void clearLegend() { + setLegend(null); + } + + private void toggleLegend() { + m_legend=!m_legend; + repaint(); + } } diff --git a/src/eva2/gui/GraphPointSet.java b/src/eva2/gui/GraphPointSet.java index 91c09d4c..11067ff9 100644 --- a/src/eva2/gui/GraphPointSet.java +++ b/src/eva2/gui/GraphPointSet.java @@ -27,7 +27,7 @@ import java.util.Arrays; * */ public class GraphPointSet { - private String m_InfoString = "InfoString"; + private String m_InfoString = "Incomplete_Run"; private int m_GraphLabel; private int colorOffset = 0; private ArrayList m_PointSetContainer = new ArrayList(); diff --git a/src/eva2/gui/GraphPointSetLegend.java b/src/eva2/gui/GraphPointSetLegend.java new file mode 100644 index 00000000..ab1b3b45 --- /dev/null +++ b/src/eva2/gui/GraphPointSetLegend.java @@ -0,0 +1,118 @@ +package eva2.gui; + +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import wsi.ra.chart2d.SlimRect; +import eva2.tools.Pair; + +/** + * A class representing the legend of a plot. It is created from a list of GraphPointSets as + * used in FunctionArea. Painting is done in FunctionArea. As an alternative, an own frame + * could be created. + * + * @author mkron + * + */ +public class GraphPointSetLegend { + Pair[] legendEntries; + + public GraphPointSetLegend(List pointSetContainer) { + legendEntries = new Pair[pointSetContainer.size()]; + for (int i = 0; i < pointSetContainer.size(); i++) { + GraphPointSet pointset = pointSetContainer.get(i); + legendEntries[i] = new Pair(pointset.getInfoString(), pointset.getColor()); + } + } + + /** + * Add the legend labels to a container. + * @param comp + */ + public void addToContainer(JComponent comp) { + for (int i = 0; i < legendEntries.length; i++) { + JLabel label = new JLabel(legendEntries[i].head); + label.setForeground(legendEntries[i].tail); + comp.add(label); + } + } + + public static JPanel makeLegendPanel(Color bgCol, ArrayList pointSetContainer) { + JPanel pan = new JPanel(); + pan.setBackground(bgCol); + pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS)); + GraphPointSetLegend lBox=new GraphPointSetLegend(pointSetContainer); + lBox.addToContainer(pan); + return pan; + } + + public static JFrame makeLegendFrame(Color bgCol, ArrayList pointSetContainer) { + JFrame frame = new JFrame("Legend"); +// LegendBox lBox = new LegendBox(bgCol, pointSetContainer); + frame.add(makeLegendPanel(bgCol, pointSetContainer)); + frame.pack(); + frame.setVisible(true); + return frame; + } + + public void paintIn(JComponent component) { + Graphics g = component.getGraphics(); + FontMetrics fm = g.getFontMetrics(); + int yOffs=5+fm.getHeight(); + int xOffs=0; + Color origCol = g.getColor(); + + for (int i=0; i textListeners; @@ -121,11 +136,17 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter initOutput(infoString); bestIndividualAllover = null; meanBestOfRunFitness = null; + meanBestFeasibleFit = null; if (refineMultiRuns) meanCollection = new ArrayList(); else meanCollection = null; + feasibleFoundAfterSum=-1; + numOfRunsFeasibleFound=0; } + feasibleFoundAfter=-1; bestCurrentIndividual = null; bestRunIndividual = null; + currentBestFeasibleFit=null; + bestRunFeasibleIndy = null; runIterCnt = 0; if (printRunIntroVerbosity()) printToTextListener("\n****** Multirun "+runNumber); if (params != null) { @@ -165,6 +186,32 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter meanBestOfRunFitness=bestRunIndividual.getFitness().clone(); } else addMean(meanBestOfRunFitness, bestRunIndividual.getFitness()); } + if (feasibleFoundAfter>0) { + if (printRunStoppedVerbosity()) printToTextListener(" Feasible ind. found after " + feasibleFoundAfter + " evaluations.\n"); + } else { + if (printRunStoppedVerbosity()) printToTextListener(" NO feasible individual found.\n"); + } + if (bestRunFeasibleIndy != null) { + if (meanBestFeasibleFit==null) { + meanBestFeasibleFit=currentBestFeasibleFit.clone(); + } else addMean(meanBestFeasibleFit, currentBestFeasibleFit); + if (printRunStoppedVerbosity()) { + if ((bestRunFeasibleIndy instanceof AbstractEAIndividual) && ((AbstractEAIndividual)bestRunFeasibleIndy).equalGenotypes((AbstractEAIndividual)bestRunIndividual)) { + printToTextListener(" Run best feasible individual equals best individual.\n"); + } else { + if (bestRunFeasibleIndy instanceof AbstractEAIndividual) { + if (((AbstractEAIndividual)bestRunIndividual).violatesConstraint()) + printToTextListener(" Run best individual violates constraints by " + ((AbstractEAIndividual)bestRunIndividual).getConstraintViolation() + "\n"); + if (((AbstractEAIndividual)bestRunIndividual).isMarkedPenalized()) + printToTextListener(" Run best individual is penalized.\n"); + } + + printToTextListener(" Run best feasible ind.: " + BeanInspector.toString(bestRunFeasibleIndy) + "\n"); + printToTextListener(" Feas. solution data : " + AbstractEAIndividual.getDefaultDataString(bestRunFeasibleIndy) + "\n"); + printToTextListener(" Feas. solution fit : " + BeanInspector.toString(bestRunFeasibleIndy.getFitness()) + "\n"); + } + } + } // if (currentBestFit!= null) { // if (printRunStoppedVerbosity()) printToTextListener(" Best Fitness: " + BeanInspector.toString(currentBestFit) + "\n"); // } @@ -174,6 +221,12 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter protected void finalizeOutput() { if (printFinalVerbosity()) printToTextListener("*******\n Runs performed: " + optRunsPerformed + ", reached target " + convergenceCnt + " times with threshold " + m_StatsParams.getConvergenceRateThreshold() + ", rate " + convergenceCnt/(double)m_StatsParams.getMultiRuns() + '\n'); if (printFinalVerbosity()) printToTextListener(" Average function calls: " + (functionCallSum/optRunsPerformed) + "\n"); + + if (printFinalVerbosity() && (feasibleFoundAfterSum>=0.)) { + printToTextListener(" Feasible solution found in " + numOfRunsFeasibleFound + " of " + optRunsPerformed + " runs \n"); + printToTextListener(" Average evaluations until feasible ind. was found in " + numOfRunsFeasibleFound + " runs: " + feasibleFoundAfterSum/numOfRunsFeasibleFound + " evaluations\n"); + } + if (printFinalVerbosity() && (bestIndividualAllover != null)) printToTextListener(" Overall best individual: " + BeanInspector.toString(bestIndividualAllover) + '\n'); if (printFinalVerbosity() && (bestIndividualAllover != null)) printToTextListener(" Overall solution data : " + AbstractEAIndividual.getDefaultDataString(bestIndividualAllover) + '\n'); if (printFinalVerbosity() && (bestIndividualAllover != null)) printToTextListener(" Overall solution fit : " + BeanInspector.toString(bestIndividualAllover.getFitness()) + '\n'); @@ -181,7 +234,13 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter if (meanBestOfRunFitness!=null) { Mathematics.svDiv((double)optRunsPerformed, meanBestOfRunFitness, meanBestOfRunFitness); if (printFinalVerbosity()) { - printToTextListener(" Averaged best fitness per run: " + BeanInspector.toString(meanBestOfRunFitness)+"\n"); + printToTextListener(" Average best fitness per run: " + BeanInspector.toString(meanBestOfRunFitness)+"\n"); + } + } + if (meanBestFeasibleFit!=null) { + Mathematics.svDiv((double)numOfRunsFeasibleFound, meanBestFeasibleFit, meanBestFeasibleFit); + if (printFinalVerbosity()) { + printToTextListener(" Average best feasible fitness in " + numOfRunsFeasibleFound + " runs: " + BeanInspector.toString(meanBestFeasibleFit)+"\n"); } } if (refineMultiRuns && (meanCollection != null)) { @@ -298,6 +357,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter functionCalls = calls; currentBestFit = bestfit; currentWorstFit = worstfit; + currentBestFeasibleFit = null; meanFitness = null; if (firstPlot) { @@ -336,6 +396,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter initPlots(m_StatsParams.getPlotDescriptions()); // if (doTextOutput()) printToTextListener(getOutputHeader(informer, pop)+'\n'); firstPlot = false; + currentBestFeasibleFit=null; } if ((runIterCnt==0) && printHeaderByVerbosity()) printToTextListener(getOutputHeader(informerList, pop)+'\n'); @@ -361,6 +422,23 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter if (currentBestFit == null) { System.err.println("BestFitness==null !"); } + if (pop instanceof Population) { + AbstractEAIndividual curBestFeasible = ((Population)pop).getBestFeasibleIndividual(-1); + + if (curBestFeasible!=null) { // a feasible ind. was found! + if (currentBestFeasibleFit==null) { // feasible indy found for the first time + numOfRunsFeasibleFound++; + feasibleFoundAfter=((Population)pop).getFunctionCalls(); + if (feasibleFoundAfterSum<0) feasibleFoundAfterSum=0.; // initial signalling value was -1. + feasibleFoundAfterSum+=feasibleFoundAfter; + } + currentBestFeasibleFit = curBestFeasible.getFitness().clone(); + if ((bestRunFeasibleIndy==null) || (secondIsBetter(bestRunFeasibleIndy, curBestFeasible))) { + bestRunFeasibleIndy=curBestFeasible; + } + } + } + meanFitness = pop.getMeanFitness().clone(); currentWorstFit = pop.getWorstIndividual().getFitness().clone(); functionCalls = pop.getFunctionCalls(); diff --git a/src/eva2/server/stat/StatisticsWithGUI.java b/src/eva2/server/stat/StatisticsWithGUI.java index 6c8e3237..2190d1a2 100644 --- a/src/eva2/server/stat/StatisticsWithGUI.java +++ b/src/eva2/server/stat/StatisticsWithGUI.java @@ -18,20 +18,21 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.List; +import wsi.ra.jproxy.MainAdapterClient; +import wsi.ra.jproxy.RMIProxyLocal; +import wsi.ra.jproxy.RMIProxyRemote; import eva2.gui.BeanInspector; import eva2.gui.Graph; import eva2.gui.GraphWindow; import eva2.gui.JTextoutputFrame; import eva2.gui.JTextoutputFrameInterface; +import eva2.gui.Plot; +import eva2.gui.PlotInterface; import eva2.server.EvAServer; import eva2.server.go.PopulationInterface; import eva2.server.go.problems.InterfaceAdditionalPopulationInformer; import eva2.tools.EVAERROR; -import wsi.ra.jproxy.MainAdapterClient; -import wsi.ra.jproxy.RMIProxyLocal; -import wsi.ra.jproxy.RMIProxyRemote; - /*==========================================================================* * CLASS DECLARATION *==========================================================================*/ @@ -105,39 +106,48 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl // m_TextCounter = m_StatisticsParameter.GetTextoutput(); m_PlotCounter = m_StatsParams.GetPlotoutput(); + if ((m_FitnessFrame!=null) && (m_FitnessFrame[0]!=null)) { + PlotInterface p = m_FitnessFrame[0].getPlotter(); + if ((p!=null) && p.isValid()) ((Plot)p).getFunctionArea().clearLegend(); + } } public void stopOptPerformed(boolean normal, String stopMessage) { super.stopOptPerformed(normal, stopMessage); - + if (optRunsPerformed > m_StatsParams.getMultiRuns()) { // this may happen if the user reduces the multirun parameter during late multiruns System.err.println("error: more runs performed than defined."); } + + int fullRuns=optRunsPerformed; + if (!normal) fullRuns--; + // unite the graphs only if the break was "normal" - if (normal && (m_StatsParams.getMultiRuns() > 1) && (m_StatGraph != null)) { + if ((m_StatsParams.getMultiRuns() > 1) && (m_StatGraph != null)) { // unite the point sets for a multirun for (int i = 0; i < m_FitnessGraph.length; i++) { for (int j = 0; j < m_FitnessGraph[i].length; j++) { - if (m_FitnessFrame[i].isValid()) { + m_StatGraph[i][j].setInfoString( + (m_FitnessGraph[i][j].getInfo().length() > 0 ? (m_FitnessGraph[i][j].getInfo() + "_") : "" ) + + (m_StatsParams.GetInfoString().length() > 0 ? (m_StatsParams.GetInfoString() + "_") : "" ) + + m_StatsParams.GetInfoString() + + "Mean_of_" + fullRuns + " ", + (float) 2.0); + if (normal && m_FitnessFrame[i].isValid()) { m_StatGraph[i][j].addGraph(m_FitnessGraph[i][j]); - m_StatGraph[i][j].setInfoString( - (m_FitnessGraph[i][j].getInfo().length() > 0 ? (m_FitnessGraph[i][j].getInfo() + "_") : "" ) - + (m_StatsParams.GetInfoString().length() > 0 ? (m_StatsParams.GetInfoString() + "_") : "" ) - + m_StatsParams.GetInfoString() - + "Mean_of_" + optRunsPerformed + " ", - (float) 2.0); m_FitnessGraph[i][j].clear(); } } } } - // this is inconsistent, shouldnt be necessary here but reset in startOpt... -// if (optRunsPerformed == m_StatisticsParameter.getMultiRuns()) { -// finalizeRuns(m_ConvergenceCnt); -// m_OptRunsPerformed = 0; -// m_ConvergenceCnt = 0; -// } + PlotInterface p = m_FitnessFrame[0].getPlotter(); + if ((optRunsPerformed >= m_StatsParams.getMultiRuns()) || !normal) { + // update the legend after the last multirun or after a user break + if ((p!=null) && p.isValid()) { + ((Plot)p).getFunctionArea().updateLegend(); + } + } } public void maybeShowProxyPrinter() { @@ -149,13 +159,13 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl maybeShowProxyPrinter(); int graphCount = description.size(); - +// System.out.println("Initializing " + graphCount + " plots (StatisticsWithGUI)"); m_FitnessFrame = new GraphWindow[graphCount]; for (int i = 0; i < m_FitnessFrame.length; i++) { // m_FitnessFrame[i] = GraphWindow.getInstance(m_MainAdapterClient, m_GraphInfoString + " " + i + " " + " on " + m_MyHostName + ", VM " + EvAServer.m_NumberOfVM, "function calls", "fitness"); m_FitnessFrame[i] = GraphWindow.getInstance(m_MainAdapterClient, "Optimization " + i + " " + " on " + m_MyHostName + ", VM " + EvAServer.m_NumberOfVM, "function calls", "fitness"); } - + m_FitnessGraph = new Graph[graphCount][]; // contains one graph for every value to be plotted (best / worst / best+worst) // TODO Im really not sure why this is a 2-dimensional array. shouldnt one be enough? @@ -163,7 +173,7 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl m_FitnessGraph[i] = new Graph[((String[]) description.get(i)).length]; for (int j = 0; j < m_FitnessGraph[i].length; j++) { String[] d = (String[]) description.get(i); - // this is where the column string for ascii export is created! + // this is where the column string for ascii export is created! Uah! m_FitnessGraph[i][j] = m_FitnessFrame[i].getNewGraph(d[j] + "_" + m_StatsParams.GetInfoString() + @@ -215,12 +225,20 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl m_PlotCounter = m_StatsParams.GetPlotoutput(); boolean doPlotBest = (fitnessplot_setting == StatsParameter.PLOT_BEST) || (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_WORST) + || (fitnessplot_setting == StatsParameter.PLOT_CURBEST_AND_RUNBEST) || (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_MEASURES); boolean doPlotWorst = (fitnessplot_setting == StatsParameter.PLOT_WORST) || (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_WORST); boolean doPlotMeasures = (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_MEASURES); + boolean doPlotBestFeasible = false; + // TODO <-- das hier besser? +// Oder erstmal ganz weg und dafür gesamtergebnis berechnen (textfenster) +// ZB: wie oft wurde feasible sol. gefunden (analog convergence counter) +// Durchschnitt: erste feasible sol., fitness der feasible sol... + int subGraph=0; if (doPlotBest) { - plotFitnessPoint(0, 0, functionCalls, currentBestFit[0]); + plotFitnessPoint(0, subGraph++, functionCalls, currentBestFit[0]); + if (fitnessplot_setting == StatsParameter.PLOT_CURBEST_AND_RUNBEST) plotFitnessPoint(0, subGraph++, functionCalls, bestRunIndividual.getFitness()[0]); } if (doPlotWorst) { // schlechteste Fitness plotten @@ -229,11 +247,14 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl System.err.println("m_WorstFitness==null in plotStatisticsPerformed"); return; } - plotFitnessPoint(0, (doPlotBest ? 1 : 0) , functionCalls, currentWorstFit[0]); + plotFitnessPoint(0, subGraph++ , functionCalls, currentWorstFit[0]); } if (doPlotMeasures) { - plotFitnessPoint(0, 1, functionCalls, avgPopDist); - plotFitnessPoint(0, 2, functionCalls, maxPopDist); + plotFitnessPoint(0, subGraph++, functionCalls, avgPopDist); + plotFitnessPoint(0, subGraph++, functionCalls, maxPopDist); + } + if (doPlotBestFeasible && currentBestFeasibleFit!=null) { + plotFitnessPoint(0, subGraph++, functionCalls, currentBestFeasibleFit[0]); } } } diff --git a/src/eva2/server/stat/StatsParameter.java b/src/eva2/server/stat/StatsParameter.java index f29b0041..84c8e262 100644 --- a/src/eva2/server/stat/StatsParameter.java +++ b/src/eva2/server/stat/StatsParameter.java @@ -33,11 +33,13 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl public final static int PLOT_WORST = 1; public final static int PLOT_BEST_AND_WORST = 2; public final static int PLOT_BEST_AND_MEASURES = 3; + public final static int PLOT_CURBEST_AND_RUNBEST = 4; public final static Tag[] TAGS_PLOT_FITNESS = { new Tag(PLOT_BEST, "plot best fitness"), new Tag(PLOT_WORST, "plot worst fitness"), new Tag(PLOT_BEST_AND_WORST, "both best and worst"), - new Tag(PLOT_BEST_AND_MEASURES, "both best and population measures") + new Tag(PLOT_BEST_AND_MEASURES, "both best and population measures"), + new Tag(PLOT_CURBEST_AND_RUNBEST, "current best and best of run") }; public final static int VERBOSITY_NONE = 0; @@ -113,7 +115,9 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl case StatsParameter.PLOT_BEST_AND_MEASURES: desc.add(new String[] {"Best", "AvgDist", "MaxDist"}); break; - } + case StatsParameter.PLOT_CURBEST_AND_RUNBEST: + desc.add(new String[] {"Cur.Best", "Run Best"}); + break; } return desc; } diff --git a/src/wsi/ra/chart2d/DArea.java b/src/wsi/ra/chart2d/DArea.java index 414699f1..70ed7d01 100644 --- a/src/wsi/ra/chart2d/DArea.java +++ b/src/wsi/ra/chart2d/DArea.java @@ -88,11 +88,10 @@ private static final boolean TRACE = false; * the measures of the area * it calculates the coordinates */ - private DMeasures measures; - + protected DMeasures measures; private DBorder dborder = new DBorder(); - + /** * initializes the DArea with the initial capacity of 10 components */ @@ -142,6 +141,7 @@ private static final boolean TRACE = false; if( max_y != null ) srect.height = Math.min(srect.height, getMaxY() - getMinY()); return srect; } + /** * switches the auto focus of this DArea on or off * @@ -406,16 +406,20 @@ private static final boolean TRACE = false; if( auto_focus ) { container.restore(); visible_rect = (DRectangle)container.getRectangle().clone(); +// grid.updateDistByRect(visible_rect); + } + if( visible_rect.isEmpty() ) { + visible_rect = (DRectangle)min_rect.clone(); +// grid.updateDistByRect(visible_rect); } - if( visible_rect.isEmpty() ) visible_rect = (DRectangle)min_rect.clone(); super.paint( g ); - + measures.setGraphics( g ); if( grid.isVisible() && !grid_to_front ) paintGrid( measures ); container.paint( measures ); - if( grid.isVisible() && grid_to_front ) paintGrid( measures ); + if( grid.isVisible() && grid_to_front ) paintGrid( measures ); } - + /** * repaints a part of the visible area * @@ -685,8 +689,8 @@ private static final boolean TRACE = false; return; } else{ - grid.hor_dist = ScaledBorder.aBitBigger( grid.rectangle.width / max_grid ); - grid.ver_dist = ScaledBorder.aBitBigger( grid.rectangle.height / max_grid ); + grid.setDistances(ScaledBorder.aBitBigger( grid.rectangle.width / max_grid ), + ScaledBorder.aBitBigger( grid.rectangle.height / max_grid )); } } grid.paint( m ); @@ -704,8 +708,7 @@ private static final boolean TRACE = false; if( TRACE ) System.out.println("DArea.paintGrid(ScaledBorder, DMeasures)"); Dimension d = getSize(); FontMetrics fm = m.getGraphics().getFontMetrics(); - grid.hor_dist = sb.getSrcdX(fm, d); - grid.ver_dist = sb.getSrcdY(fm, d); + grid.setDistances(sb.getSrcdX(fm, d), sb.getSrcdY(fm, d)); if( m.x_scale == null && m.y_scale == null ) grid.paint( m ); @@ -716,10 +719,10 @@ private static final boolean TRACE = false; SlimRect rect = getSlimRectangle(); SlimRect src_rect = m.getSourceOf( rect ); - int x = (int)(src_rect.x / grid.hor_dist), - y = (int)(src_rect.y / grid.ver_dist); - if( x * grid.hor_dist < src_rect.x ) x++; - if( y * grid.ver_dist < src_rect.y ) y++; + int x = (int)(src_rect.x / grid.getHorDist()), + y = (int)(src_rect.y / grid.getVerDist()); + if( x * grid.getHorDist() < src_rect.x ) x++; + if( y * grid.getVerDist() < src_rect.y ) y++; // DPoint min = new DPoint( rect.x, rect.y ), // max = new DPoint( min.x + rect.width, min.y + rect.height ); @@ -727,14 +730,14 @@ private static final boolean TRACE = false; double pos; - for( ; (pos = x * grid.hor_dist) < src_rect.x + src_rect.width; x++ ){ + for( ; (pos = x * grid.getHorDist()) < src_rect.x + src_rect.width; x++ ){ if( m.x_scale != null ) pos = m.x_scale.getImageOf( pos ); Point p1 = m.getPoint( pos, miny ), p2 = m.getPoint( pos, maxy ); g.drawLine( p1.x, p1.y, p2.x, p2.y ); } - for( ; (pos = y * grid.ver_dist) < src_rect.y + src_rect.height; y++ ){ + for( ; (pos = y * grid.getVerDist()) < src_rect.y + src_rect.height; y++ ){ if( m.y_scale != null ) pos = m.y_scale.getImageOf( pos ); Point p1 = m.getPoint( minx, pos ), p2 = m.getPoint( maxx, pos ); diff --git a/src/wsi/ra/chart2d/DGrid.java b/src/wsi/ra/chart2d/DGrid.java index 2dc967d9..479ce544 100644 --- a/src/wsi/ra/chart2d/DGrid.java +++ b/src/wsi/ra/chart2d/DGrid.java @@ -31,7 +31,7 @@ public class DGrid extends DComponent /** * the distances between the lines */ - double hor_dist, ver_dist; + private double hor_dist, ver_dist; private Color DEFAULT_COLOR = Color.lightGray; @@ -68,7 +68,20 @@ public class DGrid extends DComponent this.ver_dist = ver_dist; this.color = color; } + + public void setDistances(double hor, double ver) { + hor_dist=hor; + ver_dist=ver; +// System.out.println("set new Grid distances " + this.toString()); + } + public double getHorDist() { + return hor_dist; + } + + public double getVerDist() { + return ver_dist; + } /** * paints the grid... * @@ -84,7 +97,7 @@ public class DGrid extends DComponent minX = (int)( rectangle.x / hor_dist ); if( minX * hor_dist <= rectangle.x ) minX++; minX *= hor_dist; - minY = (int)( rectangle.y / ver_dist ); + minY = ( rectangle.y / ver_dist ); if( minY * ver_dist <= rectangle.y ) minY++; minY *= ver_dist; @@ -98,16 +111,32 @@ public class DGrid extends DComponent p1.x = rectangle.x; p2.x = p1.x + rectangle.width; - for( pos = minY; pos<=rectangle.y + rectangle.height; pos += ver_dist ){ + pos = minY; + while ( pos<=rectangle.y + rectangle.height){ p1.y = p2.y = pos; l = new DLine( p1, p2, color ); l.paint( m ); + if (pos+ver_dist<=pos) { + System.err.println("Overflow error in DGrid!"); + pos *= 1.01; + } else pos += ver_dist; +// System.out.println("pos is " + pos + ", loop until " + rectangle.y + rectangle.height); } } public String toString(){ return "chart2d.DGrid[ hor: "+hor_dist+", ver: "+ver_dist+" ]"; } + +// public void updateDistByRect(DRectangle rect) { +// System.out.println(rect); +// if (!rect.isEmpty() && (hor_dist>0 && ver_dist>0)) { +// double horRatio = Math.abs(rectangle.x)/hor_dist; +// double verRatio = Math.abs(rectangle.y)/ver_dist; +//// rectangle = visRect; +// setDistances(rect.x*horRatio, rect.y*verRatio); +// } +// } } /**************************************************************************** diff --git a/src/wsi/ra/chart2d/ScaledBorder.java b/src/wsi/ra/chart2d/ScaledBorder.java index 17c166ac..0e3ff5d7 100644 --- a/src/wsi/ra/chart2d/ScaledBorder.java +++ b/src/wsi/ra/chart2d/ScaledBorder.java @@ -1,23 +1,5 @@ -/** - * Filename: $RCSfile: ScaledBorder.java,v $ - * Purpose: - * Language: Java - * Compiler: JDK 1.3 - * Authors: Fabian Hennecke - * Version: $Revision: 1.1.1.1 $ - * $Date: 2003/07/03 14:59:42 $ - * $Author: ulmerh $ - * Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany - */ - - - package wsi.ra.chart2d; -/*==========================================================================* - * IMPORTS - *==========================================================================*/ - import java.awt.* ; import javax.swing.BorderFactory; import javax.swing.border.* ; @@ -25,13 +7,9 @@ import java.awt.geom.AffineTransform ; import java.text.NumberFormat; import java.text.DecimalFormat; -/*==========================================================================* - * CLASS DECLARATION - *==========================================================================*/ - /** * ScaledBorder puts an border around Components - * ( especially around DrawingAreas ) with scaled and labeled axes + * ( especially around DrawingAreas ) with scaled and labeled axes. */ public class ScaledBorder implements Border { @@ -125,7 +103,7 @@ public class ScaledBorder implements Border * formatters of the x- and y-axis numbers * @see java.text.NumberFormat */ - public NumberFormat format_x = new DecimalFormat(), + private NumberFormat format_x = new DecimalFormat(), format_y = new DecimalFormat(); private double src_dX = -1, src_dY = -1; @@ -195,6 +173,22 @@ public class ScaledBorder implements Border src_dY = dY; } + /** + * Returns the inner rectangle in pixel coordinates. + * + * @param c + * @return + */ + public SlimRect getInnerRect(Component c) { + Insets inner_insets = getBorderInsets(c); + Dimension d = c.getSize(); + int width = d.width - inner_insets.left - inner_insets.right; + int height = d.height - inner_insets.top - inner_insets.bottom; + + SlimRect rect=new SlimRect(inner_insets.left, inner_insets.top, width, height); + return rect; + } + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height){ if( under_construction ) System.out.println("ScaledBorder.paintBorder()"); if( foreground == null ) foreground = c.getForeground(); @@ -280,48 +274,68 @@ public class ScaledBorder implements Border inner_insets.top + cd.height ); } - drawYValues( g, inner_insets, cd ); + drawYValues( g, inner_insets); drawXValues( g, inner_insets, cd ); g.setColor( old_color ); } + + /** + * The scaling of the y-axis is defined here. + * + * @param g + * @param insets + */ + private void drawYValues( Graphics g, Insets insets){ + if( under_construction ) System.out.println("ScaledBorder.drawYValues()"); - private void drawYValues( Graphics g, Insets insets, Dimension cd ){ - if( under_construction ) System.out.println("ScaledBorder.drawYValues()"); - - FontMetrics fm = g.getFontMetrics(); - int n, fontAsc = fm.getAscent(), v2m = fm.stringWidth("0") / y_values2marker; - n = (int)( src_rect.y / src_dY ); - if( n * src_dY < src_rect.y || ( src_rect.x == 0 && src_rect.y == 0 ) ) n++; - - - double v, minx = src_rect.x; - if( x_scale != null ) minx = x_scale.getImageOf( minx ); - for(; (v = n * src_dY) <= src_rect.y + src_rect.height; n++ ){ - if( y_scale != null ) v = y_scale.getImageOf( v ); - String text = format_y.format(v); - try{ v = format_y.parse(text).doubleValue(); } - catch( java.text.ParseException ex ){ } - Point p = m.getPoint( minx, v ); - if( p != null ){ - g.drawString( text, - insets.left - fm.stringWidth( text ) - v2m - marker_length, - p.y + fontAsc / 2 ); - g.drawLine( insets.left - marker_length, p.y, insets.left, p.y ); - } - } + FontMetrics fm = g.getFontMetrics(); + int fontAsc = fm.getAscent(), v2m = fm.stringWidth("0") / y_values2marker; + int n = (int)( src_rect.y / src_dY ); +// if( n * src_dY < src_rect.y || ( src_rect.x == 0 && src_rect.y == 0 ) ) n++; + if( n * src_dY < src_rect.y || ( src_rect.x == 0 && src_rect.y == 0 ) ) { + if (n+1 > n) n++; + else System.err.println("Overflow error A in ScaledBorder!"); + } + + double v, scaledV, minx = src_rect.x; + if( x_scale != null ) minx = x_scale.getImageOf( minx ); + v = n * src_dY; + while (v <= src_rect.y + src_rect.height){ + if( y_scale != null ) scaledV = y_scale.getImageOf( v ); + else scaledV=v; + String text = format_y.format(scaledV); + try{ scaledV = format_y.parse(text).doubleValue(); } + catch( java.text.ParseException ex ){ } + Point p = m.getPoint( minx, scaledV ); + if( p != null ){ + g.drawString( text, + insets.left - fm.stringWidth( text ) - v2m - marker_length, + p.y + fontAsc / 2 ); + g.drawLine( insets.left - marker_length, p.y, insets.left, p.y ); + } + if (v+src_dY<= v) { + System.err.println("Overflow error B in ScaledBorder!"); + v*=1.01; + } + v += src_dY; + } } public double getSrcdY( FontMetrics fm, Dimension cd ){ - if( under_construction ) System.out.println("ScaledBorder.getSrcdY()"); - if( (!do_refresh && src_dY != -1) || !auto_scale_y ) return src_dY; - int max = cd.height / fm.getHeight(); - double minsrc_dY = 2 * src_rect.height / (double)max; // die 2 einfach mal so eingesetzt <-------------------------- - src_dY = aBitBigger( minsrc_dY ); - if( src_dY < minimal_increment ) src_dY = minimal_increment; - return src_dY; + return getSrcdY(fm.getHeight(), cd.height); } + public double getSrcdY( int fontMetricsHeight, int componentHeight ){ + if( under_construction ) System.out.println("ScaledBorder.getSrcdY()"); + if( (!do_refresh && src_dY != -1) || !auto_scale_y ) return src_dY; + int max = componentHeight / fontMetricsHeight; + double minsrc_dY = 2 * src_rect.height / (double)max; // die 2 einfach mal so eingesetzt <-------------------------- + src_dY = aBitBigger( minsrc_dY ); + if( src_dY < minimal_increment ) src_dY = minimal_increment; + return src_dY; + } + private void drawXValues( Graphics g, Insets insets, Dimension cd ){ if( under_construction ) System.out.println("ScaledBorder.drawXValues()"); @@ -418,11 +432,19 @@ public class ScaledBorder implements Border public boolean isBorderOpaque(){ return outer_border.isBorderOpaque(); } -// -// private String stringOf( double v ){ -// if( (int)v == v ) return String.valueOf( (int)v ); -// return String.valueOf( v ); -// } + + /** + * Apply a decimal format pattern to x (bXorY true) or y (bXorY false) axis. + * + * @see #java.text.DecimalFormat.applyPattern + * + * @param bXorY + * @param pattern + */ + public void applyPattern(boolean bXorY, String pattern) { + if (bXorY) ((java.text.DecimalFormat)format_x).applyPattern(pattern); + else ((java.text.DecimalFormat)format_y).applyPattern(pattern); + } public Insets getBorderInsets(Component c){ if( under_construction ) System.out.println("ScaledBorder.getBorderInsets()"); @@ -452,17 +474,24 @@ public class ScaledBorder implements Border if( y_label != null ) insets.left += fm.getAscent() + fm.getDescent(); insets.left += y_label2values * digit_width; getSrcdY( fm, c.getSize() ); - int n, maxWidth = 0; - n = (int)( src_rect.y / src_dY ); - if( n * src_dY < src_rect.y ) n++; - while( n * src_dY <= src_rect.y + src_rect.height ){ + double start, n, inc; + int maxWidth = 0; + start = src_dY*(int)( src_rect.y / src_dY ); + n=start; + if ( n < src_rect.y ) n+=src_dY; + + if (((src_rect.y + src_rect.height)-start)>20) inc = ((src_rect.y + src_rect.height)- start)/20.; + else inc = src_dY; + + for (; n <= src_rect.y + src_rect.height; n+=inc ){ // TODO here might be a bug for mean values - double v = n * src_dY; + double v = n; if( y_scale != null ) v = y_scale.getImageOf( v ); int w = fm.stringWidth( format_y.format(v) ); if( w > maxWidth ) maxWidth = w; - n++; + // avoid nearly endless loop for large src_rect.y value and small src_dY } + insets.left += 1 + y_label2border + maxWidth + digit_width / y_values2marker + marker_length; // bottom: @@ -477,9 +506,9 @@ public class ScaledBorder implements Border if( show_arrows ) insets.right += x_values2arrow + arrow_length; insets.right += axis2border; getSrcdX( fm, c.getSize() ); - n = (int)( src_rect.x + src_rect.width / src_dX ); - if( n < 0 ) n ++; - int w = fm.stringWidth( format_x.format(n * src_dX) ); + int k = (int)( src_rect.x + src_rect.width / src_dX ); + if( k < 0 ) k ++; + int w = fm.stringWidth( format_x.format(k * src_dX) ); if( w / 2 > insets.right ) insets.right = w / 2; old_insets = insets; diff --git a/src/wsi/ra/chart2d/SlimRect.java b/src/wsi/ra/chart2d/SlimRect.java index 59741642..47ac5269 100644 --- a/src/wsi/ra/chart2d/SlimRect.java +++ b/src/wsi/ra/chart2d/SlimRect.java @@ -116,4 +116,19 @@ public class SlimRect { public boolean hasEmptyIntersection(SlimRect r){ return (getIntersection(r)==null); } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getWidth() { + return width; + } + public double getHeight() { + return height; + } }