Package solver.search.loop.monitors

Source Code of solver.search.loop.monitors.SearchMonitorFactory$DefaultSolutionMessage

/*
* Copyright (c) 1999-2014, Ecole des Mines de Nantes
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the Ecole des Mines de Nantes nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package solver.search.loop.monitors;

import org.slf4j.LoggerFactory;
import solver.Solver;
import solver.exception.SolverException;
import solver.search.limits.*;
import solver.search.restart.GeometricalRestartStrategy;
import solver.search.restart.LubyRestartStrategy;
import solver.variables.Variable;

import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* <br/>
*
* @author Charles Prud'homme
* @since 09/05/11
*/
public class SearchMonitorFactory {
    SearchMonitorFactory() {
    }

    private static class DefaultSolutionMessage implements IMessage {

        private Solver solver;

        private DefaultSolutionMessage(Solver solver) {
            this.solver = solver;
        }

        @Override
        public String print() {
            return String.format("- Solution #%s found. %s \n\t%s.",
                    solver.getMeasures().getSolutionCount(),
                    solver.getMeasures().toOneShortLineString(),
                    print(solver.getStrategy().vars)
            );
        }

        private String print(Variable[] vars) {
            StringBuilder s = new StringBuilder(32);
            for (Variable v : vars) {
                s.append(v).append(' ');
            }
            return s.toString();

        }

    }

    private static class DefaultDecisionMessage implements IMessage {

        private Solver solver;

        private DefaultDecisionMessage(Solver solver) {
            this.solver = solver;
        }

        @Override
        public String print() {
            int limit = 120;
            Variable[] vars = solver.getStrategy().vars;
            StringBuilder s = new StringBuilder(32);
            for (int i = 0; i < vars.length && s.length() < limit; i++) {
                s.append(vars[i]).append(' ');
            }
            if (s.length() >= limit) {
                s.append("...");
            }
            return s.toString();
        }

    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Print statistics
     *
     * @param solver   solver to observe
     * @param solution print solutions
     * @param choices  print choices
     */
    public static void log(Solver solver, boolean solution, boolean choices) {
        solver.plugMonitor(new LogBasic(solver));
        if (solution) {
            solver.plugMonitor(new LogSolutions(new DefaultSolutionMessage(solver)));
        }
        if (choices) {
            solver.plugMonitor(new LogChoices(solver, new DefaultDecisionMessage(solver)));
        }
    }

    /**
     * Print statistics
     *
     * @param solver          solver to observe
     * @param solution        print solutions
     * @param solutionMessage print the message on solutions
     * @param choices         print choices
     */
    public static void log(Solver solver, boolean solution, IMessage solutionMessage, boolean choices) {
        solver.plugMonitor(new LogBasic(solver));
        if (solution) {
            solver.plugMonitor(new LogSolutions(solutionMessage));
        }
        if (choices) {
            solver.plugMonitor(new LogChoices(solver, new DefaultDecisionMessage(solver)));
        }
    }

    /**
     * Print statistics
     *
     * @param solver          solver to observe
     * @param solution        print solutions
     * @param choices         print choices
     * @param decisionMessage print the message on decisions
     */
    public static void log(Solver solver, boolean solution, boolean choices, IMessage decisionMessage) {
        solver.plugMonitor(new LogBasic(solver));
        if (solution) {
            solver.plugMonitor(new LogSolutions(new DefaultSolutionMessage(solver)));
        }
        if (choices) {
            solver.plugMonitor(new LogChoices(solver, decisionMessage));
        }
    }

    /**
     * Print statistics
     *
     * @param solver          solver to observe
     * @param solution        print solutions
     * @param solutionMessage print the message on solutions
     * @param choices         print choices
     * @param decisionMessage print the message on decisions
     */
    public static void log(Solver solver, boolean solution, IMessage solutionMessage, boolean choices, IMessage decisionMessage) {
        solver.plugMonitor(new LogBasic(solver));
        if (solution) {
            solver.plugMonitor(new LogSolutions(solutionMessage));
        }
        if (choices) {
            solver.plugMonitor(new LogChoices(solver, decisionMessage));
        }
    }

    /**
     * Print statistics in one line
     * @param solver the solver to observe
     */
    public static void shortlog(final Solver solver) {
        solver.plugMonitor(new IMonitorClose() {
            @Override
            public void beforeClose() {
                if (LoggerFactory.getLogger("solver").isInfoEnabled()) {
                    LoggerFactory.getLogger("solver").info(solver.getMeasures().toOneLineString());
                }
            }

            @Override
            public void afterClose() {
            }
        });
    }

    /**
     * Log execution during choices #s and #e
     *
     * @param solver a solver
     * @param s      starting choice number
     * @param e      ending choice number
     */
    public static void logWithRank(Solver solver, int s, int e) {
        solver.plugMonitor(new LogChoicesWithRank(solver, s, e, new DefaultDecisionMessage(solver)));
    }

