Skip to content

Commit

Permalink
Merge pull request #1058 from chocoteam/dev_searchconf
Browse files Browse the repository at this point in the history
Introducing blackbox search configurator
  • Loading branch information
mergify[bot] authored Aug 24, 2023
2 parents 7f3bc75 + 27c4a53 commit 6cdd154
Show file tree
Hide file tree
Showing 25 changed files with 1,269 additions and 1,053 deletions.
2 changes: 2 additions & 0 deletions parsers/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@
opens org.chocosolver.parser.flatzinc to args4j;
opens org.chocosolver.parser.xcsp to args4j;
opens org.chocosolver.parser.dimacs to args4j;
exports org.chocosolver.parser.handlers;
opens org.chocosolver.parser.handlers to args4j, org.testng;
}
55 changes: 0 additions & 55 deletions parsers/src/main/java/org/chocosolver/parser/ParserParameters.java

This file was deleted.

180 changes: 84 additions & 96 deletions parsers/src/main/java/org/chocosolver/parser/RegParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@
package org.chocosolver.parser;

import gnu.trove.set.hash.THashSet;
import org.chocosolver.solver.*;
import org.chocosolver.parser.handlers.LimitHandler;
import org.chocosolver.parser.handlers.RestartHandler;
import org.chocosolver.parser.handlers.ValSelHandler;
import org.chocosolver.parser.handlers.VarSelHandler;
import org.chocosolver.solver.Model;
import org.chocosolver.solver.ParallelPortfolio;
import org.chocosolver.solver.Settings;
import org.chocosolver.solver.Solver;
import org.chocosolver.solver.learn.XParameters;
import org.chocosolver.solver.search.loop.move.MoveBinaryDFS;
import org.chocosolver.solver.search.strategy.BlackBoxConfigurator;
import org.chocosolver.solver.search.strategy.Search;
import org.chocosolver.solver.search.strategy.selectors.values.SetDomainMax;
import org.chocosolver.solver.search.strategy.selectors.variables.DomOverWDegRef;
import org.chocosolver.solver.search.strategy.strategy.AbstractStrategy;
import org.chocosolver.solver.search.strategy.SearchParams;
import org.chocosolver.solver.variables.IntVar;
import org.chocosolver.solver.variables.SetVar;
import org.chocosolver.solver.variables.Variable;
import org.chocosolver.util.tools.VariableUtils;
import org.kohsuke.args4j.Argument;
Expand Down Expand Up @@ -71,8 +75,8 @@ public abstract class RegParser implements IParser {

@Option(name = "-limit",
handler = LimitHandler.class,
usage = "Resolution limits (XXhYYmZZs,Nruns,Msols) where each is optional (no space allowed).")
protected ParserParameters.LimConf limits = new ParserParameters.LimConf(-1, -1, -1);
usage = "Resolution limits [XXhYYmZZs,Nruns,Msols] where each is optional (no space allowed).")
protected SearchParams.LimConf limits = new SearchParams.LimConf(-1, -1, -1);

@Option(name = "-csv", aliases = {
"--print-csv"}, usage = "Print statistics on exit (default: false).")
Expand All @@ -84,42 +88,75 @@ public abstract class RegParser implements IParser {

@Option(name = "-varh", aliases = {"--varHeuristic"},
depends = {"-f"},
forbids = {"-varsel"},
usage = "Define the variable heuristic to use.")
public Search.VarH varH = Search.VarH.DEFAULT;
public SearchParams.VariableSelection varH = SearchParams.VariableSelection.DOMWDEG_CACD;

@Option(name = "-flush",
forbids = {"-varsel"},
usage = "Autoflush weights on black-box strategies (default: 32).")
protected int flushRate = 32;

@Option(name = "-varsel",
handler = VarSelHandler.class,
depends = {"-f"},
forbids = {"-varh", "-tie", "-flush"},
usage = "Define the variable selector to use. Expected format: [varsel,tie,flush] as [String,String,int] -- no space allowed.")
public SearchParams.VarSelConf varsel;

@Option(name = "-valh", aliases = {"--valHeuristic"},
depends = {"-f"},
forbids = {"-valsel"},
usage = "Define the value heuristic to use.")
public Search.ValH valH = Search.ValH.DEFAULT;
public SearchParams.ValueSelection valH = SearchParams.ValueSelection.MIN;

@Option(name = "-best",
depends = {"-f"},
forbids = {"-valsel"},
usage = "Tell use BIVS as a meta value selector.")
protected boolean best = false;

@Option(name = "-bestRate",
depends = {"-f"},
forbids = {"-valsel"},
usage = "BIVS rate call.")
protected int bestRate = 16;


@Option(name = "-last",
depends = {"-f"},
forbids = {"-valsel"},
usage = "Tell the solver to use progress (or phase) saving.")
protected boolean last = false;

@Option(name = "-valsel",
handler = ValSelHandler.class,
depends = {"-f"},
forbids = {"-valh", "-best", "-bestRate", "-last"},
usage = "Define the variable selector to use. Expected format: [valsel,best,bestRate,last] " +
"as [String,boolean,int,boolean] -- no space allowed.")
public SearchParams.ValSelConf valsel;

@Option(name = "-restarts",
handler = RestartHandler.class,
depends = {"-f"},
usage = "Define the restart heuristic to use. Expected format: (policy,cutoff,offset) (no space allowed)")
public ParserParameters.ResConf restarts =
new ParserParameters.ResConf(Search.Restarts.LUBY, 500, 5000);
usage = "Define the restart heuristic to use. Expected format: [policy,cutoff,geo?,offset] " +
"as [String,int,double?,int] -- no space allowed.")
public SearchParams.ResConf restarts =
new SearchParams.ResConf(SearchParams.Restart.GEOMETRIC, 10, 1.05, 50_000, true);

