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 }