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 }