From 9f9580c5487a3e99b194414bf7e523a48a1bdc33 Mon Sep 17 00:00:00 2001 From: massat <jean-luc.massat@univ-amu.fr> Date: Thu, 3 Oct 2024 18:12:31 +0200 Subject: [PATCH] Clean --- .idea/workspace.xml | 23 +- src/main/java/fr/univamu/solver/Interval.java | 27 +- src/main/java/fr/univamu/solver/Solver.java | 798 +++++++++--------- 3 files changed, 419 insertions(+), 429 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index eeb497a..a9393e0 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,12 +4,10 @@ <option name="autoReloadType" value="SELECTIVE" /> </component> <component name="ChangeListManager"> - <list default="true" id="a17b64ea-8b68-4cd2-aba6-1780c674b35e" name="Changes" comment="Create"> - <change afterPath="$PROJECT_DIR$/src/test/java/fr/univamu/solver/TestInterval.java" afterDir="false" /> - <change afterPath="$PROJECT_DIR$/src/test/java/fr/univamu/solver/TestSolver.java" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" /> + <list default="true" id="a17b64ea-8b68-4cd2-aba6-1780c674b35e" name="Changes" comment="Add tests"> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/src/main/java/fr/univamu/solver/Main.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/fr/univamu/solver/Main.java" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/src/main/java/fr/univamu/solver/Interval.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/fr/univamu/solver/Interval.java" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/src/main/java/fr/univamu/solver/Solver.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/fr/univamu/solver/Solver.java" afterDir="false" /> </list> <option name="SHOW_DIALOG" value="false" /> <option name="HIGHLIGHT_CONFLICTS" value="true" /> @@ -133,7 +131,7 @@ <option name="number" value="Default" /> <option name="presentableId" value="Default" /> <updated>1727967430355</updated> - <workItem from="1727967431394" duration="749000" /> + <workItem from="1727967431394" duration="4281000" /> </task> <task id="LOCAL-00001" summary="Create"> <option name="closed" value="true" /> @@ -151,7 +149,15 @@ <option name="project" value="LOCAL" /> <updated>1727967931296</updated> </task> - <option name="localTasksCounter" value="3" /> + <task id="LOCAL-00003" summary="Add tests"> + <option name="closed" value="true" /> + <created>1727968278226</created> + <option name="number" value="00003" /> + <option name="presentableId" value="LOCAL-00003" /> + <option name="project" value="LOCAL" /> + <updated>1727968278226</updated> + </task> + <option name="localTasksCounter" value="4" /> <servers /> </component> <component name="TypeScriptGeneratedFilesManager"> @@ -159,6 +165,7 @@ </component> <component name="VcsManagerConfiguration"> <MESSAGE value="Create" /> - <option name="LAST_COMMIT_MESSAGE" value="Create" /> + <MESSAGE value="Add tests" /> + <option name="LAST_COMMIT_MESSAGE" value="Add tests" /> </component> </project> \ No newline at end of file diff --git a/src/main/java/fr/univamu/solver/Interval.java b/src/main/java/fr/univamu/solver/Interval.java index 976e9b7..c035b34 100644 --- a/src/main/java/fr/univamu/solver/Interval.java +++ b/src/main/java/fr/univamu/solver/Interval.java @@ -1,8 +1,8 @@ package fr.univamu.solver; public class Interval { - public static int MIN_VALUE = -1000000000; - public static int MAX_VALUE = +1000000000; + public static int MIN_VALUE = -1_000_000_000; + public static int MAX_VALUE = 1_000_000_000; private int min = MIN_VALUE; private int max = MAX_VALUE; @@ -15,7 +15,7 @@ public class Interval { this.min = min; this.max = max; } else { - this.min = +1; + this.min = 1; this.max = -1; } } @@ -35,13 +35,13 @@ public class Interval { var oldMin = min; var oldMax = max; if (newMin > newMax) { - min = +1; + min = 1; max = -1; } else { - min = (newMin > min) ? newMin : min; - max = (newMax < max) ? newMax : max; + min = Integer.max(newMin, min); + max = Integer.min(newMax, max); if (min > max) { - min = +1; + min = 1; max = -1; } } @@ -125,7 +125,7 @@ public class Interval { } int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; - int divisors[] = { i.min, -1, 1, i.max }; + int[] divisors = { i.min, -1, 1, i.max }; for (int divisor : divisors) { if (divisor == 0) continue; @@ -141,8 +141,7 @@ public class Interval { return new Interval(min, max); } - // XXXX - public Interval div2(Interval i) { + public Interval inverseMul(Interval i) { if (isEmpty() || i.isEmpty()) { return empty(); } @@ -151,7 +150,7 @@ public class Interval { } int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; - int divisors[] = { i.min, -1, 1, i.max }; + int[] divisors = { i.min, -1, 1, i.max }; for (int divisor : divisors) { if (!i.contains(divisor)) continue; @@ -165,14 +164,12 @@ public class Interval { if (getSign() * i.getSign() == 1) { // same sign, result is > 0 - if (min <= 0) - min = 1; + min = Integer.max(1, min); } if (getSign() * i.getSign() == -1) { // different sign, result is < 0 - if (max >= 0) - max = -1; + max = Integer.min(-1, max); } return new Interval(min, max); diff --git a/src/main/java/fr/univamu/solver/Solver.java b/src/main/java/fr/univamu/solver/Solver.java index 21a9fec..4ca94b1 100644 --- a/src/main/java/fr/univamu/solver/Solver.java +++ b/src/main/java/fr/univamu/solver/Solver.java @@ -4,415 +4,401 @@ import java.util.LinkedList; import java.util.List; class Constraint { - private char type; - private Variable result; - private Variable var1; - private Variable var2; - - public String toString() { - return String.format("%s(%s,%s,%s)", type, result, var1, var2); - } - - public Constraint(char type, Variable result, Variable var1, Variable var2) { - this.type = type; - this.result = result; - this.var1 = var1; - this.var2 = var2; - } - - public char getType() { - return type; - } - - public Variable getResult() { - return result; - } - - public Variable getVar1() { - return var1; - } - - public Variable getVar2() { - return var2; - } + final private char type; + final private Variable result; + final private Variable var1; + final private Variable var2; + + public String toString() { + return String.format("%s(%s,%s,%s)", type, result, var1, var2); + } + + public Constraint(char type, Variable result, Variable var1, Variable var2) { + this.type = type; + this.result = result; + this.var1 = var1; + this.var2 = var2; + } + + public char getType() { + return type; + } + + public Variable getResult() { + return result; + } + + public Variable getVar1() { + return var1; + } + + public Variable getVar2() { + return var2; + } } public class Solver { - private static final int CHECK_INTERVALS_STRATEGY = 1; - private static final int REDUCE_AND_CHECK_INTERVALS_STRATEGY = 2; - - private List<Constraint> constraints = new LinkedList<>(); - private List<Variable> variables = new LinkedList<>(); - private int strategy = CHECK_INTERVALS_STRATEGY; - - private long solutionsCounter = 0; - private long nodesCounter = 0; - private long maxNodes = 1000_000_000L; - private boolean verbose = true; - - public void reduceAndCheckIntervalsStrategy() { - strategy = REDUCE_AND_CHECK_INTERVALS_STRATEGY; - } - - private boolean checkAddConstraintIntervalsStrategy(Constraint c) { - return c.getVar1().add(c.getVar2()).inter(c.getResult()).isNotEmpty(); - } - - private boolean checkMulConstraintIntervalsStrategy(Constraint c) { - return c.getVar1().mul(c.getVar2()).inter(c.getResult()).isNotEmpty(); - } - - private boolean checkDivConstraintIntervalsStrategy(Constraint c) { - return c.getVar1().div(c.getVar2()).inter(c.getResult()).isNotEmpty(); - } - - private boolean checkDiffConstraintIntervalsStrategy(Constraint c) { - var result = c.getResult(); - var ko = result.equals(c.getVar1()) && result.isFixed(); - return (!ko); - } - - private boolean reduceAddConstraint(Constraint c) { - var change = c.getResult().reduce(c.getVar1().add(c.getVar2())); - change = c.getVar1().reduce(c.getResult().sub(c.getVar2())) || change; - change = c.getVar2().reduce(c.getResult().sub(c.getVar1())) || change; - return change; - } - - private boolean reduceMulConstraint(Constraint c) { - var change = false; - for (int i = 0; i < 3; i++) { - change = c.getResult().reduce(c.getVar1().mul(c.getVar2())) || change; - change = c.getVar2().reduce(c.getResult().div2(c.getVar1())) || change; - change = c.getVar1().reduce(c.getResult().div2(c.getVar2())) || change; - } - return change; - } - - private boolean checkConstraintIntervalsStrategy(Constraint c) { - switch (c.getType()) { - case '+': - return checkAddConstraintIntervalsStrategy(c); - case '#': - return checkDiffConstraintIntervalsStrategy(c); - case '*': - return checkMulConstraintIntervalsStrategy(c); - case '/': - return checkDivConstraintIntervalsStrategy(c); - default: - break; - } - throw new IllegalArgumentException("bad constraint: " + c); - } - - private boolean reduce(Constraint c) { - switch (c.getType()) { - case '+': - return reduceAddConstraint(c); - case '*': - return reduceMulConstraint(c); -// case '#': -// case '/': - } - return false; - } - - private boolean checkConstraint(Constraint c) { - switch (strategy) { - case CHECK_INTERVALS_STRATEGY: - case REDUCE_AND_CHECK_INTERVALS_STRATEGY: - return checkConstraintIntervalsStrategy(c); - } - throw new IllegalStateException("bad strategy: " + strategy); - } - - private boolean checkConstraints() { - for (Constraint c : constraints) { - if (!checkConstraint(c)) { - return false; - } - } - return true; - } - - public Variable findVariable() { - Variable best = null; - for (Variable v : variables) { - if (v.isFixed()) { - // ne pas choisir - } else if (best == null) { - best = v; - } else if (v.getSize() < best.getSize()) { - best = v; - } - } - return best; - } - - public boolean findSolutions() { - if (++nodesCounter > maxNodes) { - throw new IllegalStateException("too many nodes"); - } - if (checkConstraints() == false) { - return false; - } - var v = findVariable(); - if (v == null) { - solutionsCounter++; - if (verbose) { - variables.stream().filter(Variable::isNamed).forEach(System.out::println); - System.out.println(); - } - return true; - } - - boolean result = false; - int min = v.getMin(); - int max = v.getMax(); - - // Comment découper le domaine ? - int step = 1; - if (v.getSize() > 1000) { - if (min < 0 && max >= 0) { - step = -min; - } else { - int mid = (min + max) / 2; - step = (1 + mid - min); - } - } - - // explorer le domaine - for (int value = min; value <= max; value += step) { - v.setMin(value); - v.setMax(Math.min(value + step - 1, max)); - if (findSolutions()) { - result = true; - } - } - v.setMin(min); - v.setMax(max); - return result; - } - - public Variable newVar() { - var v = new Variable(variables.size()); - variables.add(v); - return v; - } - - public Variable newVar(String name) { - var v = new Variable(name); - variables.add(v); - return v; - } - - public Variable newConstant(int value) { - return newVar().domain(value); - } - - public void eq(Variable a, Variable b) { - sub(newConstant(0), a, b); // 0 = A - B - } - - public void gt(Variable a, Variable b) { - sub(newVar().domain(1, Variable.MAX_VALUE), a, b); // Z=A-B,Z>0 - } - - public void get(Variable a, Variable b) { - sub(newVar().domain(0, Variable.MAX_VALUE), a, b); // Z=A-B, Z>=0 - } - - public void lt(Variable a, Variable b) { - gt(b, a); - } - - public void let(Variable a, Variable b) { - get(b, a); - } - - public void diff(Variable a, Variable b) { - constraints.add(new Constraint('#', a, b, null)); - } - - public void allDiff(Variable... variables) { - for (int i = 0; i < variables.length; i++) - for (int j = i + 1; j < variables.length; j++) { - diff(variables[i], variables[j]); - } - } - - private void add(Variable result, Variable a, Variable b) { - constraints.add(new Constraint('+', result, a, b)); - } - - private void sub(Variable result, Variable a, Variable b) { - add(a, result, b); - } - - private void mul(Variable result, Variable a, Variable b) { - constraints.add(new Constraint('*', result, a, b)); - } - - private void div(Variable result, Variable a, Variable b) { - constraints.add(new Constraint('/', result, a, b)); - } - - private Variable parseSimpleTerm(List<Object> terms) { - var first = terms.removeFirst(); - if (first instanceof Variable var) { - return var; - } - if (first instanceof Integer cst) { - return this.newConstant(cst); - } - throw new IllegalArgumentException("bad expression: " + first); - } - - private boolean parseToken(String token, List<Object> terms) { - if (!terms.isEmpty()) { - if (token.equals(terms.getFirst())) { - terms.removeFirst(); - return true; - } - } - return false; - } - - private Variable parseMultiplicationTerm(List<Object> terms) { - var first = parseSimpleTerm(terms); - if (parseToken("*", terms)) { - var second = parseMultiplicationTerm(terms); - var result = newVar(); - mul(result, first, second); - return result; - } - if (parseToken("/", terms)) { - var second = parseMultiplicationTerm(terms); - var result = newVar(); - div(result, first, second); - return result; - } - return first; - } - - private Variable parseAdditionTerm(List<Object> terms) { - var first = parseMultiplicationTerm(terms); - if (parseToken("+", terms)) { - var second = parseAdditionTerm(terms); - var result = newVar(); - add(result, first, second); - return result; - } - if (parseToken("-", terms)) { - var second = parseAdditionTerm(terms); - var result = newVar(); - add(first, result, second); - return result; - } - return first; - } - - public void addConstraint(Object... terms) { - var termsList = new LinkedList<>(); - termsList.addAll(List.of(terms)); - var var1 = parseAdditionTerm(termsList); - var relation = termsList.removeFirst(); - var var2 = parseAdditionTerm(termsList); - if (!termsList.isEmpty()) { - throw new IllegalArgumentException("bad expression: " + termsList); - } - if (relation instanceof String carRelation) { - switch (carRelation) { - case "=": - eq(var1, var2); - return; - case ">": - gt(var1, var2); - return; - case ">=": - get(var1, var2); - return; - case "<": - lt(var1, var2); - return; - case "<=": - let(var1, var2); - return; - case "<>": - diff(var1, var2); - return; - } - } - throw new IllegalArgumentException("bad relation: " + relation); - } - - public Variable expression2(Object... terms) { - var termsList = new LinkedList<>(List.of(terms)); - var result = parseAdditionTerm(termsList); - if (!termsList.isEmpty()) { - throw new IllegalArgumentException("bad expression: " + termsList); - } - return result; - } - - private void reduce() { - if (verbose) { - System.out.println("Variables before reduction:"); - variables.forEach(System.out::println); - } - - for (boolean change = true; change;) { - change = false; - for (Constraint c : constraints) { - if (reduce(c)) { - change = true; - } - } - } - - if (verbose) { - System.out.println("Variables after reduction:"); - variables.forEach(System.out::println); - } - } - - public long solve() { - this.solutionsCounter = 0; - this.nodesCounter = 0; - if (strategy == REDUCE_AND_CHECK_INTERVALS_STRATEGY) { - reduce(); - } - findSolutions(); - return solutionsCounter; - } - - public int getStrategy() { - return strategy; - } - - public long getNodesCounter() { - return nodesCounter; - } - - public long getMaxNodes() { - return maxNodes; - } - - public void setStrategy(int strategy) { - this.strategy = strategy; - } - - public void setMaxNodes(long maxNodes) { - this.maxNodes = maxNodes; - } - - public boolean isVerbose() { - return verbose; - } - - public void setVerbose(boolean verbose) { - this.verbose = verbose; - } + private static final int CHECK_INTERVALS_STRATEGY = 1; + private static final int REDUCE_AND_CHECK_INTERVALS_STRATEGY = 2; + + private final List<Constraint> constraints = new LinkedList<>(); + private final List<Variable> variables = new LinkedList<>(); + private int strategy = CHECK_INTERVALS_STRATEGY; + + private long solutionsCounter = 0; + private long nodesCounter = 0; + private long maxNodes = 1000_000_000L; + private boolean verbose = true; + + public void reduceAndCheckIntervalsStrategy() { + strategy = REDUCE_AND_CHECK_INTERVALS_STRATEGY; + } + + private boolean checkAddConstraintIntervalsStrategy(Constraint c) { + return c.getVar1().add(c.getVar2()).inter(c.getResult()).isNotEmpty(); + } + + private boolean checkMulConstraintIntervalsStrategy(Constraint c) { + return c.getVar1().mul(c.getVar2()).inter(c.getResult()).isNotEmpty(); + } + + private boolean checkDivConstraintIntervalsStrategy(Constraint c) { + return c.getVar1().div(c.getVar2()).inter(c.getResult()).isNotEmpty(); + } + + private boolean checkDiffConstraintIntervalsStrategy(Constraint c) { + var result = c.getResult(); + var ko = result.equals(c.getVar1()) && result.isFixed(); + return (!ko); + } + + private boolean reduceAddConstraint(Constraint c) { + var change = c.getResult().reduce(c.getVar1().add(c.getVar2())); + change = c.getVar1().reduce(c.getResult().sub(c.getVar2())) || change; + change = c.getVar2().reduce(c.getResult().sub(c.getVar1())) || change; + return change; + } + + private boolean reduceMulConstraint(Constraint c) { + var change = false; + for (int i = 0; i < 3; i++) { + change = c.getResult().reduce(c.getVar1().mul(c.getVar2())) || change; + change = c.getVar2().reduce(c.getResult().inverseMul(c.getVar1())) || change; + change = c.getVar1().reduce(c.getResult().inverseMul(c.getVar2())) || change; + } + return change; + } + + private boolean checkConstraintIntervalsStrategy(Constraint c) { + return switch (c.getType()) { + case '+' -> checkAddConstraintIntervalsStrategy(c); + case '#' -> checkDiffConstraintIntervalsStrategy(c); + case '*' -> checkMulConstraintIntervalsStrategy(c); + case '/' -> checkDivConstraintIntervalsStrategy(c); + default -> throw new IllegalArgumentException("bad constraint: " + c); + }; + } + + private boolean reduce(Constraint c) { + return switch (c.getType()) { + case '+' -> reduceAddConstraint(c); + case '*' -> reduceMulConstraint(c); + default -> false; + }; + } + + private boolean checkConstraint(Constraint c) { + return switch (strategy) { + case CHECK_INTERVALS_STRATEGY, REDUCE_AND_CHECK_INTERVALS_STRATEGY -> checkConstraintIntervalsStrategy(c); + default -> throw new IllegalStateException("bad strategy: " + strategy); + }; + } + + private boolean checkConstraints() { + for (Constraint c : constraints) { + if (!checkConstraint(c)) { + return false; + } + } + return true; + } + + public Variable findVariable() { + Variable best = null; + for (Variable v : variables) { + if (v.isFixed()) continue; + if (best == null) { + best = v; + } else if (v.getSize() < best.getSize()) { + best = v; + } + } + return best; + } + + public boolean findSolutions() { + if (++nodesCounter > maxNodes) { + throw new IllegalStateException("too many nodes"); + } + if (! checkConstraints()) { + return false; + } + var v = findVariable(); + if (v == null) { + solutionsCounter++; + if (verbose) { + variables.stream().filter(Variable::isNamed).forEach(System.out::println); + System.out.println(); + } + return true; + } + + boolean result = false; + int min = v.getMin(); + int max = v.getMax(); + + // Comment découper le domaine ? + int step = 1; + if (v.getSize() > 1000) { + if (min < 0 && max >= 0) { + step = -min; + } else { + int mid = (min + max) / 2; + step = (1 + mid - min); + } + } + + // explorer le domaine + for (int value = min; value <= max; value += step) { + v.setMin(value); + v.setMax(Math.min(value + step - 1, max)); + if (findSolutions()) { + result = true; + } + } + v.setMin(min); + v.setMax(max); + return result; + } + + public Variable newVar() { + var v = new Variable(variables.size()); + variables.add(v); + return v; + } + + public Variable newVar(String name) { + var v = new Variable(name); + variables.add(v); + return v; + } + + public Variable newConstant(int value) { + return newVar().domain(value); + } + + public void eq(Variable a, Variable b) { + sub(newConstant(0), a, b); // 0 = A - B + } + + public void gt(Variable a, Variable b) { + sub(newVar().domain(1, Variable.MAX_VALUE), a, b); // Z=A-B,Z>0 + } + + public void get(Variable a, Variable b) { + sub(newVar().domain(0, Variable.MAX_VALUE), a, b); // Z=A-B, Z>=0 + } + + public void lt(Variable a, Variable b) { + gt(b, a); + } + + public void let(Variable a, Variable b) { + get(b, a); + } + + public void diff(Variable a, Variable b) { + constraints.add(new Constraint('#', a, b, null)); + } + + public void allDiff(Variable... variables) { + for (int i = 0; i < variables.length; i++) + for (int j = i + 1; j < variables.length; j++) { + diff(variables[i], variables[j]); + } + } + + private void add(Variable result, Variable a, Variable b) { + constraints.add(new Constraint('+', result, a, b)); + } + + private void sub(Variable result, Variable a, Variable b) { + add(a, result, b); + } + + private void mul(Variable result, Variable a, Variable b) { + constraints.add(new Constraint('*', result, a, b)); + } + + private void div(Variable result, Variable a, Variable b) { + constraints.add(new Constraint('/', result, a, b)); + } + + private Variable parseSimpleTerm(List<Object> terms) { + var first = terms.removeFirst(); + if (first instanceof Variable var) { + return var; + } + if (first instanceof Integer cst) { + return this.newConstant(cst); + } + throw new IllegalArgumentException("bad expression: " + first); + } + + private boolean parseToken(String token, List<Object> terms) { + if (!terms.isEmpty()) { + if (token.equals(terms.getFirst())) { + terms.removeFirst(); + return true; + } + } + return false; + } + + private Variable parseMultiplicationTerm(List<Object> terms) { + var first = parseSimpleTerm(terms); + if (parseToken("*", terms)) { + var second = parseMultiplicationTerm(terms); + var result = newVar(); + mul(result, first, second); + return result; + } + if (parseToken("/", terms)) { + var second = parseMultiplicationTerm(terms); + var result = newVar(); + div(result, first, second); + return result; + } + return first; + } + + private Variable parseAdditionTerm(List<Object> terms) { + var first = parseMultiplicationTerm(terms); + if (parseToken("+", terms)) { + var second = parseAdditionTerm(terms); + var result = newVar(); + add(result, first, second); + return result; + } + if (parseToken("-", terms)) { + var second = parseAdditionTerm(terms); + var result = newVar(); + add(first, result, second); + return result; + } + return first; + } + + public void addConstraint(Object... terms) { + var termsList = new LinkedList<>(List.of(terms)); + var var1 = parseAdditionTerm(termsList); + var relation = termsList.removeFirst(); + var var2 = parseAdditionTerm(termsList); + if (!termsList.isEmpty()) { + throw new IllegalArgumentException("bad expression: " + termsList); + } + if (relation instanceof String carRelation) { + switch (carRelation) { + case "=": + eq(var1, var2); + return; + case ">": + gt(var1, var2); + return; + case ">=": + get(var1, var2); + return; + case "<": + lt(var1, var2); + return; + case "<=": + let(var1, var2); + return; + case "<>": + diff(var1, var2); + return; + } + } + throw new IllegalArgumentException("bad relation: " + relation); + } + + public Variable expression2(Object... terms) { + var termsList = new LinkedList<>(List.of(terms)); + var result = parseAdditionTerm(termsList); + if (!termsList.isEmpty()) { + throw new IllegalArgumentException("bad expression: " + termsList); + } + return result; + } + + private void reduce() { + if (verbose) { + System.out.println("Variables before reduction:"); + variables.forEach(System.out::println); + } + + for (boolean change = true; change; ) { + change = false; + for (Constraint c : constraints) { + if (reduce(c)) { + change = true; + } + } + } + + if (verbose) { + System.out.println("Variables after reduction:"); + variables.forEach(System.out::println); + } + } + + public long solve() { + this.solutionsCounter = 0; + this.nodesCounter = 0; + if (strategy == REDUCE_AND_CHECK_INTERVALS_STRATEGY) { + reduce(); + } + findSolutions(); + return solutionsCounter; + } + + public int getStrategy() { + return strategy; + } + + public long getNodesCounter() { + return nodesCounter; + } + + public long getMaxNodes() { + return maxNodes; + } + + public void setStrategy(int strategy) { + this.strategy = strategy; + } + + public void setMaxNodes(long maxNodes) { + this.maxNodes = maxNodes; + } + + public boolean isVerbose() { + return verbose; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } } -- GitLab