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    }