From 90f441d13d39051058d1de1abc5dd164d921a849 Mon Sep 17 00:00:00 2001 From: Steffen Hildebrandt Date: Wed, 26 Jun 2024 21:03:34 +0200 Subject: [PATCH] new concept for computation handlers --- .../logicng/backbones/BackboneGeneration.java | 10 +- .../explanations/mus/DeletionBasedMUS.java | 10 +- .../logicng/explanations/mus/MUSConfig.java | 9 +- .../mus/PlainInsertionBasedMUS.java | 14 ++- .../explanations/smus/SmusComputation.java | 36 +++--- .../booleworks/logicng/formulas/Formula.java | 3 +- .../logicng/handlers/BDDHandler.java | 25 ---- .../logicng/handlers/ComputationHandler.java | 37 +++--- .../handlers/DnnfCompilationHandler.java | 23 ---- .../handlers/FactorizationHandler.java | 34 ----- .../booleworks/logicng/handlers/Handler.java | 53 -------- .../logicng/handlers/MaxSATHandler.java | 76 ----------- .../handlers/ModelEnumerationHandler.java | 52 -------- .../logicng/handlers/NopHandler.java | 36 ++++++ .../handlers/NumberOfModelsHandler.java | 55 ++++---- .../handlers/NumberOfNodesBDDHandler.java | 27 ++-- .../logicng/handlers/OptimizationHandler.java | 53 -------- .../logicng/handlers/SATHandler.java | 40 ------ .../logicng/handlers/TimeoutBDDHandler.java | 57 --------- .../logicng/handlers/TimeoutDnnfHandler.java | 52 -------- .../logicng/handlers/TimeoutHandler.java | 75 +++++------ .../handlers/TimeoutMaxSATHandler.java | 111 ---------------- .../TimeoutModelEnumerationHandler.java | 91 -------------- .../handlers/TimeoutOptimizationHandler.java | 97 -------------- .../logicng/handlers/TimeoutSATHandler.java | 55 -------- .../events/ComputationFinishedEvent.java | 43 +++++++ .../events/ComputationStartedEvent.java | 56 +++++++++ .../events/EnumerationFoundModelsEvent.java | 38 ++++++ .../FactorizationCreatedClauseEvent.java | 38 ++++++ .../logicng/handlers/events/LogicNGEvent.java | 11 ++ .../events/MaxSatNewLowerBoundEvent.java | 33 +++++ .../events/MaxSatNewUpperBoundEvent.java | 34 +++++ .../OptimizationFoundBetterBoundEvent.java | 38 ++++++ .../logicng/handlers/events/SimpleEvent.java | 41 ++++++ .../knowledgecompilation/bdds/BDD.java | 13 +- .../knowledgecompilation/bdds/BDDFactory.java | 22 ++-- .../bdds/jbuddy/BDDKernel.java | 20 +-- .../bdds/jbuddy/BDDOperations.java | 3 +- .../dnnf/DnnfCompiler.java | 19 +-- .../dnnf/DnnfFactory.java | 7 +- .../logicng/modelcounting/ModelCounter.java | 27 ++-- .../primecomputation/NaivePrimeReduction.java | 23 ++-- .../primecomputation/PrimeCompiler.java | 37 +++--- .../logicng/solvers/MaxSATSolver.java | 7 +- .../solvers/functions/BackboneFunction.java | 15 +-- .../functions/ModelCountingFunction.java | 19 +-- .../functions/ModelEnumerationFunction.java | 19 +-- .../ModelEnumerationToBddFunction.java | 19 +-- .../functions/OptimizationFunction.java | 33 ++--- .../AbstractModelEnumerationFunction.java | 22 ++-- .../EnumerationCollector.java | 19 ++- .../ModelEnumerationConfig.java | 9 +- .../solvers/maxsat/algorithms/IncWBO.java | 23 ++-- .../solvers/maxsat/algorithms/LinearSU.java | 19 ++- .../solvers/maxsat/algorithms/LinearUS.java | 21 ++-- .../solvers/maxsat/algorithms/MSU3.java | 21 ++-- .../solvers/maxsat/algorithms/MaxSAT.java | 45 +++---- .../solvers/maxsat/algorithms/OLL.java | 13 +- .../solvers/maxsat/algorithms/WBO.java | 24 ++-- .../solvers/maxsat/algorithms/WMSU3.java | 32 +++-- .../logicng/solvers/sat/LNGCoreSolver.java | 46 +++---- .../logicng/solvers/sat/SATCall.java | 8 +- .../logicng/solvers/sat/SATCallBuilder.java | 8 +- .../AbortableFormulaTransformation.java | 8 +- .../BDDNormalFormTransformation.java | 3 +- ...ableAndAbortableFormulaTransformation.java | 4 +- .../transformations/cnf/CNFEncoder.java | 32 ++--- .../transformations/cnf/CNFFactorization.java | 25 ++-- .../transformations/dnf/DNFFactorization.java | 24 ++-- .../simplification/AdvancedSimplifier.java | 27 ++-- .../QuineMcCluskeySimplifier.java | 9 +- src/main/java/module-info.java | 2 + .../logicng/LogicNGVersionTest.java | 1 - .../backbones/BackboneGenerationTest.java | 10 +- .../logicng/encodings/CcAlkTest.java | 3 +- .../logicng/explanations/drup/DRUPTest.java | 1 - .../explanations/mus/MUSGenerationTest.java | 14 +-- .../smus/SmusComputationTest.java | 36 +++--- .../handlers/BoundedOptimizationHandler.java | 45 ++++--- .../logicng/handlers/BoundedSatHandler.java | 17 +-- .../handlers/ModelEnumerationHandlerTest.java | 12 +- .../handlers/TimeoutBDDHandlerTest.java | 32 ++--- .../handlers/TimeoutMaxSATHandlerTest.java | 72 ++++------- .../TimeoutModelEnumerationHandlerTest.java | 10 +- .../TimeoutOptimizationHandlerTest.java | 29 +++-- .../handlers/TimeoutSATHandlerTest.java | 40 +++--- .../logicng/handlers/TimerTypeTest.java | 118 +++++++----------- .../bdds/BDDReorderingTest.java | 18 +-- .../bdds/LargeBDDTest.java | 20 +-- .../bdds/SimpleBDDTest.java | 11 +- .../primecomputation/PrimeCompilerTest.java | 33 ++--- .../PrimeImplicantReductionTest.java | 11 +- .../PrimeImplicateReductionTest.java | 11 +- .../functions/ModelCountingFunctionTest.java | 2 +- .../ModelEnumerationFunctionTest.java | 2 +- .../ModelEnumerationToBddFunctionTest.java | 2 +- .../functions/OptimizationFunctionTest.java | 103 +++++++-------- .../EnumerationCollectorTestHandler.java | 43 +++---- .../solvers/maxsat/MaxSatLongRunningTest.java | 6 +- .../solvers/maxsat/PartialMaxSATTest.java | 65 ++++++++-- .../maxsat/PartialWeightedMaxSATTest.java | 12 +- .../solvers/sat/LNGCoreSolverTest.java | 3 +- .../logicng/solvers/sat/SATCallTest.java | 84 +++++++------ .../logicng/solvers/sat/SATTest.java | 45 ++++--- .../logicng/transformations/cnf/CNFTest.java | 79 ++++++------ .../cnf/CnfMethodComparisonTest.java | 8 +- .../dnf/DNFFactorizationTest.java | 43 ++++--- .../AdvancedSimplifierTest.java | 39 +++--- 108 files changed, 1414 insertions(+), 1856 deletions(-) delete mode 100644 src/main/java/com/booleworks/logicng/handlers/BDDHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/DnnfCompilationHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/FactorizationHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/Handler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/MaxSATHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/ModelEnumerationHandler.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/NopHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/OptimizationHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/SATHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/TimeoutBDDHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/TimeoutDnnfHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandler.java delete mode 100644 src/main/java/com/booleworks/logicng/handlers/TimeoutSATHandler.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/ComputationFinishedEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/ComputationStartedEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/EnumerationFoundModelsEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/FactorizationCreatedClauseEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/LogicNGEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewLowerBoundEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewUpperBoundEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/OptimizationFoundBetterBoundEvent.java create mode 100644 src/main/java/com/booleworks/logicng/handlers/events/SimpleEvent.java diff --git a/src/main/java/com/booleworks/logicng/backbones/BackboneGeneration.java b/src/main/java/com/booleworks/logicng/backbones/BackboneGeneration.java index f95e7062..08bd13c8 100644 --- a/src/main/java/com/booleworks/logicng/backbones/BackboneGeneration.java +++ b/src/main/java/com/booleworks/logicng/backbones/BackboneGeneration.java @@ -7,7 +7,8 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.functions.BackboneFunction; import com.booleworks.logicng.solvers.sat.SATSolverConfig; @@ -41,14 +42,13 @@ private BackboneGeneration() { * @param variables the given collection of relevant variables for the * backbone computation * @param type the type of backbone variables that should be computed - * @param handler an optional handler for the backbone computation's SAT - * solver + * @param handler a handler * @return the backbone or {@code null} if the computation was aborted by * the handler */ public static Backbone compute(final FormulaFactory f, final Collection formulas, final Collection variables, final BackboneType type, - final SATHandler handler) { + final ComputationHandler handler) { if (formulas == null || formulas.isEmpty()) { throw new IllegalArgumentException("Provide at least one formula for backbone computation"); } @@ -70,7 +70,7 @@ public static Backbone compute(final FormulaFactory f, final Collection */ public static Backbone compute(final FormulaFactory f, final Collection formulas, final Collection variables, final BackboneType type) { - return compute(f, formulas, variables, type, null); + return compute(f, formulas, variables, type, NopHandler.get()); } /** diff --git a/src/main/java/com/booleworks/logicng/explanations/mus/DeletionBasedMUS.java b/src/main/java/com/booleworks/logicng/explanations/mus/DeletionBasedMUS.java index a4ced58b..adf8dc08 100644 --- a/src/main/java/com/booleworks/logicng/explanations/mus/DeletionBasedMUS.java +++ b/src/main/java/com/booleworks/logicng/explanations/mus/DeletionBasedMUS.java @@ -4,10 +4,12 @@ package com.booleworks.logicng.explanations.mus; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.MUS_COMPUTATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; + import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.explanations.UNSATCore; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.Handler; import com.booleworks.logicng.propositions.Proposition; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.SolverState; @@ -25,7 +27,7 @@ public final class DeletionBasedMUS extends MUSAlgorithm { @Override public UNSATCore computeMUS(final FormulaFactory f, final List propositions, final MUSConfig config) { - Handler.start(config.handler); + config.handler.shouldResume(MUS_COMPUTATION_STARTED); final List mus = new ArrayList<>(propositions.size()); final List solverStates = new ArrayList<>(propositions.size()); final SATSolver solver = SATSolver.newSolver(f); @@ -34,7 +36,7 @@ public UNSATCore computeMUS(final FormulaFactory f, f solver.add(proposition); } boolean sat = solver.satCall().handler(config.handler).sat() == Tristate.TRUE; - if (Handler.aborted(config.handler)) { + if (!config.handler.shouldResume(NO_EVENT)) { return null; } if (sat) { @@ -46,7 +48,7 @@ public UNSATCore computeMUS(final FormulaFactory f, f solver.add(prop); } sat = solver.satCall().handler(config.handler).sat() == Tristate.TRUE; - if (Handler.aborted(config.handler)) { + if (!config.handler.shouldResume(NO_EVENT)) { return null; } if (sat) { diff --git a/src/main/java/com/booleworks/logicng/explanations/mus/MUSConfig.java b/src/main/java/com/booleworks/logicng/explanations/mus/MUSConfig.java index 8d4e1ff0..8adf4360 100644 --- a/src/main/java/com/booleworks/logicng/explanations/mus/MUSConfig.java +++ b/src/main/java/com/booleworks/logicng/explanations/mus/MUSConfig.java @@ -6,7 +6,8 @@ import com.booleworks.logicng.configurations.Configuration; import com.booleworks.logicng.configurations.ConfigurationType; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; /** * The configuration object for the MUS generation. @@ -24,7 +25,7 @@ public enum Algorithm { } final Algorithm algorithm; - final SATHandler handler; + final ComputationHandler handler; /** * Constructs a new configuration with a given type. @@ -58,7 +59,7 @@ public String toString() { public static class Builder { private Algorithm algorithm = Algorithm.DELETION; - private SATHandler handler = null; + private ComputationHandler handler = NopHandler.get(); private Builder() { // Initialize only via factory @@ -80,7 +81,7 @@ public Builder algorithm(final Algorithm algorithm) { * @param handler the SAT handler * @return the current builder */ - public Builder handler(final SATHandler handler) { + public Builder handler(final ComputationHandler handler) { this.handler = handler; return this; } diff --git a/src/main/java/com/booleworks/logicng/explanations/mus/PlainInsertionBasedMUS.java b/src/main/java/com/booleworks/logicng/explanations/mus/PlainInsertionBasedMUS.java index 51831454..300709af 100644 --- a/src/main/java/com/booleworks/logicng/explanations/mus/PlainInsertionBasedMUS.java +++ b/src/main/java/com/booleworks/logicng/explanations/mus/PlainInsertionBasedMUS.java @@ -4,11 +4,13 @@ package com.booleworks.logicng.explanations.mus; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.MUS_COMPUTATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; + import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.explanations.UNSATCore; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.Handler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.propositions.Proposition; import com.booleworks.logicng.solvers.SATSolver; @@ -25,7 +27,7 @@ public class PlainInsertionBasedMUS extends MUSAlgorithm { @Override public UNSATCore computeMUS(final FormulaFactory f, final List propositions, final MUSConfig config) { - Handler.start(config.handler); + config.handler.shouldResume(MUS_COMPUTATION_STARTED); final List currentFormula = new ArrayList<>(propositions.size()); currentFormula.addAll(propositions); final List mus = new ArrayList<>(propositions.size()); @@ -46,7 +48,7 @@ public UNSATCore computeMUS(final FormulaFactory f, f transitionProposition = removeProposition; solver.add(removeProposition); } - if (Handler.aborted(config.handler)) { + if (!config.handler.shouldResume(NO_EVENT)) { return null; } currentFormula.clear(); @@ -59,8 +61,8 @@ public UNSATCore computeMUS(final FormulaFactory f, f return new UNSATCore<>(mus, true); } - private static boolean shouldProceed(final SATSolver solver, final SATHandler handler) { + private static boolean shouldProceed(final SATSolver solver, final ComputationHandler handler) { final boolean sat = solver.satCall().handler(handler).sat() == Tristate.TRUE; - return sat && !Handler.aborted(handler); + return sat && handler.shouldResume(NO_EVENT); } } diff --git a/src/main/java/com/booleworks/logicng/explanations/smus/SmusComputation.java b/src/main/java/com/booleworks/logicng/explanations/smus/SmusComputation.java index c3f1b10d..c4bcd114 100644 --- a/src/main/java/com/booleworks/logicng/explanations/smus/SmusComputation.java +++ b/src/main/java/com/booleworks/logicng/explanations/smus/SmusComputation.java @@ -4,13 +4,16 @@ package com.booleworks.logicng.explanations.smus; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; + import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.Handler; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; import com.booleworks.logicng.propositions.Proposition; import com.booleworks.logicng.propositions.StandardProposition; import com.booleworks.logicng.solvers.SATSolver; @@ -58,14 +61,14 @@ private SmusComputation() { */ public static

List

computeSmus(final FormulaFactory f, final List

propositions, final List additionalConstraints) { - return computeSmus(f, propositions, additionalConstraints, null); + return computeSmus(f, propositions, additionalConstraints, NopHandler.get()); } /** * Computes the SMUS for the given list of propositions modulo some * additional constraint. *

- * The SMUS computation can be called with an {@link OptimizationHandler}. + * The SMUS computation can be called with an {@link ComputationHandler}. * The given handler instance will be used for every subsequent * * {@link OptimizationFunction} call and the handler's SAT handler is used * for every subsequent SAT call. @@ -79,8 +82,8 @@ public static

List

computeSmus(final FormulaFactory f */ public static

List

computeSmus(final FormulaFactory f, final List

propositions, final List additionalConstraints, - final OptimizationHandler handler) { - Handler.start(handler); + final ComputationHandler handler) { + handler.shouldResume(ComputationStartedEvent.SMUS_COMPUTATION_STARTED); final SATSolver growSolver = SATSolver.newSolver(f); growSolver.add(additionalConstraints == null ? Collections.singletonList(f.verum()) : additionalConstraints); final Map propositionMapping = new TreeMap<>(); @@ -89,19 +92,18 @@ public static

List

computeSmus(final FormulaFactory f propositionMapping.put(selector, proposition); growSolver.add(f.equivalence(selector, proposition.formula())); } - final boolean sat = growSolver.satCall().handler(OptimizationHandler.satHandler(handler)) - .addFormulas(propositionMapping.keySet()).sat() == Tristate.TRUE; - if (sat || Handler.aborted(handler)) { + final boolean sat = growSolver.satCall().handler(handler).addFormulas(propositionMapping.keySet()).sat() == Tristate.TRUE; + if (sat || !handler.shouldResume(NO_EVENT)) { return null; } final SATSolver hSolver = SATSolver.newSolver(f); while (true) { final SortedSet h = minimumHs(hSolver, propositionMapping.keySet(), handler); - if (h == null || Handler.aborted(handler)) { + if (h == null || !handler.shouldResume(NO_EVENT)) { return null; } final SortedSet c = grow(growSolver, h, propositionMapping.keySet(), handler); - if (Handler.aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } if (c == null) { @@ -122,7 +124,7 @@ public static

List

computeSmus(final FormulaFactory f */ public static List computeSmusForFormulas(final FormulaFactory f, final List formulas, final List additionalConstraints) { - return computeSmusForFormulas(f, formulas, additionalConstraints, null); + return computeSmusForFormulas(f, formulas, additionalConstraints, NopHandler.get()); } /** @@ -137,30 +139,30 @@ public static List computeSmusForFormulas(final FormulaFactory f, final */ public static List computeSmusForFormulas(final FormulaFactory f, final List formulas, final List additionalConstraints, - final OptimizationHandler handler) { + final ComputationHandler handler) { final List props = formulas.stream().map(StandardProposition::new).collect(Collectors.toList()); final List smus = computeSmus(f, props, additionalConstraints, handler); return smus == null ? null : smus.stream().map(Proposition::formula).collect(Collectors.toList()); } private static SortedSet minimumHs(final SATSolver hSolver, final Set variables, - final OptimizationHandler handler) { + final ComputationHandler handler) { final Assignment minimumHsModel = hSolver.execute(OptimizationFunction.builder() .handler(handler) .literals(variables) .minimize().build()); - return Handler.aborted(handler) ? null : new TreeSet<>(minimumHsModel.positiveVariables()); + return !handler.shouldResume(NO_EVENT) ? null : new TreeSet<>(minimumHsModel.positiveVariables()); } private static SortedSet grow(final SATSolver growSolver, final SortedSet h, - final Set variables, final OptimizationHandler handler) { + final Set variables, final ComputationHandler handler) { final SolverState solverState = growSolver.saveState(); growSolver.add(h); final Assignment maxModel = growSolver.execute(OptimizationFunction.builder() .handler(handler) .literals(variables) .maximize().build()); - if (maxModel == null || Handler.aborted(handler)) { + if (maxModel == null || !handler.shouldResume(NO_EVENT)) { return null; } else { final SortedSet maximumSatisfiableSet = maxModel.positiveVariables(); diff --git a/src/main/java/com/booleworks/logicng/formulas/Formula.java b/src/main/java/com/booleworks/logicng/formulas/Formula.java index 9461d9ed..33fbe086 100644 --- a/src/main/java/com/booleworks/logicng/formulas/Formula.java +++ b/src/main/java/com/booleworks/logicng/formulas/Formula.java @@ -10,6 +10,7 @@ import com.booleworks.logicng.functions.NumberOfAtomsFunction; import com.booleworks.logicng.functions.NumberOfNodesFunction; import com.booleworks.logicng.functions.VariablesFunction; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.knowledgecompilation.bdds.BDD; import com.booleworks.logicng.knowledgecompilation.bdds.BDDFactory; import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; @@ -356,7 +357,7 @@ default BDD bdd(final FormulaFactory f, final VariableOrderingProvider provider) } else { kernel = new BDDKernel(f, provider.getOrder(f, formula), varNum * 30, varNum * 20); } - return BDDFactory.build(f, formula, kernel, null); + return BDDFactory.build(f, formula, kernel, NopHandler.get()); } /** diff --git a/src/main/java/com/booleworks/logicng/handlers/BDDHandler.java b/src/main/java/com/booleworks/logicng/handlers/BDDHandler.java deleted file mode 100644 index bd2b143f..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/BDDHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; - -/** - * Interface for a handler for the BDD factory. - * @version 2.1.0 - * @since 1.6.2 - */ -public interface BDDHandler extends Handler { - - /** - * This method is called every time a new reference is added, i.e. the - * method {@link BDDKernel#addRef(int, BDDHandler)} is called. - * @return {@code true} if the BDD generation should be continued, otherwise - * {@code false} - */ - default boolean newRefAdded() { - return true; - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/ComputationHandler.java b/src/main/java/com/booleworks/logicng/handlers/ComputationHandler.java index 3d859a64..363c6e95 100644 --- a/src/main/java/com/booleworks/logicng/handlers/ComputationHandler.java +++ b/src/main/java/com/booleworks/logicng/handlers/ComputationHandler.java @@ -1,25 +1,24 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - package com.booleworks.logicng.handlers; +import com.booleworks.logicng.handlers.events.LogicNGEvent; + /** - * A computation handler. - * @version 1.6.2 - * @since 1.6.2 + * Interface for a computation handler. + * @since 3.0.0 + * @version 3.0.0 */ -public abstract class ComputationHandler implements Handler { - - protected boolean aborted; - - @Override - public boolean aborted() { - return aborted; - } +public interface ComputationHandler { + /** + * Processes the given event and returns {@code true} if the computation + * should be resumed and {@code false} if it should be aborted. + * @param event the event to handle, must not be {@code null} + * @return whether the computation should be resumed or not + */ + boolean shouldResume(LogicNGEvent event); - @Override - public void started() { - aborted = false; - } + /** + * @deprecated should be removed + */ + @Deprecated + boolean isAborted(); } diff --git a/src/main/java/com/booleworks/logicng/handlers/DnnfCompilationHandler.java b/src/main/java/com/booleworks/logicng/handlers/DnnfCompilationHandler.java deleted file mode 100644 index 88dfc3fc..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/DnnfCompilationHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * Interface for a handler for DNNF compilations. - * @version 2.1.0 - * @since 2.0.0 - */ -public interface DnnfCompilationHandler extends Handler { - - /** - * This method is called when a Shannon expansion was performed. - * @return {@code true} when the computation should be continued, - * {@code false} if it should be aborted with a - * {@link java.util.concurrent.TimeoutException} - */ - default boolean shannonExpansion() { - return true; - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/FactorizationHandler.java b/src/main/java/com/booleworks/logicng/handlers/FactorizationHandler.java deleted file mode 100644 index 6d363e8e..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/FactorizationHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.formulas.Formula; - -/** - * A handler for factorization methods (CNF, DNF). - * @version 2.1.0 - * @since 1.0 - */ -public interface FactorizationHandler extends Handler { - - /** - * This method is called every time a distribution is performed. - * @return {@code true} if the factorization should be continued, otherwise - * {@code false} - */ - default boolean performedDistribution() { - return true; - } - - /** - * This method is called every time a new clause is created. - * @param clause the clause - * @return {@code true} if the factorization should be continued, otherwise - * {@code false} - */ - default boolean createdClause(final Formula clause) { - return true; - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/Handler.java b/src/main/java/com/booleworks/logicng/handlers/Handler.java deleted file mode 100644 index c86b4595..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/Handler.java +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * Interface for a handler. A handler can be used as callback for different - * time-intensive computations in order to abort these computations. There are - * same often used default handlers already implemented and users can implement - * their own handlers by implementing the respective interfaces. - * @version 2.1.0 - * @since 1.6.2 - */ -public interface Handler { - - /** - * Returns whether the computation was aborted by the handler. - * @return {@code true} if the computation was aborted by the handler, - * otherwise {@code false} - */ - default boolean aborted() { - return false; - } - - /** - * This method is called when the computation starts. - */ - default void started() { - - } - - /** - * Returns {@code true} if the handler is not {@code null} and is already - * aborted. - * @param handler the handler to check - * @return {@code true} if the handler is not {@code null} and is already - * aborted, otherwise {@code false} - */ - static boolean aborted(final Handler handler) { - return handler != null && handler.aborted(); - } - - /** - * Null-safe helper method to start a handler. - * @param handler the handler to start, may be {@code null} - */ - static void start(final Handler handler) { - if (handler != null) { - handler.started(); - } - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/MaxSATHandler.java b/src/main/java/com/booleworks/logicng/handlers/MaxSATHandler.java deleted file mode 100644 index 69667bfe..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/MaxSATHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.datastructures.Assignment; - -/** - * Interface for a handler for MaxSAT solvers. - * @version 2.1.0 - * @since 1.0 - */ -public interface MaxSATHandler extends Handler { - - /** - * Returns a SAT handler which can be used to cancel internal SAT calls of - * the MaxSAT solver. - * @return a SAT handler - */ - SATHandler satHandler(); - - @Override - default boolean aborted() { - return satHandler() != null && satHandler().aborted(); - } - - /** - * This method is called when the MaxSAT solver found a new lower bound for - * a solution. - * @param lowerBound the cost of the lower bound - * @param model the model of the lower bound, may be null if not - * applicable - * @return {@code true} if the solving process should be continued, - * otherwise {@code false} - */ - boolean foundLowerBound(final int lowerBound, final Assignment model); - - /** - * This method is called when the MaxSAT solver found a new upper bound for - * a solution. - * @param upperBound the cost of the upper bound - * @param model the model of the upper bound, may be null if not - * applicable - * @return {@code true} if the solving process should be continued, - * otherwise {@code false} - */ - boolean foundUpperBound(final int upperBound, final Assignment model); - - /** - * This method is called when the MaxSAT solver finished solving. - */ - default void finishedSolving() { - - } - - /** - * Returns the last approximation of the result or -1 if there is no - * approximation for the lower bound. If the handler does not cancel the - * solving process, it is not guaranteed that this method will return the - * optimal result. Use the respective method of the MaxSAT solver instead. - * @return the last approximation of the result or -1 if no approximation is - * known - */ - int lowerBoundApproximation(); - - /** - * Returns the last approximation of the result or -1 if there is no - * approximation for the lower bound. If the handler does not cancel the - * solving process, it is not guaranteed that this method will return the - * optimal result. Use the respective method of the MaxSAT solver instead. - * @return the last approximation of the result or -1 if no approximation is - * known - */ - int upperBoundApproximation(); -} diff --git a/src/main/java/com/booleworks/logicng/handlers/ModelEnumerationHandler.java b/src/main/java/com/booleworks/logicng/handlers/ModelEnumerationHandler.java deleted file mode 100644 index 4caabfca..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/ModelEnumerationHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * Interface for a handler for the enumeration of models. - * @version 3.0.0 - * @since 3.0.0 - */ -public interface ModelEnumerationHandler extends Handler { - - /** - * Returns a SAT handler which can be used to cancel internal SAT calls of - * the model enumeration process. - * @return a SAT handler - */ - SATHandler satHandler(); - - @Override - default boolean aborted() { - return satHandler() != null && satHandler().aborted(); - } - - /** - * This method is called every time new models are found. - *

- * The found models are in an uncommitted state until they are confirmed by - * calling {@link #commit()}. It is also possible to roll back the - * uncommitted models by calling {@link #rollback()}. - * @param numberOfModels the number of found models - * @return {@code true} if the computation should continue, otherwise - * {@code false} - */ - boolean foundModels(int numberOfModels); - - /** - * All founds models since the last commit call are confirmed and cannot be - * rolled back. - * @return {@code true} if the computation should continue, otherwise - * {@code false} - */ - boolean commit(); - - /** - * All found models since the last commit should be discarded. - * @return {@code true} if the computation should continue, otherwise - * {@code false} - */ - boolean rollback(); -} diff --git a/src/main/java/com/booleworks/logicng/handlers/NopHandler.java b/src/main/java/com/booleworks/logicng/handlers/NopHandler.java new file mode 100644 index 00000000..8f2233cc --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/NopHandler.java @@ -0,0 +1,36 @@ +package com.booleworks.logicng.handlers; + +import com.booleworks.logicng.handlers.events.LogicNGEvent; + +/** + * A computation handler which never aborts the computation. + *

+ * {@link #get()} returns the one and only instance of the class. + * @version 3.0.0 + * @since 3.0.0 + */ +public class NopHandler implements ComputationHandler { + + private static final NopHandler INSTANCE = new NopHandler(); + + private NopHandler() { + } + + /** + * Returns the singleton instance of this class. + * @return the singleton instance of this class + */ + public static NopHandler get() { + return INSTANCE; + } + + @Override + public boolean shouldResume(final LogicNGEvent event) { + return true; + } + + @Override + public boolean isAborted() { + return false; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/NumberOfModelsHandler.java b/src/main/java/com/booleworks/logicng/handlers/NumberOfModelsHandler.java index d2312b32..e4f569bd 100644 --- a/src/main/java/com/booleworks/logicng/handlers/NumberOfModelsHandler.java +++ b/src/main/java/com/booleworks/logicng/handlers/NumberOfModelsHandler.java @@ -4,14 +4,20 @@ package com.booleworks.logicng.handlers; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.EnumerationFoundModelsEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; +import com.booleworks.logicng.handlers.events.SimpleEvent; + /** * A model enumeration handler that terminates the solving process after a given * number of models. * @version 3.0.0 * @since 3.0.0 */ -public class NumberOfModelsHandler extends ComputationHandler implements ModelEnumerationHandler { +public class NumberOfModelsHandler implements ComputationHandler { + private boolean aborted = false; private final int bound; private int countCommitted; private int countUncommitted; @@ -31,38 +37,27 @@ public NumberOfModelsHandler(final int bound) { } @Override - public void started() { - super.started(); - countCommitted = 0; - countUncommitted = 0; + public boolean isAborted() { + return aborted; } @Override - public SATHandler satHandler() { - return null; - } - - @Override - public boolean foundModels(final int numberOfModels) { - aborted = countUncommitted + countCommitted + numberOfModels > bound; - if (!aborted) { - countUncommitted += numberOfModels; - return true; - } else { - return false; + public boolean shouldResume(final LogicNGEvent event) { + if (event == ComputationStartedEvent.MODEL_ENUMERATION_STARTED) { + countCommitted = 0; + countUncommitted = 0; + } else if (event instanceof EnumerationFoundModelsEvent) { + final int numberOfModels = ((EnumerationFoundModelsEvent) event).getNumberOfModels(); + aborted = countUncommitted + countCommitted + numberOfModels > bound; + if (!aborted) { + countUncommitted += numberOfModels; + } + } else if (event == SimpleEvent.MODEL_ENUMERATION_COMMIT) { + countCommitted += countUncommitted; + countUncommitted = 0; + } else if (event == SimpleEvent.MODEL_ENUMERATION_ROLLBACK) { + countUncommitted = 0; } - } - - @Override - public boolean commit() { - countCommitted += countUncommitted; - countUncommitted = 0; - return true; - } - - @Override - public boolean rollback() { - countUncommitted = 0; - return true; + return !aborted; } } diff --git a/src/main/java/com/booleworks/logicng/handlers/NumberOfNodesBDDHandler.java b/src/main/java/com/booleworks/logicng/handlers/NumberOfNodesBDDHandler.java index b227a7c0..7ca71a58 100644 --- a/src/main/java/com/booleworks/logicng/handlers/NumberOfNodesBDDHandler.java +++ b/src/main/java/com/booleworks/logicng/handlers/NumberOfNodesBDDHandler.java @@ -4,14 +4,20 @@ package com.booleworks.logicng.handlers; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.BDD_COMPUTATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.BDD_NEW_REF_ADDED; + +import com.booleworks.logicng.handlers.events.LogicNGEvent; + /** * A BDD handler which cancels the build process after a given number of added * nodes. - * @version 1.6.2 - * @since 1.6.2 + * @version 3.0.0 + * @since 3.0.0 */ -public class NumberOfNodesBDDHandler extends ComputationHandler implements BDDHandler { +public class NumberOfNodesBDDHandler implements ComputationHandler { + private boolean aborted = false; private final int bound; private int count; @@ -28,14 +34,17 @@ public NumberOfNodesBDDHandler(final int bound) { } @Override - public void started() { - super.started(); - count = 0; + public boolean shouldResume(final LogicNGEvent event) { + if (event == BDD_COMPUTATION_STARTED) { + count = 0; + } else if (event == BDD_NEW_REF_ADDED) { + aborted = ++count >= bound; + } + return !aborted; } @Override - public boolean newRefAdded() { - aborted = ++count >= bound; - return !aborted; + public boolean isAborted() { + return aborted; } } diff --git a/src/main/java/com/booleworks/logicng/handlers/OptimizationHandler.java b/src/main/java/com/booleworks/logicng/handlers/OptimizationHandler.java deleted file mode 100644 index eb65a567..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/OptimizationHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.datastructures.Assignment; - -import java.util.function.Supplier; - -/** - * Interface for an optimization handler. - * @version 2.1.0 - * @since 2.1.0 - */ -public interface OptimizationHandler extends Handler { - - /** - * Returns a SAT handler which can be used to cancel internal SAT calls of - * the optimization function. - * @return a SAT handler - */ - SATHandler satHandler(); - - @Override - default boolean aborted() { - return satHandler() != null && satHandler().aborted(); - } - - /** - * This method is called when the solver found a better bound for the - * optimization. - * @param currentResultProvider a provider for the current result, can be - * used to examine the current result or to use - * this result if the optimization should be - * aborted - * @return {@code true} if the optimization process should be continued, - * otherwise {@code false} - */ - default boolean foundBetterBound(final Supplier currentResultProvider) { - return true; - } - - /** - * Returns a SAT handler if the optimization handler is not {@code null}. - * @param handler the optimization handler - * @return The SAT handler if the optimization handler is not {@code null}, - * otherwise {@code null} - */ - static SATHandler satHandler(final OptimizationHandler handler) { - return handler == null ? null : handler.satHandler(); - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/SATHandler.java b/src/main/java/com/booleworks/logicng/handlers/SATHandler.java deleted file mode 100644 index 4befdfae..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/SATHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * Interface for a handler for SAT solvers. - * @version 2.1.0 - * @since 1.0 - */ -public interface SATHandler extends Handler { - - /** - * This method is called every time a conflict is found. - * @return {@code true} if the SAT solving should be continued, otherwise - * {@code false} - */ - default boolean detectedConflict() { - return true; - } - - /** - * This method is called when the SAT solver finished solving. - */ - default void finishedSolving() { - - } - - /** - * Null-safe helper method to call {@link SATHandler#finishedSolving} on a - * handler. - * @param handler the handler to finished, may be {@code null} - */ - static void finishSolving(final SATHandler handler) { - if (handler != null) { - handler.finishedSolving(); - } - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutBDDHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutBDDHandler.java deleted file mode 100644 index 6b89f2ba..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutBDDHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; - -/** - * A BDD handler which cancels the build process after a given timeout. - * @version 2.1.0 - * @since 1.6.2 - */ -public class TimeoutBDDHandler extends TimeoutHandler implements BDDHandler { - - /** - * Constructs a new timeout handler with a given timeout and a timeout type. - * The interpretation of the timeout depends on the timeout type: - *

    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • - *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • - *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed - * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • - *
- * Note that it might take a few milliseconds more until the build process - * is actually canceled, since the handler depends on the BDD factory's call - * to {@link BDDKernel#addRef(int, BDDHandler)}. - * @param timeout the timeout in milliseconds, its meaning is defined by the - * timeout type - * @param type the type of the timer, must not be {@code null} - */ - public TimeoutBDDHandler(final long timeout, final TimerType type) { - super(timeout, type); - } - - /** - * Constructs a new timeout handler with a given timeout and uses the - * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. - * @param timeout the timeout in milliseconds - */ - public TimeoutBDDHandler(final long timeout) { - super(timeout); - } - - @Override - public boolean newRefAdded() { - return !timeLimitExceeded(); - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutDnnfHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutDnnfHandler.java deleted file mode 100644 index d65d5083..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutDnnfHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * A DNNF handler which cancels the compilation process after a given timeout. - * @version 3.0.0 - * @since 3.0.0 - */ -public class TimeoutDnnfHandler extends TimeoutHandler implements DnnfCompilationHandler { - - /** - * Constructs a new timeout handler with a given timeout and a timeout type. - * The interpretation of the timeout depends on the timeout type: - *
    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • - *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • - *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed - * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • - *
- * @param timeout the timeout in milliseconds, its meaning is defined by the - * timeout type - * @param type the type of the timer, must not be {@code null} - */ - public TimeoutDnnfHandler(final long timeout, final TimerType type) { - super(timeout, type); - } - - /** - * Constructs a new timeout handler with a given timeout and uses the - * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. - * @param timeout the timeout in milliseconds - */ - public TimeoutDnnfHandler(final long timeout) { - super(timeout); - } - - @Override - public boolean shannonExpansion() { - return !timeLimitExceeded(); - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutHandler.java index 17c8cad0..5333b31e 100644 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutHandler.java +++ b/src/main/java/com/booleworks/logicng/handlers/TimeoutHandler.java @@ -4,36 +4,38 @@ package com.booleworks.logicng.handlers; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; + /** - * An abstract timeout handler. - * @version 2.1.0 - * @since 1.6.2 + * A generic timeout handler. + * @version 3.0.0 + * @since 3.0.0 */ -public abstract class TimeoutHandler extends ComputationHandler { +public class TimeoutHandler implements ComputationHandler { + protected boolean aborted = false; protected long timeout; protected final TimerType type; protected long designatedEnd; /** - * Constructs a new abstract timeout handler with a given timeout and a - * timeout type. The interpretation of the timeout depends on the timeout - * type: + * Constructs a new timeout handler with a given timeout and a timeout + * type. The interpretation of the timeout depends on the timeout type: *
    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • + *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when a + * {@link ComputationStartedEvent} is received. Further + * {@link ComputationStartedEvent}s have no effect on the timeout. Thus, + * the timeout can only be started once.
  • *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • + * a {@link ComputationStartedEvent} is received. *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • + * aborted. *
* Note that it might take a few milliseconds more until the computation is - * actually canceled, since the cancellation depends on the next call to the - * handler. + * actually canceled, since the cancellation depends on the next call to + * {@link #shouldResume}. * @param timeout the timeout in milliseconds, its meaning is defined by the * timeout type * @param type the type of the timer, must not be {@code null} @@ -45,10 +47,10 @@ public TimeoutHandler(final long timeout, final TimerType type) { } /** - * Constructs a new abstract timeout handler with a given timeout and uses - * the timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. + * Constructs a new timeout handler with a given timeout and uses the + * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is + * started when the handler receives a {@link ComputationStartedEvent}, + * further events of this type have no effect on the timeout. * @param timeout the timeout in milliseconds */ public TimeoutHandler(final long timeout) { @@ -56,11 +58,18 @@ public TimeoutHandler(final long timeout) { } @Override - public void started() { - super.started(); - if (type == TimerType.RESTARTING_TIMEOUT || designatedEnd == 0) { - designatedEnd = System.currentTimeMillis() + timeout; + public boolean shouldResume(final LogicNGEvent event) { + if (event instanceof ComputationStartedEvent) { + if (type == TimerType.RESTARTING_TIMEOUT || designatedEnd == 0) { + designatedEnd = System.currentTimeMillis() + timeout; + } } + return !timeLimitExceeded(); + } + + @Override + public boolean isAborted() { + return timeLimitExceeded(); } /** @@ -68,8 +77,8 @@ public void started() { * @return {@code true} if the current time exceeds the timeout limit, * otherwise {@code false} */ - protected boolean timeLimitExceeded() { - aborted = System.currentTimeMillis() >= designatedEnd; + private boolean timeLimitExceeded() { + aborted = designatedEnd > 0 && System.currentTimeMillis() >= designatedEnd; return aborted; } @@ -86,26 +95,22 @@ public long getDesignatedEnd() { */ public enum TimerType { /** - * Simple timeout which is started when {@link Handler#started()} is - * called. + * Simple timeout which is started when a + * {@link ComputationStartedEvent} is received. *

- * Multiple calls to {@link Handler#started()} do not restart the - * timeout. + * Further {@link ComputationStartedEvent}s do not restart the timeout. */ SINGLE_TIMEOUT, /** - * Timeout which is restarted on every call to - * {@link Handler#started()}. + * Timeout which is restarted every time a + * {@link ComputationStartedEvent} is received. */ RESTARTING_TIMEOUT, /** * Timeout which is interpreted as fixed point in time (in milliseconds) * at which the computation should be aborted. - *

- * The method {@link Handler#started()} must still be called, but does - * not have an effect on the timeout. */ FIXED_END } diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandler.java deleted file mode 100644 index efb1d65a..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandler.java +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.datastructures.Assignment; - -/** - * A MaxSAT handler which cancels the solving process after a given timeout. - * @version 2.1.0 - * @since 1.0 - */ -public class TimeoutMaxSATHandler extends TimeoutHandler implements MaxSATHandler { - - private TimeoutSATHandler satHandler; - private int currentLb; - private int currentUb; - - /** - * Constructs a new timeout handler with a given timeout and a timeout type. - * The interpretation of the timeout depends on the timeout type: - *

    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • - *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • - *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed - * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • - *
- * Note that it might take a few milliseconds more until the solver is - * actually canceled, since the handler depends on the solvers call to - * {@code foundApproximation()} or {@link SATHandler#detectedConflict()}. - * @param timeout the timeout in milliseconds, its meaning is defined by the - * timeout type - * @param type the type of the timer, must not be {@code null} - */ - public TimeoutMaxSATHandler(final long timeout, final TimerType type) { - super(timeout, type); - currentLb = -1; - currentUb = -1; - } - - /** - * Constructs a new timeout handler with a given timeout and uses the - * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. - * @param timeout the timeout in milliseconds - */ - public TimeoutMaxSATHandler(final long timeout) { - super(timeout); - } - - @Override - public void started() { - super.started(); - if (satHandler == null || type == TimerType.RESTARTING_TIMEOUT) { - satHandler = new TimeoutSATHandler(designatedEnd, TimerType.FIXED_END); - } - currentLb = -1; - currentUb = -1; - } - - @Override - public boolean aborted() { - return super.aborted() || Handler.aborted(satHandler); - } - - /** - * Returns a SAT handler which can be used to cancel internal SAT calls of - * the model enumeration process. Note that this handler will only be - * available after the first call to {@link #started()}. - * @return the SAT handler - */ - @Override - public SATHandler satHandler() { - return satHandler; - } - - @Override - public boolean foundLowerBound(final int lowerBound, final Assignment model) { - currentLb = lowerBound; - return !timeLimitExceeded(); - } - - @Override - public boolean foundUpperBound(final int upperBound, final Assignment model) { - currentUb = upperBound; - return !timeLimitExceeded(); - } - - @Override - public void finishedSolving() { - // nothing to do here - } - - @Override - public int lowerBoundApproximation() { - return currentLb; - } - - @Override - public int upperBoundApproximation() { - return currentUb; - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandler.java deleted file mode 100644 index 2df1dfff..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandler.java +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * A model enumeration handler which cancels the computation process after a - * given timeout. - * @version 3.0.0 - * @since 3.0.0 - */ -public class TimeoutModelEnumerationHandler extends TimeoutHandler implements ModelEnumerationHandler { - - private TimeoutSATHandler satHandler; - - /** - * Constructs a new timeout handler with a given timeout and a timeout type. - * The interpretation of the timeout depends on the timeout type: - *
    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • - *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • - *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed - * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • - *
- * Note that it might take a few milliseconds more until the computation is - * actually canceled, since the handler depends on the next found model. - * @param timeout the timeout in milliseconds, its meaning is defined by the - * timeout type - * @param type the type of the timer, must not be {@code null} - */ - public TimeoutModelEnumerationHandler(final long timeout, final TimerType type) { - super(timeout, type); - } - - /** - * Constructs a new timeout handler with a given timeout and uses the - * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. - * @param timeout the timeout in milliseconds - */ - public TimeoutModelEnumerationHandler(final long timeout) { - super(timeout); - } - - /** - * Returns a SAT handler which can be used to cancel internal SAT calls of - * the model enumeration process. Note that this handler will only be - * available after the first call to {@link #started()}. - * @return the SAT handler - */ - @Override - public SATHandler satHandler() { - return satHandler; - } - - @Override - public boolean aborted() { - return super.aborted() || Handler.aborted(satHandler); - } - - @Override - public void started() { - super.started(); - if (satHandler == null || type == TimerType.RESTARTING_TIMEOUT) { - satHandler = new TimeoutSATHandler(designatedEnd, TimerType.FIXED_END); - } - } - - @Override - public boolean foundModels(final int numberOfModel) { - return !timeLimitExceeded(); - } - - @Override - public boolean commit() { - return !timeLimitExceeded(); - } - - @Override - public boolean rollback() { - return !timeLimitExceeded(); - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandler.java deleted file mode 100644 index 135807b3..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandler.java +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -import com.booleworks.logicng.datastructures.Assignment; - -import java.util.function.Supplier; - -/** - * An optimization handler which cancels the computation process after a given - * timeout. - * @version 2.1.0 - * @since 2.1.0 - */ -public class TimeoutOptimizationHandler extends TimeoutHandler implements OptimizationHandler { - - private TimeoutSATHandler satHandler; - private Supplier lastModelProvider; - - /** - * Constructs a new timeout handler with a given timeout and a timeout type. - * The interpretation of the timeout depends on the timeout type: - *
    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • - *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • - *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed - * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • - *
- * Note that it might take a few milliseconds more until the computation is - * actually canceled, since the handler depends on the next found model. - * @param timeout the timeout in milliseconds, its meaning is defined by the - * timeout type - * @param type the type of the timer, must not be {@code null} - */ - public TimeoutOptimizationHandler(final long timeout, final TimerType type) { - super(timeout, type); - } - - /** - * Constructs a new timeout handler with a given timeout and uses the - * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. - * @param timeout the timeout in milliseconds - */ - public TimeoutOptimizationHandler(final long timeout) { - super(timeout); - } - - /** - * Returns a SAT handler which can be used to cancel internal SAT calls of - * the model enumeration process. Note that this handler will only be - * available after the first call to {@link #started()}. - * @return the SAT handler - */ - @Override - public SATHandler satHandler() { - return satHandler; - } - - @Override - public boolean aborted() { - return super.aborted() || Handler.aborted(satHandler); - } - - @Override - public void started() { - super.started(); - if (satHandler == null || type == TimerType.RESTARTING_TIMEOUT) { - satHandler = new TimeoutSATHandler(designatedEnd, TimerType.FIXED_END); - } - lastModelProvider = null; - } - - @Override - public boolean foundBetterBound(final Supplier lastModelProvider) { - this.lastModelProvider = lastModelProvider; - return !timeLimitExceeded(); - } - - /** - * Returns the latest intermediate result of the optimization or - * {@code null} if no such result was yet computed. - * @return the latest intermediate result - */ - public Assignment getIntermediateResult() { - return lastModelProvider == null ? null : lastModelProvider.get(); - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/TimeoutSATHandler.java b/src/main/java/com/booleworks/logicng/handlers/TimeoutSATHandler.java deleted file mode 100644 index 279fe382..00000000 --- a/src/main/java/com/booleworks/logicng/handlers/TimeoutSATHandler.java +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 and MIT -// Copyright 2015-2023 Christoph Zengler -// Copyright 2023-20xx BooleWorks GmbH - -package com.booleworks.logicng.handlers; - -/** - * A SAT handler which cancels the solving process after a given timeout. - * @version 2.1.0 - * @since 1.0 - */ -public class TimeoutSATHandler extends TimeoutHandler implements SATHandler { - - /** - * Constructs a new timeout handler with a given timeout and a timeout type. - * The interpretation of the timeout depends on the timeout type: - *
    - *
  • {@link TimerType#SINGLE_TIMEOUT}: The timeout is started when - * {@link Handler#started()} is called. Further calls to - * {@link Handler#started()} have no effect on the timeout. Thus, the - * timeout can only be started once.
  • - *
  • {@link TimerType#RESTARTING_TIMEOUT}: The timeout is restarted when - * {@link Handler#started()} is called.
  • - *
  • {@link TimerType#FIXED_END}: Timeout which is interpreted as fixed - * point in time (in milliseconds) at which the computation should be - * aborted. The method {@link Handler#started()} must still be called, but - * does not have an effect on the timeout.
  • - *
- * Note that it might take a few milliseconds more until the sat solver is - * actually canceled, since the handler depends on the solvers call to - * {@link SATHandler#detectedConflict()}. - * @param timeout the timeout in milliseconds, its meaning is defined by the - * timeout type - * @param type the type of the timer, must not be {@code null} - */ - public TimeoutSATHandler(final long timeout, final TimerType type) { - super(timeout, type); - } - - /** - * Constructs a new timeout handler with a given timeout and uses the - * timeout type {@link TimerType#SINGLE_TIMEOUT}. Thus, the timeout is - * started when {@link Handler#started()} is called and further calls to - * {@link Handler#started()} have no effect on the timeout. - * @param timeout the timeout in milliseconds - */ - public TimeoutSATHandler(final long timeout) { - super(timeout); - } - - @Override - public boolean detectedConflict() { - return !timeLimitExceeded(); - } -} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/ComputationFinishedEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/ComputationFinishedEvent.java new file mode 100644 index 00000000..1f918594 --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/ComputationFinishedEvent.java @@ -0,0 +1,43 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.handlers.ComputationHandler; + +/** + * A class for {@link LogicNGEvent}s which indicate the end of a computation. + * By convention, these events are instantiated as {@code static final} fields + * s.t. they can be checked in {@link ComputationHandler handlers} by using + * referential equality. + *

+ * The {@link #computationType} should only be used for debugging purposes. + * @version 3.0.0 + * @since 3.0.0 + */ +public class ComputationFinishedEvent implements LogicNGEvent { + + public static final ComputationFinishedEvent SAT_CALL_FINISHED = new ComputationFinishedEvent("SAT Call"); + public static final ComputationFinishedEvent MAX_SAT_CALL_FINISHED = new ComputationFinishedEvent("MaxSAT Call"); + + private final String computationType; + + /** + * Creates a new event for the given computation type. + * @param computationType the computation type + */ + + public ComputationFinishedEvent(final String computationType) { + this.computationType = computationType; + } + + /** + * Returns the computation type. + * @return the computation type + */ + public String getComputationType() { + return computationType; + } + + @Override + public String toString() { + return "Event: Finished " + computationType; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/ComputationStartedEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/ComputationStartedEvent.java new file mode 100644 index 00000000..edf2dc12 --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/ComputationStartedEvent.java @@ -0,0 +1,56 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; + +/** + * A class for {@link LogicNGEvent}s which indicate the start of a computation. + * By convention, these events are instantiated as {@code static final} fields + * s.t. they can be checked in {@link ComputationHandler handlers} by using + * referential equality. On the other hand, some handlers (like the + * {@link TimeoutHandler}) may just check for any + * {@link ComputationStartedEvent} via {@code instanceof}. + *

+ * The {@link #computationType} should only be used for debugging purposes. + * @version 3.0.0 + * @since 3.0.0 + */ +public class ComputationStartedEvent implements LogicNGEvent { + + public static final ComputationStartedEvent FACTORIZATION_STARTED = new ComputationStartedEvent("Factorization"); + public static final ComputationStartedEvent BDD_COMPUTATION_STARTED = new ComputationStartedEvent("BDD Computation"); + public static final ComputationStartedEvent DNNF_COMPUTATION_STARTED = new ComputationStartedEvent("DNNF Computation"); + public static final ComputationStartedEvent SAT_CALL_STARTED = new ComputationStartedEvent("SAT Call"); + public static final ComputationStartedEvent MAX_SAT_CALL_STARTED = new ComputationStartedEvent("MaxSAT Call"); + public static final ComputationStartedEvent BACKBONE_COMPUTATION_STARTED = new ComputationStartedEvent("Backbone Computation"); + public static final ComputationStartedEvent ADVANCED_SIMPLIFICATION_STARTED = new ComputationStartedEvent("Advanced Simplification"); + public static final ComputationStartedEvent PRIME_COMPUTATION_STARTED = new ComputationStartedEvent("Prime Computation"); + public static final ComputationStartedEvent IMPLICATE_REDUCTION_STARTED = new ComputationStartedEvent("Implicate Reduction"); + public static final ComputationStartedEvent MUS_COMPUTATION_STARTED = new ComputationStartedEvent("MUS Computation"); + public static final ComputationStartedEvent SMUS_COMPUTATION_STARTED = new ComputationStartedEvent("SMUS Computation"); + public static final ComputationStartedEvent OPTIMIZATION_FUNCTION_STARTED = new ComputationStartedEvent("Optimization Function"); + public static final ComputationStartedEvent MODEL_ENUMERATION_STARTED = new ComputationStartedEvent("Model Enumeration"); + + private final String computationType; + + /** + * Creates a new event for the given computation type. + * @param computationType the computation type + */ + public ComputationStartedEvent(final String computationType) { + this.computationType = computationType; + } + + /** + * Returns the computation type. + * @return the computation type + */ + public String getComputationType() { + return computationType; + } + + @Override + public String toString() { + return "Event: Started " + computationType; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/EnumerationFoundModelsEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/EnumerationFoundModelsEvent.java new file mode 100644 index 00000000..11c675c4 --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/EnumerationFoundModelsEvent.java @@ -0,0 +1,38 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.solvers.functions.ModelEnumerationFunction; + +/** + * An event created when the {@link ModelEnumerationFunction} found a new set + * of models. + *

+ * Note that, due to the way the model enumeration function works, this event + * will not be fired for all models. + * @version 3.0.0 + * @since 3.0.0 + */ +public class EnumerationFoundModelsEvent implements LogicNGEvent { + + private final int numberOfModels; + + /** + * Creates a new event with the given number of models. + * @param numberOfModels the number of models which were found + */ + public EnumerationFoundModelsEvent(final int numberOfModels) { + this.numberOfModels = numberOfModels; + } + + /** + * Returns the number of models. + * @return the number of models + */ + public int getNumberOfModels() { + return numberOfModels; + } + + @Override + public String toString() { + return "Event: Model enumeration found " + numberOfModels + " new models"; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/FactorizationCreatedClauseEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/FactorizationCreatedClauseEvent.java new file mode 100644 index 00000000..d3c03dec --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/FactorizationCreatedClauseEvent.java @@ -0,0 +1,38 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.formulas.Formula; +import com.booleworks.logicng.transformations.cnf.CNFFactorization; +import com.booleworks.logicng.transformations.dnf.DNFFactorization; + +/** + * An event created when a factorization algorithm (e.g. + * {@link DNFFactorization} or {@link CNFFactorization}) + * creates a new clause. + * @version 3.0.0 + * @since 3.0.0 + */ +public class FactorizationCreatedClauseEvent implements LogicNGEvent { + + private final Formula clause; + + /** + * Creates a new event with the clause which was created. + * @param clause the clause + */ + public FactorizationCreatedClauseEvent(final Formula clause) { + this.clause = clause; + } + + /** + * Returns the created clause. + * @return the created clause + */ + public Formula getClause() { + return clause; + } + + @Override + public String toString() { + return "Event: Created clause during factorization: " + clause; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/LogicNGEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/LogicNGEvent.java new file mode 100644 index 00000000..2fe9d699 --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/LogicNGEvent.java @@ -0,0 +1,11 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.handlers.ComputationHandler; + +/** + * An event which can be passed to a {@link ComputationHandler}. + * @version 3.0.0 + * @since 3.0.0 + */ +public interface LogicNGEvent { +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewLowerBoundEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewLowerBoundEvent.java new file mode 100644 index 00000000..e8ae545b --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewLowerBoundEvent.java @@ -0,0 +1,33 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.solvers.MaxSATSolver; + +/** + * An event created when a {@link MaxSATSolver} found a new lower bound. + * @version 3.0.0 + * @since 3.0.0 + */ +public class MaxSatNewLowerBoundEvent implements LogicNGEvent { + private final int bound; + + /** + * Creates a new event with the given lower bound. + * @param bound the new lower bound + */ + public MaxSatNewLowerBoundEvent(final int bound) { + this.bound = bound; + } + + /** + * Returns the new lower bound. + * @return the new lower bound + */ + public int getBound() { + return bound; + } + + @Override + public String toString() { + return "Event: New Max SAT lower bound: " + bound; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewUpperBoundEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewUpperBoundEvent.java new file mode 100644 index 00000000..db25d785 --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/MaxSatNewUpperBoundEvent.java @@ -0,0 +1,34 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.solvers.MaxSATSolver; + +/** + * An event created when a {@link MaxSATSolver} found a new upper bound. + * @version 3.0.0 + * @since 3.0.0 + */ +public class MaxSatNewUpperBoundEvent implements LogicNGEvent { + private final int bound; + + /** + * Creates a new event with the given upper bound. + * @param bound the new upper bound + */ + + public MaxSatNewUpperBoundEvent(final int bound) { + this.bound = bound; + } + + /** + * Returns the new upper bound. + * @return the new upper bound + */ + public int getBound() { + return bound; + } + + @Override + public String toString() { + return "Event: New Max SAT upper bound: " + bound; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/OptimizationFoundBetterBoundEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/OptimizationFoundBetterBoundEvent.java new file mode 100644 index 00000000..f8dcb311 --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/OptimizationFoundBetterBoundEvent.java @@ -0,0 +1,38 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.datastructures.Assignment; +import com.booleworks.logicng.solvers.functions.OptimizationFunction; + +import java.util.function.Supplier; + +/** + * An event created when the {@link OptimizationFunction} found a better + * bound. + * @version 3.0.0 + * @since 3.0.0 + */ +public class OptimizationFoundBetterBoundEvent implements LogicNGEvent { + + private final Supplier model; + + /** + * Creates a new event including a supplier to get the latest model. + * @param model the latest model + */ + public OptimizationFoundBetterBoundEvent(final Supplier model) { + this.model = model; + } + + /** + * Returns the supplier for the latest model. + * @return the supplier for the latest model + */ + public Supplier getModel() { + return model; + } + + @Override + public String toString() { + return "Event: Optimization Function found a better bound"; + } +} diff --git a/src/main/java/com/booleworks/logicng/handlers/events/SimpleEvent.java b/src/main/java/com/booleworks/logicng/handlers/events/SimpleEvent.java new file mode 100644 index 00000000..6bd6820d --- /dev/null +++ b/src/main/java/com/booleworks/logicng/handlers/events/SimpleEvent.java @@ -0,0 +1,41 @@ +package com.booleworks.logicng.handlers.events; + +import com.booleworks.logicng.handlers.ComputationHandler; + +/** + * A class for simple {@link LogicNGEvent} types which can basically be used + * as singletons. By convention, simple events are instantiated as + * {@code static final} fields s.t. they can be checked in + * {@link ComputationHandler handlers} by using referential equality. + *

+ * The {@link #description} should only be used for debugging purposes. + * @version 3.0.0 + * @since 3.0.0 + */ +public class SimpleEvent implements LogicNGEvent { + + public static final SimpleEvent NO_EVENT = new SimpleEvent("No event"); + public static final SimpleEvent DISTRIBUTION_PERFORMED = new SimpleEvent("Distribution performed"); + public static final SimpleEvent BDD_NEW_REF_ADDED = new SimpleEvent("New reference added in BDD"); + public static final SimpleEvent DNNF_SHANNON_EXPANSION = new SimpleEvent("DNNF Shannon Expansion"); + public static final SimpleEvent SAT_CONFLICT_DETECTED = new SimpleEvent("SAT conflict detected"); + public static final SimpleEvent MODEL_ENUMERATION_COMMIT = new SimpleEvent("Model Enumeration Commit"); + public static final SimpleEvent MODEL_ENUMERATION_ROLLBACK = new SimpleEvent("Model Enumeration Rollback"); + + private final String description; + + public SimpleEvent(final String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + @Override + public String toString() { + return "Event: " + description; + } + + // no equals and hashcode implementation -- should use referential equality +} diff --git a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDD.java b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDD.java index 8d455e0a..412d33ae 100644 --- a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDD.java +++ b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDD.java @@ -10,6 +10,7 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.knowledgecompilation.bdds.datastructures.BDDNode; import com.booleworks.logicng.knowledgecompilation.bdds.functions.BDDCNFFunction; import com.booleworks.logicng.knowledgecompilation.bdds.functions.BDDDNFFunction; @@ -144,7 +145,7 @@ public Formula toFormula(final FormulaFactory f, final boolean followPathsToTrue * @return the negation of this BDD */ public BDD negate() { - return new BDD(kernel.addRef(construction.not(index), null), kernel); + return new BDD(kernel.addRef(construction.not(index), NopHandler.get()), kernel); } /** @@ -159,7 +160,7 @@ public BDD implies(final BDD other) { if (other.kernel != kernel) { throw new IllegalArgumentException("Only BDDs with the same kernel can be processed"); } - return new BDD(kernel.addRef(construction.implication(index, other.index), null), kernel); + return new BDD(kernel.addRef(construction.implication(index, other.index), NopHandler.get()), kernel); } /** @@ -174,7 +175,7 @@ public BDD impliedBy(final BDD other) { if (other.kernel != kernel) { throw new IllegalArgumentException("Only BDDs with the same kernel can be processed"); } - return new BDD(kernel.addRef(construction.implication(other.index, index), null), kernel); + return new BDD(kernel.addRef(construction.implication(other.index, index), NopHandler.get()), kernel); } /** @@ -189,7 +190,7 @@ public BDD equivalence(final BDD other) { if (other.kernel != kernel) { throw new IllegalArgumentException("Only BDDs with the same kernel can be processed"); } - return new BDD(kernel.addRef(construction.equivalence(index, other.index), null), kernel); + return new BDD(kernel.addRef(construction.equivalence(index, other.index), NopHandler.get()), kernel); } /** @@ -204,7 +205,7 @@ public BDD and(final BDD other) { if (other.kernel != kernel) { throw new IllegalArgumentException("Only BDDs with the same kernel can be processed"); } - return new BDD(kernel.addRef(construction.and(index, other.index), null), kernel); + return new BDD(kernel.addRef(construction.and(index, other.index), NopHandler.get()), kernel); } /** @@ -219,7 +220,7 @@ public BDD or(final BDD other) { if (other.kernel != kernel) { throw new IllegalArgumentException("Only BDDs with the same kernel can be processed"); } - return new BDD(kernel.addRef(construction.or(index, other.index), null), kernel); + return new BDD(kernel.addRef(construction.or(index, other.index), NopHandler.get()), kernel); } /** diff --git a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDFactory.java b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDFactory.java index f9433f98..11007314 100644 --- a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDFactory.java +++ b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDFactory.java @@ -32,6 +32,8 @@ package com.booleworks.logicng.knowledgecompilation.bdds; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.BDD_COMPUTATION_STARTED; + import com.booleworks.logicng.formulas.And; import com.booleworks.logicng.formulas.BinaryOperator; import com.booleworks.logicng.formulas.Formula; @@ -39,8 +41,8 @@ import com.booleworks.logicng.formulas.Implication; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Not; -import com.booleworks.logicng.handlers.BDDHandler; -import com.booleworks.logicng.handlers.Handler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDConstruction; import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; @@ -71,7 +73,7 @@ private BDDFactory() { * @return the top node of the BDD */ public static BDD build(final FormulaFactory f, final Formula formula) { - return build(f, formula, null, null); + return build(f, formula, null, NopHandler.get()); } /** @@ -89,7 +91,7 @@ public static BDD build(final FormulaFactory f, final Formula formula) { * computation was aborted */ public static BDD build(final FormulaFactory f, final Formula formula, final BDDKernel kernel) { - return build(f, formula, kernel, null); + return build(f, formula, kernel, NopHandler.get()); } /** @@ -108,13 +110,13 @@ public static BDD build(final FormulaFactory f, final Formula formula, final BDD * @param f the formula factory to generate new formulas * @param formula the formula * @param kernel the BBD kernel to use - * @param handler the BDD handler + * @param handler the handler * @return the top node of the BDD or {@link BDDKernel#BDD_ABORT} if the * computation was aborted */ public static BDD build(final FormulaFactory f, final Formula formula, final BDDKernel kernel, - final BDDHandler handler) { - Handler.start(handler); + final ComputationHandler handler) { + handler.shouldResume(BDD_COMPUTATION_STARTED); final int varNum = formula.variables(f).size(); final BDDKernel bddKernel = kernel == null ? new BDDKernel(f, varNum, varNum * 30, varNum * 20) : kernel; return new BDD(buildRec(f, formula, bddKernel, new BDDConstruction(bddKernel), handler), bddKernel); @@ -139,7 +141,7 @@ public static BDD build(final Collection literals, final BDDK idx = kernel.getOrAddVarIndex(lit.variable()); final int operand = lit.phase() ? construction.ithVar(idx) : construction.nithVar(idx); final int previous = bdd; - bdd = kernel.addRef(construction.and(bdd, operand), null); + bdd = kernel.addRef(construction.and(bdd, operand), NopHandler.get()); kernel.delRef(previous); kernel.delRef(operand); } @@ -157,13 +159,13 @@ public static BDD build(final Collection literals, final BDDK * @param formula the formula * @param kernel the BDD kernel * @param construction the BDD construction instance - * @param handler the BDD handler + * @param handler the handler * @return the BDD index or {@link BDDKernel#BDD_ABORT} if the computation * was aborted */ private static int buildRec(final FormulaFactory f, final Formula formula, final BDDKernel kernel, final BDDConstruction construction, - final BDDHandler handler) { + final ComputationHandler handler) { switch (formula.type()) { case FALSE: return BDDKernel.BDD_FALSE; diff --git a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDKernel.java b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDKernel.java index 58696fe7..a10d2316 100644 --- a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDKernel.java +++ b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDKernel.java @@ -32,9 +32,12 @@ package com.booleworks.logicng.knowledgecompilation.bdds.jbuddy; +import static com.booleworks.logicng.handlers.events.SimpleEvent.BDD_NEW_REF_ADDED; + import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.BDDHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.SimpleEvent; import java.util.Arrays; import java.util.List; @@ -400,18 +403,19 @@ protected int applyRec(final int l, final int r, final Operand op) throws BddReo * Adds a reference for a given node. Reference counting is done on * externally referenced nodes only and the count for a specific node * {@code r} can and must be increased using this function to avoid losing - * the node in the next garbage collection. If a BDD handler is given, the - * handler's {@link BDDHandler#newRefAdded()} method is called. If the - * generation gets aborted due to the handler, the method will return - * {@link BDDKernel#BDD_ABORT} as result. If {@code null} is passed as - * handler, the generation will continue without interruption. + * the node in the next garbage collection. If a BDD handler is given, + * {@link ComputationHandler#shouldResume} is called with the event + * {@link SimpleEvent#BDD_NEW_REF_ADDED}. If the generation gets aborted + * due to the handler, the method will return {@link BDDKernel#BDD_ABORT} + * as result. If {@code null} is passed as handler, the generation will + * continue without interruption. * @param root the node * @param handler the BDD handler * @return return the node * @throws IllegalArgumentException if the root node was invalid */ - public int addRef(final int root, final BDDHandler handler) { - if (handler != null && !handler.newRefAdded()) { + public int addRef(final int root, final ComputationHandler handler) { + if (!handler.shouldResume(BDD_NEW_REF_ADDED)) { return BDD_ABORT; } if (root < 2) { diff --git a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDOperations.java b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDOperations.java index 7e17895e..127a5ad1 100644 --- a/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDOperations.java +++ b/src/main/java/com/booleworks/logicng/knowledgecompilation/bdds/jbuddy/BDDOperations.java @@ -7,6 +7,7 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; +import com.booleworks.logicng.handlers.NopHandler; import java.math.BigInteger; import java.util.ArrayList; @@ -350,7 +351,7 @@ public int support(final int r) { k.reordering.disableReorder(); for (int n = supportMax; n >= supportMin; --n) { if (supportSet[n] == supportID) { - k.addRef(res, null); + k.addRef(res, NopHandler.get()); final int tmp = k.makeNode(n, 0, res); k.delRef(res); res = tmp; diff --git a/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfCompiler.java b/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfCompiler.java index d1c5c8ff..e9e00924 100644 --- a/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfCompiler.java +++ b/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfCompiler.java @@ -4,11 +4,14 @@ package com.booleworks.logicng.knowledgecompilation.dnnf; +import static com.booleworks.logicng.handlers.events.SimpleEvent.DNNF_SHANNON_EXPANSION; + import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; -import com.booleworks.logicng.handlers.DnnfCompilationHandler; -import com.booleworks.logicng.handlers.Handler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.dtree.DTree; import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.dtree.DTreeGenerator; import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.dtree.DTreeLeaf; @@ -44,7 +47,7 @@ public class DnnfCompiler { protected final int numberOfVariables; protected final Map cache; - protected DnnfCompilationHandler handler; + protected ComputationHandler handler; protected BitSet[][] localCacheKeys; protected int[][][] localOccurrences; @@ -87,7 +90,7 @@ public Formula compile(final DTreeGenerator generator) { * @param handler the compilation handler * @return the compiled DNNF */ - public Formula compile(final DTreeGenerator generator, final DnnfCompilationHandler handler) { + public Formula compile(final DTreeGenerator generator, final ComputationHandler handler) { if (!cnf.holds(new SATPredicate(f))) { return f.falsum(); } @@ -143,7 +146,7 @@ protected DTree generateDTree(final FormulaFactory f, final DTreeGenerator gener return tree; } - protected Formula compile(final DTree dTree, final DnnfCompilationHandler handler) { + protected Formula compile(final DTree dTree, final ComputationHandler handler) { if (nonUnitClauses.isAtomicFormula()) { return cnf; } @@ -152,7 +155,7 @@ protected Formula compile(final DTree dTree, final DnnfCompilationHandler handle } initializeCaches(dTree); this.handler = handler; - Handler.start(handler); + handler.shouldResume(ComputationStartedEvent.DNNF_COMPUTATION_STARTED); Formula result; try { @@ -160,7 +163,7 @@ protected Formula compile(final DTree dTree, final DnnfCompilationHandler handle } catch (final TimeoutException e) { result = null; } - this.handler = null; + this.handler = NopHandler.get(); return result == null ? null : f.and(unitClauses, result); } @@ -196,7 +199,7 @@ protected Formula cnf2Ddnnf(final DTree tree, final int currentShannons) throws } else { final int var = chooseShannonVariable(tree, separator, currentShannons); - if (handler != null && !handler.shannonExpansion()) { + if (!handler.shouldResume(DNNF_SHANNON_EXPANSION)) { throw new TimeoutException(); } diff --git a/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfFactory.java b/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfFactory.java index 23391469..b2d058d4 100644 --- a/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfFactory.java +++ b/src/main/java/com/booleworks/logicng/knowledgecompilation/dnnf/DnnfFactory.java @@ -7,7 +7,8 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.DnnfCompilationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.Dnnf; import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.dtree.MinFillDTreeGenerator; import com.booleworks.logicng.transformations.cnf.CNFSubsumption; @@ -29,7 +30,7 @@ public class DnnfFactory { * @return the compiled DNNF */ public Dnnf compile(final FormulaFactory f, final Formula formula) { - return compile(f, formula, null); + return compile(f, formula, NopHandler.get()); } /** @@ -39,7 +40,7 @@ public Dnnf compile(final FormulaFactory f, final Formula formula) { * @param handler the DNNF handler * @return the compiled DNNF */ - public Dnnf compile(final FormulaFactory f, final Formula formula, final DnnfCompilationHandler handler) { + public Dnnf compile(final FormulaFactory f, final Formula formula, final ComputationHandler handler) { final SortedSet originalVariables = new TreeSet<>(formula.variables(f)); final Formula cnf = formula.cnf(f); originalVariables.addAll(cnf.variables(f)); diff --git a/src/main/java/com/booleworks/logicng/modelcounting/ModelCounter.java b/src/main/java/com/booleworks/logicng/modelcounting/ModelCounter.java index f04a49b3..8f59164c 100644 --- a/src/main/java/com/booleworks/logicng/modelcounting/ModelCounter.java +++ b/src/main/java/com/booleworks/logicng/modelcounting/ModelCounter.java @@ -4,7 +4,7 @@ package com.booleworks.logicng.modelcounting; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.formulas.FType; @@ -16,7 +16,8 @@ import com.booleworks.logicng.graphs.datastructures.Graph; import com.booleworks.logicng.graphs.datastructures.Node; import com.booleworks.logicng.graphs.generators.ConstraintGraphGenerator; -import com.booleworks.logicng.handlers.DnnfCompilationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.knowledgecompilation.dnnf.DnnfFactory; import com.booleworks.logicng.knowledgecompilation.dnnf.datastructures.Dnnf; import com.booleworks.logicng.knowledgecompilation.dnnf.functions.DnnfModelCountFunction; @@ -32,7 +33,6 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; -import java.util.function.Supplier; import java.util.stream.Collectors; /** @@ -59,23 +59,21 @@ private ModelCounter() { * @return the model count of the formulas for the variables */ public static BigInteger count(final FormulaFactory f, final Collection formulas, final SortedSet variables) { - return count(f, formulas, variables, () -> null); + return count(f, formulas, variables, NopHandler.get()); } /** * Computes the model count for a given set of formulas (interpreted as conjunction) * and a set of relevant variables. This set can only be a superset of the original * formulas' variables. No projected model counting is supported. - * @param f the formula factory to generate new formulas - * @param formulas the list of formulas - * @param variables the relevant variables - * @param dnnfHandlerSupplier a supplier for a DNNF handler, it may return a new handler on each call or always the same. - * Since multiple DNNFs may be computed, the supplier may be called several times. It must not - * be {@code null}, but it may return {@code null} (i.e. return no handler). + * @param f the formula factory to generate new formulas + * @param formulas the list of formulas + * @param variables the relevant variables + * @param handler the computation handler * @return the model count of the formulas for the variables or {@code null} if the DNNF handler aborted the DNNF computation */ public static BigInteger count(final FormulaFactory f, final Collection formulas, final SortedSet variables, - final Supplier dnnfHandlerSupplier) { + final ComputationHandler handler) { if (!variables.containsAll(FormulaHelper.variables(f, formulas))) { throw new IllegalArgumentException("Expected variables to contain all of the formulas' variables."); } @@ -86,7 +84,7 @@ public static BigInteger count(final FormulaFactory f, final Collection } final List cnfs = encodeAsCnf(f, formulas); final SimplificationResult simplification = simplify(f, cnfs); - final BigInteger count = count(f, simplification.simplifiedFormulas, dnnfHandlerSupplier); + final BigInteger count = count(f, simplification.simplifiedFormulas, handler); if (count == null) { return null; } @@ -127,16 +125,15 @@ private static SimplificationResult simplify(final FormulaFactory f, final Colle } private static BigInteger count(final FormulaFactory f, final Collection formulas, - final Supplier dnnfHandlerSupplier) { + final ComputationHandler handler) { final Graph constraintGraph = ConstraintGraphGenerator.generateFromFormulas(f, formulas); final Set>> ccs = ConnectedComponentsComputation.compute(constraintGraph); final List> components = ConnectedComponentsComputation.splitFormulasByComponent(f, formulas, ccs); final DnnfFactory factory = new DnnfFactory(); BigInteger count = BigInteger.ONE; for (final List component : components) { - final DnnfCompilationHandler handler = dnnfHandlerSupplier.get(); final Dnnf dnnf = factory.compile(f, f.and(component), handler); - if (dnnf == null || aborted(handler)) { + if (dnnf == null || !handler.shouldResume(NO_EVENT)) { return null; } count = count.multiply(dnnf.execute(new DnnfModelCountFunction(f))); diff --git a/src/main/java/com/booleworks/logicng/primecomputation/NaivePrimeReduction.java b/src/main/java/com/booleworks/logicng/primecomputation/NaivePrimeReduction.java index 3020f18f..f2e86c42 100644 --- a/src/main/java/com/booleworks/logicng/primecomputation/NaivePrimeReduction.java +++ b/src/main/java/com/booleworks/logicng/primecomputation/NaivePrimeReduction.java @@ -4,12 +4,15 @@ package com.booleworks.logicng.primecomputation; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; + import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; -import com.booleworks.logicng.handlers.Handler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.sat.SATSolverConfig; import com.booleworks.logicng.util.FormulaHelper; @@ -54,7 +57,7 @@ public NaivePrimeReduction(final FormulaFactory f, final Formula formula) { * @return a prime implicant */ public SortedSet reduceImplicant(final SortedSet implicant) { - return reduceImplicant(implicant, null); + return reduceImplicant(implicant, NopHandler.get()); } /** @@ -66,14 +69,14 @@ public SortedSet reduceImplicant(final SortedSet implicant) { * @return a prime implicant or null if the computation was aborted by the * handler */ - public SortedSet reduceImplicant(final SortedSet implicant, final SATHandler handler) { - Handler.start(handler); + public SortedSet reduceImplicant(final SortedSet implicant, final ComputationHandler handler) { + handler.shouldResume(ComputationStartedEvent.IMPLICATE_REDUCTION_STARTED); final SortedSet primeImplicant = new TreeSet<>(implicant); for (final Literal lit : implicant) { primeImplicant.remove(lit); final boolean sat = implicantSolver.satCall().handler(handler).addFormulas(primeImplicant).sat() == Tristate.TRUE; - if (Handler.aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } if (sat) { @@ -92,7 +95,7 @@ public SortedSet reduceImplicant(final SortedSet implicant, fi * @return a prime implicate */ public SortedSet reduceImplicate(final FormulaFactory f, final SortedSet implicate) { - return reduceImplicate(f, implicate, null); + return reduceImplicate(f, implicate, NopHandler.get()); } /** @@ -106,15 +109,15 @@ public SortedSet reduceImplicate(final FormulaFactory f, final SortedSe * handler */ public SortedSet reduceImplicate(final FormulaFactory f, final SortedSet implicate, - final SATHandler handler) { - Handler.start(handler); + final ComputationHandler handler) { + handler.shouldResume(ComputationStartedEvent.IMPLICATE_REDUCTION_STARTED); final SortedSet primeImplicate = new TreeSet<>(implicate); for (final Literal lit : implicate) { primeImplicate.remove(lit); final List assumptions = FormulaHelper.negateLiterals(f, primeImplicate, ArrayList::new); final boolean sat = implicateSolver.satCall().handler(handler).addFormulas(assumptions).sat() == Tristate.TRUE; - if (Handler.aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } if (sat) { diff --git a/src/main/java/com/booleworks/logicng/primecomputation/PrimeCompiler.java b/src/main/java/com/booleworks/logicng/primecomputation/PrimeCompiler.java index 8b365123..d0be17c0 100644 --- a/src/main/java/com/booleworks/logicng/primecomputation/PrimeCompiler.java +++ b/src/main/java/com/booleworks/logicng/primecomputation/PrimeCompiler.java @@ -4,14 +4,17 @@ package com.booleworks.logicng.primecomputation; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; + import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.Handler; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.functions.OptimizationFunction; import com.booleworks.logicng.solvers.sat.SATCall; @@ -85,7 +88,7 @@ public static PrimeCompiler getWithMaximization() { * @return the prime result */ public PrimeResult compute(final FormulaFactory f, final Formula formula, final PrimeResult.CoverageType type) { - return compute(f, formula, type, null); + return compute(f, formula, type, NopHandler.get()); } /** @@ -93,7 +96,7 @@ public PrimeResult compute(final FormulaFactory f, final Formula formula, final * coverage type specifies if the implicants or the implicates will be * complete, the other one will still be a cover of the given formula. *

- * The prime compiler can be called with an {@link OptimizationHandler}. The + * The prime compiler can be called with an {@link ComputationHandler}. The * given handler instance will be used for every subsequent * {@link OptimizationFunction} call and the handler's SAT handler is used * for every subsequent SAT call. @@ -105,13 +108,13 @@ public PrimeResult compute(final FormulaFactory f, final Formula formula, final * handler */ public PrimeResult compute(final FormulaFactory f, final Formula formula, final PrimeResult.CoverageType type, - final OptimizationHandler handler) { - Handler.start(handler); + final ComputationHandler handler) { + handler.shouldResume(ComputationStartedEvent.PRIME_COMPUTATION_STARTED); final boolean completeImplicants = type == PrimeResult.CoverageType.IMPLICANTS_COMPLETE; final Formula formulaForComputation = completeImplicants ? formula : formula.negate(f); final Pair>, List>> result = computeGeneric(f, formulaForComputation, handler); - if (result == null || Handler.aborted(handler)) { + if (result == null || !handler.shouldResume(NO_EVENT)) { return null; } return new PrimeResult( @@ -122,7 +125,7 @@ public PrimeResult compute(final FormulaFactory f, final Formula formula, final private Pair>, List>> computeGeneric(final FormulaFactory f, final Formula formula, - final OptimizationHandler handler) { + final ComputationHandler handler) { final SubstitutionResult sub = createSubstitution(f, formula); final SATSolver hSolver = SATSolver.newSolver(f, SATSolverConfig.builder().cnfMethod(SATSolverConfig.CNFMethod.PG_ON_SOLVER).build()); @@ -136,26 +139,26 @@ private Pair>, List>> computeGeneric( while (true) { final Assignment hModel = hSolver.execute(computeWithMaximization ? OptimizationFunction.builder().handler(handler).literals(sub.newVar2oldLit.keySet()).maximize() - .build() + .build() : OptimizationFunction.builder().handler(handler).literals(sub.newVar2oldLit.keySet()).minimize() - .build()); - if (Handler.aborted(handler)) { + .build()); + if (!handler.shouldResume(NO_EVENT)) { return null; } if (hModel == null) { return new Pair<>(primeImplicants, primeImplicates); } final Assignment fModel = transformModel(hModel, sub.newVar2oldLit); - try (final SATCall fCall = fSolver.satCall().handler(OptimizationHandler.satHandler(handler)) + try (final SATCall fCall = fSolver.satCall().handler(handler) .addFormulas(fModel.literals()).solve()) { - if (Handler.aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } if (fCall.getSatResult() == Tristate.FALSE) { final SortedSet primeImplicant = computeWithMaximization - ? primeReduction.reduceImplicant(fModel.literals(), OptimizationHandler.satHandler(handler)) + ? primeReduction.reduceImplicant(fModel.literals(), handler) : fModel.literals(); - if (primeImplicant == null || Handler.aborted(handler)) { + if (primeImplicant == null || !handler.shouldResume(NO_EVENT)) { return null; } primeImplicants.add(primeImplicant); @@ -171,8 +174,8 @@ private Pair>, List>> computeGeneric( implicate.add(lit.negate(f)); } final SortedSet primeImplicate = - primeReduction.reduceImplicate(f, implicate, OptimizationHandler.satHandler(handler)); - if (primeImplicate == null || Handler.aborted(handler)) { + primeReduction.reduceImplicate(f, implicate, handler); + if (primeImplicate == null || !handler.shouldResume(NO_EVENT)) { return null; } primeImplicates.add(primeImplicate); diff --git a/src/main/java/com/booleworks/logicng/solvers/MaxSATSolver.java b/src/main/java/com/booleworks/logicng/solvers/MaxSATSolver.java index a8308091..9901cb41 100644 --- a/src/main/java/com/booleworks/logicng/solvers/MaxSATSolver.java +++ b/src/main/java/com/booleworks/logicng/solvers/MaxSATSolver.java @@ -16,7 +16,8 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.MaxSATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.solvers.maxsat.algorithms.IncWBO; import com.booleworks.logicng.solvers.maxsat.algorithms.LinearSU; import com.booleworks.logicng.solvers.maxsat.algorithms.LinearUS; @@ -365,7 +366,7 @@ protected void addClause(final Formula formula, final int weight) { * @return the result (SAT, UNSAT, Optimum found) */ public MaxSAT.MaxSATResult solve() { - return solve(null); + return solve(NopHandler.get()); } /** @@ -374,7 +375,7 @@ public MaxSAT.MaxSATResult solve() { * @return the result (SAT, UNSAT, Optimum found, or UNDEF if canceled by * the handler) */ - public MaxSAT.MaxSATResult solve(final MaxSATHandler handler) { + public MaxSAT.MaxSATResult solve(final ComputationHandler handler) { if (result != UNDEF) { return result; } diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/BackboneFunction.java b/src/main/java/com/booleworks/logicng/solvers/functions/BackboneFunction.java index 74a91c2e..3f2c4001 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/BackboneFunction.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/BackboneFunction.java @@ -4,12 +4,13 @@ package com.booleworks.logicng.solvers.functions; -import static com.booleworks.logicng.handlers.Handler.start; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.BACKBONE_COMPUTATION_STARTED; import com.booleworks.logicng.backbones.Backbone; import com.booleworks.logicng.backbones.BackboneType; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.SolverState; @@ -25,11 +26,11 @@ */ public final class BackboneFunction implements SolverFunction { - private final SATHandler handler; + private final ComputationHandler handler; private final Collection variables; private final BackboneType type; - private BackboneFunction(final SATHandler handler, final Collection variables, final BackboneType type) { + private BackboneFunction(final ComputationHandler handler, final Collection variables, final BackboneType type) { this.handler = handler; this.variables = variables; this.type = type; @@ -45,7 +46,7 @@ public static Builder builder() { @Override public Backbone apply(final SATSolver solver) { - start(handler); + handler.shouldResume(BACKBONE_COMPUTATION_STARTED); final SolverState stateBeforeBackbone = solver.saveState(); final Backbone backbone = solver.underlyingSolver().computeBackbone(variables, type, handler); solver.loadState(stateBeforeBackbone); @@ -57,7 +58,7 @@ public Backbone apply(final SATSolver solver) { */ public static class Builder { - private SATHandler handler; + private ComputationHandler handler = NopHandler.get(); private Collection variables; private BackboneType type = BackboneType.POSITIVE_AND_NEGATIVE; @@ -70,7 +71,7 @@ private Builder() { * @param handler the handler * @return the current builder */ - public Builder handler(final SATHandler handler) { + public Builder handler(final ComputationHandler handler) { this.handler = handler; return this; } diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/ModelCountingFunction.java b/src/main/java/com/booleworks/logicng/solvers/functions/ModelCountingFunction.java index 57ebf7ac..625b943b 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/ModelCountingFunction.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/ModelCountingFunction.java @@ -4,6 +4,8 @@ package com.booleworks.logicng.solvers.functions; +import static com.booleworks.logicng.handlers.events.SimpleEvent.MODEL_ENUMERATION_COMMIT; +import static com.booleworks.logicng.handlers.events.SimpleEvent.MODEL_ENUMERATION_ROLLBACK; import static java.util.Arrays.asList; import com.booleworks.logicng.collections.LNGBooleanVector; @@ -11,7 +13,8 @@ import com.booleworks.logicng.datastructures.Model; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.EnumerationFoundModelsEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.functions.modelenumeration.AbstractModelEnumerationFunction; import com.booleworks.logicng.solvers.functions.modelenumeration.EnumerationCollector; @@ -114,8 +117,8 @@ public ModelCountCollector(final int numberDontCareVariablesNotOnSolver) { @Override public boolean addModel(final LNGBooleanVector modelFromSolver, final SATSolver solver, - final LNGIntVector relevantAllIndices, final ModelEnumerationHandler handler) { - if (handler == null || handler.foundModels(dontCareFactor.intValue())) { + final LNGIntVector relevantAllIndices, final ComputationHandler handler) { + if (handler.shouldResume(new EnumerationFoundModelsEvent(dontCareFactor.intValue()))) { uncommittedModels.add(modelFromSolver); uncommittedIndices.add(relevantAllIndices); return true; @@ -125,20 +128,20 @@ public boolean addModel(final LNGBooleanVector modelFromSolver, final SATSolver } @Override - public boolean commit(final ModelEnumerationHandler handler) { + public boolean commit(final ComputationHandler handler) { committedCount = committedCount.add(BigInteger.valueOf(uncommittedModels.size()).multiply(dontCareFactor)); clearUncommitted(); - return handler == null || handler.commit(); + return handler.shouldResume(MODEL_ENUMERATION_COMMIT); } @Override - public boolean rollback(final ModelEnumerationHandler handler) { + public boolean rollback(final ComputationHandler handler) { clearUncommitted(); - return handler == null || handler.rollback(); + return handler.shouldResume(MODEL_ENUMERATION_ROLLBACK); } @Override - public List rollbackAndReturnModels(final SATSolver solver, final ModelEnumerationHandler handler) { + public List rollbackAndReturnModels(final SATSolver solver, final ComputationHandler handler) { final List modelsToReturn = new ArrayList<>(uncommittedModels.size()); for (int i = 0; i < uncommittedModels.size(); i++) { modelsToReturn.add(new Model(solver.underlyingSolver().convertInternalModel(uncommittedModels.get(i), diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunction.java b/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunction.java index 28522ab7..f4afbb62 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunction.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunction.java @@ -4,6 +4,8 @@ package com.booleworks.logicng.solvers.functions; +import static com.booleworks.logicng.handlers.events.SimpleEvent.MODEL_ENUMERATION_COMMIT; +import static com.booleworks.logicng.handlers.events.SimpleEvent.MODEL_ENUMERATION_ROLLBACK; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -14,7 +16,8 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.EnumerationFoundModelsEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.functions.modelenumeration.AbstractModelEnumerationFunction; import com.booleworks.logicng.solvers.functions.modelenumeration.EnumerationCollector; @@ -147,8 +150,8 @@ public ModelEnumerationCollector(final FormulaFactory f, final SortedSet modelLiterals = new ArrayList<>(additionalVariablesNotOnSolver); @@ -161,20 +164,20 @@ public boolean addModel(final LNGBooleanVector modelFromSolver, final SATSolver } @Override - public boolean commit(final ModelEnumerationHandler handler) { + public boolean commit(final ComputationHandler handler) { committedModels.addAll(expandUncommittedModels()); uncommittedModels.clear(); - return handler == null || handler.commit(); + return handler.shouldResume(MODEL_ENUMERATION_COMMIT); } @Override - public boolean rollback(final ModelEnumerationHandler handler) { + public boolean rollback(final ComputationHandler handler) { uncommittedModels.clear(); - return handler == null || handler.rollback(); + return handler.shouldResume(MODEL_ENUMERATION_ROLLBACK); } @Override - public List rollbackAndReturnModels(final SATSolver solver, final ModelEnumerationHandler handler) { + public List rollbackAndReturnModels(final SATSolver solver, final ComputationHandler handler) { final List modelsToReturn = uncommittedModels.stream().map(Model::new).collect(Collectors.toList()); rollback(handler); return modelsToReturn; diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunction.java b/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunction.java index 6a25ff35..599e3ae7 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunction.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunction.java @@ -4,6 +4,8 @@ package com.booleworks.logicng.solvers.functions; +import static com.booleworks.logicng.handlers.events.SimpleEvent.MODEL_ENUMERATION_COMMIT; +import static com.booleworks.logicng.handlers.events.SimpleEvent.MODEL_ENUMERATION_ROLLBACK; import static java.util.Arrays.asList; import com.booleworks.logicng.collections.LNGBooleanVector; @@ -12,7 +14,8 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.EnumerationFoundModelsEvent; import com.booleworks.logicng.knowledgecompilation.bdds.BDD; import com.booleworks.logicng.knowledgecompilation.bdds.BDDFactory; import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; @@ -128,8 +131,8 @@ public BddModelEnumerationCollector(final FormulaFactory f, final SortedSet rollbackAndReturnModels(final SATSolver solver, final ModelEnumerationHandler handler) { + public List rollbackAndReturnModels(final SATSolver solver, final ComputationHandler handler) { final List modelsToReturn = new ArrayList<>(uncommittedModels); rollback(handler); return modelsToReturn; diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/OptimizationFunction.java b/src/main/java/com/booleworks/logicng/solvers/functions/OptimizationFunction.java index 877bb6ad..1ae4b434 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/OptimizationFunction.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/OptimizationFunction.java @@ -4,9 +4,7 @@ package com.booleworks.logicng.solvers.functions; -import static com.booleworks.logicng.handlers.Handler.aborted; -import static com.booleworks.logicng.handlers.Handler.start; -import static com.booleworks.logicng.handlers.OptimizationHandler.satHandler; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.datastructures.Tristate; @@ -17,7 +15,10 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.OptimizationFoundBetterBoundEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.SolverState; import com.booleworks.logicng.solvers.sat.SATCall; @@ -47,11 +48,11 @@ public final class OptimizationFunction implements SolverFunction { private final Collection literals; private final SortedSet resultModelVariables; private final boolean maximize; - private final OptimizationHandler handler; + private final ComputationHandler handler; private OptimizationFunction(final Collection literals, final Collection additionalVariables, final boolean maximize, - final OptimizationHandler handler) { + final ComputationHandler handler) { this.literals = literals; resultModelVariables = new TreeSet<>(additionalVariables); for (final Literal lit : literals) { @@ -98,7 +99,7 @@ public Assignment apply(final SATSolver solver) { } private Assignment maximize(final SATSolver solver) { - start(handler); + handler.shouldResume(ComputationStartedEvent.OPTIMIZATION_FUNCTION_STARTED); final FormulaFactory f = solver.factory(); final Map selectorMap = new TreeMap<>(); for (final Literal lit : literals) { @@ -115,8 +116,8 @@ private Assignment maximize(final SATSolver solver) { } Assignment lastResultModel; Assignment currentSelectorModel; - try (final SATCall satCall = solver.satCall().handler(satHandler(handler)).solve()) { - if (satCall.getSatResult() != Tristate.TRUE || aborted(handler)) { + try (final SATCall satCall = solver.satCall().handler(handler).solve()) { + if (satCall.getSatResult() != Tristate.TRUE || !handler.shouldResume(NO_EVENT)) { return null; } lastResultModel = satCall.model(resultModelVariables); @@ -130,9 +131,9 @@ private Assignment maximize(final SATSolver solver) { int currentBound = currentSelectorModel.positiveVariables().size(); if (currentBound == 0) { solver.add(f.cc(CType.GE, 1, selectors)); - try (final SATCall satCall = solver.satCall().handler(satHandler(handler)).solve()) { + try (final SATCall satCall = solver.satCall().handler(handler).solve()) { final Tristate sat = satCall.getSatResult(); - if (aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } else if (sat == Tristate.FALSE) { return lastResultModel; @@ -147,14 +148,14 @@ private Assignment maximize(final SATSolver solver) { assert cc instanceof CardinalityConstraint; final CcIncrementalData incrementalData = solver.addIncrementalCc((CardinalityConstraint) cc); while (true) { - try (final SATCall satCall = solver.satCall().handler(satHandler(handler)).solve()) { - if (aborted(handler)) { + try (final SATCall satCall = solver.satCall().handler(handler).solve()) { + if (!handler.shouldResume(NO_EVENT)) { return null; } if (satCall.getSatResult() == Tristate.FALSE) { return lastResultModel; } - if (handler != null && !handler.foundBetterBound(() -> satCall.model(resultModelVariables))) { + if (!handler.shouldResume(new OptimizationFoundBetterBoundEvent(() -> satCall.model(resultModelVariables)))) { return null; } lastResultModel = satCall.model(resultModelVariables); @@ -175,7 +176,7 @@ public static class Builder { private Collection literals; private Collection additionalVariables = new TreeSet<>(); private boolean maximize = true; - private OptimizationHandler handler = null; + private ComputationHandler handler = NopHandler.get(); private Builder() { // Initialize only via factory @@ -248,7 +249,7 @@ public Builder maximize() { * @param handler the handler * @return the current builder */ - public Builder handler(final OptimizationHandler handler) { + public Builder handler(final ComputationHandler handler) { this.handler = handler; return this; } diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/AbstractModelEnumerationFunction.java b/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/AbstractModelEnumerationFunction.java index 3661ffd9..415f3799 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/AbstractModelEnumerationFunction.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/AbstractModelEnumerationFunction.java @@ -5,8 +5,7 @@ package com.booleworks.logicng.solvers.functions.modelenumeration; import static com.booleworks.logicng.datastructures.Tristate.TRUE; -import static com.booleworks.logicng.handlers.Handler.aborted; -import static com.booleworks.logicng.handlers.Handler.start; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import static com.booleworks.logicng.solvers.functions.modelenumeration.ModelEnumerationCommon.generateBlockingClause; import static com.booleworks.logicng.solvers.functions.modelenumeration.ModelEnumerationCommon.relevantAllIndicesFromSolver; import static com.booleworks.logicng.solvers.functions.modelenumeration.ModelEnumerationCommon.relevantIndicesFromSolver; @@ -20,8 +19,8 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.SolverState; import com.booleworks.logicng.solvers.functions.SolverFunction; @@ -42,7 +41,7 @@ public abstract class AbstractModelEnumerationFunction implements Solver protected final SortedSet variables; protected final SortedSet additionalVariables; - protected final ModelEnumerationHandler handler; + protected final ComputationHandler handler; protected final ModelEnumerationStrategy strategy; protected AbstractModelEnumerationFunction(final SortedSet variables, @@ -61,7 +60,7 @@ protected abstract EnumerationCollector newCollector(final FormulaFactor @Override public RESULT apply(final SATSolver solver) { - start(handler); + handler.shouldResume(ComputationStartedEvent.MODEL_ENUMERATION_STARTED); final SortedSet knownVariables = solver.underlyingSolver().knownVariables(); final SortedSet additionalVarsNotOnSolver = difference(additionalVariables, knownVariables, TreeSet::new); @@ -99,7 +98,7 @@ private void enumerateRecursive(final EnumerationCollector collector, fi } newSplitVars = strategy.reduceSplitVars(newSplitVars, recursionDepth); } - if (aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { collector.rollback(handler); return; } @@ -135,7 +134,7 @@ private void enumerateRecursive(final EnumerationCollector collector, fi protected static boolean enumerate(final EnumerationCollector collector, final SATSolver solver, final SortedSet variables, final SortedSet additionalVariables, final int maxModels, - final ModelEnumerationHandler handler) { + final ComputationHandler handler) { final SolverState stateBeforeEnumeration = solver.saveState(); final LNGIntVector relevantIndices = relevantIndicesFromSolver(variables, solver); final LNGIntVector relevantAllIndices = @@ -161,10 +160,9 @@ protected static boolean enumerate(final EnumerationCollector collector, return true; } - private static boolean modelEnumerationSATCall(final SATSolver solver, final ModelEnumerationHandler handler) { - final SATHandler satHandler = handler == null ? null : handler.satHandler(); - final boolean sat = solver.satCall().handler(satHandler).sat() == TRUE; - return !aborted(handler) && sat; + private static boolean modelEnumerationSATCall(final SATSolver solver, final ComputationHandler handler) { + final boolean sat = solver.satCall().handler(handler).sat() == TRUE; + return handler.shouldResume(NO_EVENT) && sat; } protected static FormulaFactory factory(final SortedSet variables) { diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollector.java b/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollector.java index cebbf277..4c562164 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollector.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollector.java @@ -7,7 +7,7 @@ import com.booleworks.logicng.collections.LNGBooleanVector; import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.datastructures.Model; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.solvers.SATSolver; import java.util.List; @@ -16,10 +16,10 @@ * An interface for enumeration collectors. *

* An enumeration collector gathers the found models given by - * {@link #addModel(LNGBooleanVector, SATSolver, LNGIntVector, ModelEnumerationHandler)}. + * {@link #addModel(LNGBooleanVector, SATSolver, LNGIntVector, ComputationHandler)}. * Added Models added can potentially be discarded later via - * {@link #rollback(ModelEnumerationHandler)}. To prevent models from being - * rolled back one can call {@link #commit(ModelEnumerationHandler)}. With + * {@link #rollback(ComputationHandler)}. To prevent models from being + * rolled back one can call {@link #commit(ComputationHandler)}. With * {@link #getResult()} the result, the models committed models, can be * retrieved. * @param The result type of the model enumeration function. Can be @@ -34,12 +34,11 @@ public interface EnumerationCollector { * @param modelFromSolver the model from the solver * @param solver the solver * @param relevantAllIndices the relevant indices - * @param handler the model enumeration handler, may be - * {@code null} + * @param handler the model enumeration handler * @return true if adding the model was successful, false otherwise */ boolean addModel(LNGBooleanVector modelFromSolver, SATSolver solver, LNGIntVector relevantAllIndices, - ModelEnumerationHandler handler); + ComputationHandler handler); /** * All founds models since the last commit call are confirmed and cannot be @@ -50,7 +49,7 @@ boolean addModel(LNGBooleanVector modelFromSolver, SATSolver solver, LNGIntVecto * @return {@code true} if the computation should continue, otherwise * {@code false} */ - boolean commit(ModelEnumerationHandler handler); + boolean commit(ComputationHandler handler); /** * All found models since the last commit should be discarded. @@ -60,7 +59,7 @@ boolean addModel(LNGBooleanVector modelFromSolver, SATSolver solver, LNGIntVecto * @return {@code true} if the computation should continue, otherwise * {@code false} */ - boolean rollback(ModelEnumerationHandler handler); + boolean rollback(ComputationHandler handler); /** * All found models since the last commit will be discarded and returned. @@ -70,7 +69,7 @@ boolean addModel(LNGBooleanVector modelFromSolver, SATSolver solver, LNGIntVecto * @param handler the model enumeration handler, may be {@code null} * @return list of all discarded models */ - List rollbackAndReturnModels(final SATSolver solver, ModelEnumerationHandler handler); + List rollbackAndReturnModels(final SATSolver solver, ComputationHandler handler); /** * @return the committed state of the collector diff --git a/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/ModelEnumerationConfig.java b/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/ModelEnumerationConfig.java index 6100669e..d55b424d 100644 --- a/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/ModelEnumerationConfig.java +++ b/src/main/java/com/booleworks/logicng/solvers/functions/modelenumeration/ModelEnumerationConfig.java @@ -6,7 +6,8 @@ import com.booleworks.logicng.configurations.Configuration; import com.booleworks.logicng.configurations.ConfigurationType; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.solvers.functions.ModelEnumerationFunction; import com.booleworks.logicng.solvers.functions.modelenumeration.splitprovider.MostCommonVariablesProvider; @@ -17,7 +18,7 @@ */ public class ModelEnumerationConfig extends Configuration { - final ModelEnumerationHandler handler; + final ComputationHandler handler; final ModelEnumerationStrategy strategy; /** @@ -44,7 +45,7 @@ public static Builder builder() { * @since 3.0.0 */ public static class Builder { - private ModelEnumerationHandler handler = null; + private ComputationHandler handler = NopHandler.get(); private ModelEnumerationStrategy strategy = DefaultModelEnumerationStrategy.builder().build(); private Builder() { @@ -57,7 +58,7 @@ private Builder() { * @param handler the handler, may be {@code null} * @return the current builder */ - public Builder handler(final ModelEnumerationHandler handler) { + public Builder handler(final ComputationHandler handler) { this.handler = handler; return this; } diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/IncWBO.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/IncWBO.java index 951755a9..8d4eee1c 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/IncWBO.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/IncWBO.java @@ -24,14 +24,13 @@ import static com.booleworks.logicng.datastructures.Tristate.FALSE; import static com.booleworks.logicng.datastructures.Tristate.UNDEF; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import com.booleworks.logicng.collections.LNGBooleanVector; import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.collections.LNGVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.maxsat.encodings.Encoder; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; import com.booleworks.logicng.util.Pair; @@ -100,8 +99,8 @@ public MaxSATResult search() { return normalSearch(); } else if (weightStrategy == MaxSATConfig.WeightStrategy.NORMAL || weightStrategy == MaxSATConfig.WeightStrategy.DIVERSIFY) { - return weightSearch(); - } + return weightSearch(); + } throw new IllegalArgumentException("Unknown problem type."); } @@ -321,9 +320,8 @@ protected MaxSATResult weightSearch() { assumptions.push(LNGCoreSolver.not(softClauses.get(i).assumptionVar())); } } - final SATHandler satHandler = satHandler(); - final Tristate res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + final Tristate res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == FALSE) { nbCores++; @@ -333,7 +331,7 @@ protected MaxSATResult weightSearch() { if (verbosity != MaxSATConfig.Verbosity.NONE) { output.printf("c LB : %d CS : %d W : %d%n", lbCost, solver.assumptionsConflict().size(), coreCost); } - if (!foundLowerBound(lbCost, null)) { + if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } relaxCore(solver.assumptionsConflict(), coreCost); @@ -368,7 +366,7 @@ protected MaxSATResult weightSearch() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundUpperBound(ubCost, null)) { + } else if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } incrementalBuildWeightSolver(weightStrategy); @@ -421,9 +419,8 @@ protected MaxSATResult normalSearch() { assumptions.push(LNGCoreSolver.not(softClauses.get(i).assumptionVar())); } } - final SATHandler satHandler = satHandler(); - final Tristate res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + final Tristate res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == FALSE) { nbCores++; @@ -439,7 +436,7 @@ protected MaxSATResult normalSearch() { } return MaxSATResult.OPTIMUM; } - if (!foundLowerBound(lbCost, null)) { + if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } relaxCore(solver.assumptionsConflict(), coreCost); diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearSU.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearSU.java index 7e106d96..00898b6d 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearSU.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearSU.java @@ -22,7 +22,7 @@ package com.booleworks.logicng.solvers.maxsat.algorithms; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.CardinalityEncoding; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.Verbosity; @@ -31,7 +31,6 @@ import com.booleworks.logicng.collections.LNGVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.datastructures.LNGSoftClause; import com.booleworks.logicng.solvers.maxsat.encodings.Encoder; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; @@ -114,9 +113,8 @@ protected MaxSATResult bmoSearch() { int localCost = 0; ubCost = 0; while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } if (res == Tristate.TRUE) { @@ -128,7 +126,7 @@ protected MaxSATResult bmoSearch() { output.println("o " + (newCost + lbCost)); } ubCost = newCost + lbCost; - if (newCost > 0 && !foundUpperBound(ubCost, null)) { + if (newCost > 0 && !foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } } else if (verbosity != Verbosity.NONE) { @@ -172,7 +170,7 @@ protected MaxSATResult bmoSearch() { posWeight++; currentWeight = orderWeights.get(posWeight); localCost = 0; - if (!foundLowerBound(lbCost, null)) { + if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } solver = rebuildBMO(functions, weights, currentWeight); @@ -189,9 +187,8 @@ protected MaxSATResult normalSearch() { initRelaxation(); solver = rebuildSolver(1); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; @@ -218,7 +215,7 @@ protected MaxSATResult normalSearch() { } } ubCost = newCost; - if (!foundUpperBound(ubCost, null)) { + if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } } diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearUS.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearUS.java index 4c60a8e8..0a57b912 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearUS.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/LinearUS.java @@ -22,12 +22,11 @@ package com.booleworks.logicng.solvers.maxsat.algorithms; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.maxsat.encodings.Encoder; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; @@ -96,9 +95,8 @@ protected MaxSATResult none() { final LNGIntVector assumptions = new LNGIntVector(); encoder.setIncremental(MaxSATConfig.IncrementalStrategy.NONE); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; @@ -109,7 +107,7 @@ protected MaxSATResult none() { } ubCost = newCost; if (nbSatisfiable == 1) { - if (!foundUpperBound(ubCost, null)) { + if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } if (encoder.cardEncoding() == MaxSATConfig.CardinalityEncoding.MTOTALIZER) { @@ -135,7 +133,7 @@ protected MaxSATResult none() { } else { return MaxSATResult.UNSATISFIABLE; } - } else if (!foundLowerBound(lbCost, null)) { + } else if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } solver = rebuildSolver(); @@ -153,9 +151,8 @@ protected MaxSATResult iterative() { final LNGIntVector assumptions = new LNGIntVector(); encoder.setIncremental(MaxSATConfig.IncrementalStrategy.ITERATIVE); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; @@ -166,7 +163,7 @@ protected MaxSATResult iterative() { } ubCost = newCost; if (nbSatisfiable == 1) { - if (!foundUpperBound(ubCost, null)) { + if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } for (int i = 0; i < objFunction.size(); i++) { @@ -195,7 +192,7 @@ protected MaxSATResult iterative() { return MaxSATResult.UNSATISFIABLE; } } - if (!foundLowerBound(lbCost, null)) { + if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } if (!encoder.hasCardEncoding()) { diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MSU3.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MSU3.java index 0c52a3bc..d50df4d7 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MSU3.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MSU3.java @@ -22,7 +22,7 @@ package com.booleworks.logicng.solvers.maxsat.algorithms; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.CardinalityEncoding; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.IncrementalStrategy; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.Verbosity; @@ -31,7 +31,6 @@ import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.maxsat.encodings.Encoder; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; @@ -112,9 +111,8 @@ protected MaxSATResult none() { coreMapping.put(softClauses.get(i).assumptionVar(), i); } while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; @@ -125,7 +123,7 @@ protected MaxSATResult none() { } ubCost = newCost; if (nbSatisfiable == 1) { - if (!foundUpperBound(ubCost, null)) { + if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } for (int i = 0; i < objFunction.size(); i++) { @@ -148,7 +146,7 @@ protected MaxSATResult none() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundLowerBound(lbCost, null)) { + } else if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } sumSizeCores += solver.assumptionsConflict().size(); @@ -193,9 +191,8 @@ protected MaxSATResult iterative() { coreMapping.put(softClauses.get(i).assumptionVar(), i); } while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; @@ -206,7 +203,7 @@ protected MaxSATResult iterative() { } ubCost = newCost; if (nbSatisfiable == 1) { - if (!foundUpperBound(ubCost, null)) { + if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } for (int i = 0; i < objFunction.size(); i++) { @@ -236,7 +233,7 @@ protected MaxSATResult iterative() { if (solver.assumptionsConflict().size() == 0) { return MaxSATResult.UNSATISFIABLE; } - if (!foundLowerBound(lbCost, null)) { + if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } joinObjFunction.clear(); diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MaxSAT.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MaxSAT.java index 6162a9b1..1c6181fe 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MaxSAT.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/MaxSAT.java @@ -22,17 +22,19 @@ package com.booleworks.logicng.solvers.maxsat.algorithms; -import static com.booleworks.logicng.handlers.Handler.start; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.Verbosity; import com.booleworks.logicng.collections.LNGBooleanVector; import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.collections.LNGVector; -import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.MaxSATHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.ComputationFinishedEvent; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.MaxSatNewLowerBoundEvent; +import com.booleworks.logicng.handlers.events.MaxSatNewUpperBoundEvent; import com.booleworks.logicng.solvers.datastructures.LNGHardClause; import com.booleworks.logicng.solvers.datastructures.LNGSoftClause; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; @@ -75,7 +77,7 @@ public enum MaxSATResult { final LNGVector hardClauses; final LNGIntVector orderWeights; protected Verbosity verbosity; - protected MaxSATHandler handler; + protected ComputationHandler handler; int hardWeight; ProblemType problemType; int nbVars; @@ -114,7 +116,7 @@ protected MaxSAT(final FormulaFactory f, final MaxSATConfig config) { nbSatisfiable = 0; sumSizeCores = 0; orderWeights = new LNGIntVector(); - handler = null; + handler = NopHandler.get(); } /** @@ -133,7 +135,7 @@ public static void newSATVariable(final LNGCoreSolver s) { * @param assumptions the assumptions * @return the result of the solving process */ - public static Tristate searchSATSolver(final LNGCoreSolver s, final SATHandler satHandler, + public static Tristate searchSATSolver(final LNGCoreSolver s, final ComputationHandler satHandler, final LNGIntVector assumptions) { return s.internalSolve(satHandler, assumptions); } @@ -144,7 +146,7 @@ public static Tristate searchSATSolver(final LNGCoreSolver s, final SATHandler s * @param satHandler a SAT handler * @return the result of the solving process */ - public static Tristate searchSATSolver(final LNGCoreSolver s, final SATHandler satHandler) { + public static Tristate searchSATSolver(final LNGCoreSolver s, final ComputationHandler satHandler) { return s.internalSolve(satHandler); } @@ -154,14 +156,12 @@ public static Tristate searchSATSolver(final LNGCoreSolver s, final SATHandler s * @return the result of the solving process * @throws IllegalArgumentException if the configuration was not valid */ - public final MaxSATResult search(final MaxSATHandler handler) { + public final MaxSATResult search(final ComputationHandler handler) { this.handler = handler; - start(handler); + handler.shouldResume(ComputationStartedEvent.MAX_SAT_CALL_STARTED); final MaxSATResult result = search(); - if (handler != null) { - handler.finishedSolving(); - } - this.handler = null; + handler.shouldResume(ComputationFinishedEvent.MAX_SAT_CALL_FINISHED); + this.handler = NopHandler.get(); return result; } @@ -399,21 +399,12 @@ public LNGBooleanVector model() { return model; } - /** - * Returns the current SAT handler or {@code null} if no MaxSAT handler was - * given. - * @return the current SAT handler - */ - SATHandler satHandler() { - return handler == null ? null : handler.satHandler(); - } - - boolean foundLowerBound(final int lowerBound, final Assignment model) { - return handler == null || handler.foundLowerBound(lowerBound, model); + boolean foundLowerBound(final int lowerBound) { + return handler.shouldResume(new MaxSatNewLowerBoundEvent(lowerBound)); } - boolean foundUpperBound(final int upperBound, final Assignment model) { - return handler == null || handler.foundUpperBound(upperBound, model); + boolean foundUpperBound(final int upperBound) { + return handler.shouldResume(new MaxSatNewUpperBoundEvent(upperBound)); } /** diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/OLL.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/OLL.java index 685bf57a..fc8b06c9 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/OLL.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/OLL.java @@ -4,14 +4,13 @@ package com.booleworks.logicng.solvers.maxsat.algorithms; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import com.booleworks.logicng.collections.LNGBooleanVector; import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.collections.LNGVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.maxsat.encodings.Encoder; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; @@ -117,9 +116,8 @@ private MaxSATResult unweighted() { final LNGVector softCardinality = new LNGVector<>(); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; @@ -247,9 +245,8 @@ private MaxSATResult weighted() { minWeight = currentWeight; while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == Tristate.TRUE) { nbSatisfiable++; diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WBO.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WBO.java index 31a29d2a..ede1ee94 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WBO.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WBO.java @@ -25,7 +25,7 @@ import static com.booleworks.logicng.datastructures.Tristate.FALSE; import static com.booleworks.logicng.datastructures.Tristate.TRUE; import static com.booleworks.logicng.datastructures.Tristate.UNDEF; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.Verbosity; import static com.booleworks.logicng.solvers.maxsat.algorithms.MaxSATConfig.WeightStrategy; @@ -33,7 +33,6 @@ import com.booleworks.logicng.collections.LNGVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; import com.booleworks.logicng.util.Pair; @@ -426,9 +425,8 @@ protected void symmetryBreaking() { Tristate unsatSearch() { assert assumptions.size() == 0; solver = rebuildHardSolver(); - final SATHandler satHandler = satHandler(); - final Tristate res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + final Tristate res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return UNDEF; } else if (res == FALSE) { nbCores++; @@ -458,9 +456,8 @@ protected MaxSATResult weightSearch() { updateCurrentWeight(weightStrategy); solver = rebuildWeightSolver(weightStrategy); while (true) { - final SATHandler satHandler = satHandler(); - final Tristate res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + final Tristate res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == FALSE) { nbCores++; @@ -470,7 +467,7 @@ protected MaxSATResult weightSearch() { if (verbosity != Verbosity.NONE) { output.printf("c LB : %d CS : %d W : %d%n", lbCost, solver.assumptionsConflict().size(), coreCost); } - if (!foundLowerBound(lbCost, null)) { + if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } relaxCore(solver.assumptionsConflict(), coreCost, assumptions); @@ -505,7 +502,7 @@ protected MaxSATResult weightSearch() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundUpperBound(ubCost, null)) { + } else if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } solver = rebuildWeightSolver(weightStrategy); @@ -524,9 +521,8 @@ protected MaxSATResult normalSearch() { initAssumptions(assumptions); solver = rebuildSolver(); while (true) { - final SATHandler satHandler = satHandler(); - final Tristate res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + final Tristate res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == FALSE) { nbCores++; @@ -541,7 +537,7 @@ protected MaxSATResult normalSearch() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundLowerBound(lbCost, null)) { + } else if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } relaxCore(solver.assumptionsConflict(), coreCost, assumptions); diff --git a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WMSU3.java b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WMSU3.java index 12f630b2..9c8f9631 100644 --- a/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WMSU3.java +++ b/src/main/java/com/booleworks/logicng/solvers/maxsat/algorithms/WMSU3.java @@ -23,14 +23,13 @@ package com.booleworks.logicng.solvers.maxsat.algorithms; import static com.booleworks.logicng.datastructures.Tristate.TRUE; -import static com.booleworks.logicng.handlers.Handler.aborted; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; import com.booleworks.logicng.collections.LNGBooleanVector; import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.collections.LNGVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; import com.booleworks.logicng.solvers.maxsat.encodings.Encoder; import com.booleworks.logicng.solvers.sat.LNGCoreSolver; @@ -154,9 +153,8 @@ protected MaxSATResult iterative() { final LNGIntVector fullObjFunction = new LNGIntVector(); final LNGIntVector fullCoeffsFunction = new LNGIntVector(); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == TRUE) { nbSatisfiable++; @@ -172,7 +170,7 @@ protected MaxSATResult iterative() { assert lbCost == ubCost; assert nbSatisfiable > 0; return MaxSATResult.OPTIMUM; - } else if (!foundUpperBound(ubCost, null)) { + } else if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } for (int i = 0; i < nSoft(); i++) { @@ -190,7 +188,7 @@ protected MaxSATResult iterative() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundLowerBound(lbCost, null)) { + } else if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } sumSizeCores += solver.assumptionsConflict().size(); @@ -249,9 +247,8 @@ protected MaxSATResult none() { } assumptions.clear(); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == TRUE) { nbSatisfiable++; @@ -266,7 +263,7 @@ protected MaxSATResult none() { if (ubCost == 0 || lbCost == ubCost || (currentWeight == 1 && nbSatisfiable > 1)) { assert nbSatisfiable > 0; return MaxSATResult.OPTIMUM; - } else if (!foundUpperBound(ubCost, null)) { + } else if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } for (int i = 0; i < nSoft(); i++) { @@ -284,7 +281,7 @@ protected MaxSATResult none() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundLowerBound(lbCost, null)) { + } else if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } sumSizeCores += solver.assumptionsConflict().size(); @@ -349,9 +346,8 @@ protected MaxSATResult iterativeBmo() { bmoEncodings.push(e); firstEncoding.push(true); while (true) { - final SATHandler satHandler = satHandler(); - res = searchSATSolver(solver, satHandler, assumptions); - if (aborted(satHandler)) { + res = searchSATSolver(solver, handler, assumptions); + if (!handler.shouldResume(NO_EVENT)) { return MaxSATResult.UNDEF; } else if (res == TRUE) { nbSatisfiable++; @@ -366,7 +362,7 @@ protected MaxSATResult iterativeBmo() { if (nbSatisfiable == 1) { if (ubCost == 0) { return MaxSATResult.OPTIMUM; - } else if (!foundUpperBound(ubCost, null)) { + } else if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } assert orderWeights.size() > 0; @@ -382,7 +378,7 @@ protected MaxSATResult iterativeBmo() { if (currentWeight == 1 || currentWeight == minWeight) { return MaxSATResult.OPTIMUM; } else { - if (!foundUpperBound(ubCost, null)) { + if (!foundUpperBound(ubCost)) { return MaxSATResult.UNDEF; } assumptions.clear(); @@ -433,7 +429,7 @@ protected MaxSATResult iterativeBmo() { output.println("c LB = UB"); } return MaxSATResult.OPTIMUM; - } else if (!foundLowerBound(lbCost, null)) { + } else if (!foundLowerBound(lbCost)) { return MaxSATResult.UNDEF; } sumSizeCores += solver.assumptionsConflict().size(); diff --git a/src/main/java/com/booleworks/logicng/solvers/sat/LNGCoreSolver.java b/src/main/java/com/booleworks/logicng/solvers/sat/LNGCoreSolver.java index f2e72a22..ace2f580 100644 --- a/src/main/java/com/booleworks/logicng/solvers/sat/LNGCoreSolver.java +++ b/src/main/java/com/booleworks/logicng/solvers/sat/LNGCoreSolver.java @@ -23,9 +23,10 @@ package com.booleworks.logicng.solvers.sat; import static com.booleworks.logicng.datastructures.Tristate.UNDEF; -import static com.booleworks.logicng.handlers.Handler.aborted; -import static com.booleworks.logicng.handlers.Handler.start; -import static com.booleworks.logicng.handlers.SATHandler.finishSolving; +import static com.booleworks.logicng.handlers.events.ComputationFinishedEvent.SAT_CALL_FINISHED; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.SAT_CALL_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; +import static com.booleworks.logicng.handlers.events.SimpleEvent.SAT_CONFLICT_DETECTED; import com.booleworks.logicng.backbones.Backbone; import com.booleworks.logicng.backbones.BackboneType; @@ -36,7 +37,8 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.propositions.Proposition; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.SolverState; @@ -129,7 +131,7 @@ public class LNGCoreSolver { protected int learntsLiterals = 0; // SAT handler - protected SATHandler handler; + protected ComputationHandler handler = NopHandler.get(); protected boolean canceledByHandler = false; // Proof generating information @@ -492,20 +494,20 @@ public boolean addClause(final LNGIntVector ps, final Proposition proposition) { * {@link Tristate#UNDEF} if the computation was canceled by a * {@link SATHandler}. If {@code null} is passed as handler, the solver will * run until the satisfiability is decided. - * @param handler a sat handler + * @param handler a handler * @return {@link Tristate#TRUE} if the formula is satisfiable, * {@link Tristate#FALSE} if the formula is not satisfiable, or * {@link Tristate#UNDEF} if the computation was canceled. */ - public Tristate internalSolve(final SATHandler handler) { + public Tristate internalSolve(final ComputationHandler handler) { this.handler = handler; final Tristate result = internalSolve(); - this.handler = null; + this.handler = NopHandler.get(); return result; } public Tristate internalSolve() { - start(handler); + handler.shouldResume(SAT_CALL_STARTED); model.clear(); assumptionsConflict.clear(); if (!ok) { @@ -528,7 +530,7 @@ public Tristate internalSolve() { } else if (status == Tristate.FALSE && assumptionsConflict.empty()) { ok = false; } - finishSolving(handler); + handler.shouldResume(SAT_CALL_FINISHED); cancelUntil(0); canceledByHandler = false; return status; @@ -537,9 +539,9 @@ public Tristate internalSolve() { /** * Sets (or clears) the SAT handler which should be used for subsequent SAT * calls. - * @param handler the SAT handler to be used + * @param handler the handler to be used */ - public void setHandler(final SATHandler handler) { + public void setHandler(final ComputationHandler handler) { this.handler = handler; } @@ -551,13 +553,13 @@ public void setHandler(final SATHandler handler) { * {@link Tristate#UNDEF} if the computation was canceled by a * {@link SATHandler}. If {@code null} is passed as handler, the solver will * run until the satisfiability is decided. - * @param handler a sat handler + * @param handler a handler * @param assumptions the assumptions as a given vector of literals * @return {@link Tristate#TRUE} if the formula and the assumptions are * satisfiable, {@link Tristate#FALSE} if they are not satisfiable, * or {@link Tristate#UNDEF} if the computation was canceled. */ - public Tristate internalSolve(final SATHandler handler, final LNGIntVector assumptions) { + public Tristate internalSolve(final ComputationHandler handler, final LNGIntVector assumptions) { this.assumptions = new LNGIntVector(assumptions); final Tristate result = internalSolve(handler); this.assumptions.clear(); @@ -1183,7 +1185,7 @@ protected Tristate search() { while (true) { final LNGClause confl = propagate(); if (confl != null) { - if (handler != null && !handler.detectedConflict()) { + if (!handler.shouldResume(SAT_CONFLICT_DETECTED)) { canceledByHandler = true; return Tristate.UNDEF; } @@ -1752,7 +1754,7 @@ public LNGIntVector upZeroLiterals() { * @return the backbone projected to the relevant variables */ public Backbone computeBackbone(final Collection variables, final BackboneType type) { - return computeBackbone(variables, type, null); + return computeBackbone(variables, type, NopHandler.get()); } /** @@ -1765,9 +1767,9 @@ public Backbone computeBackbone(final Collection variables, final Back * if the computation was aborted by the handler */ public Backbone computeBackbone(final Collection variables, final BackboneType type, - final SATHandler handler) { + final ComputationHandler handler) { final boolean sat = internalSolve(handler) == Tristate.TRUE; - if (aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } if (sat) { @@ -1775,7 +1777,7 @@ public Backbone computeBackbone(final Collection variables, final Back final List relevantVarIndices = getRelevantVarIndices(variables); initBackboneDS(relevantVarIndices); computeBackbone(relevantVarIndices, type, handler); - if (aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return null; } final Backbone backbone = buildBackbone(variables, type); @@ -1825,12 +1827,12 @@ protected void initBackboneDS(final List variables) { * @param type the type of the backbone * @param handler the handler */ - protected void computeBackbone(final List variables, final BackboneType type, final SATHandler handler) { + protected void computeBackbone(final List variables, final BackboneType type, final ComputationHandler handler) { createInitialCandidates(variables, type); while (!backboneCandidates.isEmpty()) { final int lit = backboneCandidates.pop(); final boolean sat = solveWithLit(lit, handler); - if (aborted(handler)) { + if (!handler.shouldResume(NO_EVENT)) { return; } if (sat) { @@ -1888,7 +1890,7 @@ protected void refineUpperBound() { * @param handler the handler * @return {@code true} if satisfiable, otherwise {@code false} */ - protected boolean solveWithLit(final int lit, final SATHandler handler) { + protected boolean solveWithLit(final int lit, final ComputationHandler handler) { backboneAssumptions.push(not(lit)); final boolean sat = internalSolve(handler, backboneAssumptions) == Tristate.TRUE; backboneAssumptions.pop(); diff --git a/src/main/java/com/booleworks/logicng/solvers/sat/SATCall.java b/src/main/java/com/booleworks/logicng/solvers/sat/SATCall.java index 306f4f8c..f786e2a6 100644 --- a/src/main/java/com/booleworks/logicng/solvers/sat/SATCall.java +++ b/src/main/java/com/booleworks/logicng/solvers/sat/SATCall.java @@ -12,7 +12,7 @@ import com.booleworks.logicng.formulas.FType; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.propositions.Proposition; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.SolverState; @@ -56,7 +56,7 @@ public class SATCall implements AutoCloseable { private int pgOriginalClausesLength = -1; private Tristate satState; - SATCall(final SATSolver solverWrapper, final SATHandler handler, + SATCall(final SATSolver solverWrapper, final ComputationHandler handler, final List additionalPropositions, final List selectionOrder) { this.solverWrapper = solverWrapper; solver = solverWrapper.underlyingSolver(); @@ -67,7 +67,7 @@ public static SATCallBuilder builder(final SATSolver solver) { return new SATCallBuilder(solver); } - private void initAndSolve(final SATHandler handler, final List additionalPropositions, final List selectionOrder) { + private void initAndSolve(final ComputationHandler handler, final List additionalPropositions, final List selectionOrder) { solver.assertNotInSatCall(); if (solver.config.proofGeneration) { pgOriginalClausesLength = solver.pgOriginalClauses.size(); @@ -109,7 +109,7 @@ private Additionals splitPropsIntoLiteralsAndFormulas(final List additionalPropositions; private List selectionOrder; SATCallBuilder(final SATSolver solver) { this.solver = solver; + handler = NopHandler.get(); additionalPropositions = new ArrayList<>(); } @@ -46,7 +48,7 @@ public SATCall solve() { * @param handler the handler * @return this builder */ - public SATCallBuilder handler(final SATHandler handler) { + public SATCallBuilder handler(final ComputationHandler handler) { this.handler = handler; return this; } diff --git a/src/main/java/com/booleworks/logicng/transformations/AbortableFormulaTransformation.java b/src/main/java/com/booleworks/logicng/transformations/AbortableFormulaTransformation.java index 6ebbd369..97b61f9d 100644 --- a/src/main/java/com/booleworks/logicng/transformations/AbortableFormulaTransformation.java +++ b/src/main/java/com/booleworks/logicng/transformations/AbortableFormulaTransformation.java @@ -5,7 +5,7 @@ package com.booleworks.logicng.transformations; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.Handler; +import com.booleworks.logicng.handlers.ComputationHandler; /** * An abortable formula transformation is a stateless transformation which can @@ -15,15 +15,15 @@ * @version 3.0.0 * @since 3.0.0 */ -public abstract class AbortableFormulaTransformation extends StatelessFormulaTransformation { - protected final H handler; +public abstract class AbortableFormulaTransformation extends StatelessFormulaTransformation { + protected final ComputationHandler handler; /** * Constructor. * @param f the formula factory to generate new formulas * @param handler the handler for the transformation **/ - protected AbortableFormulaTransformation(final FormulaFactory f, final H handler) { + protected AbortableFormulaTransformation(final FormulaFactory f, final ComputationHandler handler) { super(f); this.handler = handler; } diff --git a/src/main/java/com/booleworks/logicng/transformations/BDDNormalFormTransformation.java b/src/main/java/com/booleworks/logicng/transformations/BDDNormalFormTransformation.java index 9a06919d..44f85490 100644 --- a/src/main/java/com/booleworks/logicng/transformations/BDDNormalFormTransformation.java +++ b/src/main/java/com/booleworks/logicng/transformations/BDDNormalFormTransformation.java @@ -8,6 +8,7 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.cache.TransformationCacheEntry; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.knowledgecompilation.bdds.BDD; import com.booleworks.logicng.knowledgecompilation.bdds.BDDFactory; import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; @@ -76,7 +77,7 @@ protected Formula compute(final Formula formula) { if (cached != null) { return cached; } - final BDD bdd = BDDFactory.build(f, formula, state, null); + final BDD bdd = BDDFactory.build(f, formula, state, NopHandler.get()); final Formula normalForm = cnf ? bdd.cnf() : bdd.dnf(); final Formula simplifiedNormalForm; final UnitPropagation up = new UnitPropagation(f); diff --git a/src/main/java/com/booleworks/logicng/transformations/CacheableAndAbortableFormulaTransformation.java b/src/main/java/com/booleworks/logicng/transformations/CacheableAndAbortableFormulaTransformation.java index 7e92930e..33d59dc9 100644 --- a/src/main/java/com/booleworks/logicng/transformations/CacheableAndAbortableFormulaTransformation.java +++ b/src/main/java/com/booleworks/logicng/transformations/CacheableAndAbortableFormulaTransformation.java @@ -8,7 +8,7 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.cache.CacheEntry; import com.booleworks.logicng.formulas.implementation.cached.CachingFormulaFactory; -import com.booleworks.logicng.handlers.Handler; +import com.booleworks.logicng.handlers.ComputationHandler; import java.util.Map; @@ -23,7 +23,7 @@ * @version 3.0.0 * @since 3.0.0 */ -public abstract class CacheableAndAbortableFormulaTransformation extends CacheableFormulaTransformation { +public abstract class CacheableAndAbortableFormulaTransformation extends CacheableFormulaTransformation { protected final H handler; /** diff --git a/src/main/java/com/booleworks/logicng/transformations/cnf/CNFEncoder.java b/src/main/java/com/booleworks/logicng/transformations/cnf/CNFEncoder.java index 3929273e..c41f7a77 100644 --- a/src/main/java/com/booleworks/logicng/transformations/cnf/CNFEncoder.java +++ b/src/main/java/com/booleworks/logicng/transformations/cnf/CNFEncoder.java @@ -4,6 +4,8 @@ package com.booleworks.logicng.transformations.cnf; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.FACTORIZATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.DISTRIBUTION_PERFORMED; import static com.booleworks.logicng.transformations.cnf.PlaistedGreenbaumTransformation.PGState; import com.booleworks.logicng.configurations.ConfigurationType; @@ -12,9 +14,9 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.FormulaTransformation; import com.booleworks.logicng.formulas.implementation.cached.CachingFormulaFactory; -import com.booleworks.logicng.formulas.implementation.noncaching.NonCachingFormulaFactory; import com.booleworks.logicng.handlers.ComputationHandler; -import com.booleworks.logicng.handlers.FactorizationHandler; +import com.booleworks.logicng.handlers.events.FactorizationCreatedClauseEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; import java.util.ArrayList; import java.util.List; @@ -125,8 +127,9 @@ private static FormulaTransformation getPgTransformation(final FormulaFactory f, /** * The factorization handler for the advanced CNF encoding. */ - protected static class AdvancedFactorizationHandler extends ComputationHandler implements FactorizationHandler { + protected static class AdvancedFactorizationHandler implements ComputationHandler { + protected boolean aborted = false; protected int distributionBoundary; protected int createdClauseBoundary; protected int currentDistributions; @@ -138,22 +141,21 @@ protected void setBounds(final int distributionBoundary, final int createdClause } @Override - public void started() { - super.started(); - currentDistributions = 0; - currentClauses = 0; - } - - @Override - public boolean performedDistribution() { - aborted = distributionBoundary != -1 && ++currentDistributions > distributionBoundary; + public boolean shouldResume(final LogicNGEvent event) { + if (event == FACTORIZATION_STARTED) { + currentDistributions = 0; + currentClauses = 0; + } else if (event == DISTRIBUTION_PERFORMED) { + aborted = distributionBoundary != -1 && ++currentDistributions > distributionBoundary; + } else if (event instanceof FactorizationCreatedClauseEvent) { + aborted = createdClauseBoundary != -1 && ++currentClauses > createdClauseBoundary; + } return !aborted; } @Override - public boolean createdClause(final Formula clause) { - aborted = createdClauseBoundary != -1 && ++currentClauses > createdClauseBoundary; - return !aborted; + public boolean isAborted() { + return aborted; } } } diff --git a/src/main/java/com/booleworks/logicng/transformations/cnf/CNFFactorization.java b/src/main/java/com/booleworks/logicng/transformations/cnf/CNFFactorization.java index 8608fa2e..a24ba2d1 100644 --- a/src/main/java/com/booleworks/logicng/transformations/cnf/CNFFactorization.java +++ b/src/main/java/com/booleworks/logicng/transformations/cnf/CNFFactorization.java @@ -4,12 +4,16 @@ package com.booleworks.logicng.transformations.cnf; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.FACTORIZATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.DISTRIBUTION_PERFORMED; + import com.booleworks.logicng.formulas.FType; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.cache.TransformationCacheEntry; -import com.booleworks.logicng.handlers.FactorizationHandler; -import com.booleworks.logicng.handlers.Handler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.FactorizationCreatedClauseEvent; import com.booleworks.logicng.transformations.CacheableAndAbortableFormulaTransformation; import java.util.Iterator; @@ -21,7 +25,7 @@ * @version 3.0.0 * @since 1.0 */ -public final class CNFFactorization extends CacheableAndAbortableFormulaTransformation { +public final class CNFFactorization extends CacheableAndAbortableFormulaTransformation { private boolean proceed = true; @@ -30,7 +34,7 @@ public final class CNFFactorization extends CacheableAndAbortableFormulaTransfor * @param f the formula factory to generate new formulas */ public CNFFactorization(final FormulaFactory f) { - super(f, TransformationCacheEntry.FACTORIZED_CNF, null); + super(f, TransformationCacheEntry.FACTORIZED_CNF, NopHandler.get()); } /** @@ -39,7 +43,7 @@ public CNFFactorization(final FormulaFactory f) { * @param cache the cache to use for the transformation */ public CNFFactorization(final FormulaFactory f, final Map cache) { - this(f, null, cache); + this(f, NopHandler.get(), cache); } /** @@ -47,7 +51,7 @@ public CNFFactorization(final FormulaFactory f, final Map cach * @param f the formula factory to generate new formulas * @param handler the handler for the transformation */ - public CNFFactorization(final FormulaFactory f, final FactorizationHandler handler) { + public CNFFactorization(final FormulaFactory f, final ComputationHandler handler) { super(f, TransformationCacheEntry.FACTORIZED_CNF, handler); } @@ -59,15 +63,14 @@ public CNFFactorization(final FormulaFactory f, final FactorizationHandler handl * @param cache the cache to use for the transformation * @param handler the handler for the transformation */ - public CNFFactorization(final FormulaFactory f, final FactorizationHandler handler, + public CNFFactorization(final FormulaFactory f, final ComputationHandler handler, final Map cache) { super(f, cache, handler); } @Override public Formula apply(final Formula formula) { - Handler.start(handler); - proceed = true; + proceed = handler.shouldResume(FACTORIZATION_STARTED); return applyRec(formula); } @@ -137,7 +140,7 @@ private Formula applyRec(final Formula formula) { */ private Formula distribute(final Formula f1, final Formula f2) { if (handler != null) { - proceed = handler.performedDistribution(); + proceed = handler.shouldResume(DISTRIBUTION_PERFORMED); } if (proceed) { if (f1.type() == FType.AND || f2.type() == FType.AND) { @@ -153,7 +156,7 @@ private Formula distribute(final Formula f1, final Formula f2) { } final Formula clause = f.or(f1, f2); if (handler != null) { - proceed = handler.createdClause(clause); + proceed = handler.shouldResume(new FactorizationCreatedClauseEvent(clause)); } return clause; } diff --git a/src/main/java/com/booleworks/logicng/transformations/dnf/DNFFactorization.java b/src/main/java/com/booleworks/logicng/transformations/dnf/DNFFactorization.java index c44df72b..d2b369b7 100644 --- a/src/main/java/com/booleworks/logicng/transformations/dnf/DNFFactorization.java +++ b/src/main/java/com/booleworks/logicng/transformations/dnf/DNFFactorization.java @@ -4,12 +4,16 @@ package com.booleworks.logicng.transformations.dnf; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.FACTORIZATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.DISTRIBUTION_PERFORMED; + import com.booleworks.logicng.formulas.FType; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.cache.TransformationCacheEntry; -import com.booleworks.logicng.handlers.FactorizationHandler; -import com.booleworks.logicng.handlers.Handler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.events.FactorizationCreatedClauseEvent; import com.booleworks.logicng.transformations.CacheableAndAbortableFormulaTransformation; import java.util.Iterator; @@ -21,7 +25,7 @@ * @version 3.0.0 * @since 1.0 */ -public final class DNFFactorization extends CacheableAndAbortableFormulaTransformation { +public final class DNFFactorization extends CacheableAndAbortableFormulaTransformation { private boolean proceed = true; @@ -30,7 +34,7 @@ public final class DNFFactorization extends CacheableAndAbortableFormulaTransfor * @param f the formula factory to generate new formulas */ public DNFFactorization(final FormulaFactory f) { - super(f, TransformationCacheEntry.FACTORIZED_DNF, null); + super(f, TransformationCacheEntry.FACTORIZED_DNF, NopHandler.get()); } /** @@ -39,7 +43,7 @@ public DNFFactorization(final FormulaFactory f) { * @param cache the cache to use for the transformation */ public DNFFactorization(final FormulaFactory f, final Map cache) { - this(f, null, cache); + this(f, NopHandler.get(), cache); } /** @@ -47,7 +51,7 @@ public DNFFactorization(final FormulaFactory f, final Map cach * @param f the formula factory to generate new formulas * @param handler the handler for the transformation */ - public DNFFactorization(final FormulaFactory f, final FactorizationHandler handler) { + public DNFFactorization(final FormulaFactory f, final ComputationHandler handler) { super(f, TransformationCacheEntry.FACTORIZED_DNF, handler); } @@ -59,14 +63,14 @@ public DNFFactorization(final FormulaFactory f, final FactorizationHandler handl * @param cache the cache to use for the transformation * @param handler the handler for the transformation */ - public DNFFactorization(final FormulaFactory f, final FactorizationHandler handler, + public DNFFactorization(final FormulaFactory f, final ComputationHandler handler, final Map cache) { super(f, cache, handler); } @Override public Formula apply(final Formula formula) { - Handler.start(handler); + handler.shouldResume(FACTORIZATION_STARTED); proceed = true; return applyRec(formula); } @@ -135,7 +139,7 @@ private Formula applyRec(final Formula formula) { */ private Formula distribute(final Formula f1, final Formula f2) { if (handler != null) { - proceed = handler.performedDistribution(); + proceed = handler.shouldResume(DISTRIBUTION_PERFORMED); } if (proceed) { if (f1.type() == FType.OR || f2.type() == FType.OR) { @@ -151,7 +155,7 @@ private Formula distribute(final Formula f1, final Formula f2) { } final Formula clause = f.and(f1, f2); if (handler != null) { - proceed = handler.createdClause(clause); + proceed = handler.shouldResume(new FactorizationCreatedClauseEvent(clause)); } return clause; } diff --git a/src/main/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifier.java b/src/main/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifier.java index 18f0434e..160eb9a8 100644 --- a/src/main/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifier.java +++ b/src/main/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifier.java @@ -4,6 +4,9 @@ package com.booleworks.logicng.transformations.simplification; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.ADVANCED_SIMPLIFICATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.NO_EVENT; + import com.booleworks.logicng.backbones.Backbone; import com.booleworks.logicng.backbones.BackboneGeneration; import com.booleworks.logicng.backbones.BackboneType; @@ -13,8 +16,8 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; -import com.booleworks.logicng.handlers.Handler; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.primecomputation.PrimeCompiler; import com.booleworks.logicng.primecomputation.PrimeResult; import com.booleworks.logicng.transformations.AbortableFormulaTransformation; @@ -53,7 +56,7 @@ * @version 3.0.0 * @since 2.0.0 */ -public final class AdvancedSimplifier extends AbortableFormulaTransformation { +public final class AdvancedSimplifier extends AbortableFormulaTransformation { private final AdvancedSimplifierConfig config; @@ -63,7 +66,7 @@ public final class AdvancedSimplifier extends AbortableFormulaTransformation backboneLiterals = new TreeSet<>(); if (config.restrictBackbone) { final Backbone backbone = BackboneGeneration.compute(f, Collections.singletonList(formula), - formula.variables(f), BackboneType.POSITIVE_AND_NEGATIVE, OptimizationHandler.satHandler(handler)); - if (backbone == null || Handler.aborted(handler)) { + formula.variables(f), BackboneType.POSITIVE_AND_NEGATIVE, handler); + if (backbone == null || !handler.shouldResume(NO_EVENT)) { return null; } if (!backbone.isSat()) { @@ -141,14 +144,14 @@ private Formula computeMinDnf(final FormulaFactory f, Formula simplified) { final PrimeResult primeResult = PrimeCompiler.getWithMinimization().compute(f, simplified, PrimeResult.CoverageType.IMPLICANTS_COMPLETE, handler); - if (primeResult == null || Handler.aborted(handler)) { + if (primeResult == null || !handler.shouldResume(NO_EVENT)) { return null; } final List> primeImplicants = primeResult.getPrimeImplicants(); final List minimizedPIs = SmusComputation.computeSmusForFormulas(f, negateAllLiterals(f, primeImplicants), Collections.singletonList(simplified), handler); - if (minimizedPIs == null || Handler.aborted(handler)) { + if (minimizedPIs == null || !handler.shouldResume(NO_EVENT)) { return null; } simplified = diff --git a/src/main/java/com/booleworks/logicng/transformations/simplification/QuineMcCluskeySimplifier.java b/src/main/java/com/booleworks/logicng/transformations/simplification/QuineMcCluskeySimplifier.java index d5d12f28..dddc5330 100644 --- a/src/main/java/com/booleworks/logicng/transformations/simplification/QuineMcCluskeySimplifier.java +++ b/src/main/java/com/booleworks/logicng/transformations/simplification/QuineMcCluskeySimplifier.java @@ -6,7 +6,8 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.transformations.AbortableFormulaTransformation; /** @@ -18,14 +19,14 @@ * @version 3.0.0 * @since 1.4.0 */ -public class QuineMcCluskeySimplifier extends AbortableFormulaTransformation { +public class QuineMcCluskeySimplifier extends AbortableFormulaTransformation { /** * Constructor. * @param f the formula factory to generate new formulas **/ protected QuineMcCluskeySimplifier(final FormulaFactory f) { - super(f, null); + super(f, NopHandler.get()); } /** @@ -33,7 +34,7 @@ protected QuineMcCluskeySimplifier(final FormulaFactory f) { * @param f the formula factory to generate new formulas * @param handler the optimization handler to abort Quine-McCluskey **/ - protected QuineMcCluskeySimplifier(final FormulaFactory f, final OptimizationHandler handler) { + protected QuineMcCluskeySimplifier(final FormulaFactory f, final ComputationHandler handler) { super(f, handler); } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 225d5fc7..5707c6bf 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,5 +1,6 @@ module logicng { requires org.antlr.antlr4.runtime; + requires java.xml; exports com.booleworks.logicng.backbones; @@ -77,4 +78,5 @@ exports com.booleworks.logicng.util; opens com.booleworks.logicng.solvers.sat; + exports com.booleworks.logicng.handlers.events; } diff --git a/src/test/java/com/booleworks/logicng/LogicNGVersionTest.java b/src/test/java/com/booleworks/logicng/LogicNGVersionTest.java index 7a741125..98ff378c 100644 --- a/src/test/java/com/booleworks/logicng/LogicNGVersionTest.java +++ b/src/test/java/com/booleworks/logicng/LogicNGVersionTest.java @@ -25,7 +25,6 @@ public void test() throws ParserException { final SATSolver solver = SATSolver.newSolver(f); solver.add(f.parse("(A | ~B) & (B | C)")); solver.satCall().addFormulas(f.parse("~A"), f.parse("~C")).sat(); - System.out.println(solver); } @Test diff --git a/src/test/java/com/booleworks/logicng/backbones/BackboneGenerationTest.java b/src/test/java/com/booleworks/logicng/backbones/BackboneGenerationTest.java index 53b9d9f4..9c16983a 100644 --- a/src/test/java/com/booleworks/logicng/backbones/BackboneGenerationTest.java +++ b/src/test/java/com/booleworks/logicng/backbones/BackboneGenerationTest.java @@ -14,7 +14,7 @@ import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; import com.booleworks.logicng.handlers.BoundedSatHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.DimacsReader; import com.booleworks.logicng.io.readers.FormulaReader; @@ -41,7 +41,7 @@ public class BackboneGenerationTest { public void testNoFormulas() { assertThatThrownBy(() -> BackboneGeneration.compute(f, Collections.emptyList(), new TreeSet<>(), BackboneType.POSITIVE_AND_NEGATIVE)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -68,7 +68,7 @@ public void testBackboneGeneration() { .containsExactly(x.negate(f), z.negate(f)); assertThat( BackboneGeneration.compute(f, collection, new ArrayList<>(Arrays.asList(x, y))).getCompleteBackbone(f)) - .containsExactly(x.negate(f), y); + .containsExactly(x.negate(f), y); assertThat(BackboneGeneration .compute(f, collection, new ArrayList<>(Arrays.asList(x, y)), BackboneType.ONLY_NEGATIVE) .getCompleteBackbone(f)).containsExactly(x.negate(f)); @@ -333,12 +333,12 @@ public void testBackboneType() { public void testCancellationPoints() throws IOException { final List formulas = DimacsReader.readCNF(f, "src/test/resources/sat/term1_gr_rcs_w4.shuffled.cnf"); for (int numStarts = 0; numStarts < 10; numStarts++) { - final SATHandler handler = new BoundedSatHandler(numStarts); + final ComputationHandler handler = new BoundedSatHandler(numStarts); final Backbone result = BackboneGeneration.compute(f, formulas, FormulaHelper.variables(f, formulas), BackboneType.POSITIVE_AND_NEGATIVE, handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isNull(); } } diff --git a/src/test/java/com/booleworks/logicng/encodings/CcAlkTest.java b/src/test/java/com/booleworks/logicng/encodings/CcAlkTest.java index 84430e08..4b384ec7 100644 --- a/src/test/java/com/booleworks/logicng/encodings/CcAlkTest.java +++ b/src/test/java/com/booleworks/logicng/encodings/CcAlkTest.java @@ -4,6 +4,7 @@ package com.booleworks.logicng.encodings; +import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -70,7 +71,7 @@ private void testCC(final FormulaFactory f, final int numLits, final int rhs, fi .build()) .build(); - Assertions.assertThat(solver.execute(me)) + assertThat(solver.execute(me)) .hasSize(expected) .allMatch(m -> m.positiveVariables().size() >= rhs); } diff --git a/src/test/java/com/booleworks/logicng/explanations/drup/DRUPTest.java b/src/test/java/com/booleworks/logicng/explanations/drup/DRUPTest.java index e7222778..3e6cf159 100644 --- a/src/test/java/com/booleworks/logicng/explanations/drup/DRUPTest.java +++ b/src/test/java/com/booleworks/logicng/explanations/drup/DRUPTest.java @@ -283,7 +283,6 @@ public void testWithAssumptionSolving() throws ParserException { solver.add(f.parse("A2 => ~A1 | ~A3")); try (final SATCall satCall = solver.satCall().addFormulas(f.variable("A3"), f.variable("A1")).solve()) { assertThat(satCall.getSatResult()).isEqualTo(Tristate.FALSE); - System.out.println(satCall.unsatCore()); } } diff --git a/src/test/java/com/booleworks/logicng/explanations/mus/MUSGenerationTest.java b/src/test/java/com/booleworks/logicng/explanations/mus/MUSGenerationTest.java index 870b9cb9..c0c551e0 100644 --- a/src/test/java/com/booleworks/logicng/explanations/mus/MUSGenerationTest.java +++ b/src/test/java/com/booleworks/logicng/explanations/mus/MUSGenerationTest.java @@ -13,7 +13,7 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.handlers.BoundedSatHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.io.readers.DimacsReader; import com.booleworks.logicng.propositions.StandardProposition; import com.booleworks.logicng.solvers.SATSolver; @@ -70,7 +70,7 @@ public void testSATFormulaSetDeletionBasedMUS() { final StandardProposition proposition = new StandardProposition(f.variable("a")); assertThatThrownBy(() -> mus.computeMUS(f, Collections.singletonList(proposition), MUSConfig.builder().algorithm(MUSConfig.Algorithm.DELETION).build())) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -103,7 +103,7 @@ public void testSATFormulaSetPlainInsertionBasedMUS() { final StandardProposition proposition = new StandardProposition(f.variable("a")); assertThatThrownBy(() -> mus.computeMUS(f, Collections.singletonList(proposition), MUSConfig.builder().algorithm(MUSConfig.Algorithm.PLAIN_INSERTION).build())) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -130,13 +130,13 @@ public void testDeletionBasedCancellationPoints() throws IOException { .map(StandardProposition::new) .collect(Collectors.toList()); for (int numStarts = 0; numStarts < 20; numStarts++) { - final SATHandler handler = new BoundedSatHandler(numStarts); + final ComputationHandler handler = new BoundedSatHandler(numStarts); final MUSConfig config = MUSConfig.builder().handler(handler).algorithm(MUSConfig.Algorithm.PLAIN_INSERTION).build(); final UNSATCore result = mus.computeMUS(f, propositions, config); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isNull(); } } @@ -152,12 +152,12 @@ public void testCancellationPoints() throws IOException { Arrays.asList(MUSConfig.Algorithm.DELETION, MUSConfig.Algorithm.PLAIN_INSERTION); for (final MUSConfig.Algorithm algorithm : algorithms) { for (int numStarts = 0; numStarts < 10; numStarts++) { - final SATHandler handler = new BoundedSatHandler(numStarts); + final ComputationHandler handler = new BoundedSatHandler(numStarts); final MUSConfig config = MUSConfig.builder().handler(handler).algorithm(algorithm).build(); final UNSATCore result = mus.computeMUS(f, propositions, config); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isNull(); } } diff --git a/src/test/java/com/booleworks/logicng/explanations/smus/SmusComputationTest.java b/src/test/java/com/booleworks/logicng/explanations/smus/SmusComputationTest.java index e7f0da6a..b84ab57b 100644 --- a/src/test/java/com/booleworks/logicng/explanations/smus/SmusComputationTest.java +++ b/src/test/java/com/booleworks/logicng/explanations/smus/SmusComputationTest.java @@ -4,15 +4,17 @@ package com.booleworks.logicng.explanations.smus; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.FIXED_END; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.RESTARTING_TIMEOUT; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.SINGLE_TIMEOUT; import static org.assertj.core.api.Assertions.assertThat; import com.booleworks.logicng.LongRunningTag; import com.booleworks.logicng.TestWithExampleFormulas; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.handlers.BoundedOptimizationHandler; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.handlers.TimeoutHandler; -import com.booleworks.logicng.handlers.TimeoutOptimizationHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.DimacsReader; import com.booleworks.logicng.io.readers.FormulaReader; @@ -203,31 +205,31 @@ public void testManyConflicts() throws ParserException { @Test public void testTimeoutHandlerSmall() throws ParserException { - final List handlers = Arrays.asList( - new TimeoutOptimizationHandler(5_000L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), - new TimeoutOptimizationHandler(5_000L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), - new TimeoutOptimizationHandler(System.currentTimeMillis() + 5_000L, TimeoutHandler.TimerType.FIXED_END) + final List handlers = Arrays.asList( + new TimeoutHandler(5_000L, SINGLE_TIMEOUT), + new TimeoutHandler(5_000L, RESTARTING_TIMEOUT), + new TimeoutHandler(System.currentTimeMillis() + 5_000L, FIXED_END) ); final List formulas = Arrays.asList( f.parse("a"), f.parse("~a") ); - for (final TimeoutOptimizationHandler handler : handlers) { + for (final TimeoutHandler handler : handlers) { testHandler(handler, formulas, false); } } @Test public void testTimeoutHandlerLarge() throws ParserException, IOException { - final List handlers = Arrays.asList( - new TimeoutOptimizationHandler(1L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), - new TimeoutOptimizationHandler(1L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), - new TimeoutOptimizationHandler(System.currentTimeMillis() + 1L, TimeoutHandler.TimerType.FIXED_END) + final List handlers = Arrays.asList( + new TimeoutHandler(1L, SINGLE_TIMEOUT), + new TimeoutHandler(1L, RESTARTING_TIMEOUT), + new TimeoutHandler(System.currentTimeMillis() + 1L, FIXED_END) ); final Formula formula = FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/large_formula.txt"); final List formulas = formula.stream().collect(Collectors.toList()); - for (final TimeoutOptimizationHandler handler : handlers) { + for (final TimeoutHandler handler : handlers) { testHandler(handler, formulas, true); } } @@ -238,7 +240,7 @@ public void testCancellationPoints() throws IOException { final List formulas = DimacsReader.readCNF(f, "src/test/resources/sat/unsat/bf0432-007.cnf"); for (int numOptimizationStarts = 1; numOptimizationStarts < 5; numOptimizationStarts++) { for (int numSatHandlerStarts = 1; numSatHandlerStarts < 10; numSatHandlerStarts++) { - final OptimizationHandler handler = + final ComputationHandler handler = new BoundedOptimizationHandler(numSatHandlerStarts, numOptimizationStarts); testHandler(handler, formulas, true); } @@ -247,7 +249,7 @@ public void testCancellationPoints() throws IOException { @Test public void testMinimumHittingSetCancelled() throws ParserException { - final OptimizationHandler handler = new BoundedOptimizationHandler(-1, 0); + final ComputationHandler handler = new BoundedOptimizationHandler(-1, 0); final List formulas = Arrays.asList( f.parse("a"), f.parse("~a") @@ -257,7 +259,7 @@ public void testMinimumHittingSetCancelled() throws ParserException { @Test public void testHSolverCancelled() throws ParserException { - final OptimizationHandler handler = new BoundedOptimizationHandler(-1, 3); + final ComputationHandler handler = new BoundedOptimizationHandler(-1, 3); final List formulas = Arrays.asList( f.parse("a"), f.parse("~a"), @@ -266,11 +268,11 @@ public void testHSolverCancelled() throws ParserException { testHandler(handler, formulas, true); } - private void testHandler(final OptimizationHandler handler, final List formulas, + private void testHandler(final ComputationHandler handler, final List formulas, final boolean expAborted) { final List result = SmusComputation.computeSmusForFormulas(f, formulas, Collections.emptyList(), handler); - assertThat(handler.aborted()).isEqualTo(expAborted); + assertThat(handler.isAborted()).isEqualTo(expAborted); if (expAborted) { assertThat(result).isNull(); } else { diff --git a/src/test/java/com/booleworks/logicng/handlers/BoundedOptimizationHandler.java b/src/test/java/com/booleworks/logicng/handlers/BoundedOptimizationHandler.java index 9017fd27..116c3795 100644 --- a/src/test/java/com/booleworks/logicng/handlers/BoundedOptimizationHandler.java +++ b/src/test/java/com/booleworks/logicng/handlers/BoundedOptimizationHandler.java @@ -4,9 +4,8 @@ package com.booleworks.logicng.handlers; -import com.booleworks.logicng.datastructures.Assignment; - -import java.util.function.Supplier; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; /** * Bounded optimization handler for testing purposes. @@ -16,42 +15,40 @@ * @version 2.1.0 * @since 2.1.0 */ -public class BoundedOptimizationHandler implements OptimizationHandler { - private final SATHandler satHandler; +public class BoundedOptimizationHandler implements ComputationHandler { private final int startsLimit; + private final int satStartsLimit; private int numStarts; + private int numSatStarts; private boolean aborted; /** * Constructs a new instance with the given starts limits. - * @param satHandlerStartsLimit the number of starts limit for the SAT - * handler, if -1 then no limit is set - * @param startsLimit the number of starts limit, if -1 then no - * limit is set + * @param satStartsLimit the number of starts limit for the SAT + * solver, if -1 then no limit is set + * @param startsLimit the number of starts limit, if -1 then no + * limit is set */ - public BoundedOptimizationHandler(final int satHandlerStartsLimit, final int startsLimit) { - satHandler = new BoundedSatHandler(satHandlerStartsLimit); + public BoundedOptimizationHandler(final int satStartsLimit, final int startsLimit) { + this.satStartsLimit = satStartsLimit; this.startsLimit = startsLimit; numStarts = 0; } @Override - public boolean aborted() { - return satHandler.aborted() || aborted; - } - - @Override - public void started() { - aborted = startsLimit != -1 && ++numStarts >= startsLimit; - } - - @Override - public SATHandler satHandler() { - return satHandler; + public boolean isAborted() { + return aborted; } @Override - public boolean foundBetterBound(final Supplier currentResultProvider) { + public boolean shouldResume(final LogicNGEvent event) { + if (event instanceof ComputationStartedEvent) { + if (event == ComputationStartedEvent.SAT_CALL_STARTED) { + aborted |= satStartsLimit != -1 && ++numSatStarts >= satStartsLimit; + } else { + aborted |= startsLimit != -1 && ++numStarts >= startsLimit; + } + } return !aborted; } } diff --git a/src/test/java/com/booleworks/logicng/handlers/BoundedSatHandler.java b/src/test/java/com/booleworks/logicng/handlers/BoundedSatHandler.java index bdbd9da6..1f312778 100644 --- a/src/test/java/com/booleworks/logicng/handlers/BoundedSatHandler.java +++ b/src/test/java/com/booleworks/logicng/handlers/BoundedSatHandler.java @@ -4,6 +4,9 @@ package com.booleworks.logicng.handlers; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; + /** * Bounded SAT handler for testing purposes. *

@@ -11,7 +14,7 @@ * @version 2.1.0 * @since 2.1.0 */ -public class BoundedSatHandler implements SATHandler { +public class BoundedSatHandler implements ComputationHandler { private final int startsLimit; private int numStarts; private boolean aborted; @@ -26,17 +29,15 @@ public BoundedSatHandler(final int startsLimit) { } @Override - public boolean aborted() { + public boolean isAborted() { return aborted; } @Override - public void started() { - aborted = startsLimit != -1 && ++numStarts >= startsLimit; - } - - @Override - public boolean detectedConflict() { + public boolean shouldResume(final LogicNGEvent event) { + if (event == ComputationStartedEvent.SAT_CALL_STARTED) { + aborted = startsLimit != -1 && ++numStarts >= startsLimit; + } return !aborted; } } diff --git a/src/test/java/com/booleworks/logicng/handlers/ModelEnumerationHandlerTest.java b/src/test/java/com/booleworks/logicng/handlers/ModelEnumerationHandlerTest.java index 8bf37f98..1f3596e8 100644 --- a/src/test/java/com/booleworks/logicng/handlers/ModelEnumerationHandlerTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/ModelEnumerationHandlerTest.java @@ -37,13 +37,13 @@ public void testTimeoutHandler() throws ParserException, InterruptedException { final Formula formula = f.parse("A | B | C | D | E | F | G | H | I | J | K | L | N | M | O | P | Q | R | S | T | U | V | W"); solver.add(formula); - final TimeoutModelEnumerationHandler handler = new TimeoutModelEnumerationHandler(100); + final TimeoutHandler handler = new TimeoutHandler(100); final ModelCountingFunction enumeration = ModelCountingFunction.builder(formula.variables(f)) .configuration(ModelEnumerationConfig.builder().handler(handler).build()) .build(); Thread.sleep(150); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); final long start = System.currentTimeMillis(); solver.execute(enumeration); @@ -53,7 +53,7 @@ public void testTimeoutHandler() throws ParserException, InterruptedException { // Should be very unlikely that the formula can be fully enumerated in // 100ms. // Thus, we expect the handler to stop the execution. - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(timeElapsed).isGreaterThanOrEqualTo(100L); } @@ -68,11 +68,11 @@ public void testNumberOfModelsHandler() throws ParserException { final NumberOfModelsHandler handler = new NumberOfModelsHandler(i); final ModelCountingFunction enumeration = ModelCountingFunction.builder(vars) .configuration(ModelEnumerationConfig.builder().handler(handler).strategy( - DefaultModelEnumerationStrategy.builder().maxNumberOfModels(200).build() - ).build() + DefaultModelEnumerationStrategy.builder().maxNumberOfModels(200).build() + ).build() ).build(); final BigInteger numberOfModels = solver.execute(enumeration); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(numberOfModels.longValueExact()).isLessThanOrEqualTo(i); } } diff --git a/src/test/java/com/booleworks/logicng/handlers/TimeoutBDDHandlerTest.java b/src/test/java/com/booleworks/logicng/handlers/TimeoutBDDHandlerTest.java index bb14df13..acbd3319 100644 --- a/src/test/java/com/booleworks/logicng/handlers/TimeoutBDDHandlerTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/TimeoutBDDHandlerTest.java @@ -4,7 +4,10 @@ package com.booleworks.logicng.handlers; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.BDD_COMPUTATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.BDD_NEW_REF_ADDED; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -41,11 +44,11 @@ public void init() { @Test public void testNewRefAdded() throws InterruptedException { - final TimeoutBDDHandler handler = new TimeoutBDDHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); - handler.started(); - assertThat(handler.newRefAdded()).isTrue(); + final TimeoutHandler handler = new TimeoutHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); + handler.shouldResume(BDD_COMPUTATION_STARTED); + assertThat(handler.shouldResume(BDD_NEW_REF_ADDED)).isTrue(); Thread.sleep(200); - assertThat(handler.newRefAdded()).isFalse(); + assertThat(handler.shouldResume(BDD_NEW_REF_ADDED)).isFalse(); } @Test @@ -53,12 +56,12 @@ public void testThatMethodsAreCalled() throws ParserException { final Formula formula = f.parse("(A => ~B) & ((A & C) | (D & ~C)) & (A | Y | X)"); final VariableOrderingProvider provider = new BFSOrdering(); final BDDKernel kernel = new BDDKernel(f, provider.getOrder(f, formula), 100, 100); - final TimeoutBDDHandler handler = Mockito.mock(TimeoutBDDHandler.class); + final TimeoutHandler handler = Mockito.mock(TimeoutHandler.class); BDDFactory.build(f, formula, kernel, handler); - verify(handler, times(1)).started(); - verify(handler, atLeast(1)).newRefAdded(); + verify(handler, times(1)).shouldResume(eq(BDD_COMPUTATION_STARTED)); + verify(handler, atLeast(1)).shouldResume(eq(BDD_NEW_REF_ADDED)); } @Test @@ -66,16 +69,17 @@ public void testThatNewRefAddedHandledProperly() throws ParserException { final Formula formula = f.parse("(A => ~B) & ((A & C) | ~(D & ~C)) & (A | Y | X)"); final VariableOrderingProvider provider = new BFSOrdering(); final BDDKernel kernel = new BDDKernel(f, provider.getOrder(f, formula), 100, 100); - final TimeoutBDDHandler handler = Mockito.mock(TimeoutBDDHandler.class); + final ComputationHandler handler = Mockito.mock(ComputationHandler.class); final AtomicInteger count = new AtomicInteger(0); - when(handler.newRefAdded()).then(invocationOnMock -> count.addAndGet(1) < 5); + when(handler.shouldResume(eq(BDD_COMPUTATION_STARTED))).thenReturn(true); + when(handler.shouldResume(eq(BDD_NEW_REF_ADDED))).thenAnswer(invocationOnMock -> count.addAndGet(1) < 5); final BDD result = BDDFactory.build(f, formula, kernel, handler); assertThat(result).isEqualTo(new BDD(BDDKernel.BDD_ABORT, kernel)); - verify(handler, times(1)).started(); - verify(handler, times(5)).newRefAdded(); + verify(handler, times(1)).shouldResume(eq(BDD_COMPUTATION_STARTED)); + verify(handler, times(5)).shouldResume(eq(BDD_NEW_REF_ADDED)); } @Test @@ -83,7 +87,7 @@ public void testTimeoutHandlerSingleTimeout() { final Formula formula = pg.generate(10); final VariableOrderingProvider provider = new BFSOrdering(); final BDDKernel kernel = new BDDKernel(f, provider.getOrder(f, formula), 100, 100); - final TimeoutBDDHandler handler = new TimeoutBDDHandler(100L); + final TimeoutHandler handler = new TimeoutHandler(100L); final BDD result = BDDFactory.build(f, formula, kernel, handler); @@ -96,8 +100,8 @@ public void testTimeoutHandlerFixedEnd() { final Formula formula = pg.generate(10); final VariableOrderingProvider provider = new BFSOrdering(); final BDDKernel kernel = new BDDKernel(f, provider.getOrder(f, formula), 100, 100); - final TimeoutBDDHandler handler = - new TimeoutBDDHandler(System.currentTimeMillis() + 100L, TimeoutHandler.TimerType.FIXED_END); + final TimeoutHandler handler = + new TimeoutHandler(System.currentTimeMillis() + 100L, TimeoutHandler.TimerType.FIXED_END); final BDD result = BDDFactory.build(f, formula, kernel, handler); diff --git a/src/test/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandlerTest.java b/src/test/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandlerTest.java index 7e84ad86..9fc0e7d6 100644 --- a/src/test/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandlerTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/TimeoutMaxSATHandlerTest.java @@ -4,18 +4,19 @@ package com.booleworks.logicng.handlers; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.FIXED_END; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.SINGLE_TIMEOUT; +import static com.booleworks.logicng.handlers.events.ComputationFinishedEvent.MAX_SAT_CALL_FINISHED; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.MAX_SAT_CALL_STARTED; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.lenient; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; +import com.booleworks.logicng.handlers.events.MaxSatNewLowerBoundEvent; +import com.booleworks.logicng.handlers.events.MaxSatNewUpperBoundEvent; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.DimacsReader; import com.booleworks.logicng.solvers.MaxSATSolver; @@ -30,7 +31,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; @ExtendWith(MockitoExtension.class) class TimeoutMaxSATHandlerTest { @@ -54,20 +54,20 @@ public void init() { @Test public void testTimeoutForLowerBound() throws InterruptedException { - final TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); - handler.started(); - assertThat(handler.foundLowerBound(1, new Assignment())).isTrue(); + final TimeoutHandler handler = new TimeoutHandler(100, SINGLE_TIMEOUT); + handler.shouldResume(MAX_SAT_CALL_STARTED); + assertThat(handler.shouldResume(new MaxSatNewLowerBoundEvent(1))).isTrue(); Thread.sleep(200); - assertThat(handler.foundLowerBound(1, new Assignment())).isFalse(); + assertThat(handler.shouldResume(new MaxSatNewLowerBoundEvent(1))).isFalse(); } @Test public void testTimeoutForUpperBound() throws InterruptedException { - final TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); - handler.started(); - assertThat(handler.foundUpperBound(1, new Assignment())).isTrue(); + final TimeoutHandler handler = new TimeoutHandler(100, SINGLE_TIMEOUT); + handler.shouldResume(MAX_SAT_CALL_STARTED); + assertThat(handler.shouldResume(new MaxSatNewUpperBoundEvent(1))).isTrue(); Thread.sleep(200); - assertThat(handler.foundUpperBound(1, new Assignment())).isFalse(); + assertThat(handler.shouldResume(new MaxSatNewUpperBoundEvent(1))).isFalse(); } @Test @@ -77,38 +77,11 @@ public void testThatMethodsAreCalled() throws ParserException { solver.addHardFormula(f.parse("A&B")); solver.addSoftFormula(f.parse("~A"), weight); solver.addSoftFormula(f.parse("~B"), weight); - final TimeoutMaxSATHandler handler = Mockito.mock(TimeoutMaxSATHandler.class); + final TimeoutHandler handler = Mockito.mock(TimeoutHandler.class); solver.solve(handler); - verify(handler, times(1)).started(); - verify(handler, atLeast(1)).satHandler(); - verify(handler, times(1)).finishedSolving(); - } - } - - @Test - public void testThatSatHandlerIsHandledProperly() throws IOException { - final List formulas = DimacsReader.readCNF(f, "src/test/resources/sat/unsat/pret60_40.cnf"); - for (final MaxSATSolver solver : solvers) { - final int weight = solver.isWeighted() ? 2 : 1; - formulas.forEach(c -> solver.addSoftFormula(c, weight)); - final TimeoutSATHandler satHandler = Mockito.mock(TimeoutSATHandler.class); - final TimeoutMaxSATHandler handler = Mockito.mock(TimeoutMaxSATHandler.class); - when(handler.satHandler()).thenReturn(satHandler); - lenient().when(handler.foundLowerBound(anyInt(), any())).thenReturn(true); - lenient().when(handler.foundUpperBound(anyInt(), any())).thenReturn(true); - final AtomicInteger count = new AtomicInteger(0); - when(satHandler.detectedConflict()).thenReturn(true); - when(satHandler.aborted()).then(invocationOnMock -> count.addAndGet(1) > 1); - - final MaxSAT.MaxSATResult solve = solver.solve(handler); - - assertThat(solve).isEqualTo(MaxSAT.MaxSATResult.UNDEF); - - verify(handler, times(1)).started(); - verify(handler, atLeast(1)).satHandler(); - verify(handler, times(1)).finishedSolving(); - verify(satHandler, times(2)).aborted(); + verify(handler, times(1)).shouldResume(eq(MAX_SAT_CALL_STARTED)); + verify(handler, times(1)).shouldResume(eq(MAX_SAT_CALL_FINISHED)); } } @@ -119,11 +92,11 @@ public void testTimeoutHandlerSingleTimeout() throws IOException { for (final MaxSATSolver solver : solvers) { final int weight = solver.isWeighted() ? 2 : 1; formulas.forEach(c -> solver.addSoftFormula(c, weight)); - final TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(10L); + final TimeoutHandler handler = new TimeoutHandler(10L); final MaxSAT.MaxSATResult solve = solver.solve(handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(solve).isEqualTo(MaxSAT.MaxSATResult.UNDEF); } } @@ -134,12 +107,11 @@ public void testTimeoutHandlerFixedEnd() { for (final MaxSATSolver solver : solvers) { final int weight = solver.isWeighted() ? 2 : 1; ph.forEach(c -> solver.addSoftFormula(c, weight)); - final TimeoutMaxSATHandler handler = - new TimeoutMaxSATHandler(System.currentTimeMillis() + 100L, TimeoutHandler.TimerType.FIXED_END); + final TimeoutHandler handler = new TimeoutHandler(System.currentTimeMillis() + 100L, FIXED_END); final MaxSAT.MaxSATResult solve = solver.solve(handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(solve).isEqualTo(MaxSAT.MaxSATResult.UNDEF); } } diff --git a/src/test/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandlerTest.java b/src/test/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandlerTest.java index fd687bfe..d7a0fd46 100644 --- a/src/test/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandlerTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/TimeoutModelEnumerationHandlerTest.java @@ -4,11 +4,13 @@ package com.booleworks.logicng.handlers; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.MODEL_ENUMERATION_STARTED; import static com.booleworks.logicng.solvers.sat.SolverTestSet.SATSolverConfigParam.CNF_METHOD; import static com.booleworks.logicng.solvers.sat.SolverTestSet.SATSolverConfigParam.USE_AT_MOST_CLAUSES; import static org.assertj.core.api.Assertions.assertThat; import com.booleworks.logicng.formulas.FormulaFactory; +import com.booleworks.logicng.handlers.events.EnumerationFoundModelsEvent; import com.booleworks.logicng.solvers.SATSolver; import com.booleworks.logicng.solvers.sat.SolverTestSet; import com.booleworks.logicng.testutils.PigeonHoleGenerator; @@ -36,11 +38,11 @@ public void init() { @Test public void testFoundModel() throws InterruptedException { - final var handler = new TimeoutModelEnumerationHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); - handler.started(); - assertThat(handler.foundModels(10)).isTrue(); + final var handler = new TimeoutHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); + handler.shouldResume(MODEL_ENUMERATION_STARTED); + assertThat(handler.shouldResume(new EnumerationFoundModelsEvent(10))).isTrue(); Thread.sleep(200); - assertThat(handler.foundModels(10)).isFalse(); + assertThat(handler.shouldResume(new EnumerationFoundModelsEvent(10))).isFalse(); } // TODO diff --git a/src/test/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandlerTest.java b/src/test/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandlerTest.java index bf219c5e..5e88ff3d 100644 --- a/src/test/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandlerTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/TimeoutOptimizationHandlerTest.java @@ -4,9 +4,15 @@ package com.booleworks.logicng.handlers; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.FIXED_END; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.SINGLE_TIMEOUT; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.MODEL_ENUMERATION_STARTED; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.OPTIMIZATION_FUNCTION_STARTED; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.SAT_CALL_STARTED; import static com.booleworks.logicng.solvers.sat.SolverTestSet.SATSolverConfigParam.CNF_METHOD; import static com.booleworks.logicng.solvers.sat.SolverTestSet.SATSolverConfigParam.USE_AT_MOST_CLAUSES; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -14,6 +20,7 @@ import com.booleworks.logicng.datastructures.Assignment; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; +import com.booleworks.logicng.handlers.events.OptimizationFoundBetterBoundEvent; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.DimacsReader; import com.booleworks.logicng.solvers.SATSolver; @@ -44,12 +51,12 @@ public void init() { @Test public void testTimeoutFoundBetterBound() throws InterruptedException { - final TimeoutOptimizationHandler handler = - new TimeoutOptimizationHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); - handler.started(); - assertThat(handler.foundBetterBound(Assignment::new)).isTrue(); + final TimeoutHandler handler = + new TimeoutHandler(100, SINGLE_TIMEOUT); + handler.shouldResume(MODEL_ENUMERATION_STARTED); + assertThat(handler.shouldResume(new OptimizationFoundBetterBoundEvent(Assignment::new))).isTrue(); Thread.sleep(200); - assertThat(handler.foundBetterBound(Assignment::new)).isFalse(); + assertThat(handler.shouldResume(new OptimizationFoundBetterBoundEvent(Assignment::new))).isFalse(); } @Test @@ -57,15 +64,15 @@ public void testThatMethodsAreCalled() throws ParserException { final Formula formula = f.parse("a & b & (~a => b)"); for (final SATSolver solver : solvers) { solver.add(formula); - final TimeoutOptimizationHandler handler = Mockito.mock(TimeoutOptimizationHandler.class); + final TimeoutHandler handler = Mockito.mock(TimeoutHandler.class); solver.execute(OptimizationFunction.builder() .handler(handler) .literals(formula.variables(f)) .maximize().build()); - verify(handler, times(1)).started(); - verify(handler, atLeast(1)).satHandler(); + verify(handler, times(1)).shouldResume(eq(OPTIMIZATION_FUNCTION_STARTED)); + verify(handler, atLeast(1)).shouldResume(eq(SAT_CALL_STARTED)); } } @@ -75,7 +82,7 @@ public void testTimeoutHandlerSingleTimeout() throws IOException { DimacsReader.readCNF(f, "src/test/resources/sat/too_large_gr_rcs_w5.shuffled.cnf"); for (final SATSolver solver : solvers) { solver.add(formulas); - final TimeoutOptimizationHandler handler = new TimeoutOptimizationHandler(100L); + final TimeoutHandler handler = new TimeoutHandler(100L); final Assignment result = solver.execute(OptimizationFunction.builder() .handler(handler) @@ -92,8 +99,8 @@ public void testTimeoutHandlerFixedEnd() throws IOException { DimacsReader.readCNF(f, "src/test/resources/sat/too_large_gr_rcs_w5.shuffled.cnf"); for (final SATSolver solver : solvers) { solver.add(formulas); - final TimeoutOptimizationHandler handler = - new TimeoutOptimizationHandler(100L, TimeoutHandler.TimerType.FIXED_END); + final TimeoutHandler handler = + new TimeoutHandler(100L, FIXED_END); final Assignment result = solver.execute(OptimizationFunction.builder() .handler(handler) diff --git a/src/test/java/com/booleworks/logicng/handlers/TimeoutSATHandlerTest.java b/src/test/java/com/booleworks/logicng/handlers/TimeoutSATHandlerTest.java index 2cd270bf..1a65d728 100644 --- a/src/test/java/com/booleworks/logicng/handlers/TimeoutSATHandlerTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/TimeoutSATHandlerTest.java @@ -4,9 +4,16 @@ package com.booleworks.logicng.handlers; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.FIXED_END; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.SINGLE_TIMEOUT; +import static com.booleworks.logicng.handlers.events.ComputationFinishedEvent.SAT_CALL_FINISHED; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.SAT_CALL_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.SAT_CONFLICT_DETECTED; import static com.booleworks.logicng.solvers.sat.SolverTestSet.SATSolverConfigParam.CNF_METHOD; import static com.booleworks.logicng.solvers.sat.SolverTestSet.SATSolverConfigParam.USE_AT_MOST_CLAUSES; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -44,24 +51,24 @@ public void init() { @Test public void testDetectedConflict() throws InterruptedException { - final TimeoutSATHandler handler = new TimeoutSATHandler(100, TimeoutHandler.TimerType.SINGLE_TIMEOUT); - handler.started(); - assertThat(handler.detectedConflict()).isTrue(); + final TimeoutHandler handler = new TimeoutHandler(100, SINGLE_TIMEOUT); + handler.shouldResume(SAT_CALL_STARTED); + assertThat(handler.shouldResume(SAT_CONFLICT_DETECTED)).isTrue(); Thread.sleep(200); - assertThat(handler.detectedConflict()).isFalse(); + assertThat(handler.shouldResume(SAT_CONFLICT_DETECTED)).isFalse(); } @Test public void testThatMethodsAreCalled() throws ParserException { for (final SATSolver solver : solvers) { solver.add(f.parse("(x => y) & (~x => y) & (y => z) & (z => ~y)")); - final TimeoutSATHandler handler = Mockito.mock(TimeoutSATHandler.class); + final TimeoutHandler handler = Mockito.mock(TimeoutHandler.class); solver.satCall().handler(handler).solve().close(); - verify(handler, times(1)).started(); - verify(handler, atLeast(1)).detectedConflict(); - verify(handler, times(1)).finishedSolving(); + verify(handler, times(1)).shouldResume(eq(SAT_CALL_STARTED)); + verify(handler, atLeast(1)).shouldResume(eq(SAT_CONFLICT_DETECTED)); + verify(handler, times(1)).shouldResume(eq(SAT_CALL_FINISHED)); } } @@ -69,17 +76,18 @@ public void testThatMethodsAreCalled() throws ParserException { public void testThatDetectedConflictIsHandledProperly() { for (final SATSolver solver : solvers) { solver.add(pg.generate(10)); - final TimeoutSATHandler handler = Mockito.mock(TimeoutSATHandler.class); + final TimeoutHandler handler = Mockito.mock(TimeoutHandler.class); final AtomicInteger count = new AtomicInteger(0); - when(handler.detectedConflict()).then(invocationOnMock -> count.addAndGet(1) < 5); + when(handler.shouldResume(any())).thenReturn(true); + when(handler.shouldResume(eq(SAT_CONFLICT_DETECTED))).thenAnswer(invocationOnMock -> count.addAndGet(1) < 5); final Tristate result = solver.satCall().handler(handler).sat(); assertThat(result).isEqualTo(Tristate.UNDEF); - verify(handler, times(1)).started(); - verify(handler, times(5)).detectedConflict(); - verify(handler, times(1)).finishedSolving(); + verify(handler, times(1)).shouldResume(eq(SAT_CALL_STARTED)); + verify(handler, times(5)).shouldResume(eq(SAT_CONFLICT_DETECTED)); + verify(handler, times(1)).shouldResume(eq(SAT_CALL_FINISHED)); } } @@ -87,7 +95,7 @@ public void testThatDetectedConflictIsHandledProperly() { public void testTimeoutHandlerSingleTimeout() { for (final SATSolver solver : solvers) { solver.add(pg.generate(10)); - final TimeoutSATHandler handler = new TimeoutSATHandler(100L); + final TimeoutHandler handler = new TimeoutHandler(100L); final Tristate result = solver.satCall().handler(handler).sat(); @@ -100,8 +108,8 @@ public void testTimeoutHandlerSingleTimeout() { public void testTimeoutHandlerFixedEnd() { for (final SATSolver solver : solvers) { solver.add(pg.generate(10)); - final TimeoutSATHandler handler = - new TimeoutSATHandler(System.currentTimeMillis() + 100L, TimeoutHandler.TimerType.FIXED_END); + final TimeoutHandler handler = + new TimeoutHandler(System.currentTimeMillis() + 100L, FIXED_END); final Tristate result = solver.satCall().handler(handler).sat(); diff --git a/src/test/java/com/booleworks/logicng/handlers/TimerTypeTest.java b/src/test/java/com/booleworks/logicng/handlers/TimerTypeTest.java index c6793e31..b72b42ec 100644 --- a/src/test/java/com/booleworks/logicng/handlers/TimerTypeTest.java +++ b/src/test/java/com/booleworks/logicng/handlers/TimerTypeTest.java @@ -6,109 +6,79 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; import org.junit.jupiter.api.Test; -import java.util.Arrays; -import java.util.List; -import java.util.function.Supplier; - public class TimerTypeTest { + public static final ComputationStartedEvent COMPUTATION_STARTED = new ComputationStartedEvent("dummy"); + @Test public void testSingleTimeout() throws InterruptedException { - for (final TimeoutHandler handler : mkHandlers(100L, TimeoutHandler.TimerType.SINGLE_TIMEOUT)) { - handler.started(); - assertThat(handler.timeLimitExceeded()).isFalse(); - Thread.sleep(200L); - assertThat(handler.timeLimitExceeded()).isTrue(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isTrue(); - } + final TimeoutHandler handler = handler(100L, TimeoutHandler.TimerType.SINGLE_TIMEOUT); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isFalse(); + Thread.sleep(200L); + assertThat(handler.isAborted()).isTrue(); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isTrue(); } @Test public void testRestartingTimeout() throws InterruptedException { - for (final TimeoutHandler handler : mkHandlers(100L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT)) { - handler.started(); - assertThat(handler.timeLimitExceeded()).isFalse(); - Thread.sleep(200L); - assertThat(handler.timeLimitExceeded()).isTrue(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isFalse(); - Thread.sleep(200L); - assertThat(handler.timeLimitExceeded()).isTrue(); - } + final TimeoutHandler handler = handler(100L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isFalse(); + Thread.sleep(200L); + assertThat(handler.isAborted()).isTrue(); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isFalse(); + Thread.sleep(200L); + assertThat(handler.isAborted()).isTrue(); } @Test public void testFixedEnd() throws InterruptedException { - for (final Supplier handlerSupplier : mkFixedEndHandlers(100L)) { - final TimeoutHandler handler = handlerSupplier.get(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isFalse(); - Thread.sleep(200L); - assertThat(handler.timeLimitExceeded()).isTrue(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isTrue(); - } + final TimeoutHandler handler = fixedEndHandler(100L); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isFalse(); + Thread.sleep(200L); + assertThat(handler.isAborted()).isTrue(); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isTrue(); } @Test public void testFixedEndWithDelayedStartedCall() throws InterruptedException { - for (final Supplier handlerSupplier : mkFixedEndHandlers(100L)) { - final TimeoutHandler handler = handlerSupplier.get(); - Thread.sleep(200L); - handler.started(); - assertThat(handler.timeLimitExceeded()).isTrue(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isTrue(); - } + final TimeoutHandler handler = fixedEndHandler(100L); + Thread.sleep(200L); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isTrue(); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isTrue(); } @Test public void testFixedEndWithZeroTime() { - for (final Supplier handlerSupplier : mkFixedEndHandlers(0L)) { - final TimeoutHandler handler = handlerSupplier.get(); - assertThat(handler.timeLimitExceeded()).isTrue(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isTrue(); - } + final TimeoutHandler handler = fixedEndHandler(0L); + assertThat(handler.isAborted()).isTrue(); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isTrue(); } @Test public void testFixedEndWithPastPointInTime() { - for (final Supplier handlerSupplier : mkFixedEndHandlers(-100L)) { - final TimeoutHandler handler = handlerSupplier.get(); - assertThat(handler.timeLimitExceeded()).isTrue(); - handler.started(); - assertThat(handler.timeLimitExceeded()).isTrue(); - } + final TimeoutHandler handler = fixedEndHandler(-100L); + assertThat(handler.isAborted()).isTrue(); + handler.shouldResume(COMPUTATION_STARTED); + assertThat(handler.isAborted()).isTrue(); } - private static List mkHandlers(final long timeout, final TimeoutHandler.TimerType type) { - return Arrays.asList( - new TimeoutBDDHandler(timeout, type), - new TimeoutMaxSATHandler(timeout, type), - new TimeoutModelEnumerationHandler(timeout, type), - new TimeoutOptimizationHandler(timeout, type), - new TimeoutSATHandler(timeout, type)); + private static TimeoutHandler handler(final long timeout, final TimeoutHandler.TimerType type) { + return new TimeoutHandler(timeout, type); } - /** - * Constructs fixed timeout handlers by using suppliers, since the creation - * of the fixed timeout handler affects the duration of the timeout. - * @param delta the delta in milliseconds added to the current point in time - * when the handler is created - * @return the fixed timeout handlers as suppliers - */ - private static List> mkFixedEndHandlers(final long delta) { - return Arrays.asList( - () -> new TimeoutBDDHandler(System.currentTimeMillis() + delta, TimeoutHandler.TimerType.FIXED_END), - () -> new TimeoutMaxSATHandler(System.currentTimeMillis() + delta, TimeoutHandler.TimerType.FIXED_END), - () -> new TimeoutModelEnumerationHandler(System.currentTimeMillis() + delta, - TimeoutHandler.TimerType.FIXED_END), - () -> new TimeoutOptimizationHandler(System.currentTimeMillis() + delta, - TimeoutHandler.TimerType.FIXED_END), - () -> new TimeoutSATHandler(System.currentTimeMillis() + delta, TimeoutHandler.TimerType.FIXED_END)); + private static TimeoutHandler fixedEndHandler(final long delta) { + return new TimeoutHandler(System.currentTimeMillis() + delta, TimeoutHandler.TimerType.FIXED_END); } } diff --git a/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDReorderingTest.java b/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDReorderingTest.java index 48e5d5d1..017e662c 100644 --- a/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDReorderingTest.java +++ b/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/BDDReorderingTest.java @@ -128,7 +128,7 @@ public void testRandomReorderingQuick() { @Test @LongRunningTag public void testRandomReorderingLongRunning() { - testRandomReordering(25, 50, true); + testRandomReordering(25, 50, false); } @Test @@ -139,7 +139,7 @@ public void testReorderOnBuildQuick() { @Test @LongRunningTag public void testReorderOnBuildLongRunning() { - testReorderOnBuild(25, 50, true); + testReorderOnBuild(25, 50, false); } private void testRandomReordering(final int minVars, final int maxVars, final boolean verbose) { @@ -280,28 +280,28 @@ private void verifyVariableBlocks(final FormulaFactory f, final Formula formula, if (withBlocks) { assertThat(findSequence(bdd, IntStream.range(0, 21).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); assertThat(findSequence(bdd, IntStream.range(0, 11).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); assertThat(findSequence(bdd, IntStream.range(11, 21).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); assertThat(findSequence(bdd, IntStream.range(15, 20).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); assertThat(findSequence(bdd, IntStream.range(15, 18).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); assertThat(findSequence(bdd, IntStream.range(18, 20).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); assertThat(findSequence(bdd, IntStream.range(21, formula.variables(f).size()) .mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))).isTrue(); if (formula.variables(f).size() > 33) { assertThat(findSequence(bdd, IntStream.range(30, 34).mapToObj(i -> String.format("v%02d", i)).collect(Collectors.toSet()))) - .isTrue(); + .isTrue(); } final List order = bdd.getVariableOrder(); assertThat(order.indexOf(f.variable("v00"))).isLessThan(order.indexOf(f.variable("v11"))); diff --git a/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/LargeBDDTest.java b/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/LargeBDDTest.java index cb38266b..d50e1b6e 100644 --- a/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/LargeBDDTest.java +++ b/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/LargeBDDTest.java @@ -10,7 +10,7 @@ import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.handlers.NumberOfNodesBDDHandler; -import com.booleworks.logicng.handlers.TimeoutBDDHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.knowledgecompilation.bdds.jbuddy.BDDKernel; import com.booleworks.logicng.testutils.NQueensGenerator; @@ -68,27 +68,27 @@ private void testQueens(final FormulaFactory f, final NQueensGenerator generator } @Test - public void testTimeoutBDDHandlerSmall() { + public void testTimeoutHandlerNgSmall() { final FormulaFactory f = FormulaFactory.caching(); final NQueensGenerator generator = new NQueensGenerator(f); final Formula queens = generator.generate(4); final BDDKernel kernel = new BDDKernel(f, queens.variables(f).size(), 10000, 10000); - final TimeoutBDDHandler handler = new TimeoutBDDHandler(2000L); + final TimeoutHandler handler = new TimeoutHandler(2000L); final BDD bdd = BDDFactory.build(f, queens, kernel, handler); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(bdd.index()).isNotEqualTo(BDDKernel.BDD_ABORT); } @Test @LongRunningTag - public void testTimeoutBDDHandlerLarge() { + public void testTimeoutHandlerNgLarge() { final FormulaFactory f = FormulaFactory.caching(); final NQueensGenerator generator = new NQueensGenerator(f); final Formula queens = generator.generate(10); final BDDKernel kernel = new BDDKernel(f, queens.variables(f).size(), 10000, 10000); - final TimeoutBDDHandler handler = new TimeoutBDDHandler(1000L); + final TimeoutHandler handler = new TimeoutHandler(1000L); final BDD bdd = BDDFactory.build(f, queens, kernel, handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(bdd.index()).isEqualTo(BDDKernel.BDD_ABORT); } @@ -100,7 +100,7 @@ public void testNumberOfNodesHandlerSmall() { final BDDKernel kernel = new BDDKernel(f, queens.variables(f).size(), 10000, 10000); final NumberOfNodesBDDHandler handler = new NumberOfNodesBDDHandler(1000); final BDD bdd = BDDFactory.build(f, queens, kernel, handler); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(bdd.index()).isNotEqualTo(BDDKernel.BDD_ABORT); } @@ -112,7 +112,7 @@ public void testNumberOfNodesHandlerLarge() { final BDDKernel kernel = new BDDKernel(f, queens.variables(f).size(), 10000, 10000); final NumberOfNodesBDDHandler handler = new NumberOfNodesBDDHandler(5); final BDD bdd = BDDFactory.build(f, queens, kernel, handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(bdd.index()).isEqualTo(BDDKernel.BDD_ABORT); } @@ -123,7 +123,7 @@ public void testNumberOfNodesHandler() throws ParserException { final BDDKernel kernel = new BDDKernel(f, formula.variables(f).size(), 10000, 10000); final NumberOfNodesBDDHandler handler = new NumberOfNodesBDDHandler(5); final BDD bdd = BDDFactory.build(f, formula, kernel, handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(bdd.index()).isEqualTo(BDDKernel.BDD_ABORT); } } diff --git a/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/SimpleBDDTest.java b/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/SimpleBDDTest.java index ba8d93c7..5f053301 100644 --- a/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/SimpleBDDTest.java +++ b/src/test/java/com/booleworks/logicng/knowledgecompilation/bdds/SimpleBDDTest.java @@ -11,6 +11,7 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.TestWithFormulaContext; import com.booleworks.logicng.formulas.Variable; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.parsers.PropositionalParser; import com.booleworks.logicng.knowledgecompilation.bdds.datastructures.BDDConstant; @@ -44,7 +45,7 @@ public void testTrue(final FormulaContext _c) { @MethodSource("contexts") public void testFalse(final FormulaContext _c) { final BDDKernel kernel = new BDDKernel(_c.f, 0, 100, 100); - final BDD bdd = BDDFactory.build(_c.f, _c.f.falsum(), kernel, null); + final BDD bdd = BDDFactory.build(_c.f, _c.f.falsum(), kernel, NopHandler.get()); assertThat(bdd.isTautology()).isFalse(); assertThat(bdd.isContradiction()).isTrue(); assertThat(bdd.cnf()).isEqualTo(_c.f.falsum()); @@ -157,7 +158,7 @@ public void testAnd(final FormulaContext _c) throws ParserException { final PropositionalParser parser = new PropositionalParser(f); final List ordering = Arrays.asList(f.variable("A"), f.variable("B"), f.variable("C")); final BDDKernel kernel = new BDDKernel(f, ordering, 1000, 1000); - final BDD bdd = BDDFactory.build(f, parser.parse("A & B & ~C"), kernel, null); + final BDD bdd = BDDFactory.build(f, parser.parse("A & B & ~C"), kernel, NopHandler.get()); assertThat(bdd.isTautology()).isFalse(); assertThat(bdd.isContradiction()).isFalse(); assertThat(bdd.cnf()).isEqualTo(parser.parse("A & (~A | B) & (~A | ~B | ~C)")); @@ -179,7 +180,7 @@ public void testFormula(final FormulaContext _c) throws ParserException { final PropositionalParser parser = new PropositionalParser(f); final List ordering = Arrays.asList(f.variable("A"), f.variable("B"), f.variable("C")); final BDDKernel kernel = new BDDKernel(f, ordering, 1000, 1000); - final BDD bdd = BDDFactory.build(f, parser.parse("(A => ~C) | (B & ~C)"), kernel, null); + final BDD bdd = BDDFactory.build(f, parser.parse("(A => ~C) | (B & ~C)"), kernel, NopHandler.get()); assertThat(bdd.isTautology()).isFalse(); assertThat(bdd.isContradiction()).isFalse(); assertThat(bdd.modelCount()).isEqualTo(BigInteger.valueOf(6)); @@ -187,7 +188,7 @@ public void testFormula(final FormulaContext _c) throws ParserException { assertThat(bdd.enumerateAllModels()).hasSize(6); assertThat(bdd.enumerateAllModels(f.variable("A"))).hasSize(2); assertThat(bdd.hashCode()) - .isEqualTo(BDDFactory.build(f, parser.parse("(A => ~C) | (B & ~C)"), kernel, null).hashCode()); + .isEqualTo(BDDFactory.build(f, parser.parse("(A => ~C) | (B & ~C)"), kernel, NopHandler.get()).hashCode()); assertThat(bdd.toString()).isEqualTo("BDD{8}"); } @@ -197,7 +198,7 @@ public void testCC(final FormulaContext _c) throws ParserException { final FormulaFactory f = FormulaFactory.caching(); final PropositionalParser parser = new PropositionalParser(f); final BDDKernel kernel = new BDDKernel(f, 3, 1000, 1000); - final BDD bdd = BDDFactory.build(f, parser.parse("A + B + C = 1"), kernel, null); + final BDD bdd = BDDFactory.build(f, parser.parse("A + B + C = 1"), kernel, NopHandler.get()); assertThat(bdd.isTautology()).isFalse(); assertThat(bdd.isContradiction()).isFalse(); assertThat(bdd.cnf()).isEqualTo(parser.parse("(A | B | C) & (A | ~B | ~C) & (~A | B | ~C) & (~A | ~B)")); diff --git a/src/test/java/com/booleworks/logicng/primecomputation/PrimeCompilerTest.java b/src/test/java/com/booleworks/logicng/primecomputation/PrimeCompilerTest.java index f4fec75d..f92082b9 100644 --- a/src/test/java/com/booleworks/logicng/primecomputation/PrimeCompilerTest.java +++ b/src/test/java/com/booleworks/logicng/primecomputation/PrimeCompilerTest.java @@ -4,6 +4,9 @@ package com.booleworks.logicng.primecomputation; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.FIXED_END; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.RESTARTING_TIMEOUT; +import static com.booleworks.logicng.handlers.TimeoutHandler.TimerType.SINGLE_TIMEOUT; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; @@ -15,9 +18,8 @@ import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.TestWithFormulaContext; import com.booleworks.logicng.handlers.BoundedOptimizationHandler; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.handlers.TimeoutHandler; -import com.booleworks.logicng.handlers.TimeoutOptimizationHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.FormulaReader; import com.booleworks.logicng.predicates.satisfiability.TautologyPredicate; @@ -119,14 +121,13 @@ public void testTimeoutHandlerSmall() throws ParserException { new Pair<>(PrimeCompiler.getWithMinimization(), PrimeResult.CoverageType.IMPLICANTS_COMPLETE), new Pair<>(PrimeCompiler.getWithMinimization(), PrimeResult.CoverageType.IMPLICATES_COMPLETE)); for (final Pair compiler : compilers) { - final List handlers = Arrays.asList( - new TimeoutOptimizationHandler(5_000L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), - new TimeoutOptimizationHandler(5_000L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), - new TimeoutOptimizationHandler(System.currentTimeMillis() + 5_000L, - TimeoutHandler.TimerType.FIXED_END) + final List handlers = Arrays.asList( + new TimeoutHandler(5_000L, SINGLE_TIMEOUT), + new TimeoutHandler(5_000L, RESTARTING_TIMEOUT), + new TimeoutHandler(System.currentTimeMillis() + 5_000L, FIXED_END) ); final Formula formula = FormulaFactory.caching().parse("a & b | ~c & a"); - for (final TimeoutOptimizationHandler handler : handlers) { + for (final TimeoutHandler handler : handlers) { testHandler(handler, formula, compiler.first(), compiler.second(), false); } } @@ -141,14 +142,14 @@ public void testTimeoutHandlerLarge() throws ParserException, IOException { new Pair<>(PrimeCompiler.getWithMinimization(), PrimeResult.CoverageType.IMPLICANTS_COMPLETE), new Pair<>(PrimeCompiler.getWithMinimization(), PrimeResult.CoverageType.IMPLICATES_COMPLETE)); for (final Pair compiler : compilers) { - final List handlers = Arrays.asList( - new TimeoutOptimizationHandler(1L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), - new TimeoutOptimizationHandler(1L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), - new TimeoutOptimizationHandler(System.currentTimeMillis() + 1L, TimeoutHandler.TimerType.FIXED_END) + final List handlers = Arrays.asList( + new TimeoutHandler(1L, SINGLE_TIMEOUT), + new TimeoutHandler(1L, RESTARTING_TIMEOUT), + new TimeoutHandler(System.currentTimeMillis() + 1L, FIXED_END) ); final Formula formula = FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/large_formula.txt"); - for (final TimeoutOptimizationHandler handler : handlers) { + for (final TimeoutHandler handler : handlers) { testHandler(handler, formula, compiler.first(), compiler.second(), true); } } @@ -167,7 +168,7 @@ public void testCancellationPoints() throws IOException, ParserException { for (final Pair compiler : compilers) { for (int numOptimizationStarts = 1; numOptimizationStarts < 5; numOptimizationStarts++) { for (int numSatHandlerStarts = 1; numSatHandlerStarts < 10; numSatHandlerStarts++) { - final OptimizationHandler handler = + final BoundedOptimizationHandler handler = new BoundedOptimizationHandler(numSatHandlerStarts, numOptimizationStarts); testHandler(handler, formula, compiler.first(), compiler.second(), true); } @@ -228,11 +229,11 @@ private void verifyImplicates(final List> implicateSets, fina .isTrue(); } - private void testHandler(final OptimizationHandler handler, final Formula formula, final PrimeCompiler compiler, + private void testHandler(final ComputationHandler handler, final Formula formula, final PrimeCompiler compiler, final PrimeResult.CoverageType coverageType, final boolean expAborted) { final PrimeResult result = compiler.compute(formula.factory(), formula, coverageType, handler); - assertThat(handler.aborted()).isEqualTo(expAborted); + assertThat(handler.isAborted()).isEqualTo(expAborted); if (expAborted) { assertThat(result).isNull(); } else { diff --git a/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicantReductionTest.java b/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicantReductionTest.java index 3e4b7298..81e3afc6 100644 --- a/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicantReductionTest.java +++ b/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicantReductionTest.java @@ -15,7 +15,8 @@ import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.TestWithFormulaContext; import com.booleworks.logicng.handlers.BoundedSatHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.FormulaReader; import com.booleworks.logicng.solvers.SATSolver; @@ -122,16 +123,16 @@ public void testCancellationPoints() throws ParserException, IOException { final Formula formula = FormulaReader.readPropositionalFormula(FormulaFactory.nonCaching(), "src/test/resources/formulas/large_formula.txt"); for (int numStarts = 0; numStarts < 20; numStarts++) { - final SATHandler handler = new BoundedSatHandler(numStarts); + final ComputationHandler handler = new BoundedSatHandler(numStarts); testFormula(formula, handler, true); } } private void testFormula(final Formula formula) { - testFormula(formula, null, false); + testFormula(formula, NopHandler.get(), false); } - private void testFormula(final Formula formula, final SATHandler handler, final boolean expAborted) { + private void testFormula(final Formula formula, final ComputationHandler handler, final boolean expAborted) { final FormulaFactory f = formula.factory(); final SATSolver solver = SATSolver.newSolver(f); solver.add(formula); @@ -144,7 +145,7 @@ private void testFormula(final Formula formula, final SATHandler handler, final final NaivePrimeReduction naive = new NaivePrimeReduction(f, formula); final SortedSet primeImplicant = naive.reduceImplicant(model, handler); if (expAborted) { - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(primeImplicant).isNull(); } else { assertThat(model).containsAll(primeImplicant); diff --git a/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicateReductionTest.java b/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicateReductionTest.java index d7056e6b..9d876a5f 100644 --- a/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicateReductionTest.java +++ b/src/test/java/com/booleworks/logicng/primecomputation/PrimeImplicateReductionTest.java @@ -14,7 +14,8 @@ import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.TestWithFormulaContext; import com.booleworks.logicng.handlers.BoundedSatHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.FormulaReader; import com.booleworks.logicng.solvers.SATSolver; @@ -112,16 +113,16 @@ public void testCancellationPoints() throws ParserException, IOException { final Formula formula = FormulaReader.readPropositionalFormula(FormulaFactory.nonCaching(), "src/test/resources/formulas/large_formula.txt"); for (int numStarts = 0; numStarts < 20; numStarts++) { - final SATHandler handler = new BoundedSatHandler(numStarts); + final ComputationHandler handler = new BoundedSatHandler(numStarts); testFormula(formula, handler, true); } } private void testFormula(final Formula formula) { - testFormula(formula, null, false); + testFormula(formula, NopHandler.get(), false); } - private void testFormula(final Formula formula, final SATHandler handler, final boolean expAborted) { + private void testFormula(final Formula formula, final ComputationHandler handler, final boolean expAborted) { final FormulaFactory f = formula.factory(); final SATSolver solver = SATSolver.newSolver(f); solver.add(formula.negate(f)); @@ -135,7 +136,7 @@ private void testFormula(final Formula formula, final SATHandler handler, final final NaivePrimeReduction naive = new NaivePrimeReduction(f, formula); final SortedSet primeImplicate = naive.reduceImplicate(f, falsifyingAssignment, handler); if (expAborted) { - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(primeImplicate).isNull(); } else { assertThat(falsifyingAssignment).containsAll(primeImplicate); diff --git a/src/test/java/com/booleworks/logicng/solvers/functions/ModelCountingFunctionTest.java b/src/test/java/com/booleworks/logicng/solvers/functions/ModelCountingFunctionTest.java index dcce3606..ab002630 100644 --- a/src/test/java/com/booleworks/logicng/solvers/functions/ModelCountingFunctionTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/functions/ModelCountingFunctionTest.java @@ -214,7 +214,7 @@ public void testHandlerWithNumModelsLimit(final SplitVariableProvider splitProvi solver.add(formula); final BigInteger numberOfModels = solver.execute(ModelCountingFunction.builder(formula.variables(f)).configuration(config).build()); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(numberOfModels).isEqualTo(3); } diff --git a/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunctionTest.java b/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunctionTest.java index f9a9cdd8..d7f287d8 100644 --- a/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunctionTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationFunctionTest.java @@ -373,7 +373,7 @@ public void testHandlerWithNumModelsLimit(final SplitVariableProvider splitProvi solver.add(f.parse("(~A | C) & (~B | C)")); final List models = solver .execute(ModelEnumerationFunction.builder(f.variables("A", "B", "C")).configuration(config).build()); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(models).hasSize(3); } diff --git a/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunctionTest.java b/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunctionTest.java index f8cf8007..f92d3082 100644 --- a/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunctionTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/functions/ModelEnumerationToBddFunctionTest.java @@ -236,7 +236,7 @@ public void testHandlerWithNumModelsLimit(final SplitVariableProvider splitProvi solver.add(f.parse("(~A | C) & (~B | C)")); final BDD bdd = solver.execute( ModelEnumerationToBddFunction.builder(f.variables("A", "B", "C")).configuration(config).build()); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(bdd.modelCount()).isEqualTo(3); } diff --git a/src/test/java/com/booleworks/logicng/solvers/functions/OptimizationFunctionTest.java b/src/test/java/com/booleworks/logicng/solvers/functions/OptimizationFunctionTest.java index dcff2e14..4ad2312b 100644 --- a/src/test/java/com/booleworks/logicng/solvers/functions/OptimizationFunctionTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/functions/OptimizationFunctionTest.java @@ -22,9 +22,11 @@ import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; import com.booleworks.logicng.handlers.BoundedOptimizationHandler; -import com.booleworks.logicng.handlers.OptimizationHandler; -import com.booleworks.logicng.handlers.SATHandler; -import com.booleworks.logicng.handlers.TimeoutOptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.NopHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; +import com.booleworks.logicng.handlers.events.LogicNGEvent; +import com.booleworks.logicng.handlers.events.OptimizationFoundBetterBoundEvent; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.parsers.PropositionalParser; import com.booleworks.logicng.io.readers.DimacsReader; @@ -78,10 +80,10 @@ public void testUnsatFormula(final Supplier solver, final FormulaFact throws ParserException { final Formula formula = f.parse("a & b & (a => ~b)"); final Assignment minimumModel = optimize(Collections.singleton(formula), formula.variables(f), - Collections.emptyList(), false, solver.get(), null); + Collections.emptyList(), false, solver.get(), NopHandler.get()); assertThat(minimumModel).isNull(); final Assignment maximumModel = optimize(Collections.singleton(formula), formula.variables(f), - Collections.emptyList(), true, solver.get(), null); + Collections.emptyList(), true, solver.get(), NopHandler.get()); assertThat(maximumModel).isNull(); } @@ -92,10 +94,10 @@ public void testSingleModel(final Supplier solver, final FormulaFacto throws ParserException { final Formula formula = f.parse("~a & ~b & ~c"); final Assignment minimumModel = optimize(Collections.singleton(formula), formula.variables(f), - Collections.emptyList(), false, solver.get(), null); + Collections.emptyList(), false, solver.get(), NopHandler.get()); testMinimumModel(formula, minimumModel, formula.variables(f)); final Assignment maximumModel = optimize(Collections.singleton(formula), formula.variables(f), - Collections.emptyList(), true, solver.get(), null); + Collections.emptyList(), true, solver.get(), NopHandler.get()); testMaximumModel(formula, maximumModel, formula.variables(f)); } @@ -105,10 +107,10 @@ public void testExoModel(final Supplier solver, final FormulaFactory final CardinalityConstraint exo = (CardinalityConstraint) f.exo(f.variable("a"), f.variable("b"), f.variable("c")); final Assignment minimumModel = optimize(Collections.singleton(exo), exo.variables(f), Collections.emptyList(), - false, solver.get(), null); + false, solver.get(), NopHandler.get()); testMinimumModel(exo, minimumModel, exo.variables(f)); final Assignment maximumModel = optimize(Collections.singleton(exo), exo.variables(f), Collections.emptyList(), - true, solver.get(), null); + true, solver.get(), NopHandler.get()); testMaximumModel(exo, maximumModel, exo.variables(f)); } @@ -121,11 +123,11 @@ public void testCornerCases(final Supplier solver, final FormulaFacto final Set targetLiterals = cornerCases.getVariables(); final Assignment minimumModel = optimize(Collections.singleton(formula), targetLiterals, - Collections.emptySet(), false, solver.get(), null); + Collections.emptySet(), false, solver.get(), NopHandler.get()); testMinimumModel(formula, minimumModel, targetLiterals); final Assignment maximumModel = optimize(Collections.singleton(formula), targetLiterals, - Collections.emptySet(), true, solver.get(), null); + Collections.emptySet(), true, solver.get(), NopHandler.get()); testMaximumModel(formula, maximumModel, targetLiterals); } } @@ -136,12 +138,8 @@ public void testCornerCases(final Supplier solver, final FormulaFacto public void testRandomSmall(final Supplier solver, final FormulaFactory f0, final String solverDescription) { final FormulaFactory f = FormulaFactory.nonCaching(FormulaFactoryConfig.builder() - .formulaMergeStrategy(FormulaFactoryConfig.FormulaMergeStrategy.IMPORT).build()); // caching - // factory - // goes - // out - // of - // heap + // caching factory goes out of heap + .formulaMergeStrategy(FormulaFactoryConfig.FormulaMergeStrategy.IMPORT).build()); final Random random = new Random(42); final FormulaRandomizer randomizer = new FormulaRandomizer(f, FormulaRandomizerConfig.builder().numVars(6).weightPbc(2).seed(42).build()); @@ -154,11 +152,11 @@ public void testRandomSmall(final Supplier solver, final FormulaFacto final Set additionalVariables = randomSubset(random, variables, Math.min(variables.size(), 3)); final Assignment minimumModel = optimize(Collections.singleton(formula), targetLiterals, - additionalVariables, false, solver.get(), null); + additionalVariables, false, solver.get(), NopHandler.get()); testMinimumModel(formula, minimumModel, targetLiterals); final Assignment maximumModel = optimize(Collections.singleton(formula), targetLiterals, - additionalVariables, true, solver.get(), null); + additionalVariables, true, solver.get(), NopHandler.get()); testMaximumModel(formula, maximumModel, targetLiterals); } } @@ -250,24 +248,24 @@ public void testAdditionalVariables(final Supplier solver, final Form final List literalsANBX = Arrays.asList(a, nb, x); final Assignment minimumModel = optimize(Collections.singleton(formula), literalsANBX, Collections.emptyList(), - false, solver.get(), null); + false, solver.get(), NopHandler.get()); Assertions.assertThat(minimumModel.literals()).containsExactlyInAnyOrder(na, b, nx); final Assignment minimumModelWithY = optimize(Collections.singleton(formula), literalsANBX, - Collections.singleton(y), false, solver.get(), null); + Collections.singleton(y), false, solver.get(), NopHandler.get()); Assertions.assertThat(minimumModelWithY.literals()).containsExactlyInAnyOrder(na, b, nx, y); final Assignment minimumModelWithCY = - optimize(Collections.singleton(formula), literalsANBX, Arrays.asList(c, y), false, solver.get(), null); + optimize(Collections.singleton(formula), literalsANBX, Arrays.asList(c, y), false, solver.get(), NopHandler.get()); Assertions.assertThat(minimumModelWithCY.literals()).containsExactlyInAnyOrder(na, b, c, nx, y); final List literalsNBNX = Arrays.asList(na, nx); final Assignment maximumModel = optimize(Collections.singleton(formula), literalsNBNX, Collections.emptyList(), - true, solver.get(), null); + true, solver.get(), NopHandler.get()); Assertions.assertThat(maximumModel.literals()).containsExactlyInAnyOrder(na, nx); final Assignment maximumModelWithC = optimize(Collections.singleton(formula), literalsNBNX, - Collections.singleton(c), true, solver.get(), null); + Collections.singleton(c), true, solver.get(), NopHandler.get()); Assertions.assertThat(maximumModelWithC.literals()).containsExactlyInAnyOrder(na, c, nx); final Assignment maximumModelWithACY = optimize(Collections.singleton(formula), literalsNBNX, - Arrays.asList(a, c, y), true, solver.get(), null); + Arrays.asList(a, c, y), true, solver.get(), NopHandler.get()); Assertions.assertThat(maximumModelWithACY.literals()).containsExactlyInAnyOrder(na, c, nx, y); } @@ -281,7 +279,7 @@ public void testLargeFormulaMinimize(final Supplier solver, final For FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/large_formula.txt"); final List variables = randomSubset(formula.variables(f), 300); final Assignment minimumModel = - optimize(Collections.singleton(formula), variables, Collections.emptyList(), false, solver.get(), null); + optimize(Collections.singleton(formula), variables, Collections.emptyList(), false, solver.get(), NopHandler.get()); testMinimumModel(formula, minimumModel, variables); } @@ -294,7 +292,7 @@ public void testLargeFormulaMaximize(final Supplier solver, final For final Formula formula = FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/large_formula.txt"); final Assignment maximumModel = optimize(Collections.singleton(formula), formula.variables(f), - Collections.emptyList(), true, solver.get(), null); + Collections.emptyList(), true, solver.get(), NopHandler.get()); testMaximumModel(formula, maximumModel, formula.variables(f)); } @@ -307,7 +305,7 @@ public void testLargerFormulaMinimize(final Supplier solver, final Fo final Formula formula = FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/small_formulas.txt"); final Assignment minimumModel = optimize(Collections.singleton(formula), formula.variables(f), - Collections.emptyList(), false, solver.get(), null); + Collections.emptyList(), false, solver.get(), NopHandler.get()); testMinimumModel(formula, minimumModel, formula.variables(f)); } @@ -321,7 +319,7 @@ public void testLargerFormulaMaximize(final Supplier solver, final Fo FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/small_formulas.txt"); final List variables = randomSubset(formula.variables(f), 300); final Assignment maximumModel = - optimize(Collections.singleton(formula), variables, Collections.emptyList(), true, solver.get(), null); + optimize(Collections.singleton(formula), variables, Collections.emptyList(), true, solver.get(), NopHandler.get()); testMaximumModel(formula, maximumModel, variables); } @@ -346,11 +344,11 @@ public void compareWithMaxSat() throws IOException, ParserException { assertThat(solveMaxSat(formulas, variables, MaxSATSolver.wbo(f))).isEqualTo(expected); assertThat(satisfiedLiterals( optimize(formulas, variables, Collections.emptyList(), false, - SATSolver.newSolver(f, SATSolverConfig.builder().useAtMostClauses(false).build()), null), + SATSolver.newSolver(f, SATSolverConfig.builder().useAtMostClauses(false).build()), NopHandler.get()), variables).size()).isEqualTo(expected); assertThat(satisfiedLiterals( optimize(formulas, variables, Collections.emptyList(), false, - SATSolver.newSolver(f, SATSolverConfig.builder().useAtMostClauses(true).build()), null), + SATSolver.newSolver(f, SATSolverConfig.builder().useAtMostClauses(true).build()), NopHandler.get()), variables).size()).isEqualTo(expected); } @@ -362,31 +360,22 @@ public void testTimeoutOptimizationHandler(final Supplier solver, fin throws IOException, ParserException { final Formula formula = FormulaReader.readPropositionalFormula(f, "src/test/resources/formulas/large_formula.txt"); - final TimeoutOptimizationHandler handlerMax = new TimeoutOptimizationHandler(1L); + final TimeoutHandler handlerMax = new TimeoutHandler(1L); final Assignment maximumModel = optimize(Collections.singleton(formula), formula.variables(f), Collections.emptyList(), true, solver.get(), handlerMax); assertThat(maximumModel).isNull(); - assertThat(handlerMax.aborted()).isTrue(); + assertThat(handlerMax.isAborted()).isTrue(); - final TimeoutOptimizationHandler handlerTooShort = new TimeoutOptimizationHandler(0L); + final TimeoutHandler handlerTooShort = new TimeoutHandler(0L); final Assignment model = optimize(Collections.singleton(formula), formula.variables(f), Collections.emptyList(), false, solver.get(), handlerTooShort); assertThat(model).isNull(); - assertThat(handlerTooShort.aborted()).isTrue(); - Assertions.assertThat(handlerTooShort.getIntermediateResult()).isNull(); // SATHandler - // aborted - // before - // a - // model - // could - // be - // computed - + assertThat(handlerTooShort.isAborted()).isTrue(); final CustomOptimizationHandler customHandler = new CustomOptimizationHandler(); final Assignment modelCustom = optimize(Collections.singleton(formula), formula.variables(f), Collections.emptyList(), true, solver.get(), customHandler); assertThat(modelCustom).isNull(); - assertThat(customHandler.aborted()).isTrue(); + assertThat(customHandler.isAborted()).isTrue(); assertThat(customHandler.currentResult).isNotNull(); } @@ -408,7 +397,7 @@ public void testCancellationPoints(final Supplier solverSupplier, fin final SATSolver solver = solverSupplier.get(); for (int numSatHandlerStarts = 1; numSatHandlerStarts < 4; numSatHandlerStarts++) { solver.add(formulas); - final OptimizationHandler handler = new BoundedOptimizationHandler(numSatHandlerStarts, -1); + final ComputationHandler handler = new BoundedOptimizationHandler(numSatHandlerStarts, -1); final OptimizationFunction optimizationFunction = OptimizationFunction.builder() .handler(handler) .literals(selVars) @@ -416,7 +405,7 @@ public void testCancellationPoints(final Supplier solverSupplier, fin final Assignment result = solver.execute(optimizationFunction); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isNull(); } } @@ -437,8 +426,7 @@ private SortedSet satisfiedLiterals(final Assignment assignment, private static Assignment optimize(final Collection formulas, final Collection literals, final Collection additionalVariables, final boolean maximize, - final SATSolver solver, - final OptimizationHandler handler) { + final SATSolver solver, final ComputationHandler handler) { formulas.forEach(solver::add); if (maximize) { return solver.execute(OptimizationFunction.builder().maximize().literals(literals) @@ -487,24 +475,21 @@ private static List randomSubset(final Collection original, return variables.subList(0, size); } - private static class CustomOptimizationHandler implements OptimizationHandler { + private static class CustomOptimizationHandler implements ComputationHandler { public Assignment currentResult; private boolean aborted; @Override - public SATHandler satHandler() { - return null; - } - - @Override - public boolean aborted() { + public boolean isAborted() { return aborted; } @Override - public boolean foundBetterBound(final Supplier currentResultProvider) { - currentResult = currentResultProvider.get(); - aborted = currentResult.positiveVariables().size() >= 161; + public boolean shouldResume(final LogicNGEvent event) { + if (event instanceof OptimizationFoundBetterBoundEvent) { + currentResult = ((OptimizationFoundBetterBoundEvent) event).getModel().get(); + aborted = currentResult.positiveVariables().size() >= 161; + } return !aborted; } } diff --git a/src/test/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollectorTestHandler.java b/src/test/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollectorTestHandler.java index 39019a45..c82b979d 100644 --- a/src/test/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollectorTestHandler.java +++ b/src/test/java/com/booleworks/logicng/solvers/functions/modelenumeration/EnumerationCollectorTestHandler.java @@ -4,42 +4,35 @@ package com.booleworks.logicng.solvers.functions.modelenumeration; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; -import com.booleworks.logicng.handlers.SATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; +import com.booleworks.logicng.handlers.events.EnumerationFoundModelsEvent; +import com.booleworks.logicng.handlers.events.SimpleEvent; -public final class EnumerationCollectorTestHandler implements ModelEnumerationHandler { +public final class EnumerationCollectorTestHandler implements ComputationHandler { private int foundModels; private int commitCalls; private int rollbackCalls; @Override - public void started() { - ModelEnumerationHandler.super.started(); - foundModels = 0; - } - - @Override - public SATHandler satHandler() { - return null; - } - - @Override - public boolean foundModels(final int numberOfModels) { - foundModels += numberOfModels; + public boolean shouldResume(final LogicNGEvent event) { + if (event == ComputationStartedEvent.MODEL_ENUMERATION_STARTED) { + foundModels = 0; + } else if (event instanceof EnumerationFoundModelsEvent) { + foundModels += ((EnumerationFoundModelsEvent) event).getNumberOfModels(); + } else if (event == SimpleEvent.MODEL_ENUMERATION_COMMIT) { + ++commitCalls; + } else if (event == SimpleEvent.MODEL_ENUMERATION_ROLLBACK) { + ++rollbackCalls; + } return true; } @Override - public boolean commit() { - ++commitCalls; - return true; - } - - @Override - public boolean rollback() { - ++rollbackCalls; - return true; + public boolean isAborted() { + return false; } public int getFoundModels() { diff --git a/src/test/java/com/booleworks/logicng/solvers/maxsat/MaxSatLongRunningTest.java b/src/test/java/com/booleworks/logicng/solvers/maxsat/MaxSatLongRunningTest.java index ce66ba85..79ddf906 100644 --- a/src/test/java/com/booleworks/logicng/solvers/maxsat/MaxSatLongRunningTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/maxsat/MaxSatLongRunningTest.java @@ -35,7 +35,7 @@ public void testWeightedMaxSat() throws IOException { MaxSATSolver.incWBO(f, MaxSATConfig.builder().weight(MaxSATConfig.WeightStrategy.DIVERSIFY).build()); solvers[2] = MaxSATSolver.incWBO(f); for (final MaxSATSolver solver : solvers) { - final long start = System.currentTimeMillis(); +// final long start = System.currentTimeMillis(); for (final File file : Objects.requireNonNull(folder.listFiles())) { if (file.getName().endsWith("wcnf")) { solver.reset(); @@ -44,8 +44,8 @@ public void testWeightedMaxSat() throws IOException { assertThat(solver.result()).isEqualTo(result.get(file.getName())); } } - final long stop = System.currentTimeMillis(); - System.out.printf("%-8s: %.2f sec%n", solver.getAlgorithm(), (stop - start) / 1000.0); +// final long stop = System.currentTimeMillis(); +// System.out.printf("%-8s: %.2f sec%n", solver.getAlgorithm(), (stop - start) / 1000.0); } } diff --git a/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialMaxSATTest.java b/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialMaxSATTest.java index c3736111..8d517c46 100644 --- a/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialMaxSATTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialMaxSATTest.java @@ -11,7 +11,12 @@ import com.booleworks.logicng.LongRunningTag; import com.booleworks.logicng.TestWithExampleFormulas; import com.booleworks.logicng.formulas.Formula; -import com.booleworks.logicng.handlers.TimeoutMaxSATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; +import com.booleworks.logicng.handlers.events.ComputationStartedEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; +import com.booleworks.logicng.handlers.events.MaxSatNewLowerBoundEvent; +import com.booleworks.logicng.handlers.events.MaxSatNewUpperBoundEvent; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.solvers.MaxSATSolver; import com.booleworks.logicng.solvers.maxsat.algorithms.MaxSAT; @@ -249,21 +254,22 @@ public void testTimeoutHandlerMSU3() { } private void testTimeoutHandler(final MaxSATSolver solver) { - final TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(1000L); + final TimeoutHandler handler = new TimeoutHandler(1000L); final PigeonHoleGenerator pg = new PigeonHoleGenerator(f); final Formula formula = pg.generate(10); solver.addHardFormula(formula); solver.addSoftFormula(f.or(formula.variables(f)), 1); MaxSAT.MaxSATResult result = solver.solve(handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.UNDEF); + final TimeoutHandler handler2 = new TimeoutHandler(1000L); solver.reset(); solver.addHardFormula(IMP1); solver.addSoftFormula(AND1, 1); - result = solver.solve(handler); - assertThat(handler.aborted()).isFalse(); + result = solver.solve(handler2); + assertThat(handler2.isAborted()).isFalse(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.OPTIMUM); } @@ -272,18 +278,18 @@ public void testTimeoutHandlerSimple() throws IOException { MaxSATSolver solver = MaxSATSolver.wbo(f, MaxSATConfig.builder().verbosity(MaxSATConfig.Verbosity.SOME).output(logStream).build()); readCnfToSolver(solver, "src/test/resources/partialmaxsat/c1355_F176gat-1278gat@1.wcnf"); - TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(1000L); + MaxSatTimeoutHandlerWithApproximation handler = new MaxSatTimeoutHandlerWithApproximation(1000L); MaxSAT.MaxSATResult result = solver.solve(handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.UNDEF); - assertThat(handler.lowerBoundApproximation()).isLessThan(13); + assertThat(handler.lowerBoundApproximation).isLessThan(13); solver = MaxSATSolver.wbo(f, MaxSATConfig.builder().verbosity(MaxSATConfig.Verbosity.SOME).output(logStream).build()); readCnfToSolver(solver, "src/test/resources/partialmaxsat/c1355_F1229gat@1.wcnf"); - handler = new TimeoutMaxSATHandler(5000L); + handler = new MaxSatTimeoutHandlerWithApproximation(5000L); result = solver.solve(handler); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.OPTIMUM); } @@ -292,11 +298,11 @@ public void testTimeoutHandlerUB() throws IOException { final MaxSATSolver solver = MaxSATSolver.linearSU(f, MaxSATConfig.builder().verbosity(MaxSATConfig.Verbosity.SOME).output(logStream).build()); readCnfToSolver(solver, "src/test/resources/partialmaxsat/c1355_F1229gat@1.wcnf"); - final TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(5000L); + final MaxSatTimeoutHandlerWithApproximation handler = new MaxSatTimeoutHandlerWithApproximation(5000L); final MaxSAT.MaxSATResult result = solver.solve(handler); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.OPTIMUM); - assertThat(solver.result()).isEqualTo(handler.upperBoundApproximation()); + assertThat(solver.result()).isEqualTo(handler.upperBoundApproximation); } @Test @@ -348,4 +354,37 @@ public void testSoftConstraintsCornerCaseFalsum() throws ParserException { assertThat(solver.result()).isEqualTo(2); } } + + static class MaxSatTimeoutHandlerWithApproximation implements ComputationHandler { + boolean aborted = false; + long timeout; + long designatedEnd; + int lowerBoundApproximation; + int upperBoundApproximation; + + MaxSatTimeoutHandlerWithApproximation(final long timeout) { + this.timeout = timeout; + designatedEnd = 0; + } + + @Override + public boolean shouldResume(final LogicNGEvent event) { + if (event instanceof ComputationStartedEvent) { + if (designatedEnd == 0) { + designatedEnd = System.currentTimeMillis() + timeout; + } + } else if (event instanceof MaxSatNewLowerBoundEvent) { + lowerBoundApproximation = ((MaxSatNewLowerBoundEvent) event).getBound(); + } else if (event instanceof MaxSatNewUpperBoundEvent) { + upperBoundApproximation = ((MaxSatNewUpperBoundEvent) event).getBound(); + } + aborted = System.currentTimeMillis() >= designatedEnd; + return !aborted; + } + + @Override + public boolean isAborted() { + return aborted; + } + } } diff --git a/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialWeightedMaxSATTest.java b/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialWeightedMaxSATTest.java index df040e6b..d4b16dcf 100644 --- a/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialWeightedMaxSATTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/maxsat/PartialWeightedMaxSATTest.java @@ -11,7 +11,7 @@ import com.booleworks.logicng.LongRunningTag; import com.booleworks.logicng.TestWithExampleFormulas; import com.booleworks.logicng.formulas.Formula; -import com.booleworks.logicng.handlers.TimeoutMaxSATHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.solvers.MaxSATSolver; import com.booleworks.logicng.solvers.maxsat.algorithms.MaxSAT; @@ -378,21 +378,21 @@ public void testWeightedSoftConstraintsCornerCaseFalsum() throws ParserException } private void testTimeoutHandler(final MaxSATSolver solver) { - final TimeoutMaxSATHandler handler = new TimeoutMaxSATHandler(1000L); - + final TimeoutHandler handler = new TimeoutHandler(1000L); final PigeonHoleGenerator pg = new PigeonHoleGenerator(f); final Formula formula = pg.generate(10); solver.addHardFormula(formula); solver.addSoftFormula(f.or(formula.variables(f)), 10); MaxSAT.MaxSATResult result = solver.solve(handler); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.UNDEF); + final TimeoutHandler handler2 = new TimeoutHandler(1000L); solver.reset(); solver.addHardFormula(IMP1); solver.addSoftFormula(AND1, 10); - result = solver.solve(handler); - assertThat(handler.aborted()).isFalse(); + result = solver.solve(handler2); + assertThat(handler2.isAborted()).isFalse(); assertThat(result).isEqualTo(MaxSAT.MaxSATResult.OPTIMUM); } } diff --git a/src/test/java/com/booleworks/logicng/solvers/sat/LNGCoreSolverTest.java b/src/test/java/com/booleworks/logicng/solvers/sat/LNGCoreSolverTest.java index 0b7886da..868e316f 100644 --- a/src/test/java/com/booleworks/logicng/solvers/sat/LNGCoreSolverTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/sat/LNGCoreSolverTest.java @@ -9,6 +9,7 @@ import com.booleworks.logicng.collections.LNGIntVector; import com.booleworks.logicng.datastructures.Tristate; import com.booleworks.logicng.formulas.FormulaFactory; +import com.booleworks.logicng.handlers.NopHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.solvers.SATSolver; import org.assertj.core.api.Assertions; @@ -30,7 +31,7 @@ public void testAnalyzeAssumptionConflict() { solver.addClause(clause(-1, -3), null); solver.addClause(clause(-2, -3), null); Assertions.assertThat(solver.internalSolve()).isEqualTo(Tristate.TRUE); - Assertions.assertThat(solver.internalSolve(null, clause(1, 2))).isEqualTo(Tristate.FALSE); + Assertions.assertThat(solver.internalSolve(NopHandler.get(), clause(1, 2))).isEqualTo(Tristate.FALSE); } @Test diff --git a/src/test/java/com/booleworks/logicng/solvers/sat/SATCallTest.java b/src/test/java/com/booleworks/logicng/solvers/sat/SATCallTest.java index 16b4e060..d1cd7816 100644 --- a/src/test/java/com/booleworks/logicng/solvers/sat/SATCallTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/sat/SATCallTest.java @@ -8,8 +8,10 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.Variable; import com.booleworks.logicng.formulas.implementation.cached.CachingFormulaFactory; -import com.booleworks.logicng.handlers.SATHandler; -import com.booleworks.logicng.handlers.TimeoutSATHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; +import com.booleworks.logicng.handlers.events.LogicNGEvent; +import com.booleworks.logicng.handlers.events.SimpleEvent; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.FormulaReader; import com.booleworks.logicng.propositions.StandardProposition; @@ -31,7 +33,7 @@ public void testIllegalOperationsOnOpenSatCall() throws ParserException { final SATSolver solver = SATSolver.newSolver(f, SATSolverConfig.builder().proofGeneration(true).build()); final SATCall openCall = solver.satCall().solve(); - final SATCallBuilder newCallBuilder = solver.satCall().handler(new TimeoutSATHandler(1000)) + final SATCallBuilder newCallBuilder = solver.satCall().handler(new TimeoutHandler(1000)) .addFormulas(f.variable("a")).selectionOrder(List.of(f.variable("a"))); assertThat(newCallBuilder).isNotNull(); @@ -140,7 +142,7 @@ public void testHandler() throws IOException, ParserException { assertThat(solver.satCall().handler(new MaxConflictsHandler(0)).sat()).isEqualTo(Tristate.UNDEF); assertThat( solver.satCall().handler(new MaxConflictsHandler(0)).model(solver.underlyingSolver().knownVariables())) - .isNull(); + .isNull(); assertThat(solver.satCall().handler(new MaxConflictsHandler(0)).unsatCore()).isNull(); try (final SATCall satCall = solver.satCall().handler(new MaxConflictsHandler(100)).solve()) { @@ -167,10 +169,10 @@ public void testSelectionOrder() throws ParserException { .isEqualTo(new Assignment(a.negate(f), b, c.negate(f), d)); assertThat(solver.satCall().selectionOrder(List.of(a.negate(f), b.negate(f), c.negate(f), d.negate(f))) .model(List.of(a, b, c, d))) - .isEqualTo(new Assignment(a.negate(f), b.negate(f), c.negate(f), d)); + .isEqualTo(new Assignment(a.negate(f), b.negate(f), c.negate(f), d)); assertThat(solver.satCall().selectionOrder(List.of(a.negate(f), b.negate(f), d.negate(f), c.negate(f))) .model(List.of(a, b, c, d))) - .isEqualTo(new Assignment(a.negate(f), b.negate(f), c, d.negate(f))); + .isEqualTo(new Assignment(a.negate(f), b.negate(f), c, d.negate(f))); } @Test @@ -185,13 +187,13 @@ public void testAdditionalFormulasAndPropositions() throws ParserException { assertThat( solver.satCall().addFormulas(f.parse("e <=> ~f")).addFormulas(f.parse("~f")).unsatCore().propositions()) - .containsExactlyInAnyOrder( - new StandardProposition(f.parse("a | b | c | d")), - new StandardProposition(f.parse("e => ~a & ~b")), - new StandardProposition(f.parse("~f => ~c & ~d")), - new StandardProposition(f.parse("e <=> ~f")), - new StandardProposition(f.parse("~f")) - ); + .containsExactlyInAnyOrder( + new StandardProposition(f.parse("a | b | c | d")), + new StandardProposition(f.parse("e => ~a & ~b")), + new StandardProposition(f.parse("~f => ~c & ~d")), + new StandardProposition(f.parse("e <=> ~f")), + new StandardProposition(f.parse("~f")) + ); assertThat(solver.satCall().addFormulas(f.parse("e <=> ~f"), f.parse("e")).unsatCore().propositions()) .containsExactlyInAnyOrder( @@ -205,38 +207,38 @@ public void testAdditionalFormulasAndPropositions() throws ParserException { assertThat(solver.satCall() .addPropositions(new StandardProposition(f.parse("e <=> ~f")), new StandardProposition(f.parse("e"))) .unsatCore().propositions()) - .containsExactlyInAnyOrder( - new StandardProposition(f.parse("a | b | c | d")), - new StandardProposition(f.parse("e => ~a & ~b")), - new StandardProposition(f.parse("~f => ~c & ~d")), - new StandardProposition(f.parse("e <=> ~f")), - new StandardProposition(f.parse("e")) - ); + .containsExactlyInAnyOrder( + new StandardProposition(f.parse("a | b | c | d")), + new StandardProposition(f.parse("e => ~a & ~b")), + new StandardProposition(f.parse("~f => ~c & ~d")), + new StandardProposition(f.parse("e <=> ~f")), + new StandardProposition(f.parse("e")) + ); assertThat( solver.satCall().addFormulas(f.parse("e <=> f")).addPropositions(new StandardProposition(f.parse("~e"))) .model(solver.underlyingSolver().knownVariables())).isIn( - new Assignment(f.literal("a", true), f.literal("b", true), f.literal("c", false), - f.literal("d", false), f.literal("e", false), f.literal("f", false)), - new Assignment(f.literal("a", false), f.literal("b", true), f.literal("c", false), - f.literal("d", false), f.literal("e", false), f.literal("f", false)), - new Assignment(f.literal("a", true), f.literal("b", false), f.literal("c", false), - f.literal("d", false), f.literal("e", false), f.literal("f", false)) - ); + new Assignment(f.literal("a", true), f.literal("b", true), f.literal("c", false), + f.literal("d", false), f.literal("e", false), f.literal("f", false)), + new Assignment(f.literal("a", false), f.literal("b", true), f.literal("c", false), + f.literal("d", false), f.literal("e", false), f.literal("f", false)), + new Assignment(f.literal("a", true), f.literal("b", false), f.literal("c", false), + f.literal("d", false), f.literal("e", false), f.literal("f", false)) + ); assertThat(solver.satCall().addPropositions(new StandardProposition(f.parse("e <=> f"))) .addPropositions(new StandardProposition(f.parse("~e"))) .model(solver.underlyingSolver().knownVariables())).isIn( - new Assignment(f.literal("a", true), f.literal("b", true), f.literal("c", false), - f.literal("d", false), f.literal("e", false), f.literal("f", false)), - new Assignment(f.literal("a", false), f.literal("b", true), f.literal("c", false), - f.literal("d", false), f.literal("e", false), f.literal("f", false)), - new Assignment(f.literal("a", true), f.literal("b", false), f.literal("c", false), - f.literal("d", false), f.literal("e", false), f.literal("f", false)) - ); + new Assignment(f.literal("a", true), f.literal("b", true), f.literal("c", false), + f.literal("d", false), f.literal("e", false), f.literal("f", false)), + new Assignment(f.literal("a", false), f.literal("b", true), f.literal("c", false), + f.literal("d", false), f.literal("e", false), f.literal("f", false)), + new Assignment(f.literal("a", true), f.literal("b", false), f.literal("c", false), + f.literal("d", false), f.literal("e", false), f.literal("f", false)) + ); } - private static class MaxConflictsHandler implements SATHandler { + private static class MaxConflictsHandler implements ComputationHandler { private final int maxConflicts; private int numConflicts; private boolean aborted; @@ -247,14 +249,16 @@ public MaxConflictsHandler(final int maxConflicts) { } @Override - public boolean aborted() { - return aborted; + public boolean shouldResume(final LogicNGEvent event) { + if (event == SimpleEvent.SAT_CONFLICT_DETECTED) { + aborted = numConflicts++ > maxConflicts; + } + return !aborted; } @Override - public boolean detectedConflict() { - aborted = numConflicts++ > maxConflicts; - return !aborted; + public boolean isAborted() { + return aborted; } } } diff --git a/src/test/java/com/booleworks/logicng/solvers/sat/SATTest.java b/src/test/java/com/booleworks/logicng/solvers/sat/SATTest.java index 82aa379b..d74203c8 100644 --- a/src/test/java/com/booleworks/logicng/solvers/sat/SATTest.java +++ b/src/test/java/com/booleworks/logicng/solvers/sat/SATTest.java @@ -27,10 +27,9 @@ import com.booleworks.logicng.formulas.FormulaFactoryConfig; import com.booleworks.logicng.formulas.Literal; import com.booleworks.logicng.formulas.Variable; -import com.booleworks.logicng.handlers.ModelEnumerationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.handlers.NumberOfModelsHandler; -import com.booleworks.logicng.handlers.TimeoutModelEnumerationHandler; -import com.booleworks.logicng.handlers.TimeoutSATHandler; +import com.booleworks.logicng.handlers.TimeoutHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.parsers.PropositionalParser; import com.booleworks.logicng.propositions.StandardProposition; @@ -255,8 +254,8 @@ public void testVariableRemovedBySimplificationOccursInModel() throws ParserExce final Variable b = f.variable("B"); final Formula formula = f.parse("A & B => A"); solver.add(formula); // during NNF conversion, used by the PG - // transformation, the formula simplifies to verum - // when added to the solver + // transformation, the formula simplifies to verum + // when added to the solver assertThat(solver.sat()).isTrue(); assertThat(solver.underlyingSolver().knownVariables()).isEmpty(); assertThat(variables(f, solver.satCall().model(List.of(a, b)).literals())).containsExactlyInAnyOrder(a, b); @@ -385,9 +384,9 @@ public void testDifferentClauseMinimizations() { public void testTimeoutSATHandlerSmall() { for (final SATSolver s : solvers) { s.add(IMP1); - final TimeoutSATHandler handler = new TimeoutSATHandler(1000L); + final TimeoutHandler handler = new TimeoutHandler(1000L); final Tristate result = s.satCall().handler(handler).sat(); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(result).isEqualTo(Tristate.TRUE); } } @@ -397,9 +396,9 @@ public void testTimeoutSATHandlerSmall() { public void testTimeoutSATHandlerLarge() { for (final SATSolver s : solvers) { s.add(pg.generate(10)); - final TimeoutSATHandler handler = new TimeoutSATHandler(1000L); + final TimeoutHandler handler = new TimeoutHandler(1000L); final Tristate result = s.satCall().handler(handler).sat(); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(result).isEqualTo(Tristate.UNDEF); } } @@ -464,11 +463,11 @@ public void testTimeoutModelEnumerationHandlerWithUNSATInstance() { for (final SATSolver solver : solvers) { final Formula formula = pg.generate(10); solver.add(formula); - final var handler = new TimeoutModelEnumerationHandler(1000L); + final var handler = new TimeoutHandler(1000L); final var me = meWithHandler(handler, formula.variables(f)); final List assignments = solver.execute(me); assertThat(assignments).isEmpty(); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); } } @@ -482,10 +481,10 @@ public void testTimeoutModelEnumerationHandlerWithSATInstance1() { } solver.add(f.exo(variables)); - final var handler = new TimeoutModelEnumerationHandler(50L); + final var handler = new TimeoutHandler(50L); final var me = meWithHandler(handler, variables); solver.execute(me); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); } } @@ -498,11 +497,11 @@ public void testTimeoutModelEnumerationHandlerWithSATInstance2() { } solver.add(f.exo(variables.subList(0, 5))); - final var handler = new TimeoutModelEnumerationHandler(50L); + final var handler = new TimeoutHandler(50L); final var me = meWithHandler(handler, variables.subList(0, 5)); final List assignments = solver.execute(me); assertThat(assignments).hasSize(5); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); } } @@ -556,7 +555,7 @@ public void testModelEnumerationWithHandler01() { ModelEnumerationConfig.builder().strategy(defaultMeStrategy).handler(handler).build()) .build(); final List modelsWithHandler = s.execute(me); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(modelsWithHandler.size()).isEqualTo(29); for (final Model model : modelsWithHandler) { for (final Variable lit : lits) { @@ -588,7 +587,7 @@ public void testModelEnumerationWithHandler02() { ModelEnumerationConfig.builder().strategy(defaultMeStrategy).handler(handler).build()) .build(); final List modelsWithHandler = s.execute(me); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(modelsWithHandler.size()).isEqualTo(29); for (final Model model : modelsWithHandler) { for (final Variable lit : lits) { @@ -625,7 +624,7 @@ public void testNumberOfModelHandler() { .build(); List models = s.execute(me); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(models.size()).isEqualTo(100); for (final Model m : models) { assertThat(m.positiveVariables().size()).isEqualTo(1); @@ -639,7 +638,7 @@ public void testNumberOfModelHandler() { ModelEnumerationConfig.builder().strategy(defaultMeStrategy).handler(handler).build()) .build(); models = s.execute(me); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(models.size()).isEqualTo(100); for (final Model m : models) { assertThat(m.positiveVariables().size()).isEqualTo(1); @@ -653,7 +652,7 @@ public void testNumberOfModelHandler() { ModelEnumerationConfig.builder().strategy(defaultMeStrategy).handler(handler).build()) .build(); models = s.execute(me); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(models.size()).isEqualTo(50); for (final Model m : models) { assertThat(m.positiveVariables().size()).isEqualTo(1); @@ -667,7 +666,7 @@ public void testNumberOfModelHandler() { ModelEnumerationConfig.builder().strategy(defaultMeStrategy).handler(handler).build()) .build(); models = s.execute(me); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(models.size()).isEqualTo(1); for (final Model m : models) { assertThat(m.positiveVariables().size()).isEqualTo(1); @@ -835,7 +834,7 @@ public void testFormulaOnSolverWithContradiction2() throws ParserException { .containsExactlyInAnyOrder(f.parse("A | ~B"), f.parse("~A | B"), f.parse("~B | ~A"), f.parse("B | A")); solver.sat(); // adds learnt clauses s.t. the formula on the solver - // changes + // changes assertThat(solver.execute(FormulaOnSolverFunction.get())) .containsExactlyInAnyOrder(f.parse("A | ~B"), f.parse("~A | B"), f.parse("~B | ~A"), f.parse("B | A"), @@ -1032,7 +1031,7 @@ private void testHighestLexicographicalAssignment(final SATSolver solver, final } } - static ModelEnumerationFunction meWithHandler(final ModelEnumerationHandler handler, + static ModelEnumerationFunction meWithHandler(final ComputationHandler handler, final Collection variables) { return ModelEnumerationFunction.builder(variables) .configuration(ModelEnumerationConfig.builder() diff --git a/src/test/java/com/booleworks/logicng/transformations/cnf/CNFTest.java b/src/test/java/com/booleworks/logicng/transformations/cnf/CNFTest.java index 9fb591f3..b4841356 100644 --- a/src/test/java/com/booleworks/logicng/transformations/cnf/CNFTest.java +++ b/src/test/java/com/booleworks/logicng/transformations/cnf/CNFTest.java @@ -4,12 +4,16 @@ package com.booleworks.logicng.transformations.cnf; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.FACTORIZATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.DISTRIBUTION_PERFORMED; import static org.assertj.core.api.Assertions.assertThat; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaContext; import com.booleworks.logicng.formulas.TestWithFormulaContext; -import com.booleworks.logicng.handlers.FactorizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.FactorizationCreatedClauseEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; import com.booleworks.logicng.io.parsers.ParserException; import org.assertj.core.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; @@ -19,7 +23,7 @@ public class CNFTest extends TestWithFormulaContext { - private final FactorizationHandler handler = new TestFactorizationHandler(); + private final ComputationHandler handler = new TestFactorizationHandler(); @ParameterizedTest @MethodSource("contexts") @@ -124,49 +128,44 @@ public void testCC(final FormulaContext _c) throws ParserException { @MethodSource("contexts") public void testWithHandler(final FormulaContext _c) throws ParserException { Formula formula = _c.p.parse("(~(~(a | b) => ~(x | y))) & ((a | x) => ~(b | y))"); - final FactorizationHandler handler = new FactorizationHandler() { + final ComputationHandler handler = new ComputationHandler() { private boolean aborted; private int dists = 0; private int clauses = 0; @Override - public boolean aborted() { + public boolean isAborted() { return aborted; } @Override - public void started() { - aborted = false; - dists = 0; - clauses = 0; - } - - @Override - public boolean performedDistribution() { - dists++; - aborted = dists >= 100; - return !aborted; - } - - @Override - public boolean createdClause(final Formula clause) { - clauses++; - aborted = clauses >= 2; + public boolean shouldResume(final LogicNGEvent event) { + if (event == FACTORIZATION_STARTED) { + aborted = false; + dists = 0; + clauses = 0; + } else if (event == DISTRIBUTION_PERFORMED) { + dists++; + aborted = dists >= 100; + } else if (event instanceof FactorizationCreatedClauseEvent) { + clauses++; + aborted = clauses >= 2; + } return !aborted; } }; final CNFFactorization factorization = new CNFFactorization(_c.f, handler, null); Formula cnf = factorization.apply(formula); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(cnf).isNull(); formula = _c.p.parse("~(a | b)"); cnf = factorization.apply(formula); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(cnf).isNotNull(); } - private static class TestFactorizationHandler implements FactorizationHandler { + private static class TestFactorizationHandler implements ComputationHandler { private boolean aborted; private int distCount = 0; @@ -174,28 +173,24 @@ private static class TestFactorizationHandler implements FactorizationHandler { private long longestClause = 0; @Override - public boolean aborted() { + public boolean isAborted() { return aborted; } @Override - public void started() { - aborted = false; - distCount = 0; - clauseCount = 0; - longestClause = 0; - } - - @Override - public boolean performedDistribution() { - distCount++; - return true; - } - - @Override - public boolean createdClause(final Formula clause) { - clauseCount++; - longestClause = Math.max(clause.numberOfAtoms(clause.factory()), longestClause); + public boolean shouldResume(final LogicNGEvent event) { + if (event == FACTORIZATION_STARTED) { + aborted = false; + distCount = 0; + clauseCount = 0; + longestClause = 0; + } else if (event == DISTRIBUTION_PERFORMED) { + distCount++; + } else if (event instanceof FactorizationCreatedClauseEvent) { + final Formula clause = ((FactorizationCreatedClauseEvent) event).getClause(); + clauseCount++; + longestClause = Math.max(clause.numberOfAtoms(clause.factory()), longestClause); + } return true; } } diff --git a/src/test/java/com/booleworks/logicng/transformations/cnf/CnfMethodComparisonTest.java b/src/test/java/com/booleworks/logicng/transformations/cnf/CnfMethodComparisonTest.java index ce98b00b..ae032d07 100644 --- a/src/test/java/com/booleworks/logicng/transformations/cnf/CnfMethodComparisonTest.java +++ b/src/test/java/com/booleworks/logicng/transformations/cnf/CnfMethodComparisonTest.java @@ -110,7 +110,7 @@ private void compareBackbonePerVariable(final String fileName) throws IOExceptio private Map computeBackbonePerVariable(final String fileName, final CNFConfig cnfConfig, final SATSolverConfig.CNFMethod cnfMethod) throws IOException, ParserException { - final long start = System.currentTimeMillis(); +// final long start = System.currentTimeMillis(); final FormulaFactory f = FormulaFactory.caching(); f.putConfiguration(cnfConfig); final Formula formula = FormulaReader.readPropositionalFormula(f, fileName); @@ -129,9 +129,9 @@ private Map computeBackbonePerVariable(final String fileName solver.loadState(solverState); } } - final long stop = System.currentTimeMillis(); - System.out.println(fileName + " " + cnfConfig.algorithm + " " + cnfConfig.fallbackAlgorithmForAdvancedEncoding + - " " + cnfMethod + ": " + (stop - start) + " ms."); +// final long stop = System.currentTimeMillis(); +// System.out.println(fileName + " " + cnfConfig.algorithm + " " + cnfConfig.fallbackAlgorithmForAdvancedEncoding + +// " " + cnfMethod + ": " + (stop - start) + " ms."); return result; } diff --git a/src/test/java/com/booleworks/logicng/transformations/dnf/DNFFactorizationTest.java b/src/test/java/com/booleworks/logicng/transformations/dnf/DNFFactorizationTest.java index d8b7161d..8a8b1543 100644 --- a/src/test/java/com/booleworks/logicng/transformations/dnf/DNFFactorizationTest.java +++ b/src/test/java/com/booleworks/logicng/transformations/dnf/DNFFactorizationTest.java @@ -4,12 +4,16 @@ package com.booleworks.logicng.transformations.dnf; +import static com.booleworks.logicng.handlers.events.ComputationStartedEvent.FACTORIZATION_STARTED; +import static com.booleworks.logicng.handlers.events.SimpleEvent.DISTRIBUTION_PERFORMED; import static org.assertj.core.api.Assertions.assertThat; import com.booleworks.logicng.formulas.Formula; import com.booleworks.logicng.formulas.FormulaContext; import com.booleworks.logicng.formulas.TestWithFormulaContext; -import com.booleworks.logicng.handlers.FactorizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; +import com.booleworks.logicng.handlers.events.FactorizationCreatedClauseEvent; +import com.booleworks.logicng.handlers.events.LogicNGEvent; import com.booleworks.logicng.io.parsers.ParserException; import org.assertj.core.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; @@ -113,45 +117,40 @@ public void testCDNF(final FormulaContext _c) throws ParserException { @MethodSource("contexts") public void testWithHandler(final FormulaContext _c) throws ParserException { Formula formula = _c.p.parse("(~(~(a | b) => ~(x | y))) & ((a | x) => ~(b | y))"); - final FactorizationHandler handler = new FactorizationHandler() { + final ComputationHandler handler = new ComputationHandler() { private boolean aborted; private int dists = 0; private int clauses = 0; @Override - public boolean aborted() { + public boolean isAborted() { return aborted; } @Override - public void started() { - aborted = false; - dists = 0; - clauses = 0; - } - - @Override - public boolean performedDistribution() { - dists++; - aborted = dists >= 100; - return !aborted; - } - - @Override - public boolean createdClause(final Formula clause) { - clauses++; - aborted = clauses >= 5; + public boolean shouldResume(final LogicNGEvent event) { + if (event == FACTORIZATION_STARTED) { + aborted = false; + dists = 0; + clauses = 0; + } else if (event == DISTRIBUTION_PERFORMED) { + dists++; + aborted = dists >= 100; + } else if (event instanceof FactorizationCreatedClauseEvent) { + clauses++; + aborted = clauses >= 5; + } return !aborted; } }; final DNFFactorization factorization = new DNFFactorization(_c.f, handler, null); Formula dnf = factorization.apply(formula); - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(dnf).isNull(); formula = _c.p.parse("~(a | b)"); dnf = factorization.apply(formula); - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(dnf).isNotNull(); } } diff --git a/src/test/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifierTest.java b/src/test/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifierTest.java index 14b12760..7dfb4139 100644 --- a/src/test/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifierTest.java +++ b/src/test/java/com/booleworks/logicng/transformations/simplification/AdvancedSimplifierTest.java @@ -13,9 +13,8 @@ import com.booleworks.logicng.formulas.FormulaFactory; import com.booleworks.logicng.formulas.TestWithFormulaContext; import com.booleworks.logicng.handlers.BoundedOptimizationHandler; -import com.booleworks.logicng.handlers.OptimizationHandler; +import com.booleworks.logicng.handlers.ComputationHandler; import com.booleworks.logicng.handlers.TimeoutHandler; -import com.booleworks.logicng.handlers.TimeoutOptimizationHandler; import com.booleworks.logicng.io.parsers.ParserException; import com.booleworks.logicng.io.readers.FormulaReader; import com.booleworks.logicng.predicates.satisfiability.TautologyPredicate; @@ -63,13 +62,13 @@ public void testRandomized(final FormulaContext _c) { @ParameterizedTest @MethodSource("contexts") public void testTimeoutHandlerSmall(final FormulaContext _c) throws ParserException { - final List handlers = Arrays.asList( - new TimeoutOptimizationHandler(5_000L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), - new TimeoutOptimizationHandler(5_000L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), - new TimeoutOptimizationHandler(System.currentTimeMillis() + 5_000L, TimeoutHandler.TimerType.FIXED_END) + final List handlers = Arrays.asList( + new TimeoutHandler(5_000L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), + new TimeoutHandler(5_000L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), + new TimeoutHandler(System.currentTimeMillis() + 5_000L, TimeoutHandler.TimerType.FIXED_END) ); final Formula formula = _c.f.parse("a & b | ~c & a"); - for (final TimeoutOptimizationHandler handler : handlers) { + for (final TimeoutHandler handler : handlers) { testHandler(handler, formula, false); } } @@ -77,14 +76,14 @@ public void testTimeoutHandlerSmall(final FormulaContext _c) throws ParserExcept @ParameterizedTest @MethodSource("contexts") public void testTimeoutHandlerLarge(final FormulaContext _c) throws ParserException, IOException { - final List handlers = Arrays.asList( - new TimeoutOptimizationHandler(1L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), - new TimeoutOptimizationHandler(1L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), - new TimeoutOptimizationHandler(System.currentTimeMillis() + 1L, TimeoutHandler.TimerType.FIXED_END) + final List handlers = Arrays.asList( + new TimeoutHandler(1L, TimeoutHandler.TimerType.SINGLE_TIMEOUT), + new TimeoutHandler(1L, TimeoutHandler.TimerType.RESTARTING_TIMEOUT), + new TimeoutHandler(System.currentTimeMillis() + 1L, TimeoutHandler.TimerType.FIXED_END) ); final Formula formula = FormulaReader.readPropositionalFormula(_c.f, "src/test/resources/formulas/large_formula.txt"); - for (final TimeoutOptimizationHandler handler : handlers) { + for (final TimeoutHandler handler : handlers) { testHandler(handler, formula, true); } } @@ -92,15 +91,15 @@ public void testTimeoutHandlerLarge(final FormulaContext _c) throws ParserExcept @ParameterizedTest @MethodSource("contexts") public void testPrimeCompilerIsCancelled(final FormulaContext _c) throws ParserException { - final OptimizationHandler handler = new BoundedOptimizationHandler(-1, 0); + final ComputationHandler handler = new BoundedOptimizationHandler(-1, 0); final Formula formula = _c.f.parse("a&(b|c)"); testHandler(handler, formula, true); } @ParameterizedTest @MethodSource("contexts") - public void testSmusComputationIsCancelled(final FormulaContext _c) throws ParserException { - final OptimizationHandler handler = new BoundedOptimizationHandler(-1, 5); + public void testzSmusComputationIsCancelled(final FormulaContext _c) throws ParserException { + final ComputationHandler handler = new BoundedOptimizationHandler(-1, 5); final Formula formula = _c.f.parse("a&(b|c)"); testHandler(handler, formula, true); } @@ -144,7 +143,7 @@ public void testCancellationPoints() throws ParserException { "& (~v20 | ~v8) & (v9 | ~v20) & (~v21 | ~v8) & (v9 | ~v21) & (~v21 | ~v10) & (~v21 | ~v11) & v19"); for (int numOptimizationStarts = 1; numOptimizationStarts < 30; numOptimizationStarts++) { for (int numSatHandlerStarts = 1; numSatHandlerStarts < 500; numSatHandlerStarts++) { - final OptimizationHandler handler = + final ComputationHandler handler = new BoundedOptimizationHandler(numSatHandlerStarts, numOptimizationStarts); testHandler(handler, formula, true); } @@ -158,16 +157,16 @@ private void computeAndVerify(final Formula formula) { .isTrue(); } - private void testHandler(final OptimizationHandler handler, final Formula formula, final boolean expAborted) { + private void testHandler(final ComputationHandler handler, final Formula formula, final boolean expAborted) { final AdvancedSimplifier simplifierWithHandler = new AdvancedSimplifier(formula.factory(), AdvancedSimplifierConfig.builder().build(), handler); final Formula simplified = formula.transform(simplifierWithHandler); - assertThat(handler.aborted()).isEqualTo(expAborted); + assertThat(handler.isAborted()).isEqualTo(expAborted); if (expAborted) { - assertThat(handler.aborted()).isTrue(); + assertThat(handler.isAborted()).isTrue(); assertThat(simplified).isNull(); } else { - assertThat(handler.aborted()).isFalse(); + assertThat(handler.isAborted()).isFalse(); assertThat(simplified).isNotNull(); } }