001    package net.sf.cpsolver.ifs.termination;
002    
003    import net.sf.cpsolver.ifs.model.Value;
004    import net.sf.cpsolver.ifs.model.Variable;
005    import net.sf.cpsolver.ifs.solution.Solution;
006    import net.sf.cpsolver.ifs.util.DataProperties;
007    
008    /**
009     * General implementation of termination condition. <br>
010     * <br>
011     * Solver stops when the solution is complete (all varaibles are assigned) or
012     * when a timeout is reached (expressed either by the number of iterations or by
013     * a time). <br>
014     * <br>
015     * Parameters: <br>
016     * <table border='1'>
017     * <tr>
018     * <th>Parameter</th>
019     * <th>Type</th>
020     * <th>Comment</th>
021     * </tr>
022     * <tr>
023     * <td>Termination.StopWhenComplete</td>
024     * <td>{@link Double}</td>
025     * <td>if true, solver stops when a complete solution is found</td>
026     * </tr>
027     * <tr>
028     * <td>Termination.MaxIters</td>
029     * <td>{@link Integer}</td>
030     * <td>if zero or positive, solver stops when the given number of iteration is
031     * reached</td>
032     * </tr>
033     * <tr>
034     * <td>Termination.TimeOut</td>
035     * <td>{@link Double}</td>
036     * <td>if zero or positive, solver stops when the given timeout (given in
037     * seconds) is reached</td>
038     * </tr>
039     * </table>
040     * 
041     * @see net.sf.cpsolver.ifs.solver.Solver
042     * 
043     * @version IFS 1.2 (Iterative Forward Search)<br>
044     *          Copyright (C) 2006 - 2010 Tomas Muller<br>
045     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
046     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
047     * <br>
048     *          This library is free software; you can redistribute it and/or modify
049     *          it under the terms of the GNU Lesser General Public License as
050     *          published by the Free Software Foundation; either version 3 of the
051     *          License, or (at your option) any later version. <br>
052     * <br>
053     *          This library is distributed in the hope that it will be useful, but
054     *          WITHOUT ANY WARRANTY; without even the implied warranty of
055     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
056     *          Lesser General Public License for more details. <br>
057     * <br>
058     *          You should have received a copy of the GNU Lesser General Public
059     *          License along with this library; if not see <http://www.gnu.org/licenses/>.
060     **/
061    public class GeneralTerminationCondition<V extends Variable<V, T>, T extends Value<V, T>> implements
062            TerminationCondition<V, T> {
063        protected static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger
064                .getLogger(GeneralTerminationCondition.class);
065        private int iMaxIter;
066        private double iTimeOut;
067        private boolean iStopWhenComplete;
068    
069        public GeneralTerminationCondition(DataProperties properties) {
070            iMaxIter = properties.getPropertyInt("Termination.MaxIters", -1);
071            iTimeOut = properties.getPropertyDouble("Termination.TimeOut", -1.0);
072            iStopWhenComplete = properties.getPropertyBoolean("Termination.StopWhenComplete", false);
073        }
074    
075        @Override
076        public boolean canContinue(Solution<V, T> currentSolution) {
077            if (iMaxIter >= 0 && currentSolution.getIteration() >= iMaxIter) {
078                sLogger.info("Maximum number of iteration reached.");
079                return false;
080            }
081            if (iTimeOut >= 0 && currentSolution.getTime() > iTimeOut) {
082                sLogger.info("Timeout reached.");
083                return false;
084            }
085            if (iStopWhenComplete || (iMaxIter < 0 && iTimeOut < 0)) {
086                boolean ret = (currentSolution.getModel().nrUnassignedVariables() != 0);
087                if (!ret)
088                    sLogger.info("Complete solution found.");
089                return ret;
090            }
091            return true;
092        }
093    }