    /**
     * Log execution during choices #s and #e
     *
     * @param solver          a solver
     * @param s               starting choice number
     * @param e               ending choice number
     * @param decisionMessage print the specific message
     */
    public static void logWithRank(Solver solver, int s, int e, IMessage decisionMessage) {
        solver.plugMonitor(new LogChoicesWithRank(solver, s, e, decisionMessage));
    }

    /**
     * Log contradictions thrown during the resolution
     *
     * @param solver a solver
     */
    public static void logContradiction(Solver solver) {
        solver.plugMonitor(new LogContradiction());
    }

    /**
     * Print one-line statistics every XX ms
     *
     * @param solver
     * @param everyXXmms print one-line statistics every XX ms
     */
    public static void statEveryXXms(Solver solver, long everyXXmms) {
        if (everyXXmms > 0) {
            solver.plugMonitor(new LogStatEveryXXms(solver, everyXXmms));
        }
    }

    /**
     * Branch a luby restart strategy to the solver
     *
     * @param solver               the solver
     * @param scaleFactor          scale factor
     * @param geometricalFactor    increasing factor
     * @param restartStrategyLimit restart trigger
     * @param restartLimit         restart limits (limit of number of restarts)
     */
    public static void luby(Solver solver, int scaleFactor, int geometricalFactor,
                            ICounter restartStrategyLimit, int restartLimit) {
        solver.plugMonitor(new RestartManager(
                new LubyRestartStrategy(scaleFactor, geometricalFactor),
                restartStrategyLimit, solver.getSearchLoop(), restartLimit
        ));
    }

    /**
     * Build a geometrical restart strategy
     *
     * @param solver               the solver
     * @param scaleFactor          scale factor
     * @param geometricalFactor    increasing factor
     * @param restartStrategyLimit restart trigger
     * @param restartLimit         restart limits (limit of number of restarts)
     */
    public static void geometrical(Solver solver, int scaleFactor, double geometricalFactor,
                                   ICounter restartStrategyLimit, int restartLimit) {
        solver.plugMonitor(new RestartManager(
                new GeometricalRestartStrategy(scaleFactor, geometricalFactor),
                restartStrategyLimit, solver.getSearchLoop(), restartLimit
        ));
    }

    /**
     * Print the total number of propagation count per propagator
     *
     * @param solver a solver
     */
    public static void prop_count(Solver solver) {
        solver.plugMonitor(new LogPropagationCount(solver));
    }

    /**
     * Defines a limit on the number of nodes allowed in the tree search.
     * When the limit is reached, the resolution is stopped.
     *
     * @param limit maximal number of nodes to open
     */
    public static void limitNode(Solver solver, long limit) {
        NodeCounter counter = new NodeCounter(limit);
        counter.setAction(ActionCounterFactory.interruptSearch(solver.getSearchLoop()));
        solver.plugMonitor(counter);
    }

    /**
     * Defines a limit over the number of solutions found during the resolution.
     * WHen the limit is reached, the resolution is stopped.
     *
     * @param limit maximal number of solutions
     */
    public static void limitSolution(Solver solver, long limit) {
        SolutionCounter counter = new SolutionCounter(limit);
        counter.setAction(ActionCounterFactory.interruptSearch(solver.getSearchLoop()));
        solver.plugMonitor(counter);
    }


    /**
     * Defines a limit over the run time.
     * When the limit is reached, the resolution is stopped.
     * <br/>
     * <br/>
     * <b>One must consider also {@code SearchMonitorFactory.limitThreadTime(long)}, that runs the limit in a separated thread.</b>
     *
     * @param solver the solver subject to the time limit
     * @param limit  maximal resolution time in millisecond
     * @see SearchMonitorFactory#limitThreadTime(solver.Solver, long)
     */
    public static void limitTime(Solver solver, long limit) {
        TimeCounter counter = new TimeCounter(solver, limit);
        counter.setAction(ActionCounterFactory.interruptSearch(solver.getSearchLoop()));
        solver.plugMonitor(counter);
    }

    /**
     * Defines a limit over the run time.
     * When the limit is reached, the resolution is stopped.
     * <br/>
     * <br/>
     * <b>One must consider also {@code SearchMonitorFactory.limitThreadTime(String)}, that runs the limit in a separated thread.</b>
     * <p/>
     * Based on {@code SearchMonitorFactory.convertInMilliseconds(String duration)}
     *
     * @param duration a String which states the duration like "WWd XXh YYm ZZs".
     * @see SearchMonitorFactory#limitThreadTime(solver.Solver, long)
     * @see SearchMonitorFactory#convertInMilliseconds(String)
     */
    public static void limitTime(Solver solver, String duration) {
        limitTime(solver, convertInMilliseconds(duration));
    }

