    001    package ifs.termination;
    002
    003    import ifs.solution.Solution;
    004    import ifs.util.DataProperties;
    005
    006    /**
    007     * General implementation of termination condition for minimal perturbation problem.
    008     * <br><br>
    009     * Solver stops when a timeout is reached (expressed either by the number of iterations or by a time) or
    010     * when an acceptable complete (all variables are assigned) solution is found. The acceptance
    011     * of a solution is expressed either by the minimal number of variables assigned to not-initial
    012     * values or by the perturbations penalty.
    013     * <br><br>
    014     * Parameters:
    015     * <br>
    016     * <table border='1'><tr><th>Parameter</th><th>Type</th><th>Comment</th></tr>
    017     * <tr><td>Termination.StopWhenComplete</td><td>{@link Double}</td><td>if true, solver stops when a complete solution is found</td></tr>
    018     * <tr><td>Termination.MaxIters</td><td>{@link Integer}</td><td>if zero or positive, solver stops when the given number of iteration is reached</td></tr>
    019     * <tr><td>Termination.TimeOut</td><td>{@link Double}</td><td>if zero or positive, solver stops when the given timeout (given in seconds) is reached</td></tr>
    020     * <tr><td>Termination.MinPerturbances</td><td>{@link Integer}</td><td>if zero or positive, solver stops when the solution is complete and the number of variables with non-initial values is below or equal to this limit</td></tr>
    021     * <tr><td>Termination.MinPerturbationPenalty</td><td>{@link Double}</td><td>if zero or positive, solver stops when the solution is complete and when the perturbation penaly of the solution is below or equal to this limit</td></tr>
    022     * </table>
    023     *
    024     * @see ifs.solver.Solver
    025     * @see ifs.perturbations.PerturbationsCounter
    026     *
    027     * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
    028     * @version 1.0
    029     **/public class MPPTerminationCondition implements TerminationCondition {
    030        protected static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(MPPTerminationCondition.class);
    031        private int iMinPerturbances;
    032        private int iMaxIter;
    033        private double iTimeOut;
    034        private double iMinPertPenalty;
    035        private boolean iStopWhenComplete;
    036
    037        public MPPTerminationCondition(DataProperties properties) {
    038            iMaxIter = properties.getPropertyInt("Termination.MaxIters",-1);
    039            iTimeOut = properties.getPropertyDouble("Termination.TimeOut",  -1.0);
    040            iMinPerturbances = properties.getPropertyInt("Termination.MinPerturbances",-1);
    041            iStopWhenComplete = properties.getPropertyBoolean("Termination.StopWhenComplete", false);
    042            iMinPertPenalty = properties.getPropertyDouble("Termination.MinPerturbationPenalty", -1.0);
    043        }
    044
    045        public MPPTerminationCondition(int maxIter, double timeout, int minPerturbances) {
    046            iMaxIter = maxIter;
    047            iMinPerturbances = minPerturbances;
    048            iTimeOut = timeout;
    049        }
    050
    051        public boolean canContinue(Solution currentSolution) {
    052            if (iMinPerturbances>=0 && currentSolution.getModel().unassignedVariables().isEmpty() &&
    053                currentSolution.getModel().perturbVariables().size()<=iMinPerturbances) {
    054                    sLogger.info("A complete solution with allowed number of perturbances found.");
    055                    return false;
    056            }
    057            if (iMinPertPenalty>=0.0 && currentSolution.getModel().unassignedVariables().isEmpty() &&
    058                currentSolution.getPerturbationsCounter().getPerturbationPenalty(currentSolution)<=iMinPertPenalty) {
    059                    sLogger.info("A complete solution with allowed perturbation penalty found.");
    060                    return false;
    061            }
    062            if (iMaxIter>=0 && currentSolution.getIteration()>=iMaxIter) {
    063                sLogger.info("Maximum number of iteration reached.");
    064                return false;
    065            }
    066            if (iTimeOut>=0 && currentSolution.getTime()>iTimeOut) {
    067                sLogger.info("Timeout reached.");
    068                return false;
    069            }
    070            if (iStopWhenComplete || (iMaxIter<0 && iTimeOut<0)) {
    071                boolean ret = (!currentSolution.getModel().unassignedVariables().isEmpty());
    072                if (!ret) sLogger.info("Complete solution found.");
    073                return ret;
    074            }
    075            return true;
    076        }
    077
    078    }