001 package net.sf.cpsolver.ifs.solution; 002 003 import java.util.*; 004 005 import net.sf.cpsolver.ifs.model.*; 006 import net.sf.cpsolver.ifs.perturbations.*; 007 import net.sf.cpsolver.ifs.solver.*; 008 import net.sf.cpsolver.ifs.util.*; 009 010 /** 011 * Generic solution. 012 * <br><br> 013 * It consist from the model and information about current iteration and solution time. 014 * 015 * @see Model 016 * @see net.sf.cpsolver.ifs.solver.Solver 017 * 018 * @version 019 * IFS 1.1 (Iterative Forward Search)<br> 020 * Copyright (C) 2006 Tomáš Müller<br> 021 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 022 * Lazenska 391, 76314 Zlin, Czech Republic<br> 023 * <br> 024 * This library is free software; you can redistribute it and/or 025 * modify it under the terms of the GNU Lesser General Public 026 * License as published by the Free Software Foundation; either 027 * version 2.1 of the License, or (at your option) any later version. 028 * <br><br> 029 * This library is distributed in the hope that it will be useful, 030 * but WITHOUT ANY WARRANTY; without even the implied warranty of 031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 032 * Lesser General Public License for more details. 033 * <br><br> 034 * You should have received a copy of the GNU Lesser General Public 035 * License along with this library; if not, write to the Free Software 036 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 037 */ 038 039 public class Solution { 040 private static java.text.DecimalFormat sTimeFormat = new java.text.DecimalFormat("0.00",new java.text.DecimalFormatSymbols(Locale.US)); 041 042 private Model iModel; 043 private long iIteration = 0; 044 private double iTime = 0.0; 045 046 private boolean iBestComplete = false; 047 private Hashtable iBestInfo = null; 048 private long iBestIteration = -1; 049 private double iBestTime = -1; 050 private double iBestPerturbationsPenaly = -1.0; 051 private double iBestValue = 0; 052 053 private Vector iSolutionListeners = new FastVector(); 054 private PerturbationsCounter iPerturbationsCounter = null; 055 056 /** Constructor */ 057 public Solution(Model model) { 058 this(model, 0, 0.0); 059 } 060 061 /** Constructor */ 062 public Solution(Model model, long iteration, double time) { 063 iModel = model; 064 iIteration = iteration; 065 iTime = time; 066 } 067 068 /** Current iteration */ 069 public long getIteration() { 070 return iIteration; 071 } 072 073 /** The model associated with the solution */ 074 public Model getModel() { 075 return iModel; 076 } 077 078 /** Current solution time (time in seconds from the start of the solver) */ 079 public double getTime() { 080 return iTime; 081 } 082 083 /** Update time, increment current iteration */ 084 public void update(double time) { 085 iTime = time; iIteration++; 086 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 087 ((SolutionListener)i.nextElement()).solutionUpdated(this); 088 } 089 090 /** Initialization */ 091 public void init(Solver solver) { 092 iIteration=0; 093 iTime=0; 094 if (iModel!=null) iModel.init(solver); 095 iPerturbationsCounter = solver.getPerturbationsCounter(); 096 } 097 098 public String toString() { 099 return "Solution{\n model="+iModel+",\n iteration="+iIteration+",\n time="+iTime+"\n}"; 100 } 101 102 /** Solution information. It consits from info from the model which is associated with the solution, 103 * time, iteration, speed and infos from all solution listeners. 104 */ 105 public Hashtable getInfo() { 106 Hashtable ret=getModel().getInfo(); 107 if (getPerturbationsCounter()!=null) getPerturbationsCounter().getInfo(ret,getModel()); 108 ret.put("Time",sTimeFormat.format(getTime())+" sec"); 109 ret.put("Iteration",String.valueOf(getIteration())); 110 if (getTime()>0) ret.put("Speed",sTimeFormat.format((getIteration())/(double)getTime())+" it/s"); 111 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 112 ((SolutionListener)i.nextElement()).getInfo(this, ret); 113 return ret; 114 } 115 116 /** 117 * Extended solution information. 118 * Similar to {@link Solution#getInfo()}, but some more information (that is more expensive to compute) might be added. 119 * Also extended model information is added (see {@link Model#getExtendedInfo()}) into the resultant table. 120 */ 121 public Hashtable getExtendedInfo() { 122 Hashtable ret=getModel().getExtendedInfo(); 123 if (getPerturbationsCounter()!=null) getPerturbationsCounter().getInfo(ret,getModel()); 124 ret.put("Time",sTimeFormat.format(getTime())+" sec"); 125 ret.put("Iteration",String.valueOf(getIteration())); 126 if (getTime()>0) ret.put("Speed",sTimeFormat.format((getIteration())/(double)getTime())+" it/s"); 127 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 128 ((SolutionListener)i.nextElement()).getInfo(this, ret); 129 return ret; 130 } 131 132 /** Solution information. It consists from info from the model which is associated with the solution, 133 * time, iteration, speed and infos from all solution listeners. Only variables from the given set 134 * are included. 135 */ 136 public Hashtable getInfo(Vector variables) { 137 Hashtable ret=getModel().getInfo(variables); 138 if (getPerturbationsCounter()!=null) getPerturbationsCounter().getInfo(ret,getModel(),variables); 139 ret.put("Time",sTimeFormat.format(getTime())+" sec"); 140 ret.put("Iteration",String.valueOf(getIteration())); 141 if (getTime()>0) ret.put("Speed",sTimeFormat.format((getIteration())/(double)getTime())+" it/s"); 142 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 143 ((SolutionListener)i.nextElement()).getInfo(this, ret, variables); 144 return ret; 145 } 146 147 /** Info of the best ever found solution */ 148 public Hashtable getBestInfo() { return iBestInfo; } 149 /** Iteration when the best ever found solution was found */ 150 public long getBestIteration() { return (iBestIteration<0?getIteration():iBestIteration); } 151 /** Solution time when the best ever found solution was found */ 152 public double getBestTime() { return (iBestTime<0?getTime():iBestTime); } 153 /** Returns true, if all variables of the best ever solution found are assigned */ 154 public boolean isBestComplete() { return iBestComplete; } 155 /** Total value of the best ever found solution -- sum of all assigned values (see {@link Value#toDouble()}).*/ 156 public double getBestValue() { return iBestValue; } 157 /** Set total value of the best ever found solution */ 158 public void setBestValue(double bestValue) { iBestValue = bestValue; } 159 /** Perturbation penalty of the best ever found solution (see {@link PerturbationsCounter}) */ 160 public double getBestPerturbationsPenalty() { return iBestPerturbationsPenaly; } 161 162 /** Returns perturbation counter */ 163 public PerturbationsCounter getPerturbationsCounter() { return iPerturbationsCounter; } 164 165 /** Clear the best ever found solution */ 166 public void clearBest() { 167 getModel().clearBest(); 168 iBestInfo = null; 169 iBestTime = -1; 170 iBestIteration = -1; 171 iBestComplete = false; 172 iBestValue = 0; 173 iBestPerturbationsPenaly = -1.0; 174 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 175 ((SolutionListener)i.nextElement()).bestCleared(this); 176 } 177 178 /** Save the current solution as the best ever found solution (it also calls {@link Model#saveBest()}) */ 179 public void saveBest() { 180 getModel().saveBest(); 181 iBestInfo = getInfo(); 182 iBestTime = getTime(); 183 iBestIteration = getIteration(); 184 iBestComplete = getModel().nrUnassignedVariables()==0; 185 iBestValue = getModel().getTotalValue(); 186 iBestPerturbationsPenaly = (iPerturbationsCounter==null?0.0:iPerturbationsCounter.getPerturbationPenalty(getModel())); 187 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 188 ((SolutionListener)i.nextElement()).bestSaved(this); 189 } 190 191 /** Restore the best ever found solution into the current solution (it also calls {@link Model#restoreBest()})*/ 192 public void restoreBest() { 193 if (iBestInfo==null) return; 194 getModel().restoreBest(); 195 iTime = iBestTime; 196 iIteration = iBestIteration; 197 for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();) 198 ((SolutionListener)i.nextElement()).bestRestored(this); 199 } 200 201 /** Adds solution listner */ 202 public void addSolutionListener(SolutionListener listener) { 203 iSolutionListeners.addElement(listener); 204 } 205 /** Removes solution listener */ 206 public void removeSolutionListener(SolutionListener listener) { 207 iSolutionListeners.removeElement(listener); 208 } 209 }