    /**
     * Defines a limit over the run time, set in a thread.
     * When the limit is reached, the resolution is stopped.
     *
     * @param limit maximal resolution time in millisecond
     * @see SearchMonitorFactory#limitTime(solver.Solver, long)
     * @see SearchMonitorFactory#convertInMilliseconds(String)
     */
    public static void limitThreadTime(Solver solver, long limit) {
        ThreadTimeCounter counter = new ThreadTimeCounter(solver, limit);
        counter.setAction(ActionCounterFactory.interruptSearch(solver.getSearchLoop()));
        solver.plugMonitor(counter);
    }

    /**
     * Defines a limit over the run time, set in a thread.
     * When the limit is reached, the resolution is stopped.
     *
     * @param duration a String which states the duration like "WWd XXh YYm ZZs".
     * @see SearchMonitorFactory#limitTime(solver.Solver, String)
     * @see SearchMonitorFactory#convertInMilliseconds(String)
     */
    public static void limitThreadTime(Solver solver, String duration) {
        limitThreadTime(solver, convertInMilliseconds(duration));
    }

    public static Pattern Dp = Pattern.compile("(\\d+)d");
    public static Pattern Hp = Pattern.compile("(\\d+)h");
    public static Pattern Mp = Pattern.compile("(\\d+)m");
    public static Pattern Sp = Pattern.compile("(\\d+(\\.\\d+)?)s");


    /**
     * Convert a string which represents a duration. It can be composed of days, hours, minutes and seconds.
     * Examples:
     * <p/>
     * - "1d2h3m4.5s": one day, two hours, three minutes, four seconds and 500 milliseconds<p/>
     * - "2h30m": two hours and 30 minutes<p/>
     * - "30.5s": 30 seconds and 500 ms<p/>
     * - "180s": three minutes
     *
     * @param duration a String which describes the duration
     * @return the duration in milliseconds
     */
    public static long convertInMilliseconds(String duration) {
        long milliseconds = 0;
        duration = duration.replaceAll("\\s+", "");
        Matcher matcher = Dp.matcher(duration);
        if (matcher.find() && matcher.groupCount() == 1) {
            int days = Integer.parseInt(matcher.group(1));
            milliseconds += TimeUnit.MILLISECONDS.convert(days, TimeUnit.DAYS);
        }
        matcher = Hp.matcher(duration);
        if (matcher.find() && matcher.groupCount() == 1) {
            int hours = Integer.parseInt(matcher.group(1));
            milliseconds += TimeUnit.MILLISECONDS.convert(hours, TimeUnit.HOURS);
        }
        matcher = Mp.matcher(duration);
        if (matcher.find() && matcher.groupCount() == 1) {
            int minutes = Integer.parseInt(matcher.group(1));
            milliseconds += TimeUnit.MILLISECONDS.convert(minutes, TimeUnit.MINUTES);
        }
        matcher = Sp.matcher(duration);
        if (matcher.find() && matcher.groupCount() == 2) {
            double seconds = Double.parseDouble(matcher.group(1));
            milliseconds += (int) (seconds * 1000);
        }
        if (milliseconds == 0) throw new SolverException("Duration cannot be parsed or must be positive" + duration);
        return milliseconds;
    }

    /**
     * Defines a limit over the number of fails allowed during the resolution.
     * WHen the limit is reached, the resolution is stopped.
     *
     * @param limit maximal number of fails
     */

    public static void limitFail(Solver solver, long limit) {
        FailCounter counter = new FailCounter(limit);
        counter.setAction(ActionCounterFactory.interruptSearch(solver.getSearchLoop()));
        solver.plugMonitor(counter);
    }

    /**
     * Defines a limit over the number of backtracks allowed during the resolution.
     * WHen the limit is reached, the resolution is stopped.
     *
     * @param limit maximal number of backtracks
     */
    public static void limitBacktrack(Solver solver, long limit) {
        BacktrackCounter counter = new BacktrackCounter(limit);
        counter.setAction(ActionCounterFactory.interruptSearch(solver.getSearchLoop()));
        solver.plugMonitor(counter);
    }


    /**
     * Output results to a CSV file (append in set to true).
     *
     * @param solver   a solver
     * @param prefix   String identifying the instance that has been solved
     * @param filename absolute path of the CSV output file
     */
    public static void toCSV(Solver solver, String prefix, String filename) {
        solver.plugMonitor(new OutputCSV(solver, prefix, filename));
    }

    public static void restartAfterEachSolution(final Solver solver) {
        solver.plugMonitor(new IMonitorSolution() {
            @Override
            public void onSolution() {
                solver.getSearchLoop().restart();
            }
        });
    }
}
TOP

Related Classes of solver.search.loop.monitors.SearchMonitorFactory$DefaultSolutionMessage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.