    001    package ifs.solution;
    002
    003    import ifs.model.*;
    004    import ifs.solver.*;
    005    import ifs.util.*;
    006    import ifs.perturbations.*;
    007    import java.util.*;
    008
    009    /**
    010     * Generic solution.
    011     * <br><br>
    012     * It consist from the model and information about current iteration and solution time.
    013     *
    014     * @see Model
    015     * @see ifs.solver.Solver
    016     *
    017     * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
    018     * @version 1.0
    019     */
    020
    021    public class Solution {
    022        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(Solution.class);
    023        private static java.text.DecimalFormat sTimeFormat = new java.text.DecimalFormat("0.00",new java.text.DecimalFormatSymbols(Locale.US));
    024
    025        private Model iModel;
    026        private long iIteration = 0;
    027        private double iTime = 0.0;
    028
    029        private boolean iBestComplete = false;
    030        private Hashtable iBestInfo = null;
    031        private long iBestIteration = -1;
    032        private double iBestTime = -1;
    033        private double iBestPerturbationsPenaly = -1.0;
    034        private int iBestValue = 0;
    035        private int iBestPertirbations = -1;
    036
    037        private Vector iSolutionListeners = new FastVector();
    038        private PerturbationsCounter iPerturbationsCounter = null;
    039
    040        /** Constructor */
    041        public Solution(Model model) {
    042            this(model, 0, 0.0);
    043        }
    044
    045        /** Constructor */
    046        public Solution(Model model, long iteration, double time) {
    047            iModel =  model;
    048            iIteration = iteration;
    049            iTime = time;
    050        }
    051
    052        /** Current iteration */
    053        public long getIteration() {
    054            return iIteration;
    055        }
    056
    057        /** The model associated with the solution */
    058        public Model getModel() {
    059            return iModel;
    060        }
    061
    062        /** Current solution time (time in seconds from the start of the solver) */
    063        public double getTime() {
    064            return iTime;
    065        }
    066
    067        /** Update time, increment current iteration */
    068        public void update(double time) {
    069            iTime = time; iIteration++;
    070            for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();)
    071                ((SolutionListener)i.nextElement()).solutionUpdated(this);
    072        }
    073
    074        /** Initialization */
    075        public void init(Solver solver) {
    076            iIteration=0;
    077            iTime=0;
    078            if (iModel!=null) iModel.init(solver);
    079            iPerturbationsCounter = solver.getPerturbationsCounter();
    080        }
    081
    082        public String toString() {
    083            return "Solution{\n  model="+iModel+",\n  iteration="+iIteration+",\n  time="+iTime+"\n}";
    084        }
    085
    086        /** Solution information. It consits from info from the model which is associated with the solution,
    087         * time, iteration, speed and infos from all solution listeners.
    088         */
    089        public Hashtable getInfo() {
    090            Hashtable ret=getModel().getInfo();
    091            if (getPerturbationsCounter()!=null) getPerturbationsCounter().getInfo(ret,this);
    092            ret.put("Time",sTimeFormat.format(getTime())+" sec");
    093            ret.put("Iteration",String.valueOf(getIteration()));
    094            if (getTime()>0) ret.put("Speed",sTimeFormat.format((getIteration())/(double)getTime())+" it/s");
    095            for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();)
    096                ((SolutionListener)i.nextElement()).getInfo(this, ret);
    097            return ret;
    098        }
    099
    100        /** Info of the best ever found solution */
    101        public Hashtable getBestInfo() { return iBestInfo; }
    102        /** Iteration when the best ever found solution was found */
    103        public long getBestIteration() { return (iBestIteration<0?getIteration():iBestIteration); }
    104        /** Solution time when the best ever found solution was found */
    105        public double getBestTime() { return (iBestTime<0?getTime():iBestTime); }
    106        /** Number of perturbation variables (variables with non-initial value assigned) if the best ever solution found */
    107        public int getBestPertirbations() { return iBestPertirbations; }
    108        /** Returns true, if all variables of the best ever solution found are assigned */
    109        public boolean isBestComplete() { return iBestComplete; }
    110        /** Total value of the best ever found solution -- sum of all assigned values (see {@link Value#toInt()}).*/
    111        public int getBestValue() { return iBestValue; }
    112        /** Perturbation penalty of the best ever found solution (see {@link PerturbationsCounter}) */
    113        public double getBestPerturbationsPenalty() { return iBestPerturbationsPenaly; }
    114
    115        /** Returns perturbation counter */
    116        public PerturbationsCounter getPerturbationsCounter() { return iPerturbationsCounter; }
    117
    118        /** Clear the best ever found solution */
    119        public void clearBest() {
    120            iBestInfo = null;
    121            iBestTime = 0;
    122            iBestIteration = 0;
    123            iBestPertirbations = -1;
    124            iBestComplete = false;
    125            iBestValue = 0;
    126            iBestPerturbationsPenaly = -1.0;
    127            for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();)
    128                ((SolutionListener)i.nextElement()).bestCleared(this);
    129        }
    130
    131        /** Save the current solution as the best ever found solution (it also calls {@link Model#saveBest()}) */
    132        public void saveBest() {
    133            getModel().saveBest();
    134            iBestInfo = getInfo();
    135            iBestTime = getTime();
    136            iBestIteration = getIteration();
    137            iBestPertirbations = getModel().perturbVariables().size();
    138            iBestComplete = getModel().unassignedVariables().isEmpty();
    139            iBestValue = getModel().getTotalValue();
    140            iBestPerturbationsPenaly = iPerturbationsCounter.getPerturbationPenalty(this);
    141            for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();)
    142                ((SolutionListener)i.nextElement()).bestSaved(this);
    143        }
    144
    145        /** Restore the best ever found solution into the current solution (it also calls {@link Model#restoreBest()})*/
    146        public void restoreBest() {
    147            if (iBestInfo==null) return;
    148            getModel().restoreBest();
    149            iTime = iBestTime;
    150            iIteration = iBestIteration;
    151            for (Enumeration i=iSolutionListeners.elements();i.hasMoreElements();)
    152                ((SolutionListener)i.nextElement()).bestRestored(this);
    153        }
    154
    155        /** Adds solution listner */
    156        public void addSolutionListener(SolutionListener listener) {
    157            iSolutionListeners.addElement(listener);
    158        }
    159        /** Removes solution listener */
    160        public void removeSolutionListener(SolutionListener listener) {
    161            iSolutionListeners.removeElement(listener);
    162        }
    163    }