package ifs.termination;

import ifs.solution.Solution;
import ifs.util.DataProperties;

/**
 * General implementation of termination condition.
 * <br><br>
 * Solver stops when the solution is complete (all varaibles are assigned) or when a timeout
 * is reached (expressed either by the number of iterations or by a time).
 * <br><br>
 * Parameters:
 * <br>
 * <table border='1'><tr><th>Parameter</th><th>Type</th><th>Comment</th></tr>
 * <tr><td>Termination.StopWhenComplete</td><td>{@link Double}</td><td>if true, solver stops when a complete solution is found</td></tr>
 * <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>
 * <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>
 * </table>
 *
 * @see ifs.solver.Solver
 *
 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomas Muller</a>
 * @version 1.0
 **/
public class GeneralTerminationCondition implements TerminationCondition {
    protected static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(GeneralTerminationCondition.class);
    private int iMaxIter;
    private double iTimeOut;
    private boolean iStopWhenComplete;
    
    public GeneralTerminationCondition(DataProperties properties) {
        iMaxIter = properties.getPropertyInt("Termination.MaxIters",-1);
        iTimeOut = properties.getPropertyDouble("Termination.TimeOut",  -1.0);
        iStopWhenComplete = properties.getPropertyBoolean("Termination.StopWhenComplete", false);
    }
    
    public boolean canContinue(Solution currentSolution) {
        if (iMaxIter>=0 && currentSolution.getIteration()>=iMaxIter) {
            sLogger.info("Maximum number of iteration reached.");
            return false;
        }
        if (iTimeOut>=0 && currentSolution.getTime()>iTimeOut) {
            sLogger.info("Timeout reached.");
            return false;
        }
        if (iStopWhenComplete || (iMaxIter<0 && iTimeOut<0)) {
            boolean ret = (!currentSolution.getModel().unassignedVariables().isEmpty());
            if (!ret) sLogger.info("Complete solution found.");
            return ret;
        }
        return true;
    }
}
