From c87f5c8bee740fbe2e9192866ab79e25b5a8c4c2 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Mon, 18 Jul 2022 15:50:14 +0200 Subject: [PATCH 01/53] Add naive solver and grounder restart --- .../kr/alpha/core/common/AtomStore.java | 5 ++ .../kr/alpha/core/common/AtomStoreImpl.java | 13 ++++ .../alpha/core/grounder/ChoiceRecorder.java | 6 ++ .../kr/alpha/core/grounder/Grounder.java | 5 ++ .../kr/alpha/core/grounder/NaiveGrounder.java | 17 +++++- .../alpha/core/grounder/NogoodRegistry.java | 7 +++ .../kr/alpha/core/grounder/WorkingMemory.java | 24 ++++++-- .../structure/AnalyzeUnjustified.java | 5 ++ .../transformation/StratifiedEvaluation.java | 4 +- .../kr/alpha/core/solver/AtomizedChoice.java | 27 ++++++++ .../kr/alpha/core/solver/ChoiceManager.java | 29 ++++++--- .../kr/alpha/core/solver/DefaultSolver.java | 61 ++++++++++++++++--- .../alpha/core/solver/NaiveNoGoodStore.java | 5 ++ .../kr/alpha/core/solver/NoGoodStore.java | 7 ++- .../core/solver/NoGoodStoreAlphaRoaming.java | 5 ++ .../alpha/core/grounder/ChoiceGrounder.java | 7 +++ .../kr/alpha/core/grounder/DummyGrounder.java | 7 +++ 17 files changed, 209 insertions(+), 25 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java index e55c6fcfb..f14e5dba4 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java @@ -116,4 +116,9 @@ default String noGoodToString(T noGood) { } AtomCounter getAtomCounter(); + + /** + * Clears all data within the atom store and resets it to its initial empty state. + */ + void reset(); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java index 4f9cf9a55..ec047a03a 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java @@ -129,4 +129,17 @@ public int get(Atom atom) { public AtomCounter getAtomCounter() { return atomCounter; } + + @Override + public void reset() { + atomIdsToInternalBasicAtoms.clear(); + atomIdsToInternalBasicAtoms.add(null); + + predicateInstancesToAtomIds.clear(); + + atomIdGenerator.resetGenerator(); + atomIdGenerator.getNextId(); + + releasedAtomIds.clear(); + } } \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java index 19b012b41..b1da72d43 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java @@ -115,6 +115,12 @@ public void addHeadToBody(int headId, int bodyId) { existingBodies.add(bodyId); } + public void reset() { + ID_GENERATOR.resetGenerator(); + newChoiceAtoms = new ImmutablePair<>(new LinkedHashMap<>(), new LinkedHashMap<>()); + newHeadsToBodies = new LinkedHashMap<>(); + } + @Override public String toString() { StringBuilder sb = new StringBuilder("[enablers: "); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java index 2c697f955..ff3d96415 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java @@ -80,4 +80,9 @@ public interface Grounder { * @return */ int register(NoGood noGood); + + /** + * Restarts the grounder. + */ + void restart(Assignment currentAssignment); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index 1e498d50d..23b295406 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -139,6 +139,7 @@ private NaiveGrounder(CompiledProgram program, AtomStore atomStore, GrounderHeur this.debugInternalChecks = debugInternalChecks; + // Initialize RuleInstantiator and instantiation strategy. Note that the instantiation strategy also // needs the current assignment, which is set with every call of getGroundInstantiations. this.instantiationStrategy = new DefaultLazyGroundingInstantiationStrategy(this.workingMemory, this.atomStore, this.factsFromProgram, @@ -364,7 +365,7 @@ public Map getNoGoods(Assignment currentAssignment) { modifiedWorkingMemory.markRecentlyAddedInstancesDone(); } - workingMemory.reset(); + workingMemory.resetModified(); for (Atom removeAtom : removeAfterObtainingNewNoGoods) { final IndexedInstanceStorage storage = workingMemory.get(removeAtom, true); Instance instance = new Instance(removeAtom.getTerms()); @@ -412,6 +413,20 @@ public int register(NoGood noGood) { return registry.register(noGood); } + @Override + public void restart(Assignment currentAssignment) { + workingMemory.reset(); + registry.reset(); + choiceRecorder.reset(); + analyzeUnjustified.reset(); + rulesUsingPredicateWorkingMemory.clear(); + removeAfterObtainingNewNoGoods = new LinkedHashSet<>(); + instantiationStrategy.setStaleWorkingMemoryEntries(removeAfterObtainingNewNoGoods); + instantiationStrategy.setCurrentAssignment(currentAssignment); + fixedRules = new ArrayList<>(); + initializeFactsAndRules(); + } + // Ideally, this method should be private. It's only visible because NaiveGrounderTest needs to access it. BindingResult getGroundInstantiations(CompiledRule rule, RuleGroundingOrder groundingOrder, Substitution partialSubstitution, Assignment currentAssignment) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java index 970ab86e6..c6b164675 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java @@ -11,6 +11,13 @@ public class NogoodRegistry { private Map registeredIdentifiers = new LinkedHashMap<>(); + /** + * Clears all registered identifiers. + */ + public void reset() { + registeredIdentifiers = new LinkedHashMap<>(); + } + /** * Helper methods to analyze average nogood length. * @return diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java index 549feddf0..9bd9eb068 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java @@ -27,10 +27,7 @@ */ package at.ac.tuwien.kr.alpha.core.grounder; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.*; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -104,11 +101,28 @@ public void addInstances(Predicate predicate, boolean value, Iterable } } - public void reset() { + /** + * Resets the modified working memory entries. + */ + public void resetModified() { modifiedWorkingMemories = new LinkedHashSet<>(); } + /** + * Returns all recently modified working memory entries. + * @return the set of working memory entries that were modified since the last call + * to {@link WorkingMemory#resetModified}. + */ public Set modified() { return modifiedWorkingMemories; } + + /** + * Resets the modified working memory entries using {@link WorkingMemory#resetModified} and + * clears the whole working memory. + */ + public void reset() { + resetModified(); + workingMemory = new LinkedHashMap<>(); + } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java index cb12167db..a8cfb4af9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java @@ -80,6 +80,11 @@ public Set analyze(int atomToJustify, Assignment currentAssignment) { return analyze((BasicAtom) atom, currentAssignment); } + public void reset() { + renamingCounter = 0; + padDepth = 0; + } + private Set analyze(BasicAtom atom, Assignment currentAssignment) { log(pad("Starting analyze, current assignment is: {}"), currentAssignment); LinkedHashSet vL = new LinkedHashSet<>(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java index 9dfc543e2..659877bfb 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java @@ -80,7 +80,7 @@ public InternalProgram apply(AnalyzedProgram inputProgram) { } } - workingMemory.reset(); + workingMemory.resetModified(); // Set up literal instantiator. literalInstantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(workingMemory)); @@ -150,7 +150,7 @@ private void evaluateComponent(ComponentGraph.SCComponent comp) { } private void evaluateRules(Set rules, boolean isInitialRun) { - workingMemory.reset(); + workingMemory.resetModified(); LOGGER.debug("Starting component evaluation run..."); for (CompiledRule r : rules) { evaluateRule(r, !isInitialRun); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java new file mode 100644 index 000000000..f77ac0f64 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java @@ -0,0 +1,27 @@ +package at.ac.tuwien.kr.alpha.core.solver; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; + +public class AtomizedChoice { + private final Atom atom; + private final boolean truthValue; + private final boolean backtracked; + + public AtomizedChoice(Atom atom, boolean truthValue, boolean backtracked) { + this.atom = atom; + this.truthValue = truthValue; + this.backtracked = backtracked; + } + + public Atom getAtom() { + return atom; + } + + public boolean getTruthValue() { + return truthValue; + } + + public boolean isBacktracked() { + return backtracked; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java index 8d8edcbb3..bd3695346 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java @@ -30,14 +30,8 @@ import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; -import java.util.Stack; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; @@ -262,6 +256,27 @@ public BinaryNoGoodPropagationEstimation getBinaryNoGoodPropagationEstimation() return bnpEstimation; } + /** + * Returns the current choice stack as a list of choices containing atom ids. + * @return a list of the choices on the current choice stack ordered from oldest to newest. + */ + public List getChoiceList() { + return new ArrayList<>(choiceStack); + } + + /** + * Clear the current assignment and choice stack. Then enforce the given choice stack as the current assignment and + * choice stack. + * @param newChoiceStack the new choice stack to use. + */ + public void setChoiceStack(Stack newChoiceStack) { + assignment.clear(); + choiceStack.clear(); + for (Choice choice : newChoiceStack) { + choose(choice); + } + } + /** * A helper class for halting the debugger when certain assignments occur on the choice stack. * diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index b6d952e23..cb18a30b1 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -35,15 +35,8 @@ import static at.ac.tuwien.kr.alpha.core.solver.heuristics.BranchingHeuristic.DEFAULT_CHOICE_LITERAL; import static at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult.UNSAT; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Random; -import java.util.Set; import java.util.function.Consumer; import org.slf4j.Logger; @@ -526,7 +519,57 @@ private boolean choose() { choiceManager.choose(new Choice(literal, false)); return true; } - + + /** + * Performs a restart of the solving process while preserving the current assignment - and thus the progress made. + * Nogood store and grounder are reset. Then the {@link AtomStore} is emptied and the current assignment + * is reconstructed. + */ + private void restart() { + LOGGER.debug("Performing solver and grounder restart."); + Stack atomizedChoiceStack = getAtomizedChoiceStack(); + + store.reset(); + grounder.restart(assignment); + atomStore.reset(); + + setAtomizedChoiceStack(atomizedChoiceStack); + getNoGoodsFromGrounderAndIngest(); + + LOGGER.debug("Solver and grounder restart finished."); + System.out.println("Solver and grounder restart performed."); + } + + /** + * Extract the current choice stack with atom ids replaced by the respective atoms. + * @return the choice stack containing atoms instead of atom ids. + */ + private Stack getAtomizedChoiceStack() { + List choiceList = choiceManager.getChoiceList(); + Stack choiceStack = new Stack<>(); + for (Choice choice : choiceList) { + Atom atom = atomStore.get(choice.getAtom()); + choiceStack.push(new AtomizedChoice(atom, choice.getTruthValue(), choice.isBacktracked())); + } + return choiceStack; + } + + /** + * Convert the given choice stack into one containing atom ids instead of atoms and replace the current + * choice stack with it. + * @param atomizedChoiceStack the stack of choices containing atoms. + */ + private void setAtomizedChoiceStack(Stack atomizedChoiceStack) { + Stack choiceStack = new Stack<>(); + for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { + Atom atom = atomizedChoice.getAtom(); + atomStore.putIfAbsent(atom); + int atomId = atomStore.get(atom); + choiceStack.push(new Choice(atomId, atomizedChoice.getTruthValue(), atomizedChoice.isBacktracked())); + } + choiceManager.setChoiceStack(choiceStack); + } + @Override public int getNumberOfChoices() { return choiceManager.getChoices(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java index 7eb8bc6a2..c383a6f01 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java @@ -139,6 +139,11 @@ public NoGoodCounter getNoGoodCounter() { return counter; } + @Override + public void reset() { + clear(); + } + @Override public void cleanupLearnedNoGoods() { } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java index ec70069c1..c3e3e7165 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java @@ -49,10 +49,15 @@ public interface NoGoodStore { void growForMaxAtomId(int maxAtomId); /** - * Tests whether a cleanup of the learned NoGoods database is appropriate and exectutes the cleaning if + * Tests whether a cleanup of the learned NoGoods database is appropriate and executes the cleaning if * necessary. */ void cleanupLearnedNoGoods(); NoGoodCounter getNoGoodCounter(); + + /** + * Clears all data within the nogood store. + */ + void reset(); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index 8b4d1977e..a96047c81 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -155,6 +155,11 @@ public NoGoodCounter getNoGoodCounter() { return counter; } + @Override + public void reset() { + clear(); + } + @Override public void cleanupLearnedNoGoods() { if (learnedNoGoodDeletion.needToRunNoGoodDeletion()) { diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java index 66374d312..9977dabd8 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java @@ -211,4 +211,11 @@ public int register(NoGood noGood) { } return solverDerivedNoGoods.get(noGood); } + + /** + * Empty interface implementation. + */ + @Override + public void restart(Assignment currentAssignment) { + } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java index 669e6037f..b0fd28af6 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java @@ -126,6 +126,13 @@ public int register(NoGood noGood) { return solverDerivedNoGoods.get(noGood); } + /** + * Empty interface implementation. + */ + @Override + public void restart(Assignment currentAssignment) { + } + @Override public AnswerSet assignmentToAnswerSet(Iterable trueAtoms) { // Note: This grounder only deals with 0-ary predicates, i.e., every atom is a predicate and there is From ce135ea70975ed09e2a6d0d7ef0f142a21d11710 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 4 Aug 2022 17:59:33 +0200 Subject: [PATCH 02/53] Add reset for atom counter and nogood counter --- .../at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java | 2 ++ .../java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java | 4 ++++ .../at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java | 1 + .../at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java | 5 +++++ .../tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java | 1 + 5 files changed, 13 insertions(+) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java index ec047a03a..8df2a3b19 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java @@ -141,5 +141,7 @@ public void reset() { atomIdGenerator.getNextId(); releasedAtomIds.clear(); + + atomCounter.reset(); } } \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java index 753f04a8a..21197d5dd 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java @@ -66,4 +66,8 @@ public String getStatsByType() { return String.join(" ", statsList); } + public void reset() { + countByType.clear(); + } + } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java index c383a6f01..a895d8d26 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java @@ -142,6 +142,7 @@ public NoGoodCounter getNoGoodCounter() { @Override public void reset() { clear(); + counter.reset(); } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java index 3ff15e8e8..4fd591744 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java @@ -125,5 +125,10 @@ public String getStatsByType() { public String getStatsByCardinality() { return "unary: " + getNumberOfUnaryNoGoods() + " binary: " + getNumberOfBinaryNoGoods() + " larger: " + getNumberOfNAryNoGoods(); } + + public void reset() { + countByType = new int[Type.values().length]; + countByCardinality = new int[3]; + } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index a96047c81..0e1c7e30b 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -158,6 +158,7 @@ public NoGoodCounter getNoGoodCounter() { @Override public void reset() { clear(); + counter.reset(); } @Override From 287aedfc26f42319f67ba2d59356707b70e87861 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 4 Aug 2022 18:08:59 +0200 Subject: [PATCH 03/53] Fix choice replay during restart, add replay of enumeration nogoods --- .../kr/alpha/core/solver/AtomizedNoGood.java | 85 +++++++++++++++++++ .../core/solver/AtomizedNoGoodStore.java | 32 +++++++ .../core/solver/ChoiceInfluenceManager.java | 9 ++ .../kr/alpha/core/solver/ChoiceManager.java | 25 ++++-- .../kr/alpha/core/solver/DefaultSolver.java | 47 ++++++++-- 5 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java new file mode 100644 index 000000000..be54e9e36 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016-2020, the Alpha Team. + * All rights reserved. + * + * Additional changes made by Siemens. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver; + + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +/** + * A nogood independent of atom ids provided by an {@link AtomStore}. + */ +public class AtomizedNoGood { + private final SimpleLiteral[] literals; + + public AtomizedNoGood(NoGood noGood, AtomStore atomStore) { + this.literals = new SimpleLiteral[noGood.size()]; + for (int i = 0; i < noGood.size(); i++) { + int literalId = noGood.getLiteral(i); + int atomId = Literals.atomOf(literalId); + Atom atom = atomStore.get(atomId); + boolean truthValue = Literals.isPositive(literalId); + + this.literals[i] = new SimpleLiteral(atom, truthValue); + } + } + + public NoGood deatomize(AtomStore atomStore) { + int[] literals = new int[this.literals.length]; + for (int i = 0; i < this.literals.length; i++) { + Atom atom = this.literals[i].getAtom(); + atomStore.putIfAbsent(atom); + int atomId = atomStore.get(atom); + boolean truthValue = this.literals[i].isPositive(); + + literals[i] = Literals.atomToLiteral(atomId, truthValue); + } + + return new NoGood(literals); + } + + private static class SimpleLiteral { + private final Atom atom; + private final boolean truthValue; + + public SimpleLiteral(Atom atom, boolean truthValue) { + this.atom = atom; + this.truthValue = truthValue; + } + + public Atom getAtom() { + return atom; + } + + public boolean isPositive() { + return truthValue; + } + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java new file mode 100644 index 000000000..cc1664f96 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java @@ -0,0 +1,32 @@ +package at.ac.tuwien.kr.alpha.core.solver; + +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +import java.util.LinkedList; +import java.util.List; + +/** + * A store for nogoods that allows extraction of nogoods also after changes in atom ids. + */ +public class AtomizedNoGoodStore { + private final AtomStore atomStore; + private final List atomizedNoGoods; + + public AtomizedNoGoodStore(AtomStore atomStore) { + this.atomStore = atomStore; + this.atomizedNoGoods = new LinkedList<>(); + } + + public void add(NoGood noGood) { + atomizedNoGoods.add(new AtomizedNoGood(noGood, atomStore)); + } + + public List getNoGoods() { + List noGoods = new LinkedList<>(); + for (AtomizedNoGood atomizedNoGood : atomizedNoGoods) { + noGoods.add(atomizedNoGood.deatomize(atomStore)); + } + return noGoods; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java index 8ab9088d3..f7c1f5816 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java @@ -181,6 +181,15 @@ void setActivityListener(ActivityListener listener) { this.activityListener = listener; } + /** + * Clear all active choice point and influencer information. + */ + public void reset() { + activeChoicePoints.clear(); + activeChoicePointsAtoms.clear(); + influencers = new ChoicePoint[0]; + } + private class ChoicePoint { final Integer atom; final int enabler; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java index bd3695346..bf5876fe9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java @@ -265,15 +265,28 @@ public List getChoiceList() { } /** - * Clear the current assignment and choice stack. Then enforce the given choice stack as the current assignment and - * choice stack. - * @param newChoiceStack the new choice stack to use. + * Reset the current choice influence manager. Then clear the current choice stack and mappings + * between rule heads and bodies. */ - public void setChoiceStack(Stack newChoiceStack) { - assignment.clear(); + public void reset() { + choicePointInfluenceManager.reset(); choiceStack.clear(); - for (Choice choice : newChoiceStack) { + headsToBodies.clear(); + bodiesToHeads.clear(); + } + + /** + * Make the given choice if its atom is an active choice atom. + * + * @param choice the choice to make. + * @return whether the atom of the given choice was an active choice atom. + */ + public boolean replayChoice(Choice choice) { + if (isActiveChoiceAtom(choice.getAtom())) { choose(choice); + return true; + } else { + return false; } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index cb18a30b1..745098239 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -74,6 +74,7 @@ public class DefaultSolver extends AbstractSolver implements StatisticsReporting private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSolver.class); private final NoGoodStore store; + private final AtomizedNoGoodStore enumerationNoGoodStore; private final ChoiceManager choiceManager; private final WritableAssignment assignment; private final GroundConflictNoGoodLearner learner; @@ -95,12 +96,13 @@ private static class SearchState { private final SearchState searchState = new SearchState(); private final PerformanceLog performanceLog; - + public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); this.assignment = assignment; this.store = store; + this.enumerationNoGoodStore = new AtomizedNoGoodStore(atomStore); this.choiceManager = new ChoiceManager(assignment, store); this.choiceManager.setChecksEnabled(config.isDebugInternalChecks()); this.learner = new GroundConflictNoGoodLearner(assignment, atomStore); @@ -186,6 +188,7 @@ private void prepareForSubsequentAnswerSet() { // Backjump instead of backtrackSlow, enumerationNoGood will invert last choice. choiceManager.backjump(backjumpLevel - 1); LOGGER.debug("Adding enumeration nogood: {}", enumerationNoGood); + enumerationNoGoodStore.add(enumerationNoGood); if (!addAndBackjumpIfNecessary(grounder.register(enumerationNoGood), enumerationNoGood, Integer.MAX_VALUE)) { searchState.isSearchSpaceCompletelyExplored = true; } @@ -530,14 +533,16 @@ private void restart() { Stack atomizedChoiceStack = getAtomizedChoiceStack(); store.reset(); + assignment.clear(); grounder.restart(assignment); atomStore.reset(); + choiceManager.reset(); - setAtomizedChoiceStack(atomizedChoiceStack); getNoGoodsFromGrounderAndIngest(); + addEnumerationNoGoods(); + replayAtomizedChoiceStack(atomizedChoiceStack); LOGGER.debug("Solver and grounder restart finished."); - System.out.println("Solver and grounder restart performed."); } /** @@ -555,19 +560,43 @@ private Stack getAtomizedChoiceStack() { } /** - * Convert the given choice stack into one containing atom ids instead of atoms and replace the current - * choice stack with it. + * Convert the given choice stack into one containing atom ids instead of atoms and apply + * the choices on the resulting stack using the choice manager. + * Propagation is performed initially and after each choice. * @param atomizedChoiceStack the stack of choices containing atoms. */ - private void setAtomizedChoiceStack(Stack atomizedChoiceStack) { - Stack choiceStack = new Stack<>(); + private void replayAtomizedChoiceStack(Stack atomizedChoiceStack) { + if (propagate() != null) { + throw oops("Conflict in replay during restart"); + } + for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { Atom atom = atomizedChoice.getAtom(); atomStore.putIfAbsent(atom); int atomId = atomStore.get(atom); - choiceStack.push(new Choice(atomId, atomizedChoice.getTruthValue(), atomizedChoice.isBacktracked())); + Choice choice = new Choice(atomId, atomizedChoice.getTruthValue(), atomizedChoice.isBacktracked()); + + choiceManager.addChoiceInformation(grounder.getChoiceAtoms(), grounder.getHeadsToBodies()); + choiceManager.updateAssignments(); + boolean activeChoice = choiceManager.replayChoice(choice); + + if (activeChoice && propagate() != null) { + throw oops("Conflict in replay during restart"); + } + } + } + + /** + * Add all nogoods from the enumeration nogood store to the regular nogood store. + */ + private void addEnumerationNoGoods() { + Map newNoGoods = new LinkedHashMap<>(); + for (NoGood noGood : enumerationNoGoodStore.getNoGoods()) { + newNoGoods.put(grounder.register(noGood), noGood); + } + if (!ingest(newNoGoods)) { + searchState.isSearchSpaceCompletelyExplored = true; } - choiceManager.setChoiceStack(choiceStack); } @Override From c3197c1358e0a7db04a6feb9aa03a77570bd7096 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 4 Aug 2022 18:17:44 +0200 Subject: [PATCH 04/53] Fix license comments --- .../kr/alpha/core/solver/AtomizedChoice.java | 25 +++++++++++++++++++ .../kr/alpha/core/solver/AtomizedNoGood.java | 6 ++--- .../core/solver/AtomizedNoGoodStore.java | 25 +++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java index f77ac0f64..3cb9dadb0 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java @@ -1,3 +1,28 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java index be54e9e36..ead9823b0 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java @@ -1,9 +1,7 @@ -/* - * Copyright (c) 2016-2020, the Alpha Team. +/** + * Copyright (c) 2022, the Alpha Team. * All rights reserved. * - * Additional changes made by Siemens. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java index cc1664f96..04544043a 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java @@ -1,3 +1,28 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.core.common.AtomStore; From 04a7d076d1724e84fe09c8a8d01a998e03301a0d Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 6 Aug 2022 12:44:06 +0200 Subject: [PATCH 05/53] Add separate structure for ground rule uniqueness check --- .../tuwien/kr/alpha/core/grounder/NaiveGrounder.java | 1 + .../kr/alpha/core/grounder/NoGoodGenerator.java | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index 23b295406..2c60156e6 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -417,6 +417,7 @@ public int register(NoGood noGood) { public void restart(Assignment currentAssignment) { workingMemory.reset(); registry.reset(); + noGoodGenerator.reset(); choiceRecorder.reset(); analyzeUnjustified.reset(); rulesUsingPredicateWorkingMemory.clear(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java index 3d97e7fa6..225e555ae 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java @@ -63,6 +63,7 @@ public class NoGoodGenerator { private final Map> factsFromProgram; private final CompiledProgram programAnalysis; private final Set uniqueGroundRulePerGroundHead; + private final Set groundRuleAtoms; NoGoodGenerator(AtomStore atomStore, ChoiceRecorder recorder, Map> factsFromProgram, CompiledProgram programAnalysis, Set uniqueGroundRulePerGroundHead) { this.atomStore = atomStore; @@ -70,6 +71,7 @@ public class NoGoodGenerator { this.factsFromProgram = factsFromProgram; this.programAnalysis = programAnalysis; this.uniqueGroundRulePerGroundHead = uniqueGroundRulePerGroundHead; + this.groundRuleAtoms = new HashSet<>(); } /** @@ -103,14 +105,14 @@ List generateNoGoodsFromGroundSubstitution(final CompiledRule nonGroundR // Prepare atom representing the rule body. final RuleAtom bodyAtom = new RuleAtom(nonGroundRule, substitution); - // Check uniqueness of ground rule by testing whether the - // body representing atom already has an id. - if (atomStore.contains(bodyAtom)) { + // Check uniqueness of ground rule. + if (groundRuleAtoms.contains(bodyAtom)) { // The current ground instance already exists, // therefore all nogoods have already been created. return emptyList(); } + groundRuleAtoms.add(bodyAtom); final int bodyRepresentingLiteral = atomToLiteral(atomStore.putIfAbsent(bodyAtom)); final int headLiteral = atomToLiteral(atomStore.putIfAbsent(nonGroundRule.getHeadAtom().substitute(substitution))); @@ -162,6 +164,10 @@ List collectNegLiterals(final CompiledRule nonGroundRule, final Substit return bodyLiteralsNegative; } + void reset() { + groundRuleAtoms.clear(); + } + private List collectPosLiterals(final CompiledRule nonGroundRule, final Substitution substitution) { final List bodyLiteralsPositive = new ArrayList<>(); for (Literal lit : nonGroundRule.getPositiveBody()) { From e10a13e1890b6a685a04d8b98ffc32aa4f03ba01 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 6 Aug 2022 14:15:28 +0200 Subject: [PATCH 06/53] Add heuristic state reset for VSIDS --- .../tuwien/kr/alpha/core/solver/DefaultSolver.java | 2 ++ .../core/solver/heuristics/BranchingHeuristic.java | 6 ++++++ .../core/solver/heuristics/HeapOfActiveAtoms.java | 12 ++++++++++++ .../kr/alpha/core/solver/heuristics/VSIDS.java | 6 ++++++ 4 files changed, 26 insertions(+) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 745098239..487b7d262 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -530,9 +530,11 @@ private boolean choose() { */ private void restart() { LOGGER.debug("Performing solver and grounder restart."); + Stack atomizedChoiceStack = getAtomizedChoiceStack(); store.reset(); + branchingHeuristic.reset(); assignment.clear(); grounder.restart(assignment); atomStore.reset(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java index 2e0bb219d..b7e15f236 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java @@ -81,4 +81,10 @@ default void newNoGoods(Collection newNoGoods) { default void growForMaxAtomId(int maxAtomId) { } + + /** + * Reset the state of the heuristic to its initial state. + */ + default void reset() { + } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java index 94421084f..ad9fe9e73 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java @@ -281,4 +281,16 @@ public void setMOMsStrategy(BinaryNoGoodPropagationEstimationStrategy momsStrate } } + /** + * Reset the heap to its empty state. + */ + public void reset() { + incrementedActivityScores = new boolean[0]; + activityScores = new double[0]; + heap.clear(); + stepsSinceLastDecay = 0; + currentActivityIncrement = 1.0; + numberOfNormalizations = 0; + } + } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java index bb29d6e14..ccee389cb 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java @@ -253,4 +253,10 @@ public String toString() { return this.getClass().getSimpleName(); } + @Override + public void reset() { + heapOfActiveAtoms.reset(); + signBalances = new int[0]; + bufferedNoGoods.clear(); + } } From 3d39abf39012541872eba67a465e679c34648914 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 6 Aug 2022 21:17:34 +0200 Subject: [PATCH 07/53] Add grounder assignment sync in decision replay during restart --- .../kr/alpha/core/solver/DefaultSolver.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 487b7d262..da99894c0 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -144,8 +144,7 @@ protected boolean tryAdvance(Consumer action) { learnFromConflict(conflictCause); } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); - grounder.updateAssignment(assignment.getNewPositiveAssignmentsIterator()); - getNoGoodsFromGrounderAndIngest(); + syncWithGrounder(); } else if (choose()) { LOGGER.debug("Did choice."); } else if (close()) { @@ -166,6 +165,15 @@ private void initializeSearch() { searchState.hasBeenInitialized = true; } + /** + * Updates the assignment for the grounder and then gets new nogoods from the grounder + * by calling {@link DefaultSolver#getNoGoodsFromGrounderAndIngest()}. + */ + private void syncWithGrounder() { + grounder.updateAssignment(assignment.getNewPositiveAssignmentsIterator()); + getNoGoodsFromGrounderAndIngest(); + } + private void prepareForSubsequentAnswerSet() { // We already found one Answer-Set and are requested to find another one. searchState.afterAllAtomsAssigned = false; @@ -540,7 +548,7 @@ private void restart() { atomStore.reset(); choiceManager.reset(); - getNoGoodsFromGrounderAndIngest(); + syncWithGrounder(); addEnumerationNoGoods(); replayAtomizedChoiceStack(atomizedChoiceStack); @@ -582,8 +590,14 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack choiceManager.updateAssignments(); boolean activeChoice = choiceManager.replayChoice(choice); - if (activeChoice && propagate() != null) { - throw oops("Conflict in replay during restart"); + if (activeChoice) { + if (propagate() != null) { + throw oops("Conflict in replay during restart"); + } + syncWithGrounder(); + if (propagate() != null) { + throw oops("Conflict in replay during restart"); + } } } } From 7c746731ad2909c4e26de6a5e711d4fc2202c6ce Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 13 Aug 2022 12:02:28 +0200 Subject: [PATCH 08/53] Add reset for EnumerationAtom in grounder restart --- .../at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java | 2 ++ ...AtomizedNoGoodStore.java => AtomizedNoGoodCollection.java} | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{AtomizedNoGoodStore.java => AtomizedNoGoodCollection.java} (96%) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index 2c60156e6..719d2ba71 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -43,6 +43,7 @@ import java.util.SortedSet; import java.util.TreeSet; +import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; @@ -424,6 +425,7 @@ public void restart(Assignment currentAssignment) { removeAfterObtainingNewNoGoods = new LinkedHashSet<>(); instantiationStrategy.setStaleWorkingMemoryEntries(removeAfterObtainingNewNoGoods); instantiationStrategy.setCurrentAssignment(currentAssignment); + EnumerationAtom.resetEnumerations(); fixedRules = new ArrayList<>(); initializeFactsAndRules(); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java similarity index 96% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java index 04544043a..79f1f2dd1 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java @@ -34,11 +34,11 @@ /** * A store for nogoods that allows extraction of nogoods also after changes in atom ids. */ -public class AtomizedNoGoodStore { +public class NoGoodBulkAtomizer { private final AtomStore atomStore; private final List atomizedNoGoods; - public AtomizedNoGoodStore(AtomStore atomStore) { + public NoGoodBulkAtomizer(AtomStore atomStore) { this.atomStore = atomStore; this.atomizedNoGoods = new LinkedList<>(); } From 1265f2040bf9d135c2a5afd8f6abac95b874636f Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 13 Aug 2022 12:09:09 +0200 Subject: [PATCH 09/53] Rename collection of atomized nogoods --- .../kr/alpha/core/solver/AtomizedNoGood.java | 12 +++++++ .../core/solver/AtomizedNoGoodCollection.java | 20 +++++++++-- .../kr/alpha/core/solver/DefaultSolver.java | 34 +++++++++++++++---- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java index ead9823b0..1d397fd29 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java @@ -37,6 +37,12 @@ public class AtomizedNoGood { private final SimpleLiteral[] literals; + /** + * Initializes an {@link AtomizedNoGood} with the same literals as the given {@link NoGood}. + * Atom ids are provided by the given {@link AtomStore}. + * @param noGood the {@link NoGood} to get the list of literals from. + * @param atomStore the {@link AtomStore} to get atom ids from. + */ public AtomizedNoGood(NoGood noGood, AtomStore atomStore) { this.literals = new SimpleLiteral[noGood.size()]; for (int i = 0; i < noGood.size(); i++) { @@ -49,6 +55,12 @@ public AtomizedNoGood(NoGood noGood, AtomStore atomStore) { } } + /** + * Creates a new {@link NoGood} with the same literals as this {@link AtomizedNoGood}. + * Atom ids are provided by the given {@link AtomStore}. + * @param atomStore the {@link AtomStore} to get atom ids from. + * @return the newly created {@link NoGood} with the same literals as this {@link AtomizedNoGood}. + */ public NoGood deatomize(AtomStore atomStore) { int[] literals = new int[this.literals.length]; for (int i = 0; i < this.literals.length; i++) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java index 79f1f2dd1..21a6783b6 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java @@ -32,21 +32,35 @@ import java.util.List; /** - * A store for nogoods that allows extraction of nogoods also after changes in atom ids. + * A collection for nogoods that allows extraction of nogoods also after changes in atom ids. This is done by + * converting nogoods to an atomized state based on a specific {@link AtomStore}. */ -public class NoGoodBulkAtomizer { +public class AtomizedNoGoodCollection { private final AtomStore atomStore; private final List atomizedNoGoods; - public NoGoodBulkAtomizer(AtomStore atomStore) { + /** + * Initializes the {@link AtomizedNoGoodCollection} with a specific {@link AtomStore} to use for conversions. + * @param atomStore the {@link AtomStore} to use. + */ + public AtomizedNoGoodCollection(AtomStore atomStore) { this.atomStore = atomStore; this.atomizedNoGoods = new LinkedList<>(); } + /** + * Adds a nogood to the collection. The nogood is stored in an atomized way, meaning that it does not depend on + * the atom ids of an {@link AtomStore}. + * @param noGood the nogood to add. + */ public void add(NoGood noGood) { atomizedNoGoods.add(new AtomizedNoGood(noGood, atomStore)); } + /** + * Gets all nogoods in the collection with atom ids based on the current {@link AtomStore}. + * @return all nogoods in the collection converted to contain atom ids based on the current {@link AtomStore}. + */ public List getNoGoods() { List noGoods = new LinkedList<>(); for (AtomizedNoGood atomizedNoGood : atomizedNoGoods) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index da99894c0..f28a0d66c 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -74,7 +74,7 @@ public class DefaultSolver extends AbstractSolver implements StatisticsReporting private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSolver.class); private final NoGoodStore store; - private final AtomizedNoGoodStore enumerationNoGoodStore; + private final AtomizedNoGoodCollection enumerationNoGoods; private final ChoiceManager choiceManager; private final WritableAssignment assignment; private final GroundConflictNoGoodLearner learner; @@ -102,7 +102,7 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.assignment = assignment; this.store = store; - this.enumerationNoGoodStore = new AtomizedNoGoodStore(atomStore); + this.enumerationNoGoods = new AtomizedNoGoodCollection(atomStore); this.choiceManager = new ChoiceManager(assignment, store); this.choiceManager.setChecksEnabled(config.isDebugInternalChecks()); this.learner = new GroundConflictNoGoodLearner(assignment, atomStore); @@ -196,7 +196,7 @@ private void prepareForSubsequentAnswerSet() { // Backjump instead of backtrackSlow, enumerationNoGood will invert last choice. choiceManager.backjump(backjumpLevel - 1); LOGGER.debug("Adding enumeration nogood: {}", enumerationNoGood); - enumerationNoGoodStore.add(enumerationNoGood); + enumerationNoGoods.add(enumerationNoGood); if (!addAndBackjumpIfNecessary(grounder.register(enumerationNoGood), enumerationNoGood, Integer.MAX_VALUE)) { searchState.isSearchSpaceCompletelyExplored = true; } @@ -552,11 +552,31 @@ private void restart() { addEnumerationNoGoods(); replayAtomizedChoiceStack(atomizedChoiceStack); + System.out.println("# Solver and grounder restart performed."); + System.out.println("# After restart, before second gc"); + printMemoryStats(); + +// try { +// Thread.sleep(10000); +// } catch (InterruptedException e) { +// throw new RuntimeException(e); +// } + + System.gc(); + System.out.println("# After second gc"); + printMemoryStats(); + +// try { +// Thread.sleep(10000); +// } catch (InterruptedException e) { +// throw new RuntimeException(e); +// } + LOGGER.debug("Solver and grounder restart finished."); } /** - * Extract the current choice stack with atom ids replaced by the respective atoms. + * Extracts the current choice stack with atom ids replaced by the respective atoms. * @return the choice stack containing atoms instead of atom ids. */ private Stack getAtomizedChoiceStack() { @@ -570,7 +590,7 @@ private Stack getAtomizedChoiceStack() { } /** - * Convert the given choice stack into one containing atom ids instead of atoms and apply + * Converts the given choice stack into one containing atom ids instead of atoms and applies * the choices on the resulting stack using the choice manager. * Propagation is performed initially and after each choice. * @param atomizedChoiceStack the stack of choices containing atoms. @@ -603,11 +623,11 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack } /** - * Add all nogoods from the enumeration nogood store to the regular nogood store. + * Adds all nogoods from the enumeration nogood store to the regular nogood store. */ private void addEnumerationNoGoods() { Map newNoGoods = new LinkedHashMap<>(); - for (NoGood noGood : enumerationNoGoodStore.getNoGoods()) { + for (NoGood noGood : enumerationNoGoods.getNoGoods()) { newNoGoods.put(grounder.register(noGood), noGood); } if (!ingest(newNoGoods)) { From 66477d27d6c308cb4fe6aa66d72f1f5a2d1d3d3f Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 13 Aug 2022 18:07:03 +0200 Subject: [PATCH 10/53] Fix chained branching heuristic reset --- .../core/solver/heuristics/ChainedBranchingHeuristics.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java index 729386635..0e0736e1e 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java @@ -122,4 +122,11 @@ public String toString() { return this.getClass().getSimpleName() + chain; } + @Override + public void reset() { + for (BranchingHeuristic heuristic : chain) { + heuristic.reset(); + } + } + } From bf43569f34c2edd0d9d87151c8e81307e1c64cd3 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 13 Aug 2022 18:15:31 +0200 Subject: [PATCH 11/53] Add configuration parameters for restarts --- .../kr/alpha/api/config/SystemConfig.java | 20 ++++++++++++++++ .../alpha/app/config/CommandLineParser.java | 23 +++++++++++++++++++ .../kr/alpha/core/solver/DefaultSolver.java | 11 +++++++++ 3 files changed, 54 insertions(+) diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index 27019ce10..c93409ca0 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -49,6 +49,8 @@ public class SystemConfig { public static final String DEFAULT_NOGOOD_STORE_NAME = "alphaRoaming"; public static final Heuristic DEFAULT_BRANCHING_HEURISTIC = Heuristic.VSIDS; public static final BinaryNoGoodPropagationEstimationStrategy DEFAULT_MOMS_STRATEGY = BinaryNoGoodPropagationEstimationStrategy.CountBinaryWatches; + public static final boolean DEFAULT_RESTARTS_ENABLED = false; + public static final int DEFAULT_RESTART_ITERATIONS = 10000; public static final long DEFAULT_SEED = System.nanoTime(); public static final boolean DEFAULT_DETERMINISTIC = false; public static final boolean DEFAULT_PRINT_STATS = false; @@ -73,6 +75,8 @@ public class SystemConfig { private boolean debugInternalChecks = DEFAULT_DEBUG_INTERNAL_CHECKS; private Heuristic branchingHeuristic = DEFAULT_BRANCHING_HEURISTIC; private BinaryNoGoodPropagationEstimationStrategy momsStrategy = DEFAULT_MOMS_STRATEGY; + private boolean restartsEnabled = DEFAULT_RESTARTS_ENABLED; + private int restartIterations = DEFAULT_RESTART_ITERATIONS; private boolean quiet = DEFAULT_QUIET; private boolean printStats = DEFAULT_PRINT_STATS; private boolean disableJustificationSearch = DEFAULT_DISABLE_JUSTIFICATION_SEARCH; @@ -119,6 +123,22 @@ public void setNogoodStoreName(String nogoodStoreName) { this.nogoodStoreName = nogoodStoreName; } + public boolean isRestartsEnabled() { + return restartsEnabled; + } + + public void setRestartsEnabled(boolean restartsEnabled) { + this.restartsEnabled = restartsEnabled; + } + + public int getRestartIterations() { + return restartIterations; + } + + public void setRestartIterations(int restartIterations) { + this.restartIterations = restartIterations; + } + public boolean isDeterministic() { return this.deterministic; } diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 4b3ccf1f5..1276f8d98 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -96,6 +96,10 @@ public class CommandLineParser { .desc("the solver implementation to use (default: " + SystemConfig.DEFAULT_SOLVER_NAME + ")").build(); private static final Option OPT_NOGOOD_STORE = Option.builder("r").longOpt("store").hasArg(true).argName("store") .desc("the nogood store to use (default: " + SystemConfig.DEFAULT_NOGOOD_STORE_NAME + ")").build(); + private static final Option OPT_RESTARTS_ENABLED = Option.builder("rst").longOpt("enableRestarts") + .desc("enable solver restarts (default: " + SystemConfig.DEFAULT_RESTARTS_ENABLED + ")").build(); + private static final Option OPT_RESTART_ITERATIONS = Option.builder("rit").longOpt("restartIterations").hasArg(true).argName("number").type(Integer.class) + .desc("the number of solver iterations between restarts (default: " + SystemConfig.DEFAULT_RESTART_ITERATIONS + ")").build(); private static final Option OPT_SORT = Option.builder("sort").longOpt("sort").hasArg(false) .desc("sort answer sets (default: " + SystemConfig.DEFAULT_SORT_ANSWER_SETS + ")").build(); private static final Option OPT_DETERMINISTIC = Option.builder("d").longOpt("deterministic").hasArg(false) @@ -170,6 +174,8 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_GROUNDER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SOLVER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NOGOOD_STORE); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_RESTARTS_ENABLED); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_RESTART_ITERATIONS); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SORT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_DETERMINISTIC); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SEED); @@ -228,6 +234,8 @@ private void initializeGlobalOptionHandlers() { this.globalOptionHandlers.put(CommandLineParser.OPT_GROUNDER.getOpt(), this::handleGrounder); this.globalOptionHandlers.put(CommandLineParser.OPT_SOLVER.getOpt(), this::handleSolver); this.globalOptionHandlers.put(CommandLineParser.OPT_NOGOOD_STORE.getOpt(), this::handleNogoodStore); + this.globalOptionHandlers.put(CommandLineParser.OPT_RESTARTS_ENABLED.getOpt(), this::handleRestartsEnabled); + this.globalOptionHandlers.put(CommandLineParser.OPT_RESTART_ITERATIONS.getOpt(), this::handleRestartIterations); this.globalOptionHandlers.put(CommandLineParser.OPT_SORT.getOpt(), this::handleSort); this.globalOptionHandlers.put(CommandLineParser.OPT_DETERMINISTIC.getOpt(), this::handleDeterministic); this.globalOptionHandlers.put(CommandLineParser.OPT_SEED.getOpt(), this::handleSeed); @@ -347,6 +355,21 @@ private void handleNogoodStore(Option opt, SystemConfig cfg) { cfg.setNogoodStoreName(opt.getValue(SystemConfig.DEFAULT_NOGOOD_STORE_NAME)); } + private void handleRestartsEnabled(Option opt, SystemConfig cfg) { + cfg.setRestartsEnabled(true); + } + + private void handleRestartIterations(Option opt, SystemConfig cfg) { + String optVal = opt.getValue(); + int limit; + if (optVal != null) { + limit = Integer.parseInt(optVal); + cfg.setRestartIterations(limit); + } else { + cfg.setRestartIterations(SystemConfig.DEFAULT_RESTART_ITERATIONS); + } + } + private void handleFilters(Option opt, InputConfig cfg) { String pred = opt.getValue().trim(); cfg.getDesiredPredicates().add(pred); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index f28a0d66c..f24a09166 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -79,6 +79,9 @@ public class DefaultSolver extends AbstractSolver implements StatisticsReporting private final WritableAssignment assignment; private final GroundConflictNoGoodLearner learner; private final BranchingHeuristic branchingHeuristic; + private boolean restartsEnabled; + private final int restartIterationBreakpoint; + private int iterationCounter; private int mbtAtFixpoint; private int conflictsAfterClosing; @@ -110,6 +113,9 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableJustifications = config.isDisableJustificationSearch(); this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, 1000); + this.restartsEnabled = config.isRestartsEnabled(); + this.restartIterationBreakpoint = config.getRestartIterations(); + this.iterationCounter = 0; } private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAssignment assignment, Random random, HeuristicsConfiguration heuristicsConfiguration) { @@ -132,6 +138,7 @@ protected boolean tryAdvance(Consumer action) { } // Try all assignments until grounder reports no more NoGoods and all of them are satisfied while (true) { + iterationCounter++; performanceLog.writeIfTimeForLogging(LOGGER); if (searchState.isSearchSpaceCompletelyExplored) { LOGGER.debug("Search space has been fully explored, there are no more answer-sets."); @@ -145,6 +152,10 @@ protected boolean tryAdvance(Consumer action) { } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); syncWithGrounder(); + } else if (restartsEnabled && iterationCounter >= restartIterationBreakpoint) { + restart(); + restartsEnabled = false; + iterationCounter = 0; } else if (choose()) { LOGGER.debug("Did choice."); } else if (close()) { From 62e190088663424d7e321815866efd3ade33ae06 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Mon, 15 Aug 2022 12:08:43 +0200 Subject: [PATCH 12/53] Remove debugging output --- .../kr/alpha/core/solver/DefaultSolver.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index f24a09166..1790a43c9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -563,26 +563,6 @@ private void restart() { addEnumerationNoGoods(); replayAtomizedChoiceStack(atomizedChoiceStack); - System.out.println("# Solver and grounder restart performed."); - System.out.println("# After restart, before second gc"); - printMemoryStats(); - -// try { -// Thread.sleep(10000); -// } catch (InterruptedException e) { -// throw new RuntimeException(e); -// } - - System.gc(); - System.out.println("# After second gc"); - printMemoryStats(); - -// try { -// Thread.sleep(10000); -// } catch (InterruptedException e) { -// throw new RuntimeException(e); -// } - LOGGER.debug("Solver and grounder restart finished."); } From 3b3343f6e0af7e9658a85147db8cc7e203820f40 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Mon, 15 Aug 2022 13:09:20 +0200 Subject: [PATCH 13/53] Add test configurations with restarts enabled --- .../core/solver/RegressionTestConfig.java | 18 ++++++- .../solver/RegressionTestConfigProvider.java | 54 +++++++++++-------- .../kr/alpha/core/solver/SolverTests.java | 8 ++- .../kr/alpha/core/test/util/TestUtils.java | 4 ++ 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index 73c318012..78239428b 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -13,6 +13,9 @@ public class RegressionTestConfig { private final Heuristic branchingHeuristic; + private final boolean restartsEnabled; + private final int restartIterations; + private final long seed; private final boolean debugChecks; @@ -31,13 +34,15 @@ public class RegressionTestConfig { public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, - Heuristic branchingHeuristic, long seed, + Heuristic branchingHeuristic, boolean restartsEnabled, int restartIterations, long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { this.solverName = solverName; this.grounderName = grounderName; this.noGoodStoreName = noGoodStoreName; this.branchingHeuristic = branchingHeuristic; + this.restartsEnabled = restartsEnabled; + this.restartIterations = restartIterations; this.seed = seed; this.debugChecks = debugChecks; this.grounderToleranceConstraints = grounderToleranceConstraints; @@ -53,6 +58,8 @@ public SystemConfig toSystemConfig() { retVal.setGrounderName(this.grounderName); retVal.setSolverName(this.solverName); retVal.setNogoodStoreName(this.noGoodStoreName); + retVal.setRestartsEnabled(this.restartsEnabled); + retVal.setRestartIterations(this.restartIterations); retVal.setSeed(this.seed); retVal.setBranchingHeuristic(this.branchingHeuristic); retVal.setDebugInternalChecks(this.debugChecks); @@ -81,6 +88,14 @@ public Heuristic getBranchingHeuristic() { return this.branchingHeuristic; } + public boolean isRestartsEnabled() { + return restartsEnabled; + } + + public int getRestartIterations() { + return restartIterations; + } + public long getSeed() { return this.seed; } @@ -121,5 +136,4 @@ public String toString() { this.grounderToleranceConstraints, this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); } - } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index 20f139581..73352be22 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -15,6 +15,8 @@ public class RegressionTestConfigProvider { private static final String DEFAULT_GROUNDER_NAME = "naive"; private static final String DEFAULT_ATOM_STORE = "alpharoaming"; private static final String DEFAULT_BRANCHING_HEURISTIC = "VSIDS"; + private static final boolean DEFAULT_RESTARTS_ENABLED = false; + private static final int DEFAULT_RESTART_ITERATIONS = 5; private static final String DEFAULT_GROUNDER_TOLERANCE = "strict"; private static final boolean DEFAULT_DISABLE_INSTANCE_REMOVAL = false; private static final boolean DEFAULT_ENABLE_DEBUG_CHECKS = false; @@ -24,7 +26,7 @@ public class RegressionTestConfigProvider { * "RegressionTest" annotation. * Exact number of combinations depends on the "CI" environment variable that can be used to signal that a test is being run in a CI * environment. - * + * * @return */ private static List buildConfigs() { @@ -32,15 +34,17 @@ private static List buildConfigs() { boolean ci = Boolean.valueOf(System.getenv("CI")); //@formatter:off - String[] solvers = ci ? new String[]{DEFAULT_SOLVER_NAME, "naive" } : new String[]{DEFAULT_SOLVER_NAME }; + String[] solvers = ci ? new String[]{DEFAULT_SOLVER_NAME, "naive"} : new String[]{DEFAULT_SOLVER_NAME}; String grounder = DEFAULT_GROUNDER_NAME; - String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive" } : new String[]{DEFAULT_ATOM_STORE }; - String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC }; - String[] gtcValues = new String[]{DEFAULT_GROUNDER_TOLERANCE, "permissive" }; + String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive"} : new String[]{DEFAULT_ATOM_STORE}; + String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC}; + boolean[] restartEnabledValues = new boolean[]{DEFAULT_RESTARTS_ENABLED, true}; + int[] restartIterationsValues = new int[]{DEFAULT_RESTART_ITERATIONS}; + String[] gtcValues = new String[]{DEFAULT_GROUNDER_TOLERANCE, "permissive"}; String gtrValue = DEFAULT_GROUNDER_TOLERANCE; - boolean[] disableInstanceRemovalValues = ci ? new boolean[]{DEFAULT_DISABLE_INSTANCE_REMOVAL, true } : new boolean[]{DEFAULT_DISABLE_INSTANCE_REMOVAL }; - boolean[] evaluateStratifiedValues = new boolean[]{false, true }; - boolean[] enableDebugChecksValues = new boolean[]{DEFAULT_ENABLE_DEBUG_CHECKS, true }; + boolean[] disableInstanceRemovalValues = ci ? new boolean[]{DEFAULT_DISABLE_INSTANCE_REMOVAL, true} : new boolean[]{DEFAULT_DISABLE_INSTANCE_REMOVAL}; + boolean[] evaluateStratifiedValues = new boolean[]{false, true}; + boolean[] enableDebugChecksValues = new boolean[]{DEFAULT_ENABLE_DEBUG_CHECKS, true}; //@formatter:on // NOTE: @@ -56,14 +60,20 @@ private static List buildConfigs() { for (String solverName : solvers) { for (String atomStoreName : atomStores) { for (String branchingHeuristicName : heuristics) { - for (String grounderTolerance : gtcValues) { - for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { - for (boolean evaluateStratified : evaluateStratifiedValues) { - for (boolean enableDebugChecks : enableDebugChecksValues) { - configsToTest.add(new RegressionTestConfig( - solverName, grounder, atomStoreName, Heuristic.valueOf(branchingHeuristicName), - seed, enableDebugChecks, grounderTolerance, gtrValue, disableInstanceRemoval, evaluateStratified, - true, true)); + for (boolean restartsEnabled : restartEnabledValues) { + for (int restartIterations : restartIterationsValues) { + for (String grounderTolerance : gtcValues) { + for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { + for (boolean evaluateStratified : evaluateStratifiedValues) { + for (boolean enableDebugChecks : enableDebugChecksValues) { + configsToTest.add(new RegressionTestConfig( + solverName, grounder, atomStoreName, + Heuristic.valueOf(branchingHeuristicName), + restartsEnabled, restartIterations, seed, enableDebugChecks, + grounderTolerance, gtrValue, disableInstanceRemoval, + evaluateStratified, true, true)); + } + } } } } @@ -79,15 +89,15 @@ private static List buildConfigs() { * Provides {@link RegressionTestConfig}s specifically for tests concerned with AggregateRewriting. * All parameters fixed to default values except stratified evaluation, sorting grid encoding for count rewriting * and negative sum element support. - * + * * @return */ private static List buildConfigsForAggregateTests() { List configsToTest = new ArrayList<>(); - boolean[] evaluateStratifiedValues = new boolean[] {true, false }; - boolean[] useSortingGridValues = new boolean[] {true, false }; - boolean[] supportNegativeSumElementsValues = new boolean[] {true, false }; + boolean[] evaluateStratifiedValues = new boolean[]{true, false}; + boolean[] useSortingGridValues = new boolean[]{true, false}; + boolean[] supportNegativeSumElementsValues = new boolean[]{true, false}; for (boolean evalStratified : evaluateStratifiedValues) { for (boolean useSortingGrid : useSortingGridValues) { @@ -95,7 +105,7 @@ private static List buildConfigsForAggregateTests() { configsToTest.add( new RegressionTestConfig( DEFAULT_SOLVER_NAME, DEFAULT_GROUNDER_NAME, DEFAULT_ATOM_STORE, Heuristic.valueOf(DEFAULT_BRANCHING_HEURISTIC), - 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, + DEFAULT_RESTARTS_ENABLED, DEFAULT_RESTART_ITERATIONS, 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, evalStratified, useSortingGrid, supportNegativeElements)); } @@ -128,6 +138,6 @@ private static final String[] nonDeprecatedHeuristics() { nonDeprecatedHeuristicsNames.add(field.getName()); } } - return nonDeprecatedHeuristicsNames.toArray(new String[] {}); + return nonDeprecatedHeuristicsNames.toArray(new String[]{}); } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java index 911a2dd32..a84e6576d 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java @@ -27,11 +27,7 @@ */ package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.assertRegressionTestAnswerSet; -import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.assertRegressionTestAnswerSets; -import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.assertRegressionTestAnswerSetsWithBase; -import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.collectRegressionTestAnswerSets; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.*; import static java.util.Collections.singleton; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -806,12 +802,14 @@ public void smallCardinalityAggregate(RegressionTestConfig cfg) { @RegressionTest public void dummyGrounder(RegressionTestConfig cfg) { + ignoreTestForRestartsEnabled(cfg); // Do not run this test case with restarts enabled. AtomStore atomStore = new AtomStoreImpl(); assertEquals(DummyGrounder.EXPECTED, buildSolverForRegressionTest(atomStore, new DummyGrounder(atomStore), cfg).collectSet()); } @RegressionTest public void choiceGrounder(RegressionTestConfig cfg) { + ignoreTestForRestartsEnabled(cfg); // Do not run this test case with restarts enabled. AtomStore atomStore = new AtomStoreImpl(); assertEquals(ChoiceGrounder.EXPECTED, buildSolverForRegressionTest(atomStore, new ChoiceGrounder(atomStore), cfg).collectSet()); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java index 75cbc20df..20cc55d62 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java @@ -216,4 +216,8 @@ public static void ignoreTestForSimplifiedSumAggregates(RegressionTestConfig cfg Assumptions.assumeTrue(cfg.isSupportNegativeSumElements()); } + public static void ignoreTestForRestartsEnabled(RegressionTestConfig cfg) { + Assumptions.assumeFalse(cfg.isRestartsEnabled()); + } + } From 6c029a16eb114ce9117646f47dcd4b098b42aad4 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Mon, 15 Aug 2022 16:48:59 +0200 Subject: [PATCH 14/53] Ignore specific test case if restarts enabled --- .../ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java index 1afed713b..a0e910abb 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java @@ -26,6 +26,7 @@ package at.ac.tuwien.kr.alpha.core.solver; import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.ignoreTestForRestartsEnabled; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -58,6 +59,7 @@ public void checkStatsStringZeroChoices(RegressionTestConfig cfg) { @RegressionTest public void checkStatsStringOneChoice(RegressionTestConfig cfg) { + ignoreTestForRestartsEnabled(cfg); Solver solver = buildSolverForRegressionTest("a :- not b. b :- not a.", cfg); assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckStats(solver, 2, 1, 1, 1, 1, 0, 0, 0); From 318c28bc2c17589af817ab5f2c409836e384bc65 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 16 Aug 2022 13:58:04 +0200 Subject: [PATCH 15/53] Fix growing for atom ids during choice replay in restart --- .../kr/alpha/core/solver/DefaultSolver.java | 25 +++++++++++++++---- .../core/solver/RegressionTestConfig.java | 13 +++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 1790a43c9..b98440ebb 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -39,6 +39,7 @@ import java.util.Map.Entry; import java.util.function.Consumer; +import at.ac.tuwien.kr.alpha.core.common.Assignment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -475,11 +476,7 @@ private boolean backtrack() { } private boolean ingest(Map obtained) { - assignment.growForMaxAtomId(); - int maxAtomId = atomStore.getMaxAtomId(); - store.growForMaxAtomId(maxAtomId); - choiceManager.growForMaxAtomId(maxAtomId); - branchingHeuristic.growForMaxAtomId(maxAtomId); + growForMaxAtomId(); branchingHeuristic.newNoGoods(obtained.values()); LinkedList> noGoodsToAdd = new LinkedList<>(obtained.entrySet()); @@ -594,6 +591,11 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { Atom atom = atomizedChoice.getAtom(); atomStore.putIfAbsent(atom); + } + growForMaxAtomId(); + + for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { + Atom atom = atomizedChoice.getAtom(); int atomId = atomStore.get(atom); Choice choice = new Choice(atomId, atomizedChoice.getTruthValue(), atomizedChoice.isBacktracked()); @@ -613,6 +615,19 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack } } + /** + * Grows the current {@link Assignment}, {@link NoGoodStore}, {@link ChoiceManager} and {@link BranchingHeuristic} + * by calling {@link Assignment#growForMaxAtomId()}, {@link NoGoodStore#growForMaxAtomId(int)}, + * {@link ChoiceManager#growForMaxAtomId(int)} and {@link BranchingHeuristic#growForMaxAtomId(int)} respectively. + */ + private void growForMaxAtomId() { + assignment.growForMaxAtomId(); + int maxAtomId = atomStore.getMaxAtomId(); + store.growForMaxAtomId(maxAtomId); + choiceManager.growForMaxAtomId(maxAtomId); + branchingHeuristic.growForMaxAtomId(maxAtomId); + } + /** * Adds all nogoods from the enumeration nogood store to the regular nogood store. */ diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index 78239428b..bc2ec6302 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -36,7 +36,8 @@ public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, Heuristic branchingHeuristic, boolean restartsEnabled, int restartIterations, long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, - boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { + boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, + boolean supportNegativeSumElements) { this.solverName = solverName; this.grounderName = grounderName; this.noGoodStoreName = noGoodStoreName; @@ -131,9 +132,13 @@ public boolean isSupportNegativeSumElements() { @Override public String toString() { return String.format( - "RegressionTestConfig [solverName=%s, grounderName=%s, noGoodStoreName=%s, branchingHeuristic=%s, seed=%s, debugChecks=%s, grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s, evaluateStratifiedPart=%s, useSortingGrid=%s, supportNegativeSumElements=%s]", - this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.seed, this.debugChecks, - this.grounderToleranceConstraints, this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, + "RegressionTestConfig [solverName=%s, grounderName=%s, noGoodStoreName=%s, branchingHeuristic=%s," + + " restartsEnabled=%b, restartIterations=%d, seed=%s, debugChecks=%s, grounderToleranceConstraints=%s," + + " grounderToleranceRules=%s, disableInstanceRemoval=%s, evaluateStratifiedPart=%s, useSortingGrid=%s," + + " supportNegativeSumElements=%s]", + this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.restartsEnabled, + this.restartIterations, this.seed, this.debugChecks, this.grounderToleranceConstraints, + this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); } } From 0749bd03bfe4ee82517e727644496e42446ce6f7 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 2 Sep 2022 18:36:31 +0200 Subject: [PATCH 16/53] Add unit tests for atomized structures, create package for solver and grounder reset --- .../kr/alpha/core/solver/DefaultSolver.java | 4 +- .../core/solver/reset/AtomValuePair.java | 55 ++++ .../solver/{ => reset}/AtomizedChoice.java | 16 +- .../{ => reset}/AtomizedNoGoodCollection.java | 26 +- .../NoGoodAtomizer.java} | 54 ++-- .../core/solver/SolverStatisticsTests.java | 2 +- .../reset/AtomizedNoGoodCollectionTest.java | 255 ++++++++++++++++++ .../core/solver/reset/NoGoodAtomizerTest.java | 187 +++++++++++++ .../core/solver/reset/TestAtomGenerator.java | 117 ++++++++ 9 files changed, 659 insertions(+), 57 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{ => reset}/AtomizedChoice.java (86%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{ => reset}/AtomizedNoGoodCollection.java (82%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{AtomizedNoGood.java => reset/NoGoodAtomizer.java} (70%) create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index b98440ebb..6c473776f 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -541,8 +541,8 @@ private boolean choose() { /** * Performs a restart of the solving process while preserving the current assignment - and thus the progress made. - * Nogood store and grounder are reset. Then the {@link AtomStore} is emptied and the current assignment - * is reconstructed. + * {@link NoGoodStore} and {@link Grounder} are reset. Then the {@link AtomStore} is emptied and the current + * assignment is reconstructed. */ private void restart() { LOGGER.debug("Performing solver and grounder restart."); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java new file mode 100644 index 000000000..e754399ab --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reset; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; + +public class AtomValuePair { + private final Atom atom; + private final boolean truthValue; + + public AtomValuePair(Atom atom, boolean truthValue) { + this.atom = atom; + this.truthValue = truthValue; + } + + public Atom getAtom() { + return atom; + } + + public boolean isPositive() { + return truthValue; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof AtomValuePair)) { + return false; + } + AtomValuePair other = (AtomValuePair) obj; + return atom.compareTo(other.atom) == 0 && truthValue == other.isPositive(); + } +} \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedChoice.java similarity index 86% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedChoice.java index 3cb9dadb0..fe2a19520 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedChoice.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedChoice.java @@ -1,17 +1,17 @@ /** * Copyright (c) 2022, the Alpha Team. * All rights reserved. - * + *

* Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + *

* 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * + * list of conditions and the following disclaimer. + *

* 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver; +package at.ac.tuwien.kr.alpha.core.solver.reset; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollection.java similarity index 82% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollection.java index 21a6783b6..0eb1f4a6e 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGoodCollection.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollection.java @@ -1,17 +1,17 @@ /** * Copyright (c) 2022, the Alpha Team. * All rights reserved. - * + *

* Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + *

* 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * + * list of conditions and the following disclaimer. + *

* 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver; +package at.ac.tuwien.kr.alpha.core.solver.reset; import at.ac.tuwien.kr.alpha.core.common.AtomStore; import at.ac.tuwien.kr.alpha.core.common.NoGood; @@ -37,10 +37,11 @@ */ public class AtomizedNoGoodCollection { private final AtomStore atomStore; - private final List atomizedNoGoods; + private final List atomizedNoGoods; /** * Initializes the {@link AtomizedNoGoodCollection} with a specific {@link AtomStore} to use for conversions. + * * @param atomStore the {@link AtomStore} to use. */ public AtomizedNoGoodCollection(AtomStore atomStore) { @@ -51,19 +52,22 @@ public AtomizedNoGoodCollection(AtomStore atomStore) { /** * Adds a nogood to the collection. The nogood is stored in an atomized way, meaning that it does not depend on * the atom ids of an {@link AtomStore}. + * * @param noGood the nogood to add. */ public void add(NoGood noGood) { - atomizedNoGoods.add(new AtomizedNoGood(noGood, atomStore)); + atomizedNoGoods.add(new NoGoodAtomizer(noGood, atomStore)); } /** * Gets all nogoods in the collection with atom ids based on the current {@link AtomStore}. + * * @return all nogoods in the collection converted to contain atom ids based on the current {@link AtomStore}. + * The list is sorted in the order the nogoods were added to the collection. */ public List getNoGoods() { List noGoods = new LinkedList<>(); - for (AtomizedNoGood atomizedNoGood : atomizedNoGoods) { + for (NoGoodAtomizer atomizedNoGood : atomizedNoGoods) { noGoods.add(atomizedNoGood.deatomize(atomStore)); } return noGoods; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java similarity index 70% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java index 1d397fd29..2470a9ab6 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomizedNoGood.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java @@ -1,17 +1,17 @@ /** * Copyright (c) 2022, the Alpha Team. * All rights reserved. - * + *

* Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + *

* 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * + * list of conditions and the following disclaimer. + *

* 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver; +package at.ac.tuwien.kr.alpha.core.solver.reset; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; @@ -34,32 +34,34 @@ /** * A nogood independent of atom ids provided by an {@link AtomStore}. */ -public class AtomizedNoGood { - private final SimpleLiteral[] literals; +public class NoGoodAtomizer { + private final AtomValuePair[] literals; /** - * Initializes an {@link AtomizedNoGood} with the same literals as the given {@link NoGood}. + * Initializes a {@link NoGoodAtomizer} with the same literals as the given {@link NoGood}. * Atom ids are provided by the given {@link AtomStore}. - * @param noGood the {@link NoGood} to get the list of literals from. + * + * @param noGood the {@link NoGood} to get the list of literals from. * @param atomStore the {@link AtomStore} to get atom ids from. */ - public AtomizedNoGood(NoGood noGood, AtomStore atomStore) { - this.literals = new SimpleLiteral[noGood.size()]; + public NoGoodAtomizer(NoGood noGood, AtomStore atomStore) { + this.literals = new AtomValuePair[noGood.size()]; for (int i = 0; i < noGood.size(); i++) { int literalId = noGood.getLiteral(i); int atomId = Literals.atomOf(literalId); Atom atom = atomStore.get(atomId); boolean truthValue = Literals.isPositive(literalId); - this.literals[i] = new SimpleLiteral(atom, truthValue); + this.literals[i] = new AtomValuePair(atom, truthValue); } } /** - * Creates a new {@link NoGood} with the same literals as this {@link AtomizedNoGood}. + * Creates a new {@link NoGood} with the same literals as this {@link NoGoodAtomizer}. * Atom ids are provided by the given {@link AtomStore}. + * * @param atomStore the {@link AtomStore} to get atom ids from. - * @return the newly created {@link NoGood} with the same literals as this {@link AtomizedNoGood}. + * @return the newly created {@link NoGood} with the same literals as this {@link NoGoodAtomizer}. */ public NoGood deatomize(AtomStore atomStore) { int[] literals = new int[this.literals.length]; @@ -74,22 +76,4 @@ public NoGood deatomize(AtomStore atomStore) { return new NoGood(literals); } - - private static class SimpleLiteral { - private final Atom atom; - private final boolean truthValue; - - public SimpleLiteral(Atom atom, boolean truthValue) { - this.atom = atom; - this.truthValue = truthValue; - } - - public Atom getAtom() { - return atom; - } - - public boolean isPositive() { - return truthValue; - } - } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java index a0e910abb..72807a35e 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java @@ -59,7 +59,7 @@ public void checkStatsStringZeroChoices(RegressionTestConfig cfg) { @RegressionTest public void checkStatsStringOneChoice(RegressionTestConfig cfg) { - ignoreTestForRestartsEnabled(cfg); + ignoreTestForRestartsEnabled(cfg); // Do not run this test case with restarts enabled. Solver solver = buildSolverForRegressionTest("a :- not b. b :- not a.", cfg); assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckStats(solver, 2, 1, 1, 1, 1, 0, 0, 0); diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java new file mode 100644 index 000000000..92df69aba --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java @@ -0,0 +1,255 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reset; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Provides test cases for creating nogoods and checking correctness + * of the atom id translation performed by a {@link AtomizedNoGoodCollection}. + */ +class AtomizedNoGoodCollectionTest { + AtomStore atomStore; + TestAtomGenerator atomGenerator; + + public AtomizedNoGoodCollectionTest() { + atomStore = new AtomStoreImpl(); + atomGenerator = new TestAtomGenerator(atomStore); + } + + @BeforeEach + public void setUp() { + atomStore = new AtomStoreImpl(); + atomGenerator = new TestAtomGenerator(atomStore); + } + + + /** + * Creates a nogood with a single literal + * and tests conversion correctness after change in the single atom id. + */ + @Test + void oneSingleLiteralNoGood() { + atomGenerator.generateAndRegisterFillerAtoms(1); + List literals = Collections.singletonList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST_", 0), true) + ); + int[] literalIds = atomGenerator.getLiteralIds(literals); + NoGood noGood = new NoGood(literalIds); + + AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); + atomizedCollection.add(noGood); + + atomStore.reset(); + atomStore.putIfAbsent(literals.get(0).getAtom()); + extractAndCheckNoGoods(Collections.singletonList(literals), atomizedCollection); + } + + /** + * Creates two nogoods with a single literal + * and tests conversion correctness after change in an atom id of one of them. + */ + @Test + void twoSingleLiteralNoGoodsChangeIdForOne() { + atomGenerator.generateAndRegisterFillerAtoms(2); + List noGood1 = Collections.singletonList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), false) + ); + List noGood2 = Collections.singletonList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 2), true) + ); + + AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); + List> noGoods = Arrays.asList(noGood1, noGood2); + addAtomizedNoGoods(atomizedCollection, noGoods); + + atomStore.reset(); + atomGenerator.generateAndRegisterFillerAtoms(2); + atomStore.putIfAbsent(noGood1.get(0).getAtom()); + atomGenerator.generateAndRegisterFillerAtoms(2, 2); + atomStore.putIfAbsent(noGood2.get(0).getAtom()); + extractAndCheckNoGoods(noGoods, atomizedCollection); + } + + + /** + * Creates a nogood with multiple literals + * and tests conversion correctness after change in all atom ids. + */ + @Test + void oneMultiLiteralNoGoodChangeAllIds() { + + } + + /** + * Creates a nogood with multiple literals + * and tests conversion correctness after change in a single atom id. + */ + @Test + void oneMultiLiteralNoGoodChangeSingleId() { + atomGenerator.generateAndRegisterFillerAtoms(1); + List noGood = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), true), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 2), false) + ); + + AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); + List> noGoods = Collections.singletonList(noGood); + addAtomizedNoGoods(atomizedCollection, noGoods); + + atomStore.reset(); + atomStore.putIfAbsent(noGood.get(0).getAtom()); + atomStore.putIfAbsent(noGood.get(1).getAtom()); + extractAndCheckNoGoods(noGoods, atomizedCollection); + } + + /** + * Creates two nogoods with multiple literals + * and tests conversion correctness after change in a single atom id. + */ + @Test + void twoMultiLiteralNoGoodsChangeSingleId() { + atomGenerator.generateAndRegisterFillerAtoms(2); + List noGood1 = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), false), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), false) + ); + List noGood2 = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST3_", 2), true), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST4_", 1), false) + ); + + AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); + List> noGoods = Arrays.asList(noGood1, noGood2); + addAtomizedNoGoods(atomizedCollection, noGoods); + + atomStore.reset(); + atomGenerator.generateAndRegisterFillerAtoms(2); + atomStore.putIfAbsent(noGood1.get(0).getAtom()); + atomStore.putIfAbsent(noGood1.get(1).getAtom()); + atomStore.putIfAbsent(noGood2.get(0).getAtom()); + atomGenerator.generateAndRegisterFillerAtoms(2, 2); + atomStore.putIfAbsent(noGood2.get(1).getAtom()); + extractAndCheckNoGoods(noGoods, atomizedCollection); + } + + /** + * Creates two nogoods with multiple literals + * and tests conversion correctness after change in all atom ids. + */ + @Test + void twoMultiLiteralNoGoodsChangeAllIds() { + atomGenerator.generateAndRegisterFillerAtoms(2); + List noGood1 = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), false), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), true) + ); + List noGood2 = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST3_", 2), true), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST4_", 1), true) + ); + + AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); + List> noGoods = Arrays.asList(noGood1, noGood2); + addAtomizedNoGoods(atomizedCollection, noGoods); + + atomStore.reset(); + atomStore.putIfAbsent(noGood1.get(0).getAtom()); + atomStore.putIfAbsent(noGood1.get(1).getAtom()); + atomStore.putIfAbsent(noGood2.get(0).getAtom()); + atomStore.putIfAbsent(noGood2.get(1).getAtom()); + extractAndCheckNoGoods(noGoods, atomizedCollection); + } + + /** + * Extracts the {@link NoGood}s from a given {@link AtomizedNoGoodCollection} and asserts that the literals + * in these {@link NoGood}s are the same as the literals in the given literal lists. + * + * @param noGoods the lists of literals where each nogood is represented by a list that contains pairs + * of atom and truth value. + * @param atomizedCollection the {@link AtomizedNoGoodCollection} to extract the {@link NoGood}s from. + */ + private void extractAndCheckNoGoods(List> noGoods, + AtomizedNoGoodCollection atomizedCollection) { + List noGoodsExtracted = atomizedCollection.getNoGoods(); + assertEquals(noGoods.size(), noGoodsExtracted.size()); + + for (int i = 0; i < noGoods.size(); i++) { + List literals = noGoods.get(i); + NoGood noGoodExtracted = noGoodsExtracted.get(i); + checkNoGood(literals, noGoodExtracted); + } + } + + /** + * Asserts that the literals in the given {@link NoGood} are the same as the given literals. + * + * @param literals the literals to compare to represented as pairs of atom and truth value. + * @param noGood the given {@link NoGood} to check the literals of. + */ + private void checkNoGood(List literals, NoGood noGood) { + assertEquals(literals.size(), noGood.size()); + + for (int i = 0; i < literals.size(); i++) { + AtomValuePair literal = literals.get(i); + int literalExtractedId = noGood.getLiteral(i); + + Atom atomExtracted = atomStore.get(Literals.atomOf(literalExtractedId)); + assertEquals(literal.getAtom(), atomExtracted); + + boolean truthValueExtracted = Literals.isPositive(literalExtractedId); + assertEquals(literal.isPositive(), truthValueExtracted); + } + } + + /** + * Adds the given nogoods to the given {@link AtomizedNoGoodCollection}. + * + * @param atomizedCollection the {@link AtomizedNoGoodCollection} to add to. + * @param noGoods the nogoods to add to the collection. Each nogood is represented by a list that contains pairs + * of atom and truth value. + */ + private void addAtomizedNoGoods(AtomizedNoGoodCollection atomizedCollection, + List> noGoods) { + for (List literals : noGoods) { + int[] literalIds = atomGenerator.getLiteralIds(literals); + NoGood noGood = new NoGood(literalIds); + atomizedCollection.add(noGood); + } + } +} \ No newline at end of file diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java new file mode 100644 index 000000000..3d1273137 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reset; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Provides test cases for creating nogoods and checking correctness + * of the atom id translation performed by a {@link NoGoodAtomizer}. + */ +class NoGoodAtomizerTest { + AtomStore atomStore; + TestAtomGenerator atomGenerator; + + public NoGoodAtomizerTest() { + atomStore = new AtomStoreImpl(); + atomGenerator = new TestAtomGenerator(atomStore); + } + + @BeforeEach + public void setUp() { + atomStore = new AtomStoreImpl(); + atomGenerator = new TestAtomGenerator(atomStore); + } + + /** + * Registers multiple atoms at the {@link AtomStore} and resets the {@link AtomStore}. + * Then registers the same atoms in the same order again and checks whether all of them receive + * the same id as before. + */ + @Test + void sameAtomIdsAfterAtomStoreReset() { + int ATOM_COUNT = 6; + + List atoms = new ArrayList<>(); + List atomIds = new ArrayList<>(); + for (int i = 0; i < ATOM_COUNT; i++) { + Atom atom = atomGenerator.generateAndRegisterAtom(String.format("_TEST%d_", i), 0); + atoms.add(atom); + atomIds.add(atomStore.get(atom)); + } + + atomStore.reset(); + for (int i = 0; i < ATOM_COUNT; i++) { + Atom atom = atoms.get(i); + atomStore.putIfAbsent(atom); + assertEquals(atomIds.get(i), atomStore.get(atom)); + } + } + + /** + * Creates a nogood with a single literal + * and tests conversion correctness after change in atom id. + */ + @Test + void singleLiteralNoGood() { + List literals = Collections.singletonList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST_", 0), false) + ); + int[] literalIds = atomGenerator.getLiteralIds(literals); + NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); + + atomStore.reset(); + atomGenerator.generateAndRegisterFillerAtoms(1); + atomStore.putIfAbsent(literals.get(0).getAtom()); + extractAndCheckLiterals(literals, noGoodAtomizer); + } + + /** + * Creates a nogood with a single literal of arity > 0 + * and tests conversion correctness after change in atom id. + */ + @Test + void singleTwoTermLiteralNoGood() { + atomGenerator.generateAndRegisterFillerAtoms(1); + List literals = Collections.singletonList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST_", 2), true) + ); + int[] literalIds = atomGenerator.getLiteralIds(literals); + NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); + + atomStore.reset(); + atomStore.putIfAbsent(literals.get(0).getAtom()); + extractAndCheckLiterals(literals, noGoodAtomizer); + } + + /** + * Creates a nogood with multiple literals + * and tests conversion correctness after change in a single atom id. + */ + @Test + void multiLiteralNoGoodChangeSingleId() { + atomGenerator.generateAndRegisterFillerAtoms(2); + List literals = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), true), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), false) + ); + int[] literalIds = atomGenerator.getLiteralIds(literals); + NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); + + atomStore.reset(); + atomGenerator.generateAndRegisterFillerAtoms(2); + atomStore.putIfAbsent(literals.get(0).getAtom()); + atomGenerator.generateAndRegisterFillerAtoms(2, 2); + atomStore.putIfAbsent(literals.get(1).getAtom()); + extractAndCheckLiterals(literals, noGoodAtomizer); + } + + /** + * Creates a nogood with multiple literals + * and tests conversion correctness after change in all atom ids. + */ + @Test + void multiLiteralNoGoodChangeAllIds() { + atomGenerator.generateAndRegisterFillerAtoms(2); + List literals = Arrays.asList( + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), true), + new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), false) + ); + int[] literalIds = atomGenerator.getLiteralIds(literals); + NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); + + atomStore.reset(); + atomStore.putIfAbsent(literals.get(0).getAtom()); + atomStore.putIfAbsent(literals.get(1).getAtom()); + extractAndCheckLiterals(literals, noGoodAtomizer); + } + + /** + * Extracts the {@link NoGood} from a given {@link NoGoodAtomizer} and asserts that the literals in this + * {@link NoGood} are the same as the given literals. + * + * @param literals a list of literals where each literal is represented by a pair of atom and truth value. + * @param noGoodAtomizer the {@link NoGoodAtomizer} to extract the {@link NoGood} from. + */ + private void extractAndCheckLiterals(List literals, NoGoodAtomizer noGoodAtomizer) { + NoGood noGood = noGoodAtomizer.deatomize(atomStore); + assertEquals(literals.size(), noGood.size()); + + for (int i = 0; i < literals.size(); i++) { + AtomValuePair literal = literals.get(i); + int literalExtractedId = noGood.getLiteral(i); + + Atom atomExtracted = atomStore.get(Literals.atomOf(literalExtractedId)); + assertEquals(literal.getAtom(), atomExtracted); + + boolean truthValueExtracted = Literals.isPositive(literalExtractedId); + assertEquals(literal.isPositive(), truthValueExtracted); + } + } +} \ No newline at end of file diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java new file mode 100644 index 000000000..ae4fa6953 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reset; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Provides utility methods to generate atoms and register them at an {@link AtomStore}. + */ +public class TestAtomGenerator { + private final AtomStore atomStore; + + public TestAtomGenerator(AtomStore atomStore) { + this.atomStore = atomStore; + } + + /** + * Maps a given list of literals to literal ids based on the current {@link AtomStore}. + * + * @param literals the list of literals where each literal is represented by a pair of atom and truth value. + * @return the list of ids for the given literals based on the current {@link AtomStore}. + */ + public int[] getLiteralIds(List literals) { + int[] literalIds = new int[literals.size()]; + + int position = 0; + for (AtomValuePair literal : literals) { + literalIds[position] = Literals.atomToLiteral(atomStore.get(literal.getAtom()), literal.isPositive()); + position++; + } + + return literalIds; + } + + /** + * Generates a given number of new filler atoms and registers them at the current {@link AtomStore}. + * + * @param count the number of filler atoms to generate and register. + */ + public void generateAndRegisterFillerAtoms(int count) { + generateAndRegisterFillerAtoms(count, 0); + } + + /** + * Generates a given number of new filler atoms and registers them at the current {@link AtomStore}. + * Filler atoms are generated under the assumption that a given number of filler atoms were already generated. + * + * @param count the number of filler atoms to generate and register. + * @param existing the number of filler atoms already generated before. + */ + public void generateAndRegisterFillerAtoms(int count, int existing) { + for (int i = existing; i < existing + count; i++) { + generateAndRegisterAtom(String.format("_FILL%d_", i), 0); + } + } + + /** + * Generates a new {@link Atom} with a given predicate symbol and arity. + * The generated {@link Atom} is then registered at the current {@link AtomStore}. + * Constant terms starting from 1 up to the arity are used. + * + * @param symbol the predicate symbol of the {@link Atom} to generate. + * @param arity the arity of the atom to generate. + * @return the generated {@link Atom}. + */ + public Atom generateAndRegisterAtom(String symbol, int arity) { + Predicate predicate = Predicates.getPredicate(symbol, arity); + + Atom atom; + if (arity == 0) { + atom = Atoms.newBasicAtom(predicate); + } else { + List terms = IntStream.iterate(1, x -> x + 1).limit(arity) + .mapToObj(Integer::toString) + .map(Terms::newConstant) + .collect(Collectors.toList()); + atom = Atoms.newBasicAtom(predicate, terms); + } + + atomStore.putIfAbsent(atom); + return atom; + } +} From 9abb63eaba8d6eb75fc621d36e4021577e7b9e52 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 2 Sep 2022 19:29:32 +0200 Subject: [PATCH 17/53] Fix imports and code style --- .../at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 2 ++ .../tuwien/kr/alpha/core/solver/reset/AtomValuePair.java | 9 --------- .../kr/alpha/core/solver/reset/NoGoodAtomizerTest.java | 6 +++--- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 6c473776f..d1855310f 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -40,6 +40,8 @@ import java.util.function.Consumer; import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.reset.AtomizedChoice; +import at.ac.tuwien.kr.alpha.core.solver.reset.AtomizedNoGoodCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java index e754399ab..18a7c13d9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java @@ -43,13 +43,4 @@ public Atom getAtom() { public boolean isPositive() { return truthValue; } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof AtomValuePair)) { - return false; - } - AtomValuePair other = (AtomValuePair) obj; - return atom.compareTo(other.atom) == 0 && truthValue == other.isPositive(); - } } \ No newline at end of file diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java index 3d1273137..855260411 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java @@ -66,18 +66,18 @@ public void setUp() { */ @Test void sameAtomIdsAfterAtomStoreReset() { - int ATOM_COUNT = 6; + int atomCount = 6; List atoms = new ArrayList<>(); List atomIds = new ArrayList<>(); - for (int i = 0; i < ATOM_COUNT; i++) { + for (int i = 0; i < atomCount; i++) { Atom atom = atomGenerator.generateAndRegisterAtom(String.format("_TEST%d_", i), 0); atoms.add(atom); atomIds.add(atomStore.get(atom)); } atomStore.reset(); - for (int i = 0; i < ATOM_COUNT; i++) { + for (int i = 0; i < atomCount; i++) { Atom atom = atoms.get(i); atomStore.putIfAbsent(atom); assertEquals(atomIds.get(i), atomStore.get(atom)); From a5329f47e669efc632b403bf3f5d2f4f709d1916 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 6 Sep 2022 17:15:45 +0200 Subject: [PATCH 18/53] Refactor unit tests for atomized structures --- ...erator.java => AtomGeneratorForTests.java} | 38 ++++---- .../reset/AtomizedNoGoodCollectionTest.java | 94 +++++++++---------- .../core/solver/reset/NoGoodAtomizerTest.java | 47 +++++----- 3 files changed, 87 insertions(+), 92 deletions(-) rename alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/{TestAtomGenerator.java => AtomGeneratorForTests.java} (71%) diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomGeneratorForTests.java similarity index 71% rename from alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomGeneratorForTests.java index ae4fa6953..37a9e86f5 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/TestAtomGenerator.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomGeneratorForTests.java @@ -41,20 +41,15 @@ /** * Provides utility methods to generate atoms and register them at an {@link AtomStore}. */ -public class TestAtomGenerator { - private final AtomStore atomStore; - - public TestAtomGenerator(AtomStore atomStore) { - this.atomStore = atomStore; - } - +public class AtomGeneratorForTests { /** - * Maps a given list of literals to literal ids based on the current {@link AtomStore}. + * Maps a given list of literals to literal ids based on a given {@link AtomStore}. * - * @param literals the list of literals where each literal is represented by a pair of atom and truth value. + * @param literals the list of literals where each literal is represented by a pair of atom and truth value. + * @param atomStore the {@link AtomStore} to use for converting atom ids. * @return the list of ids for the given literals based on the current {@link AtomStore}. */ - public int[] getLiteralIds(List literals) { + public static int[] getLiteralIds(List literals, AtomStore atomStore) { int[] literalIds = new int[literals.size()]; int position = 0; @@ -69,22 +64,24 @@ public int[] getLiteralIds(List literals) { /** * Generates a given number of new filler atoms and registers them at the current {@link AtomStore}. * - * @param count the number of filler atoms to generate and register. + * @param count the number of filler atoms to generate and register. + * @param atomStore the {@link AtomStore} to use for converting atom ids. */ - public void generateAndRegisterFillerAtoms(int count) { - generateAndRegisterFillerAtoms(count, 0); + public static void generateAndRegisterFillerAtoms(int count, AtomStore atomStore) { + generateAndRegisterFillerAtoms(count, 0, atomStore); } /** * Generates a given number of new filler atoms and registers them at the current {@link AtomStore}. * Filler atoms are generated under the assumption that a given number of filler atoms were already generated. * - * @param count the number of filler atoms to generate and register. - * @param existing the number of filler atoms already generated before. + * @param count the number of filler atoms to generate and register. + * @param existing the number of filler atoms already generated before. + * @param atomStore the {@link AtomStore} to use for converting atom ids. */ - public void generateAndRegisterFillerAtoms(int count, int existing) { + public static void generateAndRegisterFillerAtoms(int count, int existing, AtomStore atomStore) { for (int i = existing; i < existing + count; i++) { - generateAndRegisterAtom(String.format("_FILL%d_", i), 0); + generateAndRegisterAtom(String.format("_FILL%d_", i), 0, atomStore); } } @@ -93,11 +90,12 @@ public void generateAndRegisterFillerAtoms(int count, int existing) { * The generated {@link Atom} is then registered at the current {@link AtomStore}. * Constant terms starting from 1 up to the arity are used. * - * @param symbol the predicate symbol of the {@link Atom} to generate. - * @param arity the arity of the atom to generate. + * @param symbol the predicate symbol of the {@link Atom} to generate. + * @param arity the arity of the atom to generate. + * @param atomStore the {@link AtomStore} to use for converting atom ids. * @return the generated {@link Atom}. */ - public Atom generateAndRegisterAtom(String symbol, int arity) { + public static Atom generateAndRegisterAtom(String symbol, int arity, AtomStore atomStore) { Predicate predicate = Predicates.getPredicate(symbol, arity); Atom atom; diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java index 92df69aba..6b2b53b4f 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java @@ -45,17 +45,17 @@ */ class AtomizedNoGoodCollectionTest { AtomStore atomStore; - TestAtomGenerator atomGenerator; + AtomGeneratorForTests atomGenerator; public AtomizedNoGoodCollectionTest() { atomStore = new AtomStoreImpl(); - atomGenerator = new TestAtomGenerator(atomStore); + atomGenerator = new AtomGeneratorForTests(); } @BeforeEach public void setUp() { atomStore = new AtomStoreImpl(); - atomGenerator = new TestAtomGenerator(atomStore); + atomGenerator = new AtomGeneratorForTests(); } @@ -64,12 +64,12 @@ public void setUp() { * and tests conversion correctness after change in the single atom id. */ @Test - void oneSingleLiteralNoGood() { - atomGenerator.generateAndRegisterFillerAtoms(1); + void testOneSingleLiteralNoGood() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(1, atomStore); List literals = Collections.singletonList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST_", 0), true) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST_", 0, atomStore), true) ); - int[] literalIds = atomGenerator.getLiteralIds(literals); + int[] literalIds = AtomGeneratorForTests.getLiteralIds(literals, atomStore); NoGood noGood = new NoGood(literalIds); AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); @@ -77,7 +77,7 @@ void oneSingleLiteralNoGood() { atomStore.reset(); atomStore.putIfAbsent(literals.get(0).getAtom()); - extractAndCheckNoGoods(Collections.singletonList(literals), atomizedCollection); + extractAndCheckNoGoods(Collections.singletonList(literals), atomizedCollection, atomStore); } /** @@ -85,25 +85,25 @@ void oneSingleLiteralNoGood() { * and tests conversion correctness after change in an atom id of one of them. */ @Test - void twoSingleLiteralNoGoodsChangeIdForOne() { - atomGenerator.generateAndRegisterFillerAtoms(2); + void testTwoSingleLiteralNoGoodsChangeIdForOne() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); List noGood1 = Collections.singletonList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST1_", 0, atomStore), false) ); List noGood2 = Collections.singletonList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 2), true) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST2_", 2, atomStore), true) ); AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); List> noGoods = Arrays.asList(noGood1, noGood2); - addAtomizedNoGoods(atomizedCollection, noGoods); + addAtomizedNoGoods(atomizedCollection, noGoods, atomStore); atomStore.reset(); - atomGenerator.generateAndRegisterFillerAtoms(2); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); atomStore.putIfAbsent(noGood1.get(0).getAtom()); - atomGenerator.generateAndRegisterFillerAtoms(2, 2); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, 2, atomStore); atomStore.putIfAbsent(noGood2.get(0).getAtom()); - extractAndCheckNoGoods(noGoods, atomizedCollection); + extractAndCheckNoGoods(noGoods, atomizedCollection, atomStore); } @@ -112,7 +112,7 @@ void twoSingleLiteralNoGoodsChangeIdForOne() { * and tests conversion correctness after change in all atom ids. */ @Test - void oneMultiLiteralNoGoodChangeAllIds() { + void testOneMultiLiteralNoGoodChangeAllIds() { } @@ -121,21 +121,21 @@ void oneMultiLiteralNoGoodChangeAllIds() { * and tests conversion correctness after change in a single atom id. */ @Test - void oneMultiLiteralNoGoodChangeSingleId() { - atomGenerator.generateAndRegisterFillerAtoms(1); + void testOneMultiLiteralNoGoodChangeSingleId() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(1, atomStore); List noGood = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), true), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 2), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST1_", 0, atomStore), true), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST2_", 2, atomStore), false) ); AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); List> noGoods = Collections.singletonList(noGood); - addAtomizedNoGoods(atomizedCollection, noGoods); + addAtomizedNoGoods(atomizedCollection, noGoods, atomStore); atomStore.reset(); atomStore.putIfAbsent(noGood.get(0).getAtom()); atomStore.putIfAbsent(noGood.get(1).getAtom()); - extractAndCheckNoGoods(noGoods, atomizedCollection); + extractAndCheckNoGoods(noGoods, atomizedCollection, atomStore); } /** @@ -143,29 +143,29 @@ void oneMultiLiteralNoGoodChangeSingleId() { * and tests conversion correctness after change in a single atom id. */ @Test - void twoMultiLiteralNoGoodsChangeSingleId() { - atomGenerator.generateAndRegisterFillerAtoms(2); + void testTwoMultiLiteralNoGoodsChangeSingleId() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); List noGood1 = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), false), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST1_", 0, atomStore), false), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST2_", 0, atomStore), false) ); List noGood2 = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST3_", 2), true), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST4_", 1), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST3_", 2, atomStore), true), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST4_", 1, atomStore), false) ); AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); List> noGoods = Arrays.asList(noGood1, noGood2); - addAtomizedNoGoods(atomizedCollection, noGoods); + addAtomizedNoGoods(atomizedCollection, noGoods, atomStore); atomStore.reset(); - atomGenerator.generateAndRegisterFillerAtoms(2); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); atomStore.putIfAbsent(noGood1.get(0).getAtom()); atomStore.putIfAbsent(noGood1.get(1).getAtom()); atomStore.putIfAbsent(noGood2.get(0).getAtom()); - atomGenerator.generateAndRegisterFillerAtoms(2, 2); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, 2, atomStore); atomStore.putIfAbsent(noGood2.get(1).getAtom()); - extractAndCheckNoGoods(noGoods, atomizedCollection); + extractAndCheckNoGoods(noGoods, atomizedCollection, atomStore); } /** @@ -173,27 +173,27 @@ void twoMultiLiteralNoGoodsChangeSingleId() { * and tests conversion correctness after change in all atom ids. */ @Test - void twoMultiLiteralNoGoodsChangeAllIds() { - atomGenerator.generateAndRegisterFillerAtoms(2); + void testTwoMultiLiteralNoGoodsChangeAllIds() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); List noGood1 = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), false), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), true) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST1_", 0, atomStore), false), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST2_", 0, atomStore), true) ); List noGood2 = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST3_", 2), true), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST4_", 1), true) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST3_", 2, atomStore), true), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST4_", 1, atomStore), true) ); AtomizedNoGoodCollection atomizedCollection = new AtomizedNoGoodCollection(atomStore); List> noGoods = Arrays.asList(noGood1, noGood2); - addAtomizedNoGoods(atomizedCollection, noGoods); + addAtomizedNoGoods(atomizedCollection, noGoods, atomStore); atomStore.reset(); atomStore.putIfAbsent(noGood1.get(0).getAtom()); atomStore.putIfAbsent(noGood1.get(1).getAtom()); atomStore.putIfAbsent(noGood2.get(0).getAtom()); atomStore.putIfAbsent(noGood2.get(1).getAtom()); - extractAndCheckNoGoods(noGoods, atomizedCollection); + extractAndCheckNoGoods(noGoods, atomizedCollection, atomStore); } /** @@ -204,15 +204,15 @@ void twoMultiLiteralNoGoodsChangeAllIds() { * of atom and truth value. * @param atomizedCollection the {@link AtomizedNoGoodCollection} to extract the {@link NoGood}s from. */ - private void extractAndCheckNoGoods(List> noGoods, - AtomizedNoGoodCollection atomizedCollection) { + private void extractAndCheckNoGoods(List> noGoods, AtomizedNoGoodCollection atomizedCollection, + AtomStore atomStore) { List noGoodsExtracted = atomizedCollection.getNoGoods(); assertEquals(noGoods.size(), noGoodsExtracted.size()); for (int i = 0; i < noGoods.size(); i++) { List literals = noGoods.get(i); NoGood noGoodExtracted = noGoodsExtracted.get(i); - checkNoGood(literals, noGoodExtracted); + checkNoGood(literals, noGoodExtracted, atomStore); } } @@ -222,7 +222,7 @@ private void extractAndCheckNoGoods(List> noGoods, * @param literals the literals to compare to represented as pairs of atom and truth value. * @param noGood the given {@link NoGood} to check the literals of. */ - private void checkNoGood(List literals, NoGood noGood) { + private void checkNoGood(List literals, NoGood noGood, AtomStore atomStore) { assertEquals(literals.size(), noGood.size()); for (int i = 0; i < literals.size(); i++) { @@ -245,9 +245,9 @@ private void checkNoGood(List literals, NoGood noGood) { * of atom and truth value. */ private void addAtomizedNoGoods(AtomizedNoGoodCollection atomizedCollection, - List> noGoods) { + List> noGoods, AtomStore atomStore) { for (List literals : noGoods) { - int[] literalIds = atomGenerator.getLiteralIds(literals); + int[] literalIds = AtomGeneratorForTests.getLiteralIds(literals, atomStore); NoGood noGood = new NoGood(literalIds); atomizedCollection.add(noGood); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java index 855260411..7070afdca 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java @@ -46,17 +46,14 @@ */ class NoGoodAtomizerTest { AtomStore atomStore; - TestAtomGenerator atomGenerator; public NoGoodAtomizerTest() { atomStore = new AtomStoreImpl(); - atomGenerator = new TestAtomGenerator(atomStore); } @BeforeEach public void setUp() { atomStore = new AtomStoreImpl(); - atomGenerator = new TestAtomGenerator(atomStore); } /** @@ -65,13 +62,13 @@ public void setUp() { * the same id as before. */ @Test - void sameAtomIdsAfterAtomStoreReset() { + void testSameAtomIdsAfterAtomStoreReset() { int atomCount = 6; List atoms = new ArrayList<>(); List atomIds = new ArrayList<>(); for (int i = 0; i < atomCount; i++) { - Atom atom = atomGenerator.generateAndRegisterAtom(String.format("_TEST%d_", i), 0); + Atom atom = AtomGeneratorForTests.generateAndRegisterAtom(String.format("_TEST%d_", i), 0, atomStore); atoms.add(atom); atomIds.add(atomStore.get(atom)); } @@ -89,15 +86,15 @@ void sameAtomIdsAfterAtomStoreReset() { * and tests conversion correctness after change in atom id. */ @Test - void singleLiteralNoGood() { + void testSingleLiteralNoGood() { List literals = Collections.singletonList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST_", 0), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST_", 0, atomStore), false) ); - int[] literalIds = atomGenerator.getLiteralIds(literals); + int[] literalIds = AtomGeneratorForTests.getLiteralIds(literals, atomStore); NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); atomStore.reset(); - atomGenerator.generateAndRegisterFillerAtoms(1); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(1, atomStore); atomStore.putIfAbsent(literals.get(0).getAtom()); extractAndCheckLiterals(literals, noGoodAtomizer); } @@ -107,12 +104,12 @@ void singleLiteralNoGood() { * and tests conversion correctness after change in atom id. */ @Test - void singleTwoTermLiteralNoGood() { - atomGenerator.generateAndRegisterFillerAtoms(1); + void testSingleTwoTermLiteralNoGood() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(1, atomStore); List literals = Collections.singletonList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST_", 2), true) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST_", 2, atomStore), true) ); - int[] literalIds = atomGenerator.getLiteralIds(literals); + int[] literalIds = AtomGeneratorForTests.getLiteralIds(literals, atomStore); NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); atomStore.reset(); @@ -125,19 +122,19 @@ void singleTwoTermLiteralNoGood() { * and tests conversion correctness after change in a single atom id. */ @Test - void multiLiteralNoGoodChangeSingleId() { - atomGenerator.generateAndRegisterFillerAtoms(2); + void testMultiLiteralNoGoodChangeSingleId() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); List literals = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), true), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST2_", 0, atomStore), false), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST1_", 0, atomStore), true) ); - int[] literalIds = atomGenerator.getLiteralIds(literals); + int[] literalIds = AtomGeneratorForTests.getLiteralIds(literals, atomStore); NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); atomStore.reset(); - atomGenerator.generateAndRegisterFillerAtoms(2); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); atomStore.putIfAbsent(literals.get(0).getAtom()); - atomGenerator.generateAndRegisterFillerAtoms(2, 2); + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, 2, atomStore); atomStore.putIfAbsent(literals.get(1).getAtom()); extractAndCheckLiterals(literals, noGoodAtomizer); } @@ -147,13 +144,13 @@ void multiLiteralNoGoodChangeSingleId() { * and tests conversion correctness after change in all atom ids. */ @Test - void multiLiteralNoGoodChangeAllIds() { - atomGenerator.generateAndRegisterFillerAtoms(2); + void testMultiLiteralNoGoodChangeAllIds() { + AtomGeneratorForTests.generateAndRegisterFillerAtoms(2, atomStore); List literals = Arrays.asList( - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST1_", 0), true), - new AtomValuePair(atomGenerator.generateAndRegisterAtom("_TEST2_", 0), false) + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST1_", 0, atomStore), true), + new AtomValuePair(AtomGeneratorForTests.generateAndRegisterAtom("_TEST2_", 0, atomStore), false) ); - int[] literalIds = atomGenerator.getLiteralIds(literals); + int[] literalIds = AtomGeneratorForTests.getLiteralIds(literals, atomStore); NoGoodAtomizer noGoodAtomizer = new NoGoodAtomizer(new NoGood(literalIds), atomStore); atomStore.reset(); From de9182739b1260936385dc086f22f230e1906823 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 20 Sep 2022 16:00:38 +0200 Subject: [PATCH 19/53] Add nogood type to atomized nogoods --- .../ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java index 2470a9ab6..12d33c965 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java @@ -30,12 +30,14 @@ import at.ac.tuwien.kr.alpha.core.atoms.Literals; import at.ac.tuwien.kr.alpha.core.common.AtomStore; import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type; /** * A nogood independent of atom ids provided by an {@link AtomStore}. */ public class NoGoodAtomizer { private final AtomValuePair[] literals; + private final Type type; /** * Initializes a {@link NoGoodAtomizer} with the same literals as the given {@link NoGood}. @@ -46,6 +48,7 @@ public class NoGoodAtomizer { */ public NoGoodAtomizer(NoGood noGood, AtomStore atomStore) { this.literals = new AtomValuePair[noGood.size()]; + this.type = noGood.getType(); for (int i = 0; i < noGood.size(); i++) { int literalId = noGood.getLiteral(i); int atomId = Literals.atomOf(literalId); @@ -74,6 +77,6 @@ public NoGood deatomize(AtomStore atomStore) { literals[i] = Literals.atomToLiteral(atomId, truthValue); } - return new NoGood(literals); + return new NoGood(type, literals); } } From 1e6b528e6601ff9e6b230dd9072453dc15fa6046 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 20 Sep 2022 21:44:02 +0200 Subject: [PATCH 20/53] Enable repeated restarts, keep learnt nogoods at restart --- .../java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index d1855310f..ba353d1a0 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -157,7 +157,6 @@ protected boolean tryAdvance(Consumer action) { syncWithGrounder(); } else if (restartsEnabled && iterationCounter >= restartIterationBreakpoint) { restart(); - restartsEnabled = false; iterationCounter = 0; } else if (choose()) { LOGGER.debug("Did choice."); @@ -313,6 +312,7 @@ private boolean learnBackjumpAddFromConflict(ConflictCause conflictCause) { choiceManager.backjump(analysisResult.backjumpLevel); final NoGood learnedNoGood = analysisResult.learnedNoGood; + enumerationNoGoods.add(learnedNoGood); int noGoodId = grounder.register(learnedNoGood); return addAndBackjumpIfNecessary(noGoodId, learnedNoGood, analysisResult.lbd); } From e91e1940206021c1efb9311815e7316c23334699 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 21 Sep 2022 17:01:42 +0200 Subject: [PATCH 21/53] Add runtime performance logging --- .../core/solver/CumulativeStopWatch.java | 24 +++++++++++++++++ .../kr/alpha/core/solver/DefaultSolver.java | 27 ++++++++++++++++--- .../core/solver/NoGoodStoreAlphaRoaming.java | 1 + .../kr/alpha/core/solver/PerformanceLog.java | 16 ++++++----- 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java new file mode 100644 index 000000000..1589fe3e6 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.kr.alpha.core.solver; + +public class CumulativeStopWatch { + private long startTime; + private long runtime; + private boolean running; + + public void start() { + if (!running) { + startTime = System.nanoTime(); + running = true; + } + } + + public void stop() { + long currentTime = System.nanoTime(); + runtime += (currentTime - startTime); + running = false; + } + + public long getRuntime() { + return runtime; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index ba353d1a0..1720dda35 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -103,6 +103,9 @@ private static class SearchState { private final PerformanceLog performanceLog; + private final CumulativeStopWatch solverStopWatch; + private final CumulativeStopWatch grounderStopWatch; + public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); @@ -115,10 +118,13 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.branchingHeuristic = chainFallbackHeuristic(grounder, assignment, random, heuristicsConfiguration); this.disableJustifications = config.isDisableJustificationSearch(); this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); - this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, 1000); + this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, + store.getNoGoodCounter(), 1000); this.restartsEnabled = config.isRestartsEnabled(); this.restartIterationBreakpoint = config.getRestartIterations(); this.iterationCounter = 0; + solverStopWatch = new CumulativeStopWatch(); + grounderStopWatch = new CumulativeStopWatch(); } private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAssignment assignment, Random random, HeuristicsConfiguration heuristicsConfiguration) { @@ -134,6 +140,7 @@ private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAss @Override protected boolean tryAdvance(Consumer action) { + solverStopWatch.start(); if (!searchState.hasBeenInitialized) { initializeSearch(); } else { @@ -146,6 +153,7 @@ protected boolean tryAdvance(Consumer action) { if (searchState.isSearchSpaceCompletelyExplored) { LOGGER.debug("Search space has been fully explored, there are no more answer-sets."); logStats(); + stopSolverWatchAndLogRuntimes(); return false; } ConflictCause conflictCause = propagate(); @@ -164,6 +172,7 @@ protected boolean tryAdvance(Consumer action) { LOGGER.debug("Closed unassigned known atoms (assigning FALSE)."); } else if (assignment.getMBTCount() == 0) { provideAnswerSet(action); + stopSolverWatchAndLogRuntimes(); return true; } else { backtrackFromMBTsRemaining(); @@ -216,7 +225,9 @@ private void prepareForSubsequentAnswerSet() { } private void getNoGoodsFromGrounderAndIngest() { + grounderStopWatch.start(); Map obtained = grounder.getNoGoods(assignment); + grounderStopWatch.stop(); if (!ingest(obtained)) { searchState.isSearchSpaceCompletelyExplored = true; } @@ -547,7 +558,7 @@ private boolean choose() { * assignment is reconstructed. */ private void restart() { - LOGGER.debug("Performing solver and grounder restart."); + LOGGER.info("Performing solver and grounder restart."); Stack atomizedChoiceStack = getAtomizedChoiceStack(); @@ -562,7 +573,7 @@ private void restart() { addEnumerationNoGoods(); replayAtomizedChoiceStack(atomizedChoiceStack); - LOGGER.debug("Solver and grounder restart finished."); + LOGGER.info("Solver and grounder restart finished."); } /** @@ -643,6 +654,16 @@ private void addEnumerationNoGoods() { } } + /** + * Stops the {@link DefaultSolver#solverStopWatch} and logs the current runtime + * of {@link DefaultSolver#solverStopWatch} and {@link DefaultSolver#grounderStopWatch}. + */ + private void stopSolverWatchAndLogRuntimes() { + solverStopWatch.stop(); + LOGGER.info("Solver runtime: {}", solverStopWatch.getRuntime()); + LOGGER.info("Grounder runtime: {}", grounderStopWatch.getRuntime()); + } + @Override public int getNumberOfChoices() { return choiceManager.getChoices(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index 0e1c7e30b..d92a1d27b 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -165,6 +165,7 @@ public void reset() { public void cleanupLearnedNoGoods() { if (learnedNoGoodDeletion.needToRunNoGoodDeletion()) { learnedNoGoodDeletion.runNoGoodDeletion(); + LOGGER.info("Nogood deletion performed."); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java index d9153e729..2f3810b4b 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java @@ -1,17 +1,17 @@ /** * Copyright (c) 2019 Siemens AG * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * 1) Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * 2) Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -34,8 +34,9 @@ public class PerformanceLog { private final ChoiceManager choiceManager; private final TrailAssignment assignment; + private final NoGoodCounter noGoodCounter; private final long msBetweenOutputs; - + private Long timeFirstEntry; private Long timeLastPerformanceLog; private int numberOfChoicesLastPerformanceLog; @@ -43,10 +44,12 @@ public class PerformanceLog { /** * @param msBetweenOutputs minimum number of milliseconds that have to pass between writing of performance logs. */ - public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, long msBetweenOutputs) { + public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, + NoGoodCounter noGoodCounter, long msBetweenOutputs) { super(); this.choiceManager = choiceManager; this.assignment = assignment; + this.noGoodCounter = noGoodCounter; this.msBetweenOutputs = msBetweenOutputs; } @@ -69,6 +72,7 @@ public void writeIfTimeForLogging(Logger logger) { float overallTime = (currentTime - timeFirstEntry) / 1000.0f; float decisionsPerSec = currentNumberOfChoices / overallTime; logger.info("Overall performance: {} decisions in {}s or {} decisions per sec. Overall replayed assignments: {}.", currentNumberOfChoices, overallTime, decisionsPerSec, assignment.replayCounter); + logger.info("Current nogood counts: {}", noGoodCounter.getStatsByType()); } } } \ No newline at end of file From b101c950c2df58a8dde6ca089778b298caa67992 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 21 Sep 2022 17:52:20 +0200 Subject: [PATCH 22/53] Rename solver and grounder restart to reboot, fix reboot tests --- .../kr/alpha/api/config/SystemConfig.java | 34 ++++++---- .../alpha/app/config/CommandLineParser.java | 33 ++++++---- .../kr/alpha/core/grounder/Grounder.java | 4 +- .../kr/alpha/core/grounder/NaiveGrounder.java | 2 +- .../core/solver/CumulativeStopWatch.java | 24 ------- .../kr/alpha/core/solver/DefaultSolver.java | 45 ++++++++------ .../kr/alpha/core/solver/PerformanceLog.java | 3 +- .../kr/alpha/core/solver/StopWatch.java | 62 +++++++++++++++++++ .../alpha/core/grounder/ChoiceGrounder.java | 2 +- .../kr/alpha/core/grounder/DummyGrounder.java | 2 +- .../core/solver/RegressionTestConfig.java | 41 ++++++------ .../solver/RegressionTestConfigProvider.java | 44 +++++++------ .../core/solver/SolverStatisticsTests.java | 4 +- .../kr/alpha/core/solver/SolverTests.java | 4 +- .../kr/alpha/core/test/util/TestUtils.java | 4 +- 15 files changed, 189 insertions(+), 119 deletions(-) delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index c93409ca0..e9163d78c 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -49,8 +49,9 @@ public class SystemConfig { public static final String DEFAULT_NOGOOD_STORE_NAME = "alphaRoaming"; public static final Heuristic DEFAULT_BRANCHING_HEURISTIC = Heuristic.VSIDS; public static final BinaryNoGoodPropagationEstimationStrategy DEFAULT_MOMS_STRATEGY = BinaryNoGoodPropagationEstimationStrategy.CountBinaryWatches; - public static final boolean DEFAULT_RESTARTS_ENABLED = false; - public static final int DEFAULT_RESTART_ITERATIONS = 10000; + public static final boolean DEFAULT_REBOOT_ENABLED = false; + public static final int DEFAULT_REBOOT_ITERATIONS = 10000; + public static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = false; public static final long DEFAULT_SEED = System.nanoTime(); public static final boolean DEFAULT_DETERMINISTIC = false; public static final boolean DEFAULT_PRINT_STATS = false; @@ -75,8 +76,9 @@ public class SystemConfig { private boolean debugInternalChecks = DEFAULT_DEBUG_INTERNAL_CHECKS; private Heuristic branchingHeuristic = DEFAULT_BRANCHING_HEURISTIC; private BinaryNoGoodPropagationEstimationStrategy momsStrategy = DEFAULT_MOMS_STRATEGY; - private boolean restartsEnabled = DEFAULT_RESTARTS_ENABLED; - private int restartIterations = DEFAULT_RESTART_ITERATIONS; + private boolean rebootEnabled = DEFAULT_REBOOT_ENABLED; + private int rebootIterations = DEFAULT_REBOOT_ITERATIONS; + private boolean disableRebootRepeat = DEFAULT_DISABLE_REBOOT_REPEAT; private boolean quiet = DEFAULT_QUIET; private boolean printStats = DEFAULT_PRINT_STATS; private boolean disableJustificationSearch = DEFAULT_DISABLE_JUSTIFICATION_SEARCH; @@ -123,20 +125,28 @@ public void setNogoodStoreName(String nogoodStoreName) { this.nogoodStoreName = nogoodStoreName; } - public boolean isRestartsEnabled() { - return restartsEnabled; + public boolean isRebootEnabled() { + return rebootEnabled; } - public void setRestartsEnabled(boolean restartsEnabled) { - this.restartsEnabled = restartsEnabled; + public void setRebootEnabled(boolean rebootEnabled) { + this.rebootEnabled = rebootEnabled; } - public int getRestartIterations() { - return restartIterations; + public int getRebootIterations() { + return rebootIterations; } - public void setRestartIterations(int restartIterations) { - this.restartIterations = restartIterations; + public void setRebootIterations(int rebootIterations) { + this.rebootIterations = rebootIterations; + } + + public boolean isDisableRebootRepeat() { + return disableRebootRepeat; + } + + public void setDisableRebootRepeat(boolean disableRebootRepeat) { + this.disableRebootRepeat = disableRebootRepeat; } public boolean isDeterministic() { diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 1276f8d98..72cb5fdbc 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -96,10 +96,12 @@ public class CommandLineParser { .desc("the solver implementation to use (default: " + SystemConfig.DEFAULT_SOLVER_NAME + ")").build(); private static final Option OPT_NOGOOD_STORE = Option.builder("r").longOpt("store").hasArg(true).argName("store") .desc("the nogood store to use (default: " + SystemConfig.DEFAULT_NOGOOD_STORE_NAME + ")").build(); - private static final Option OPT_RESTARTS_ENABLED = Option.builder("rst").longOpt("enableRestarts") - .desc("enable solver restarts (default: " + SystemConfig.DEFAULT_RESTARTS_ENABLED + ")").build(); - private static final Option OPT_RESTART_ITERATIONS = Option.builder("rit").longOpt("restartIterations").hasArg(true).argName("number").type(Integer.class) - .desc("the number of solver iterations between restarts (default: " + SystemConfig.DEFAULT_RESTART_ITERATIONS + ")").build(); + private static final Option OPT_REBOOT_ENABLED = Option.builder("rbt").longOpt("enableReboot") + .desc("enable solver reboots (default: " + SystemConfig.DEFAULT_REBOOT_ENABLED + ")").build(); + private static final Option OPT_REBOOT_ITERATIONS = Option.builder("rit").longOpt("rebootIterations").hasArg(true).argName("number").type(Integer.class) + .desc("the number of solver iterations between reboots (default: " + SystemConfig.DEFAULT_REBOOT_ITERATIONS + ")").build(); + private static final Option OPT_NO_REBOOT_REPEAT = Option.builder("drr").longOpt("disableRebootRepeat") + .desc("disables repeated reboots resulting in at most one reboot during solving, only effective if reboot is enabled (default: " + SystemConfig.DEFAULT_REBOOT_ENABLED + ")").build(); private static final Option OPT_SORT = Option.builder("sort").longOpt("sort").hasArg(false) .desc("sort answer sets (default: " + SystemConfig.DEFAULT_SORT_ANSWER_SETS + ")").build(); private static final Option OPT_DETERMINISTIC = Option.builder("d").longOpt("deterministic").hasArg(false) @@ -174,8 +176,8 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_GROUNDER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SOLVER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NOGOOD_STORE); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_RESTARTS_ENABLED); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_RESTART_ITERATIONS); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ENABLED); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ITERATIONS); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SORT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_DETERMINISTIC); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SEED); @@ -234,8 +236,9 @@ private void initializeGlobalOptionHandlers() { this.globalOptionHandlers.put(CommandLineParser.OPT_GROUNDER.getOpt(), this::handleGrounder); this.globalOptionHandlers.put(CommandLineParser.OPT_SOLVER.getOpt(), this::handleSolver); this.globalOptionHandlers.put(CommandLineParser.OPT_NOGOOD_STORE.getOpt(), this::handleNogoodStore); - this.globalOptionHandlers.put(CommandLineParser.OPT_RESTARTS_ENABLED.getOpt(), this::handleRestartsEnabled); - this.globalOptionHandlers.put(CommandLineParser.OPT_RESTART_ITERATIONS.getOpt(), this::handleRestartIterations); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_ENABLED.getOpt(), this::handleRebootEnabled); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_ITERATIONS.getOpt(), this::handleRebootIterations); + this.globalOptionHandlers.put(CommandLineParser.OPT_NO_REBOOT_REPEAT.getOpt(), this::handleDisableRebootRepeat); this.globalOptionHandlers.put(CommandLineParser.OPT_SORT.getOpt(), this::handleSort); this.globalOptionHandlers.put(CommandLineParser.OPT_DETERMINISTIC.getOpt(), this::handleDeterministic); this.globalOptionHandlers.put(CommandLineParser.OPT_SEED.getOpt(), this::handleSeed); @@ -355,18 +358,22 @@ private void handleNogoodStore(Option opt, SystemConfig cfg) { cfg.setNogoodStoreName(opt.getValue(SystemConfig.DEFAULT_NOGOOD_STORE_NAME)); } - private void handleRestartsEnabled(Option opt, SystemConfig cfg) { - cfg.setRestartsEnabled(true); + private void handleRebootEnabled(Option opt, SystemConfig cfg) { + cfg.setRebootEnabled(true); } - private void handleRestartIterations(Option opt, SystemConfig cfg) { + private void handleDisableRebootRepeat(Option opt, SystemConfig cfg) { + cfg.setDisableRebootRepeat(true); + } + + private void handleRebootIterations(Option opt, SystemConfig cfg) { String optVal = opt.getValue(); int limit; if (optVal != null) { limit = Integer.parseInt(optVal); - cfg.setRestartIterations(limit); + cfg.setRebootIterations(limit); } else { - cfg.setRestartIterations(SystemConfig.DEFAULT_RESTART_ITERATIONS); + cfg.setRebootIterations(SystemConfig.DEFAULT_REBOOT_ITERATIONS); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java index ff3d96415..4884d8420 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java @@ -82,7 +82,7 @@ public interface Grounder { int register(NoGood noGood); /** - * Restarts the grounder. + * Reboots the grounder, returning it to its initial state. */ - void restart(Assignment currentAssignment); + void reboot(Assignment currentAssignment); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index 719d2ba71..55e2d8f16 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -415,7 +415,7 @@ public int register(NoGood noGood) { } @Override - public void restart(Assignment currentAssignment) { + public void reboot(Assignment currentAssignment) { workingMemory.reset(); registry.reset(); noGoodGenerator.reset(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java deleted file mode 100644 index 1589fe3e6..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/CumulativeStopWatch.java +++ /dev/null @@ -1,24 +0,0 @@ -package at.ac.tuwien.kr.alpha.core.solver; - -public class CumulativeStopWatch { - private long startTime; - private long runtime; - private boolean running; - - public void start() { - if (!running) { - startTime = System.nanoTime(); - running = true; - } - } - - public void stop() { - long currentTime = System.nanoTime(); - runtime += (currentTime - startTime); - running = false; - } - - public long getRuntime() { - return runtime; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 1720dda35..3b7c233df 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -82,8 +82,9 @@ public class DefaultSolver extends AbstractSolver implements StatisticsReporting private final WritableAssignment assignment; private final GroundConflictNoGoodLearner learner; private final BranchingHeuristic branchingHeuristic; - private boolean restartsEnabled; - private final int restartIterationBreakpoint; + private boolean rebootEnabled; + private final int rebootIterationBreakpoint; + private final boolean disableRebootRepeat; private int iterationCounter; private int mbtAtFixpoint; @@ -103,8 +104,8 @@ private static class SearchState { private final PerformanceLog performanceLog; - private final CumulativeStopWatch solverStopWatch; - private final CumulativeStopWatch grounderStopWatch; + private final StopWatch solverStopWatch; + private final StopWatch grounderStopWatch; public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); @@ -120,11 +121,12 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), 1000); - this.restartsEnabled = config.isRestartsEnabled(); - this.restartIterationBreakpoint = config.getRestartIterations(); + this.rebootEnabled = config.isRebootEnabled(); + this.rebootIterationBreakpoint = config.getRebootIterations(); + this.disableRebootRepeat = config.isDisableRebootRepeat(); this.iterationCounter = 0; - solverStopWatch = new CumulativeStopWatch(); - grounderStopWatch = new CumulativeStopWatch(); + solverStopWatch = new StopWatch(); + grounderStopWatch = new StopWatch(); } private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAssignment assignment, Random random, HeuristicsConfiguration heuristicsConfiguration) { @@ -163,9 +165,12 @@ protected boolean tryAdvance(Consumer action) { } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); syncWithGrounder(); - } else if (restartsEnabled && iterationCounter >= restartIterationBreakpoint) { - restart(); + } else if (rebootEnabled && iterationCounter >= rebootIterationBreakpoint) { + reboot(); iterationCounter = 0; + if (disableRebootRepeat) { + rebootEnabled = false; + } } else if (choose()) { LOGGER.debug("Did choice."); } else if (close()) { @@ -553,19 +558,19 @@ private boolean choose() { } /** - * Performs a restart of the solving process while preserving the current assignment - and thus the progress made. + * Performs a reboot of the solving process while preserving the current assignment - and thus the progress made. * {@link NoGoodStore} and {@link Grounder} are reset. Then the {@link AtomStore} is emptied and the current * assignment is reconstructed. */ - private void restart() { - LOGGER.info("Performing solver and grounder restart."); + private void reboot() { + LOGGER.info("Performing solver and grounder reboot."); Stack atomizedChoiceStack = getAtomizedChoiceStack(); store.reset(); branchingHeuristic.reset(); assignment.clear(); - grounder.restart(assignment); + grounder.reboot(assignment); atomStore.reset(); choiceManager.reset(); @@ -573,7 +578,7 @@ private void restart() { addEnumerationNoGoods(); replayAtomizedChoiceStack(atomizedChoiceStack); - LOGGER.info("Solver and grounder restart finished."); + LOGGER.info("Solver and grounder reboot finished."); } /** @@ -598,7 +603,7 @@ private Stack getAtomizedChoiceStack() { */ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack) { if (propagate() != null) { - throw oops("Conflict in replay during restart"); + throw oops("Conflict in replay during reboot."); } for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { @@ -618,11 +623,11 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack if (activeChoice) { if (propagate() != null) { - throw oops("Conflict in replay during restart"); + throw oops("Conflict in replay during reboot."); } syncWithGrounder(); if (propagate() != null) { - throw oops("Conflict in replay during restart"); + throw oops("Conflict in replay during reboot."); } } } @@ -660,8 +665,8 @@ private void addEnumerationNoGoods() { */ private void stopSolverWatchAndLogRuntimes() { solverStopWatch.stop(); - LOGGER.info("Solver runtime: {}", solverStopWatch.getRuntime()); - LOGGER.info("Grounder runtime: {}", grounderStopWatch.getRuntime()); + LOGGER.info("Solver runtime: {}", solverStopWatch.getNanoTime()); + LOGGER.info("Grounder runtime: {}", grounderStopWatch.getNanoTime()); } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java index 2f3810b4b..dc1c7e987 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java @@ -44,8 +44,7 @@ public class PerformanceLog { /** * @param msBetweenOutputs minimum number of milliseconds that have to pass between writing of performance logs. */ - public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, - NoGoodCounter noGoodCounter, long msBetweenOutputs) { + public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, NoGoodCounter noGoodCounter, long msBetweenOutputs) { super(); this.choiceManager = choiceManager; this.assignment = assignment; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java new file mode 100644 index 000000000..e5cf700a8 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver; + +public class StopWatch { + private long startTime; + private long nanoTime; + private boolean running; + + /** + * Starts the {@link StopWatch}. If it is already running, this function does nothing. + */ + public void start() { + if (!running) { + startTime = System.nanoTime(); + running = true; + } + } + + /** + * Stops the {@link StopWatch}. If it is not running, this function does nothing. + */ + public void stop() { + if (running) { + long currentTime = System.nanoTime(); + nanoTime += currentTime - startTime; + running = false; + } + } + + /** + * Returns the time in nanoseconds the {@link StopWatch} has been running in total. + * @return the total running time of the {@link StopWatch} in nanoseconds. + */ + public long getNanoTime() { + long currentNanos = running ? System.nanoTime() - startTime : 0; + return nanoTime + currentNanos; + } +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java index 9977dabd8..6a132db7b 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java @@ -216,6 +216,6 @@ public int register(NoGood noGood) { * Empty interface implementation. */ @Override - public void restart(Assignment currentAssignment) { + public void reboot(Assignment currentAssignment) { } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java index b0fd28af6..6d3d6e1bc 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java @@ -130,7 +130,7 @@ public int register(NoGood noGood) { * Empty interface implementation. */ @Override - public void restart(Assignment currentAssignment) { + public void reboot(Assignment currentAssignment) { } @Override diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index bc2ec6302..28cb7d0bb 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -13,8 +13,9 @@ public class RegressionTestConfig { private final Heuristic branchingHeuristic; - private final boolean restartsEnabled; - private final int restartIterations; + private final boolean rebootEnabled; + private final int rebootIterations; + private final boolean disableRebootRepeat; private final long seed; @@ -34,16 +35,17 @@ public class RegressionTestConfig { public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, - Heuristic branchingHeuristic, boolean restartsEnabled, int restartIterations, long seed, - boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, + Heuristic branchingHeuristic, boolean rebootEnabled, int rebootIterations, boolean disableRebootRepeat, + long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { this.solverName = solverName; this.grounderName = grounderName; this.noGoodStoreName = noGoodStoreName; this.branchingHeuristic = branchingHeuristic; - this.restartsEnabled = restartsEnabled; - this.restartIterations = restartIterations; + this.rebootEnabled = rebootEnabled; + this.rebootIterations = rebootIterations; + this.disableRebootRepeat = disableRebootRepeat; this.seed = seed; this.debugChecks = debugChecks; this.grounderToleranceConstraints = grounderToleranceConstraints; @@ -59,8 +61,9 @@ public SystemConfig toSystemConfig() { retVal.setGrounderName(this.grounderName); retVal.setSolverName(this.solverName); retVal.setNogoodStoreName(this.noGoodStoreName); - retVal.setRestartsEnabled(this.restartsEnabled); - retVal.setRestartIterations(this.restartIterations); + retVal.setRebootEnabled(this.rebootEnabled); + retVal.setRebootIterations(this.rebootIterations); + retVal.setDisableRebootRepeat(this.disableRebootRepeat); retVal.setSeed(this.seed); retVal.setBranchingHeuristic(this.branchingHeuristic); retVal.setDebugInternalChecks(this.debugChecks); @@ -89,12 +92,12 @@ public Heuristic getBranchingHeuristic() { return this.branchingHeuristic; } - public boolean isRestartsEnabled() { - return restartsEnabled; + public boolean isRebootEnabled() { + return rebootEnabled; } - public int getRestartIterations() { - return restartIterations; + public int getRebootIterations() { + return rebootIterations; } public long getSeed() { @@ -133,12 +136,12 @@ public boolean isSupportNegativeSumElements() { public String toString() { return String.format( "RegressionTestConfig [solverName=%s, grounderName=%s, noGoodStoreName=%s, branchingHeuristic=%s," - + " restartsEnabled=%b, restartIterations=%d, seed=%s, debugChecks=%s, grounderToleranceConstraints=%s," - + " grounderToleranceRules=%s, disableInstanceRemoval=%s, evaluateStratifiedPart=%s, useSortingGrid=%s," - + " supportNegativeSumElements=%s]", - this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.restartsEnabled, - this.restartIterations, this.seed, this.debugChecks, this.grounderToleranceConstraints, - this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, - this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); + + " rebootEnabled=%b, rebootIterations=%d, disableRebootRepeat=%b, seed=%s, debugChecks=%s," + + " grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s," + + " evaluateStratifiedPart=%s, useSortingGrid=%s, supportNegativeSumElements=%s]", + this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.rebootEnabled, + this.rebootIterations, this.disableRebootRepeat, this.seed, this.debugChecks, + this.grounderToleranceConstraints, this.grounderToleranceRules, this.disableInstanceRemoval, + this.evaluateStratifiedPart, this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index 73352be22..95c215dd7 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -15,8 +15,9 @@ public class RegressionTestConfigProvider { private static final String DEFAULT_GROUNDER_NAME = "naive"; private static final String DEFAULT_ATOM_STORE = "alpharoaming"; private static final String DEFAULT_BRANCHING_HEURISTIC = "VSIDS"; - private static final boolean DEFAULT_RESTARTS_ENABLED = false; - private static final int DEFAULT_RESTART_ITERATIONS = 5; + private static final boolean DEFAULT_REBOOT_ENABLED = false; + private static final int DEFAULT_REBOOT_ITERATIONS = 5; + private static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = true; private static final String DEFAULT_GROUNDER_TOLERANCE = "strict"; private static final boolean DEFAULT_DISABLE_INSTANCE_REMOVAL = false; private static final boolean DEFAULT_ENABLE_DEBUG_CHECKS = false; @@ -38,8 +39,9 @@ private static List buildConfigs() { String grounder = DEFAULT_GROUNDER_NAME; String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive"} : new String[]{DEFAULT_ATOM_STORE}; String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC}; - boolean[] restartEnabledValues = new boolean[]{DEFAULT_RESTARTS_ENABLED, true}; - int[] restartIterationsValues = new int[]{DEFAULT_RESTART_ITERATIONS}; + boolean[] rebootEnabledValues = new boolean[]{DEFAULT_REBOOT_ENABLED, true}; + int[] rebootIterationsValues = new int[]{DEFAULT_REBOOT_ITERATIONS}; + boolean[] disableRebootRepeatValues = new boolean[]{DEFAULT_DISABLE_REBOOT_REPEAT}; String[] gtcValues = new String[]{DEFAULT_GROUNDER_TOLERANCE, "permissive"}; String gtrValue = DEFAULT_GROUNDER_TOLERANCE; boolean[] disableInstanceRemovalValues = ci ? new boolean[]{DEFAULT_DISABLE_INSTANCE_REMOVAL, true} : new boolean[]{DEFAULT_DISABLE_INSTANCE_REMOVAL}; @@ -60,18 +62,21 @@ private static List buildConfigs() { for (String solverName : solvers) { for (String atomStoreName : atomStores) { for (String branchingHeuristicName : heuristics) { - for (boolean restartsEnabled : restartEnabledValues) { - for (int restartIterations : restartIterationsValues) { - for (String grounderTolerance : gtcValues) { - for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { - for (boolean evaluateStratified : evaluateStratifiedValues) { - for (boolean enableDebugChecks : enableDebugChecksValues) { - configsToTest.add(new RegressionTestConfig( - solverName, grounder, atomStoreName, - Heuristic.valueOf(branchingHeuristicName), - restartsEnabled, restartIterations, seed, enableDebugChecks, - grounderTolerance, gtrValue, disableInstanceRemoval, - evaluateStratified, true, true)); + for (boolean rebootEnabled : rebootEnabledValues) { + for (int rebootIterations : rebootIterationsValues) { + for (boolean disableRebootRepeat : disableRebootRepeatValues) { + for (String grounderTolerance : gtcValues) { + for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { + for (boolean evaluateStratified : evaluateStratifiedValues) { + for (boolean enableDebugChecks : enableDebugChecksValues) { + configsToTest.add(new RegressionTestConfig( + solverName, grounder, atomStoreName, + Heuristic.valueOf(branchingHeuristicName), + rebootEnabled, rebootIterations, disableRebootRepeat, + seed, enableDebugChecks, grounderTolerance, gtrValue, + disableInstanceRemoval, evaluateStratified, + true, true)); + } } } } @@ -104,8 +109,11 @@ private static List buildConfigsForAggregateTests() { for (boolean supportNegativeElements : supportNegativeSumElementsValues) { configsToTest.add( new RegressionTestConfig( - DEFAULT_SOLVER_NAME, DEFAULT_GROUNDER_NAME, DEFAULT_ATOM_STORE, Heuristic.valueOf(DEFAULT_BRANCHING_HEURISTIC), - DEFAULT_RESTARTS_ENABLED, DEFAULT_RESTART_ITERATIONS, 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, + DEFAULT_SOLVER_NAME, DEFAULT_GROUNDER_NAME, DEFAULT_ATOM_STORE, + Heuristic.valueOf(DEFAULT_BRANCHING_HEURISTIC), + DEFAULT_REBOOT_ENABLED, DEFAULT_REBOOT_ITERATIONS, DEFAULT_DISABLE_REBOOT_REPEAT, + 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, + DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, evalStratified, useSortingGrid, supportNegativeElements)); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java index 72807a35e..c102e1e13 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java @@ -26,7 +26,7 @@ package at.ac.tuwien.kr.alpha.core.solver; import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.ignoreTestForRestartsEnabled; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.ignoreTestForRebootEnabled; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -59,7 +59,7 @@ public void checkStatsStringZeroChoices(RegressionTestConfig cfg) { @RegressionTest public void checkStatsStringOneChoice(RegressionTestConfig cfg) { - ignoreTestForRestartsEnabled(cfg); // Do not run this test case with restarts enabled. + ignoreTestForRebootEnabled(cfg); // Do not run this test case with reboot enabled. Solver solver = buildSolverForRegressionTest("a :- not b. b :- not a.", cfg); assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckStats(solver, 2, 1, 1, 1, 1, 0, 0, 0); diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java index a84e6576d..4332c2c9c 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java @@ -802,14 +802,14 @@ public void smallCardinalityAggregate(RegressionTestConfig cfg) { @RegressionTest public void dummyGrounder(RegressionTestConfig cfg) { - ignoreTestForRestartsEnabled(cfg); // Do not run this test case with restarts enabled. + ignoreTestForRebootEnabled(cfg); // Do not run this test case with reboot enabled. AtomStore atomStore = new AtomStoreImpl(); assertEquals(DummyGrounder.EXPECTED, buildSolverForRegressionTest(atomStore, new DummyGrounder(atomStore), cfg).collectSet()); } @RegressionTest public void choiceGrounder(RegressionTestConfig cfg) { - ignoreTestForRestartsEnabled(cfg); // Do not run this test case with restarts enabled. + ignoreTestForRebootEnabled(cfg); // Do not run this test case with reboot enabled. AtomStore atomStore = new AtomStoreImpl(); assertEquals(ChoiceGrounder.EXPECTED, buildSolverForRegressionTest(atomStore, new ChoiceGrounder(atomStore), cfg).collectSet()); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java index 20cc55d62..bc99eba21 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java @@ -216,8 +216,8 @@ public static void ignoreTestForSimplifiedSumAggregates(RegressionTestConfig cfg Assumptions.assumeTrue(cfg.isSupportNegativeSumElements()); } - public static void ignoreTestForRestartsEnabled(RegressionTestConfig cfg) { - Assumptions.assumeFalse(cfg.isRestartsEnabled()); + public static void ignoreTestForRebootEnabled(RegressionTestConfig cfg) { + Assumptions.assumeFalse(cfg.isRebootEnabled()); } } From d6204196598847b47bfb198435b5cb95fac27ca4 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 23 Sep 2022 16:30:53 +0200 Subject: [PATCH 23/53] Prevent VSIDS from ignoring learnt nogoods, rename reboot related package --- .../at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 6 +++--- .../kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java | 2 +- .../alpha/core/solver/{reset => reboot}/AtomValuePair.java | 2 +- .../alpha/core/solver/{reset => reboot}/AtomizedChoice.java | 2 +- .../solver/{reset => reboot}/AtomizedNoGoodCollection.java | 2 +- .../alpha/core/solver/{reset => reboot}/NoGoodAtomizer.java | 2 +- .../solver/{reset => reboot}/AtomGeneratorForTests.java | 2 +- .../{reset => reboot}/AtomizedNoGoodCollectionTest.java | 2 +- .../core/solver/{reset => reboot}/NoGoodAtomizerTest.java | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/AtomValuePair.java (97%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/AtomizedChoice.java (97%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/AtomizedNoGoodCollection.java (98%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/NoGoodAtomizer.java (98%) rename alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/AtomGeneratorForTests.java (98%) rename alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/AtomizedNoGoodCollectionTest.java (99%) rename alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/{reset => reboot}/NoGoodAtomizerTest.java (99%) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 3b7c233df..4cae322e2 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -40,8 +40,8 @@ import java.util.function.Consumer; import at.ac.tuwien.kr.alpha.core.common.Assignment; -import at.ac.tuwien.kr.alpha.core.solver.reset.AtomizedChoice; -import at.ac.tuwien.kr.alpha.core.solver.reset.AtomizedNoGoodCollection; +import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; +import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedNoGoodCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -660,7 +660,7 @@ private void addEnumerationNoGoods() { } /** - * Stops the {@link DefaultSolver#solverStopWatch} and logs the current runtime + * Stops the {@link DefaultSolver#solverStopWatch} and logs the current total time * of {@link DefaultSolver#solverStopWatch} and {@link DefaultSolver#grounderStopWatch}. */ private void stopSolverWatchAndLogRuntimes() { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java index ad9fe9e73..dc0ea58bd 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java @@ -130,7 +130,7 @@ void decayIfTimeHasCome() { public void newNoGoods(Collection newNoGoods) { for (NoGood newNoGood : newNoGoods) { Type type = newNoGood.getType(); - if (type != Type.LEARNT && type != Type.INTERNAL) { + if (type != Type.INTERNAL) { analyzeNewNoGood(newNoGood); initActivity(newNoGood); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomValuePair.java similarity index 97% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomValuePair.java index 18a7c13d9..ca9692ab4 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomValuePair.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomValuePair.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedChoice.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java similarity index 97% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedChoice.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java index fe2a19520..bac554deb 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedChoice.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollection.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java similarity index 98% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollection.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java index 0eb1f4a6e..c6893b075 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollection.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import at.ac.tuwien.kr.alpha.core.common.AtomStore; import at.ac.tuwien.kr.alpha.core.common.NoGood; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java similarity index 98% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java index 12d33c965..7f9b9c5ff 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizer.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomGeneratorForTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomGeneratorForTests.java similarity index 98% rename from alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomGeneratorForTests.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomGeneratorForTests.java index 37a9e86f5..f2f8ff779 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomGeneratorForTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomGeneratorForTests.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import at.ac.tuwien.kr.alpha.api.programs.Predicate; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollectionTest.java similarity index 99% rename from alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollectionTest.java index 6b2b53b4f..751c6deac 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/AtomizedNoGoodCollectionTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollectionTest.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizerTest.java similarity index 99% rename from alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizerTest.java index 7070afdca..e10d694ca 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reset/NoGoodAtomizerTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizerTest.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reset; +package at.ac.tuwien.kr.alpha.core.solver.reboot; import static org.junit.jupiter.api.Assertions.assertEquals; From 48d92708b44460b4cfdd4e2d8fde81a50c698117 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 4 Oct 2022 13:20:14 +0200 Subject: [PATCH 24/53] Fix propagation stopwatch --- .../kr/alpha/core/solver/DefaultSolver.java | 54 +++++++++++----- .../strategies/FixedRebootStrategy.java | 51 ++++++++++++++++ .../strategies/GeometricRebootStrategy.java | 50 +++++++++++++++ .../reboot/strategies/LubyRebootStrategy.java | 61 +++++++++++++++++++ .../reboot/strategies/RebootStrategy.java | 32 ++++++++++ .../core/{solver => util}/StopWatch.java | 2 +- 6 files changed, 235 insertions(+), 15 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/{solver => util}/StopWatch.java (98%) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 4cae322e2..586ba4f95 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -42,6 +42,9 @@ import at.ac.tuwien.kr.alpha.core.common.Assignment; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedNoGoodCollection; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedRebootStrategy; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; +import at.ac.tuwien.kr.alpha.core.util.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -78,14 +81,14 @@ public class DefaultSolver extends AbstractSolver implements StatisticsReporting private final NoGoodStore store; private final AtomizedNoGoodCollection enumerationNoGoods; + private final AtomizedNoGoodCollection learnedNoGoods; private final ChoiceManager choiceManager; private final WritableAssignment assignment; private final GroundConflictNoGoodLearner learner; private final BranchingHeuristic branchingHeuristic; + private final RebootStrategy rebootStrategy; private boolean rebootEnabled; - private final int rebootIterationBreakpoint; private final boolean disableRebootRepeat; - private int iterationCounter; private int mbtAtFixpoint; private int conflictsAfterClosing; @@ -106,6 +109,7 @@ private static class SearchState { private final StopWatch solverStopWatch; private final StopWatch grounderStopWatch; + private final StopWatch propagationStopWatch; public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); @@ -113,6 +117,7 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.assignment = assignment; this.store = store; this.enumerationNoGoods = new AtomizedNoGoodCollection(atomStore); + this.learnedNoGoods = new AtomizedNoGoodCollection(atomStore); this.choiceManager = new ChoiceManager(assignment, store); this.choiceManager.setChecksEnabled(config.isDebugInternalChecks()); this.learner = new GroundConflictNoGoodLearner(assignment, atomStore); @@ -121,12 +126,14 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), 1000); + this.rebootEnabled = config.isRebootEnabled(); - this.rebootIterationBreakpoint = config.getRebootIterations(); this.disableRebootRepeat = config.isDisableRebootRepeat(); - this.iterationCounter = 0; - solverStopWatch = new StopWatch(); - grounderStopWatch = new StopWatch(); + this.rebootStrategy = new FixedRebootStrategy(config.getRebootIterations()); + + this.solverStopWatch = new StopWatch(); + this.grounderStopWatch = new StopWatch(); + this.propagationStopWatch = new StopWatch(); } private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAssignment assignment, Random random, HeuristicsConfiguration heuristicsConfiguration) { @@ -150,7 +157,7 @@ protected boolean tryAdvance(Consumer action) { } // Try all assignments until grounder reports no more NoGoods and all of them are satisfied while (true) { - iterationCounter++; + rebootStrategy.stepPerformed(); performanceLog.writeIfTimeForLogging(LOGGER); if (searchState.isSearchSpaceCompletelyExplored) { LOGGER.debug("Search space has been fully explored, there are no more answer-sets."); @@ -165,9 +172,10 @@ protected boolean tryAdvance(Consumer action) { } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); syncWithGrounder(); - } else if (rebootEnabled && iterationCounter >= rebootIterationBreakpoint) { +// } else if (rebootEnabled && iterationCounter >= rebootIterationBreakpoint) { + } else if (rebootEnabled && rebootStrategy.isRebootScheduled()) { reboot(); - iterationCounter = 0; + rebootStrategy.rebootPerformed(); if (disableRebootRepeat) { rebootEnabled = false; } @@ -260,7 +268,9 @@ private void learnFromConflict(ConflictCause conflictCause) { private ConflictCause propagate() { LOGGER.trace("Doing propagation step."); + propagationStopWatch.start(); ConflictCause conflictCause = store.propagate(); + propagationStopWatch.stop(); LOGGER.trace("Assignment after propagation is: {}", assignment); if (!disableNoGoodDeletion && conflictCause == null) { // Run learned-NoGood deletion-strategy. @@ -299,9 +309,11 @@ private boolean addAndBackjumpIfNecessary(int noGoodId, NoGood noGood, int lbd) return false; } choiceManager.backjump(backjumpLevel); + propagationStopWatch.start(); if (store.propagate() != null) { throw oops("Violated NoGood after backtracking."); } + propagationStopWatch.stop(); } return true; } @@ -328,7 +340,7 @@ private boolean learnBackjumpAddFromConflict(ConflictCause conflictCause) { choiceManager.backjump(analysisResult.backjumpLevel); final NoGood learnedNoGood = analysisResult.learnedNoGood; - enumerationNoGoods.add(learnedNoGood); + learnedNoGoods.add(learnedNoGood); int noGoodId = grounder.register(learnedNoGood); return addAndBackjumpIfNecessary(noGoodId, learnedNoGood, analysisResult.lbd); } @@ -575,7 +587,8 @@ private void reboot() { choiceManager.reset(); syncWithGrounder(); - addEnumerationNoGoods(); + ingestNoGoodCollection(enumerationNoGoods); + ingestNoGoodCollection(learnedNoGoods); replayAtomizedChoiceStack(atomizedChoiceStack); LOGGER.info("Solver and grounder reboot finished."); @@ -647,11 +660,11 @@ private void growForMaxAtomId() { } /** - * Adds all nogoods from the enumeration nogood store to the regular nogood store. + * Adds all nogoods from the given {@link AtomizedNoGoodCollection} to the regular nogood store. */ - private void addEnumerationNoGoods() { + private void ingestNoGoodCollection(AtomizedNoGoodCollection noGoodCollection) { Map newNoGoods = new LinkedHashMap<>(); - for (NoGood noGood : enumerationNoGoods.getNoGoods()) { + for (NoGood noGood : noGoodCollection.getNoGoods()) { newNoGoods.put(grounder.register(noGood), noGood); } if (!ingest(newNoGoods)) { @@ -659,6 +672,18 @@ private void addEnumerationNoGoods() { } } + /** + * Updates the branching heuristic as if all the nogoods in {@link DefaultSolver#learnedNoGoods} + * were learned from conflicts in the order they are stored in {@link DefaultSolver#learnedNoGoods}. + */ + private void simulateOldConflicts() { + for (NoGood noGood : learnedNoGoods.getNoGoods()) { + GroundConflictNoGoodLearner.ConflictAnalysisResult analysisResult = + new GroundConflictNoGoodLearner.ConflictAnalysisResult(noGood, 0, Collections.emptyList()); + branchingHeuristic.analyzedConflict(analysisResult); + } + } + /** * Stops the {@link DefaultSolver#solverStopWatch} and logs the current total time * of {@link DefaultSolver#solverStopWatch} and {@link DefaultSolver#grounderStopWatch}. @@ -667,6 +692,7 @@ private void stopSolverWatchAndLogRuntimes() { solverStopWatch.stop(); LOGGER.info("Solver runtime: {}", solverStopWatch.getNanoTime()); LOGGER.info("Grounder runtime: {}", grounderStopWatch.getNanoTime()); + LOGGER.info("Propagation runtime: {}", propagationStopWatch.getNanoTime()); } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java new file mode 100644 index 000000000..311255f93 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +public class FixedRebootStrategy implements RebootStrategy { + private final int breakpoint; + private int stepCount; + + public FixedRebootStrategy(int breakpoint) { + this.breakpoint = breakpoint; + this.stepCount = 0; + } + + @Override + public void stepPerformed() { + stepCount++; + } + + @Override + public boolean isRebootScheduled() { + return stepCount >= breakpoint; + } + + @Override + public void rebootPerformed() { + stepCount = 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java new file mode 100644 index 000000000..36eba3d06 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +public class GeometricRebootStrategy implements RebootStrategy { + private static final double BASE = 1.5; + private static final double SCALING_FACTOR = 2; + + private int rebootCount; + private int stepCount; + + @Override + public void stepPerformed() { + stepCount++; + } + + @Override + public boolean isRebootScheduled() { + return stepCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); + } + + @Override + public void rebootPerformed() { + rebootCount++; + stepCount = 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java new file mode 100644 index 000000000..f32527289 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +public class LubyRebootStrategy implements RebootStrategy { + private static final double SCALING_FACTOR = 10; + + private int rebootCount; + private int stepCount; + + @Override + public void stepPerformed() { + stepCount++; + } + + @Override + public boolean isRebootScheduled() { + return stepCount >= SCALING_FACTOR * luby(rebootCount + 1); + } + + @Override + public void rebootPerformed() { + rebootCount++; + } + + private double luby(double i) { + for (int k = 1; k < 31; k++) { + if (i == (Math.pow(2, k)) - 1) { + return Math.pow(2, k - 1); + } + } + for (int k = 1;; k++) { + if (Math.pow(2, k - 1) <= i && i < Math.pow(2, k) - 1) { + return luby(i - Math.pow(2, k - 1) + 1); + } + } + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java new file mode 100644 index 000000000..387409bc1 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +public interface RebootStrategy { + void stepPerformed(); + boolean isRebootScheduled(); + void rebootPerformed(); +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java similarity index 98% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java index e5cf700a8..b3c389aca 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/StopWatch.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java @@ -23,7 +23,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver; +package at.ac.tuwien.kr.alpha.core.util; public class StopWatch { private long startTime; From 759c551d292d8ac967d17d5185932f53b90d7599 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 18 Oct 2022 15:59:26 +0200 Subject: [PATCH 25/53] Fix reboot repeat command line option --- .../java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java | 6 +++--- .../at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index e9163d78c..0f85de0cb 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -126,7 +126,7 @@ public void setNogoodStoreName(String nogoodStoreName) { } public boolean isRebootEnabled() { - return rebootEnabled; + return this.rebootEnabled; } public void setRebootEnabled(boolean rebootEnabled) { @@ -134,7 +134,7 @@ public void setRebootEnabled(boolean rebootEnabled) { } public int getRebootIterations() { - return rebootIterations; + return this.rebootIterations; } public void setRebootIterations(int rebootIterations) { @@ -142,7 +142,7 @@ public void setRebootIterations(int rebootIterations) { } public boolean isDisableRebootRepeat() { - return disableRebootRepeat; + return this.disableRebootRepeat; } public void setDisableRebootRepeat(boolean disableRebootRepeat) { diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 72cb5fdbc..14b9045c5 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -101,7 +101,7 @@ public class CommandLineParser { private static final Option OPT_REBOOT_ITERATIONS = Option.builder("rit").longOpt("rebootIterations").hasArg(true).argName("number").type(Integer.class) .desc("the number of solver iterations between reboots (default: " + SystemConfig.DEFAULT_REBOOT_ITERATIONS + ")").build(); private static final Option OPT_NO_REBOOT_REPEAT = Option.builder("drr").longOpt("disableRebootRepeat") - .desc("disables repeated reboots resulting in at most one reboot during solving, only effective if reboot is enabled (default: " + SystemConfig.DEFAULT_REBOOT_ENABLED + ")").build(); + .desc("disables repeated reboots resulting in at most one reboot during solving, only effective if reboot is enabled (default: " + SystemConfig.DEFAULT_DISABLE_REBOOT_REPEAT + ")").build(); private static final Option OPT_SORT = Option.builder("sort").longOpt("sort").hasArg(false) .desc("sort answer sets (default: " + SystemConfig.DEFAULT_SORT_ANSWER_SETS + ")").build(); private static final Option OPT_DETERMINISTIC = Option.builder("d").longOpt("deterministic").hasArg(false) @@ -178,6 +178,7 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NOGOOD_STORE); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ENABLED); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ITERATIONS); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NO_REBOOT_REPEAT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SORT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_DETERMINISTIC); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SEED); From 658457ed11d95b8d11821d75e05b3c3751caab7f Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 20 Oct 2022 18:14:07 +0200 Subject: [PATCH 26/53] Store learnt nogoods also after assignment is closed --- .../at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 586ba4f95..4a7aa678d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -460,7 +460,11 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { return false; } // Add newly obtained noGoods. - if (!ingest(obtained)) { + boolean success = ingest(obtained); + for (NoGood noGood : obtained.values()) { + learnedNoGoods.add(noGood); + } + if (!success) { logStats(); return false; } From cf68c6a269a9f011b4febd129af6d483a4e59927 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 20 Oct 2022 18:14:37 +0200 Subject: [PATCH 27/53] Add additional statistic tracking --- .../kr/alpha/core/solver/DefaultSolver.java | 39 ++++++++- .../alpha/core/solver/NaiveNoGoodStore.java | 21 +++++ .../kr/alpha/core/solver/NoGoodStore.java | 9 +++ .../core/solver/NoGoodStoreAlphaRoaming.java | 81 ++++++++++++++++++- .../kr/alpha/core/solver/PerformanceLog.java | 12 ++- .../solver/reboot/stats/QuotientTracker.java | 51 ++++++++++++ .../reboot/stats/SimpleCountingTracker.java | 54 +++++++++++++ .../core/solver/reboot/stats/StatTracker.java | 31 +++++++ .../reboot/stats/StaticNoGoodTracker.java | 56 +++++++++++++ .../reboot/stats/TotalNoGoodTracker.java | 55 +++++++++++++ 10 files changed, 405 insertions(+), 4 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 4a7aa678d..53abee197 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -42,6 +42,7 @@ import at.ac.tuwien.kr.alpha.core.common.Assignment; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedNoGoodCollection; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.*; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedRebootStrategy; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; import at.ac.tuwien.kr.alpha.core.util.StopWatch; @@ -110,6 +111,9 @@ private static class SearchState { private final StopWatch solverStopWatch; private final StopWatch grounderStopWatch; private final StopWatch propagationStopWatch; + private final SimpleCountingTracker iterationTracker; + private final SimpleCountingTracker conflictTracker; + private final SimpleCountingTracker decisionTracker; public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); @@ -124,8 +128,6 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.branchingHeuristic = chainFallbackHeuristic(grounder, assignment, random, heuristicsConfiguration); this.disableJustifications = config.isDisableJustificationSearch(); this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); - this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, - store.getNoGoodCounter(), 1000); this.rebootEnabled = config.isRebootEnabled(); this.disableRebootRepeat = config.isDisableRebootRepeat(); @@ -134,6 +136,36 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.solverStopWatch = new StopWatch(); this.grounderStopWatch = new StopWatch(); this.propagationStopWatch = new StopWatch(); + + this.iterationTracker = new SimpleCountingTracker("iterations"); + this.conflictTracker = new SimpleCountingTracker("conflicts"); + this.decisionTracker = new SimpleCountingTracker("decisions"); + SimpleCountingTracker propagationTracker = new SimpleCountingTracker("prop_count"); + SimpleCountingTracker propagationConflictTracker = new SimpleCountingTracker("prop_conflicts"); + SimpleCountingTracker nonbinPropagationTracker = new SimpleCountingTracker("nonbin_prop_count"); + SimpleCountingTracker nonbinPropagationConflictTracker = new SimpleCountingTracker("nonbin_prop_conflicts"); + StaticNoGoodTracker staticNoGoodTracker = new StaticNoGoodTracker(getNoGoodCounter()); + TotalNoGoodTracker totalNoGoodTracker = new TotalNoGoodTracker(getNoGoodCounter()); + + List statTrackers = new LinkedList<>(); + statTrackers.add(iterationTracker); + statTrackers.add(conflictTracker); + statTrackers.add(decisionTracker); + statTrackers.add(propagationTracker); + statTrackers.add(propagationConflictTracker); + statTrackers.add(nonbinPropagationTracker); + statTrackers.add(nonbinPropagationConflictTracker); + statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); + statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodTracker, totalNoGoodTracker)); + statTrackers.add(new QuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); + statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); + + this.store.setPropagationTracker(propagationTracker); + this.store.setPropagationConflictTracker(propagationConflictTracker); + this.store.setNonbinPropagationTracker(nonbinPropagationTracker); + this.store.setNonbinPropagationConflictTracker(nonbinPropagationConflictTracker); + this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, + store.getNoGoodCounter(), statTrackers, 1000); } private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAssignment assignment, Random random, HeuristicsConfiguration heuristicsConfiguration) { @@ -158,6 +190,7 @@ protected boolean tryAdvance(Consumer action) { // Try all assignments until grounder reports no more NoGoods and all of them are satisfied while (true) { rebootStrategy.stepPerformed(); + iterationTracker.increment(); performanceLog.writeIfTimeForLogging(LOGGER); if (searchState.isSearchSpaceCompletelyExplored) { LOGGER.debug("Search space has been fully explored, there are no more answer-sets."); @@ -169,6 +202,7 @@ protected boolean tryAdvance(Consumer action) { if (conflictCause != null) { LOGGER.debug("Conflict encountered, analyzing conflict."); learnFromConflict(conflictCause); + conflictTracker.increment(); } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); syncWithGrounder(); @@ -570,6 +604,7 @@ private boolean choose() { } choiceManager.choose(new Choice(literal, false)); + decisionTracker.increment(); return true; } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java index a895d8d26..eb21d6a86 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java @@ -27,6 +27,7 @@ */ package at.ac.tuwien.kr.alpha.core.solver; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.SimpleCountingTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -145,6 +146,26 @@ public void reset() { counter.reset(); } + @Override + public void setPropagationTracker(SimpleCountingTracker tracker) { + + } + + @Override + public void setPropagationConflictTracker(SimpleCountingTracker tracker) { + + } + + @Override + public void setNonbinPropagationTracker(SimpleCountingTracker tracker) { + + } + + @Override + public void setNonbinPropagationConflictTracker(SimpleCountingTracker tracker) { + + } + @Override public void cleanupLearnedNoGoods() { } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java index c3e3e7165..60380ecfb 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java @@ -1,6 +1,7 @@ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.SimpleCountingTracker; /** * An interface defining the use of a NoGood store. @@ -60,4 +61,12 @@ public interface NoGoodStore { * Clears all data within the nogood store. */ void reset(); + + void setPropagationTracker(SimpleCountingTracker tracker); + + void setPropagationConflictTracker(SimpleCountingTracker tracker); + + void setNonbinPropagationTracker(SimpleCountingTracker tracker); + + void setNonbinPropagationConflictTracker(SimpleCountingTracker tracker); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index d92a1d27b..21b1dd433 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -27,6 +27,7 @@ */ package at.ac.tuwien.kr.alpha.core.solver; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.SimpleCountingTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,6 +88,11 @@ public class NoGoodStoreAlphaRoaming implements NoGoodStore, BinaryNoGoodPropaga private final NoGoodCounter counter = new NoGoodCounter(); + private SimpleCountingTracker propagationTracker; + private SimpleCountingTracker propagationConflictTracker; + private SimpleCountingTracker nonbinPropagationTracker; + private SimpleCountingTracker nonbinPropagationConflictTracker; + public NoGoodStoreAlphaRoaming(WritableAssignment assignment, boolean checksEnabled) { this.assignment = assignment; this.checksEnabled = checksEnabled; @@ -159,6 +165,30 @@ public NoGoodCounter getNoGoodCounter() { public void reset() { clear(); counter.reset(); + propagationTracker.reset(); + propagationConflictTracker.reset(); + nonbinPropagationTracker.reset(); + nonbinPropagationConflictTracker.reset(); + } + + @Override + public void setPropagationTracker(SimpleCountingTracker tracker) { + this.propagationTracker = tracker; + } + + @Override + public void setPropagationConflictTracker(SimpleCountingTracker tracker) { + this.propagationConflictTracker = tracker; + } + + @Override + public void setNonbinPropagationTracker(SimpleCountingTracker tracker) { + this.nonbinPropagationTracker = tracker; + } + + @Override + public void setNonbinPropagationConflictTracker(SimpleCountingTracker tracker) { + this.nonbinPropagationConflictTracker = tracker; } @Override @@ -458,11 +488,14 @@ private ConflictCause assignTruth(int atom, ThriceTruth truth, Antecedent implie * @param literal the literal that triggers the propagation. */ private ConflictCause propagateWeakly(int literal, int currentDecisionLevel, boolean restrictToBinaryNoGoods) { + incrementPropagationTracker(); + incrementNonbinPropagationTracker(); final ArrayList watchesOfAssignedAtom = watches(literal); // Propagate binary watches. ConflictCause conflictCause = binaryWatches[literal].propagateWeakly(); if (conflictCause != null || restrictToBinaryNoGoods) { + handleTrackersForBinaryConflict(); return conflictCause; } @@ -479,9 +512,11 @@ private ConflictCause propagateWeakly(int literal, int currentDecisionLevel, boo while (watchIterator.hasNext()) { watchlist.add(watchIterator.next()); } + handleTrackersForNonBinaryConflict(); return conflictCause; } } + handleTrackersForNoConflict(); return null; } @@ -550,10 +585,10 @@ private void logNoGoodAndAssignment(WatchedNoGood noGood, Assignment assignment) } private ConflictCause propagateStrongly(int literal, int currentDecisionLevel, boolean restrictToBinaryNoGoods) { - // Propagate binary watches. ConflictCause conflictCause = binaryWatches[literal].propagateStrongly(); if (conflictCause != null || restrictToBinaryNoGoods) { + handleTrackersForBinaryConflict(); return conflictCause; } @@ -573,9 +608,11 @@ private ConflictCause propagateStrongly(int literal, int currentDecisionLevel, b while (watchIterator.hasNext()) { watchlist.add(watchIterator.next()); } + handleTrackersForNonBinaryConflict(); return conflictCause; } } + handleTrackersForNoConflict(); return null; } @@ -681,6 +718,48 @@ public void setChecksEnabled(boolean checksEnabled) { this.checksEnabled = checksEnabled; } + + private void incrementPropagationTracker() { + if (propagationTracker != null) { + propagationTracker.increment(); + } + } + + private void incrementPropagationConflictTracker() { + if (propagationTracker != null) { + propagationTracker.increment(); + } + } + + private void incrementNonbinPropagationTracker() { + if (nonbinPropagationTracker != null) { + nonbinPropagationTracker.increment(); + } + } + + private void incrementNonbinPropagationConflictTracker() { + if (nonbinPropagationConflictTracker != null) { + nonbinPropagationConflictTracker.increment(); + } + } + + private void handleTrackersForBinaryConflict() { + incrementPropagationTracker(); + incrementPropagationConflictTracker(); + } + + private void handleTrackersForNonBinaryConflict() { + incrementPropagationTracker(); + incrementNonbinPropagationTracker(); + incrementPropagationConflictTracker(); + incrementNonbinPropagationConflictTracker(); + } + + private void handleTrackersForNoConflict() { + incrementPropagationTracker(); + incrementNonbinPropagationTracker(); + } + class BinaryWatchList implements ShallowAntecedent { private int[] noGoodsWithoutHead = new int[10]; private int noGoodsWithoutHeadSize; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java index dc1c7e987..fc68c7e91 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java @@ -25,8 +25,11 @@ */ package at.ac.tuwien.kr.alpha.core.solver; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.StatTracker; import org.slf4j.Logger; +import java.util.List; + /** * Collects performance data (mainly number of decisions per second) and outputs them on demand. */ @@ -35,6 +38,7 @@ public class PerformanceLog { private final ChoiceManager choiceManager; private final TrailAssignment assignment; private final NoGoodCounter noGoodCounter; + private final List statTrackers; private final long msBetweenOutputs; private Long timeFirstEntry; @@ -44,11 +48,12 @@ public class PerformanceLog { /** * @param msBetweenOutputs minimum number of milliseconds that have to pass between writing of performance logs. */ - public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, NoGoodCounter noGoodCounter, long msBetweenOutputs) { + public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, NoGoodCounter noGoodCounter, List statTrackers, long msBetweenOutputs) { super(); this.choiceManager = choiceManager; this.assignment = assignment; this.noGoodCounter = noGoodCounter; + this.statTrackers = statTrackers; this.msBetweenOutputs = msBetweenOutputs; } @@ -72,6 +77,11 @@ public void writeIfTimeForLogging(Logger logger) { float decisionsPerSec = currentNumberOfChoices / overallTime; logger.info("Overall performance: {} decisions in {}s or {} decisions per sec. Overall replayed assignments: {}.", currentNumberOfChoices, overallTime, decisionsPerSec, assignment.replayCounter); logger.info("Current nogood counts: {}", noGoodCounter.getStatsByType()); + if (statTrackers != null) { + for (StatTracker statTracker : statTrackers) { + logger.info("Tracked [{}]: {}", statTracker.getStatName(), String.format("%f", statTracker.getStatValue())); + } + } } } } \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java new file mode 100644 index 000000000..670f83fa2 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +public class QuotientTracker implements StatTracker { + private final String name; + private final StatTracker numerator; + private final StatTracker denominator; + + public QuotientTracker(String name, StatTracker numerator, StatTracker denominator) { + this.name = name; + this.numerator = numerator; + this.denominator = denominator; + } + + @Override + public String getStatName() { + return name; + } + + @Override + public double getStatValue() { + if (denominator.getStatValue() == 0) { + return 0; + } + return numerator.getStatValue() / denominator.getStatValue(); + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java new file mode 100644 index 000000000..466faeeaf --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +public class SimpleCountingTracker implements StatTracker { + private String name; + private int count; + + public SimpleCountingTracker(String name) { + this.name = name; + this.count = 0; + } + + public void increment() { + count++; + } + + public void reset() { + count = 0; + } + + @Override + public String getStatName() { + return name; + } + + @Override + public double getStatValue() { + return count; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java new file mode 100644 index 000000000..139b5654c --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +public interface StatTracker { + String getStatName(); + double getStatValue(); +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java new file mode 100644 index 000000000..c0267e5d8 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +import at.ac.tuwien.kr.alpha.core.solver.NoGoodCounter; + +public class StaticNoGoodTracker implements StatTracker { + private final NoGoodCounter nogoodCounter; + + public StaticNoGoodTracker(NoGoodCounter nogoodCounter) { + this.nogoodCounter = nogoodCounter; + } + + @Override + public String getStatName() { + return "static_nogoods"; + } + + @Override + public double getStatValue() { + return extractStaticCount(nogoodCounter.getStatsByType()); + } + + private int extractStaticCount(String countStr) { + String[] parts = countStr.split(" "); + for (int i = 0; i < parts.length; i++) { + if (parts[i].equals("STATIC:") && i + 1 < parts.length) { + return Integer.parseInt(parts[i + 1]); + } + } + return 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java new file mode 100644 index 000000000..3f78fa6f1 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +import at.ac.tuwien.kr.alpha.core.solver.NoGoodCounter; + +public class TotalNoGoodTracker implements StatTracker { + private final NoGoodCounter nogoodCounter; + + public TotalNoGoodTracker(NoGoodCounter nogoodCounter) { + this.nogoodCounter = nogoodCounter; + } + + @Override + public String getStatName() { + return "total_nogoods"; + } + + @Override + public double getStatValue() { + return extractTotalCount(nogoodCounter.getStatsByType()); + } + + private int extractTotalCount(String countStr) { + int count = 0; + String[] parts = countStr.split(" "); + for (int i = 1; i < parts.length; i += 2) { + count += Integer.parseInt(parts[i]); + } + return count; + } +} \ No newline at end of file From b5f9474fed573d6b45aee2205d0129779e860e8b Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 21 Oct 2022 15:17:03 +0200 Subject: [PATCH 28/53] Move propagation stat tracking to separate class --- .../kr/alpha/core/solver/DefaultSolver.java | 28 +++--- .../alpha/core/solver/NaiveNoGoodStore.java | 21 +---- .../kr/alpha/core/solver/NoGoodStore.java | 10 +- .../core/solver/NoGoodStoreAlphaRoaming.java | 88 +++--------------- .../reboot/stats/PropagationStatManager.java | 92 +++++++++++++++++++ 5 files changed, 123 insertions(+), 116 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 53abee197..9bc2d2dae 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -140,10 +140,6 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.iterationTracker = new SimpleCountingTracker("iterations"); this.conflictTracker = new SimpleCountingTracker("conflicts"); this.decisionTracker = new SimpleCountingTracker("decisions"); - SimpleCountingTracker propagationTracker = new SimpleCountingTracker("prop_count"); - SimpleCountingTracker propagationConflictTracker = new SimpleCountingTracker("prop_conflicts"); - SimpleCountingTracker nonbinPropagationTracker = new SimpleCountingTracker("nonbin_prop_count"); - SimpleCountingTracker nonbinPropagationConflictTracker = new SimpleCountingTracker("nonbin_prop_conflicts"); StaticNoGoodTracker staticNoGoodTracker = new StaticNoGoodTracker(getNoGoodCounter()); TotalNoGoodTracker totalNoGoodTracker = new TotalNoGoodTracker(getNoGoodCounter()); @@ -151,19 +147,23 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, statTrackers.add(iterationTracker); statTrackers.add(conflictTracker); statTrackers.add(decisionTracker); - statTrackers.add(propagationTracker); - statTrackers.add(propagationConflictTracker); - statTrackers.add(nonbinPropagationTracker); - statTrackers.add(nonbinPropagationConflictTracker); + + PropagationStatManager propagationStatManager = this.store.getPropagationStatManager(); + if (propagationStatManager != null) { + List propagationTrackers = propagationStatManager.getStatTrackerList(); + statTrackers.addAll(propagationTrackers); + + StatTracker propagationTracker = propagationStatManager.getPropagationTracker(); + StatTracker propagationConflictTracker = propagationStatManager.getPropagationConflictTracker(); + StatTracker nonbinPropagationTracker = propagationStatManager.getNonbinPropagationTracker(); + StatTracker nonbinPropagationConflictTracker = propagationStatManager.getNonbinPropagationConflictTracker(); + statTrackers.add(new QuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); + statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); + } + statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodTracker, totalNoGoodTracker)); - statTrackers.add(new QuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); - statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); - this.store.setPropagationTracker(propagationTracker); - this.store.setPropagationConflictTracker(propagationConflictTracker); - this.store.setNonbinPropagationTracker(nonbinPropagationTracker); - this.store.setNonbinPropagationConflictTracker(nonbinPropagationConflictTracker); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), statTrackers, 1000); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java index eb21d6a86..4a811abdd 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java @@ -27,7 +27,7 @@ */ package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.SimpleCountingTracker; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.PropagationStatManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -147,23 +147,8 @@ public void reset() { } @Override - public void setPropagationTracker(SimpleCountingTracker tracker) { - - } - - @Override - public void setPropagationConflictTracker(SimpleCountingTracker tracker) { - - } - - @Override - public void setNonbinPropagationTracker(SimpleCountingTracker tracker) { - - } - - @Override - public void setNonbinPropagationConflictTracker(SimpleCountingTracker tracker) { - + public PropagationStatManager getPropagationStatManager() { + return null; } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java index 60380ecfb..5fb0feb10 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java @@ -1,7 +1,7 @@ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.core.common.NoGood; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.SimpleCountingTracker; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.PropagationStatManager; /** * An interface defining the use of a NoGood store. @@ -62,11 +62,5 @@ public interface NoGoodStore { */ void reset(); - void setPropagationTracker(SimpleCountingTracker tracker); - - void setPropagationConflictTracker(SimpleCountingTracker tracker); - - void setNonbinPropagationTracker(SimpleCountingTracker tracker); - - void setNonbinPropagationConflictTracker(SimpleCountingTracker tracker); + PropagationStatManager getPropagationStatManager(); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index 21b1dd433..a0f13670e 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -27,7 +27,7 @@ */ package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.SimpleCountingTracker; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.PropagationStatManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,16 +87,13 @@ public class NoGoodStoreAlphaRoaming implements NoGoodStore, BinaryNoGoodPropaga private boolean hasBinaryNoGoods; private final NoGoodCounter counter = new NoGoodCounter(); - - private SimpleCountingTracker propagationTracker; - private SimpleCountingTracker propagationConflictTracker; - private SimpleCountingTracker nonbinPropagationTracker; - private SimpleCountingTracker nonbinPropagationConflictTracker; + private final PropagationStatManager propagationStatManager; public NoGoodStoreAlphaRoaming(WritableAssignment assignment, boolean checksEnabled) { this.assignment = assignment; this.checksEnabled = checksEnabled; this.learnedNoGoodDeletion = new LearnedNoGoodDeletion(this, assignment); + this.propagationStatManager = new PropagationStatManager(); } public NoGoodStoreAlphaRoaming(WritableAssignment assignment) { @@ -165,31 +162,14 @@ public NoGoodCounter getNoGoodCounter() { public void reset() { clear(); counter.reset(); - propagationTracker.reset(); - propagationConflictTracker.reset(); - nonbinPropagationTracker.reset(); - nonbinPropagationConflictTracker.reset(); - } - - @Override - public void setPropagationTracker(SimpleCountingTracker tracker) { - this.propagationTracker = tracker; - } - - @Override - public void setPropagationConflictTracker(SimpleCountingTracker tracker) { - this.propagationConflictTracker = tracker; + propagationStatManager.reset(); } @Override - public void setNonbinPropagationTracker(SimpleCountingTracker tracker) { - this.nonbinPropagationTracker = tracker; + public PropagationStatManager getPropagationStatManager() { + return propagationStatManager; } - @Override - public void setNonbinPropagationConflictTracker(SimpleCountingTracker tracker) { - this.nonbinPropagationConflictTracker = tracker; - } @Override public void cleanupLearnedNoGoods() { @@ -488,14 +468,12 @@ private ConflictCause assignTruth(int atom, ThriceTruth truth, Antecedent implie * @param literal the literal that triggers the propagation. */ private ConflictCause propagateWeakly(int literal, int currentDecisionLevel, boolean restrictToBinaryNoGoods) { - incrementPropagationTracker(); - incrementNonbinPropagationTracker(); final ArrayList watchesOfAssignedAtom = watches(literal); // Propagate binary watches. ConflictCause conflictCause = binaryWatches[literal].propagateWeakly(); if (conflictCause != null || restrictToBinaryNoGoods) { - handleTrackersForBinaryConflict(); + propagationStatManager.handleBinaryConflict(); return conflictCause; } @@ -512,11 +490,11 @@ private ConflictCause propagateWeakly(int literal, int currentDecisionLevel, boo while (watchIterator.hasNext()) { watchlist.add(watchIterator.next()); } - handleTrackersForNonBinaryConflict(); + propagationStatManager.handleNonBinaryConflict(); return conflictCause; } } - handleTrackersForNoConflict(); + propagationStatManager.handleNoConflict(); return null; } @@ -588,7 +566,7 @@ private ConflictCause propagateStrongly(int literal, int currentDecisionLevel, b // Propagate binary watches. ConflictCause conflictCause = binaryWatches[literal].propagateStrongly(); if (conflictCause != null || restrictToBinaryNoGoods) { - handleTrackersForBinaryConflict(); + propagationStatManager.handleBinaryConflict(); return conflictCause; } @@ -608,11 +586,11 @@ private ConflictCause propagateStrongly(int literal, int currentDecisionLevel, b while (watchIterator.hasNext()) { watchlist.add(watchIterator.next()); } - handleTrackersForNonBinaryConflict(); + propagationStatManager.handleNonBinaryConflict(); return conflictCause; } } - handleTrackersForNoConflict(); + propagationStatManager.handleNoConflict(); return null; } @@ -718,48 +696,6 @@ public void setChecksEnabled(boolean checksEnabled) { this.checksEnabled = checksEnabled; } - - private void incrementPropagationTracker() { - if (propagationTracker != null) { - propagationTracker.increment(); - } - } - - private void incrementPropagationConflictTracker() { - if (propagationTracker != null) { - propagationTracker.increment(); - } - } - - private void incrementNonbinPropagationTracker() { - if (nonbinPropagationTracker != null) { - nonbinPropagationTracker.increment(); - } - } - - private void incrementNonbinPropagationConflictTracker() { - if (nonbinPropagationConflictTracker != null) { - nonbinPropagationConflictTracker.increment(); - } - } - - private void handleTrackersForBinaryConflict() { - incrementPropagationTracker(); - incrementPropagationConflictTracker(); - } - - private void handleTrackersForNonBinaryConflict() { - incrementPropagationTracker(); - incrementNonbinPropagationTracker(); - incrementPropagationConflictTracker(); - incrementNonbinPropagationConflictTracker(); - } - - private void handleTrackersForNoConflict() { - incrementPropagationTracker(); - incrementNonbinPropagationTracker(); - } - class BinaryWatchList implements ShallowAntecedent { private int[] noGoodsWithoutHead = new int[10]; private int noGoodsWithoutHeadSize; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java new file mode 100644 index 000000000..f6becc4dc --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +import java.util.ArrayList; +import java.util.List; + +public class PropagationStatManager { + private final SimpleCountingTracker propagationTracker; + private final SimpleCountingTracker propagationConflictTracker; + private final SimpleCountingTracker nonbinPropagationTracker; + private final SimpleCountingTracker nonbinPropagationConflictTracker; + + public PropagationStatManager() { + this.propagationTracker = new SimpleCountingTracker("prop_count"); + this.propagationConflictTracker = new SimpleCountingTracker("prop_conflicts"); + this.nonbinPropagationTracker = new SimpleCountingTracker("nonbin_prop_count"); + this.nonbinPropagationConflictTracker = new SimpleCountingTracker("nonbin_prop_conflicts"); + } + + public StatTracker getPropagationTracker() { + return propagationTracker; + } + + public StatTracker getPropagationConflictTracker() { + return propagationConflictTracker; + } + + public StatTracker getNonbinPropagationTracker() { + return nonbinPropagationTracker; + } + + public StatTracker getNonbinPropagationConflictTracker() { + return nonbinPropagationConflictTracker; + } + + public List getStatTrackerList() { + List statTrackers = new ArrayList<>(); + statTrackers.add(propagationTracker); + statTrackers.add(propagationConflictTracker); + statTrackers.add(nonbinPropagationTracker); + statTrackers.add(nonbinPropagationConflictTracker); + return statTrackers; + } + + public void handleBinaryConflict() { + propagationTracker.increment(); + propagationConflictTracker.increment(); + } + + public void handleNonBinaryConflict() { + propagationTracker.increment(); + nonbinPropagationTracker.increment(); + propagationConflictTracker.increment(); + nonbinPropagationConflictTracker.increment(); + } + + public void handleNoConflict() { + propagationTracker.increment(); + nonbinPropagationTracker.increment(); + } + + public void reset() { + propagationTracker.reset(); + propagationConflictTracker.reset(); + nonbinPropagationTracker.reset(); + nonbinPropagationConflictTracker.reset(); + } +} From 5c518b3ada8671abaf1dcd9461f072939cf0d38e Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 21 Oct 2022 16:00:06 +0200 Subject: [PATCH 29/53] Extend reboot strategy interface --- .../kr/alpha/core/solver/DefaultSolver.java | 68 +++++++++-------- .../reboot/AtomizedNoGoodCollection.java | 10 +++ .../FixedConflictRebootStrategy.java | 73 +++++++++++++++++++ ....java => FixedDecisionRebootStrategy.java} | 37 ++++++++-- .../FixedIterationRebootStrategy.java | 73 +++++++++++++++++++ ...a => GeometricConflictRebootStrategy.java} | 34 +++++++-- ...y.java => LubyConflictRebootStrategy.java} | 32 ++++++-- .../reboot/strategies/RebootStrategy.java | 16 +++- 8 files changed, 293 insertions(+), 50 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{FixedRebootStrategy.java => FixedDecisionRebootStrategy.java} (74%) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{GeometricRebootStrategy.java => GeometricConflictRebootStrategy.java} (76%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{LubyRebootStrategy.java => LubyConflictRebootStrategy.java} (80%) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 9bc2d2dae..1361900cc 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -43,7 +43,7 @@ import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedNoGoodCollection; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.*; -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedRebootStrategy; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedIterationRebootStrategy; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; import at.ac.tuwien.kr.alpha.core.util.StopWatch; import org.slf4j.Logger; @@ -131,7 +131,7 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.rebootEnabled = config.isRebootEnabled(); this.disableRebootRepeat = config.isDisableRebootRepeat(); - this.rebootStrategy = new FixedRebootStrategy(config.getRebootIterations()); + this.rebootStrategy = new FixedIterationRebootStrategy(config.getRebootIterations()); this.solverStopWatch = new StopWatch(); this.grounderStopWatch = new StopWatch(); @@ -140,29 +140,7 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.iterationTracker = new SimpleCountingTracker("iterations"); this.conflictTracker = new SimpleCountingTracker("conflicts"); this.decisionTracker = new SimpleCountingTracker("decisions"); - StaticNoGoodTracker staticNoGoodTracker = new StaticNoGoodTracker(getNoGoodCounter()); - TotalNoGoodTracker totalNoGoodTracker = new TotalNoGoodTracker(getNoGoodCounter()); - - List statTrackers = new LinkedList<>(); - statTrackers.add(iterationTracker); - statTrackers.add(conflictTracker); - statTrackers.add(decisionTracker); - - PropagationStatManager propagationStatManager = this.store.getPropagationStatManager(); - if (propagationStatManager != null) { - List propagationTrackers = propagationStatManager.getStatTrackerList(); - statTrackers.addAll(propagationTrackers); - - StatTracker propagationTracker = propagationStatManager.getPropagationTracker(); - StatTracker propagationConflictTracker = propagationStatManager.getPropagationConflictTracker(); - StatTracker nonbinPropagationTracker = propagationStatManager.getNonbinPropagationTracker(); - StatTracker nonbinPropagationConflictTracker = propagationStatManager.getNonbinPropagationConflictTracker(); - statTrackers.add(new QuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); - statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); - } - - statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); - statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodTracker, totalNoGoodTracker)); + List statTrackers = initStatTrackers(); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), statTrackers, 1000); @@ -189,7 +167,7 @@ protected boolean tryAdvance(Consumer action) { } // Try all assignments until grounder reports no more NoGoods and all of them are satisfied while (true) { - rebootStrategy.stepPerformed(); + rebootStrategy.nextIteration(); iterationTracker.increment(); performanceLog.writeIfTimeForLogging(LOGGER); if (searchState.isSearchSpaceCompletelyExplored) { @@ -203,10 +181,10 @@ protected boolean tryAdvance(Consumer action) { LOGGER.debug("Conflict encountered, analyzing conflict."); learnFromConflict(conflictCause); conflictTracker.increment(); + rebootStrategy.conflictEncountered(); } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); syncWithGrounder(); -// } else if (rebootEnabled && iterationCounter >= rebootIterationBreakpoint) { } else if (rebootEnabled && rebootStrategy.isRebootScheduled()) { reboot(); rebootStrategy.rebootPerformed(); @@ -215,6 +193,7 @@ protected boolean tryAdvance(Consumer action) { } } else if (choose()) { LOGGER.debug("Did choice."); + rebootStrategy.decisionMade(); } else if (close()) { LOGGER.debug("Closed unassigned known atoms (assigning FALSE)."); } else if (assignment.getMBTCount() == 0) { @@ -375,6 +354,7 @@ private boolean learnBackjumpAddFromConflict(ConflictCause conflictCause) { choiceManager.backjump(analysisResult.backjumpLevel); final NoGood learnedNoGood = analysisResult.learnedNoGood; learnedNoGoods.add(learnedNoGood); + rebootStrategy.newLearnedNoGood(learnedNoGood); int noGoodId = grounder.register(learnedNoGood); return addAndBackjumpIfNecessary(noGoodId, learnedNoGood, analysisResult.lbd); } @@ -495,9 +475,8 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { } // Add newly obtained noGoods. boolean success = ingest(obtained); - for (NoGood noGood : obtained.values()) { - learnedNoGoods.add(noGood); - } + learnedNoGoods.addAll(obtained.values()); + rebootStrategy.newLearnedNoGoods(obtained.values()); if (!success) { logStats(); return false; @@ -546,6 +525,7 @@ private boolean backtrack() { private boolean ingest(Map obtained) { growForMaxAtomId(); branchingHeuristic.newNoGoods(obtained.values()); + rebootStrategy.newNoGoods(obtained.values()); LinkedList> noGoodsToAdd = new LinkedList<>(obtained.entrySet()); Map.Entry entry; @@ -734,6 +714,34 @@ private void stopSolverWatchAndLogRuntimes() { LOGGER.info("Propagation runtime: {}", propagationStopWatch.getNanoTime()); } + private List initStatTrackers() { + StaticNoGoodTracker staticNoGoodTracker = new StaticNoGoodTracker(getNoGoodCounter()); + TotalNoGoodTracker totalNoGoodTracker = new TotalNoGoodTracker(getNoGoodCounter()); + + List statTrackers = new LinkedList<>(); + statTrackers.add(iterationTracker); + statTrackers.add(conflictTracker); + statTrackers.add(decisionTracker); + + PropagationStatManager propagationStatManager = this.store.getPropagationStatManager(); + if (propagationStatManager != null) { + List propagationTrackers = propagationStatManager.getStatTrackerList(); + statTrackers.addAll(propagationTrackers); + + StatTracker propagationTracker = propagationStatManager.getPropagationTracker(); + StatTracker propagationConflictTracker = propagationStatManager.getPropagationConflictTracker(); + StatTracker nonbinPropagationTracker = propagationStatManager.getNonbinPropagationTracker(); + StatTracker nonbinPropagationConflictTracker = propagationStatManager.getNonbinPropagationConflictTracker(); + statTrackers.add(new QuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); + statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); + } + + statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); + statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodTracker, totalNoGoodTracker)); + + return statTrackers; + } + @Override public int getNumberOfChoices() { return choiceManager.getChoices(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java index c6893b075..4a8ab80a9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedNoGoodCollection.java @@ -28,6 +28,7 @@ import at.ac.tuwien.kr.alpha.core.common.AtomStore; import at.ac.tuwien.kr.alpha.core.common.NoGood; +import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -59,6 +60,15 @@ public void add(NoGood noGood) { atomizedNoGoods.add(new NoGoodAtomizer(noGood, atomStore)); } + /** + * see {@link AtomizedNoGoodCollection#add(NoGood)} + * + * @param noGoods the nogoods to add + */ + public void addAll(Collection noGoods) { + noGoods.forEach(this::add); + } + /** * Gets all nogoods in the collection with atom ids based on the current {@link AtomStore}. * diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java new file mode 100644 index 000000000..a8382a5b5 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class FixedConflictRebootStrategy implements RebootStrategy { + private final int breakpoint; + private int conflictCount; + + public FixedConflictRebootStrategy(int breakpoint) { + this.breakpoint = breakpoint; + this.conflictCount = 0; + } + + @Override + public void nextIteration() { + + } + + @Override + public void decisionMade() { + + } + + @Override + public void conflictEncountered() { + conflictCount++; + } + + @Override + public void newNoGood(NoGood noGood) { + + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + + } + + @Override + public boolean isRebootScheduled() { + return conflictCount >= breakpoint; + } + + @Override + public void rebootPerformed() { + conflictCount = 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java similarity index 74% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java index 311255f93..33c246ce5 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java @@ -25,27 +25,48 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -public class FixedRebootStrategy implements RebootStrategy { +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class FixedDecisionRebootStrategy implements RebootStrategy { private final int breakpoint; - private int stepCount; + private int decisionCount; - public FixedRebootStrategy(int breakpoint) { + public FixedDecisionRebootStrategy(int breakpoint) { this.breakpoint = breakpoint; - this.stepCount = 0; + this.decisionCount = 0; + } + + @Override + public void nextIteration() { + } + + @Override + public void decisionMade() { + decisionCount++; + } + + @Override + public void conflictEncountered() { + + } + + @Override + public void newNoGood(NoGood noGood) { + } @Override - public void stepPerformed() { - stepCount++; + public void newLearnedNoGood(NoGood noGood) { + } @Override public boolean isRebootScheduled() { - return stepCount >= breakpoint; + return decisionCount >= breakpoint; } @Override public void rebootPerformed() { - stepCount = 0; + decisionCount = 0; } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java new file mode 100644 index 000000000..b67664a92 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class FixedIterationRebootStrategy implements RebootStrategy { + private final int breakpoint; + private int iterationCount; + + public FixedIterationRebootStrategy(int breakpoint) { + this.breakpoint = breakpoint; + this.iterationCount = 0; + } + + @Override + public void nextIteration() { + iterationCount++; + } + + @Override + public void decisionMade() { + + } + + @Override + public void conflictEncountered() { + + } + + @Override + public void newNoGood(NoGood noGood) { + + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + + } + + @Override + public boolean isRebootScheduled() { + return iterationCount >= breakpoint; + } + + @Override + public void rebootPerformed() { + iterationCount = 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java similarity index 76% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java index 36eba3d06..205410a8b 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java @@ -25,26 +25,48 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -public class GeometricRebootStrategy implements RebootStrategy { +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class GeometricConflictRebootStrategy implements RebootStrategy { private static final double BASE = 1.5; private static final double SCALING_FACTOR = 2; private int rebootCount; - private int stepCount; + private int conflictCount; + + @Override + public void nextIteration() { + + } + + @Override + public void decisionMade() { + + } @Override - public void stepPerformed() { - stepCount++; + public void conflictEncountered() { + conflictCount++; + } + + @Override + public void newNoGood(NoGood noGood) { + + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + } @Override public boolean isRebootScheduled() { - return stepCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); + return conflictCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); } @Override public void rebootPerformed() { rebootCount++; - stepCount = 0; + conflictCount = 0; } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java similarity index 80% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java index f32527289..307e0ed5d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java @@ -25,20 +25,42 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -public class LubyRebootStrategy implements RebootStrategy { +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class LubyConflictRebootStrategy implements RebootStrategy { private static final double SCALING_FACTOR = 10; private int rebootCount; - private int stepCount; + private int conflictCount; + + @Override + public void nextIteration() { + + } + + @Override + public void decisionMade() { + + } @Override - public void stepPerformed() { - stepCount++; + public void conflictEncountered() { + conflictCount++; + } + + @Override + public void newNoGood(NoGood noGood) { + + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + } @Override public boolean isRebootScheduled() { - return stepCount >= SCALING_FACTOR * luby(rebootCount + 1); + return conflictCount >= SCALING_FACTOR * luby(rebootCount + 1); } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java index 387409bc1..724b88fba 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java @@ -25,8 +25,22 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +import java.util.Collection; + public interface RebootStrategy { - void stepPerformed(); + void nextIteration(); + void decisionMade(); + void conflictEncountered(); + void newNoGood(NoGood noGood); + default void newNoGoods(Collection newNoGoods) { + newNoGoods.forEach(this::newNoGood); + } + void newLearnedNoGood(NoGood noGood); + default void newLearnedNoGoods(Collection newNoGoods) { + newNoGoods.forEach(this::newLearnedNoGood); + } boolean isRebootScheduled(); void rebootPerformed(); } From 91640c20002fd66a8f64412fd001d64b3ae77ae6 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 2 Nov 2022 18:09:12 +0100 Subject: [PATCH 30/53] Implement simple dynamic reboot strategy --- .../kr/alpha/core/solver/DefaultSolver.java | 60 +++++--- .../reboot/stats/LearnedNoGoodTracker.java | 56 ++++++++ .../reboot/stats/PropagationStatManager.java | 12 +- .../stats/ResettableQuotientTracker.java | 57 ++++++++ .../reboot/stats/ResettableStatTracker.java | 30 ++++ .../reboot/stats/SimpleCountingTracker.java | 10 +- .../reboot/stats/StaticNoGoodTracker.java | 2 +- .../solver/reboot/stats/StopWatchTracker.java | 53 +++++++ .../reboot/stats/TotalNoGoodTracker.java | 2 +- .../DynamicLearnedIntervalRebootStrategy.java | 131 ++++++++++++++++++ .../FixedLearnedRebootStrategy.java | 48 +++++++ .../tuwien/kr/alpha/core/util/StopWatch.java | 24 ++++ 12 files changed, 458 insertions(+), 27 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 1361900cc..d6cb2f7f1 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -43,7 +43,7 @@ import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedNoGoodCollection; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.*; -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedIterationRebootStrategy; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.DynamicLearnedIntervalRebootStrategy; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; import at.ac.tuwien.kr.alpha.core.util.StopWatch; import org.slf4j.Logger; @@ -111,9 +111,13 @@ private static class SearchState { private final StopWatch solverStopWatch; private final StopWatch grounderStopWatch; private final StopWatch propagationStopWatch; + private final StopWatch mbtBacktrackingStopWatch; + private final StopWatch epochStopWatch; private final SimpleCountingTracker iterationTracker; private final SimpleCountingTracker conflictTracker; private final SimpleCountingTracker decisionTracker; + private final SimpleCountingTracker learnedNoGoodTracker; + private final ResettableStatTracker learnEfficiencyTracker; public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); @@ -129,19 +133,27 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableJustifications = config.isDisableJustificationSearch(); this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); - this.rebootEnabled = config.isRebootEnabled(); - this.disableRebootRepeat = config.isDisableRebootRepeat(); - this.rebootStrategy = new FixedIterationRebootStrategy(config.getRebootIterations()); - this.solverStopWatch = new StopWatch(); this.grounderStopWatch = new StopWatch(); this.propagationStopWatch = new StopWatch(); + this.mbtBacktrackingStopWatch = new StopWatch(); + this.epochStopWatch = new StopWatch(); this.iterationTracker = new SimpleCountingTracker("iterations"); this.conflictTracker = new SimpleCountingTracker("conflicts"); this.decisionTracker = new SimpleCountingTracker("decisions"); + this.learnedNoGoodTracker = new SimpleCountingTracker("learned_nogoods"); + this.learnEfficiencyTracker = new ResettableQuotientTracker("learn_effic", + learnedNoGoodTracker, new StopWatchTracker("solver_time", epochStopWatch)); List statTrackers = initStatTrackers(); + this.rebootEnabled = config.isRebootEnabled(); + this.disableRebootRepeat = config.isDisableRebootRepeat(); + DynamicLearnedIntervalRebootStrategy dynamicRebootStrategy = new DynamicLearnedIntervalRebootStrategy( + learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); + this.rebootStrategy = dynamicRebootStrategy; + statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); + this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), statTrackers, 1000); } @@ -160,6 +172,7 @@ private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAss @Override protected boolean tryAdvance(Consumer action) { solverStopWatch.start(); + epochStopWatch.start(); if (!searchState.hasBeenInitialized) { initializeSearch(); } else { @@ -201,7 +214,9 @@ protected boolean tryAdvance(Consumer action) { stopSolverWatchAndLogRuntimes(); return true; } else { + mbtBacktrackingStopWatch.start(); backtrackFromMBTsRemaining(); + mbtBacktrackingStopWatch.stop(); } } } @@ -355,6 +370,7 @@ private boolean learnBackjumpAddFromConflict(ConflictCause conflictCause) { final NoGood learnedNoGood = analysisResult.learnedNoGood; learnedNoGoods.add(learnedNoGood); rebootStrategy.newLearnedNoGood(learnedNoGood); + learnedNoGoodTracker.increment(); int noGoodId = grounder.register(learnedNoGood); return addAndBackjumpIfNecessary(noGoodId, learnedNoGood, analysisResult.lbd); } @@ -477,6 +493,7 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { boolean success = ingest(obtained); learnedNoGoods.addAll(obtained.values()); rebootStrategy.newLearnedNoGoods(obtained.values()); + learnedNoGoodTracker.incrementBy(obtained.values().size()); if (!success) { logStats(); return false; @@ -635,7 +652,7 @@ private Stack getAtomizedChoiceStack() { */ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack) { if (propagate() != null) { - throw oops("Conflict in replay during reboot."); + throw oops("Conflict in replay during reboot"); } for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { @@ -655,11 +672,11 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack if (activeChoice) { if (propagate() != null) { - throw oops("Conflict in replay during reboot."); + throw oops("Conflict in replay during reboot"); } syncWithGrounder(); if (propagate() != null) { - throw oops("Conflict in replay during reboot."); + throw oops("Conflict in replay during reboot"); } } } @@ -709,35 +726,44 @@ private void simulateOldConflicts() { */ private void stopSolverWatchAndLogRuntimes() { solverStopWatch.stop(); + epochStopWatch.stop(); LOGGER.info("Solver runtime: {}", solverStopWatch.getNanoTime()); LOGGER.info("Grounder runtime: {}", grounderStopWatch.getNanoTime()); LOGGER.info("Propagation runtime: {}", propagationStopWatch.getNanoTime()); + LOGGER.info("Mbt-backtracking runtime: {}", mbtBacktrackingStopWatch.getNanoTime()); + LOGGER.info("Epoch runtime: {}", epochStopWatch.getNanoTime()); } private List initStatTrackers() { - StaticNoGoodTracker staticNoGoodTracker = new StaticNoGoodTracker(getNoGoodCounter()); - TotalNoGoodTracker totalNoGoodTracker = new TotalNoGoodTracker(getNoGoodCounter()); + StaticNoGoodTracker staticNoGoodExtrTracker = new StaticNoGoodTracker(getNoGoodCounter()); + LearnedNoGoodTracker learnedNoGoodExtrTracker = new LearnedNoGoodTracker(getNoGoodCounter()); + TotalNoGoodTracker totalNoGoodExtrTracker = new TotalNoGoodTracker(getNoGoodCounter()); List statTrackers = new LinkedList<>(); statTrackers.add(iterationTracker); statTrackers.add(conflictTracker); statTrackers.add(decisionTracker); + statTrackers.add(learnedNoGoodTracker); + statTrackers.add(staticNoGoodExtrTracker); + statTrackers.add(learnedNoGoodExtrTracker); + statTrackers.add(totalNoGoodExtrTracker); + statTrackers.add(learnEfficiencyTracker); PropagationStatManager propagationStatManager = this.store.getPropagationStatManager(); if (propagationStatManager != null) { - List propagationTrackers = propagationStatManager.getStatTrackerList(); + List propagationTrackers = propagationStatManager.getStatTrackerList(); statTrackers.addAll(propagationTrackers); - StatTracker propagationTracker = propagationStatManager.getPropagationTracker(); - StatTracker propagationConflictTracker = propagationStatManager.getPropagationConflictTracker(); - StatTracker nonbinPropagationTracker = propagationStatManager.getNonbinPropagationTracker(); - StatTracker nonbinPropagationConflictTracker = propagationStatManager.getNonbinPropagationConflictTracker(); - statTrackers.add(new QuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); + ResettableStatTracker propagationTracker = propagationStatManager.getPropagationTracker(); + ResettableStatTracker propagationConflictTracker = propagationStatManager.getPropagationConflictTracker(); + ResettableStatTracker nonbinPropagationTracker = propagationStatManager.getNonbinPropagationTracker(); + ResettableStatTracker nonbinPropagationConflictTracker = propagationStatManager.getNonbinPropagationConflictTracker(); + statTrackers.add(new ResettableQuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); } statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); - statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodTracker, totalNoGoodTracker)); + statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodExtrTracker, totalNoGoodExtrTracker)); return statTrackers; } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java new file mode 100644 index 000000000..04f8fc41a --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +import at.ac.tuwien.kr.alpha.core.solver.NoGoodCounter; + +public class LearnedNoGoodTracker implements StatTracker { + private final NoGoodCounter nogoodCounter; + + public LearnedNoGoodTracker(NoGoodCounter nogoodCounter) { + this.nogoodCounter = nogoodCounter; + } + + @Override + public String getStatName() { + return "_learned_nogoods"; + } + + @Override + public double getStatValue() { + return extractStaticCount(nogoodCounter.getStatsByType()); + } + + private int extractStaticCount(String countStr) { + String[] parts = countStr.split(" "); + for (int i = 0; i < parts.length; i++) { + if (parts[i].equals("LEARNT:") && i + 1 < parts.length) { + return Integer.parseInt(parts[i + 1]); + } + } + return 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java index f6becc4dc..55e0cf46d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java @@ -41,24 +41,24 @@ public PropagationStatManager() { this.nonbinPropagationConflictTracker = new SimpleCountingTracker("nonbin_prop_conflicts"); } - public StatTracker getPropagationTracker() { + public ResettableStatTracker getPropagationTracker() { return propagationTracker; } - public StatTracker getPropagationConflictTracker() { + public ResettableStatTracker getPropagationConflictTracker() { return propagationConflictTracker; } - public StatTracker getNonbinPropagationTracker() { + public ResettableStatTracker getNonbinPropagationTracker() { return nonbinPropagationTracker; } - public StatTracker getNonbinPropagationConflictTracker() { + public ResettableStatTracker getNonbinPropagationConflictTracker() { return nonbinPropagationConflictTracker; } - public List getStatTrackerList() { - List statTrackers = new ArrayList<>(); + public List getStatTrackerList() { + List statTrackers = new ArrayList<>(); statTrackers.add(propagationTracker); statTrackers.add(propagationConflictTracker); statTrackers.add(nonbinPropagationTracker); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java new file mode 100644 index 000000000..cf70a9341 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +public class ResettableQuotientTracker implements ResettableStatTracker { + private final String name; + private final ResettableStatTracker numerator; + private final ResettableStatTracker denominator; + + public ResettableQuotientTracker(String name, ResettableStatTracker numerator, ResettableStatTracker denominator) { + this.name = name; + this.numerator = numerator; + this.denominator = denominator; + } + + @Override + public String getStatName() { + return name; + } + + @Override + public double getStatValue() { + if (denominator.getStatValue() == 0) { + return 0; + } + return numerator.getStatValue() / denominator.getStatValue(); + } + + @Override + public void reset() { + numerator.reset(); + denominator.reset(); + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java new file mode 100644 index 000000000..a3fe41a65 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +public interface ResettableStatTracker extends StatTracker { + void reset(); +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java index 466faeeaf..90f09fa74 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java @@ -25,8 +25,8 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; -public class SimpleCountingTracker implements StatTracker { - private String name; +public class SimpleCountingTracker implements ResettableStatTracker { + private final String name; private int count; public SimpleCountingTracker(String name) { @@ -38,6 +38,12 @@ public void increment() { count++; } + public void incrementBy(int i) { + if (i >= 0) { + count += i; + } + } + public void reset() { count = 0; } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java index c0267e5d8..818184c65 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java @@ -36,7 +36,7 @@ public StaticNoGoodTracker(NoGoodCounter nogoodCounter) { @Override public String getStatName() { - return "static_nogoods"; + return "_static_nogoods"; } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java new file mode 100644 index 000000000..282d68aab --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; + +import at.ac.tuwien.kr.alpha.core.util.StopWatch; + +public class StopWatchTracker implements ResettableStatTracker { + private final String name; + private final StopWatch stopWatch; + + public StopWatchTracker(String name, StopWatch stopWatch) { + this.name = name; + this.stopWatch = stopWatch; + } + + @Override + public String getStatName() { + return name; + } + + @Override + public double getStatValue() { + return stopWatch.getTime(); + } + + @Override + public void reset() { + stopWatch.reset(); + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java index 3f78fa6f1..48d0df571 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java @@ -36,7 +36,7 @@ public TotalNoGoodTracker(NoGoodCounter nogoodCounter) { @Override public String getStatName() { - return "total_nogoods"; + return "_total_nogoods"; } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java new file mode 100644 index 000000000..dd8af39bf --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.ResettableStatTracker; +import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.StatTracker; + +public class DynamicLearnedIntervalRebootStrategy implements RebootStrategy { + private final ResettableStatTracker efficiencyMeasure; + private final StatTracker intervalSizeTracker; + private final int minInterval; + private final double scalingFactor; + private double intervalSize; + private int learnedCount; + private double previousIntervalMeasure; + private boolean isFirstInterval; + + public DynamicLearnedIntervalRebootStrategy(ResettableStatTracker efficiencyMeasure, + double scalingFactor, + int minInterval, int startInterval) { + this.efficiencyMeasure = efficiencyMeasure; + this.intervalSizeTracker = new StatTracker() { + @Override + public String getStatName() { + return "interval_size"; + } + + @Override + public double getStatValue() { + return intervalSize; + } + }; + this.scalingFactor = scalingFactor; + this.minInterval = minInterval; + this.intervalSize = startInterval; + this.learnedCount = 0; + this.previousIntervalMeasure = 0; + this.isFirstInterval = true; + } + + public StatTracker getIntervalSizeTracker() { + return intervalSizeTracker; + } + + @Override + public void nextIteration() { + + } + + @Override + public void decisionMade() { + + } + + @Override + public void conflictEncountered() { + + } + + @Override + public void newNoGood(NoGood noGood) { + learnedCount++; + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + + } + + @Override + public boolean isRebootScheduled() { + return learnedCount >= (int) intervalSize; + } + + @Override + public void rebootPerformed() { + double currentIntervalMeasure = efficiencyMeasure.getStatValue(); + intervalSize = getNewIntervalSize(currentIntervalMeasure); + previousIntervalMeasure = currentIntervalMeasure; + + efficiencyMeasure.reset(); + learnedCount = 0; + } + + private double getNewIntervalSize(double currentIntervalMeasure) { + double oldIntervalSize = intervalSize; + + if (isFirstInterval) { + isFirstInterval = false; + return intervalSize; + } else if (currentIntervalMeasure > previousIntervalMeasure) { + double newIntervalSize = intervalSize * scalingFactor; + System.out.printf("# Reboot performed. Interval size (old -> new): %f -> %f [+ scaled down]\n", + oldIntervalSize, intervalSize); + System.out.printf("# Reason (old, new): %f < %f\n", + previousIntervalMeasure, currentIntervalMeasure); + return Math.max(newIntervalSize, minInterval); + } else { + double newIntervalSize = intervalSize / scalingFactor; + System.out.printf("# Reboot performed. Interval size (old -> new): %f -> %f [- scaled up]\n", + oldIntervalSize, intervalSize); + System.out.printf("# Reason (old, new): %f >= %f\n", + previousIntervalMeasure, currentIntervalMeasure); + return Math.max(newIntervalSize, minInterval); + } + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java new file mode 100644 index 000000000..9bd1d7dcc --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java @@ -0,0 +1,48 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class FixedLearnedRebootStrategy implements RebootStrategy { + private int breakpoint; + private int learnedCounter; + + public FixedLearnedRebootStrategy(int breakpoint) { + this.breakpoint = breakpoint; + this.learnedCounter = 0; + } + + @Override + public void nextIteration() { + + } + + @Override + public void decisionMade() { + + } + + @Override + public void conflictEncountered() { + + } + + @Override + public void newNoGood(NoGood noGood) { + + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + learnedCounter++; + } + + @Override + public boolean isRebootScheduled() { + return learnedCounter >= breakpoint; + } + + @Override + public void rebootPerformed() { + learnedCounter = 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java index b3c389aca..240d1d701 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java @@ -59,4 +59,28 @@ public long getNanoTime() { long currentNanos = running ? System.nanoTime() - startTime : 0; return nanoTime + currentNanos; } + + /** + * Returns the time in milliseconds the {@link StopWatch} has been running in total. + * @return the total running time of the {@link StopWatch} in milliseconds. + */ + public double getMilliTime() { + return (long)(getNanoTime() / 1e6); + } + + /** + * Returns the time in seconds the {@link StopWatch} has been running in total. + * @return the total running time of the {@link StopWatch} in seconds. + */ + public double getTime() { + return getNanoTime() / 1e9; + } + + /** + * Resets the {@link StopWatch} but keeps it running if it was running before. + */ + public void reset() { + nanoTime = 0; + startTime = System.nanoTime(); + } } From 52b54e49bce1ac1357e9e3f4b8fb9c6415e60c38 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 3 Nov 2022 12:20:05 +0100 Subject: [PATCH 31/53] Minor naming and documentation changes --- .../kr/alpha/core/solver/DefaultSolver.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index d6cb2f7f1..b5fe663c9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -186,7 +186,7 @@ protected boolean tryAdvance(Consumer action) { if (searchState.isSearchSpaceCompletelyExplored) { LOGGER.debug("Search space has been fully explored, there are no more answer-sets."); logStats(); - stopSolverWatchAndLogRuntimes(); + stopStopWatchesAndLogRuntimes(); return false; } ConflictCause conflictCause = propagate(); @@ -211,7 +211,7 @@ protected boolean tryAdvance(Consumer action) { LOGGER.debug("Closed unassigned known atoms (assigning FALSE)."); } else if (assignment.getMBTCount() == 0) { provideAnswerSet(action); - stopSolverWatchAndLogRuntimes(); + stopStopWatchesAndLogRuntimes(); return true; } else { mbtBacktrackingStopWatch.start(); @@ -721,10 +721,10 @@ private void simulateOldConflicts() { } /** - * Stops the {@link DefaultSolver#solverStopWatch} and logs the current total time - * of {@link DefaultSolver#solverStopWatch} and {@link DefaultSolver#grounderStopWatch}. + * Stops the {@link DefaultSolver#solverStopWatch} and {@link DefaultSolver#epochStopWatch}. + * Then logs the current total time of all {@link StopWatch}es kept by the {@link DefaultSolver}. */ - private void stopSolverWatchAndLogRuntimes() { + private void stopStopWatchesAndLogRuntimes() { solverStopWatch.stop(); epochStopWatch.stop(); LOGGER.info("Solver runtime: {}", solverStopWatch.getNanoTime()); @@ -735,18 +735,18 @@ private void stopSolverWatchAndLogRuntimes() { } private List initStatTrackers() { - StaticNoGoodTracker staticNoGoodExtrTracker = new StaticNoGoodTracker(getNoGoodCounter()); - LearnedNoGoodTracker learnedNoGoodExtrTracker = new LearnedNoGoodTracker(getNoGoodCounter()); - TotalNoGoodTracker totalNoGoodExtrTracker = new TotalNoGoodTracker(getNoGoodCounter()); + StaticNoGoodTracker staticNoGoodExtractingTracker = new StaticNoGoodTracker(getNoGoodCounter()); + LearnedNoGoodTracker learnedNoGoodExtractingTracker = new LearnedNoGoodTracker(getNoGoodCounter()); + TotalNoGoodTracker totalNoGoodExtractingTracker = new TotalNoGoodTracker(getNoGoodCounter()); List statTrackers = new LinkedList<>(); statTrackers.add(iterationTracker); statTrackers.add(conflictTracker); statTrackers.add(decisionTracker); statTrackers.add(learnedNoGoodTracker); - statTrackers.add(staticNoGoodExtrTracker); - statTrackers.add(learnedNoGoodExtrTracker); - statTrackers.add(totalNoGoodExtrTracker); + statTrackers.add(staticNoGoodExtractingTracker); + statTrackers.add(learnedNoGoodExtractingTracker); + statTrackers.add(totalNoGoodExtractingTracker); statTrackers.add(learnEfficiencyTracker); PropagationStatManager propagationStatManager = this.store.getPropagationStatManager(); @@ -763,7 +763,7 @@ private List initStatTrackers() { } statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); - statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodExtrTracker, totalNoGoodExtrTracker)); + statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodExtractingTracker, totalNoGoodExtractingTracker)); return statTrackers; } From 212f15c5464965ead17c0ba5abb4172d736e4f25 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 8 Nov 2022 23:47:21 +0100 Subject: [PATCH 32/53] Implement regrounding rules for rule atoms after reboot --- .../alpha/core/grounder/ChoiceRecorder.java | 3 +- .../kr/alpha/core/grounder/Grounder.java | 5 - .../kr/alpha/core/grounder/NaiveGrounder.java | 25 +++- .../core/grounder/RebootableGrounder.java | 47 ++++++++ .../kr/alpha/core/solver/DefaultSolver.java | 68 +++++++---- .../core/solver/reboot/NoGoodAtomizer.java | 1 + .../core/solver/reboot/RebootManager.java | 113 ++++++++++++++++++ .../DynamicLearnedIntervalRebootStrategy.java | 4 +- .../kr/alpha/core/util/Substitutions.java | 10 +- .../alpha/core/grounder/ChoiceGrounder.java | 7 -- .../kr/alpha/core/grounder/DummyGrounder.java | 7 -- 11 files changed, 235 insertions(+), 55 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RebootableGrounder.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java index b1da72d43..d3fe92cb0 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java @@ -71,7 +71,6 @@ public Map> getAndResetHeadsToBodies() { return currentHeadsToBodies; } - public List generateChoiceNoGoods(final List posLiterals, final List negLiterals, final int bodyRepresentingLiteral) { // Obtain an ID for this new choice. final int choiceId = ID_GENERATOR.getNextId(); @@ -94,7 +93,7 @@ private NoGood generatePos(final int atomOn, List posLiterals) { return NoGood.fromBodyInternal(posLiterals, emptyList(), literalOn); } - private List generateNeg(final int atomOff, List negLiterals) { + private List generateNeg(final int atomOff, List negLiterals) { final int negLiteralOff = negateLiteral(atomToLiteral(atomOff)); final List noGoods = new ArrayList<>(negLiterals.size() + 1); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java index 4884d8420..2c697f955 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java @@ -80,9 +80,4 @@ public interface Grounder { * @return */ int register(NoGood noGood); - - /** - * Reboots the grounder, returning it to its initial state. - */ - void reboot(Assignment currentAssignment); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index 55e2d8f16..d612ab6d9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -43,7 +43,9 @@ import java.util.SortedSet; import java.util.TreeSet; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; +import at.ac.tuwien.kr.alpha.core.util.Substitutions; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; @@ -83,7 +85,7 @@ * * Copyright (c) 2016-2020, the Alpha Team. */ -public class NaiveGrounder extends BridgedGrounder implements ProgramAnalyzingGrounder { +public class NaiveGrounder extends BridgedGrounder implements ProgramAnalyzingGrounder, RebootableGrounder { private static final Logger LOGGER = LoggerFactory.getLogger(NaiveGrounder.class); private final WorkingMemory workingMemory = new WorkingMemory(); @@ -430,6 +432,23 @@ public void reboot(Assignment currentAssignment) { initializeFactsAndRules(); } + @Override + public Map forceRuleGrounding(RuleAtom atom) { + Map newNoGoods = new LinkedHashMap<>(); + + // Translate RuleAtom back to NonGroundRule + Substitution. + String ruleId = (String) ((ConstantTerm)atom.getTerms().get(0)).getObject(); + CompiledRule nonGroundRule = getNonGroundRule(Integer.parseInt(ruleId)); + String substitution = (String) ((ConstantTerm)atom.getTerms().get(1)).getObject(); + Substitution groundingSubstitution = Substitutions.fromString(substitution); + + // Generate the rules that correspond to the RuleAtom + List generatedNoGoods = noGoodGenerator.generateNoGoodsFromGroundSubstitution( + nonGroundRule, groundingSubstitution); + registry.register(generatedNoGoods, newNoGoods); + return newNoGoods; + } + // Ideally, this method should be private. It's only visible because NaiveGrounderTest needs to access it. BindingResult getGroundInstantiations(CompiledRule rule, RuleGroundingOrder groundingOrder, Substitution partialSubstitution, Assignment currentAssignment) { @@ -456,7 +475,7 @@ BindingResult getGroundInstantiations(CompiledRule rule, RuleGroundingOrder grou } /** - * Helper method used by {@link NaiveGrounder#bindNextAtomInRule(RuleGroundingOrderImpl, int, int, int, BasicSubstitution)}. + * Helper method used by {@link NaiveGrounder#bindNextAtomInRule(RuleGroundingOrder, int, int, int, Substitution)}. * * Takes an ImmutablePair of a {@link BasicSubstitution} and an accompanying {@link AssignmentStatus} and calls * bindNextAtomInRule for the next literal in the grounding order. @@ -638,7 +657,7 @@ public Set justifyAtom(int atomToJustify, Assignment currentAssignment) /** * Checks that every nogood not marked as {@link NoGoodInterface.Type#INTERNAL} contains only - * atoms which are not {@link PredicateImpl#isSolverInternal()} (except {@link RuleAtom}s, which are allowed). + * atoms which are not {@link Predicate#isSolverInternal()} (except {@link RuleAtom}s, which are allowed). * * @param newNoGoods */ diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RebootableGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RebootableGrounder.java new file mode 100644 index 000000000..2ca0651cb --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RebootableGrounder.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.grounder; + +import at.ac.tuwien.kr.alpha.core.atoms.RuleAtom; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +import java.util.Map; + +public interface RebootableGrounder extends Grounder { + /** + * Reboots the grounder, returning it to its initial state. + */ + void reboot(Assignment currentAssignment); + + /** + * Grounds the rule corresponding to the given {@link RuleAtom} and generates the respective {@link NoGood}s + * for this ground rule. + * @param ruleAtom the {@link RuleAtom} to ground the corresponding rule for. + * @return the nogoods resulting from the grounding of the rule. + */ + Map forceRuleGrounding(RuleAtom ruleAtom); +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index b5fe663c9..2df492ec8 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -40,10 +40,12 @@ import java.util.function.Consumer; import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.grounder.RebootableGrounder; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; -import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedNoGoodCollection; +import at.ac.tuwien.kr.alpha.core.solver.reboot.RebootManager; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.*; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.DynamicLearnedIntervalRebootStrategy; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedLearnedRebootStrategy; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; import at.ac.tuwien.kr.alpha.core.util.StopWatch; import org.slf4j.Logger; @@ -81,9 +83,8 @@ public class DefaultSolver extends AbstractSolver implements StatisticsReporting private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSolver.class); private final NoGoodStore store; - private final AtomizedNoGoodCollection enumerationNoGoods; - private final AtomizedNoGoodCollection learnedNoGoods; private final ChoiceManager choiceManager; + private final RebootManager rebootManager; private final WritableAssignment assignment; private final GroundConflictNoGoodLearner learner; private final BranchingHeuristic branchingHeuristic; @@ -124,10 +125,9 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.assignment = assignment; this.store = store; - this.enumerationNoGoods = new AtomizedNoGoodCollection(atomStore); - this.learnedNoGoods = new AtomizedNoGoodCollection(atomStore); this.choiceManager = new ChoiceManager(assignment, store); this.choiceManager.setChecksEnabled(config.isDebugInternalChecks()); + this.rebootManager = new RebootManager(atomStore); this.learner = new GroundConflictNoGoodLearner(assignment, atomStore); this.branchingHeuristic = chainFallbackHeuristic(grounder, assignment, random, heuristicsConfiguration); this.disableJustifications = config.isDisableJustificationSearch(); @@ -151,11 +151,18 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableRebootRepeat = config.isDisableRebootRepeat(); DynamicLearnedIntervalRebootStrategy dynamicRebootStrategy = new DynamicLearnedIntervalRebootStrategy( learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); - this.rebootStrategy = dynamicRebootStrategy; +// this.rebootStrategy = new FixedIterationRebootStrategy(config.getRebootIterations()); + this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); +// this.rebootStrategy = dynamicRebootStrategy; statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), statTrackers, 1000); + + if (this.rebootEnabled && !(grounder instanceof RebootableGrounder)) { + this.rebootEnabled = false; + LOGGER.warn("Reboot was disabled since grounder does not support it."); + } } private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAssignment assignment, Random random, HeuristicsConfiguration heuristicsConfiguration) { @@ -229,7 +236,7 @@ private void initializeSearch() { } /** - * Updates the assignment for the grounder and then gets new nogoods from the grounder + * Updates the assignment for the grounder and then gets new {@link NoGood}s from the grounder * by calling {@link DefaultSolver#getNoGoodsFromGrounderAndIngest()}. */ private void syncWithGrounder() { @@ -259,7 +266,7 @@ private void prepareForSubsequentAnswerSet() { // Backjump instead of backtrackSlow, enumerationNoGood will invert last choice. choiceManager.backjump(backjumpLevel - 1); LOGGER.debug("Adding enumeration nogood: {}", enumerationNoGood); - enumerationNoGoods.add(enumerationNoGood); + rebootManager.newEnumerationNoGood(enumerationNoGood); if (!addAndBackjumpIfNecessary(grounder.register(enumerationNoGood), enumerationNoGood, Integer.MAX_VALUE)) { searchState.isSearchSpaceCompletelyExplored = true; } @@ -368,7 +375,7 @@ private boolean learnBackjumpAddFromConflict(ConflictCause conflictCause) { choiceManager.backjump(analysisResult.backjumpLevel); final NoGood learnedNoGood = analysisResult.learnedNoGood; - learnedNoGoods.add(learnedNoGood); + rebootManager.newLearnedNoGood(learnedNoGood); rebootStrategy.newLearnedNoGood(learnedNoGood); learnedNoGoodTracker.increment(); int noGoodId = grounder.register(learnedNoGood); @@ -491,7 +498,7 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { } // Add newly obtained noGoods. boolean success = ingest(obtained); - learnedNoGoods.addAll(obtained.values()); + rebootManager.newLearnedNoGoods(obtained.values()); rebootStrategy.newLearnedNoGoods(obtained.values()); learnedNoGoodTracker.incrementBy(obtained.values().size()); if (!success) { @@ -618,21 +625,22 @@ private void reboot() { store.reset(); branchingHeuristic.reset(); assignment.clear(); - grounder.reboot(assignment); + ((RebootableGrounder) grounder).reboot(assignment); atomStore.reset(); choiceManager.reset(); syncWithGrounder(); - ingestNoGoodCollection(enumerationNoGoods); - ingestNoGoodCollection(learnedNoGoods); + ingestNoGoodCollection(rebootManager.getEnumerationNoGoods()); + ingestNoGoodCollection(rebootManager.getLearnedNoGoods()); + ingestNoGoodsFromRulesOfRuleAtoms(rebootManager.getDiscoveredRuleAtoms()); replayAtomizedChoiceStack(atomizedChoiceStack); LOGGER.info("Solver and grounder reboot finished."); } /** - * Extracts the current choice stack with atom ids replaced by the respective atoms. - * @return the choice stack containing atoms instead of atom ids. + * Extracts the current choice stack with atom ids replaced by the respective {@link Atom}s. + * @return the choice stack containing {@link Atom}s instead of atom ids. */ private Stack getAtomizedChoiceStack() { List choiceList = choiceManager.getChoiceList(); @@ -696,11 +704,13 @@ private void growForMaxAtomId() { } /** - * Adds all nogoods from the given {@link AtomizedNoGoodCollection} to the regular nogood store. + * Registers the given collection of {@link NoGood}s at the {@link Grounder} + * and calls {@link DefaultSolver#ingest(Map)} with the resulting ids as keys. + * @param noGoods the {@link NoGood}s to ingest. */ - private void ingestNoGoodCollection(AtomizedNoGoodCollection noGoodCollection) { + private void ingestNoGoodCollection(Collection noGoods) { Map newNoGoods = new LinkedHashMap<>(); - for (NoGood noGood : noGoodCollection.getNoGoods()) { + for (NoGood noGood : noGoods) { newNoGoods.put(grounder.register(noGood), noGood); } if (!ingest(newNoGoods)) { @@ -709,14 +719,22 @@ private void ingestNoGoodCollection(AtomizedNoGoodCollection noGoodCollection) { } /** - * Updates the branching heuristic as if all the nogoods in {@link DefaultSolver#learnedNoGoods} - * were learned from conflicts in the order they are stored in {@link DefaultSolver#learnedNoGoods}. + * Forces the {@link RebootableGrounder} to ground all rules corresponding to the given list of + * {@link RuleAtom}s. Then calls {@link DefaultSolver#ingest(Map)} with the {@link NoGood}s obtained this way. + * This method must not be called if reboots are disabled. + * @param ruleAtoms the {@link RuleAtom}s to ground and ingest the corresponding rules for. */ - private void simulateOldConflicts() { - for (NoGood noGood : learnedNoGoods.getNoGoods()) { - GroundConflictNoGoodLearner.ConflictAnalysisResult analysisResult = - new GroundConflictNoGoodLearner.ConflictAnalysisResult(noGood, 0, Collections.emptyList()); - branchingHeuristic.analyzedConflict(analysisResult); + private void ingestNoGoodsFromRulesOfRuleAtoms(List ruleAtoms) { + if (!rebootEnabled) { + throw oops("Reboot is not enabled but nogood ingestion from rule atoms was called"); + } + Map newNoGoods = new LinkedHashMap<>(); + for (RuleAtom ruleAtom : ruleAtoms) { + Map obtained = ((RebootableGrounder) grounder).forceRuleGrounding(ruleAtom); + newNoGoods.putAll(obtained); + } + if (!ingest(newNoGoods)) { + searchState.isSearchSpaceCompletelyExplored = true; } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java index 7f9b9c5ff..1c2477668 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/NoGoodAtomizer.java @@ -62,6 +62,7 @@ public NoGoodAtomizer(NoGood noGood, AtomStore atomStore) { /** * Creates a new {@link NoGood} with the same literals as this {@link NoGoodAtomizer}. * Atom ids are provided by the given {@link AtomStore}. + * Atoms are added to the {@link AtomStore} if they are not contained yet. * * @param atomStore the {@link AtomStore} to get atom ids from. * @return the newly created {@link NoGood} with the same literals as this {@link NoGoodAtomizer}. diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java new file mode 100644 index 000000000..976362dc9 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.atoms.ChoiceAtom; +import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.atoms.RuleAtom; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +public class RebootManager { + private static final Logger LOGGER = LoggerFactory.getLogger(RebootManager.class); + + private final AtomStore atomStore; + private final AtomizedNoGoodCollection enumerationNoGoods; + private final AtomizedNoGoodCollection learnedNoGoods; + private final List discoveredRuleAtoms; + private int filteredCounter; + + public RebootManager(AtomStore atomStore) { + this.atomStore = atomStore; + this.enumerationNoGoods = new AtomizedNoGoodCollection(atomStore); + this.learnedNoGoods = new AtomizedNoGoodCollection(atomStore); + this.discoveredRuleAtoms = new LinkedList<>(); + this.filteredCounter = 0; + } + + public void newEnumerationNoGood(NoGood noGood) { + enumerationNoGoods.add(noGood); + discoverRuleAtoms(noGood); + } + + public void newEnumerationNoGoods(Collection noGoods) { + noGoods.forEach(this::newEnumerationNoGood); + } + + public void newLearnedNoGood(NoGood noGood) { + if (!scanForAtomsToFilter(noGood)) { + learnedNoGoods.add(noGood); + discoverRuleAtoms(noGood); + } else { + filteredCounter++; + } + } + + public void newLearnedNoGoods(Collection noGoods) { + noGoods.forEach(this::newLearnedNoGood); + } + + public List getEnumerationNoGoods() { + return enumerationNoGoods.getNoGoods(); + } + + public List getLearnedNoGoods() { + return learnedNoGoods.getNoGoods(); + } + + public List getDiscoveredRuleAtoms() { + LOGGER.info("Number of rule atoms: " + discoveredRuleAtoms.size()); + LOGGER.info("Number of filtered out nogoods: " + filteredCounter); + return discoveredRuleAtoms; + } + + private void discoverRuleAtoms(NoGood noGood) { + noGood.stream().forEach((literalId) -> { + Atom atom = atomStore.get(Literals.atomOf(literalId)); + if (atom instanceof RuleAtom) { + discoveredRuleAtoms.add((RuleAtom) atom); + } + }); + } + + private boolean scanForAtomsToFilter(NoGood noGood) { + for (int literalId : noGood) { + Atom atom = atomStore.get(Literals.atomOf(literalId)); + if (atom instanceof EnumerationAtom || atom instanceof ChoiceAtom) { + return true; + } + } + return false; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java index dd8af39bf..5e4f0beea 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java @@ -115,14 +115,14 @@ private double getNewIntervalSize(double currentIntervalMeasure) { } else if (currentIntervalMeasure > previousIntervalMeasure) { double newIntervalSize = intervalSize * scalingFactor; System.out.printf("# Reboot performed. Interval size (old -> new): %f -> %f [+ scaled down]\n", - oldIntervalSize, intervalSize); + oldIntervalSize, newIntervalSize); System.out.printf("# Reason (old, new): %f < %f\n", previousIntervalMeasure, currentIntervalMeasure); return Math.max(newIntervalSize, minInterval); } else { double newIntervalSize = intervalSize / scalingFactor; System.out.printf("# Reboot performed. Interval size (old -> new): %f -> %f [- scaled up]\n", - oldIntervalSize, intervalSize); + oldIntervalSize, newIntervalSize); System.out.printf("# Reason (old, new): %f >= %f\n", previousIntervalMeasure, currentIntervalMeasure); return Math.max(newIntervalSize, minInterval); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java index 40470cf09..10105586f 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java @@ -20,10 +20,12 @@ public static Substitution fromString(String str) { String[] assignments = bare.split(","); BasicSubstitution ret = new BasicSubstitution(); for (String assignment : assignments) { - String[] keyVal = assignment.split("->"); - VariableTerm variable = Terms.newVariable(keyVal[0]); - Term assignedTerm = PROGRAM_PART_PARSER.parseTerm(keyVal[1]); - ret.put(variable, assignedTerm); + if (!assignment.equals("")) { + String[] keyVal = assignment.split("->"); + VariableTerm variable = Terms.newVariable(keyVal[0]); + Term assignedTerm = PROGRAM_PART_PARSER.parseTerm(keyVal[1]); + ret.put(variable, assignedTerm); + } } return ret; } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java index 6a132db7b..66374d312 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java @@ -211,11 +211,4 @@ public int register(NoGood noGood) { } return solverDerivedNoGoods.get(noGood); } - - /** - * Empty interface implementation. - */ - @Override - public void reboot(Assignment currentAssignment) { - } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java index 6d3d6e1bc..669e6037f 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java @@ -126,13 +126,6 @@ public int register(NoGood noGood) { return solverDerivedNoGoods.get(noGood); } - /** - * Empty interface implementation. - */ - @Override - public void reboot(Assignment currentAssignment) { - } - @Override public AnswerSet assignmentToAnswerSet(Iterable trueAtoms) { // Note: This grounder only deals with 0-ary predicates, i.e., every atom is a predicate and there is From 1902d0cd06d149a81226ab4ce107211d72d5c44e Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 9 Nov 2022 23:42:35 +0100 Subject: [PATCH 33/53] Remove assumption about choice points --- .../ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 10 ++++++---- .../solver/heuristics/HeapOfActiveChoicePoints.java | 7 ++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 2df492ec8..64198774d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -346,7 +346,7 @@ private boolean addAndBackjumpIfNecessary(int noGoodId, NoGood noGood, int lbd) choiceManager.backjump(backjumpLevel); propagationStopWatch.start(); if (store.propagate() != null) { - throw oops("Violated NoGood after backtracking."); + throw oops("Violated NoGood after backtracking."); } propagationStopWatch.stop(); } @@ -620,12 +620,13 @@ private boolean choose() { private void reboot() { LOGGER.info("Performing solver and grounder reboot."); + RebootableGrounder rebootableGrounder = ((RebootableGrounder) grounder); Stack atomizedChoiceStack = getAtomizedChoiceStack(); store.reset(); branchingHeuristic.reset(); assignment.clear(); - ((RebootableGrounder) grounder).reboot(assignment); + rebootableGrounder.reboot(assignment); atomStore.reset(); choiceManager.reset(); @@ -706,7 +707,7 @@ private void growForMaxAtomId() { /** * Registers the given collection of {@link NoGood}s at the {@link Grounder} * and calls {@link DefaultSolver#ingest(Map)} with the resulting ids as keys. - * @param noGoods the {@link NoGood}s to ingest. + * @param noGoods the {@link NoGood}s to register and ingest. */ private void ingestNoGoodCollection(Collection noGoods) { Map newNoGoods = new LinkedHashMap<>(); @@ -728,9 +729,10 @@ private void ingestNoGoodsFromRulesOfRuleAtoms(List ruleAtoms) { if (!rebootEnabled) { throw oops("Reboot is not enabled but nogood ingestion from rule atoms was called"); } + RebootableGrounder rebootableGrounder = ((RebootableGrounder) grounder); Map newNoGoods = new LinkedHashMap<>(); for (RuleAtom ruleAtom : ruleAtoms) { - Map obtained = ((RebootableGrounder) grounder).forceRuleGrounding(ruleAtom); + Map obtained = rebootableGrounder.forceRuleGrounding(ruleAtom); newNoGoods.putAll(obtained); } if (!ingest(newNoGoods)) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java index 24644e69b..e8957a234 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java @@ -82,9 +82,10 @@ private void recordAtomRelationships(NoGood noGood) { if (body == none && choiceManager.isAtomChoice(atom)) { body = atom; } else { - if (choiceManager.isChecksEnabled() && choiceManager.isAtomChoice(atom)) { - throw oops("More than one choice point in a nogood: " + body + ", " + atom); - } + // TODO: reevaluate assumption because of reboots +// if (choiceManager.isChecksEnabled() && choiceManager.isAtomChoice(atom)) { +// throw oops("More than one choice point in a nogood: " + body + ", " + atom); +// } others.add(atom); } } From 700ae2bfae42d1fcc66e987a4945c9865a124bf5 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 10 Nov 2022 01:07:04 +0100 Subject: [PATCH 34/53] Fix code style --- .../java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 4 ++-- .../core/solver/heuristics/HeapOfActiveChoicePoints.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 64198774d..885968f1d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -620,7 +620,7 @@ private boolean choose() { private void reboot() { LOGGER.info("Performing solver and grounder reboot."); - RebootableGrounder rebootableGrounder = ((RebootableGrounder) grounder); + RebootableGrounder rebootableGrounder = (RebootableGrounder) grounder; Stack atomizedChoiceStack = getAtomizedChoiceStack(); store.reset(); @@ -729,7 +729,7 @@ private void ingestNoGoodsFromRulesOfRuleAtoms(List ruleAtoms) { if (!rebootEnabled) { throw oops("Reboot is not enabled but nogood ingestion from rule atoms was called"); } - RebootableGrounder rebootableGrounder = ((RebootableGrounder) grounder); + RebootableGrounder rebootableGrounder = (RebootableGrounder) grounder; Map newNoGoods = new LinkedHashMap<>(); for (RuleAtom ruleAtom : ruleAtoms) { Map obtained = rebootableGrounder.forceRuleGrounding(ruleAtom); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java index e8957a234..b00f7db4b 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java @@ -34,7 +34,6 @@ import java.util.HashSet; import java.util.Set; -import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; /** From 8d741742951f81364494b8d1e487860ad81823b3 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Mon, 14 Nov 2022 15:19:49 +0100 Subject: [PATCH 35/53] Remove enumeration atom reset during reboot --- .../kr/alpha/core/grounder/NaiveGrounder.java | 8 ++------ .../kr/alpha/core/solver/DefaultSolver.java | 20 ++++++++----------- .../core/solver/reboot/AtomizedChoice.java | 5 +++++ .../kr/alpha/core/util/Substitutions.java | 13 ++++++++++++ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index d612ab6d9..d6dba37c2 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -43,7 +43,6 @@ import java.util.SortedSet; import java.util.TreeSet; -import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; import at.ac.tuwien.kr.alpha.core.util.Substitutions; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -427,7 +426,6 @@ public void reboot(Assignment currentAssignment) { removeAfterObtainingNewNoGoods = new LinkedHashSet<>(); instantiationStrategy.setStaleWorkingMemoryEntries(removeAfterObtainingNewNoGoods); instantiationStrategy.setCurrentAssignment(currentAssignment); - EnumerationAtom.resetEnumerations(); fixedRules = new ArrayList<>(); initializeFactsAndRules(); } @@ -437,10 +435,8 @@ public Map forceRuleGrounding(RuleAtom atom) { Map newNoGoods = new LinkedHashMap<>(); // Translate RuleAtom back to NonGroundRule + Substitution. - String ruleId = (String) ((ConstantTerm)atom.getTerms().get(0)).getObject(); - CompiledRule nonGroundRule = getNonGroundRule(Integer.parseInt(ruleId)); - String substitution = (String) ((ConstantTerm)atom.getTerms().get(1)).getObject(); - Substitution groundingSubstitution = Substitutions.fromString(substitution); + CompiledRule nonGroundRule = Substitutions.getNonGroundRuleFromRuleAtom(atom, this); + Substitution groundingSubstitution = Substitutions.getSubstitutionFromRuleAtom(atom); // Generate the rules that correspond to the RuleAtom List generatedNoGoods = noGoodGenerator.generateNoGoodsFromGroundSubstitution( diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 885968f1d..d1d2f555d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -44,9 +44,7 @@ import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; import at.ac.tuwien.kr.alpha.core.solver.reboot.RebootManager; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.*; -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.DynamicLearnedIntervalRebootStrategy; -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.FixedLearnedRebootStrategy; -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.*; import at.ac.tuwien.kr.alpha.core.util.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +57,6 @@ import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; import at.ac.tuwien.kr.alpha.api.programs.atoms.ComparisonAtom; import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; -import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; import at.ac.tuwien.kr.alpha.core.atoms.RuleAtom; import at.ac.tuwien.kr.alpha.core.common.AtomStore; import at.ac.tuwien.kr.alpha.core.common.NoGood; @@ -152,8 +149,9 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, DynamicLearnedIntervalRebootStrategy dynamicRebootStrategy = new DynamicLearnedIntervalRebootStrategy( learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); // this.rebootStrategy = new FixedIterationRebootStrategy(config.getRebootIterations()); - this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); -// this.rebootStrategy = dynamicRebootStrategy; +// this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); + this.rebootStrategy = dynamicRebootStrategy; +// this.rebootStrategy = new LubyLearnedRebootStrategy(); statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, @@ -460,12 +458,10 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { toJustifyIterator.remove(); continue; } - // For RuleAtoms in toJustify the corresponding ground body contains BasicAtoms that have been assigned FALSE in the closing. - // First, translate RuleAtom back to NonGroundRule + Substitution. - String ruleId = (String) ((ConstantTerm)atom.getTerms().get(0)).getObject(); - CompiledRule nonGroundRule = analyzingGrounder.getNonGroundRule(Integer.parseInt(ruleId)); - String substitution = (String) ((ConstantTerm)atom.getTerms().get(1)).getObject(); - Substitution groundingSubstitution = Substitutions.fromString(substitution); + // Translate RuleAtom back to NonGroundRule + Substitution. + RuleAtom ruleAtom = (RuleAtom) atom; + CompiledRule nonGroundRule = Substitutions.getNonGroundRuleFromRuleAtom(ruleAtom, analyzingGrounder); + Substitution groundingSubstitution = Substitutions.getSubstitutionFromRuleAtom(ruleAtom); // Find ground literals in the body that have been assigned false and justify those. for (Literal bodyLiteral : nonGroundRule.getBody()) { Atom groundAtom = bodyLiteral.getAtom().substitute(groundingSubstitution); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java index bac554deb..a1e28a0ca 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/AtomizedChoice.java @@ -26,7 +26,12 @@ package at.ac.tuwien.kr.alpha.core.solver.reboot; import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +/** + * A choice independent of atom ids provided by an {@link AtomStore}. + * It contains an {@link Atom}, a truth value and a backtracked flag. + */ public class AtomizedChoice { private final Atom atom; private final boolean truthValue; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java index 10105586f..58df8f9a7 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java @@ -1,11 +1,15 @@ package at.ac.tuwien.kr.alpha.core.util; import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; import at.ac.tuwien.kr.alpha.api.terms.Term; import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.atoms.RuleAtom; +import at.ac.tuwien.kr.alpha.core.grounder.ProgramAnalyzingGrounder; import at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; public final class Substitutions { @@ -30,4 +34,13 @@ public static Substitution fromString(String str) { return ret; } + public static Substitution getSubstitutionFromRuleAtom(RuleAtom atom) { + String substitution = (String) ((ConstantTerm)atom.getTerms().get(1)).getObject(); + return fromString(substitution); + } + + public static CompiledRule getNonGroundRuleFromRuleAtom(RuleAtom atom, ProgramAnalyzingGrounder grounder) { + String ruleId = (String) ((ConstantTerm)atom.getTerms().get(0)).getObject(); + return grounder.getNonGroundRule(Integer.parseInt(ruleId)); + } } From 9d99858fbed78cd133dac44981c898ec436a54fb Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 15 Nov 2022 14:29:03 +0100 Subject: [PATCH 36/53] Add luby learned strategy, move strategy calls --- .../kr/alpha/core/grounder/NaiveGrounder.java | 1 - .../kr/alpha/core/solver/DefaultSolver.java | 3 +- .../strategies/LubyLearnedRebootStrategy.java | 83 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index d6dba37c2..9d0770ab7 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -43,7 +43,6 @@ import java.util.SortedSet; import java.util.TreeSet; -import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; import at.ac.tuwien.kr.alpha.core.util.Substitutions; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index d1d2f555d..6015b773b 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -274,6 +274,7 @@ private void getNoGoodsFromGrounderAndIngest() { grounderStopWatch.start(); Map obtained = grounder.getNoGoods(assignment); grounderStopWatch.stop(); + rebootStrategy.newNoGoods(obtained.values()); if (!ingest(obtained)) { searchState.isSearchSpaceCompletelyExplored = true; } @@ -406,6 +407,7 @@ private boolean justifyMbtAndBacktrack() { obtained.put(noGoodID, noGood); LOGGER.debug("Learned NoGood is: {}", atomStore.noGoodToString(noGood)); // Add NoGood and trigger backjumping. + rebootStrategy.newLearnedNoGoods(obtained.values()); if (!ingest(obtained)) { logStats(); return false; @@ -545,7 +547,6 @@ private boolean backtrack() { private boolean ingest(Map obtained) { growForMaxAtomId(); branchingHeuristic.newNoGoods(obtained.values()); - rebootStrategy.newNoGoods(obtained.values()); LinkedList> noGoodsToAdd = new LinkedList<>(obtained.entrySet()); Map.Entry entry; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java new file mode 100644 index 000000000..95a6d5c74 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class LubyLearnedRebootStrategy implements RebootStrategy { + private static final double SCALING_FACTOR = 10; + + private int rebootCount; + private int learnedCount; + + @Override + public void nextIteration() { + + } + + @Override + public void decisionMade() { + + } + + @Override + public void conflictEncountered() { + + } + + @Override + public void newNoGood(NoGood noGood) { + + } + + @Override + public void newLearnedNoGood(NoGood noGood) { + learnedCount++; + } + + @Override + public boolean isRebootScheduled() { + return learnedCount >= SCALING_FACTOR * luby(rebootCount + 1); + } + + @Override + public void rebootPerformed() { + rebootCount++; + } + + private double luby(double i) { + for (int k = 1; k < 31; k++) { + if (i == (Math.pow(2, k)) - 1) { + return Math.pow(2, k - 1); + } + } + for (int k = 1;; k++) { + if (Math.pow(2, k - 1) <= i && i < Math.pow(2, k) - 1) { + return luby(i - Math.pow(2, k - 1) + 1); + } + } + } +} From 2da3694dc370f00e54c0dc9461230afc52f56cd8 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 18 Nov 2022 15:13:30 +0100 Subject: [PATCH 37/53] Fix logging --- .../kr/alpha/core/solver/DefaultSolver.java | 4 +--- .../DynamicLearnedIntervalRebootStrategy.java | 16 ++++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 6015b773b..87d0e6d76 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -148,10 +148,9 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableRebootRepeat = config.isDisableRebootRepeat(); DynamicLearnedIntervalRebootStrategy dynamicRebootStrategy = new DynamicLearnedIntervalRebootStrategy( learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); -// this.rebootStrategy = new FixedIterationRebootStrategy(config.getRebootIterations()); // this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); - this.rebootStrategy = dynamicRebootStrategy; // this.rebootStrategy = new LubyLearnedRebootStrategy(); + this.rebootStrategy = dynamicRebootStrategy; statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, @@ -407,7 +406,6 @@ private boolean justifyMbtAndBacktrack() { obtained.put(noGoodID, noGood); LOGGER.debug("Learned NoGood is: {}", atomStore.noGoodToString(noGood)); // Add NoGood and trigger backjumping. - rebootStrategy.newLearnedNoGoods(obtained.values()); if (!ingest(obtained)) { logStats(); return false; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java index 5e4f0beea..361cc3cfc 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java @@ -28,8 +28,12 @@ import at.ac.tuwien.kr.alpha.core.common.NoGood; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.ResettableStatTracker; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.StatTracker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DynamicLearnedIntervalRebootStrategy implements RebootStrategy { + private static final Logger LOGGER = LoggerFactory.getLogger(DynamicLearnedIntervalRebootStrategy.class); + private final ResettableStatTracker efficiencyMeasure; private final StatTracker intervalSizeTracker; private final int minInterval; @@ -114,17 +118,13 @@ private double getNewIntervalSize(double currentIntervalMeasure) { return intervalSize; } else if (currentIntervalMeasure > previousIntervalMeasure) { double newIntervalSize = intervalSize * scalingFactor; - System.out.printf("# Reboot performed. Interval size (old -> new): %f -> %f [+ scaled down]\n", - oldIntervalSize, newIntervalSize); - System.out.printf("# Reason (old, new): %f < %f\n", - previousIntervalMeasure, currentIntervalMeasure); + LOGGER.info("Reboot interval size: {} -> {}", oldIntervalSize, newIntervalSize); + LOGGER.info("Interval measures were: {} < {}", previousIntervalMeasure, currentIntervalMeasure); return Math.max(newIntervalSize, minInterval); } else { double newIntervalSize = intervalSize / scalingFactor; - System.out.printf("# Reboot performed. Interval size (old -> new): %f -> %f [- scaled up]\n", - oldIntervalSize, newIntervalSize); - System.out.printf("# Reason (old, new): %f >= %f\n", - previousIntervalMeasure, currentIntervalMeasure); + LOGGER.info("Reboot interval size: {} -> {}", oldIntervalSize, newIntervalSize); + LOGGER.info("Interval measures were: {} >= {}", previousIntervalMeasure, currentIntervalMeasure); return Math.max(newIntervalSize, minInterval); } } From 6b36e0e7e6ad48d7e8ff23209eb15cc22e95dc0a Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 26 Nov 2022 23:08:24 +0100 Subject: [PATCH 38/53] Fix dynamic reboot strategy --- .../strategies/DynamicLearnedIntervalRebootStrategy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java index 361cc3cfc..513846d2c 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java @@ -87,12 +87,12 @@ public void conflictEncountered() { @Override public void newNoGood(NoGood noGood) { - learnedCount++; + } @Override public void newLearnedNoGood(NoGood noGood) { - + learnedCount++; } @Override From ec49b534d4505860201ccc35471f6020b308411f Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 6 Dec 2022 16:48:16 +0100 Subject: [PATCH 39/53] Add reboot strategies and add empty default implementations --- .../kr/alpha/core/solver/DefaultSolver.java | 7 ++- .../CompleteAssignmentRebootStrategy.java | 29 +++++++++++ .../DynamicLearnedIntervalRebootStrategy.java | 20 ------- .../FixedConflictRebootStrategy.java | 20 ------- .../FixedDecisionRebootStrategy.java | 19 ------- .../FixedIterationRebootStrategy.java | 20 ------- .../FixedLearnedRebootStrategy.java | 20 ------- .../GeometricConflictRebootStrategy.java | 21 -------- .../GeometricLearnedRebootStrategy.java | 52 +++++++++++++++++++ .../LubyConflictRebootStrategy.java | 20 ------- .../strategies/LubyLearnedRebootStrategy.java | 20 ------- .../reboot/strategies/RebootStrategy.java | 14 +++-- 12 files changed, 96 insertions(+), 166 deletions(-) create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 87d0e6d76..c4e251c03 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -150,7 +150,8 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); // this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); // this.rebootStrategy = new LubyLearnedRebootStrategy(); - this.rebootStrategy = dynamicRebootStrategy; +// this.rebootStrategy = dynamicRebootStrategy; + this.rebootStrategy = new GeometricLearnedRebootStrategy(); statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, @@ -215,12 +216,14 @@ protected boolean tryAdvance(Consumer action) { LOGGER.debug("Closed unassigned known atoms (assigning FALSE)."); } else if (assignment.getMBTCount() == 0) { provideAnswerSet(action); + rebootStrategy.answerSetFound(); stopStopWatchesAndLogRuntimes(); return true; } else { mbtBacktrackingStopWatch.start(); backtrackFromMBTsRemaining(); mbtBacktrackingStopWatch.stop(); + rebootStrategy.backtrackJustified(); } } } @@ -264,6 +267,7 @@ private void prepareForSubsequentAnswerSet() { choiceManager.backjump(backjumpLevel - 1); LOGGER.debug("Adding enumeration nogood: {}", enumerationNoGood); rebootManager.newEnumerationNoGood(enumerationNoGood); + rebootStrategy.newEnumerationNoGood(enumerationNoGood); if (!addAndBackjumpIfNecessary(grounder.register(enumerationNoGood), enumerationNoGood, Integer.MAX_VALUE)) { searchState.isSearchSpaceCompletelyExplored = true; } @@ -404,6 +408,7 @@ private boolean justifyMbtAndBacktrack() { int noGoodID = grounder.register(noGood); Map obtained = new LinkedHashMap<>(); obtained.put(noGoodID, noGood); + rebootStrategy.newJustificationNoGood(noGood); LOGGER.debug("Learned NoGood is: {}", atomStore.noGoodToString(noGood)); // Add NoGood and trigger backjumping. if (!ingest(obtained)) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategy.java new file mode 100644 index 000000000..017288841 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategy.java @@ -0,0 +1,29 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +public class CompleteAssignmentRebootStrategy implements RebootStrategy { + private boolean reboot; + + public CompleteAssignmentRebootStrategy() { + reboot = false; + } + + @Override + public void answerSetFound() { + reboot = true; + } + + @Override + public void backtrackJustified() { + reboot = true; + } + + @Override + public boolean isRebootScheduled() { + return reboot; + } + + @Override + public void rebootPerformed() { + reboot = false; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java index 513846d2c..fdcb06e86 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java @@ -70,26 +70,6 @@ public StatTracker getIntervalSizeTracker() { return intervalSizeTracker; } - @Override - public void nextIteration() { - - } - - @Override - public void decisionMade() { - - } - - @Override - public void conflictEncountered() { - - } - - @Override - public void newNoGood(NoGood noGood) { - - } - @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java index a8382a5b5..6f7a60448 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java @@ -36,31 +36,11 @@ public FixedConflictRebootStrategy(int breakpoint) { this.conflictCount = 0; } - @Override - public void nextIteration() { - - } - - @Override - public void decisionMade() { - - } - @Override public void conflictEncountered() { conflictCount++; } - @Override - public void newNoGood(NoGood noGood) { - - } - - @Override - public void newLearnedNoGood(NoGood noGood) { - - } - @Override public boolean isRebootScheduled() { return conflictCount >= breakpoint; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java index 33c246ce5..7a2b00f05 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java @@ -36,30 +36,11 @@ public FixedDecisionRebootStrategy(int breakpoint) { this.decisionCount = 0; } - @Override - public void nextIteration() { - } - @Override public void decisionMade() { decisionCount++; } - @Override - public void conflictEncountered() { - - } - - @Override - public void newNoGood(NoGood noGood) { - - } - - @Override - public void newLearnedNoGood(NoGood noGood) { - - } - @Override public boolean isRebootScheduled() { return decisionCount >= breakpoint; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java index b67664a92..f2c02b9cd 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java @@ -41,26 +41,6 @@ public void nextIteration() { iterationCount++; } - @Override - public void decisionMade() { - - } - - @Override - public void conflictEncountered() { - - } - - @Override - public void newNoGood(NoGood noGood) { - - } - - @Override - public void newLearnedNoGood(NoGood noGood) { - - } - @Override public boolean isRebootScheduled() { return iterationCount >= breakpoint; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java index 9bd1d7dcc..cf7321eb6 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java @@ -11,26 +11,6 @@ public FixedLearnedRebootStrategy(int breakpoint) { this.learnedCounter = 0; } - @Override - public void nextIteration() { - - } - - @Override - public void decisionMade() { - - } - - @Override - public void conflictEncountered() { - - } - - @Override - public void newNoGood(NoGood noGood) { - - } - @Override public void newLearnedNoGood(NoGood noGood) { learnedCounter++; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java index 205410a8b..6ecdacace 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java @@ -33,32 +33,11 @@ public class GeometricConflictRebootStrategy implements RebootStrategy { private int rebootCount; private int conflictCount; - - @Override - public void nextIteration() { - - } - - @Override - public void decisionMade() { - - } - @Override public void conflictEncountered() { conflictCount++; } - @Override - public void newNoGood(NoGood noGood) { - - } - - @Override - public void newLearnedNoGood(NoGood noGood) { - - } - @Override public boolean isRebootScheduled() { return conflictCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java new file mode 100644 index 000000000..be6c961d5 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2022, the Alpha Team. + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + *

+ * 1) Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + *

+ * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; + +public class GeometricLearnedRebootStrategy implements RebootStrategy { + private static final double BASE = 1.5; + private static final double SCALING_FACTOR = 2; + + private int rebootCount; + private int learnedCount; + + @Override + public void newLearnedNoGood(NoGood noGood) { + learnedCount++; + } + + @Override + public boolean isRebootScheduled() { + return learnedCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); + } + + @Override + public void rebootPerformed() { + rebootCount++; + learnedCount = 0; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java index 307e0ed5d..c8e31853d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java @@ -33,31 +33,11 @@ public class LubyConflictRebootStrategy implements RebootStrategy { private int rebootCount; private int conflictCount; - @Override - public void nextIteration() { - - } - - @Override - public void decisionMade() { - - } - @Override public void conflictEncountered() { conflictCount++; } - @Override - public void newNoGood(NoGood noGood) { - - } - - @Override - public void newLearnedNoGood(NoGood noGood) { - - } - @Override public boolean isRebootScheduled() { return conflictCount >= SCALING_FACTOR * luby(rebootCount + 1); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java index 95a6d5c74..37a6c2156 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java @@ -33,26 +33,6 @@ public class LubyLearnedRebootStrategy implements RebootStrategy { private int rebootCount; private int learnedCount; - @Override - public void nextIteration() { - - } - - @Override - public void decisionMade() { - - } - - @Override - public void conflictEncountered() { - - } - - @Override - public void newNoGood(NoGood noGood) { - - } - @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java index 724b88fba..2743e422f 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java @@ -30,14 +30,18 @@ import java.util.Collection; public interface RebootStrategy { - void nextIteration(); - void decisionMade(); - void conflictEncountered(); - void newNoGood(NoGood noGood); + default void nextIteration() {} + default void decisionMade() {} + default void conflictEncountered() {} + default void answerSetFound() {} + default void backtrackJustified() {} + default void newEnumerationNoGood(NoGood noGood) {} + default void newJustificationNoGood(NoGood justification) {} + default void newNoGood(NoGood noGood) {} default void newNoGoods(Collection newNoGoods) { newNoGoods.forEach(this::newNoGood); } - void newLearnedNoGood(NoGood noGood); + default void newLearnedNoGood(NoGood noGood) {} default void newLearnedNoGoods(Collection newNoGoods) { newNoGoods.forEach(this::newLearnedNoGood); } From 913902de42866559763d53bd88cd9e1d426a7226 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 6 Dec 2022 19:16:47 +0100 Subject: [PATCH 40/53] Fix code style --- .../FixedConflictRebootStrategy.java | 2 - .../FixedDecisionRebootStrategy.java | 2 - .../FixedIterationRebootStrategy.java | 2 - .../GeometricConflictRebootStrategy.java | 2 - .../LubyConflictRebootStrategy.java | 2 - .../reboot/strategies/RebootStrategy.java | 39 ++++++++++++++----- 6 files changed, 30 insertions(+), 19 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java index 6f7a60448..e1f697fb2 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java @@ -25,8 +25,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -import at.ac.tuwien.kr.alpha.core.common.NoGood; - public class FixedConflictRebootStrategy implements RebootStrategy { private final int breakpoint; private int conflictCount; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java index 7a2b00f05..123429676 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java @@ -25,8 +25,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -import at.ac.tuwien.kr.alpha.core.common.NoGood; - public class FixedDecisionRebootStrategy implements RebootStrategy { private final int breakpoint; private int decisionCount; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java index f2c02b9cd..117cedee5 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java @@ -25,8 +25,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -import at.ac.tuwien.kr.alpha.core.common.NoGood; - public class FixedIterationRebootStrategy implements RebootStrategy { private final int breakpoint; private int iterationCount; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java index 6ecdacace..6a209ccfc 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java @@ -25,8 +25,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -import at.ac.tuwien.kr.alpha.core.common.NoGood; - public class GeometricConflictRebootStrategy implements RebootStrategy { private static final double BASE = 1.5; private static final double SCALING_FACTOR = 2; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java index c8e31853d..1ac4a5760 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java @@ -25,8 +25,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; -import at.ac.tuwien.kr.alpha.core.common.NoGood; - public class LubyConflictRebootStrategy implements RebootStrategy { private static final double SCALING_FACTOR = 10; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java index 2743e422f..43c305e2e 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java @@ -30,21 +30,42 @@ import java.util.Collection; public interface RebootStrategy { - default void nextIteration() {} - default void decisionMade() {} - default void conflictEncountered() {} - default void answerSetFound() {} - default void backtrackJustified() {} - default void newEnumerationNoGood(NoGood noGood) {} - default void newJustificationNoGood(NoGood justification) {} - default void newNoGood(NoGood noGood) {} + default void nextIteration() { + } + + default void decisionMade() { + } + + default void conflictEncountered() { + } + + default void answerSetFound() { + } + + default void backtrackJustified() { + } + + default void newEnumerationNoGood(NoGood noGood) { + } + + default void newJustificationNoGood(NoGood justification) { + } + + default void newNoGood(NoGood noGood) { + } + default void newNoGoods(Collection newNoGoods) { newNoGoods.forEach(this::newNoGood); } - default void newLearnedNoGood(NoGood noGood) {} + + default void newLearnedNoGood(NoGood noGood) { + } + default void newLearnedNoGoods(Collection newNoGoods) { newNoGoods.forEach(this::newLearnedNoGood); } + boolean isRebootScheduled(); + void rebootPerformed(); } From 1c94cb1a04330275b51961ed1841089513d9a6dd Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 13 Dec 2022 12:03:25 +0100 Subject: [PATCH 41/53] Change reboot strategy --- .../java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index c4e251c03..cf401d3b2 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -150,8 +150,8 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); // this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); // this.rebootStrategy = new LubyLearnedRebootStrategy(); -// this.rebootStrategy = dynamicRebootStrategy; - this.rebootStrategy = new GeometricLearnedRebootStrategy(); + this.rebootStrategy = dynamicRebootStrategy; +// this.rebootStrategy = new GeometricLearnedRebootStrategy(); statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, From 7998ec9a2fd87a13f1adaa00d168d62cf0c7936b Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sat, 25 Feb 2023 00:45:50 +0100 Subject: [PATCH 42/53] Add reboot strategy parametrization --- .../kr/alpha/api/config/RebootStrategy.java | 22 ++++++ .../kr/alpha/api/config/SystemConfig.java | 56 ++++++++++++--- .../alpha/app/config/CommandLineParser.java | 69 +++++++++++++++---- .../kr/alpha/core/solver/DefaultSolver.java | 8 +-- .../strategies/AnswerSetRebootStrategy.java | 24 +++++++ .../FixedLearnedRebootStrategy.java | 2 +- .../GeometricLearnedRebootStrategy.java | 11 ++- .../strategies/LubyLearnedRebootStrategy.java | 9 ++- .../strategies/RebootStrategyFactory.java | 21 ++++++ .../DynamicLearnedIntervalRebootStrategy.java | 43 ++++++++++-- .../FixedConflictRebootStrategy.java | 4 +- .../FixedDecisionRebootStrategy.java | 4 +- .../FixedIterationRebootStrategy.java | 4 +- .../GeometricConflictRebootStrategy.java | 4 +- .../{ => old}/LubyConflictRebootStrategy.java | 4 +- .../kr/alpha/core/util/Substitutions.java | 3 + .../core/solver/RegressionTestConfig.java | 23 +++---- .../solver/RegressionTestConfigProvider.java | 46 +++++++------ 18 files changed, 275 insertions(+), 82 deletions(-) create mode 100644 alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategy.java create mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{ => old}/DynamicLearnedIntervalRebootStrategy.java (77%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{ => old}/FixedConflictRebootStrategy.java (92%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{ => old}/FixedDecisionRebootStrategy.java (92%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{ => old}/FixedIterationRebootStrategy.java (92%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{ => old}/GeometricConflictRebootStrategy.java (93%) rename alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/{ => old}/LubyConflictRebootStrategy.java (93%) diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java new file mode 100644 index 000000000..19c5b09e1 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java @@ -0,0 +1,22 @@ +package at.ac.tuwien.kr.alpha.api.config; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * The available reboot strategies. + */ +public enum RebootStrategy { + FIXED, + GEOM, + LUBY, + ASSIGN, + ANSWER; + + /** + * @return a comma-separated list of names of known reboot strategies + */ + public static String listAllowedValues() { + return Arrays.stream(values()).map(RebootStrategy::toString).collect(Collectors.joining(", ")); + } +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index 0f85de0cb..8ae17b628 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -36,7 +36,7 @@ /** * Config structure for {@link Alpha} instances. - * + * * Copyright (c) 2021, the Alpha Team. */ public class SystemConfig { @@ -50,8 +50,11 @@ public class SystemConfig { public static final Heuristic DEFAULT_BRANCHING_HEURISTIC = Heuristic.VSIDS; public static final BinaryNoGoodPropagationEstimationStrategy DEFAULT_MOMS_STRATEGY = BinaryNoGoodPropagationEstimationStrategy.CountBinaryWatches; public static final boolean DEFAULT_REBOOT_ENABLED = false; - public static final int DEFAULT_REBOOT_ITERATIONS = 10000; public static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = false; + public static final RebootStrategy DEFAULT_REBOOT_STRATEGY = RebootStrategy.ANSWER; + public static final int DEFAULT_REBOOT_STRATEGY_ITERATIONS = 10000; + public static final double DEFAULT_REBOOT_STRATEGY_BASE = 1.5; + public static final double DEFAULT_REBOOT_STRATEGY_FACTOR = 2; public static final long DEFAULT_SEED = System.nanoTime(); public static final boolean DEFAULT_DETERMINISTIC = false; public static final boolean DEFAULT_PRINT_STATS = false; @@ -77,8 +80,11 @@ public class SystemConfig { private Heuristic branchingHeuristic = DEFAULT_BRANCHING_HEURISTIC; private BinaryNoGoodPropagationEstimationStrategy momsStrategy = DEFAULT_MOMS_STRATEGY; private boolean rebootEnabled = DEFAULT_REBOOT_ENABLED; - private int rebootIterations = DEFAULT_REBOOT_ITERATIONS; private boolean disableRebootRepeat = DEFAULT_DISABLE_REBOOT_REPEAT; + private RebootStrategy rebootStrategy = DEFAULT_REBOOT_STRATEGY; + private int rebootStrategyIterations = DEFAULT_REBOOT_STRATEGY_ITERATIONS; + private double rebootStrategyBase = DEFAULT_REBOOT_STRATEGY_BASE; + private double rebootStrategyFactor = DEFAULT_REBOOT_STRATEGY_FACTOR; private boolean quiet = DEFAULT_QUIET; private boolean printStats = DEFAULT_PRINT_STATS; private boolean disableJustificationSearch = DEFAULT_DISABLE_JUSTIFICATION_SEARCH; @@ -133,14 +139,6 @@ public void setRebootEnabled(boolean rebootEnabled) { this.rebootEnabled = rebootEnabled; } - public int getRebootIterations() { - return this.rebootIterations; - } - - public void setRebootIterations(int rebootIterations) { - this.rebootIterations = rebootIterations; - } - public boolean isDisableRebootRepeat() { return this.disableRebootRepeat; } @@ -149,6 +147,42 @@ public void setDisableRebootRepeat(boolean disableRebootRepeat) { this.disableRebootRepeat = disableRebootRepeat; } + public RebootStrategy getRebootStrategy() { + return this.rebootStrategy; + } + + public void setRebootStrategy(RebootStrategy rebootStrategy) { + this.rebootStrategy = rebootStrategy; + } + + public void setRebootStrategyName(String rebootStrategyName) { + this.rebootStrategy = RebootStrategy.valueOf(rebootStrategyName.replace("-", "_").toUpperCase()); + } + + public int getRebootStrategyIterations() { + return this.rebootStrategyIterations; + } + + public void setRebootStrategyIterations(int rebootStrategyIterations) { + this.rebootStrategyIterations = rebootStrategyIterations; + } + + public double getRebootStrategyBase() { + return this.rebootStrategyBase; + } + + public void setRebootStrategyBase(double rebootStrategyBase) { + this.rebootStrategyBase = rebootStrategyBase; + } + + public double getRebootStrategyFactor() { + return this.rebootStrategyFactor; + } + + public void setRebootStrategyFactor(double rebootStrategyFactor) { + this.rebootStrategyFactor = rebootStrategyFactor; + } + public boolean isDeterministic() { return this.deterministic; } diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 14b9045c5..18a41c628 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.function.Consumer; +import at.ac.tuwien.kr.alpha.api.config.*; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.HelpFormatter; @@ -45,13 +46,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.api.config.AggregateRewritingConfig; -import at.ac.tuwien.kr.alpha.api.config.AlphaConfig; -import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; -import at.ac.tuwien.kr.alpha.api.config.Heuristic; -import at.ac.tuwien.kr.alpha.api.config.InputConfig; -import at.ac.tuwien.kr.alpha.api.config.SystemConfig; - /** * Parses given argument lists (as passed when Alpha is called from command line) into {@link SystemConfig}s and * {@link InputConfig}s. @@ -98,10 +92,19 @@ public class CommandLineParser { .desc("the nogood store to use (default: " + SystemConfig.DEFAULT_NOGOOD_STORE_NAME + ")").build(); private static final Option OPT_REBOOT_ENABLED = Option.builder("rbt").longOpt("enableReboot") .desc("enable solver reboots (default: " + SystemConfig.DEFAULT_REBOOT_ENABLED + ")").build(); - private static final Option OPT_REBOOT_ITERATIONS = Option.builder("rit").longOpt("rebootIterations").hasArg(true).argName("number").type(Integer.class) - .desc("the number of solver iterations between reboots (default: " + SystemConfig.DEFAULT_REBOOT_ITERATIONS + ")").build(); private static final Option OPT_NO_REBOOT_REPEAT = Option.builder("drr").longOpt("disableRebootRepeat") .desc("disables repeated reboots resulting in at most one reboot during solving, only effective if reboot is enabled (default: " + SystemConfig.DEFAULT_DISABLE_REBOOT_REPEAT + ")").build(); + private static final Option OPT_REBOOT_STRATEGY = Option.builder("rbs").longOpt("rebootStrategy").hasArg(true).argName("strategy") + .desc("the reboot strategy to use (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY.name() + ")").build(); + private static final Option OPT_REBOOT_STRATEGY_ITERATIONS = Option.builder("rsi").longOpt("rebootIterations") + .hasArg(true).argName("number").type(Integer.class) + .desc("the number of solver iterations between reboots for a fixed reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_ITERATIONS + ")").build(); + private static final Option OPT_REBOOT_STRATEGY_BASE = Option.builder("rsb").longOpt("rebootIterations") + .hasArg(true).argName("number").type(Double.class) + .desc("the base value of a reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_BASE + ")").build(); + private static final Option OPT_REBOOT_STRATEGY_FACTOR = Option.builder("rsf").longOpt("rebootIterations") + .hasArg(true).argName("number").type(Double.class) + .desc("the scaling factor of a reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_FACTOR + ")").build(); private static final Option OPT_SORT = Option.builder("sort").longOpt("sort").hasArg(false) .desc("sort answer sets (default: " + SystemConfig.DEFAULT_SORT_ANSWER_SETS + ")").build(); private static final Option OPT_DETERMINISTIC = Option.builder("d").longOpt("deterministic").hasArg(false) @@ -177,8 +180,11 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SOLVER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NOGOOD_STORE); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ENABLED); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ITERATIONS); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NO_REBOOT_REPEAT); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_ITERATIONS); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_BASE); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_FACTOR); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SORT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_DETERMINISTIC); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SEED); @@ -238,8 +244,11 @@ private void initializeGlobalOptionHandlers() { this.globalOptionHandlers.put(CommandLineParser.OPT_SOLVER.getOpt(), this::handleSolver); this.globalOptionHandlers.put(CommandLineParser.OPT_NOGOOD_STORE.getOpt(), this::handleNogoodStore); this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_ENABLED.getOpt(), this::handleRebootEnabled); - this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_ITERATIONS.getOpt(), this::handleRebootIterations); this.globalOptionHandlers.put(CommandLineParser.OPT_NO_REBOOT_REPEAT.getOpt(), this::handleDisableRebootRepeat); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY.getOpt(), this::handleRebootStrategy); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_ITERATIONS.getOpt(), this::handleRebootStrategyIterations); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_BASE.getOpt(), this::handleRebootStrategyBase); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_FACTOR.getOpt(), this::handleRebootStrategyFactor); this.globalOptionHandlers.put(CommandLineParser.OPT_SORT.getOpt(), this::handleSort); this.globalOptionHandlers.put(CommandLineParser.OPT_DETERMINISTIC.getOpt(), this::handleDeterministic); this.globalOptionHandlers.put(CommandLineParser.OPT_SEED.getOpt(), this::handleSeed); @@ -367,14 +376,46 @@ private void handleDisableRebootRepeat(Option opt, SystemConfig cfg) { cfg.setDisableRebootRepeat(true); } - private void handleRebootIterations(Option opt, SystemConfig cfg) { + private void handleRebootStrategy(Option opt, SystemConfig cfg) throws ParseException { + String rebootStrategyName = opt.getValue(SystemConfig.DEFAULT_REBOOT_STRATEGY.name()); + try { + cfg.setRebootStrategyName(rebootStrategyName); + } catch (IllegalArgumentException e) { + throw new ParseException( + "Unknown reboot strategy: " + rebootStrategyName + ". Please try one of the following: " + RebootStrategy.listAllowedValues()); + } + } + + private void handleRebootStrategyIterations(Option opt, SystemConfig cfg) { String optVal = opt.getValue(); int limit; if (optVal != null) { limit = Integer.parseInt(optVal); - cfg.setRebootIterations(limit); + cfg.setRebootStrategyIterations(limit); + } else { + cfg.setRebootStrategyIterations(SystemConfig.DEFAULT_REBOOT_STRATEGY_ITERATIONS); + } + } + + private void handleRebootStrategyBase(Option opt, SystemConfig cfg) { + String optVal = opt.getValue(); + double limit; + if (optVal != null) { + limit = Double.parseDouble(optVal); + cfg.setRebootStrategyBase(limit); + } else { + cfg.setRebootStrategyBase(SystemConfig.DEFAULT_REBOOT_STRATEGY_BASE); + } + } + + private void handleRebootStrategyFactor(Option opt, SystemConfig cfg) { + String optVal = opt.getValue(); + double limit; + if (optVal != null) { + limit = Double.parseDouble(optVal); + cfg.setRebootStrategyFactor(limit); } else { - cfg.setRebootIterations(SystemConfig.DEFAULT_REBOOT_ITERATIONS); + cfg.setRebootStrategyFactor(SystemConfig.DEFAULT_REBOOT_STRATEGY_FACTOR); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index cf401d3b2..92bed8069 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -146,13 +146,7 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.rebootEnabled = config.isRebootEnabled(); this.disableRebootRepeat = config.isDisableRebootRepeat(); - DynamicLearnedIntervalRebootStrategy dynamicRebootStrategy = new DynamicLearnedIntervalRebootStrategy( - learnEfficiencyTracker, 0.7, 5, config.getRebootIterations()); -// this.rebootStrategy = new FixedLearnedRebootStrategy(config.getRebootIterations()); -// this.rebootStrategy = new LubyLearnedRebootStrategy(); - this.rebootStrategy = dynamicRebootStrategy; -// this.rebootStrategy = new GeometricLearnedRebootStrategy(); - statTrackers.add(dynamicRebootStrategy.getIntervalSizeTracker()); + this.rebootStrategy = RebootStrategyFactory.getRebootStrategy(config); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, store.getNoGoodCounter(), statTrackers, 1000); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategy.java new file mode 100644 index 000000000..0a4f142ba --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategy.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +public class AnswerSetRebootStrategy implements RebootStrategy { + private boolean reboot; + + public AnswerSetRebootStrategy() { + reboot = false; + } + + @Override + public void answerSetFound() { + reboot = true; + } + + @Override + public boolean isRebootScheduled() { + return reboot; + } + + @Override + public void rebootPerformed() { + reboot = false; + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java index cf7321eb6..ac4db3c76 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java @@ -3,7 +3,7 @@ import at.ac.tuwien.kr.alpha.core.common.NoGood; public class FixedLearnedRebootStrategy implements RebootStrategy { - private int breakpoint; + private final int breakpoint; private int learnedCounter; public FixedLearnedRebootStrategy(int breakpoint) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java index be6c961d5..333749cd3 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java @@ -28,12 +28,17 @@ import at.ac.tuwien.kr.alpha.core.common.NoGood; public class GeometricLearnedRebootStrategy implements RebootStrategy { - private static final double BASE = 1.5; - private static final double SCALING_FACTOR = 2; + private final double base; + private final double scalingFactor; private int rebootCount; private int learnedCount; + public GeometricLearnedRebootStrategy(double base, double scalingFactor) { + this.base = base; + this.scalingFactor = scalingFactor; + } + @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; @@ -41,7 +46,7 @@ public void newLearnedNoGood(NoGood noGood) { @Override public boolean isRebootScheduled() { - return learnedCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); + return learnedCount >= scalingFactor * Math.pow(base, rebootCount); } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java index 37a6c2156..49efba3f6 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java @@ -28,11 +28,14 @@ import at.ac.tuwien.kr.alpha.core.common.NoGood; public class LubyLearnedRebootStrategy implements RebootStrategy { - private static final double SCALING_FACTOR = 10; - + private final double scalingFactor; private int rebootCount; private int learnedCount; + public LubyLearnedRebootStrategy(double scalingFactor) { + this.scalingFactor = scalingFactor; + } + @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; @@ -40,7 +43,7 @@ public void newLearnedNoGood(NoGood noGood) { @Override public boolean isRebootScheduled() { - return learnedCount >= SCALING_FACTOR * luby(rebootCount + 1); + return learnedCount >= scalingFactor * luby(rebootCount + 1); } @Override diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java new file mode 100644 index 000000000..cd7f83f75 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java @@ -0,0 +1,21 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; + +public final class RebootStrategyFactory { + public static RebootStrategy getRebootStrategy(SystemConfig config) { + switch (config.getRebootStrategy()) { + case FIXED: + return new FixedLearnedRebootStrategy(config.getRebootStrategyIterations()); + case GEOM: + return new GeometricLearnedRebootStrategy(config.getRebootStrategyBase(), config.getRebootStrategyFactor()); + case LUBY: + return new LubyLearnedRebootStrategy(config.getRebootStrategyFactor()); + case ASSIGN: + return new CompleteAssignmentRebootStrategy(); + case ANSWER: + return new AnswerSetRebootStrategy(); + } + throw new IllegalArgumentException("Unknown reboot strategy requested."); + } +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java similarity index 77% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java index fdcb06e86..e2ab0f06d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/DynamicLearnedIntervalRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java @@ -23,11 +23,12 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; import at.ac.tuwien.kr.alpha.core.common.NoGood; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.ResettableStatTracker; import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.StatTracker; +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,9 +40,11 @@ public class DynamicLearnedIntervalRebootStrategy implements RebootStrategy { private final int minInterval; private final double scalingFactor; private double intervalSize; + private double nextIntervalSize; private int learnedCount; private double previousIntervalMeasure; private boolean isFirstInterval; + private boolean wasHalfPointHandled; public DynamicLearnedIntervalRebootStrategy(ResettableStatTracker efficiencyMeasure, double scalingFactor, @@ -64,6 +67,7 @@ public double getStatValue() { this.learnedCount = 0; this.previousIntervalMeasure = 0; this.isFirstInterval = true; + this.wasHalfPointHandled = false; } public StatTracker getIntervalSizeTracker() { @@ -73,6 +77,7 @@ public StatTracker getIntervalSizeTracker() { @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; + handleHalfPointIfNeeded(); } @Override @@ -82,12 +87,12 @@ public boolean isRebootScheduled() { @Override public void rebootPerformed() { - double currentIntervalMeasure = efficiencyMeasure.getStatValue(); - intervalSize = getNewIntervalSize(currentIntervalMeasure); - previousIntervalMeasure = currentIntervalMeasure; + previousIntervalMeasure = efficiencyMeasure.getStatValue(); + intervalSize = nextIntervalSize; efficiencyMeasure.reset(); learnedCount = 0; + wasHalfPointHandled = false; } private double getNewIntervalSize(double currentIntervalMeasure) { @@ -97,15 +102,41 @@ private double getNewIntervalSize(double currentIntervalMeasure) { isFirstInterval = false; return intervalSize; } else if (currentIntervalMeasure > previousIntervalMeasure) { - double newIntervalSize = intervalSize * scalingFactor; + double newIntervalSize = downscaleIntervalSize(intervalSize); LOGGER.info("Reboot interval size: {} -> {}", oldIntervalSize, newIntervalSize); LOGGER.info("Interval measures were: {} < {}", previousIntervalMeasure, currentIntervalMeasure); return Math.max(newIntervalSize, minInterval); } else { - double newIntervalSize = intervalSize / scalingFactor; + double newIntervalSize = upscaleIntervalSize(intervalSize); LOGGER.info("Reboot interval size: {} -> {}", oldIntervalSize, newIntervalSize); LOGGER.info("Interval measures were: {} >= {}", previousIntervalMeasure, currentIntervalMeasure); return Math.max(newIntervalSize, minInterval); } } + + private double downscaleIntervalSize(double intervalSize) { + return intervalSize * scalingFactor; + } + + private double upscaleIntervalSize(double intervalSize) { + return intervalSize / (scalingFactor * scalingFactor); + } + + private boolean isHalfPointReached() { + return learnedCount >= (int) (intervalSize / 2); + } + + private void handleHalfPoint() { + double currentIntervalMeasure = efficiencyMeasure.getStatValue(); + nextIntervalSize = getNewIntervalSize(currentIntervalMeasure); + + efficiencyMeasure.reset(); + wasHalfPointHandled = true; + } + + private void handleHalfPointIfNeeded() { + if (!wasHalfPointHandled && isHalfPointReached()) { + handleHalfPoint(); + } + } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java similarity index 92% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java index e1f697fb2..74af2b63e 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java @@ -23,7 +23,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; + +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; public class FixedConflictRebootStrategy implements RebootStrategy { private final int breakpoint; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java similarity index 92% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java index 123429676..6ba71f73c 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedDecisionRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java @@ -23,7 +23,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; + +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; public class FixedDecisionRebootStrategy implements RebootStrategy { private final int breakpoint; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java similarity index 92% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java index 117cedee5..393e8f78c 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedIterationRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java @@ -23,7 +23,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; + +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; public class FixedIterationRebootStrategy implements RebootStrategy { private final int breakpoint; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java similarity index 93% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java index 6a209ccfc..73ec9debf 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java @@ -23,7 +23,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; + +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; public class GeometricConflictRebootStrategy implements RebootStrategy { private static final double BASE = 1.5; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java similarity index 93% rename from alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java index 1ac4a5760..4418f32c4 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyConflictRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java @@ -23,7 +23,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; + +import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; public class LubyConflictRebootStrategy implements RebootStrategy { private static final double SCALING_FACTOR = 10; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java index 58df8f9a7..a3ea6f550 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java @@ -27,6 +27,9 @@ public static Substitution fromString(String str) { if (!assignment.equals("")) { String[] keyVal = assignment.split("->"); VariableTerm variable = Terms.newVariable(keyVal[0]); + if (keyVal.length < 2) { + System.out.println(assignment); + } Term assignedTerm = PROGRAM_PART_PARSER.parseTerm(keyVal[1]); ret.put(variable, assignedTerm); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index 28cb7d0bb..6c7ab1639 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -1,6 +1,7 @@ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.api.config.Heuristic; +import at.ac.tuwien.kr.alpha.api.config.RebootStrategy; import at.ac.tuwien.kr.alpha.api.config.SystemConfig; public class RegressionTestConfig { @@ -14,8 +15,9 @@ public class RegressionTestConfig { private final Heuristic branchingHeuristic; private final boolean rebootEnabled; - private final int rebootIterations; private final boolean disableRebootRepeat; + private final RebootStrategy rebootStrategy; + private final int rebootStrategyIterations; private final long seed; @@ -34,8 +36,8 @@ public class RegressionTestConfig { private final boolean supportNegativeSumElements; public RegressionTestConfig( - String solverName, String grounderName, String noGoodStoreName, - Heuristic branchingHeuristic, boolean rebootEnabled, int rebootIterations, boolean disableRebootRepeat, + String solverName, String grounderName, String noGoodStoreName, Heuristic branchingHeuristic, + boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategy rebootStrategy, int rebootIterations, long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { @@ -44,8 +46,9 @@ public RegressionTestConfig( this.noGoodStoreName = noGoodStoreName; this.branchingHeuristic = branchingHeuristic; this.rebootEnabled = rebootEnabled; - this.rebootIterations = rebootIterations; this.disableRebootRepeat = disableRebootRepeat; + this.rebootStrategy = rebootStrategy; + this.rebootStrategyIterations = rebootIterations; this.seed = seed; this.debugChecks = debugChecks; this.grounderToleranceConstraints = grounderToleranceConstraints; @@ -62,7 +65,7 @@ public SystemConfig toSystemConfig() { retVal.setSolverName(this.solverName); retVal.setNogoodStoreName(this.noGoodStoreName); retVal.setRebootEnabled(this.rebootEnabled); - retVal.setRebootIterations(this.rebootIterations); + retVal.setRebootStrategyIterations(this.rebootStrategyIterations); retVal.setDisableRebootRepeat(this.disableRebootRepeat); retVal.setSeed(this.seed); retVal.setBranchingHeuristic(this.branchingHeuristic); @@ -96,10 +99,6 @@ public boolean isRebootEnabled() { return rebootEnabled; } - public int getRebootIterations() { - return rebootIterations; - } - public long getSeed() { return this.seed; } @@ -136,11 +135,11 @@ public boolean isSupportNegativeSumElements() { public String toString() { return String.format( "RegressionTestConfig [solverName=%s, grounderName=%s, noGoodStoreName=%s, branchingHeuristic=%s," - + " rebootEnabled=%b, rebootIterations=%d, disableRebootRepeat=%b, seed=%s, debugChecks=%s," - + " grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s," + + " rebootEnabled=%b, disableRebootRepeat=%b, rebootStrategy=%s, rebootStrategyIterations=%d, seed=%s," + + " debugChecks=%s, grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s," + " evaluateStratifiedPart=%s, useSortingGrid=%s, supportNegativeSumElements=%s]", this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.rebootEnabled, - this.rebootIterations, this.disableRebootRepeat, this.seed, this.debugChecks, + this.disableRebootRepeat, this.rebootStrategy, this.rebootStrategyIterations, this.seed, this.debugChecks, this.grounderToleranceConstraints, this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index 95c215dd7..2d4a8e615 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Random; +import at.ac.tuwien.kr.alpha.api.config.RebootStrategy; import org.junit.jupiter.params.provider.Arguments; import at.ac.tuwien.kr.alpha.api.config.Heuristic; @@ -16,8 +17,9 @@ public class RegressionTestConfigProvider { private static final String DEFAULT_ATOM_STORE = "alpharoaming"; private static final String DEFAULT_BRANCHING_HEURISTIC = "VSIDS"; private static final boolean DEFAULT_REBOOT_ENABLED = false; - private static final int DEFAULT_REBOOT_ITERATIONS = 5; private static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = true; + private static final RebootStrategy DEFAULT_REBOOT_STRATEGY = RebootStrategy.FIXED; + private static final int DEFAULT_REBOOT_STRATEGY_ITERATIONS = 5; private static final String DEFAULT_GROUNDER_TOLERANCE = "strict"; private static final boolean DEFAULT_DISABLE_INSTANCE_REMOVAL = false; private static final boolean DEFAULT_ENABLE_DEBUG_CHECKS = false; @@ -40,7 +42,8 @@ private static List buildConfigs() { String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive"} : new String[]{DEFAULT_ATOM_STORE}; String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC}; boolean[] rebootEnabledValues = new boolean[]{DEFAULT_REBOOT_ENABLED, true}; - int[] rebootIterationsValues = new int[]{DEFAULT_REBOOT_ITERATIONS}; + RebootStrategy[] rebootStrategyValues = new RebootStrategy[]{DEFAULT_REBOOT_STRATEGY}; + int[] rebootStrategyIterationsValues = new int[]{DEFAULT_REBOOT_STRATEGY_ITERATIONS}; boolean[] disableRebootRepeatValues = new boolean[]{DEFAULT_DISABLE_REBOOT_REPEAT}; String[] gtcValues = new String[]{DEFAULT_GROUNDER_TOLERANCE, "permissive"}; String gtrValue = DEFAULT_GROUNDER_TOLERANCE; @@ -63,19 +66,22 @@ private static List buildConfigs() { for (String atomStoreName : atomStores) { for (String branchingHeuristicName : heuristics) { for (boolean rebootEnabled : rebootEnabledValues) { - for (int rebootIterations : rebootIterationsValues) { - for (boolean disableRebootRepeat : disableRebootRepeatValues) { - for (String grounderTolerance : gtcValues) { - for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { - for (boolean evaluateStratified : evaluateStratifiedValues) { - for (boolean enableDebugChecks : enableDebugChecksValues) { - configsToTest.add(new RegressionTestConfig( - solverName, grounder, atomStoreName, - Heuristic.valueOf(branchingHeuristicName), - rebootEnabled, rebootIterations, disableRebootRepeat, - seed, enableDebugChecks, grounderTolerance, gtrValue, - disableInstanceRemoval, evaluateStratified, - true, true)); + for (boolean disableRebootRepeat : disableRebootRepeatValues) { + for (RebootStrategy rebootStrategy : rebootStrategyValues) { + for (int rebootIterations : rebootStrategyIterationsValues) { + for (String grounderTolerance : gtcValues) { + for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { + for (boolean evaluateStratified : evaluateStratifiedValues) { + for (boolean enableDebugChecks : enableDebugChecksValues) { + configsToTest.add(new RegressionTestConfig( + solverName, grounder, atomStoreName, + Heuristic.valueOf(branchingHeuristicName), + rebootEnabled, disableRebootRepeat, rebootStrategy, + rebootIterations, seed, enableDebugChecks, + grounderTolerance, gtrValue, + disableInstanceRemoval, evaluateStratified, + true, true)); + } } } } @@ -111,11 +117,11 @@ private static List buildConfigsForAggregateTests() { new RegressionTestConfig( DEFAULT_SOLVER_NAME, DEFAULT_GROUNDER_NAME, DEFAULT_ATOM_STORE, Heuristic.valueOf(DEFAULT_BRANCHING_HEURISTIC), - DEFAULT_REBOOT_ENABLED, DEFAULT_REBOOT_ITERATIONS, DEFAULT_DISABLE_REBOOT_REPEAT, - 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, - DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, - evalStratified, - useSortingGrid, supportNegativeElements)); + DEFAULT_REBOOT_ENABLED, DEFAULT_DISABLE_REBOOT_REPEAT, DEFAULT_REBOOT_STRATEGY, + DEFAULT_REBOOT_STRATEGY_ITERATIONS, 0, DEFAULT_ENABLE_DEBUG_CHECKS, + DEFAULT_GROUNDER_TOLERANCE, DEFAULT_GROUNDER_TOLERANCE, + DEFAULT_DISABLE_INSTANCE_REMOVAL, + evalStratified, useSortingGrid, supportNegativeElements)); } } } From 8de265710bbb1d82feca1ad8e5f8922504a5e71a Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 28 Feb 2023 15:59:01 +0100 Subject: [PATCH 43/53] Remove obsolete Substitutions class, track enumeration nogoods in fixed reboot strategy --- .../FixedLearnedRebootStrategy.java | 5 +++ .../kr/alpha/core/util/Substitutions.java | 35 ------------------- 2 files changed, 5 insertions(+), 35 deletions(-) delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java index ac4db3c76..0df0fdf2d 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java @@ -11,6 +11,11 @@ public FixedLearnedRebootStrategy(int breakpoint) { this.learnedCounter = 0; } + @Override + public void newEnumerationNoGood(NoGood noGood) { + learnedCounter++; + } + @Override public void newLearnedNoGood(NoGood noGood) { learnedCounter++; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java deleted file mode 100644 index e018fce4b..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java +++ /dev/null @@ -1,35 +0,0 @@ -package at.ac.tuwien.kr.alpha.core.util; - -import at.ac.tuwien.kr.alpha.api.grounder.Substitution; -import at.ac.tuwien.kr.alpha.api.programs.terms.Term; -import at.ac.tuwien.kr.alpha.api.programs.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.commons.programs.terms.Terms; -import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; -import at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser; - -public final class Substitutions { - - private static final ProgramPartParser PROGRAM_PART_PARSER = new ProgramPartParser(); - - private Substitutions() { - throw new AssertionError("Cannot instantiate utility class!"); - } - - public static Substitution fromString(String str) { - String bare = str.substring(1, str.length() - 1); - String[] assignments = bare.split(","); - BasicSubstitution ret = new BasicSubstitution(); - for (String assignment : assignments) { - if (!assignment.equals("")) { - String[] keyVal = assignment.split("->"); - VariableTerm variable = Terms.newVariable(keyVal[0]); - if (keyVal.length < 2) { - System.out.println(assignment); - } - Term assignedTerm = PROGRAM_PART_PARSER.parseTerm(keyVal[1]); - ret.put(variable, assignedTerm); - } - } - return ret; - } -} From f106f3106f7f5bba91f18b5fadb997c5f00a2c0b Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 1 Mar 2023 14:40:05 +0100 Subject: [PATCH 44/53] Track enumeration nogoods in static reboot strategies, fix long option names --- .../kr/alpha/app/config/CommandLineParser.java | 6 +++--- .../strategies/FixedLearnedRebootStrategy.java | 12 ++++++------ .../strategies/GeometricLearnedRebootStrategy.java | 5 +++++ .../reboot/strategies/LubyLearnedRebootStrategy.java | 5 +++++ 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 53ee81bae..2ab52cd8f 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -97,13 +97,13 @@ public class CommandLineParser { .desc("disables repeated reboots resulting in at most one reboot during solving, only effective if reboot is enabled (default: " + SystemConfig.DEFAULT_DISABLE_REBOOT_REPEAT + ")").build(); private static final Option OPT_REBOOT_STRATEGY = Option.builder("rbs").longOpt("rebootStrategy").hasArg(true).argName("strategy") .desc("the reboot strategy to use (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY.name() + ")").build(); - private static final Option OPT_REBOOT_STRATEGY_ITERATIONS = Option.builder("rsi").longOpt("rebootIterations") + private static final Option OPT_REBOOT_STRATEGY_ITERATIONS = Option.builder("rsi").longOpt("rebootStrategyIterations") .hasArg(true).argName("number").type(Integer.class) .desc("the number of solver iterations between reboots for a fixed reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_ITERATIONS + ")").build(); - private static final Option OPT_REBOOT_STRATEGY_BASE = Option.builder("rsb").longOpt("rebootIterations") + private static final Option OPT_REBOOT_STRATEGY_BASE = Option.builder("rsb").longOpt("rebootStrategyBase") .hasArg(true).argName("number").type(Double.class) .desc("the base value of a reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_BASE + ")").build(); - private static final Option OPT_REBOOT_STRATEGY_FACTOR = Option.builder("rsf").longOpt("rebootIterations") + private static final Option OPT_REBOOT_STRATEGY_FACTOR = Option.builder("rsf").longOpt("rebootStrategyFactor") .hasArg(true).argName("number").type(Double.class) .desc("the scaling factor of a reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_FACTOR + ")").build(); private static final Option OPT_SORT = Option.builder("sort").longOpt("sort").hasArg(false) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java index 0df0fdf2d..6a0cc8a6a 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategy.java @@ -4,30 +4,30 @@ public class FixedLearnedRebootStrategy implements RebootStrategy { private final int breakpoint; - private int learnedCounter; + private int learnedCount; public FixedLearnedRebootStrategy(int breakpoint) { this.breakpoint = breakpoint; - this.learnedCounter = 0; + this.learnedCount = 0; } @Override public void newEnumerationNoGood(NoGood noGood) { - learnedCounter++; + learnedCount++; } @Override public void newLearnedNoGood(NoGood noGood) { - learnedCounter++; + learnedCount++; } @Override public boolean isRebootScheduled() { - return learnedCounter >= breakpoint; + return learnedCount >= breakpoint; } @Override public void rebootPerformed() { - learnedCounter = 0; + learnedCount = 0; } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java index 333749cd3..c54152c34 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategy.java @@ -39,6 +39,11 @@ public GeometricLearnedRebootStrategy(double base, double scalingFactor) { this.scalingFactor = scalingFactor; } + @Override + public void newEnumerationNoGood(NoGood noGood) { + learnedCount++; + } + @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java index 49efba3f6..7b12ee116 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java @@ -36,6 +36,11 @@ public LubyLearnedRebootStrategy(double scalingFactor) { this.scalingFactor = scalingFactor; } + @Override + public void newEnumerationNoGood(NoGood noGood) { + learnedCount++; + } + @Override public void newLearnedNoGood(NoGood noGood) { learnedCount++; From 227cd61105b15f1b8688100238de0fd95844a18a Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 1 Mar 2023 18:22:59 +0100 Subject: [PATCH 45/53] Rename solver option --- .../tuwien/kr/alpha/api/config/SystemConfig.java | 12 ++++++------ .../kr/alpha/app/config/CommandLineParser.java | 14 +++++++------- .../reboot/strategies/RebootStrategyFactory.java | 2 +- .../kr/alpha/core/solver/RegressionTestConfig.java | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index 8ae17b628..2ef40dfe7 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -52,7 +52,7 @@ public class SystemConfig { public static final boolean DEFAULT_REBOOT_ENABLED = false; public static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = false; public static final RebootStrategy DEFAULT_REBOOT_STRATEGY = RebootStrategy.ANSWER; - public static final int DEFAULT_REBOOT_STRATEGY_ITERATIONS = 10000; + public static final int DEFAULT_REBOOT_STRATEGY_INTERVAL = 10000; public static final double DEFAULT_REBOOT_STRATEGY_BASE = 1.5; public static final double DEFAULT_REBOOT_STRATEGY_FACTOR = 2; public static final long DEFAULT_SEED = System.nanoTime(); @@ -82,7 +82,7 @@ public class SystemConfig { private boolean rebootEnabled = DEFAULT_REBOOT_ENABLED; private boolean disableRebootRepeat = DEFAULT_DISABLE_REBOOT_REPEAT; private RebootStrategy rebootStrategy = DEFAULT_REBOOT_STRATEGY; - private int rebootStrategyIterations = DEFAULT_REBOOT_STRATEGY_ITERATIONS; + private int rebootStrategyInterval = DEFAULT_REBOOT_STRATEGY_INTERVAL; private double rebootStrategyBase = DEFAULT_REBOOT_STRATEGY_BASE; private double rebootStrategyFactor = DEFAULT_REBOOT_STRATEGY_FACTOR; private boolean quiet = DEFAULT_QUIET; @@ -159,12 +159,12 @@ public void setRebootStrategyName(String rebootStrategyName) { this.rebootStrategy = RebootStrategy.valueOf(rebootStrategyName.replace("-", "_").toUpperCase()); } - public int getRebootStrategyIterations() { - return this.rebootStrategyIterations; + public int getRebootStrategyInterval() { + return this.rebootStrategyInterval; } - public void setRebootStrategyIterations(int rebootStrategyIterations) { - this.rebootStrategyIterations = rebootStrategyIterations; + public void setRebootStrategyInterval(int rebootStrategyInterval) { + this.rebootStrategyInterval = rebootStrategyInterval; } public double getRebootStrategyBase() { diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 2ab52cd8f..3b5f6db74 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -97,9 +97,9 @@ public class CommandLineParser { .desc("disables repeated reboots resulting in at most one reboot during solving, only effective if reboot is enabled (default: " + SystemConfig.DEFAULT_DISABLE_REBOOT_REPEAT + ")").build(); private static final Option OPT_REBOOT_STRATEGY = Option.builder("rbs").longOpt("rebootStrategy").hasArg(true).argName("strategy") .desc("the reboot strategy to use (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY.name() + ")").build(); - private static final Option OPT_REBOOT_STRATEGY_ITERATIONS = Option.builder("rsi").longOpt("rebootStrategyIterations") + private static final Option OPT_REBOOT_STRATEGY_INTERVAL = Option.builder("rsi").longOpt("rebootStrategyInterval") .hasArg(true).argName("number").type(Integer.class) - .desc("the number of solver iterations between reboots for a fixed reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_ITERATIONS + ")").build(); + .desc("the size of the interval between reboots for a fixed reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_INTERVAL + ")").build(); private static final Option OPT_REBOOT_STRATEGY_BASE = Option.builder("rsb").longOpt("rebootStrategyBase") .hasArg(true).argName("number").type(Double.class) .desc("the base value of a reboot strategy (default: " + SystemConfig.DEFAULT_REBOOT_STRATEGY_BASE + ")").build(); @@ -184,7 +184,7 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_ENABLED); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_NO_REBOOT_REPEAT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_ITERATIONS); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_INTERVAL); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_BASE); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_REBOOT_STRATEGY_FACTOR); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SORT); @@ -248,7 +248,7 @@ private void initializeGlobalOptionHandlers() { this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_ENABLED.getOpt(), this::handleRebootEnabled); this.globalOptionHandlers.put(CommandLineParser.OPT_NO_REBOOT_REPEAT.getOpt(), this::handleDisableRebootRepeat); this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY.getOpt(), this::handleRebootStrategy); - this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_ITERATIONS.getOpt(), this::handleRebootStrategyIterations); + this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_INTERVAL.getOpt(), this::handleRebootStrategyInterval); this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_BASE.getOpt(), this::handleRebootStrategyBase); this.globalOptionHandlers.put(CommandLineParser.OPT_REBOOT_STRATEGY_FACTOR.getOpt(), this::handleRebootStrategyFactor); this.globalOptionHandlers.put(CommandLineParser.OPT_SORT.getOpt(), this::handleSort); @@ -389,14 +389,14 @@ private void handleRebootStrategy(Option opt, SystemConfig cfg) throws ParseExce } } - private void handleRebootStrategyIterations(Option opt, SystemConfig cfg) { + private void handleRebootStrategyInterval(Option opt, SystemConfig cfg) { String optVal = opt.getValue(); int limit; if (optVal != null) { limit = Integer.parseInt(optVal); - cfg.setRebootStrategyIterations(limit); + cfg.setRebootStrategyInterval(limit); } else { - cfg.setRebootStrategyIterations(SystemConfig.DEFAULT_REBOOT_STRATEGY_ITERATIONS); + cfg.setRebootStrategyInterval(SystemConfig.DEFAULT_REBOOT_STRATEGY_INTERVAL); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java index cd7f83f75..140376b35 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategyFactory.java @@ -6,7 +6,7 @@ public final class RebootStrategyFactory { public static RebootStrategy getRebootStrategy(SystemConfig config) { switch (config.getRebootStrategy()) { case FIXED: - return new FixedLearnedRebootStrategy(config.getRebootStrategyIterations()); + return new FixedLearnedRebootStrategy(config.getRebootStrategyInterval()); case GEOM: return new GeometricLearnedRebootStrategy(config.getRebootStrategyBase(), config.getRebootStrategyFactor()); case LUBY: diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index 6c7ab1639..3959dcc39 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -17,7 +17,7 @@ public class RegressionTestConfig { private final boolean rebootEnabled; private final boolean disableRebootRepeat; private final RebootStrategy rebootStrategy; - private final int rebootStrategyIterations; + private final int rebootStrategyInterval; private final long seed; @@ -37,7 +37,7 @@ public class RegressionTestConfig { public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, Heuristic branchingHeuristic, - boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategy rebootStrategy, int rebootIterations, + boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategy rebootStrategy, int rebootStrategyInterval, long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { @@ -48,7 +48,7 @@ public RegressionTestConfig( this.rebootEnabled = rebootEnabled; this.disableRebootRepeat = disableRebootRepeat; this.rebootStrategy = rebootStrategy; - this.rebootStrategyIterations = rebootIterations; + this.rebootStrategyInterval = rebootStrategyInterval; this.seed = seed; this.debugChecks = debugChecks; this.grounderToleranceConstraints = grounderToleranceConstraints; @@ -65,7 +65,7 @@ public SystemConfig toSystemConfig() { retVal.setSolverName(this.solverName); retVal.setNogoodStoreName(this.noGoodStoreName); retVal.setRebootEnabled(this.rebootEnabled); - retVal.setRebootStrategyIterations(this.rebootStrategyIterations); + retVal.setRebootStrategyInterval(this.rebootStrategyInterval); retVal.setDisableRebootRepeat(this.disableRebootRepeat); retVal.setSeed(this.seed); retVal.setBranchingHeuristic(this.branchingHeuristic); @@ -135,11 +135,11 @@ public boolean isSupportNegativeSumElements() { public String toString() { return String.format( "RegressionTestConfig [solverName=%s, grounderName=%s, noGoodStoreName=%s, branchingHeuristic=%s," - + " rebootEnabled=%b, disableRebootRepeat=%b, rebootStrategy=%s, rebootStrategyIterations=%d, seed=%s," + + " rebootEnabled=%b, disableRebootRepeat=%b, rebootStrategy=%s, rebootStrategyInterval=%d, seed=%s," + " debugChecks=%s, grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s," + " evaluateStratifiedPart=%s, useSortingGrid=%s, supportNegativeSumElements=%s]", this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.rebootEnabled, - this.disableRebootRepeat, this.rebootStrategy, this.rebootStrategyIterations, this.seed, this.debugChecks, + this.disableRebootRepeat, this.rebootStrategy, this.rebootStrategyInterval, this.seed, this.debugChecks, this.grounderToleranceConstraints, this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); } From 3dfad440e32d83d47fce12bc212aaf90df536921 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Fri, 17 Mar 2023 15:09:59 +0100 Subject: [PATCH 46/53] Remove stat trackers and stop watches --- .../kr/alpha/core/solver/DefaultSolver.java | 94 +----------- .../alpha/core/solver/NaiveNoGoodStore.java | 8 +- .../kr/alpha/core/solver/NoGoodStore.java | 3 - .../core/solver/NoGoodStoreAlphaRoaming.java | 15 -- .../kr/alpha/core/solver/PerformanceLog.java | 18 +-- .../core/solver/reboot/RebootManager.java | 8 +- .../reboot/stats/LearnedNoGoodTracker.java | 56 ------- .../reboot/stats/PropagationStatManager.java | 92 ------------ .../solver/reboot/stats/QuotientTracker.java | 51 ------- .../stats/ResettableQuotientTracker.java | 57 ------- .../reboot/stats/ResettableStatTracker.java | 30 ---- .../reboot/stats/SimpleCountingTracker.java | 60 -------- .../core/solver/reboot/stats/StatTracker.java | 31 ---- .../reboot/stats/StaticNoGoodTracker.java | 56 ------- .../solver/reboot/stats/StopWatchTracker.java | 53 ------- .../reboot/stats/TotalNoGoodTracker.java | 55 ------- .../DynamicLearnedIntervalRebootStrategy.java | 142 ------------------ .../old/FixedConflictRebootStrategy.java | 53 ------- .../old/FixedDecisionRebootStrategy.java | 53 ------- .../old/FixedIterationRebootStrategy.java | 53 ------- .../old/GeometricConflictRebootStrategy.java | 51 ------- .../old/LubyConflictRebootStrategy.java | 63 -------- .../tuwien/kr/alpha/core/util/StopWatch.java | 86 ----------- 23 files changed, 8 insertions(+), 1180 deletions(-) delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java delete mode 100644 alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index e9e821726..364d43381 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -43,9 +43,7 @@ import at.ac.tuwien.kr.alpha.core.grounder.RebootableGrounder; import at.ac.tuwien.kr.alpha.core.solver.reboot.AtomizedChoice; import at.ac.tuwien.kr.alpha.core.solver.reboot.RebootManager; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.*; import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.*; -import at.ac.tuwien.kr.alpha.core.util.StopWatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -106,17 +104,6 @@ private static class SearchState { private final PerformanceLog performanceLog; - private final StopWatch solverStopWatch; - private final StopWatch grounderStopWatch; - private final StopWatch propagationStopWatch; - private final StopWatch mbtBacktrackingStopWatch; - private final StopWatch epochStopWatch; - private final SimpleCountingTracker iterationTracker; - private final SimpleCountingTracker conflictTracker; - private final SimpleCountingTracker decisionTracker; - private final SimpleCountingTracker learnedNoGoodTracker; - private final ResettableStatTracker learnEfficiencyTracker; - public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, WritableAssignment assignment, Random random, SystemConfig config, HeuristicsConfiguration heuristicsConfiguration) { super(atomStore, grounder); @@ -130,26 +117,12 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableJustifications = config.isDisableJustificationSearch(); this.disableNoGoodDeletion = config.isDisableNoGoodDeletion(); - this.solverStopWatch = new StopWatch(); - this.grounderStopWatch = new StopWatch(); - this.propagationStopWatch = new StopWatch(); - this.mbtBacktrackingStopWatch = new StopWatch(); - this.epochStopWatch = new StopWatch(); - - this.iterationTracker = new SimpleCountingTracker("iterations"); - this.conflictTracker = new SimpleCountingTracker("conflicts"); - this.decisionTracker = new SimpleCountingTracker("decisions"); - this.learnedNoGoodTracker = new SimpleCountingTracker("learned_nogoods"); - this.learnEfficiencyTracker = new ResettableQuotientTracker("learn_effic", - learnedNoGoodTracker, new StopWatchTracker("solver_time", epochStopWatch)); - List statTrackers = initStatTrackers(); - this.rebootEnabled = config.isRebootEnabled(); this.disableRebootRepeat = config.isDisableRebootRepeat(); this.rebootStrategy = RebootStrategyFactory.getRebootStrategy(config); this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, - store.getNoGoodCounter(), statTrackers, 1000); + store.getNoGoodCounter(), 1000); if (this.rebootEnabled && !(grounder instanceof RebootableGrounder)) { this.rebootEnabled = false; @@ -170,8 +143,6 @@ private BranchingHeuristic chainFallbackHeuristic(Grounder grounder, WritableAss @Override protected boolean tryAdvance(Consumer action) { - solverStopWatch.start(); - epochStopWatch.start(); if (!searchState.hasBeenInitialized) { initializeSearch(); } else { @@ -180,19 +151,16 @@ protected boolean tryAdvance(Consumer action) { // Try all assignments until grounder reports no more NoGoods and all of them are satisfied while (true) { rebootStrategy.nextIteration(); - iterationTracker.increment(); performanceLog.writeIfTimeForLogging(LOGGER); if (searchState.isSearchSpaceCompletelyExplored) { LOGGER.debug("Search space has been fully explored, there are no more answer-sets."); logStats(); - stopStopWatchesAndLogRuntimes(); return false; } ConflictCause conflictCause = propagate(); if (conflictCause != null) { LOGGER.debug("Conflict encountered, analyzing conflict."); learnFromConflict(conflictCause); - conflictTracker.increment(); rebootStrategy.conflictEncountered(); } else if (assignment.didChange()) { LOGGER.debug("Updating grounder with new assignments and (potentially) obtaining new NoGoods."); @@ -211,12 +179,9 @@ protected boolean tryAdvance(Consumer action) { } else if (assignment.getMBTCount() == 0) { provideAnswerSet(action); rebootStrategy.answerSetFound(); - stopStopWatchesAndLogRuntimes(); return true; } else { - mbtBacktrackingStopWatch.start(); backtrackFromMBTsRemaining(); - mbtBacktrackingStopWatch.stop(); rebootStrategy.backtrackJustified(); } } @@ -268,9 +233,7 @@ private void prepareForSubsequentAnswerSet() { } private void getNoGoodsFromGrounderAndIngest() { - grounderStopWatch.start(); Map obtained = grounder.getNoGoods(assignment); - grounderStopWatch.stop(); rebootStrategy.newNoGoods(obtained.values()); if (!ingest(obtained)) { searchState.isSearchSpaceCompletelyExplored = true; @@ -299,9 +262,7 @@ private void learnFromConflict(ConflictCause conflictCause) { private ConflictCause propagate() { LOGGER.trace("Doing propagation step."); - propagationStopWatch.start(); ConflictCause conflictCause = store.propagate(); - propagationStopWatch.stop(); LOGGER.trace("Assignment after propagation is: {}", assignment); if (!disableNoGoodDeletion && conflictCause == null) { // Run learned-NoGood deletion-strategy. @@ -340,11 +301,9 @@ private boolean addAndBackjumpIfNecessary(int noGoodId, NoGood noGood, int lbd) return false; } choiceManager.backjump(backjumpLevel); - propagationStopWatch.start(); if (store.propagate() != null) { throw oops("Violated NoGood after backtracking."); } - propagationStopWatch.stop(); } return true; } @@ -373,7 +332,6 @@ private boolean learnBackjumpAddFromConflict(ConflictCause conflictCause) { final NoGood learnedNoGood = analysisResult.learnedNoGood; rebootManager.newLearnedNoGood(learnedNoGood); rebootStrategy.newLearnedNoGood(learnedNoGood); - learnedNoGoodTracker.increment(); int noGoodId = grounder.register(learnedNoGood); return addAndBackjumpIfNecessary(noGoodId, learnedNoGood, analysisResult.lbd); } @@ -496,7 +454,6 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { boolean success = ingest(obtained); rebootManager.newLearnedNoGoods(obtained.values()); rebootStrategy.newLearnedNoGoods(obtained.values()); - learnedNoGoodTracker.incrementBy(obtained.values().size()); if (!success) { logStats(); return false; @@ -603,7 +560,6 @@ private boolean choose() { } choiceManager.choose(new Choice(literal, false)); - decisionTracker.increment(); return true; } @@ -735,54 +691,6 @@ private void ingestNoGoodsFromRulesOfRuleAtoms(List ruleAtoms) { } } - /** - * Stops the {@link DefaultSolver#solverStopWatch} and {@link DefaultSolver#epochStopWatch}. - * Then logs the current total time of all {@link StopWatch}es kept by the {@link DefaultSolver}. - */ - private void stopStopWatchesAndLogRuntimes() { - solverStopWatch.stop(); - epochStopWatch.stop(); - LOGGER.info("Solver runtime: {}", solverStopWatch.getNanoTime()); - LOGGER.info("Grounder runtime: {}", grounderStopWatch.getNanoTime()); - LOGGER.info("Propagation runtime: {}", propagationStopWatch.getNanoTime()); - LOGGER.info("Mbt-backtracking runtime: {}", mbtBacktrackingStopWatch.getNanoTime()); - LOGGER.info("Epoch runtime: {}", epochStopWatch.getNanoTime()); - } - - private List initStatTrackers() { - StaticNoGoodTracker staticNoGoodExtractingTracker = new StaticNoGoodTracker(getNoGoodCounter()); - LearnedNoGoodTracker learnedNoGoodExtractingTracker = new LearnedNoGoodTracker(getNoGoodCounter()); - TotalNoGoodTracker totalNoGoodExtractingTracker = new TotalNoGoodTracker(getNoGoodCounter()); - - List statTrackers = new LinkedList<>(); - statTrackers.add(iterationTracker); - statTrackers.add(conflictTracker); - statTrackers.add(decisionTracker); - statTrackers.add(learnedNoGoodTracker); - statTrackers.add(staticNoGoodExtractingTracker); - statTrackers.add(learnedNoGoodExtractingTracker); - statTrackers.add(totalNoGoodExtractingTracker); - statTrackers.add(learnEfficiencyTracker); - - PropagationStatManager propagationStatManager = this.store.getPropagationStatManager(); - if (propagationStatManager != null) { - List propagationTrackers = propagationStatManager.getStatTrackerList(); - statTrackers.addAll(propagationTrackers); - - ResettableStatTracker propagationTracker = propagationStatManager.getPropagationTracker(); - ResettableStatTracker propagationConflictTracker = propagationStatManager.getPropagationConflictTracker(); - ResettableStatTracker nonbinPropagationTracker = propagationStatManager.getNonbinPropagationTracker(); - ResettableStatTracker nonbinPropagationConflictTracker = propagationStatManager.getNonbinPropagationConflictTracker(); - statTrackers.add(new ResettableQuotientTracker("prop_quot", propagationConflictTracker, propagationTracker)); - statTrackers.add(new QuotientTracker("prop_quot_nonbin", nonbinPropagationConflictTracker, nonbinPropagationTracker)); - } - - statTrackers.add(new QuotientTracker("conflict_quot", conflictTracker, iterationTracker)); - statTrackers.add(new QuotientTracker("nogood_quot", staticNoGoodExtractingTracker, totalNoGoodExtractingTracker)); - - return statTrackers; - } - @Override public int getNumberOfChoices() { return choiceManager.getChoices(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java index 173a4b4cf..3aa2a9331 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java @@ -27,7 +27,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.PropagationStatManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -145,12 +144,7 @@ public void reset() { clear(); counter.reset(); } - - @Override - public PropagationStatManager getPropagationStatManager() { - return null; - } - + @Override public void cleanupLearnedNoGoods() { } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java index 5fb0feb10..c3e3e7165 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java @@ -1,7 +1,6 @@ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.core.common.NoGood; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.PropagationStatManager; /** * An interface defining the use of a NoGood store. @@ -61,6 +60,4 @@ public interface NoGoodStore { * Clears all data within the nogood store. */ void reset(); - - PropagationStatManager getPropagationStatManager(); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index f1dd99cf0..80e450ca9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -27,7 +27,6 @@ */ package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.PropagationStatManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,13 +86,11 @@ public class NoGoodStoreAlphaRoaming implements NoGoodStore, BinaryNoGoodPropaga private boolean hasBinaryNoGoods; private final NoGoodCounter counter = new NoGoodCounter(); - private final PropagationStatManager propagationStatManager; public NoGoodStoreAlphaRoaming(WritableAssignment assignment, boolean checksEnabled) { this.assignment = assignment; this.checksEnabled = checksEnabled; this.learnedNoGoodDeletion = new LearnedNoGoodDeletion(this, assignment); - this.propagationStatManager = new PropagationStatManager(); } public NoGoodStoreAlphaRoaming(WritableAssignment assignment) { @@ -162,12 +159,6 @@ public NoGoodCounter getNoGoodCounter() { public void reset() { clear(); counter.reset(); - propagationStatManager.reset(); - } - - @Override - public PropagationStatManager getPropagationStatManager() { - return propagationStatManager; } @@ -473,7 +464,6 @@ private ConflictCause propagateWeakly(int literal, int currentDecisionLevel, boo // Propagate binary watches. ConflictCause conflictCause = binaryWatches[literal].propagateWeakly(); if (conflictCause != null || restrictToBinaryNoGoods) { - propagationStatManager.handleBinaryConflict(); return conflictCause; } @@ -490,11 +480,9 @@ private ConflictCause propagateWeakly(int literal, int currentDecisionLevel, boo while (watchIterator.hasNext()) { watchlist.add(watchIterator.next()); } - propagationStatManager.handleNonBinaryConflict(); return conflictCause; } } - propagationStatManager.handleNoConflict(); return null; } @@ -566,7 +554,6 @@ private ConflictCause propagateStrongly(int literal, int currentDecisionLevel, b // Propagate binary watches. ConflictCause conflictCause = binaryWatches[literal].propagateStrongly(); if (conflictCause != null || restrictToBinaryNoGoods) { - propagationStatManager.handleBinaryConflict(); return conflictCause; } @@ -586,11 +573,9 @@ private ConflictCause propagateStrongly(int literal, int currentDecisionLevel, b while (watchIterator.hasNext()) { watchlist.add(watchIterator.next()); } - propagationStatManager.handleNonBinaryConflict(); return conflictCause; } } - propagationStatManager.handleNoConflict(); return null; } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java index fc68c7e91..fc20fe6a8 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java @@ -25,11 +25,8 @@ */ package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.StatTracker; import org.slf4j.Logger; -import java.util.List; - /** * Collects performance data (mainly number of decisions per second) and outputs them on demand. */ @@ -38,7 +35,6 @@ public class PerformanceLog { private final ChoiceManager choiceManager; private final TrailAssignment assignment; private final NoGoodCounter noGoodCounter; - private final List statTrackers; private final long msBetweenOutputs; private Long timeFirstEntry; @@ -48,12 +44,11 @@ public class PerformanceLog { /** * @param msBetweenOutputs minimum number of milliseconds that have to pass between writing of performance logs. */ - public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, NoGoodCounter noGoodCounter, List statTrackers, long msBetweenOutputs) { + public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, NoGoodCounter noGoodCounter, long msBetweenOutputs) { super(); this.choiceManager = choiceManager; this.assignment = assignment; this.noGoodCounter = noGoodCounter; - this.statTrackers = statTrackers; this.msBetweenOutputs = msBetweenOutputs; } @@ -70,18 +65,13 @@ public void writeIfTimeForLogging(Logger logger) { long currentTime = System.currentTimeMillis(); int currentNumberOfChoices = choiceManager.getChoices(); if (currentTime >= timeLastPerformanceLog + msBetweenOutputs) { - logger.info("Decisions in {}s: {}", (currentTime - timeLastPerformanceLog) / 1000.0f, currentNumberOfChoices - numberOfChoicesLastPerformanceLog); + logger.debug("Decisions in {}s: {}", (currentTime - timeLastPerformanceLog) / 1000.0f, currentNumberOfChoices - numberOfChoicesLastPerformanceLog); timeLastPerformanceLog = currentTime; numberOfChoicesLastPerformanceLog = currentNumberOfChoices; float overallTime = (currentTime - timeFirstEntry) / 1000.0f; float decisionsPerSec = currentNumberOfChoices / overallTime; - logger.info("Overall performance: {} decisions in {}s or {} decisions per sec. Overall replayed assignments: {}.", currentNumberOfChoices, overallTime, decisionsPerSec, assignment.replayCounter); - logger.info("Current nogood counts: {}", noGoodCounter.getStatsByType()); - if (statTrackers != null) { - for (StatTracker statTracker : statTrackers) { - logger.info("Tracked [{}]: {}", statTracker.getStatName(), String.format("%f", statTracker.getStatValue())); - } - } + logger.debug("Overall performance: {} decisions in {}s or {} decisions per sec. Overall replayed assignments: {}.", currentNumberOfChoices, overallTime, decisionsPerSec, assignment.replayCounter); + logger.debug("Current nogood counts: {}", noGoodCounter.getStatsByType()); } } } \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java index ec19a3566..c9d7433f9 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/RebootManager.java @@ -61,10 +61,6 @@ public void newEnumerationNoGood(NoGood noGood) { discoverRuleAtoms(noGood); } - public void newEnumerationNoGoods(Collection noGoods) { - noGoods.forEach(this::newEnumerationNoGood); - } - public void newLearnedNoGood(NoGood noGood) { if (!scanForAtomsToFilter(noGood)) { learnedNoGoods.add(noGood); @@ -87,8 +83,8 @@ public List getLearnedNoGoods() { } public List getDiscoveredRuleAtoms() { - LOGGER.info("Number of rule atoms: " + discoveredRuleAtoms.size()); - LOGGER.info("Number of filtered out nogoods: " + filteredCounter); + LOGGER.debug("Number of rule atoms: " + discoveredRuleAtoms.size()); + LOGGER.debug("Number of filtered out nogoods: " + filteredCounter); return discoveredRuleAtoms; } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java deleted file mode 100644 index 04f8fc41a..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/LearnedNoGoodTracker.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -import at.ac.tuwien.kr.alpha.core.solver.NoGoodCounter; - -public class LearnedNoGoodTracker implements StatTracker { - private final NoGoodCounter nogoodCounter; - - public LearnedNoGoodTracker(NoGoodCounter nogoodCounter) { - this.nogoodCounter = nogoodCounter; - } - - @Override - public String getStatName() { - return "_learned_nogoods"; - } - - @Override - public double getStatValue() { - return extractStaticCount(nogoodCounter.getStatsByType()); - } - - private int extractStaticCount(String countStr) { - String[] parts = countStr.split(" "); - for (int i = 0; i < parts.length; i++) { - if (parts[i].equals("LEARNT:") && i + 1 < parts.length) { - return Integer.parseInt(parts[i + 1]); - } - } - return 0; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java deleted file mode 100644 index 55e0cf46d..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/PropagationStatManager.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -import java.util.ArrayList; -import java.util.List; - -public class PropagationStatManager { - private final SimpleCountingTracker propagationTracker; - private final SimpleCountingTracker propagationConflictTracker; - private final SimpleCountingTracker nonbinPropagationTracker; - private final SimpleCountingTracker nonbinPropagationConflictTracker; - - public PropagationStatManager() { - this.propagationTracker = new SimpleCountingTracker("prop_count"); - this.propagationConflictTracker = new SimpleCountingTracker("prop_conflicts"); - this.nonbinPropagationTracker = new SimpleCountingTracker("nonbin_prop_count"); - this.nonbinPropagationConflictTracker = new SimpleCountingTracker("nonbin_prop_conflicts"); - } - - public ResettableStatTracker getPropagationTracker() { - return propagationTracker; - } - - public ResettableStatTracker getPropagationConflictTracker() { - return propagationConflictTracker; - } - - public ResettableStatTracker getNonbinPropagationTracker() { - return nonbinPropagationTracker; - } - - public ResettableStatTracker getNonbinPropagationConflictTracker() { - return nonbinPropagationConflictTracker; - } - - public List getStatTrackerList() { - List statTrackers = new ArrayList<>(); - statTrackers.add(propagationTracker); - statTrackers.add(propagationConflictTracker); - statTrackers.add(nonbinPropagationTracker); - statTrackers.add(nonbinPropagationConflictTracker); - return statTrackers; - } - - public void handleBinaryConflict() { - propagationTracker.increment(); - propagationConflictTracker.increment(); - } - - public void handleNonBinaryConflict() { - propagationTracker.increment(); - nonbinPropagationTracker.increment(); - propagationConflictTracker.increment(); - nonbinPropagationConflictTracker.increment(); - } - - public void handleNoConflict() { - propagationTracker.increment(); - nonbinPropagationTracker.increment(); - } - - public void reset() { - propagationTracker.reset(); - propagationConflictTracker.reset(); - nonbinPropagationTracker.reset(); - nonbinPropagationConflictTracker.reset(); - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java deleted file mode 100644 index 670f83fa2..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/QuotientTracker.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -public class QuotientTracker implements StatTracker { - private final String name; - private final StatTracker numerator; - private final StatTracker denominator; - - public QuotientTracker(String name, StatTracker numerator, StatTracker denominator) { - this.name = name; - this.numerator = numerator; - this.denominator = denominator; - } - - @Override - public String getStatName() { - return name; - } - - @Override - public double getStatValue() { - if (denominator.getStatValue() == 0) { - return 0; - } - return numerator.getStatValue() / denominator.getStatValue(); - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java deleted file mode 100644 index cf70a9341..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableQuotientTracker.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -public class ResettableQuotientTracker implements ResettableStatTracker { - private final String name; - private final ResettableStatTracker numerator; - private final ResettableStatTracker denominator; - - public ResettableQuotientTracker(String name, ResettableStatTracker numerator, ResettableStatTracker denominator) { - this.name = name; - this.numerator = numerator; - this.denominator = denominator; - } - - @Override - public String getStatName() { - return name; - } - - @Override - public double getStatValue() { - if (denominator.getStatValue() == 0) { - return 0; - } - return numerator.getStatValue() / denominator.getStatValue(); - } - - @Override - public void reset() { - numerator.reset(); - denominator.reset(); - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java deleted file mode 100644 index a3fe41a65..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/ResettableStatTracker.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -public interface ResettableStatTracker extends StatTracker { - void reset(); -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java deleted file mode 100644 index 90f09fa74..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/SimpleCountingTracker.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -public class SimpleCountingTracker implements ResettableStatTracker { - private final String name; - private int count; - - public SimpleCountingTracker(String name) { - this.name = name; - this.count = 0; - } - - public void increment() { - count++; - } - - public void incrementBy(int i) { - if (i >= 0) { - count += i; - } - } - - public void reset() { - count = 0; - } - - @Override - public String getStatName() { - return name; - } - - @Override - public double getStatValue() { - return count; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java deleted file mode 100644 index 139b5654c..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StatTracker.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -public interface StatTracker { - String getStatName(); - double getStatValue(); -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java deleted file mode 100644 index 818184c65..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StaticNoGoodTracker.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -import at.ac.tuwien.kr.alpha.core.solver.NoGoodCounter; - -public class StaticNoGoodTracker implements StatTracker { - private final NoGoodCounter nogoodCounter; - - public StaticNoGoodTracker(NoGoodCounter nogoodCounter) { - this.nogoodCounter = nogoodCounter; - } - - @Override - public String getStatName() { - return "_static_nogoods"; - } - - @Override - public double getStatValue() { - return extractStaticCount(nogoodCounter.getStatsByType()); - } - - private int extractStaticCount(String countStr) { - String[] parts = countStr.split(" "); - for (int i = 0; i < parts.length; i++) { - if (parts[i].equals("STATIC:") && i + 1 < parts.length) { - return Integer.parseInt(parts[i + 1]); - } - } - return 0; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java deleted file mode 100644 index 282d68aab..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/StopWatchTracker.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -import at.ac.tuwien.kr.alpha.core.util.StopWatch; - -public class StopWatchTracker implements ResettableStatTracker { - private final String name; - private final StopWatch stopWatch; - - public StopWatchTracker(String name, StopWatch stopWatch) { - this.name = name; - this.stopWatch = stopWatch; - } - - @Override - public String getStatName() { - return name; - } - - @Override - public double getStatValue() { - return stopWatch.getTime(); - } - - @Override - public void reset() { - stopWatch.reset(); - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java deleted file mode 100644 index 48d0df571..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/stats/TotalNoGoodTracker.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.stats; - -import at.ac.tuwien.kr.alpha.core.solver.NoGoodCounter; - -public class TotalNoGoodTracker implements StatTracker { - private final NoGoodCounter nogoodCounter; - - public TotalNoGoodTracker(NoGoodCounter nogoodCounter) { - this.nogoodCounter = nogoodCounter; - } - - @Override - public String getStatName() { - return "_total_nogoods"; - } - - @Override - public double getStatValue() { - return extractTotalCount(nogoodCounter.getStatsByType()); - } - - private int extractTotalCount(String countStr) { - int count = 0; - String[] parts = countStr.split(" "); - for (int i = 1; i < parts.length; i += 2) { - count += Integer.parseInt(parts[i]); - } - return count; - } -} \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java deleted file mode 100644 index e2ab0f06d..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/DynamicLearnedIntervalRebootStrategy.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; - -import at.ac.tuwien.kr.alpha.core.common.NoGood; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.ResettableStatTracker; -import at.ac.tuwien.kr.alpha.core.solver.reboot.stats.StatTracker; -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DynamicLearnedIntervalRebootStrategy implements RebootStrategy { - private static final Logger LOGGER = LoggerFactory.getLogger(DynamicLearnedIntervalRebootStrategy.class); - - private final ResettableStatTracker efficiencyMeasure; - private final StatTracker intervalSizeTracker; - private final int minInterval; - private final double scalingFactor; - private double intervalSize; - private double nextIntervalSize; - private int learnedCount; - private double previousIntervalMeasure; - private boolean isFirstInterval; - private boolean wasHalfPointHandled; - - public DynamicLearnedIntervalRebootStrategy(ResettableStatTracker efficiencyMeasure, - double scalingFactor, - int minInterval, int startInterval) { - this.efficiencyMeasure = efficiencyMeasure; - this.intervalSizeTracker = new StatTracker() { - @Override - public String getStatName() { - return "interval_size"; - } - - @Override - public double getStatValue() { - return intervalSize; - } - }; - this.scalingFactor = scalingFactor; - this.minInterval = minInterval; - this.intervalSize = startInterval; - this.learnedCount = 0; - this.previousIntervalMeasure = 0; - this.isFirstInterval = true; - this.wasHalfPointHandled = false; - } - - public StatTracker getIntervalSizeTracker() { - return intervalSizeTracker; - } - - @Override - public void newLearnedNoGood(NoGood noGood) { - learnedCount++; - handleHalfPointIfNeeded(); - } - - @Override - public boolean isRebootScheduled() { - return learnedCount >= (int) intervalSize; - } - - @Override - public void rebootPerformed() { - previousIntervalMeasure = efficiencyMeasure.getStatValue(); - intervalSize = nextIntervalSize; - - efficiencyMeasure.reset(); - learnedCount = 0; - wasHalfPointHandled = false; - } - - private double getNewIntervalSize(double currentIntervalMeasure) { - double oldIntervalSize = intervalSize; - - if (isFirstInterval) { - isFirstInterval = false; - return intervalSize; - } else if (currentIntervalMeasure > previousIntervalMeasure) { - double newIntervalSize = downscaleIntervalSize(intervalSize); - LOGGER.info("Reboot interval size: {} -> {}", oldIntervalSize, newIntervalSize); - LOGGER.info("Interval measures were: {} < {}", previousIntervalMeasure, currentIntervalMeasure); - return Math.max(newIntervalSize, minInterval); - } else { - double newIntervalSize = upscaleIntervalSize(intervalSize); - LOGGER.info("Reboot interval size: {} -> {}", oldIntervalSize, newIntervalSize); - LOGGER.info("Interval measures were: {} >= {}", previousIntervalMeasure, currentIntervalMeasure); - return Math.max(newIntervalSize, minInterval); - } - } - - private double downscaleIntervalSize(double intervalSize) { - return intervalSize * scalingFactor; - } - - private double upscaleIntervalSize(double intervalSize) { - return intervalSize / (scalingFactor * scalingFactor); - } - - private boolean isHalfPointReached() { - return learnedCount >= (int) (intervalSize / 2); - } - - private void handleHalfPoint() { - double currentIntervalMeasure = efficiencyMeasure.getStatValue(); - nextIntervalSize = getNewIntervalSize(currentIntervalMeasure); - - efficiencyMeasure.reset(); - wasHalfPointHandled = true; - } - - private void handleHalfPointIfNeeded() { - if (!wasHalfPointHandled && isHalfPointReached()) { - handleHalfPoint(); - } - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java deleted file mode 100644 index 74af2b63e..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedConflictRebootStrategy.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; - -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; - -public class FixedConflictRebootStrategy implements RebootStrategy { - private final int breakpoint; - private int conflictCount; - - public FixedConflictRebootStrategy(int breakpoint) { - this.breakpoint = breakpoint; - this.conflictCount = 0; - } - - @Override - public void conflictEncountered() { - conflictCount++; - } - - @Override - public boolean isRebootScheduled() { - return conflictCount >= breakpoint; - } - - @Override - public void rebootPerformed() { - conflictCount = 0; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java deleted file mode 100644 index 6ba71f73c..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedDecisionRebootStrategy.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; - -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; - -public class FixedDecisionRebootStrategy implements RebootStrategy { - private final int breakpoint; - private int decisionCount; - - public FixedDecisionRebootStrategy(int breakpoint) { - this.breakpoint = breakpoint; - this.decisionCount = 0; - } - - @Override - public void decisionMade() { - decisionCount++; - } - - @Override - public boolean isRebootScheduled() { - return decisionCount >= breakpoint; - } - - @Override - public void rebootPerformed() { - decisionCount = 0; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java deleted file mode 100644 index 393e8f78c..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/FixedIterationRebootStrategy.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; - -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; - -public class FixedIterationRebootStrategy implements RebootStrategy { - private final int breakpoint; - private int iterationCount; - - public FixedIterationRebootStrategy(int breakpoint) { - this.breakpoint = breakpoint; - this.iterationCount = 0; - } - - @Override - public void nextIteration() { - iterationCount++; - } - - @Override - public boolean isRebootScheduled() { - return iterationCount >= breakpoint; - } - - @Override - public void rebootPerformed() { - iterationCount = 0; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java deleted file mode 100644 index 73ec9debf..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/GeometricConflictRebootStrategy.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; - -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; - -public class GeometricConflictRebootStrategy implements RebootStrategy { - private static final double BASE = 1.5; - private static final double SCALING_FACTOR = 2; - - private int rebootCount; - private int conflictCount; - @Override - public void conflictEncountered() { - conflictCount++; - } - - @Override - public boolean isRebootScheduled() { - return conflictCount >= SCALING_FACTOR * Math.pow(BASE, rebootCount); - } - - @Override - public void rebootPerformed() { - rebootCount++; - conflictCount = 0; - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java deleted file mode 100644 index 4418f32c4..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/old/LubyConflictRebootStrategy.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.old; - -import at.ac.tuwien.kr.alpha.core.solver.reboot.strategies.RebootStrategy; - -public class LubyConflictRebootStrategy implements RebootStrategy { - private static final double SCALING_FACTOR = 10; - - private int rebootCount; - private int conflictCount; - - @Override - public void conflictEncountered() { - conflictCount++; - } - - @Override - public boolean isRebootScheduled() { - return conflictCount >= SCALING_FACTOR * luby(rebootCount + 1); - } - - @Override - public void rebootPerformed() { - rebootCount++; - } - - private double luby(double i) { - for (int k = 1; k < 31; k++) { - if (i == (Math.pow(2, k)) - 1) { - return Math.pow(2, k - 1); - } - } - for (int k = 1;; k++) { - if (Math.pow(2, k - 1) <= i && i < Math.pow(2, k) - 1) { - return luby(i - Math.pow(2, k - 1) + 1); - } - } - } -} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java deleted file mode 100644 index 240d1d701..000000000 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/StopWatch.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2022, the Alpha Team. - * All rights reserved. - *

- * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - *

- * 1) Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - *

- * 2) Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - *

- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package at.ac.tuwien.kr.alpha.core.util; - -public class StopWatch { - private long startTime; - private long nanoTime; - private boolean running; - - /** - * Starts the {@link StopWatch}. If it is already running, this function does nothing. - */ - public void start() { - if (!running) { - startTime = System.nanoTime(); - running = true; - } - } - - /** - * Stops the {@link StopWatch}. If it is not running, this function does nothing. - */ - public void stop() { - if (running) { - long currentTime = System.nanoTime(); - nanoTime += currentTime - startTime; - running = false; - } - } - - /** - * Returns the time in nanoseconds the {@link StopWatch} has been running in total. - * @return the total running time of the {@link StopWatch} in nanoseconds. - */ - public long getNanoTime() { - long currentNanos = running ? System.nanoTime() - startTime : 0; - return nanoTime + currentNanos; - } - - /** - * Returns the time in milliseconds the {@link StopWatch} has been running in total. - * @return the total running time of the {@link StopWatch} in milliseconds. - */ - public double getMilliTime() { - return (long)(getNanoTime() / 1e6); - } - - /** - * Returns the time in seconds the {@link StopWatch} has been running in total. - * @return the total running time of the {@link StopWatch} in seconds. - */ - public double getTime() { - return getNanoTime() / 1e9; - } - - /** - * Resets the {@link StopWatch} but keeps it running if it was running before. - */ - public void reset() { - nanoTime = 0; - startTime = System.nanoTime(); - } -} From 8f2d6a34a7808eead2d70b49a33cc9a7ba6ab899 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 18 Jul 2023 18:51:57 +0200 Subject: [PATCH 47/53] Add reboot strategy parameters to tests --- .../core/solver/RegressionTestConfig.java | 27 +++++++----- .../solver/RegressionTestConfigProvider.java | 42 ++++++++++++------- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index 3959dcc39..abf2fa2e4 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -18,6 +18,8 @@ public class RegressionTestConfig { private final boolean disableRebootRepeat; private final RebootStrategy rebootStrategy; private final int rebootStrategyInterval; + private final double rebootStrategyBase; + private final double rebootStrategyFactor; private final long seed; @@ -32,13 +34,14 @@ public class RegressionTestConfig { private final boolean evaluateStratifiedPart; private final boolean encodeAggregatesUsingSortingGrid; - + private final boolean supportNegativeSumElements; public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, Heuristic branchingHeuristic, - boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategy rebootStrategy, int rebootStrategyInterval, - long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, + boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategy rebootStrategy, + int rebootStrategyInterval, double rebootStrategyBase, double rebootStrategyFactor, long seed, + boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { this.solverName = solverName; @@ -49,6 +52,8 @@ public RegressionTestConfig( this.disableRebootRepeat = disableRebootRepeat; this.rebootStrategy = rebootStrategy; this.rebootStrategyInterval = rebootStrategyInterval; + this.rebootStrategyBase = rebootStrategyBase; + this.rebootStrategyFactor = rebootStrategyFactor; this.seed = seed; this.debugChecks = debugChecks; this.grounderToleranceConstraints = grounderToleranceConstraints; @@ -130,17 +135,19 @@ public boolean isEncodeAggregatesUsingSortingGrid() { public boolean isSupportNegativeSumElements() { return this.supportNegativeSumElements; } - + @Override public String toString() { return String.format( "RegressionTestConfig [solverName=%s, grounderName=%s, noGoodStoreName=%s, branchingHeuristic=%s," - + " rebootEnabled=%b, disableRebootRepeat=%b, rebootStrategy=%s, rebootStrategyInterval=%d, seed=%s," - + " debugChecks=%s, grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s," - + " evaluateStratifiedPart=%s, useSortingGrid=%s, supportNegativeSumElements=%s]", + + " rebootEnabled=%b, disableRebootRepeat=%b, rebootStrategy=%s, rebootStrategyInterval=%d," + + " rebootStrategyBase=%f, rebootStrategyFactor=%f, seed=%s, debugChecks=%s," + + " grounderToleranceConstraints=%s, grounderToleranceRules=%s, disableInstanceRemoval=%s," + + " evaluateStratifiedPart=%s, useSortingGrid=%s, supportNegativeSumElements=%s]", this.solverName, this.grounderName, this.noGoodStoreName, this.branchingHeuristic, this.rebootEnabled, - this.disableRebootRepeat, this.rebootStrategy, this.rebootStrategyInterval, this.seed, this.debugChecks, - this.grounderToleranceConstraints, this.grounderToleranceRules, this.disableInstanceRemoval, - this.evaluateStratifiedPart, this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); + this.disableRebootRepeat, this.rebootStrategy, this.rebootStrategyInterval, this.rebootStrategyBase, + this.rebootStrategyFactor, this.seed, this.debugChecks, this.grounderToleranceConstraints, + this.grounderToleranceRules, this.disableInstanceRemoval, this.evaluateStratifiedPart, + this.encodeAggregatesUsingSortingGrid, this.supportNegativeSumElements); } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index 2d4a8e615..213b61596 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -20,6 +20,8 @@ public class RegressionTestConfigProvider { private static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = true; private static final RebootStrategy DEFAULT_REBOOT_STRATEGY = RebootStrategy.FIXED; private static final int DEFAULT_REBOOT_STRATEGY_ITERATIONS = 5; + private static final double DEFAULT_REBOOT_STRATEGY_BASE = 5; + private static final double DEFAULT_REBOOT_STRATEGY_FACTOR = 2; private static final String DEFAULT_GROUNDER_TOLERANCE = "strict"; private static final boolean DEFAULT_DISABLE_INSTANCE_REMOVAL = false; private static final boolean DEFAULT_ENABLE_DEBUG_CHECKS = false; @@ -42,8 +44,13 @@ private static List buildConfigs() { String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive"} : new String[]{DEFAULT_ATOM_STORE}; String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC}; boolean[] rebootEnabledValues = new boolean[]{DEFAULT_REBOOT_ENABLED, true}; - RebootStrategy[] rebootStrategyValues = new RebootStrategy[]{DEFAULT_REBOOT_STRATEGY}; + RebootStrategy[] rebootStrategyValues = ci ? new RebootStrategy[]{ + RebootStrategy.FIXED, RebootStrategy.ANSWER, RebootStrategy.ASSIGN, + RebootStrategy.GEOM, RebootStrategy.LUBY + } : new RebootStrategy[]{DEFAULT_REBOOT_STRATEGY}; int[] rebootStrategyIterationsValues = new int[]{DEFAULT_REBOOT_STRATEGY_ITERATIONS}; + double[] rebootStrategyBaseValues = new double[]{DEFAULT_REBOOT_STRATEGY_BASE}; + double[] rebootStrategyFactorValues = new double[]{DEFAULT_REBOOT_STRATEGY_FACTOR}; boolean[] disableRebootRepeatValues = new boolean[]{DEFAULT_DISABLE_REBOOT_REPEAT}; String[] gtcValues = new String[]{DEFAULT_GROUNDER_TOLERANCE, "permissive"}; String gtrValue = DEFAULT_GROUNDER_TOLERANCE; @@ -69,18 +76,22 @@ private static List buildConfigs() { for (boolean disableRebootRepeat : disableRebootRepeatValues) { for (RebootStrategy rebootStrategy : rebootStrategyValues) { for (int rebootIterations : rebootStrategyIterationsValues) { - for (String grounderTolerance : gtcValues) { - for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { - for (boolean evaluateStratified : evaluateStratifiedValues) { - for (boolean enableDebugChecks : enableDebugChecksValues) { - configsToTest.add(new RegressionTestConfig( - solverName, grounder, atomStoreName, - Heuristic.valueOf(branchingHeuristicName), - rebootEnabled, disableRebootRepeat, rebootStrategy, - rebootIterations, seed, enableDebugChecks, - grounderTolerance, gtrValue, - disableInstanceRemoval, evaluateStratified, - true, true)); + for (double rebootStrategyBase : rebootStrategyBaseValues) { + for (double rebootStrategyFactor : rebootStrategyFactorValues) { + for (String grounderTolerance : gtcValues) { + for (boolean disableInstanceRemoval : disableInstanceRemovalValues) { + for (boolean evaluateStratified : evaluateStratifiedValues) { + for (boolean enableDebugChecks : enableDebugChecksValues) { + configsToTest.add(new RegressionTestConfig( + solverName, grounder, atomStoreName, + Heuristic.valueOf(branchingHeuristicName), + rebootEnabled, disableRebootRepeat, rebootStrategy, + rebootIterations, rebootStrategyBase, rebootStrategyFactor, + seed, enableDebugChecks, grounderTolerance, gtrValue, + disableInstanceRemoval, evaluateStratified, + true, true)); + } + } } } } @@ -117,8 +128,9 @@ private static List buildConfigsForAggregateTests() { new RegressionTestConfig( DEFAULT_SOLVER_NAME, DEFAULT_GROUNDER_NAME, DEFAULT_ATOM_STORE, Heuristic.valueOf(DEFAULT_BRANCHING_HEURISTIC), - DEFAULT_REBOOT_ENABLED, DEFAULT_DISABLE_REBOOT_REPEAT, DEFAULT_REBOOT_STRATEGY, - DEFAULT_REBOOT_STRATEGY_ITERATIONS, 0, DEFAULT_ENABLE_DEBUG_CHECKS, + DEFAULT_REBOOT_ENABLED, DEFAULT_DISABLE_REBOOT_REPEAT, DEFAULT_REBOOT_STRATEGY, + DEFAULT_REBOOT_STRATEGY_ITERATIONS, DEFAULT_REBOOT_STRATEGY_BASE, + DEFAULT_REBOOT_STRATEGY_FACTOR, 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, evalStratified, useSortingGrid, supportNegativeElements)); From 4a51d9e8971d9306169d4e07ac7b9f7da6495bba Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Tue, 18 Jul 2023 23:47:48 +0200 Subject: [PATCH 48/53] Remove obsolete test configurations --- .../kr/alpha/core/solver/RegressionTestConfigProvider.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index 213b61596..23999d9ec 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -44,10 +44,7 @@ private static List buildConfigs() { String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive"} : new String[]{DEFAULT_ATOM_STORE}; String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC}; boolean[] rebootEnabledValues = new boolean[]{DEFAULT_REBOOT_ENABLED, true}; - RebootStrategy[] rebootStrategyValues = ci ? new RebootStrategy[]{ - RebootStrategy.FIXED, RebootStrategy.ANSWER, RebootStrategy.ASSIGN, - RebootStrategy.GEOM, RebootStrategy.LUBY - } : new RebootStrategy[]{DEFAULT_REBOOT_STRATEGY}; + RebootStrategy[] rebootStrategyValues = new RebootStrategy[]{DEFAULT_REBOOT_STRATEGY}; int[] rebootStrategyIterationsValues = new int[]{DEFAULT_REBOOT_STRATEGY_ITERATIONS}; double[] rebootStrategyBaseValues = new double[]{DEFAULT_REBOOT_STRATEGY_BASE}; double[] rebootStrategyFactorValues = new double[]{DEFAULT_REBOOT_STRATEGY_FACTOR}; From 74817582245429baabc7b892afcf270b87e0cb38 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Thu, 20 Jul 2023 12:28:53 +0200 Subject: [PATCH 49/53] Reduce nesting depth --- .../kr/alpha/core/solver/DefaultSolver.java | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 364d43381..43cc71513 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -168,9 +168,7 @@ protected boolean tryAdvance(Consumer action) { } else if (rebootEnabled && rebootStrategy.isRebootScheduled()) { reboot(); rebootStrategy.rebootPerformed(); - if (disableRebootRepeat) { - rebootEnabled = false; - } + disableRebootIfNoRepeat(); } else if (choose()) { LOGGER.debug("Did choice."); rebootStrategy.decisionMade(); @@ -606,7 +604,7 @@ private Stack getAtomizedChoiceStack() { /** * Converts the given choice stack into one containing atom ids instead of atoms and applies - * the choices on the resulting stack using the choice manager. + * the choices to the resulting choice stack using the {@link DefaultSolver#choiceManager}. * Propagation is performed initially and after each choice. * @param atomizedChoiceStack the stack of choices containing atoms. */ @@ -622,22 +620,31 @@ private void replayAtomizedChoiceStack(Stack atomizedChoiceStack growForMaxAtomId(); for (AtomizedChoice atomizedChoice : atomizedChoiceStack) { - Atom atom = atomizedChoice.getAtom(); - int atomId = atomStore.get(atom); - Choice choice = new Choice(atomId, atomizedChoice.getTruthValue(), atomizedChoice.isBacktracked()); + replayAtomizedChoice(atomizedChoice); + } + } - choiceManager.addChoiceInformation(grounder.getChoiceAtoms(), grounder.getHeadsToBodies()); - choiceManager.updateAssignments(); - boolean activeChoice = choiceManager.replayChoice(choice); + /** + * Applies a given {@link AtomizedChoice} to the current choice stack using the {@link DefaultSolver#choiceManager}. + * Propagation and grounding are performed after the choice. + * @param atomizedChoice the choice to apply. + */ + private void replayAtomizedChoice(AtomizedChoice atomizedChoice) { + Atom atom = atomizedChoice.getAtom(); + int atomId = atomStore.get(atom); + Choice choice = new Choice(atomId, atomizedChoice.getTruthValue(), atomizedChoice.isBacktracked()); - if (activeChoice) { - if (propagate() != null) { - throw oops("Conflict in replay during reboot"); - } - syncWithGrounder(); - if (propagate() != null) { - throw oops("Conflict in replay during reboot"); - } + choiceManager.addChoiceInformation(grounder.getChoiceAtoms(), grounder.getHeadsToBodies()); + choiceManager.updateAssignments(); + boolean activeChoice = choiceManager.replayChoice(choice); + + if (activeChoice) { + if (propagate() != null) { + throw oops("Conflict in replay during reboot"); + } + syncWithGrounder(); + if (propagate() != null) { + throw oops("Conflict in replay during reboot"); } } } @@ -691,6 +698,12 @@ private void ingestNoGoodsFromRulesOfRuleAtoms(List ruleAtoms) { } } + private void disableRebootIfNoRepeat() { + if (disableRebootRepeat) { + rebootEnabled = false; + } + } + @Override public int getNumberOfChoices() { return choiceManager.getChoices(); From dbaab675dc3485658ca0fa53d2cf7b1c943a7efd Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sun, 23 Jul 2023 17:12:26 +0200 Subject: [PATCH 50/53] Add reboot strategy tests --- ...tStrategy.java => RebootStrategyEnum.java} | 4 +- .../kr/alpha/api/config/SystemConfig.java | 10 +- .../alpha/app/config/CommandLineParser.java | 2 +- .../strategies/LubyLearnedRebootStrategy.java | 1 + .../reboot/strategies/RebootStrategy.java | 2 +- .../core/solver/RegressionTestConfig.java | 6 +- .../solver/RegressionTestConfigProvider.java | 8 +- .../AnswerSetRebootStrategyTest.java | 67 +++++++++ .../CompleteAssignmentRebootStrategyTest.java | 64 +++++++++ .../FixedLearnedRebootStrategyTest.java | 117 +++++++++++++++ .../GeometricLearnedRebootStrategyTest.java | 133 ++++++++++++++++++ .../LubyLearnedRebootStrategyTest.java | 131 +++++++++++++++++ 12 files changed, 529 insertions(+), 16 deletions(-) rename alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/{RebootStrategy.java => RebootStrategyEnum.java} (70%) create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategyTest.java create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategyTest.java create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategyTest.java create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategyTest.java create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategyTest.java diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategyEnum.java similarity index 70% rename from alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategyEnum.java index 19c5b09e1..483925416 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategy.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/RebootStrategyEnum.java @@ -6,7 +6,7 @@ /** * The available reboot strategies. */ -public enum RebootStrategy { +public enum RebootStrategyEnum { FIXED, GEOM, LUBY, @@ -17,6 +17,6 @@ public enum RebootStrategy { * @return a comma-separated list of names of known reboot strategies */ public static String listAllowedValues() { - return Arrays.stream(values()).map(RebootStrategy::toString).collect(Collectors.joining(", ")); + return Arrays.stream(values()).map(RebootStrategyEnum::toString).collect(Collectors.joining(", ")); } } diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index 2ef40dfe7..2b54c84c9 100644 --- a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -51,7 +51,7 @@ public class SystemConfig { public static final BinaryNoGoodPropagationEstimationStrategy DEFAULT_MOMS_STRATEGY = BinaryNoGoodPropagationEstimationStrategy.CountBinaryWatches; public static final boolean DEFAULT_REBOOT_ENABLED = false; public static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = false; - public static final RebootStrategy DEFAULT_REBOOT_STRATEGY = RebootStrategy.ANSWER; + public static final RebootStrategyEnum DEFAULT_REBOOT_STRATEGY = RebootStrategyEnum.ANSWER; public static final int DEFAULT_REBOOT_STRATEGY_INTERVAL = 10000; public static final double DEFAULT_REBOOT_STRATEGY_BASE = 1.5; public static final double DEFAULT_REBOOT_STRATEGY_FACTOR = 2; @@ -81,7 +81,7 @@ public class SystemConfig { private BinaryNoGoodPropagationEstimationStrategy momsStrategy = DEFAULT_MOMS_STRATEGY; private boolean rebootEnabled = DEFAULT_REBOOT_ENABLED; private boolean disableRebootRepeat = DEFAULT_DISABLE_REBOOT_REPEAT; - private RebootStrategy rebootStrategy = DEFAULT_REBOOT_STRATEGY; + private RebootStrategyEnum rebootStrategy = DEFAULT_REBOOT_STRATEGY; private int rebootStrategyInterval = DEFAULT_REBOOT_STRATEGY_INTERVAL; private double rebootStrategyBase = DEFAULT_REBOOT_STRATEGY_BASE; private double rebootStrategyFactor = DEFAULT_REBOOT_STRATEGY_FACTOR; @@ -147,16 +147,16 @@ public void setDisableRebootRepeat(boolean disableRebootRepeat) { this.disableRebootRepeat = disableRebootRepeat; } - public RebootStrategy getRebootStrategy() { + public RebootStrategyEnum getRebootStrategy() { return this.rebootStrategy; } - public void setRebootStrategy(RebootStrategy rebootStrategy) { + public void setRebootStrategy(RebootStrategyEnum rebootStrategy) { this.rebootStrategy = rebootStrategy; } public void setRebootStrategyName(String rebootStrategyName) { - this.rebootStrategy = RebootStrategy.valueOf(rebootStrategyName.replace("-", "_").toUpperCase()); + this.rebootStrategy = RebootStrategyEnum.valueOf(rebootStrategyName.replace("-", "_").toUpperCase()); } public int getRebootStrategyInterval() { diff --git a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 21a94c986..7d7cad2d0 100644 --- a/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -388,7 +388,7 @@ private void handleRebootStrategy(Option opt, SystemConfig cfg) throws ParseExce cfg.setRebootStrategyName(rebootStrategyName); } catch (IllegalArgumentException e) { throw new ParseException( - "Unknown reboot strategy: " + rebootStrategyName + ". Please try one of the following: " + RebootStrategy.listAllowedValues()); + "Unknown reboot strategy: " + rebootStrategyName + ". Please try one of the following: " + RebootStrategyEnum.listAllowedValues()); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java index 7b12ee116..3b5b7177c 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategy.java @@ -54,6 +54,7 @@ public boolean isRebootScheduled() { @Override public void rebootPerformed() { rebootCount++; + learnedCount = 0; } private double luby(double i) { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java index 43c305e2e..9bed67fe5 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/RebootStrategy.java @@ -48,7 +48,7 @@ default void backtrackJustified() { default void newEnumerationNoGood(NoGood noGood) { } - default void newJustificationNoGood(NoGood justification) { + default void newJustificationNoGood(NoGood noGood) { } default void newNoGood(NoGood noGood) { diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index abf2fa2e4..c535c8dab 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java @@ -1,7 +1,7 @@ package at.ac.tuwien.kr.alpha.core.solver; import at.ac.tuwien.kr.alpha.api.config.Heuristic; -import at.ac.tuwien.kr.alpha.api.config.RebootStrategy; +import at.ac.tuwien.kr.alpha.api.config.RebootStrategyEnum; import at.ac.tuwien.kr.alpha.api.config.SystemConfig; public class RegressionTestConfig { @@ -16,7 +16,7 @@ public class RegressionTestConfig { private final boolean rebootEnabled; private final boolean disableRebootRepeat; - private final RebootStrategy rebootStrategy; + private final RebootStrategyEnum rebootStrategy; private final int rebootStrategyInterval; private final double rebootStrategyBase; private final double rebootStrategyFactor; @@ -39,7 +39,7 @@ public class RegressionTestConfig { public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, Heuristic branchingHeuristic, - boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategy rebootStrategy, + boolean rebootEnabled, boolean disableRebootRepeat, RebootStrategyEnum rebootStrategy, int rebootStrategyInterval, double rebootStrategyBase, double rebootStrategyFactor, long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index 23999d9ec..82ba7c2bd 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Random; -import at.ac.tuwien.kr.alpha.api.config.RebootStrategy; +import at.ac.tuwien.kr.alpha.api.config.RebootStrategyEnum; import org.junit.jupiter.params.provider.Arguments; import at.ac.tuwien.kr.alpha.api.config.Heuristic; @@ -18,7 +18,7 @@ public class RegressionTestConfigProvider { private static final String DEFAULT_BRANCHING_HEURISTIC = "VSIDS"; private static final boolean DEFAULT_REBOOT_ENABLED = false; private static final boolean DEFAULT_DISABLE_REBOOT_REPEAT = true; - private static final RebootStrategy DEFAULT_REBOOT_STRATEGY = RebootStrategy.FIXED; + private static final RebootStrategyEnum DEFAULT_REBOOT_STRATEGY = RebootStrategyEnum.ANSWER; private static final int DEFAULT_REBOOT_STRATEGY_ITERATIONS = 5; private static final double DEFAULT_REBOOT_STRATEGY_BASE = 5; private static final double DEFAULT_REBOOT_STRATEGY_FACTOR = 2; @@ -44,7 +44,7 @@ private static List buildConfigs() { String[] atomStores = ci ? new String[]{DEFAULT_ATOM_STORE, "naive"} : new String[]{DEFAULT_ATOM_STORE}; String[] heuristics = ci ? nonDeprecatedHeuristics() : new String[]{"NAIVE", DEFAULT_BRANCHING_HEURISTIC}; boolean[] rebootEnabledValues = new boolean[]{DEFAULT_REBOOT_ENABLED, true}; - RebootStrategy[] rebootStrategyValues = new RebootStrategy[]{DEFAULT_REBOOT_STRATEGY}; + RebootStrategyEnum[] rebootStrategyValues = new RebootStrategyEnum[]{DEFAULT_REBOOT_STRATEGY}; int[] rebootStrategyIterationsValues = new int[]{DEFAULT_REBOOT_STRATEGY_ITERATIONS}; double[] rebootStrategyBaseValues = new double[]{DEFAULT_REBOOT_STRATEGY_BASE}; double[] rebootStrategyFactorValues = new double[]{DEFAULT_REBOOT_STRATEGY_FACTOR}; @@ -71,7 +71,7 @@ private static List buildConfigs() { for (String branchingHeuristicName : heuristics) { for (boolean rebootEnabled : rebootEnabledValues) { for (boolean disableRebootRepeat : disableRebootRepeatValues) { - for (RebootStrategy rebootStrategy : rebootStrategyValues) { + for (RebootStrategyEnum rebootStrategy : rebootStrategyValues) { for (int rebootIterations : rebootStrategyIterationsValues) { for (double rebootStrategyBase : rebootStrategyBaseValues) { for (double rebootStrategyFactor : rebootStrategyFactorValues) { diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategyTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategyTest.java new file mode 100644 index 000000000..1402b762a --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/AnswerSetRebootStrategyTest.java @@ -0,0 +1,67 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class AnswerSetRebootStrategyTest { + @Test + public void testStrategySchedulesAfterAnswerSet() { + RebootStrategy strategy = new AnswerSetRebootStrategy(); + strategy.answerSetFound(); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyResetsAfterReboot() { + RebootStrategy strategy = new AnswerSetRebootStrategy(); + strategy.answerSetFound(); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleImmediately() { + RebootStrategy strategy = new AnswerSetRebootStrategy(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterIteration() { + RebootStrategy strategy = new AnswerSetRebootStrategy(); + strategy.nextIteration(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterUnrelatedEvents() { + RebootStrategy strategy = new AnswerSetRebootStrategy(); + + strategy.nextIteration(); + assertFalse(strategy.isRebootScheduled()); + + strategy.decisionMade(); + assertFalse(strategy.isRebootScheduled()); + + strategy.conflictEncountered(); + assertFalse(strategy.isRebootScheduled()); + + strategy.backtrackJustified(); + assertFalse(strategy.isRebootScheduled()); + + strategy.newNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + + strategy.newEnumerationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + + strategy.newJustificationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategyTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategyTest.java new file mode 100644 index 000000000..34a34aa77 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/CompleteAssignmentRebootStrategyTest.java @@ -0,0 +1,64 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CompleteAssignmentRebootStrategyTest { + @Test + public void testStrategySchedulesAfterAnswerSet() { + RebootStrategy strategy = new CompleteAssignmentRebootStrategy(); + strategy.answerSetFound(); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterJustification() { + RebootStrategy strategy = new CompleteAssignmentRebootStrategy(); + strategy.backtrackJustified(); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyResetsAfterReboot() { + RebootStrategy strategy = new CompleteAssignmentRebootStrategy(); + strategy.answerSetFound(); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNoScheduleImmediately() { + RebootStrategy strategy = new CompleteAssignmentRebootStrategy(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterUnrelatedEvents() { + RebootStrategy strategy = new CompleteAssignmentRebootStrategy(); + + strategy.nextIteration(); + assertFalse(strategy.isRebootScheduled()); + + strategy.decisionMade(); + assertFalse(strategy.isRebootScheduled()); + + strategy.conflictEncountered(); + assertFalse(strategy.isRebootScheduled()); + + strategy.newNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + + strategy.newEnumerationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + + strategy.newJustificationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategyTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategyTest.java new file mode 100644 index 000000000..d5e6af777 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/FixedLearnedRebootStrategyTest.java @@ -0,0 +1,117 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FixedLearnedRebootStrategyTest { + @Test + public void testStrategySchedulesAfterLearnedNogoods() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newLearnedNoGood(new NoGood()); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterEnumerationNogoods() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newEnumerationNoGood(new NoGood()); + strategy.newEnumerationNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterMixedNogoods() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newLearnedNoGood(new NoGood()); + strategy.newEnumerationNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterNogoodBundle() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + Collection noGoods = List.of(new NoGood(), new NoGood()); + strategy.newLearnedNoGoods(noGoods); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyResetsAfterReboot() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(1); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleImmediately() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterSmallerBundle() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(3); + Collection noGoods = List.of(new NoGood(), new NoGood()); + strategy.newLearnedNoGoods(noGoods); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterSingleEnumerationNogood() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newEnumerationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterStaticNogoods() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newNoGood(new NoGood()); + strategy.newNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterStaticNogoodBundle() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newNoGoods(List.of(new NoGood(), new NoGood())); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterJustificationNogoods() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(2); + strategy.newJustificationNoGood(new NoGood()); + strategy.newJustificationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterUnrelatedEvents() { + RebootStrategy strategy = new FixedLearnedRebootStrategy(1); + + strategy.nextIteration(); + assertFalse(strategy.isRebootScheduled()); + + strategy.decisionMade(); + assertFalse(strategy.isRebootScheduled()); + + strategy.conflictEncountered(); + assertFalse(strategy.isRebootScheduled()); + + strategy.backtrackJustified(); + assertFalse(strategy.isRebootScheduled()); + + strategy.answerSetFound(); + assertFalse(strategy.isRebootScheduled()); + } +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategyTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategyTest.java new file mode 100644 index 000000000..c04ad257c --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/GeometricLearnedRebootStrategyTest.java @@ -0,0 +1,133 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class GeometricLearnedRebootStrategyTest { + @Test + public void testStrategySchedulesAfterLearnedNogoods() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newLearnedNoGood(new NoGood()); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterEnumerationNogoods() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newEnumerationNoGood(new NoGood()); + strategy.newEnumerationNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterMixedNogoods() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newLearnedNoGood(new NoGood()); + strategy.newEnumerationNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesFirstThreeCorrectly() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 1); + + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyResetsAfterReboot() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 1); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleImmediately() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterSmallerBundle() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 3); + Collection noGoods = List.of(new NoGood(), new NoGood()); + strategy.newLearnedNoGoods(noGoods); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterSingleEnumerationNogood() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newEnumerationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterStaticNogoods() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newNoGood(new NoGood()); + strategy.newNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterStaticNogoodBundle() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newNoGoods(List.of(new NoGood(), new NoGood())); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterJustificationNogoods() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 2); + strategy.newJustificationNoGood(new NoGood()); + strategy.newJustificationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterUnrelatedEvents() { + RebootStrategy strategy = new GeometricLearnedRebootStrategy(2, 1); + + strategy.nextIteration(); + assertFalse(strategy.isRebootScheduled()); + + strategy.decisionMade(); + assertFalse(strategy.isRebootScheduled()); + + strategy.conflictEncountered(); + assertFalse(strategy.isRebootScheduled()); + + strategy.backtrackJustified(); + assertFalse(strategy.isRebootScheduled()); + + strategy.answerSetFound(); + assertFalse(strategy.isRebootScheduled()); + } +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategyTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategyTest.java new file mode 100644 index 000000000..1eff7c596 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/strategies/LubyLearnedRebootStrategyTest.java @@ -0,0 +1,131 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot.strategies; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import org.junit.jupiter.api.Test; + +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class LubyLearnedRebootStrategyTest { + @Test + public void testStrategySchedulesAfterLearnedNogoods() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newLearnedNoGood(new NoGood()); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterEnumerationNogoods() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newEnumerationNoGood(new NoGood()); + strategy.newEnumerationNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesAfterMixedNogoods() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newLearnedNoGood(new NoGood()); + strategy.newEnumerationNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategySchedulesFirstFourCorrectly() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(1); + + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + + strategy.newLearnedNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyResetsAfterReboot() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(1); + strategy.newLearnedNoGood(new NoGood()); + assertTrue(strategy.isRebootScheduled()); + strategy.rebootPerformed(); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleImmediately() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(1); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterSmallerBundle() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(3); + Collection noGoods = List.of(new NoGood(), new NoGood()); + strategy.newLearnedNoGoods(noGoods); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterSingleEnumerationNogood() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newEnumerationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterStaticNogoods() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newNoGood(new NoGood()); + strategy.newNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterStaticNogoodBundle() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newNoGoods(List.of(new NoGood(), new NoGood())); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterJustificationNogoods() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(2); + strategy.newJustificationNoGood(new NoGood()); + strategy.newJustificationNoGood(new NoGood()); + assertFalse(strategy.isRebootScheduled()); + } + + @Test + public void testStrategyDoesNotScheduleAfterUnrelatedEvents() { + RebootStrategy strategy = new LubyLearnedRebootStrategy(1); + + strategy.nextIteration(); + assertFalse(strategy.isRebootScheduled()); + + strategy.decisionMade(); + assertFalse(strategy.isRebootScheduled()); + + strategy.conflictEncountered(); + assertFalse(strategy.isRebootScheduled()); + + strategy.backtrackJustified(); + assertFalse(strategy.isRebootScheduled()); + + strategy.answerSetFound(); + assertFalse(strategy.isRebootScheduled()); + } +} From 20c6ebdb5c7748c80326a1cf0c11a74ced55a519 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 26 Jul 2023 16:07:10 +0200 Subject: [PATCH 51/53] Add tests of ground explosion program --- .../solver/reboot/GroundExplosionTest.java | 56 +++++++++++++++++++ .../kr/alpha/core/test/util/TestUtils.java | 4 ++ 2 files changed, 60 insertions(+) create mode 100644 alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/GroundExplosionTest.java diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/GroundExplosionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/GroundExplosionTest.java new file mode 100644 index 000000000..b59dec501 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/reboot/GroundExplosionTest.java @@ -0,0 +1,56 @@ +package at.ac.tuwien.kr.alpha.core.solver.reboot; + +import at.ac.tuwien.kr.alpha.core.solver.RegressionTest; +import at.ac.tuwien.kr.alpha.core.solver.RegressionTestConfig; + +import java.util.stream.IntStream; + +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.assertRegressionTestAnswerSets; + +public class GroundExplosionTest { + @RegressionTest + public void testGroundExplosion_1(RegressionTestConfig cfg) { + String domainStr = getDomainString(1); + assertRegressionTestAnswerSets(cfg, + getProgramString(1), + domainStr, + "sel(1), p(1,1,1,1,1,1), " + domainStr); + } + + @RegressionTest + public void testGroundExplosion_5(RegressionTestConfig cfg) { + String domainStr = getDomainString(5); + assertRegressionTestAnswerSets(cfg, + getProgramString(5), + domainStr, + "sel(1), p(1,1,1,1,1,1), " + domainStr, + "sel(2), p(2,2,2,2,2,2), " + domainStr, + "sel(3), p(3,3,3,3,3,3), " + domainStr, + "sel(4), p(4,4,4,4,4,4), " + domainStr, + "sel(5), p(5,5,5,5,5,5), " + domainStr); + } + + /** + * Constructs a ground explosion program string with the given domain size. + * + * @param n the size of the encoded domain. + */ + private String getProgramString(int n) { + return "{ sel(X) } :- dom(X)." + + ":- sel(X), sel(Y), X != Y." + + "p(X1,X2,X3,X4,X5,X6) :- sel(X1), sel(X2), sel(X3), sel(X4), sel(X5), sel(X6)." + + String.format("dom(1..%d).", n); + } + + /** + * Constructs a string of atoms representing a domain of the given size. + * + * @param n the size of the encoded domain. + */ + private String getDomainString(int n) { + return IntStream.range(1, n + 1) + .mapToObj(x -> String.format("dom(%d)", x)) + .reduce((x, y) -> String.format("%s, %s", x, y)) + .orElse(""); + } +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java index 666e4c28c..78f2df608 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java @@ -220,4 +220,8 @@ public static void ignoreTestForRebootEnabled(RegressionTestConfig cfg) { Assumptions.assumeFalse(cfg.isRebootEnabled()); } + public static void ignoreTestForRebootDisabled(RegressionTestConfig cfg) { + Assumptions.assumeTrue(cfg.isRebootEnabled()); + } + } From 8bfecd778c7e8e3adf9c2283b60016c9581acaf2 Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Wed, 26 Jul 2023 19:29:49 +0200 Subject: [PATCH 52/53] Add berkmin heuristic reset for reboot --- .../alpha/core/solver/heuristics/BerkMin.java | 8 +++++ .../solver/heuristics/BerkMinLiteral.java | 5 +++ .../kr/alpha/core/test/util/TestUtils.java | 35 ++++++++----------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java index ff1c65c7f..3fa8515ca 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java @@ -278,4 +278,12 @@ private boolean isUnassigned(int atom) { public String toString() { return this.getClass().getSimpleName(); } + + @Override + public void reset() { + activityCounters = new LinkedHashMap<>(); + signCounters = new LinkedHashMap<>(); + stackOfNoGoods = new ArrayDeque<>(); + stepsSinceLastDecay = 0; + } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java index 8a46227f6..6935709aa 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java @@ -79,4 +79,9 @@ protected void pushToStack(NoGood noGood) { } } } + + @Override + public void reset() { + activeLiterals = new LinkedList<>(); + } } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java index 78f2df608..2bf50698c 100644 --- a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java @@ -54,7 +54,7 @@ public static void fillAtomStore(AtomStore atomStore, int numberOfAtomsToFill) { atomStore.putIfAbsent(Atoms.newBasicAtom(predA, Terms.newConstant(i))); } } - + public static Atom atom(String predicateName, String... termStrings) { Term[] terms = new Term[termStrings.length]; for (int i = 0; i < termStrings.length; i++) { @@ -75,11 +75,11 @@ public static Atom atom(String predicateName, int... termInts) { } return Atoms.newBasicAtom(Predicates.getPredicate(predicateName, terms.length), terms); } - + public static void printNoGoods(AtomStore atomStore, Collection noGoods) { System.out.println(noGoods.stream().map(atomStore::noGoodToString).collect(Collectors.toSet())); } - + public static void assertAnswerSetsEqual(Set expected, Set actual) { if (expected == null) { if (actual != null) { @@ -161,15 +161,15 @@ private static Solver buildSolverFromSystemConfig(ASPCore2Program prog, SystemCo : InternalProgram.fromNormalProgram(normalProg); return SolverFactory.getInstance(cfg, atomStore, GrounderFactory.getInstance(cfg.getGrounderName(), preprocessed, atomStore, cfg.isDebugInternalChecks())); } - + public static Solver buildSolverForRegressionTest(ASPCore2Program prog, RegressionTestConfig cfg) { return buildSolverFromSystemConfig(prog, cfg.toSystemConfig()); } - + public static Solver buildSolverForRegressionTest(String prog, RegressionTestConfig cfg) { return buildSolverFromSystemConfig(new ProgramParserImpl().parse(prog), cfg.toSystemConfig()); } - + public static Solver buildSolverForRegressionTest(AtomStore atomStore, Grounder grounder, RegressionTestConfig cfg) { SystemConfig systemCfg = cfg.toSystemConfig(); return SolverFactory.getInstance(systemCfg, atomStore, grounder); @@ -178,7 +178,7 @@ public static Solver buildSolverForRegressionTest(AtomStore atomStore, Grounder public static Set collectRegressionTestAnswerSets(ASPCore2Program prog, RegressionTestConfig cfg) { return buildSolverForRegressionTest(prog, cfg).collectSet(); } - + public static Set collectRegressionTestAnswerSets(String aspstr, RegressionTestConfig cfg) { ASPCore2Program prog = new ProgramParserImpl().parse(aspstr); return collectRegressionTestAnswerSets(prog, cfg); @@ -188,30 +188,30 @@ public static void assertRegressionTestAnswerSet(RegressionTestConfig cfg, Strin Set actualAnswerSets = collectRegressionTestAnswerSets(program, cfg); TestUtils.assertAnswerSetsEqual(answerSet, actualAnswerSets); } - + public static void assertRegressionTestAnswerSets(RegressionTestConfig cfg, String program, String... answerSets) { Set actualAnswerSets = collectRegressionTestAnswerSets(program, cfg); - TestUtils.assertAnswerSetsEqual(answerSets, actualAnswerSets); + TestUtils.assertAnswerSetsEqual(answerSets, actualAnswerSets); } - + public static void assertRegressionTestAnswerSetsWithBase(RegressionTestConfig cfg, String program, String base, String... answerSets) { Set actualAnswerSets = collectRegressionTestAnswerSets(program, cfg); - TestUtils.assertAnswerSetsEqualWithBase(base, answerSets, actualAnswerSets); + TestUtils.assertAnswerSetsEqualWithBase(base, answerSets, actualAnswerSets); } - + public static void runWithTimeout(RegressionTestConfig cfg, long baseTimeout, long timeoutFactor, Executable action) { long timeout = cfg.isDebugChecks() ? timeoutFactor * baseTimeout : baseTimeout; assertTimeoutPreemptively(Duration.ofMillis(timeout), action); } - + public static void ignoreTestForNaiveSolver(RegressionTestConfig cfg) { Assumptions.assumeFalse(cfg.getSolverName().equals("naive")); } - + public static void ignoreTestForNonDefaultDomainIndependentHeuristics(RegressionTestConfig cfg) { Assumptions.assumeTrue(cfg.getBranchingHeuristic() == Heuristic.VSIDS); } - + public static void ignoreTestForSimplifiedSumAggregates(RegressionTestConfig cfg) { Assumptions.assumeTrue(cfg.isSupportNegativeSumElements()); } @@ -219,9 +219,4 @@ public static void ignoreTestForSimplifiedSumAggregates(RegressionTestConfig cfg public static void ignoreTestForRebootEnabled(RegressionTestConfig cfg) { Assumptions.assumeFalse(cfg.isRebootEnabled()); } - - public static void ignoreTestForRebootDisabled(RegressionTestConfig cfg) { - Assumptions.assumeTrue(cfg.isRebootEnabled()); - } - } From b3839965aa2d8f87d8bcd48c535b651333a5c73a Mon Sep 17 00:00:00 2001 From: Paul Behofsics Date: Sun, 30 Jul 2023 16:15:55 +0200 Subject: [PATCH 53/53] Remove extra log output --- .../at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java | 3 +-- .../ac/tuwien/kr/alpha/core/solver/PerformanceLog.java | 9 +++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index 43cc71513..ebf73c375 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -121,8 +121,7 @@ public DefaultSolver(AtomStore atomStore, Grounder grounder, NoGoodStore store, this.disableRebootRepeat = config.isDisableRebootRepeat(); this.rebootStrategy = RebootStrategyFactory.getRebootStrategy(config); - this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, - store.getNoGoodCounter(), 1000); + this.performanceLog = new PerformanceLog(choiceManager, (TrailAssignment) assignment, 1000); if (this.rebootEnabled && !(grounder instanceof RebootableGrounder)) { this.rebootEnabled = false; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java index fc20fe6a8..c85d41879 100644 --- a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java @@ -34,7 +34,6 @@ public class PerformanceLog { private final ChoiceManager choiceManager; private final TrailAssignment assignment; - private final NoGoodCounter noGoodCounter; private final long msBetweenOutputs; private Long timeFirstEntry; @@ -44,11 +43,10 @@ public class PerformanceLog { /** * @param msBetweenOutputs minimum number of milliseconds that have to pass between writing of performance logs. */ - public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, NoGoodCounter noGoodCounter, long msBetweenOutputs) { + public PerformanceLog(ChoiceManager choiceManager, TrailAssignment assignment, long msBetweenOutputs) { super(); this.choiceManager = choiceManager; this.assignment = assignment; - this.noGoodCounter = noGoodCounter; this.msBetweenOutputs = msBetweenOutputs; } @@ -65,13 +63,12 @@ public void writeIfTimeForLogging(Logger logger) { long currentTime = System.currentTimeMillis(); int currentNumberOfChoices = choiceManager.getChoices(); if (currentTime >= timeLastPerformanceLog + msBetweenOutputs) { - logger.debug("Decisions in {}s: {}", (currentTime - timeLastPerformanceLog) / 1000.0f, currentNumberOfChoices - numberOfChoicesLastPerformanceLog); + logger.info("Decisions in {}s: {}", (currentTime - timeLastPerformanceLog) / 1000.0f, currentNumberOfChoices - numberOfChoicesLastPerformanceLog); timeLastPerformanceLog = currentTime; numberOfChoicesLastPerformanceLog = currentNumberOfChoices; float overallTime = (currentTime - timeFirstEntry) / 1000.0f; float decisionsPerSec = currentNumberOfChoices / overallTime; - logger.debug("Overall performance: {} decisions in {}s or {} decisions per sec. Overall replayed assignments: {}.", currentNumberOfChoices, overallTime, decisionsPerSec, assignment.replayCounter); - logger.debug("Current nogood counts: {}", noGoodCounter.getStatsByType()); + logger.info("Overall performance: {} decisions in {}s or {} decisions per sec. Overall replayed assignments: {}.", currentNumberOfChoices, overallTime, decisionsPerSec, assignment.replayCounter); } } } \ No newline at end of file