@Option(name = "-lc",
aliases = {"--lact-conflict"},
depends = {"-f"},
forbids = {"-cos"},
usage = "Tell the solver to use last-conflict reasoning.")
protected int lc = 1;

@Option(name = "-cos",
depends = {"-f"},
forbids = {"-lc"},
usage = "Tell the solver to use conflict ordering search.")
protected boolean cos = false;

@Option(name = "-last",
depends = {"-f"},
usage = "Tell the solver to use use progress (or phase) saving.")
protected boolean last = false;

@Option(name = "-flush", usage = "Autoflush weights on black-box strategies (default: 32).")
protected int flush = 5000;

@Option(name = "-a", aliases = {"--all"}, usage = "Search for all solutions (default: false).")
public boolean all = false;

Expand Down Expand Up @@ -192,6 +229,16 @@ public void createSolver() {
}
}

public void freesearch(Solver solver){
BlackBoxConfigurator bb;
if (solver.getObjectiveManager().isOptimization()) {
bb = BlackBoxConfigurator.forCOP();
} else {
bb = BlackBoxConfigurator.forCSP();
}
bb.make(solver.getModel());
}

@Override
public final boolean setUp(String... args) throws SetUpException {
CmdLineParser cmdparser = new CmdLineParser(this);
Expand All @@ -206,6 +253,12 @@ public final boolean setUp(String... args) throws SetUpException {
if (level.isLoggable(Level.INFO)) {
System.out.printf("%s\n", Arrays.toString(args));
}
if(varsel == null){
varsel = new SearchParams.VarSelConf(varH, flushRate);
}
if(valsel == null){
valsel = new SearchParams.ValSelConf(valH, best, bestRate, last);
}
createSettings();
Runtime.getRuntime().addShutdownHook(statOnKill);
return true;
Expand Down Expand Up @@ -237,7 +290,7 @@ protected void makeComplementarySearch(Model m, int i) {
}

@Override
public final void configureSearch() {
public void configureSearch() {
Solver solver = portfolio.getModels().get(0).getSolver();
if (level.is(Level.VERBOSE)) {
solver.verboseSolving(1000);
Expand All @@ -260,83 +313,18 @@ public final void configureSearch() {
}
}
if (free) {
if (level.isLoggable(Level.INFO)) {
solver.log().white().printf("set search to: (%s,%s) + %s\n", varH, valH, restarts.pol);
}
if (lc > 0 || cos || last) {
if (level.isLoggable(Level.INFO)) solver.log().white().print("add techniques: ");
if (cos) {
if (level.isLoggable(Level.INFO)) solver.log().white().print("-cos ");
} else if (lc > 0) {
if (level.isLoggable(Level.INFO)) solver.log().white().printf("-lc %d ", lc);
}
if (last) {
if (level.isLoggable(Level.INFO)) solver.log().white().print("-last");
}
if (level.isLoggable(Level.INFO)) solver.log().white().print("\n");
}
IntVar obj = (IntVar) solver.getObjectiveManager().getObjective();
IntVar[] dvars;
SetVar[] svars;
if (solver.getMove().getStrategy() != null) {
dvars = Arrays.stream(solver.getMove().getStrategy().getVariables())
.filter(VariableUtils::isInt)
.map(Variable::asIntVar)
.filter(v -> v != obj)
.toArray(IntVar[]::new);
svars = Arrays.stream(solver.getMove().getStrategy().getVariables())
.filter(VariableUtils::isSet)
.map(Variable::asSetVar)
.toArray(SetVar[]::new);
} else {
dvars = Arrays.stream(solver.getModel().retrieveIntVars(true))
.map(Variable::asIntVar)
.filter(v -> v != obj)
.toArray(IntVar[]::new);
svars = Arrays.stream(solver.getModel().retrieveSetVars())
.map(Variable::asSetVar)
.toArray(SetVar[]::new);
}
if (dvars.length == 0) {
dvars = new IntVar[]{solver.getModel().intVar(0)};
}
if (svars.length == 0) {
svars = new SetVar[]{solver.getModel().setVar()};
}
solver.getMove().removeStrategy();
solver.setMove(new MoveBinaryDFS());
AbstractStrategy<IntVar> istrat = varH.make(solver, dvars, valH, flush, last);
AbstractStrategy<SetVar> sstrat = Search.setVarSearch(new DomOverWDegRef<>(svars, solver.getModel().getSeed()), new SetDomainMax(), true, svars);

if (obj != null) {
boolean max = solver.getObjectiveManager().getPolicy() == ResolutionPolicy.MAXIMIZE;
solver.setSearch(
istrat,
sstrat,
max ? Search.minDomUBSearch(obj) : Search.minDomLBSearch((obj))
);
} else {
solver.setSearch(istrat, sstrat);
}
if (cos) {
solver.setSearch(Search.conflictOrderingSearch(solver.getSearch()));
} else if (lc > 0) {
solver.setSearch(Search.lastConflict(solver.getSearch(), lc));
}
restarts.declare(solver);
//solver.plugMonitor(new BackjumpRestart(solver));
//solver.showDecisions();
freesearch(solver);
}
}
for (int i = 0; i < nb_cores; i++) {
if (limits.time > -1) {
portfolio.getModels().get(i).getSolver().limitTime(limits.time);
if (limits.getTime() > -1) {
portfolio.getModels().get(i).getSolver().limitTime(limits.getTime());
}
if (limits.sols > -1) {
portfolio.getModels().get(i).getSolver().limitSolution(limits.sols);
if (limits.getSols() > -1) {
portfolio.getModels().get(i).getSolver().limitSolution(limits.getSols());
}
if (limits.runs > -1) {
portfolio.getModels().get(i).getSolver().limitRestart(limits.runs);
if (limits.getRuns() > -1) {
portfolio.getModels().get(i).getSolver().limitRestart(limits.getRuns());
}
makeComplementarySearch(portfolio.getModels().get(i), i);
}
Expand Down Expand Up @@ -383,6 +371,6 @@ public final int bestModelID() {

protected boolean runInTime() {
long rtime = (System.currentTimeMillis() - time);
return limits.time < 0 || rtime < limits.time;
return limits.getTime() < 0 || rtime < limits.getTime();
}
}
25 changes: 11 additions & 14 deletions parsers/src/main/java/org/chocosolver/parser/dimacs/DIMACS.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
import org.chocosolver.solver.ResolutionPolicy;
import org.chocosolver.solver.Settings;
import org.chocosolver.solver.Solver;
import org.chocosolver.solver.search.limits.FailCounter;
import org.chocosolver.solver.search.strategy.Search;
import org.chocosolver.solver.search.restart.GeometricalCutoff;
import org.chocosolver.solver.search.restart.Restarter;
import org.chocosolver.solver.search.strategy.BlackBoxConfigurator;
import org.chocosolver.util.logger.Logger;
import org.kohsuke.args4j.Option;

Expand Down Expand Up @@ -88,10 +89,10 @@ public void buildModel() {
try {
long ptime = -System.currentTimeMillis();
parse(m, parsers[i], i);
if(logFilePath != null) {
if (logFilePath != null) {
s.log().remove(System.out);
s.log().add(new PrintStream(Files.newOutputStream(Paths.get(logFilePath)), true));
}else {
} else {
s.logWithANSI(ansi);
}
if (level.isLoggable(Level.INFO)) {
Expand Down Expand Up @@ -135,16 +136,12 @@ public void buildModel() {
public void parse(Model target, DIMACSParser parser, int i) throws Exception {
parser.model(target, instance);
if (i == 0) {
Solver solver = target.getSolver();
if (target.getNbRealVar() == 0) {
target.getSolver().setSearch(
Search.domOverWDegSearch(getModel().retrieveBoolVars())
);
solver.setLubyRestart(500, new FailCounter(target, 0), 5000);
} else {
solver.setSearch(Search.defaultSearch(target));
solver.setLubyRestart(500, new FailCounter(target, 0), 5000);
}
BlackBoxConfigurator.init()
.setRestartPolicy(
s -> new Restarter(
new GeometricalCutoff(5, 1.05),
c -> s.getFailCount() >= c, 50_000, true))
.make(target);
}
}

Expand Down
Loading

0 comments on commit 6cdd154

Please sign in to comment.