diff --git a/.gitignore b/.gitignore index 097f6d161..7f953ccdb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,10 @@ # Temporary/Generated Files /out/ +*/build + +# Log files +junit.log # Created by https://www.gitignore.io/api/java,gradle,eclipse @@ -97,8 +101,9 @@ gradle-app.setting ### Custom additions ### /.checkstyle -/junit.log +*/junit.log .idea/modules/*.iml *.tokens /.dbeaver /Scripts +/.vscode/ diff --git a/RELEASE.md b/RELEASE.md index 01645a22b..13200d6e1 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -47,15 +47,15 @@ as JAR files and two scripts to run Alpha on Unix-like and Windows respectively. To generate `alpha.jar`: ```bash -$ ./gradlew bundledJar -$ cp build/libs/alpha-bundled.jar alpha.jar +$ ./gradlew alpha-cli-app:bundledJar +$ cp alpha-cli-app/build/libs/alpha-cli*-bundled.jar alpha.jar ``` To generate `alpha.zip`: ```bash -$ ./gradlew distZip -$ cp build/distributions/alpha.zip alpha.zip +$ ./gradlew alpha-cli-app:distZip +$ cp alpha-cli-app/build/distributions/*.zip alpha.zip ``` Attach the two files to the release on GitHub, then publish the release. Lastly, check that everything is fine, diff --git a/alpha-api/.gitignore b/alpha-api/.gitignore new file mode 100644 index 000000000..84c048a73 --- /dev/null +++ b/alpha-api/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/alpha-api/build.gradle.kts b/alpha-api/build.gradle.kts new file mode 100644 index 000000000..55c7becf9 --- /dev/null +++ b/alpha-api/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("alpha.java-library-conventions") +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java new file mode 100644 index 000000000..d1b37b00c --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java @@ -0,0 +1,149 @@ +package at.ac.tuwien.kr.alpha.api; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.config.InputConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; + +/** + * Main API entry point for the Alpha ASP system. Provides facilities for parsing, normalizing and solving ASP programs. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface Alpha { + + /** + * Reads an ASP program using the configuration and sources specified in a given {@link InputConfig}. + * + * @param cfg and {@link InputConfig} specifying program sources (strings, files) as well as config metadata (e.g. literate program, + * external atoms, etc) + * @return an {@link ASPCore2Program} representing the parsed ASP code from all sources referenced in the given {@link InputConfig} + * @throws IOException in case one or more program sources (e.g. files) cannot be read, or parsing fails + */ + ASPCore2Program readProgram(InputConfig cfg) throws IOException; + + /** + * Reads and parses an {@link ASPCore2Program} from a list of {@link String}s representing paths. + * + * @param literate flag indicating whether ASP code should be treated as "literate". + * @param externals Custom {@link PredicateInterpretation}s for user-defined external atoms + * @param paths a list of {@link String}s representing paths containing all sources from which ASP code should be read + * @return an {@link ASPCore2Program} representing the parsed ASP code from all given path strings + * @throws IOException in case one or more program sources cannot be read, or parsing fails + */ + ASPCore2Program readProgramFiles(boolean literate, Map externals, List paths) throws IOException; + + /** + * see {@link Alpha#readProgramFiles(boolean, Map, List)} + */ + ASPCore2Program readProgramFiles(boolean literate, Map externals, Path... paths) throws IOException; + + /** + * Parses a given String into an {@link ASPCore2Program}, using a map of custom {@link PredicateInterpretation}s to resolve external atoms + * in ASP code. + * + * @param aspString a string representing a valid ASP-Core2 program + * @param externals a map of custom {@link PredicateInterpretation}s against which external atoms in the given code are resolved + * @return an {@link ASPCore2Program} representing the parsed ASP code + */ + ASPCore2Program readProgramString(String aspString, Map externals); + + /** + * Convenience method to parse ASP strings not containing any user-defined external atoms, see {@link Alpha#readProgramString(String, Map)}. + */ + ASPCore2Program readProgramString(String aspString); + + /** + * Prepares a {@link DebugSolvingContext} for the given {@link ASPCore2Program} to debug program preprocessing. + * + * @return a {@link DebugSolvingContext} holding debug information for the given program + */ + DebugSolvingContext prepareDebugSolve(final ASPCore2Program program); + + /** + * Prepares a {@link DebugSolvingContext} for the given {@link NormalProgram} to debug program preprocessing. + * + * @return a {@link DebugSolvingContext} holding debug information for the given program + */ + DebugSolvingContext prepareDebugSolve(final NormalProgram program); + + /** + * Prepares a {@link DebugSolvingContext} for the given {@link ASPCore2Program} to debug program preprocessing. + * + * @param filter a {@link java.util.function.Predicate} against which {@link Predicate}s of answer sets are tested. + * @return a {@link DebugSolvingContext} holding debug information for the given program + */ + DebugSolvingContext prepareDebugSolve(final ASPCore2Program program, java.util.function.Predicate filter); + + /** + * Prepares a {@link DebugSolvingContext} for the given {@link NormalProgram} to debug program preprocessing. + * + * @param filter a {@link java.util.function.Predicate} against which {@link Predicate}s of answer sets are tested. + * @return a {@link DebugSolvingContext} holding debug information for the given program + */ + DebugSolvingContext prepareDebugSolve(final NormalProgram program, java.util.function.Predicate filter); + + /** + * Solves the given {@link ASPCore2Program}. + * @param program an input program + * @return a {@link Stream} of {@link AnswerSet}s of the given program + */ + Stream solve(ASPCore2Program program); + + /** + * Solves the given {@link ASPCore2Program}. + * @param program an input program + * @param filter a {@link java.util.function.Predicate} against which {@link Predicate}s of answer sets are tested. + * @return a {@link Stream} of {@link AnswerSet}s of the given program + */ + Stream solve(ASPCore2Program program, java.util.function.Predicate filter); + + /** + * Solves the given {@link NormalProgram}. + * @param program an input program + * @return a {@link Stream} of {@link AnswerSet}s of the given program + */ + Stream solve(NormalProgram program); + + /** + * Solves the given {@link NormalProgram}. + * @param program an input program + * @param filter a {@link java.util.function.Predicate} against which {@link Predicate}s of answer sets are tested. + * @return a {@link Stream} of {@link AnswerSet}s of the given program + */ + Stream solve(NormalProgram program, java.util.function.Predicate filter); + + /** + * Normalizes a program, i.e. rewrites all syntax constructs not natively supported by Alphas back-end into semantically equivalent ASP code. + * See {@link NormalProgram}, + * @param program An {@link ASPCore2Program} to normalize + * @return a {@link NormalProgram} that is a semantic equivalent to the given input program + */ + NormalProgram normalizeProgram(ASPCore2Program program); + + /** + * Constructs a @{link Solver} pre-loaded with the given {@link ASPCore2Program} from which {@link AnswerSet}s can be obtained via {@link Solver#stream()}. + * + * @param program the program to solve + * @param filter a {@link java.util.function.Predicate} against which {@link Predicate}s of answer sets are tested. + * @return a {@link Solver} pre-loaded withthe given program + */ + Solver prepareSolverFor(ASPCore2Program program, java.util.function.Predicate filter); + + /** + * Constructs a @{link Solver} pre-loaded with the given {@link NormalProgram} from which {@link AnswerSet}s can be obtained via {@link Solver#stream()}. + * + * @param program the program to solve + * @param filter a {@link java.util.function.Predicate} against which {@link Predicate}s of answer sets are tested. + * @return a {@link Solver} pre-loaded withthe given program + */ + Solver prepareSolverFor(NormalProgram program, java.util.function.Predicate filter); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/AnswerSet.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/AnswerSet.java new file mode 100644 index 000000000..748e1a781 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/AnswerSet.java @@ -0,0 +1,35 @@ +package at.ac.tuwien.kr.alpha.api; + +import java.util.List; +import java.util.SortedSet; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; + +/** + * API representation of an answer set, i.e. a set of atoms that is a model of an ASP program. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface AnswerSet extends Comparable { + + /** + * The set of all predicates contained in the answer set. + */ + SortedSet getPredicates(); + + /** + * All instances of the given predicate within the answer set. + */ + SortedSet getPredicateInstances(Predicate predicate); + + /** + * Boolean flag indicating whether this {@link AnswerSet} represents the empty set. + */ + boolean isEmpty(); + + /** + * List {@link Atom}s in this answer set satisfying the given {@link AnswerSetQuery}. + */ + List query(AnswerSetQuery query); +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/AnswerSetQuery.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/AnswerSetQuery.java new file mode 100644 index 000000000..dcd015a21 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/AnswerSetQuery.java @@ -0,0 +1,82 @@ +package at.ac.tuwien.kr.alpha.api; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.terms.Term; + +/** + * A {@link java.util.function.Predicate} testing {@link Atom}s in order to query {@link AnswerSet}s for {@link Atom}s satisfying a specific + * query. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface AnswerSetQuery extends java.util.function.Predicate { + + /** + * Adds a filter predicate to apply on terms at the given index position. + * + * @param termIdx the term index on which to apply the new filter + * @param filter a filter predicate + * @return this answer set query withthe given filter added + */ + AnswerSetQuery withFilter(int termIdx, java.util.function.Predicate filter); + + /** + * Convenience method - adds a filter to match names of symbolic constants against a string. + * + * @param termIdx + * @param str + * @return + */ + AnswerSetQuery withConstantEquals(int termIdx, String str); + + /** + * Convenience method - adds a filter to match values of constant terms against a string. + * + * @param termIdx + * @param str + * @return + */ + AnswerSetQuery withStringEquals(int termIdx, String str); + + /** + * Convenience method - adds a filter to check for function terms with a given function symbol and arity. + * + * @param termIdx + * @param funcSymbol + * @param funcArity + * @return + */ + AnswerSetQuery withFunctionTerm(int termIdx, String funcSymbol, int funcArity); + + /** + * Convenience method - adds a filter to check whether a term is equal to a given term. + * + * @param termIdx + * @param otherTerm + * @return + */ + AnswerSetQuery withTermEquals(int termIdx, Term otherTerm); + + /** + * Applies this query to an atom. Filters are worked off in + * order of ascending term index in a conjunctive fashion, i.e. for an atom + * to match the query, all of its terms must satisfy all filters on these + * terms + * + * @param atom the atom to which to apply the query + * @return true iff the atom satisfies the query + */ + @Override + boolean test(Atom atom); + + /** + * Applies this query to an {@link AnswerSet}. + * + * @param as + * @return + */ + List applyTo(AnswerSet as); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/ComparisonOperator.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/ComparisonOperator.java new file mode 100644 index 000000000..b6cbfb168 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/ComparisonOperator.java @@ -0,0 +1,34 @@ +package at.ac.tuwien.kr.alpha.api; + +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.terms.Term; + +/** + * A comparison operator that can be used in {@link ASPCore2Program}s. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ComparisonOperator { + + /** + * The operator symbol, i.e. the operator's string representation. + */ + String getSymbol(); + + /** + * The {@link Predicate} associated with this operator. + */ + Predicate toPredicate(); + + /** + * The inverse of this operator (e.g. the inverse of "=" is "!=") + */ + ComparisonOperator negate(); + + /** + * Tests whether two terms are in the relation defined by this operator. + */ + boolean compare(Term t1, Term t2); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/DebugSolvingContext.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/DebugSolvingContext.java new file mode 100644 index 000000000..60966193a --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/DebugSolvingContext.java @@ -0,0 +1,43 @@ +package at.ac.tuwien.kr.alpha.api; + +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; + +/** + * Wrapper object for debug information on program preprocessing produced by {@link Alpha}. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface DebugSolvingContext { + + /** + * The normalized version of the {@link ASPCore2Program} that is being solved. + * See {@link Alpha#normalizeProgram(ASPCore2Program)}. + */ + NormalProgram getNormalizedProgram(); + + /** + * The fully preprocessed version of the {@link ASPCore2Program} that is being solved. + * This differs from the value of {@link DebugSolvingContext#getNormalizedProgram()} in the stratified part of the normalized program may + * already be evaluated depending on the respective configuration of {@link Alpha}. + */ + NormalProgram getPreprocessedProgram(); + + /** + * The {@link DependencyGraph} of the program being solved. + */ + DependencyGraph getDependencyGraph(); + + /** + * The {@link ComponentGraph} of the program being solved. + */ + ComponentGraph getComponentGraph(); + + /** + * A {@link Solver} instance pre-loaded with the program being solved, from which {@link AnswerSet}s can be streamed. + */ + Solver getSolver(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/Solver.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/Solver.java new file mode 100644 index 000000000..2dbd6be90 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/Solver.java @@ -0,0 +1,41 @@ +package at.ac.tuwien.kr.alpha.api; + +import java.util.List; +import java.util.Set; +import java.util.Spliterator; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * API representation of a solving component for a specific ASP program. + * Exposes {@link AnswerSet}s of the program for which the solver was created through {@link Solver#stream()}. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface Solver { + + Spliterator spliterator(); + + default Stream stream() { + return StreamSupport.stream(spliterator(), false); + } + + /** + * Rather than streaming {@link AnswerSet}s, collect the whole stream into a {@link Set}. Note that this method blocks unitl all answer sets + * are calculated, which may take a long time. + */ + default Set collectSet() { + return stream().collect(Collectors.toSet()); + } + + /** + * Rather than streaming {@link AnswerSet}s, collect the whole stream into a {@link List}. Note that this method blocks unitl all answer + * sets + * are calculated, which may take a long time. + */ + default List collectList() { + return stream().collect(Collectors.toList()); + } + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/StatisticsReportingSolver.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/StatisticsReportingSolver.java new file mode 100644 index 000000000..a9acf7405 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/StatisticsReportingSolver.java @@ -0,0 +1,81 @@ +package at.ac.tuwien.kr.alpha.api; + +import java.io.PrintStream; + +/** + * A {@link Solver} that collects statistics about the solving process while working. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface StatisticsReportingSolver extends Solver { + + + /** + * Returns how often the solver made a choice (i.e., the number of times it was guessing a truth value for a + * grounded rule). + */ + int getNumberOfChoices(); + + /** + * Returns the total number of backtracks (i.e., the number of decision levels that were rolled back). + * This includes all decision levels backtracked via backjumps. + * + * The number of backtracks excluding those within backjumps is + * {@link #getNumberOfBacktracks()} ()} minus {@link #getNumberOfBacktracksWithinBackjumps()} ()}. + */ + int getNumberOfBacktracks(); + + /** + * Returns the total number of backtracks executed during backjumping. + * That is, the total number of decision levels that were rolled back due to backjumps. + */ + int getNumberOfBacktracksWithinBackjumps(); + + /** + * Returns the number of times a backjump was executed, regardless of how many decision levels were rolled back + * by each backjump. + */ + int getNumberOfBackjumps(); + + /** + * Returns the number of times a complete assignment was found which contained some atoms assigned to + * must-be-true. Those assignments are no answer-sets and subsequently backtracking (or justification analysis) + * is triggered. + */ + int getNumberOfBacktracksDueToRemnantMBTs(); + + /** + * Returns the number of learned nogoods that were deleted again due to not being active enough. + * Learned-nogood deletion removes nogoods that were once learned but in the long run turned out to be no longer + * valuable for search, i.e., (large) nogoods that no longer appear in conflicts and do not propagate. + */ + int getNumberOfDeletedNoGoods(); + + /** + * Returns the number of times that a conflict was reached when the solver closed all atoms. + * Closing is the last step to make an assignment complete after search reaches a fixpoint (i.e., the lazy + * grounder instantiates no more nogoods and there are no more ground instances of rules to guess on), hence all + * atoms not yet assigned a truth value are therefore false, but this may still violate some nogoods and lead to + * a conflict. + */ + int getNumberOfConflictsAfterClosing(); + + default String getStatisticsString() { + return "g=" + getNumberOfChoices() + ", bt=" + getNumberOfBacktracks() + ", bj=" + getNumberOfBackjumps() + ", bt_within_bj=" + + getNumberOfBacktracksWithinBackjumps() + ", mbt=" + getNumberOfBacktracksDueToRemnantMBTs() + ", cac=" + getNumberOfConflictsAfterClosing() + + ", del_ng=" + getNumberOfDeletedNoGoods(); + } + + default String getStatisticsCSV() { + return String.format("%d,%d,%d,%d,%d,%d,%d", getNumberOfChoices(), getNumberOfBacktracks(), getNumberOfBackjumps(), getNumberOfBacktracksWithinBackjumps(), getNumberOfBacktracksDueToRemnantMBTs(), getNumberOfConflictsAfterClosing(), getNumberOfDeletedNoGoods()); + } + + default void printStatistics(PrintStream out) { + out.println(getStatisticsString()); + } + + default void printStatistics() { + printStatistics(System.out); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BindingPredicateInterpretation.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/common/fixedinterpretations/BindingPredicateInterpretation.java similarity index 77% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BindingPredicateInterpretation.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/common/fixedinterpretations/BindingPredicateInterpretation.java index e354d35a5..4517fa0f2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BindingPredicateInterpretation.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/common/fixedinterpretations/BindingPredicateInterpretation.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.fixedinterpretations; +package at.ac.tuwien.kr.alpha.api.common.fixedinterpretations; /** * This interface is used to mark predicate interpretations that might generate diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/PredicateInterpretation.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/common/fixedinterpretations/PredicateInterpretation.java similarity index 92% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/PredicateInterpretation.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/common/fixedinterpretations/PredicateInterpretation.java index 337dbc372..655fff135 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/PredicateInterpretation.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/common/fixedinterpretations/PredicateInterpretation.java @@ -25,14 +25,14 @@ * 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.common.fixedinterpretations; - -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +package at.ac.tuwien.kr.alpha.api.common.fixedinterpretations; import java.util.List; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; + import static java.util.Collections.*; @FunctionalInterface diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/AggregateRewritingConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/AggregateRewritingConfig.java new file mode 100644 index 000000000..6c72fbe62 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/AggregateRewritingConfig.java @@ -0,0 +1,45 @@ +package at.ac.tuwien.kr.alpha.api.config; + +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; + +/** + * Configuration structure controlling how {@link AggregateLiteral}s are compiled during program normalization in + * {@link Alpha#normalizeProgram(at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program)}. + * + * Copyright (c) 2021, the Alpha Team. + */ +public class AggregateRewritingConfig { + + public static final boolean DEFAULT_USE_SORTING_GRID = true; + public static final boolean DEFAULT_SUPPORT_NEGATIVE_INTEGERS = true; + + private boolean useSortingGridEncoding = DEFAULT_USE_SORTING_GRID; + private boolean supportNegativeValuesInSums = DEFAULT_SUPPORT_NEGATIVE_INTEGERS; + + public boolean isUseSortingGridEncoding() { + return this.useSortingGridEncoding; + } + + public boolean isSupportNegativeValuesInSums() { + return this.supportNegativeValuesInSums; + } + + /** + * Indicates whether "#count" aggregates should be compiled using a sorting-grid based encoding + * (details) + * rather than a simpler version with quadratic complexity in grounding. + */ + public void setUseSortingGridEncoding(boolean useSortingGridEncoding) { + this.useSortingGridEncoding = useSortingGridEncoding; + } + + /** + * Indicates whether encodings for "#sum" aggregates should support negative elements in the aggregated sets. While being more generic, this + * encoding negatively impacts grounding performance. + */ + public void setSupportNegativeValuesInSums(boolean supportNegativeValuesInSums) { + this.supportNegativeValuesInSums = supportNegativeValuesInSums; + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/AlphaConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/AlphaConfig.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/config/AlphaConfig.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/AlphaConfig.java index 86fbf473a..2486d4801 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/AlphaConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/AlphaConfig.java @@ -1,7 +1,7 @@ -package at.ac.tuwien.kr.alpha.config; +package at.ac.tuwien.kr.alpha.api.config; /** - * Wrapper type for AlphaConfig and InputConfig. + * Wrapper type for {@link SystemConfig} and {@link InputConfig}. */ public class AlphaConfig { diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/BinaryNoGoodPropagationEstimationStrategy.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/BinaryNoGoodPropagationEstimationStrategy.java new file mode 100644 index 000000000..0fccc02ca --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/BinaryNoGoodPropagationEstimationStrategy.java @@ -0,0 +1,33 @@ +package at.ac.tuwien.kr.alpha.api.config; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * The available strategies for estimating initial heuristic values for heuristics like VSIDS. + * Modern heuristics determine dynamically which atoms are of high interest. Initial values however must be determined + * by some other mechanism. One possibility is MOMS where the propagation from binary nogoods is used to estimate how + * much influence each atom might have. + */ +public enum BinaryNoGoodPropagationEstimationStrategy { + /** + * Estimate influence of literal under consideration by simply counting the number of binary nogoods (i.e., the + * length of the binary watch-list) this literal occurs in. + * Requires less computation than BinaryNoGoodPropagation but is also less precise. + */ + CountBinaryWatches, + + /** + * Count how many atoms are assigned after the literal under consideration is assigned true. + * This requires an assignment and a propagation cycle followed by a backtracking. More precise than + * CountBinaryWatches but significantly more computation required. + */ + BinaryNoGoodPropagation; + + /** + * @return a comma-separated list of names of known heuristics + */ + public static String listAllowedValues() { + return Arrays.stream(values()).map(BinaryNoGoodPropagationEstimationStrategy::toString).collect(Collectors.joining(", ")); + } +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/heuristics/GrounderHeuristicsConfiguration.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/GrounderHeuristicsConfiguration.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/heuristics/GrounderHeuristicsConfiguration.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/GrounderHeuristicsConfiguration.java index 5b501c2cc..e6b4bb540 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/heuristics/GrounderHeuristicsConfiguration.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/GrounderHeuristicsConfiguration.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. - * + * 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,13 +23,11 @@ * 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.grounder.heuristics; - -import at.ac.tuwien.kr.alpha.grounder.Grounder; +package at.ac.tuwien.kr.alpha.api.config; /** - * Contains configuration parameters for heuristics used by {@link Grounder}s. - * + * Contains configuration parameters for heuristics used by the grounder. + * * Both parameters {@link #toleranceConstraints} and {@link #toleranceRules} are interpreted as follows: * A rule (or constraint) is grounded if the following conditions are satisfied: *

    @@ -41,7 +39,7 @@ * being a fact, because the alternative would necessitate triggering re-grounding during backtracking.) *
  • At most {@code N} atoms occurring positively in the body are still unassigned.
  • *
- * + * * The parameter {@link #toleranceConstraints} specifies {@code N} for constraints, while {@link #toleranceRules} * specifies {@code N} for all other rules. Infinity is represented by the value {@code -1}. * The default value for both parameters is {@code 0}, which means that only those rules and constraints are @@ -49,7 +47,6 @@ * * The additional parameter {@link #accumulatorEnabled} is a switch for the accumulator grounding strategy * which disables the removal of instances from the grounder memory in certain cases. - * */ public class GrounderHeuristicsConfiguration { @@ -57,17 +54,17 @@ public class GrounderHeuristicsConfiguration { public static final int STRICT_INT = 0; public static final String PERMISSIVE_STRING = "permissive"; public static final int PERMISSIVE_INT = -1; - + private int toleranceConstraints; private int toleranceRules; private boolean accumulatorEnabled; - + public GrounderHeuristicsConfiguration() { super(); this.toleranceConstraints = STRICT_INT; this.toleranceRules = STRICT_INT; } - + /** * @param toleranceConstraints * @param toleranceRules @@ -119,11 +116,11 @@ public void setAccumulatorEnabled(boolean accumulatorEnabled) { public static GrounderHeuristicsConfiguration strict() { return new GrounderHeuristicsConfiguration(STRICT_INT, STRICT_INT); } - + public static GrounderHeuristicsConfiguration permissive() { return new GrounderHeuristicsConfiguration(PERMISSIVE_INT, PERMISSIVE_INT); } - + public static GrounderHeuristicsConfiguration getInstance(int toleranceConstraints, int toleranceRules) { return new GrounderHeuristicsConfiguration(toleranceConstraints, toleranceRules); } @@ -141,7 +138,7 @@ private static int parseTolerance(String tolerance) { return Integer.parseInt(tolerance); } } - + @Override public String toString() { return this.getClass().getSimpleName() + "(toleranceConstraints=" + toleranceConstraints + ",toleranceRules=" + toleranceRules + ",disableInstanceRemoval=" + accumulatorEnabled + ")"; diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/Heuristic.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/Heuristic.java new file mode 100644 index 000000000..f9cb45982 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/Heuristic.java @@ -0,0 +1,52 @@ +package at.ac.tuwien.kr.alpha.api.config; + +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * The available domain-independent heuristics. + * Some are deprecated because they perform poorly and have not been improved for some time, + * however the code is kept for now so that it stays compatible when interfaces are refactored. + */ +public enum Heuristic { + NAIVE, + BERKMIN, + BERKMINLITERAL, + @Deprecated + DD, + @Deprecated + DD_SUM, + @Deprecated + DD_AVG, + @Deprecated + DD_MAX, + @Deprecated + DD_MIN, + @Deprecated + DD_PYRO, + @Deprecated + GDD, + @Deprecated + GDD_SUM, + @Deprecated + GDD_AVG, + @Deprecated + GDD_MAX, + @Deprecated + GDD_MIN, + @Deprecated + GDD_PYRO, + @Deprecated + ALPHA_ACTIVE_RULE, + @Deprecated + ALPHA_HEAD_MBT, + VSIDS, + GDD_VSIDS; + + /** + * @return a comma-separated list of names of known heuristics + */ + public static String listAllowedValues() { + return Arrays.stream(values()).map(Heuristic::toString).collect(Collectors.joining(", ")); + } +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/InputConfig.java similarity index 56% rename from src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/InputConfig.java index 3459af103..5ce30a2bb 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/InputConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/InputConfig.java @@ -1,27 +1,29 @@ -package at.ac.tuwien.kr.alpha.config; - -import at.ac.tuwien.kr.alpha.api.externals.Externals; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - +package at.ac.tuwien.kr.alpha.api.config; + +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; + +import java.util.*; + +/** + * Config structure for ASP input supplied to {@link Alpha} instances. + * + * Copyright (c) 2021, the Alpha Team. + */ public class InputConfig { - + public static final java.util.function.Predicate DEFAULT_FILTER = p -> true; public static final boolean DEFAULT_LITERATE = false; public static final int DEFAULT_NUM_ANSWER_SETS = 0; - public static final boolean DEFAULT_WRITE_DEPENDENCY_GRAPH = false; + public static final boolean DEFAULT_DEBUG_PREPROCESSING = false; public static final String DEFAULT_DEPGRAPH_TARGET_FILE = "depgraph.dot"; - public static final boolean DEFAULT_WRITE_COMPONENT_GRAPH = false; public static final String DEFAULT_COMPGRAPH_TARGET_FILE = "compgraph.dot"; - public static final boolean DEFAULT_WRITE_PREPROCESSED_PROG = false; + public static final String DEFAULT_NORMALIZED_TARGET_FILE = "input.normalized.asp"; public static final String DEFAULT_PREPROC_TARGET_FILE = "input.preproc.asp"; - public static final String PREPROC_STDOUT_PATH = "---"; // indicator preprocessed program should be written to stdout public static final boolean DEFAULT_WRITE_XLSX = false; public static final String DEFAULT_XLSX_OUTFILE_PATH = "alphaAnswerSet"; // current directory, files named "alphaAnswerSet.{num}.{ext}" @@ -30,14 +32,13 @@ public class InputConfig { private boolean literate = InputConfig.DEFAULT_LITERATE; private int numAnswerSets = InputConfig.DEFAULT_NUM_ANSWER_SETS; private Set desiredPredicates = new HashSet<>(); - private boolean writeDependencyGraph = InputConfig.DEFAULT_WRITE_DEPENDENCY_GRAPH; + private boolean debugPreprocessing = InputConfig.DEFAULT_DEBUG_PREPROCESSING; private String depgraphPath = InputConfig.DEFAULT_DEPGRAPH_TARGET_FILE; - private boolean writeComponentGraph = InputConfig.DEFAULT_WRITE_COMPONENT_GRAPH; private String compgraphPath = InputConfig.DEFAULT_COMPGRAPH_TARGET_FILE; - private boolean writePreprocessed = InputConfig.DEFAULT_WRITE_PREPROCESSED_PROG; + private String normalizedPath = InputConfig.DEFAULT_NORMALIZED_TARGET_FILE; private String preprocessedPath = InputConfig.DEFAULT_PREPROC_TARGET_FILE; - // standard library externals are always loaded - private Map predicateMethods = Externals.getStandardLibraryExternals(); + + private Map predicateMethods = new HashMap<>(); private boolean writeAnswerSetsAsXlsx = InputConfig.DEFAULT_WRITE_XLSX; private String answerSetFileOutputPath; @@ -51,6 +52,9 @@ public List getAspStrings() { return this.aspStrings; } + /** + * Sets a list of strings constituitng valid ASP code which togehter make up (part of) an APS program. + */ public void setAspStrings(List aspStrings) { this.aspStrings = aspStrings; } @@ -59,6 +63,9 @@ public boolean isLiterate() { return this.literate; } + /** + * Sets whether the ASP code in this input config should be treated as literate (i.e. comment- and code lines "switched"). + */ public void setLiterate(boolean literate) { this.literate = literate; } @@ -67,6 +74,9 @@ public int getNumAnswerSets() { return this.numAnswerSets; } + /** + * Sets the number of {@link AnswerSet}s Alpha should caluclate for this input. (set zero to calculate all answer sets) + */ public void setNumAnswerSets(int numAnswerSets) { this.numAnswerSets = numAnswerSets; } @@ -79,6 +89,9 @@ public Map getPredicateMethods() { return this.predicateMethods; } + /** + * Adds annotated java methods against which external atoms in the ASP input should be resolved. + */ public void addPredicateMethods(Map predicateMethods) { for (Map.Entry entry : predicateMethods.entrySet()) { if (this.predicateMethods.containsKey(entry.getKey())) { @@ -96,6 +109,9 @@ public List getFiles() { return this.files; } + /** + * Sets a list of files containing ASP code that make up (part of) the ASP program represented by this input config. + */ public void setFiles(List files) { this.files = files; } @@ -104,38 +120,21 @@ public Set getDesiredPredicates() { return this.desiredPredicates; } + /** + * Sets a set of predicates against which answer sets for this input should be filtered. + */ public void setDesiredPredicates(Set desiredPredicates) { this.desiredPredicates = desiredPredicates; } - public boolean isWriteDependencyGraph() { - return this.writeDependencyGraph; - } - - public void setWriteDependencyGraph(boolean writeDependencyGraph) { - this.writeDependencyGraph = writeDependencyGraph; - } - - public boolean isWriteComponentGraph() { - return this.writeComponentGraph; - } - - public void setWriteComponentGraph(boolean writeComponentGraph) { - this.writeComponentGraph = writeComponentGraph; - } - - public boolean isWritePreprocessed() { - return this.writePreprocessed; - } - - public void setWritePreprocessed(boolean writePreprocessed) { - this.writePreprocessed = writePreprocessed; - } - public String getDepgraphPath() { return this.depgraphPath; } + /** + * Sets a path to which the {@link DependencyGraph} of the input program should be written. Note that + * {@link InputConfig#setDebugPreprocessing(boolean)} has to be active for this to take effect. + */ public void setDepgraphPath(String depgraphPath) { this.depgraphPath = depgraphPath; } @@ -144,6 +143,10 @@ public String getCompgraphPath() { return this.compgraphPath; } + /** + * Sets a path to which the {@link ComponentGraph} of the input program should be written. Note that + * {@link InputConfig#setDebugPreprocessing(boolean)} has to be active for this to take effect. + */ public void setCompgraphPath(String compgraphPath) { this.compgraphPath = compgraphPath; } @@ -152,6 +155,10 @@ public String getPreprocessedPath() { return this.preprocessedPath; } + /** + * Sets a path to which the preprocessed (i.e. normalized and up-front evaluated) version of the input program should be written. Note that + * {@link InputConfig#setDebugPreprocessing(boolean)} has to be active for this to take effect. + */ public void setPreprocessedPath(String preprocessedPath) { this.preprocessedPath = preprocessedPath; } @@ -160,6 +167,9 @@ public boolean isWriteAnswerSetsAsXlsx() { return this.writeAnswerSetsAsXlsx; } + /** + * If set to true, answer sets for this input will be written into an xslx worksheet rather than as plain-text console output. + */ public void setWriteAnswerSetsAsXlsx(boolean writeAnswerSetsAsXslx) { this.writeAnswerSetsAsXlsx = writeAnswerSetsAsXslx; } @@ -168,8 +178,35 @@ public String getAnswerSetFileOutputPath() { return this.answerSetFileOutputPath; } + /** + * If {@link InputConfig#setWriteAnswerSetsAsXlsx(boolean)} is set, answer sets for this input will be written into an xslx worksheet stored + * to the path set here. + */ public void setAnswerSetFileOutputPath(String answerSetFileOutputPath) { this.answerSetFileOutputPath = answerSetFileOutputPath; } + public String getNormalizedPath() { + return this.normalizedPath; + } + + /** + * Sets a path to which the normalized version of the input program should be written. Note that + * {@link InputConfig#setDebugPreprocessing(boolean)} has to be active for this to take effect. + */ + public void setNormalizedPath(String normalizedPath) { + this.normalizedPath = normalizedPath; + } + + public boolean isDebugPreprocessing() { + return this.debugPreprocessing; + } + + /** + * Enables collection of debug data during program preprocessing. + */ + public void setDebugPreprocessing(boolean debugPreprocessing) { + this.debugPreprocessing = debugPreprocessing; + } + } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/SystemConfig.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/config/SystemConfig.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java index ae9173f32..27019ce10 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/SystemConfig.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/config/SystemConfig.java @@ -25,20 +25,21 @@ * 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.config; +package at.ac.tuwien.kr.alpha.api.config; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingConfig; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory.Heuristic; +import at.ac.tuwien.kr.alpha.api.Alpha; +/** + * Config structure for {@link Alpha} instances. + * + * Copyright (c) 2021, the Alpha Team. + */ public class SystemConfig { - // Note: Defining constants for default values here rather than just // initializing from those values in order to have the values accessible in // contexts where no AlphaConfig instance exists (e.g. argument parsing from @@ -47,7 +48,7 @@ public class SystemConfig { public static final String DEFAULT_SOLVER_NAME = "default"; public static final String DEFAULT_NOGOOD_STORE_NAME = "alphaRoaming"; public static final Heuristic DEFAULT_BRANCHING_HEURISTIC = Heuristic.VSIDS; - public static final BinaryNoGoodPropagationEstimation.Strategy DEFAULT_MOMS_STRATEGY = BinaryNoGoodPropagationEstimation.Strategy.CountBinaryWatches; + public static final BinaryNoGoodPropagationEstimationStrategy DEFAULT_MOMS_STRATEGY = BinaryNoGoodPropagationEstimationStrategy.CountBinaryWatches; public static final long DEFAULT_SEED = System.nanoTime(); public static final boolean DEFAULT_DETERMINISTIC = false; public static final boolean DEFAULT_PRINT_STATS = false; @@ -71,7 +72,7 @@ public class SystemConfig { private long seed = DEFAULT_SEED; private boolean debugInternalChecks = DEFAULT_DEBUG_INTERNAL_CHECKS; private Heuristic branchingHeuristic = DEFAULT_BRANCHING_HEURISTIC; - private BinaryNoGoodPropagationEstimation.Strategy momsStrategy = DEFAULT_MOMS_STRATEGY; + private BinaryNoGoodPropagationEstimationStrategy momsStrategy = DEFAULT_MOMS_STRATEGY; private boolean quiet = DEFAULT_QUIET; private boolean printStats = DEFAULT_PRINT_STATS; private boolean disableJustificationSearch = DEFAULT_DISABLE_JUSTIFICATION_SEARCH; @@ -89,6 +90,9 @@ public String getGrounderName() { return this.grounderName; } + /** + * Sets the name of the grounder implementation to use. + */ public void setGrounderName(String grounderName) { this.grounderName = grounderName; } @@ -97,6 +101,9 @@ public String getSolverName() { return this.solverName; } + /** + * Sets the name of the solver implementation to use. + */ public void setSolverName(String solverName) { this.solverName = solverName; } @@ -105,6 +112,9 @@ public String getNogoodStoreName() { return this.nogoodStoreName; } + /** + * Sets the name of the nogood store implementation to use. + */ public void setNogoodStoreName(String nogoodStoreName) { this.nogoodStoreName = nogoodStoreName; } @@ -113,6 +123,10 @@ public boolean isDeterministic() { return this.deterministic; } + /** + * If set, 0 will be used as random seed for solver-internal branching heuristics, resulting in answer sets of the same program being found + * in a fixed sequence. + */ public void setDeterministic(boolean deterministic) { this.deterministic = deterministic; } @@ -121,6 +135,9 @@ public long getSeed() { return this.seed; } + /** + * Sets a fixed seed for solver-internal branching heuristics. + */ public void setSeed(long seed) { this.seed = seed; } @@ -129,6 +146,9 @@ public boolean isDebugInternalChecks() { return this.debugInternalChecks; } + /** + * Enables additional (time-consuming) debug options in the core solving component. + */ public void setDebugInternalChecks(boolean debugInternalChecks) { this.debugInternalChecks = debugInternalChecks; } @@ -137,6 +157,9 @@ public Heuristic getBranchingHeuristic() { return this.branchingHeuristic; } + /** + * Use the given branching heuristic. + */ public void setBranchingHeuristic(Heuristic branchingHeuristic) { this.branchingHeuristic = branchingHeuristic; } @@ -145,16 +168,16 @@ public void setBranchingHeuristicName(String branchingHeuristicName) { this.branchingHeuristic = Heuristic.valueOf(branchingHeuristicName.replace("-", "_").toUpperCase()); } - public BinaryNoGoodPropagationEstimation.Strategy getMomsStrategy() { + public BinaryNoGoodPropagationEstimationStrategy getMomsStrategy() { return momsStrategy; } - public void setMomsStrategy(BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public void setMomsStrategy(BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this.momsStrategy = momsStrategy; } public void setMomsStrategyName(String momsStrategyName) { - this.momsStrategy = BinaryNoGoodPropagationEstimation.Strategy.valueOf(momsStrategyName); + this.momsStrategy = BinaryNoGoodPropagationEstimationStrategy.valueOf(momsStrategyName); } public boolean isQuiet() { @@ -256,5 +279,5 @@ public AggregateRewritingConfig getAggregateRewritingConfig() { public void setAggregateRewritingConfig(AggregateRewritingConfig aggregateRewritingConfig) { this.aggregateRewritingConfig = aggregateRewritingConfig; } - + } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Predicate.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Predicate.java similarity index 76% rename from src/main/java/at/ac/tuwien/kr/alpha/api/externals/Predicate.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Predicate.java index 928f2cf99..f19ddf46e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Predicate.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Predicate.java @@ -6,17 +6,17 @@ import java.lang.annotation.Target; /** - * This annotation is used for discovery of method that represent + * This annotation is used for discovery of methods that represent * external predicates at runtime. * * In order to have your method detected by Alpha, annotate it - * with this annotation and call {@link Externals#scan}. - * - * @see Externals#scan + * with this annotation. Also make sure to configure your instance + * of Alpha to scan the package that contains the annotated method(s). */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Predicate { + /** * The name of the predicate that will be used to refer to * the annotated method. If it is the empty string (which diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/grounder/Substitution.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/grounder/Substitution.java new file mode 100644 index 000000000..3bc416b54 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/grounder/Substitution.java @@ -0,0 +1,23 @@ +package at.ac.tuwien.kr.alpha.api.grounder; + +import java.util.TreeMap; + +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; + +/** + * A mapping from {@link VariableTerm}s to {@link Term}s used during grounding to represent ground instances of terms, literals and rules. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface Substitution { + + Term eval(VariableTerm variableTerm); + + TreeMap getSubstitution(); + + > Term put(VariableTerm variableTerm, Term groundTerm); + + boolean isVariableSet(VariableTerm var); + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java similarity index 97% rename from src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java index 8f745e556..2d45ff5b2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToObjectMapper.java @@ -25,7 +25,7 @@ */ package at.ac.tuwien.kr.alpha.api.mapper; -import at.ac.tuwien.kr.alpha.common.AnswerSet; +import at.ac.tuwien.kr.alpha.api.AnswerSet; /** * Copyright (c) 2020, the Alpha Team. diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/ASPCore2Program.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/ASPCore2Program.java new file mode 100644 index 000000000..00d11f974 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/ASPCore2Program.java @@ -0,0 +1,13 @@ +package at.ac.tuwien.kr.alpha.api.programs; + +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; + +/** + * A {@link Program} that conforms to Alphas implementation of the ASP-Core2-Standard. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ASPCore2Program extends Program> { + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/InlineDirectives.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/InlineDirectives.java new file mode 100644 index 000000000..04a8a054c --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/InlineDirectives.java @@ -0,0 +1,26 @@ +package at.ac.tuwien.kr.alpha.api.programs; + +import java.util.Map; + +/** + * Deprecated - This should be refactored: Currently there can only be one instance of each directive, which should not be the case. Also, + * directives should probably be objects rather than key-value pairs. + * + * Copyright (c) 2021, the Alpha Team. + */ +@Deprecated +public interface InlineDirectives { + + public enum DIRECTIVE { + enum_predicate_is + } + + void accumulate(InlineDirectives other); + + Map getDirectives(); + + void addDirective(DIRECTIVE directive, String text); + + String getDirectiveValue(DIRECTIVE directive); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/NormalProgram.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/NormalProgram.java new file mode 100644 index 000000000..92734afab --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/NormalProgram.java @@ -0,0 +1,12 @@ +package at.ac.tuwien.kr.alpha.api.programs; + +import at.ac.tuwien.kr.alpha.api.rules.NormalRule; + +/** + * A {@link Program} consisting only of facts and {@link NormalRule}s, i.e. no disjunctive- or choice-rules, and no aggregates in rule bodies. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface NormalProgram extends Program { + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/Predicate.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/Predicate.java new file mode 100644 index 000000000..60f926dc4 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/Predicate.java @@ -0,0 +1,41 @@ +package at.ac.tuwien.kr.alpha.api.programs; + +/** + * A (first-order logic) predicate as used in ASP programs accepted by Alpha. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface Predicate extends Comparable { + + /** + * The predicate symbol. + */ + String getName(); + + /** + * The arity, i.e. number of arguments/terms of an instance over this predicate. + */ + int getArity(); + + @Override + default int compareTo(Predicate other) { + int result = getName().compareTo(other.getName()); + + if (result != 0) { + return result; + } + + return Integer.compare(getArity(), other.getArity()); + } + + /** + * Indicates whether this predicate is internal. Internal predicates are not shown in answer sets. + */ + boolean isInternal(); + + /** + * Indicates whether this predicate is internal to the solver. Solver-internal predicates are not shown in answer sets and may not be + * contained in input programs. + */ + boolean isSolverInternal(); +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/Program.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/Program.java new file mode 100644 index 000000000..2e8c0f528 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/Program.java @@ -0,0 +1,32 @@ +package at.ac.tuwien.kr.alpha.api.programs; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; + +/** + * An ASP program as accepted by Alpha. + * + * @param the type of rule this program may consist of (Normal-, Choice-, Disjunctive Rules) + * Copyright (c) 2021, the Alpha Team. + */ +public interface Program> { + + /** + * The facts, i.e. rule heads without body, in the program. + */ + List getFacts(); + + /** + * The {@link InlineDirectives} (i.e. meta-statements for the solver) that are part of this program. + */ + InlineDirectives getInlineDirectives(); + + /** + * The rules in the program. + */ + List getRules(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/ProgramParser.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/ProgramParser.java new file mode 100644 index 000000000..39f23cae8 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/ProgramParser.java @@ -0,0 +1,48 @@ +package at.ac.tuwien.kr.alpha.api.programs; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; + +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; + +/** + * A parser for {@link ASPCore2Program}s. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ProgramParser { + + default ASPCore2Program parse(String programString) { + return parse(programString, Collections.emptyMap()); + } + + default ASPCore2Program parse(InputStream programSource) throws IOException { + return parse(programSource, Collections.emptyMap()); + } + + default ASPCore2Program parse(Path programPath) throws IOException { + return parse(programPath, Collections.emptyMap()); + } + + default ASPCore2Program parse(Path... programSources) throws IOException { + return parse(Collections.emptyMap(), programSources); + } + + default ASPCore2Program parse(Iterable programSources) throws IOException { + return parse(programSources, Collections.emptyMap()); + } + + ASPCore2Program parse(String programString, Map externalPredicateDefinitions); + + ASPCore2Program parse(InputStream programSource, Map externalPredicateDefinitions) throws IOException; + + ASPCore2Program parse(Path programPath, Map externalPredicateDefinitions) throws IOException; + + ASPCore2Program parse(Map externalPredicateDefinitions, Path... programSources) throws IOException; + + ASPCore2Program parse(Iterable programSources, Map externalPredicateDefinitions) throws IOException; + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/VariableNormalizableAtom.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/VariableNormalizableAtom.java similarity index 85% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/VariableNormalizableAtom.java rename to alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/VariableNormalizableAtom.java index c6fbe0856..6a2efbba4 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/VariableNormalizableAtom.java +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/VariableNormalizableAtom.java @@ -1,4 +1,6 @@ -package at.ac.tuwien.kr.alpha.common.atoms; +package at.ac.tuwien.kr.alpha.api.programs; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; /** * Interface for atom whose variables can be normalized, i.e., enumerated from diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/analysis/ComponentGraph.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/analysis/ComponentGraph.java new file mode 100644 index 000000000..a124bf9db --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/analysis/ComponentGraph.java @@ -0,0 +1,41 @@ +package at.ac.tuwien.kr.alpha.api.programs.analysis; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * The component graph of an ASP program. The nodes of a component graph are strongly-connected components of the underlying + * {@link DependencyGraph}. Component graphs are always directed acyclic graphs. Every component (i.e. graph node) represents a set of + * predicates that cyclically depend on each other. Predicates that are not part of dependency cycles form components of their own. Paths go + * from components to those components that depend on them. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ComponentGraph { + + /** + * The full list of nodes (i.e. sets of predicates) in this graph. + */ + List getComponents(); + + /** + * The list of components that have no incoming edges (i.e. predicates that do not depend on other predicates) in the graph. + */ + List getEntryPoints(); + + interface SCComponent { + + Map getDependencyIds(); + + Set getDependentIds(); + + boolean hasNegativeCycle(); + + List getNodes(); + + int getId(); + + } + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/analysis/DependencyGraph.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/analysis/DependencyGraph.java new file mode 100644 index 000000000..29f83101a --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/analysis/DependencyGraph.java @@ -0,0 +1,37 @@ +package at.ac.tuwien.kr.alpha.api.programs.analysis; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; + +import java.util.List; +import java.util.Map; + +/** + * The predicate-level dependency graph of an ASP program. + * Each node of the dependency graph represents one {@link Predicate}. + * An edge from node A to node B indicates that predicate B depends on predicate A. Edges also store a "sign" (true or false) + * indicating whether a dependency is positive or negative (i.e. the predicate A occurs negated in the rule body deriving B). + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface DependencyGraph { + + Node getNodeForPredicate(Predicate p); + + Map> getAdjancencyMap(); + + interface Edge { + + Node getTarget(); + + boolean getSign(); + + } + + interface Node { + + Predicate getPredicate(); + + String getLabel(); + + } +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/AggregateAtom.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/AggregateAtom.java new file mode 100644 index 000000000..4dae7148c --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/AggregateAtom.java @@ -0,0 +1,59 @@ +package at.ac.tuwien.kr.alpha.api.programs.atoms; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; + +/** + * An {@link Atom} representing a comparison over an aggregate function, for example '13 < #sum{ X : p(X) }'. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface AggregateAtom extends Atom { + + /** + * Aggregate functions supported by Alpha. + * + * Copyright (c) 2021, the Alpha Team. + */ + enum AggregateFunctionSymbol { + COUNT, + MAX, + MIN, + SUM + } + + ComparisonOperator getLowerBoundOperator(); + + Term getLowerBoundTerm(); + + ComparisonOperator getUpperBoundOperator(); + + Term getUpperBoundTerm(); + + AggregateFunctionSymbol getAggregateFunction(); + + List getAggregateVariables(); + + List getAggregateElements(); + + @Override + AggregateLiteral toLiteral(boolean positive); + + interface AggregateElement { + + List getElementTerms(); + + List getElementLiterals(); + + List getOccurringVariables(); + + boolean isGround(); + + } + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/Atom.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/Atom.java new file mode 100644 index 000000000..c5cffbbfd --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/Atom.java @@ -0,0 +1,79 @@ +package at.ac.tuwien.kr.alpha.api.programs.atoms; + +import java.util.List; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; + +/** + * An Atom is the common super-interface of all representations of ASP atoms used by Alpha. + */ +public interface Atom extends Comparable { + + Predicate getPredicate(); + + List getTerms(); + + /** + * Returns whether this atom is ground, i.e., variable-free. + * + * @return true iff the terms of this atom contain no {@link VariableTerm}. + */ + boolean isGround(); + + /** + * Creates a non-negated literal containing this atom. + */ + default Literal toLiteral() { + return toLiteral(true); + } + + /** + * Creates a literal containing this atom which will be negated if {@code positive} is {@code false}. + * + * @param positive the polarity of the resulting literal. + * @return a literal that is positive iff the given parameter is true. + */ + Literal toLiteral(boolean positive); + + Set getOccurringVariables(); + + Atom substitute(Substitution substitution); // Introduce parameterized interface Substituable to get atom types right? + + Atom renameVariables(String newVariablePrefix); + + Atom withTerms(List terms); + + @Override + default int compareTo(Atom o) { + if (o == null) { + return 1; + } + + final List aTerms = this.getTerms(); + final List bTerms = o.getTerms(); + + if (aTerms.size() != bTerms.size()) { + return Integer.compare(aTerms.size(), bTerms.size()); + } + + int result = this.getPredicate().compareTo(o.getPredicate()); + + if (result != 0) { + return result; + } + + for (int i = 0; i < aTerms.size(); i++) { + result = aTerms.get(i).compareTo(o.getTerms().get(i)); + if (result != 0) { + return result; + } + } + + return 0; + } +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/BasicAtom.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/BasicAtom.java new file mode 100644 index 000000000..25486283f --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/BasicAtom.java @@ -0,0 +1,16 @@ +package at.ac.tuwien.kr.alpha.api.programs.atoms; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom; + +/** + * A "normal" atom according to the ASP Core 2 Standard. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface BasicAtom extends Atom, VariableNormalizableAtom { + + @Override + BasicAtom substitute(Substitution substitution); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/ComparisonAtom.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/ComparisonAtom.java new file mode 100644 index 000000000..f723709b1 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/ComparisonAtom.java @@ -0,0 +1,19 @@ +package at.ac.tuwien.kr.alpha.api.programs.atoms; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom; + +/** + * An {@link Atom} representing a comparison of terms. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ComparisonAtom extends Atom, VariableNormalizableAtom { + + ComparisonOperator getOperator(); + + @Override + ComparisonAtom substitute(Substitution subst); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/ExternalAtom.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/ExternalAtom.java new file mode 100644 index 000000000..42b4f110e --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/atoms/ExternalAtom.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.kr.alpha.api.programs.atoms; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom; +import at.ac.tuwien.kr.alpha.api.terms.Term; + +/** + * An external atom, i.e. an {@link Atom} that is interpreted by calling a linked Java-Method. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ExternalAtom extends Atom, VariableNormalizableAtom { + + boolean hasOutput(); + + List getInput(); + + List getOutput(); + + PredicateInterpretation getInterpretation(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/AggregateLiteral.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/AggregateLiteral.java new file mode 100644 index 000000000..702f587b6 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/AggregateLiteral.java @@ -0,0 +1,10 @@ +package at.ac.tuwien.kr.alpha.api.programs.literals; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; + +public interface AggregateLiteral extends Literal { + + @Override + AggregateAtom getAtom(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/BasicLiteral.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/BasicLiteral.java new file mode 100644 index 000000000..691142da4 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/BasicLiteral.java @@ -0,0 +1,5 @@ +package at.ac.tuwien.kr.alpha.api.programs.literals; + +public interface BasicLiteral extends Literal { + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/ComparisonLiteral.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/ComparisonLiteral.java new file mode 100644 index 000000000..01b7d6075 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/ComparisonLiteral.java @@ -0,0 +1,9 @@ +package at.ac.tuwien.kr.alpha.api.programs.literals; + +public interface ComparisonLiteral extends Literal, FixedInterpretationLiteral { + + boolean isLeftOrRightAssigning(); + + boolean isNormalizedEquality(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/ExternalLiteral.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/ExternalLiteral.java new file mode 100644 index 000000000..4fd301a3e --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/ExternalLiteral.java @@ -0,0 +1,10 @@ +package at.ac.tuwien.kr.alpha.api.programs.literals; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.ExternalAtom; + +public interface ExternalLiteral extends FixedInterpretationLiteral { + + @Override + ExternalAtom getAtom(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/FixedInterpretationLiteral.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/FixedInterpretationLiteral.java new file mode 100644 index 000000000..e1210428f --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/FixedInterpretationLiteral.java @@ -0,0 +1,28 @@ +package at.ac.tuwien.kr.alpha.api.programs.literals; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; + +/** + * Represents a literal whose ground truth value(s) are independent of the + * current assignment. + * Examples of atoms underlying such literals are builtin atoms and external + * atoms. + * Copyright (c) 2017-2021, the Alpha Team. + */ +public interface FixedInterpretationLiteral extends Literal { + + /** + * Creates a list of {@link Substitution}s based on the given partial substitution, such that this {@link FixedInterpretationLiteral} is + * true in every returned substitution. In cases where this is not possible (because of conflicting variable assignments in the partial + * substitution), getSatisfyingSubstitutions is required to return an empty list + * + * @param partialSubstitution a partial substitution that is required to bind + * all variables that are non-binding in this literal + * @return a list of substitutions, in each of which this literal is true, or an + * empty list if no such substitution exists + */ + public abstract List getSatisfyingSubstitutions(Substitution partialSubstitution); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/Literal.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/Literal.java new file mode 100644 index 000000000..13b4dac0c --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/programs/literals/Literal.java @@ -0,0 +1,39 @@ +package at.ac.tuwien.kr.alpha.api.programs.literals; + +import java.util.List; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.api.terms.VariableTerm; + +/** + * A literal according to the ASP Core 2 Standard. + * Wraps an {@link Atom} that may or may not be negated. + * + * Copyright (c) 2017-2021, the Alpha Team. + */ +// TODO go through implementations and pull out stuff that can be default-implemented here +public interface Literal { + Atom getAtom(); + + boolean isNegated(); + + Literal negate(); + + Predicate getPredicate(); + + List getTerms(); + + Set getOccurringVariables(); + + boolean isGround(); + + Set getBindingVariables(); + + Set getNonBindingVariables(); + + Literal substitute(Substitution substitution); +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/NormalRule.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/NormalRule.java new file mode 100644 index 000000000..5a5c995c6 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/NormalRule.java @@ -0,0 +1,15 @@ +package at.ac.tuwien.kr.alpha.api.rules; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; + +/** + * A {@link Rule} with a {@link NormalHead}. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface NormalRule extends Rule { + + BasicAtom getHeadAtom(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/Rule.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/Rule.java new file mode 100644 index 000000000..4f3013a86 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/Rule.java @@ -0,0 +1,25 @@ +package at.ac.tuwien.kr.alpha.api.rules; + +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; + +/** + * A rule as defined in the ASP Core 2 Standard. + * + * @param the type of rule head (e.g. choice, normal, disjunctive) supported by a specific rule. + * Copyright (c) 2021, the Alpha Team. + */ +public interface Rule { + + H getHead(); + + Set getBody(); + + boolean isConstraint(); + + Set getPositiveBody(); + + Set getNegativeBody(); +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/ChoiceHead.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/ChoiceHead.java new file mode 100644 index 000000000..2adf05d2c --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/ChoiceHead.java @@ -0,0 +1,35 @@ +package at.ac.tuwien.kr.alpha.api.rules.heads; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; + +/** + * A choice head as defined by the ASP Core 2 Standard. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ChoiceHead extends Head { + + Term getLowerBound(); + + Term getUpperBound(); + + ComparisonOperator getLowerOperator(); + + ComparisonOperator getUpperOperator(); + + List getChoiceElements(); + + public static interface ChoiceElement { + + BasicAtom getChoiceAtom(); + + List getConditionLiterals(); + + } + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/DisjunctiveHead.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/DisjunctiveHead.java new file mode 100644 index 000000000..24d19172f --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/DisjunctiveHead.java @@ -0,0 +1,11 @@ +package at.ac.tuwien.kr.alpha.api.rules.heads; + +/** + * Deprecated - A disjunctive head (see ASP Core 2 Standard). Should be removed since disjunction is not actually supported by Alpha. + * + * Copyright (c) 2021, the Alpha Team. + */ +@Deprecated +public interface DisjunctiveHead extends Head { + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/Head.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/Head.java new file mode 100644 index 000000000..4fb9e365b --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/Head.java @@ -0,0 +1,9 @@ +package at.ac.tuwien.kr.alpha.api.rules.heads; + +/** + * The head of an ASP rule. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface Head { +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/NormalHead.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/NormalHead.java new file mode 100644 index 000000000..64c335807 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/rules/heads/NormalHead.java @@ -0,0 +1,16 @@ +package at.ac.tuwien.kr.alpha.api.rules.heads; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; + +/** + * The "standard case" of a rule head, representing the head of a rule which derives a new {@link BasicAtom}. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface NormalHead extends Head { + + BasicAtom getAtom(); + + boolean isGround(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ArithmeticOperator.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ArithmeticOperator.java new file mode 100644 index 000000000..33be0a5e9 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ArithmeticOperator.java @@ -0,0 +1,51 @@ +package at.ac.tuwien.kr.alpha.api.terms; + +import com.google.common.math.IntMath; + +/** + * Arithmetic operators supported by Alpha. + * + * Copyright (c) 2021, the Alpha Team. + */ +public enum ArithmeticOperator { + PLUS("+"), + MINUS("-"), + TIMES("*"), + DIV("/"), + POWER("**"), + MODULO("\\"), + BITXOR("^"); + + private String asString; + + ArithmeticOperator(String asString) { + this.asString = asString; + } + + @Override + public String toString() { + return asString; + } + + public Integer eval(Integer left, Integer right) { + switch (this) { + case PLUS: + return left + right; + case MINUS: + return left - right; + case TIMES: + return left * right; + case DIV: + return left / right; + case POWER: + return IntMath.checkedPow(left, right); + case MODULO: + return left % right; + case BITXOR: + return left ^ right; + default: + throw new RuntimeException("Unknown arithmetic operator encountered."); + + } + } +} \ No newline at end of file diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ArithmeticTerm.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ArithmeticTerm.java new file mode 100644 index 000000000..8f0551d89 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ArithmeticTerm.java @@ -0,0 +1,18 @@ +package at.ac.tuwien.kr.alpha.api.terms; + +/** + * A {@link Term} that is a binary arithmetic expression. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface ArithmeticTerm extends Term { + + ArithmeticOperator getOperator(); + + Term getLeftOperand(); + + Term getRightOperand(); + + Integer evaluateExpression(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ConstantTerm.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ConstantTerm.java new file mode 100644 index 000000000..bc41438d0 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/ConstantTerm.java @@ -0,0 +1,15 @@ +package at.ac.tuwien.kr.alpha.api.terms; + +/** + * A term consisting of a constant symbol. + * + * @param the type of object represented by this term. + * Copyright (c) 2021, the Alpha Team. + */ +public interface ConstantTerm> extends Term { + + T getObject(); + + boolean isSymbolic(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/FunctionTerm.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/FunctionTerm.java new file mode 100644 index 000000000..a524ca619 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/FunctionTerm.java @@ -0,0 +1,16 @@ +package at.ac.tuwien.kr.alpha.api.terms; + +import java.util.List; + +/** + * A term representing an uninterpreted function + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface FunctionTerm extends Term { + + List getTerms(); + + String getSymbol(); + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/Term.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/Term.java new file mode 100644 index 000000000..4ed768155 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/Term.java @@ -0,0 +1,39 @@ +package at.ac.tuwien.kr.alpha.api.terms; + +import java.util.Map; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; + +/** + * Common super-interface for terms supported by Alpha. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface Term extends Comparable { + + boolean isGround(); + + Set getOccurringVariables(); + + Term substitute(Substitution substitution); + + /** + * Rename all variables occurring in this Term by prefixing their name. + * + * @param renamePrefix the name to prefix all occurring variables. + * @return the term with all variables renamed. + */ + Term renameVariables(String renamePrefix); + + Term normalizeVariables(String renamePrefix, RenameCounter counter); + + public static interface RenameCounter { + + Map getRenamedVariables(); + + int getAndIncrement(); + + } + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/VariableTerm.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/VariableTerm.java new file mode 100644 index 000000000..d735ed942 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/terms/VariableTerm.java @@ -0,0 +1,10 @@ +package at.ac.tuwien.kr.alpha.api.terms; + +/** + * A term representing a variable symbol in ASP programs. + * + * Copyright (c) 2021, the Alpha Team. + */ +public interface VariableTerm extends Term { + +} diff --git a/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/util/AnswerSetFormatter.java b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/util/AnswerSetFormatter.java new file mode 100644 index 000000000..ef1c034e8 --- /dev/null +++ b/alpha-api/src/main/java/at/ac/tuwien/kr/alpha/api/util/AnswerSetFormatter.java @@ -0,0 +1,14 @@ +package at.ac.tuwien.kr.alpha.api.util; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; + +/** + * Formats an {@link AnswerSet} to an instance of type T. + * + * @param the type to which to convert the answer set. + * Copyright (c) 2021, the Alpha Team. + */ +@FunctionalInterface +public interface AnswerSetFormatter { + T format(AnswerSet answerSet); +} diff --git a/alpha-cli-app/.gitignore b/alpha-cli-app/.gitignore new file mode 100644 index 000000000..84c048a73 --- /dev/null +++ b/alpha-cli-app/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/alpha-cli-app/build.gradle.kts b/alpha-cli-app/build.gradle.kts new file mode 100644 index 000000000..463a4af4b --- /dev/null +++ b/alpha-cli-app/build.gradle.kts @@ -0,0 +1,73 @@ +plugins { + id("alpha.java-application-conventions") +} + +dependencies { + implementation(project(":alpha-solver")) + implementation(project(":alpha-commons")) + + implementation("commons-cli:commons-cli:1.3.1") + + val poiVersion = "4.1.1" + implementation("org.apache.poi:poi:${poiVersion}") + implementation("org.apache.poi:poi-ooxml:${poiVersion}") + + // Logging Implementation and SLF4J + implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.14.1") { + // Exclude the SLF4J API, because we already have it via `alpha.java-application-conventions`. + exclude("org.slf4j", "slf4j-api") + } +} + +val main = "at.ac.tuwien.kr.alpha.Main" + +application { + mainClass.set(main) +} + +tasks.create("bundledJar") { + dependsOn(":alpha-api:jar", ":alpha-commons:jar", ":alpha-core:jar", ":alpha-solver:jar") + + manifest { + attributes["Main-Class"] = main + attributes["Multi-Release"] = true + } + + with(tasks["jar"] as CopySpec) + + from(configurations.runtimeClasspath.get().map({ if (it.isDirectory()) it else zipTree(it) })) + + archiveFileName.set("${project.name}-bundled.jar") + + exclude("META-INF/DEPENDENCIES") + + /* + * In order to make sure we don"t overwrite NOTICE and LICENSE files coming from dependency + * jars with each other, number them while copying + */ + var noticeCount = 0 + rename { it : String -> + return@rename if ("NOTICE.txt".equals(it) || "NOTICE".equals(it)) { + noticeCount++ + "NOTICE.${noticeCount}.txt" + } else { + it + } + } + + var licenseCount = 0 + rename { it : String -> + return@rename if ("LICENSE.txt".equals(it) || "LICENSE".equals(it)) { + licenseCount++ + "LICENSE.${licenseCount}.txt" + } else { + it + } + } + + duplicatesStrategy = DuplicatesStrategy.FAIL +} + +tasks.test { + useJUnitPlatform() +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java index fc61c4b9b..ee9a3bad2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriter.java @@ -14,9 +14,9 @@ import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import at.ac.tuwien.kr.alpha.api.AnswerSet; import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToObjectMapper; -import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToWorkbookMapper; -import at.ac.tuwien.kr.alpha.common.AnswerSet; +import at.ac.tuwien.kr.alpha.app.mappers.AnswerSetToWorkbookMapper; public class AnswerSetToXlsxWriter implements BiConsumer { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Main.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/Main.java similarity index 63% rename from src/main/java/at/ac/tuwien/kr/alpha/Main.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/Main.java index bcc79c8e9..487e25099 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Main.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/Main.java @@ -27,28 +27,6 @@ */ package at.ac.tuwien.kr.alpha; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetFormatter; -import at.ac.tuwien.kr.alpha.common.SimpleAnswerSetFormatter; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.DependencyGraph; -import at.ac.tuwien.kr.alpha.common.graphio.ComponentGraphWriter; -import at.ac.tuwien.kr.alpha.common.graphio.DependencyGraphWriter; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.config.AlphaConfig; -import at.ac.tuwien.kr.alpha.config.CommandLineParser; -import at.ac.tuwien.kr.alpha.config.InputConfig; -import at.ac.tuwien.kr.alpha.solver.Solver; -import at.ac.tuwien.kr.alpha.solver.SolverMaintainingStatistics; -import org.antlr.v4.runtime.RecognitionException; -import org.apache.commons.cli.ParseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -60,6 +38,29 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.cli.ParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.DebugSolvingContext; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.StatisticsReportingSolver; +import at.ac.tuwien.kr.alpha.api.config.AlphaConfig; +import at.ac.tuwien.kr.alpha.api.config.InputConfig; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.impl.AlphaImpl; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.api.util.AnswerSetFormatter; +import at.ac.tuwien.kr.alpha.app.ComponentGraphWriter; +import at.ac.tuwien.kr.alpha.app.DependencyGraphWriter; +import at.ac.tuwien.kr.alpha.app.config.CommandLineParser; +import at.ac.tuwien.kr.alpha.commons.util.SimpleAnswerSetFormatter; + /** * Main entry point for Alpha. */ @@ -79,43 +80,30 @@ public static void main(String[] args) { Main.exitWithMessage(commandLineParser.getUsageMessage(), 1); } - Alpha alpha = new Alpha(cfg.getSystemConfig()); + Alpha alpha = new AlphaImpl(cfg.getSystemConfig()); - InputProgram program = null; + ASPCore2Program program = null; try { program = alpha.readProgram(cfg.getInputConfig()); - } catch (RecognitionException e) { - // In case a recognition exception occurred, parseVisit will - // already have printed an error message, so we just exit - // at this point without further logging. - System.exit(1); } catch (FileNotFoundException e) { Main.bailOut(e.getMessage()); } catch (IOException e) { Main.bailOut("Failed to parse program.", e); } - NormalProgram normalized = alpha.normalizeProgram(program); - InternalProgram preprocessed; InputConfig inputCfg = cfg.getInputConfig(); - if (!(inputCfg.isWriteDependencyGraph() || inputCfg.isWriteComponentGraph())) { - LOGGER.debug("Not writing dependency or component graphs, starting preprocessing..."); - preprocessed = alpha.performProgramPreprocessing(InternalProgram.fromNormalProgram(normalized)); + Solver solver; + if (inputCfg.isDebugPreprocessing()) { + DebugSolvingContext dbgCtx = alpha.prepareDebugSolve(program); + Main.writeNormalProgram(dbgCtx.getNormalizedProgram(), inputCfg.getNormalizedPath()); + Main.writeNormalProgram(dbgCtx.getPreprocessedProgram(), inputCfg.getPreprocessedPath()); + Main.writeDependencyGraph(dbgCtx.getDependencyGraph(), inputCfg.getDepgraphPath()); + Main.writeComponentGraph(dbgCtx.getComponentGraph(), inputCfg.getCompgraphPath()); + solver = dbgCtx.getSolver(); } else { - LOGGER.debug("Performing program analysis in preparation for writing dependency and/or component graph file..."); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalized); - if (cfg.getInputConfig().isWriteDependencyGraph()) { - Main.writeDependencyGraph(analyzed.getDependencyGraph(), cfg.getInputConfig().getDepgraphPath()); - } - if (cfg.getInputConfig().isWriteComponentGraph()) { - Main.writeComponentGraph(analyzed.getComponentGraph(), cfg.getInputConfig().getCompgraphPath()); - } - preprocessed = alpha.performProgramPreprocessing(analyzed); - } - if (cfg.getInputConfig().isWritePreprocessed()) { - Main.writeInternalProgram(preprocessed, cfg.getInputConfig().getPreprocessedPath()); + solver = alpha.prepareSolverFor(program, inputCfg.getFilter()); } - Main.computeAndConsumeAnswerSets(alpha, cfg.getInputConfig(), preprocessed); + Main.computeAndConsumeAnswerSets(solver, cfg); } /** @@ -150,31 +138,28 @@ private static void writeComponentGraph(ComponentGraph cg, String path) { } /** - * Writes the given {@link InternalProgram} to the destination passed as the second parameter + * Writes the given {@link CompiledProgram} to the destination passed as the second parameter * - * @param prg the program to write + * @param prg the program to write * @param path the path to write the program to */ - private static void writeInternalProgram(InternalProgram prg, String path) { - LOGGER.debug("Writing preprocessed program to {}", path); + private static void writeNormalProgram(NormalProgram prg, String path) { + LOGGER.debug("Writing program to {}", path); PrintStream ps; try { - if (path.equals(InputConfig.PREPROC_STDOUT_PATH)) { - ps = System.out; - } else { - ps = new PrintStream(new File(path)); - } + ps = new PrintStream(new File(path)); ps.println(prg.toString()); } catch (IOException ex) { - LOGGER.error("Failed writing preprocessed program file", ex); - Main.bailOut("Failed writing preprocessed program file " + ex.getMessage()); + LOGGER.error("Failed writing program file", ex); + Main.bailOut("Failed writing program file " + ex.getMessage()); } } - private static void computeAndConsumeAnswerSets(Alpha alpha, InputConfig inputCfg, InternalProgram program) { - Solver solver = alpha.prepareSolverFor(program, inputCfg.getFilter()); + private static void computeAndConsumeAnswerSets(Solver solver, AlphaConfig alphaCfg) { + SystemConfig sysCfg = alphaCfg.getSystemConfig(); + InputConfig inputCfg = alphaCfg.getInputConfig(); Stream stream = solver.stream(); - if (alpha.getConfig().isSortAnswerSets()) { + if (sysCfg.isSortAnswerSets()) { stream = stream.sorted(); } @@ -183,10 +168,10 @@ private static void computeAndConsumeAnswerSets(Alpha alpha, InputConfig inputCf stream = stream.limit(limit); } - if (!alpha.getConfig().isQuiet()) { + if (!sysCfg.isQuiet()) { AtomicInteger counter = new AtomicInteger(0); final BiConsumer answerSetHandler; - final AnswerSetFormatter fmt = new SimpleAnswerSetFormatter(alpha.getConfig().getAtomSeparator()); + final AnswerSetFormatter fmt = new SimpleAnswerSetFormatter(sysCfg.getAtomSeparator()); BiConsumer stdoutPrinter = (n, as) -> { System.out.println("Answer set " + Integer.toString(n) + ":" + System.lineSeparator() + fmt.format(as)); }; @@ -217,8 +202,13 @@ private static void computeAndConsumeAnswerSets(Alpha alpha, InputConfig inputCf // answer sets. stream.collect(Collectors.toList()); } - if (alpha.getConfig().isPrintStats()) { - ((SolverMaintainingStatistics) solver).printStatistics(); + if (sysCfg.isPrintStats()) { + if (solver instanceof StatisticsReportingSolver) { + ((StatisticsReportingSolver) solver).printStatistics(); + } else { + // Note: Should not happen with proper validation of commandline args + System.err.println("Solver of type " + solver.getClass().getSimpleName() + " does not support solving statistics!"); + } } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/graphio/ComponentGraphWriter.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/ComponentGraphWriter.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/common/graphio/ComponentGraphWriter.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/ComponentGraphWriter.java index de315f778..b23b11325 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/graphio/ComponentGraphWriter.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/ComponentGraphWriter.java @@ -23,17 +23,16 @@ * 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.common.graphio; - -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph.SCComponent; -import at.ac.tuwien.kr.alpha.common.depgraph.Node; +package at.ac.tuwien.kr.alpha.app; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; import java.util.Map.Entry; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; + public class ComponentGraphWriter { private static final String GRAPH_HEADING = "digraph componentGraph"; @@ -72,7 +71,7 @@ private void writeComponentsTable(PrintStream ps, ComponentGraph cg) { contentBuilder.append("Predicates"); for (int i = 0; i < cg.getComponents().size(); i++) { contentBuilder.append(""); - for (Node n : cg.getComponents().get(i).getNodes()) { + for (DependencyGraph.Node n : cg.getComponents().get(i).getNodes()) { contentBuilder.append(n.getLabel()).append("
"); } contentBuilder.append(""); @@ -84,7 +83,7 @@ private void writeComponentsTable(PrintStream ps, ComponentGraph cg) { } private void writeGraph(PrintStream ps, ComponentGraph cg) { - List components = cg.getComponents(); + List components = cg.getComponents(); // Write the node descriptors for the components. for (int componentId = 0; componentId < components.size(); componentId++) { ps.printf(NODE_FMT, componentId, componentId); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/graphio/DependencyGraphWriter.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/DependencyGraphWriter.java similarity index 75% rename from src/main/java/at/ac/tuwien/kr/alpha/common/graphio/DependencyGraphWriter.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/DependencyGraphWriter.java index 7d838f8ca..8704a7ac9 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/graphio/DependencyGraphWriter.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/DependencyGraphWriter.java @@ -23,11 +23,10 @@ * 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.common.graphio; +package at.ac.tuwien.kr.alpha.app; -import at.ac.tuwien.kr.alpha.common.depgraph.DependencyGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.Edge; -import at.ac.tuwien.kr.alpha.common.depgraph.Node; + +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; import java.io.OutputStream; import java.io.PrintStream; @@ -48,29 +47,29 @@ public void writeAsDot(DependencyGraph graph, OutputStream out) { writeAsDot(graph.getAdjancencyMap(), out); } - private void writeAsDot(Map> graph, OutputStream out) { - BiFunction nodeFormatter = this::buildNodeString; + private void writeAsDot(Map> graph, OutputStream out) { + BiFunction nodeFormatter = this::buildNodeString; writeAsDot(graph, out, nodeFormatter); } - private void writeAsDot(Map> graph, OutputStream out, BiFunction nodeFormatter) { + private void writeAsDot(Map> graph, OutputStream out, BiFunction nodeFormatter) { PrintStream ps = new PrintStream(out); startGraph(ps); - Set>> graphDataEntries = graph.entrySet(); + Set>> graphDataEntries = graph.entrySet(); // First, write all nodes. int nodeCnt = 0; - Map nodesToNumbers = new HashMap<>(); - for (Map.Entry> entry : graphDataEntries) { + Map nodesToNumbers = new HashMap<>(); + for (Map.Entry> entry : graphDataEntries) { ps.print(nodeFormatter.apply(entry.getKey(), nodeCnt)); nodesToNumbers.put(entry.getKey(), nodeCnt); nodeCnt++; } // Second, write all edges. - for (Map.Entry> entry : graphDataEntries) { + for (Map.Entry> entry : graphDataEntries) { int fromNodeNum = nodesToNumbers.get(entry.getKey()); - for (Edge edge : entry.getValue()) { + for (DependencyGraph.Edge edge : entry.getValue()) { int toNodeNum = nodesToNumbers.get(edge.getTarget()); ps.printf(DependencyGraphWriter.DEFAULT_EDGE_FORMAT, fromNodeNum, toNodeNum, edge.getSign() ? "+" : "-"); } @@ -91,7 +90,7 @@ private void finishGraph(PrintStream ps) { ps.println("}"); } - private String buildNodeString(Node n, int nodeNum) { + private String buildNodeString(DependencyGraph.Node n, int nodeNum) { return String.format(DependencyGraphWriter.DEFAULT_NODE_FORMAT, nodeNum, n.getLabel()); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CliOptionHandler.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CliOptionHandler.java similarity index 83% rename from src/main/java/at/ac/tuwien/kr/alpha/config/CliOptionHandler.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CliOptionHandler.java index 054f01654..adc671dc2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CliOptionHandler.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CliOptionHandler.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.config; +package at.ac.tuwien.kr.alpha.app.config; import org.apache.commons.cli.Option; import org.apache.commons.cli.ParseException; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java index 53528ff9c..4b3ccf1f5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/config/CommandLineParser.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParser.java @@ -25,7 +25,14 @@ * 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.config; +package at.ac.tuwien.kr.alpha.app.config; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; @@ -38,16 +45,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; - -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingConfig; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory.Heuristic; +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 @@ -81,12 +84,8 @@ public class CommandLineParser { .desc("provide the asp program as a string").build(); private static final Option OPT_LITERATE = Option.builder("l").longOpt("literate") .desc("enable literate programming mode (default: " + InputConfig.DEFAULT_LITERATE + ")").build(); - private static final Option OPT_WRITE_PREPROCESSED = Option.builder("wpp").longOpt("writePreprocessedProgram").hasArg(true).argName("target") - .desc("write the internal program that is passed into the solver after transformations to a file. Writing to STDOUT is possible by setting target to: " + InputConfig.PREPROC_STDOUT_PATH).build(); - private static final Option OPT_WRITE_DEPGRAPH = Option.builder("wdg").longOpt("writeDependencyGraph").hasArg(true).argName("target") - .desc("Write a dot file with the input program's dependency graph").build(); - private static final Option OPT_WRITE_COMPGRAPH = Option.builder("wcg").longOpt("writeComponentGraph").hasArg(true).argName("target") - .desc("Write a dot file with the input program's component graph").build(); + private static final Option OPT_DEBUG_PREPROCESSING = Option.builder("dbgp").longOpt("DebugPreprocessing") + .desc("write files for normalized and preprocessed programs, also emit dependency- and component graphs as (graphviz) dot files").build(); private static final Option OPT_WRITE_XSLX = Option.builder("wx").longOpt("write-xlsx").hasArg(true).argName("path").type(String.class) .desc("Write answer sets to excel files, i.e. xlsx workbooks (one workbook per answer set)").build(); @@ -103,7 +102,7 @@ public class CommandLineParser { .desc("disables randomness (default: " + SystemConfig.DEFAULT_DETERMINISTIC + ")").build(); private static final Option OPT_SEED = Option.builder("e").longOpt("seed").hasArg(true).argName("seed").type(Integer.class) .desc("set seed (default: System.nanoTime())").build(); - private static final Option OPT_DEBUG_INTERNAL_CHECKS = Option.builder("dbg").longOpt("DebugEnableInternalChecks") + private static final Option OPT_DEBUG_INTERNAL_CHECKS = Option.builder("dbgs").longOpt("DebugEnableInternalChecks") .desc("run additional (time-consuming) safety checks (default: " + SystemConfig.DEFAULT_DEBUG_INTERNAL_CHECKS + ")").build(); private static final Option OPT_BRANCHING_HEURISTIC = Option.builder("b").longOpt("branchingHeuristic").hasArg(true).argName("heuristic") .desc("the branching heuristic to use (default: " + SystemConfig.DEFAULT_BRANCHING_HEURISTIC.name() + ")").build(); @@ -165,10 +164,8 @@ public class CommandLineParser { CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_LITERATE); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_INPUT); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_ASPSTRING); + CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_DEBUG_PREPROCESSING); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_WRITE_XSLX); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_WRITE_PREPROCESSED); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_WRITE_DEPGRAPH); - CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_WRITE_COMPGRAPH); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_GROUNDER); CommandLineParser.CLI_OPTS.addOption(CommandLineParser.OPT_SOLVER); @@ -257,10 +254,8 @@ private void initializeInputOptionHandlers() { this.inputOptionHandlers.put(CommandLineParser.OPT_FILTER.getOpt(), this::handleFilters); this.inputOptionHandlers.put(CommandLineParser.OPT_ASPSTRING.getOpt(), this::handleAspString); this.inputOptionHandlers.put(CommandLineParser.OPT_LITERATE.getOpt(), this::handleLiterate); + this.inputOptionHandlers.put(CommandLineParser.OPT_DEBUG_PREPROCESSING.getOpt(), this::handleDebugPreprocessing); this.inputOptionHandlers.put(CommandLineParser.OPT_WRITE_XSLX.getOpt(), this::handleWriteXlsx); - this.inputOptionHandlers.put(CommandLineParser.OPT_WRITE_PREPROCESSED.getOpt(), this::handleWritePreprocessed); - this.inputOptionHandlers.put(CommandLineParser.OPT_WRITE_DEPGRAPH.getOpt(), this::handleWriteDepgraph); - this.inputOptionHandlers.put(CommandLineParser.OPT_WRITE_COMPGRAPH.getOpt(), this::handleWriteCompgraph); } public AlphaConfig parseCommandLine(String[] args) throws ParseException { @@ -403,7 +398,7 @@ private void handleMomsStrategy(Option opt, SystemConfig cfg) throws ParseExcept cfg.setMomsStrategyName(momsStrategyName); } catch (IllegalArgumentException e) { throw new ParseException("Unknown mom's strategy: " + momsStrategyName + ". Please try one of the following: " - + BinaryNoGoodPropagationEstimation.Strategy.listAllowedValues()); + + BinaryNoGoodPropagationEstimationStrategy.listAllowedValues()); } } @@ -450,22 +445,8 @@ private void handleDisableStratifedEval(Option opt, SystemConfig cfg) { cfg.setEvaluateStratifiedPart(false); } - private void handleWritePreprocessed(Option opt, InputConfig cfg) { - cfg.setWritePreprocessed(true); - String preprocessedPath = opt.getValue(InputConfig.DEFAULT_PREPROC_TARGET_FILE); - cfg.setPreprocessedPath(preprocessedPath); - } - - private void handleWriteDepgraph(Option opt, InputConfig cfg) { - cfg.setWriteDependencyGraph(true); - String depgraphPath = opt.getValue(InputConfig.DEFAULT_DEPGRAPH_TARGET_FILE); - cfg.setDepgraphPath(depgraphPath); - } - - private void handleWriteCompgraph(Option opt, InputConfig cfg) { - cfg.setWriteComponentGraph(true); - String compgraphPath = opt.getValue(InputConfig.DEFAULT_COMPGRAPH_TARGET_FILE); - cfg.setCompgraphPath(compgraphPath); + private void handleDebugPreprocessing(Option opt, InputConfig cfg) { + cfg.setDebugPreprocessing(true); } private void handleNoNoGoodDeletion(Option opt, SystemConfig cfg) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToWorkbookMapper.java b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/mappers/AnswerSetToWorkbookMapper.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToWorkbookMapper.java rename to alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/mappers/AnswerSetToWorkbookMapper.java index 0f6499728..4fc5e81ee 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToWorkbookMapper.java +++ b/alpha-cli-app/src/main/java/at/ac/tuwien/kr/alpha/app/mappers/AnswerSetToWorkbookMapper.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.api.mapper; +package at.ac.tuwien.kr.alpha.app.mappers; import java.util.List; @@ -39,10 +39,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToObjectMapper; +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; /** * Implementation of {@link AnswerSetToObjectMapper} that generates an office open xml workbook ("excel file") from a given answer set. @@ -95,7 +96,7 @@ private void writeAtomToSheet(Sheet sheet, Atom atom) { rownum = sheet.getLastRowNum() + 1; } Row atomRow = sheet.createRow(rownum); - List terms = atom.getTerms(); + List terms = atom.getTerms(); Cell currCell; if (terms.isEmpty()) { // 0-arity atom diff --git a/src/main/resources/logback.xml b/alpha-cli-app/src/main/resources/logback.xml similarity index 100% rename from src/main/resources/logback.xml rename to alpha-cli-app/src/main/resources/logback.xml diff --git a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java similarity index 93% rename from src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java rename to alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java index 4e17c27e7..f1bf9e441 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java +++ b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/AnswerSetToXlsxWriterTest.java @@ -15,9 +15,9 @@ import org.apache.poi.ss.usermodel.WorkbookFactory; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.mapper.AnswerSetToWorkbookMapperTest; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.app.mappers.AnswerSetToWorkbookMapperTest; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; public class AnswerSetToXlsxWriterTest { diff --git a/src/test/java/at/ac/tuwien/kr/alpha/MainTest.java b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/MainTest.java similarity index 100% rename from src/test/java/at/ac/tuwien/kr/alpha/MainTest.java rename to alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/MainTest.java diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/graphio/ComponentGraphWriterTest.java b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/ComponentGraphWriterTest.java similarity index 85% rename from src/test/java/at/ac/tuwien/kr/alpha/common/graphio/ComponentGraphWriterTest.java rename to alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/ComponentGraphWriterTest.java index dc4facdd4..fff165831 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/graphio/ComponentGraphWriterTest.java +++ b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/ComponentGraphWriterTest.java @@ -1,8 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.graphio; - -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; +package at.ac.tuwien.kr.alpha.app; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -10,6 +6,11 @@ import org.junit.jupiter.api.Test; +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.DebugSolvingContext; +import at.ac.tuwien.kr.alpha.api.impl.AlphaImpl; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; + public class ComponentGraphWriterTest { private static final String LS = System.lineSeparator(); @@ -52,10 +53,9 @@ public void smokeTest() { "n1 -> n5 [xlabel=\"-\" labeldistance=0.1]" + LS + "n2 -> n5 [xlabel=\"+\" labeldistance=0.1]" + LS + "}" + LS; - Alpha alpha = new Alpha(); - AnalyzedProgram prog = AnalyzedProgram.analyzeNormalProgram( - alpha.normalizeProgram(alpha.readProgramString(asp))); - ComponentGraph compgraph = prog.getComponentGraph(); + Alpha alpha = new AlphaImpl(); + DebugSolvingContext dbgResult = alpha.prepareDebugSolve(alpha.readProgramString(asp)); + ComponentGraph compgraph = dbgResult.getComponentGraph(); ComponentGraphWriter writer = new ComponentGraphWriter(); ByteArrayOutputStream out = new ByteArrayOutputStream(); writer.writeAsDot(compgraph, out); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/graphio/DependencyGraphWriterTest.java b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/DependencyGraphWriterTest.java similarity index 84% rename from src/test/java/at/ac/tuwien/kr/alpha/common/graphio/DependencyGraphWriterTest.java rename to alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/DependencyGraphWriterTest.java index b7b340a57..b487e8479 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/graphio/DependencyGraphWriterTest.java +++ b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/DependencyGraphWriterTest.java @@ -1,8 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.graphio; - -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.depgraph.DependencyGraph; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; +package at.ac.tuwien.kr.alpha.app; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -10,6 +6,11 @@ import org.junit.jupiter.api.Test; +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.DebugSolvingContext; +import at.ac.tuwien.kr.alpha.api.impl.AlphaImpl; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; + public class DependencyGraphWriterTest { private static final String LS = System.lineSeparator(); @@ -49,10 +50,9 @@ public void smokeTest() { "n6 -> n4 [xlabel=\"+\" labeldistance=0.1]" + LS + "n6 -> n5 [xlabel=\"+\" labeldistance=0.1]" + LS + "}" + LS; - Alpha alpha = new Alpha(); - AnalyzedProgram prog = AnalyzedProgram.analyzeNormalProgram( - alpha.normalizeProgram(alpha.readProgramString(asp))); - DependencyGraph depgraph = prog.getDependencyGraph(); + Alpha alpha = new AlphaImpl(); + DebugSolvingContext dbgResult = alpha.prepareDebugSolve(alpha.readProgramString(asp)); + DependencyGraph depgraph = dbgResult.getDependencyGraph(); DependencyGraphWriter writer = new DependencyGraphWriter(); ByteArrayOutputStream out = new ByteArrayOutputStream(); writer.writeAsDot(depgraph, out); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/config/CommandLineParserTest.java b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParserTest.java similarity index 98% rename from src/test/java/at/ac/tuwien/kr/alpha/config/CommandLineParserTest.java rename to alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParserTest.java index 5761660ca..f77f6527e 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/config/CommandLineParserTest.java +++ b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/config/CommandLineParserTest.java @@ -25,10 +25,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.config; - -import org.apache.commons.cli.ParseException; -import org.junit.jupiter.api.Test; +package at.ac.tuwien.kr.alpha.app.config; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -38,6 +35,10 @@ import java.util.Arrays; import java.util.function.Consumer; +import org.apache.commons.cli.ParseException; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.config.AlphaConfig; public class CommandLineParserTest { diff --git a/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToWorkbookMapperTest.java b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/mappers/AnswerSetToWorkbookMapperTest.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToWorkbookMapperTest.java rename to alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/mappers/AnswerSetToWorkbookMapperTest.java index 2774f79c6..a2433d692 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/api/mapper/AnswerSetToWorkbookMapperTest.java +++ b/alpha-cli-app/src/test/java/at/ac/tuwien/kr/alpha/app/mappers/AnswerSetToWorkbookMapperTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.api.mapper; +package at.ac.tuwien.kr.alpha.app.mappers; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -15,11 +15,12 @@ import org.junit.jupiter.api.Test; import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.impl.AlphaImpl; +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.AnswerSetBuilder; public class AnswerSetToWorkbookMapperTest { @@ -45,8 +46,8 @@ public void solveAndWriteWorkbookTest() { + "p(N) :- p(I), N = I + 1, N <= MX, maxP(MX)." + "q(A, B) :- p(A), p(B)."; //@formatter:on - Alpha alpha = new Alpha(); - List answerSets = alpha.solve(alpha.readProgramString(progstr, null)).collect(Collectors.toList()); + Alpha alpha = new AlphaImpl(); + List answerSets = alpha.solve(alpha.readProgramString(progstr)).collect(Collectors.toList()); assertEquals(1, answerSets.size()); AnswerSet as = answerSets.get(0); Workbook answerSetWorkbook = this.mapper.mapFromAnswerSet(as); diff --git a/alpha-commons/.gitignore b/alpha-commons/.gitignore new file mode 100644 index 000000000..84c048a73 --- /dev/null +++ b/alpha-commons/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/alpha-commons/build.gradle.kts b/alpha-commons/build.gradle.kts new file mode 100644 index 000000000..f0ab5b2f5 --- /dev/null +++ b/alpha-commons/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("alpha.java-library-conventions") +} + +// Keep this in sync with antlr version to avoid multiple versions in classpath +val stringtemplateVersion = "4.0.8" + +dependencies { + api(project(":alpha-api")) + + implementation("org.antlr:ST4:${stringtemplateVersion}") +} + +tasks.test { + useJUnitPlatform() +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSetBuilder.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/AnswerSetBuilder.java similarity index 64% rename from src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSetBuilder.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/AnswerSetBuilder.java index 9cc1b9c0d..ca8d6db68 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSetBuilder.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/AnswerSetBuilder.java @@ -1,15 +1,21 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.commons; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import static java.util.Collections.singletonList; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; import java.util.stream.Stream; -import static java.util.Collections.singletonList; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; public class AnswerSetBuilder { private boolean firstInstance = true; @@ -30,14 +36,14 @@ public AnswerSetBuilder(AnswerSetBuilder copy) { this.instances = new TreeSet<>(copy.instances); this.predicateInstances = new HashMap<>(copy.predicateInstances); this.predicateInstances = copy.predicateInstances.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> new TreeSet<>(e.getValue()))); + .collect(Collectors.toMap(Map.Entry::getKey, e -> new TreeSet<>(e.getValue()))); } private void flush() { if (firstInstance) { - predicate = Predicate.getInstance(predicateSymbol, 0); + predicate = Predicates.getPredicate(predicateSymbol, 0); predicates.add(predicate); - predicateInstances.put(predicate, new TreeSet<>(singletonList(new BasicAtom(predicate)))); + predicateInstances.put(predicate, new TreeSet<>(singletonList(Atoms.newBasicAtom(predicate)))); } else { SortedSet atoms = predicateInstances.get(predicate); if (atoms == null) { @@ -63,34 +69,35 @@ public AnswerSetBuilder predicate(String predicateSymbol) { public final > AnswerSetBuilder instance(final T... terms) { if (firstInstance) { firstInstance = false; - predicate = Predicate.getInstance(predicateSymbol, terms.length); + predicate = Predicates.getPredicate(predicateSymbol, terms.length); predicates.add(predicate); } // Note that usage of terms does not pollute the heap, // since we are only reading, not writing. + @SuppressWarnings("varargs") List termList = Stream - .of(terms) - .map(ConstantTerm::getInstance) - .collect(Collectors.toList()); + .of(terms) + .map(Terms::newConstant) + .collect(Collectors.toList()); - instances.add(new BasicAtom(predicate, termList)); + instances.add(Atoms.newBasicAtom(predicate, termList)); return this; } public AnswerSetBuilder symbolicInstance(String... terms) { if (firstInstance) { firstInstance = false; - predicate = Predicate.getInstance(predicateSymbol, terms.length); + predicate = Predicates.getPredicate(predicateSymbol, terms.length); predicates.add(predicate); } - List termList = Stream.of(terms).map(ConstantTerm::getSymbolicInstance).collect(Collectors.toList()); - instances.add(new BasicAtom(predicate, termList)); + List termList = Stream.of(terms).map(Terms::newSymbolicConstant).collect(Collectors.toList()); + instances.add(Atoms.newBasicAtom(predicate, termList)); return this; } - public BasicAnswerSet build() { + public AnswerSet build() { flush(); return new BasicAnswerSet(predicates, predicateInstances); } diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/AnswerSets.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/AnswerSets.java new file mode 100644 index 000000000..0587e51d8 --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/AnswerSets.java @@ -0,0 +1,22 @@ +package at.ac.tuwien.kr.alpha.commons; + +import java.util.Map; +import java.util.SortedSet; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; + +public final class AnswerSets { + + public static final AnswerSet EMPTY_SET = BasicAnswerSet.EMPTY; + + private AnswerSets() { + throw new AssertionError("Cannot instantiate utility class"); + } + + public static AnswerSet newAnswerSet(SortedSet predicates, Map> predicateInstances) { + return new BasicAnswerSet(predicates, predicateInstances); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/BasicAnswerSet.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/BasicAnswerSet.java similarity index 61% rename from src/main/java/at/ac/tuwien/kr/alpha/common/BasicAnswerSet.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/BasicAnswerSet.java index 7d4f8137d..3dede61cc 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/BasicAnswerSet.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/BasicAnswerSet.java @@ -1,25 +1,31 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.commons; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; +import static java.util.Collections.emptyMap; +import static java.util.Collections.emptySortedSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; -import static java.util.Collections.emptyMap; -import static java.util.Collections.emptySortedSet; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.AnswerSetQuery; +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.commons.util.Util; /** * Copyright (c) 2016, the Alpha Team. */ -public class BasicAnswerSet implements AnswerSet { - public static final BasicAnswerSet EMPTY = new BasicAnswerSet(emptySortedSet(), emptyMap()); +class BasicAnswerSet implements AnswerSet { + + static final BasicAnswerSet EMPTY = new BasicAnswerSet(emptySortedSet(), emptyMap()); private final SortedSet predicates; private final Map> predicateInstances; - public BasicAnswerSet(SortedSet predicates, Map> predicateInstances) { + BasicAnswerSet(SortedSet predicates, Map> predicateInstances) { this.predicates = predicates; this.predicateInstances = predicateInstances; } @@ -90,6 +96,31 @@ public boolean equals(Object o) { @Override public int hashCode() { - return 31 * predicates.hashCode() + predicateInstances.hashCode(); + return 31 * predicates.hashCode() + predicateInstances.hashCode(); + } + + @Override + public int compareTo(AnswerSet other) { + final SortedSet predicates = this.getPredicates(); + int result = Util.compareSortedSets(predicates, other.getPredicates()); + + if (result != 0) { + return result; + } + + for (Predicate predicate : predicates) { + result = Util.compareSortedSets(this.getPredicateInstances(predicate), other.getPredicateInstances(predicate)); + + if (result != 0) { + return result; + } + } + + return 0; + } + + @Override + public List query(AnswerSetQuery query) { + return query.applyTo(this); } } \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/Predicate.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/PredicateImpl.java similarity index 59% rename from src/main/java/at/ac/tuwien/kr/alpha/common/Predicate.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/PredicateImpl.java index e181c9200..2f8c5975d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/Predicate.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/PredicateImpl.java @@ -1,33 +1,31 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.commons; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.commons.util.Interner; /** - * Copyright (c) 2016, the Alpha Team. + * A predicate as used by the Alpha solver internally. + * + * Copyright (c) 2016-2020, the Alpha Team. */ -public class Predicate implements Comparable { - private static final Interner INTERNER = new Interner<>(); +class PredicateImpl implements Predicate { + + private static final Interner INTERNER = new Interner<>(); private final String name; private final int arity; private final boolean internal; private final boolean solverInternal; - protected Predicate(String name, int arity, boolean internal, boolean solverInternal) { + PredicateImpl(String name, int arity, boolean internal, boolean solverInternal) { this.name = name; this.arity = arity; this.internal = internal; this.solverInternal = solverInternal; } - public static Predicate getInstance(String symbol, int arity) { - return getInstance(symbol, arity, false, false); - } - - public static Predicate getInstance(String symbol, int arity, boolean internal) { - return getInstance(symbol, arity, internal, false); - } - - public static Predicate getInstance(String symbol, int arity, boolean internal, boolean solverInternal) { - return INTERNER.intern(new Predicate(symbol, arity, internal, solverInternal)); + static PredicateImpl getInstance(String symbol, int arity, boolean internal, boolean solverInternal) { + return INTERNER.intern(new PredicateImpl(symbol, arity, internal, solverInternal)); } @Override @@ -44,11 +42,11 @@ public boolean equals(Object o) { return true; } - if (!(o instanceof Predicate)) { + if (!(o instanceof PredicateImpl)) { return false; } - Predicate predicate = (Predicate) o; + PredicateImpl predicate = (PredicateImpl) o; if (arity != predicate.arity) { return false; @@ -65,6 +63,7 @@ public boolean equals(Object o) { * Marks internal predicates that should not be shown/printed in answer sets. * @return true iff this Predicate should be omitted from answer sets. */ + @Override public boolean isInternal() { return internal; } @@ -74,25 +73,17 @@ public boolean isInternal() { * predicates are guaranteed to not occur in any rule bodies and hence are ignored by the grounder. * @return true iff this Predicate is internal to the solver component. */ + @Override public boolean isSolverInternal() { return solverInternal; } @Override - public int compareTo(Predicate other) { - int result = getName().compareTo(other.getName()); - - if (result != 0) { - return result; - } - - return Integer.compare(getArity(), other.getArity()); - } - public String getName() { return name; } + @Override public int getArity() { return arity; } diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/Predicates.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/Predicates.java new file mode 100644 index 000000000..a4d5a5893 --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/Predicates.java @@ -0,0 +1,23 @@ +package at.ac.tuwien.kr.alpha.commons; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; + +public final class Predicates { + + private Predicates() { + throw new AssertionError("Cannot instantiate utility class!"); + } + + public static Predicate getPredicate(String symbol, int arity) { + return PredicateImpl.getInstance(symbol, arity, false, false); + } + + public static Predicate getPredicate(String symbol, int arity, boolean internal) { + return PredicateImpl.getInstance(symbol, arity, internal, false); + } + + public static Predicate getPredicate(String symbol, int arity, boolean internal, boolean solverInternal) { + return PredicateImpl.getInstance(symbol, arity, internal, solverInternal); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/Atom.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/AbstractAtom.java similarity index 59% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/Atom.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/AbstractAtom.java index 7c5b32f5e..f55611a0f 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/Atom.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/AbstractAtom.java @@ -1,19 +1,19 @@ /** * 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. - * + * 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 @@ -25,44 +25,37 @@ * 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.common.atoms; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.Unifier; +package at.ac.tuwien.kr.alpha.commons.atoms; import java.util.List; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.literals.Literal; +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.terms.Terms; + /** * An Atom is the common superclass of all representations of ASP atoms used by Alpha. */ -public abstract class Atom implements Comparable { - - public abstract Predicate getPredicate(); - - public abstract List getTerms(); +public abstract class AbstractAtom implements Atom { /** * Creates a new Atom that represents this Atom, but has the given term list instead. - * + * * @param terms the terms to set. * @return a new Atom with the given terms set. */ + @Override public abstract Atom withTerms(List terms); - /** - * Returns whether this atom is ground, i.e., variable-free. - * - * @return true iff the terms of this atom contain no {@link VariableTerm}. - */ - public abstract boolean isGround(); - /** * Returns the set of all variables occurring in the Atom. */ + @Override public Set getOccurringVariables() { return toLiteral().getOccurringVariables(); } @@ -70,63 +63,33 @@ public Set getOccurringVariables() { /** * This method applies a substitution to the atom. Note that, depending on the atom and the substitution, the * resulting atom may still contain variables. - * + * * @param substitution the variable substitution to apply. * @return the atom resulting from the application of the substitution. */ + @Override public abstract Atom substitute(Substitution substitution); - /** - * Creates a non-negated literal containing this atom. - */ - public Literal toLiteral() { - return toLiteral(true); - } + @Override + public abstract List getTerms(); + + @Override + public abstract Predicate getPredicate(); /** - * Creates a literal containing this atom which will be negated if {@code positive} is {@code false}. - * - * @param positive the polarity of the resulting literal. - * @return a literal that is positive iff the given parameter is true. + * Returns whether this atom is ground, i.e., variable-free. + * + * @return true iff the terms of this atom contain no {@link VariableTermImpl}. */ - public abstract Literal toLiteral(boolean positive); - - public Atom renameVariables(String newVariablePrefix) { - Unifier renamingSubstitution = new Unifier(); - int counter = 0; - for (VariableTerm variable : getOccurringVariables()) { - renamingSubstitution.put(variable, VariableTerm.getInstance(newVariablePrefix + counter++)); - } - return this.substitute(renamingSubstitution); - } - @Override - public int compareTo(Atom o) { - if (o == null) { - return 1; - } - - final List aTerms = this.getTerms(); - final List bTerms = o.getTerms(); - - if (aTerms.size() != bTerms.size()) { - return Integer.compare(aTerms.size(), bTerms.size()); - } - - int result = this.getPredicate().compareTo(o.getPredicate()); - - if (result != 0) { - return result; - } + public abstract boolean isGround(); - for (int i = 0; i < aTerms.size(); i++) { - result = aTerms.get(i).compareTo(o.getTerms().get(i)); - if (result != 0) { - return result; - } - } + @Override + public abstract Literal toLiteral(boolean positive); - return 0; + @Override + public Atom renameVariables(String newVariablePrefix) { + return this.substitute(Terms.renameVariables(getOccurringVariables(), newVariablePrefix)); } @Override diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/AggregateAtom.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/AggregateAtomImpl.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/AggregateAtom.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/AggregateAtomImpl.java index 46f4aff18..964728e57 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/AggregateAtom.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/AggregateAtomImpl.java @@ -25,22 +25,26 @@ * 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.common.atoms; +package at.ac.tuwien.kr.alpha.commons.atoms; -import static at.ac.tuwien.kr.alpha.Util.join; -import static at.ac.tuwien.kr.alpha.Util.oops; +import static at.ac.tuwien.kr.alpha.commons.util.Util.join; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.Collections; import java.util.LinkedList; import java.util.List; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +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.literals.Literals; -public class AggregateAtom extends Atom { +class AggregateAtomImpl extends AbstractAtom implements AggregateAtom { private final ComparisonOperator lowerBoundOperator; private final Term lowerBoundTerm; @@ -49,7 +53,8 @@ public class AggregateAtom extends Atom { private final AggregateFunctionSymbol aggregatefunction; private final List aggregateElements; - public AggregateAtom(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, ComparisonOperator upperBoundOperator, Term upperBoundTerm, AggregateFunctionSymbol aggregatefunction, List aggregateElements) { + AggregateAtomImpl(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, ComparisonOperator upperBoundOperator, Term upperBoundTerm, + AggregateFunctionSymbol aggregatefunction, List aggregateElements) { this.lowerBoundOperator = lowerBoundOperator; this.lowerBoundTerm = lowerBoundTerm; this.upperBoundOperator = upperBoundOperator; @@ -58,7 +63,7 @@ public AggregateAtom(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, this.aggregateElements = aggregateElements; } - public AggregateAtom(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, AggregateFunctionSymbol aggregatefunction, List aggregateElements) { + public AggregateAtomImpl(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, AggregateFunctionSymbol aggregatefunction, List aggregateElements) { this(lowerBoundOperator, lowerBoundTerm, null, null, aggregatefunction, aggregateElements); } @@ -76,10 +81,9 @@ public boolean isGround() { return true; } - @Override public AggregateLiteral toLiteral(boolean positive) { - return new AggregateLiteral(this, positive); + return Literals.fromAtom(this, positive); } @Override @@ -91,7 +95,7 @@ public List getTerms() { public AggregateAtom withTerms(List terms) { throw new UnsupportedOperationException("Editing term list is not supported for aggregate atoms!"); } - + @Override public Predicate getPredicate() { throw oops("Aggregate atom cannot report predicate."); @@ -99,8 +103,10 @@ public Predicate getPredicate() { /** * Returns all variables occurring inside the aggregate, between { ... }. + * * @return each variable occurring in some aggregate element. */ + @Override public List getAggregateVariables() { List occurringVariables = new LinkedList<>(); for (AggregateElement aggregateElement : aggregateElements) { @@ -110,8 +116,8 @@ public List getAggregateVariables() { } @Override - public AggregateAtom substitute(Substitution substitution) { - throw new UnsupportedOperationException("Cannot apply substitution to AggregateAtom!"); + public AggregateAtomImpl substitute(Substitution substitution) { + throw new UnsupportedOperationException("Cannot substitute AggregateAtom!"); } @Override @@ -123,7 +129,7 @@ public boolean equals(Object o) { return false; } - AggregateAtom that = (AggregateAtom) o; + AggregateAtomImpl that = (AggregateAtomImpl) o; if (lowerBoundOperator != that.lowerBoundOperator) { return false; @@ -161,54 +167,56 @@ public int hashCode() { return result; } + @Override public ComparisonOperator getLowerBoundOperator() { return lowerBoundOperator; } + @Override public Term getLowerBoundTerm() { return lowerBoundTerm; } + @Override public ComparisonOperator getUpperBoundOperator() { return upperBoundOperator; } + @Override public Term getUpperBoundTerm() { return upperBoundTerm; } - public AggregateFunctionSymbol getAggregatefunction() { - return aggregatefunction; + @Override + public AggregateFunctionSymbol getAggregateFunction() { + return this.aggregatefunction; } + @Override public List getAggregateElements() { return Collections.unmodifiableList(aggregateElements); } - public enum AggregateFunctionSymbol { - COUNT, - MAX, - MIN, - SUM - } - - public static class AggregateElement { + static class AggregateElementImpl implements AggregateElement { final List elementTerms; final List elementLiterals; - public AggregateElement(List elementTerms, List elementLiterals) { + public AggregateElementImpl(List elementTerms, List elementLiterals) { this.elementTerms = elementTerms; this.elementLiterals = elementLiterals; } + @Override public List getElementTerms() { return elementTerms; } + @Override public List getElementLiterals() { return elementLiterals; } + @Override public boolean isGround() { for (Term elementTerm : elementTerms) { if (!elementTerm.isGround()) { @@ -223,6 +231,7 @@ public boolean isGround() { return true; } + @Override public List getOccurringVariables() { List occurringVariables = new LinkedList<>(); for (Term term : elementTerms) { @@ -246,7 +255,7 @@ public boolean equals(Object o) { return false; } - AggregateElement that = (AggregateElement) o; + AggregateElementImpl that = (AggregateElementImpl) o; if (elementTerms != null ? !elementTerms.equals(that.elementTerms) : that.elementTerms != null) { return false; @@ -266,5 +275,5 @@ public String toString() { return join("", elementTerms, " : ") + join("", elementLiterals, ""); } } - + } diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/Atoms.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/Atoms.java new file mode 100644 index 000000000..ed7b95ddc --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/Atoms.java @@ -0,0 +1,65 @@ +package at.ac.tuwien.kr.alpha.commons.atoms; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateElement; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +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.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.atoms.AggregateAtomImpl.AggregateElementImpl; + +public final class Atoms { + + private Atoms() { + throw new AssertionError("Cannot instantiate utility class"); + } + + /** + * Creates a positive BasicAtom over predicate and terms. + * + * @param predicate + * @param terms + */ + public static BasicAtom newBasicAtom(Predicate predicate, List terms) { + return new BasicAtomImpl(predicate, terms); + } + + public static BasicAtom newBasicAtom(Predicate predicate, Term... terms) { + return new BasicAtomImpl(predicate, Arrays.asList(terms)); + } + + public static BasicAtom newBasicAtom(Predicate predicate) { + return new BasicAtomImpl(predicate, Collections.emptyList()); + } + + public static AggregateAtom newAggregateAtom(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, ComparisonOperator upperBoundOperator, + Term upperBoundTerm, AggregateFunctionSymbol aggregatefunction, List aggregateElements) { + return new AggregateAtomImpl(lowerBoundOperator, lowerBoundTerm, upperBoundOperator, upperBoundTerm, aggregatefunction, aggregateElements); + } + + public static AggregateAtom newAggregateAtom(ComparisonOperator lowerBoundOperator, Term lowerBoundTerm, AggregateFunctionSymbol aggregatefunction, List aggregateElements) { + return new AggregateAtomImpl(lowerBoundOperator, lowerBoundTerm, null, null, aggregatefunction, aggregateElements); + } + + public static AggregateAtom.AggregateElement newAggregateElement(List elementTerms, List elementLiterals) { + return new AggregateElementImpl(elementTerms, elementLiterals); + } + + public static ComparisonAtom newComparisonAtom(Term term1, Term term2, ComparisonOperator operator) { + return new ComparisonAtomImpl(term1, term2, operator); + } + + public static ExternalAtom newExternalAtom(Predicate predicate, PredicateInterpretation interpretation, List input, List output) { + return new ExternalAtomImpl(predicate, interpretation, input, output); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/BasicAtom.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/BasicAtomImpl.java similarity index 73% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/BasicAtom.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/BasicAtomImpl.java index 98c7954aa..6b7cc57e5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/BasicAtom.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/BasicAtomImpl.java @@ -25,23 +25,27 @@ * 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.common.atoms; - -import static at.ac.tuwien.kr.alpha.Util.join; +package at.ac.tuwien.kr.alpha.commons.atoms; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; /** * Represents ordinary ASP atoms. */ -public class BasicAtom extends Atom implements VariableNormalizableAtom { +class BasicAtomImpl extends AbstractAtom implements BasicAtom { private final Predicate predicate; private final List terms; private final boolean ground; @@ -52,7 +56,7 @@ public class BasicAtom extends Atom implements VariableNormalizableAtom { * @param predicate * @param terms */ - public BasicAtom(Predicate predicate, List terms) { + BasicAtomImpl(Predicate predicate, List terms) { if (terms.size() != predicate.getArity()) { throw new IllegalArgumentException( "Cannot create Atom with terms: " + terms + " - Predicate " + predicate.getName() + " has incompatible arity " + predicate.getArity()); @@ -72,11 +76,11 @@ public BasicAtom(Predicate predicate, List terms) { this.ground = ground; } - public BasicAtom(Predicate predicate, Term... terms) { + BasicAtomImpl(Predicate predicate, Term... terms) { this(predicate, Arrays.asList(terms)); } - public BasicAtom(Predicate predicate) { + BasicAtomImpl(Predicate predicate) { this(predicate, Collections.emptyList()); } @@ -96,21 +100,21 @@ public boolean isGround() { } @Override - public BasicAtom substitute(Substitution substitution) { - return new BasicAtom(predicate, terms.stream() + public BasicAtomImpl substitute(Substitution substitution) { + return new BasicAtomImpl(predicate, terms.stream() .map(t -> t.substitute(substitution)) .collect(Collectors.toList())); } @Override - public BasicAtom normalizeVariables(String prefix, int counterStartingValue) { - List renamedTerms = Term.renameTerms(terms, prefix, counterStartingValue); - return new BasicAtom(predicate, renamedTerms); + public BasicAtomImpl normalizeVariables(String prefix, int counterStartingValue) { + List renamedTerms = Terms.renameTerms(terms, prefix, counterStartingValue); + return new BasicAtomImpl(predicate, renamedTerms); } @Override - public BasicLiteral toLiteral(boolean positive) { - return new BasicLiteral(this, positive); + public Literal toLiteral(boolean positive) { + return Literals.fromAtom(this, positive); } @Override @@ -120,7 +124,7 @@ public String toString() { return prefix; } - return join(prefix + "(", terms, ")"); + return Util.join(prefix + "(", terms, ")"); } @Override @@ -154,7 +158,7 @@ public boolean equals(Object o) { return false; } - BasicAtom that = (BasicAtom) o; + BasicAtomImpl that = (BasicAtomImpl) o; return predicate.equals(that.predicate) && terms.equals(that.terms); } @@ -166,7 +170,7 @@ public int hashCode() { @Override public Atom withTerms(List terms) { - return new BasicAtom(predicate, terms); + return new BasicAtomImpl(predicate, terms); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ComparisonAtom.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/ComparisonAtomImpl.java similarity index 67% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ComparisonAtom.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/ComparisonAtomImpl.java index 55c2629b3..52d063427 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ComparisonAtom.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/ComparisonAtomImpl.java @@ -25,32 +25,38 @@ * 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.common.atoms; - -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.commons.atoms; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.atoms.ComparisonAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; + /** * Represents a builtin comparison atom according to the standard. */ -public class ComparisonAtom extends Atom implements VariableNormalizableAtom { +class ComparisonAtomImpl extends AbstractAtom implements ComparisonAtom { + private final Predicate predicate; - final ComparisonOperator operator; + private final ComparisonOperator operator; private final List terms; - private ComparisonAtom(List terms, ComparisonOperator operator) { + private ComparisonAtomImpl(List terms, ComparisonOperator operator) { this.terms = terms; this.operator = operator; - this.predicate = operator.predicate(); + this.predicate = operator.toPredicate(); } - public ComparisonAtom(Term term1, Term term2, ComparisonOperator operator) { + ComparisonAtomImpl(Term term1, Term term2, ComparisonOperator operator) { this(Arrays.asList(term1, term2), operator); } @@ -72,12 +78,12 @@ public boolean isGround() { @Override public ComparisonAtom substitute(Substitution substitution) { List substitutedTerms = getTerms().stream().map(t -> t.substitute(substitution)).collect(Collectors.toList()); - return new ComparisonAtom(substitutedTerms, operator); + return new ComparisonAtomImpl(substitutedTerms, operator); } @Override public ComparisonLiteral toLiteral(boolean positive) { - return new ComparisonLiteral(this, positive); + return Literals.fromAtom(this, positive); } @Override @@ -100,7 +106,7 @@ public boolean equals(Object o) { return false; } - ComparisonAtom that = (ComparisonAtom) o; + ComparisonAtomImpl that = (ComparisonAtomImpl) o; if (operator != that.operator) { return false; @@ -114,14 +120,19 @@ public int hashCode() { } @Override - public ComparisonAtom normalizeVariables(String prefix, int counterStartingValue) { - List renamedTerms = Term.renameTerms(terms, prefix, counterStartingValue); - return new ComparisonAtom(renamedTerms.get(0), renamedTerms.get(1), operator); + public ComparisonAtomImpl normalizeVariables(String prefix, int counterStartingValue) { + List renamedTerms = Terms.renameTerms(terms, prefix, counterStartingValue); + return new ComparisonAtomImpl(renamedTerms.get(0), renamedTerms.get(1), operator); } @Override public Atom withTerms(List terms) { - return new ComparisonAtom(terms, operator); + return new ComparisonAtomImpl(terms, operator); + } + + @Override + public ComparisonOperator getOperator() { + return this.operator; } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ExternalAtom.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/ExternalAtomImpl.java similarity index 69% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ExternalAtom.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/ExternalAtomImpl.java index b19bc3d57..e5e5ef5e6 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ExternalAtom.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/atoms/ExternalAtomImpl.java @@ -1,19 +1,19 @@ /** - * Copyright (c) 2017-2020, the Alpha Team. + * Copyright (c) 2017-2021, 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. - * + * 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 @@ -25,12 +25,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.common.atoms; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.commons.atoms; import java.util.Collections; import java.util.List; @@ -38,9 +33,17 @@ import org.apache.commons.collections4.ListUtils; -import static at.ac.tuwien.kr.alpha.Util.join; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ExternalLiteral; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; -public class ExternalAtom extends Atom implements VariableNormalizableAtom { +class ExternalAtomImpl extends AbstractAtom implements ExternalAtom { private final List input; private final List output; @@ -48,7 +51,7 @@ public class ExternalAtom extends Atom implements VariableNormalizableAtom { protected final Predicate predicate; protected final PredicateInterpretation interpretation; - public ExternalAtom(Predicate predicate, PredicateInterpretation interpretation, List input, List output) { + ExternalAtomImpl(Predicate predicate, PredicateInterpretation interpretation, List input, List output) { if (predicate == null) { throw new IllegalArgumentException("predicate must not be null!"); } @@ -67,6 +70,7 @@ public ExternalAtom(Predicate predicate, PredicateInterpretation interpretation, this.output = output; } + @Override public boolean hasOutput() { return !output.isEmpty(); } @@ -76,14 +80,17 @@ public Predicate getPredicate() { return predicate; } + @Override public PredicateInterpretation getInterpretation() { return interpretation; } + @Override public List getInput() { return Collections.unmodifiableList(input); } + @Override public List getOutput() { return Collections.unmodifiableList(output); } @@ -109,25 +116,25 @@ public boolean isGround() { } @Override - public ExternalAtom substitute(Substitution substitution) { + public ExternalAtomImpl substitute(Substitution substitution) { List substitutedInput = this.input.stream().map(t -> t.substitute(substitution)).collect(Collectors.toList()); List substitutedOutput = this.output.stream().map(t -> t.substitute(substitution)).collect(Collectors.toList()); - return new ExternalAtom(predicate, interpretation, substitutedInput, substitutedOutput); + return new ExternalAtomImpl(predicate, interpretation, substitutedInput, substitutedOutput); } @Override public ExternalLiteral toLiteral(boolean positive) { - return new ExternalLiteral(this, positive); + return Literals.fromAtom(this, positive); } @Override public String toString() { String result = "&" + predicate.getName(); if (!input.isEmpty()) { - result += join("[", input, "]"); + result += Util.join("[", input, "]"); } if (!output.isEmpty()) { - result += join("(", output, ")"); + result += Util.join("(", output, ")"); } return result; } @@ -145,7 +152,7 @@ public ExternalAtom withTerms(List terms) { } List newInput = terms.subList(0, this.input.size()); List newOutput = terms.subList(this.input.size(), terms.size()); - return new ExternalAtom(this.predicate, this.interpretation, newInput, newOutput); + return new ExternalAtomImpl(this.predicate, this.interpretation, newInput, newOutput); } @Override @@ -170,23 +177,23 @@ public boolean equals(Object obj) { return false; } ExternalAtom other = (ExternalAtom) obj; - if (!this.input.equals(other.input)) { + if (!this.input.equals(other.getInput())) { return false; } - if (!this.output.equals(other.output)) { + if (!this.output.equals(other.getOutput())) { return false; } - if (!this.predicate.equals(other.predicate)) { + if (!this.predicate.equals(other.getPredicate())) { return false; } return true; } @Override - public ExternalAtom normalizeVariables(String prefix, int counterStartingValue) { - List renamedInput = Term.renameTerms(this.input, prefix + "_IN_", counterStartingValue); - List renamedOutput = Term.renameTerms(this.output, prefix + "_OUT_", counterStartingValue); - return new ExternalAtom(this.predicate, this.interpretation, renamedInput, renamedOutput); + public ExternalAtomImpl normalizeVariables(String prefix, int counterStartingValue) { + List renamedInput = Terms.renameTerms(this.input, prefix + "_IN_", counterStartingValue); + List renamedOutput = Terms.renameTerms(this.output, prefix + "_OUT_", counterStartingValue); + return new ExternalAtomImpl(this.predicate, this.interpretation, renamedInput, renamedOutput); } } diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/comparisons/AbstractComparisonOperator.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/comparisons/AbstractComparisonOperator.java new file mode 100644 index 000000000..2ea96c01f --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/comparisons/AbstractComparisonOperator.java @@ -0,0 +1,59 @@ +package at.ac.tuwien.kr.alpha.commons.comparisons; + +import java.util.Objects; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.Predicates; + +abstract class AbstractComparisonOperator implements ComparisonOperator { + + private final String symbol; + + AbstractComparisonOperator(String symbol) { + this.symbol = symbol; + } + + @Override + public String getSymbol() { + return this.symbol; + } + + @Override + public String toString() { + return this.getSymbol(); + } + + @Override + public Predicate toPredicate() { + return Predicates.getPredicate(this.symbol, 2); + } + + @Override + public abstract ComparisonOperator negate(); + + @Override + public abstract boolean compare(Term t1, Term t2); + + @Override + public int hashCode() { + return Objects.hash(symbol); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AbstractComparisonOperator other = (AbstractComparisonOperator) obj; + return Objects.equals(this.symbol, other.symbol); + } + +} diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/comparisons/ComparisonOperators.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/comparisons/ComparisonOperators.java new file mode 100644 index 000000000..1b851da26 --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/comparisons/ComparisonOperators.java @@ -0,0 +1,95 @@ +package at.ac.tuwien.kr.alpha.commons.comparisons; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.terms.Term; + +public class ComparisonOperators { + + public static final ComparisonOperator EQ = new AbstractComparisonOperator("=") { + + @Override + public ComparisonOperator negate() { + return ComparisonOperators.NE; + } + + @Override + public boolean compare(Term t1, Term t2) { + return t1.compareTo(t2) == 0; + } + + }; + + public static final ComparisonOperator NE = new AbstractComparisonOperator("!=") { + + @Override + public ComparisonOperator negate() { + return ComparisonOperators.EQ; + } + + @Override + public boolean compare(Term t1, Term t2) { + return t1.compareTo(t2) != 0; + } + }; + + public static final ComparisonOperator LT = new AbstractComparisonOperator("<") { + + @Override + public ComparisonOperator negate() { + return ComparisonOperators.GE; + } + + @Override + public boolean compare(Term t1, Term t2) { + return t1.compareTo(t2) < 0; + } + + }; + + public static final ComparisonOperator GT = new AbstractComparisonOperator(">") { + + @Override + public ComparisonOperator negate() { + return ComparisonOperators.LE; + } + + @Override + public boolean compare(Term t1, Term t2) { + return t1.compareTo(t2) > 0; + } + + }; + + public static final ComparisonOperator LE = new AbstractComparisonOperator("<=") { + + @Override + public ComparisonOperator negate() { + return ComparisonOperators.GT; + } + + @Override + public boolean compare(Term t1, Term t2) { + return t1.compareTo(t2) <= 0; + } + + }; + + public static final ComparisonOperator GE = new AbstractComparisonOperator(">=") { + + @Override + public ComparisonOperator negate() { + return ComparisonOperators.LT; + } + + @Override + public boolean compare(Term t1, Term t2) { + return t1.compareTo(t2) >= 0; + } + + }; + + public static final ComparisonOperator[] operators() { + return new ComparisonOperator[] {EQ, NE, LT, GT, LE, GE }; + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/Literal.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/AbstractLiteral.java similarity index 75% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/Literal.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/AbstractLiteral.java index 907a38b04..8d96711b1 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/Literal.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/AbstractLiteral.java @@ -1,19 +1,19 @@ /** - * Copyright (c) 2017-2018, the Alpha Team. + * Copyright (c) 2017-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 @@ -25,76 +25,89 @@ * 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.common.atoms; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import org.apache.commons.collections4.SetUtils; +package at.ac.tuwien.kr.alpha.commons.literals; import java.util.List; import java.util.Set; +import org.apache.commons.collections4.SetUtils; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; + /** - * A potentially negated {@link Atom} - * + * A potentially negated {@link AbstractAtom} + * * Copyright (c) 2017-2018, the Alpha Team. */ -public abstract class Literal { - +public abstract class AbstractLiteral implements Literal { + protected final Atom atom; protected final boolean positive; - - public Literal(Atom atom, boolean positive) { + + public AbstractLiteral(Atom atom, boolean positive) { this.atom = atom; this.positive = positive; } + @Override public Atom getAtom() { return atom; } + @Override public boolean isNegated() { return !positive; } - + + @Override public abstract Literal negate(); - + + @Override public abstract Literal substitute(Substitution substitution); - + + @Override public abstract Set getBindingVariables(); - + + @Override public abstract Set getNonBindingVariables(); - + /** * Union of {@link #getBindingVariables()} and {@link #getNonBindingVariables()} */ + @Override public Set getOccurringVariables() { return SetUtils.union(getBindingVariables(), getNonBindingVariables()); } /** - * @see Atom#getPredicate() + * @see AbstractAtom#getPredicate() */ + @Override public Predicate getPredicate() { return atom.getPredicate(); } /** - * @see Atom#getTerms() + * @see AbstractAtom#getTerms() */ + @Override public List getTerms() { return atom.getTerms(); } /** - * @see Atom#isGround() + * @see AbstractAtom#isGround() */ + @Override public boolean isGround() { return atom.isGround(); } - + @Override public String toString() { return (positive ? "" : "not ") + atom.toString(); @@ -111,7 +124,7 @@ public boolean equals(Object o) { Literal that = (Literal) o; - return atom.equals(that.atom) && positive == that.positive; + return atom.equals(that.getAtom()) && positive == !that.isNegated(); } @Override diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/AggregateLiteral.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/AggregateLiteralImpl.java similarity index 50% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/AggregateLiteral.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/AggregateLiteralImpl.java index 087b191c6..082d5cf5d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/AggregateLiteral.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/AggregateLiteralImpl.java @@ -1,37 +1,44 @@ -package at.ac.tuwien.kr.alpha.common.atoms; - -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.commons.literals; import java.util.HashSet; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +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.atoms.AbstractAtom; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; + /** * Copyright (c) 2018, the Alpha Team. */ -public class AggregateLiteral extends Literal { - public AggregateLiteral(AggregateAtom atom, boolean positive) { +class AggregateLiteralImpl extends AbstractLiteral implements AggregateLiteral { + + AggregateLiteralImpl(AggregateAtom atom, boolean positive) { super(atom, positive); } @Override public AggregateAtom getAtom() { - return (AggregateAtom)atom; + return (AggregateAtom) atom; } @Override - public AggregateLiteral negate() { - return new AggregateLiteral(getAtom(), !positive); + public AggregateLiteralImpl negate() { + return new AggregateLiteralImpl(getAtom(), !positive); } /** - * @see Atom#substitute(Substitution) + * @see AbstractAtom#substitute(Substitution) */ @Override - public AggregateLiteral substitute(Substitution substitution) { - return new AggregateLiteral(getAtom().substitute(substitution), positive); + public AggregateLiteralImpl substitute(Substitution substitution) { + //return new AggregateLiteral(getAtom().substitute(substitution), positive); + // TODO either remove substitute method from abstract type or don't extend + throw new UnsupportedOperationException("Cannot substitute AggregateLiteral!"); } @Override @@ -54,7 +61,7 @@ public Set getNonBindingVariables() { } private static VariableTerm boundBindingVariable(ComparisonOperator op, Term bound, boolean positive) { - boolean isNormalizedEquality = op == ComparisonOperator.EQ && positive || op == ComparisonOperator.NE && !positive; + boolean isNormalizedEquality = op == ComparisonOperators.EQ && positive || op == ComparisonOperators.NE && !positive; if (isNormalizedEquality && bound instanceof VariableTerm) { return (VariableTerm) bound; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/BasicLiteral.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/BasicLiteralImpl.java similarity index 73% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/BasicLiteral.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/BasicLiteralImpl.java index c3a078fd8..4f0479d1f 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/BasicLiteral.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/BasicLiteralImpl.java @@ -1,19 +1,19 @@ /** * Copyright (c) 2017-2018, 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 @@ -25,51 +25,55 @@ * 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.common.atoms; - -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.commons.literals; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +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.atoms.AbstractAtom; + /** - * Contains a potentially negated {@link BasicAtom}. - * + * Contains a potentially negated {@link BasicAtomImpl}. + * * Copyright (c) 2017-2018, the Alpha Team. */ -public class BasicLiteral extends Literal { - - public BasicLiteral(BasicAtom atom, boolean positive) { +class BasicLiteralImpl extends AbstractLiteral implements BasicLiteral { + + BasicLiteralImpl(BasicAtom atom, boolean positive) { super(atom, positive); } - + @Override public BasicAtom getAtom() { - return (BasicAtom)atom; + return (BasicAtom) atom; } /** * Returns a new copy of this literal whose {@link Literal#isNegated()} status is inverted */ @Override - public BasicLiteral negate() { - return new BasicLiteral(getAtom(), !positive); + public BasicLiteralImpl negate() { + return new BasicLiteralImpl(getAtom(), !positive); } /** - * @see Atom#substitute(Substitution) + * @see AbstractAtom#substitute(Substitution) */ @Override - public BasicLiteral substitute(Substitution substitution) { - return new BasicLiteral(getAtom().substitute(substitution), positive); + public BasicLiteralImpl substitute(Substitution substitution) { + return new BasicLiteralImpl(getAtom().substitute(substitution), positive); } /** * Set of all variables occurring in the Atom that are potentially binding, i.e., variables in positive atoms. - * + * * @return */ @Override @@ -86,8 +90,9 @@ public Set getBindingVariables() { } /** - * Set of all variables occurring in the Atom that are never binding, not even in positive atoms, e.g., variables in intervals or built-in atoms. - * + * Set of all variables occurring in the Atom that are never binding, not even in positive atoms, e.g., variables in intervals or built-in + * atoms. + * * @return */ @Override diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ComparisonLiteral.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/ComparisonLiteralImpl.java similarity index 74% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ComparisonLiteral.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/ComparisonLiteralImpl.java index d7639e108..cad9d1121 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ComparisonLiteral.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/ComparisonLiteralImpl.java @@ -25,37 +25,46 @@ * 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.common.atoms; +package at.ac.tuwien.kr.alpha.commons.literals; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; -import java.util.*; - -import static at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm.evaluateGroundTerm; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.ComparisonAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm; +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.atoms.AbstractAtom; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; /** - * Contains a potentially negated {@link ComparisonAtom}. + * Contains a potentially negated {@link ComparisonAtomImpl}. */ -public class ComparisonLiteral extends FixedInterpretationLiteral { +class ComparisonLiteralImpl extends AbstractLiteral implements ComparisonLiteral { private final boolean isNormalizedEquality; - public ComparisonLiteral(ComparisonAtom atom, boolean positive) { + ComparisonLiteralImpl(ComparisonAtom atom, boolean positive) { super(atom, positive); - final ComparisonOperator operator = getAtom().operator; - isNormalizedEquality = (positive && operator == ComparisonOperator.EQ) - || (!positive && operator == ComparisonOperator.NE); + final ComparisonOperator operator = getAtom().getOperator(); + isNormalizedEquality = (positive && operator == ComparisonOperators.EQ) + || (!positive && operator == ComparisonOperators.NE); } - + @Override public ComparisonAtom getAtom() { - return (ComparisonAtom)atom; + return (ComparisonAtom) atom; } - + + @Override public boolean isNormalizedEquality() { return isNormalizedEquality; } @@ -64,16 +73,16 @@ public boolean isNormalizedEquality() { * Returns a new copy of this literal whose {@link Literal#isNegated()} status is inverted */ @Override - public ComparisonLiteral negate() { - return new ComparisonLiteral(getAtom(), !positive); + public ComparisonLiteralImpl negate() { + return new ComparisonLiteralImpl(getAtom(), !positive); } /** - * @see Atom#substitute(Substitution) + * @see AbstractAtom#substitute(BasicSubstitution) */ @Override - public ComparisonLiteral substitute(Substitution substitution) { - return new ComparisonLiteral(getAtom().substitute(substitution), positive); + public ComparisonLiteralImpl substitute(Substitution substitution) { + return (ComparisonLiteralImpl) getAtom().substitute(substitution).toLiteral(positive); } private boolean assignable(Term term) { @@ -158,20 +167,21 @@ public List getSatisfyingSubstitutions(Substitution partialSubstit Term resultTerm = null; // Check if the groundTerm is an arithmetic expression and evaluate it if so. if (groundTerm instanceof ArithmeticTerm) { - Integer result = evaluateGroundTerm(groundTerm); + Integer result = Terms.evaluateGroundTerm(groundTerm); if (result == null) { return Collections.emptyList(); } - resultTerm = ConstantTerm.getInstance(result); + resultTerm = Terms.newConstant(result); } else { // Ground term is another term (constant, or function term). resultTerm = groundTerm; } - Substitution extendedSubstitution = new Substitution(partialSubstitution); + BasicSubstitution extendedSubstitution = new BasicSubstitution(partialSubstitution); extendedSubstitution.put(variable, resultTerm); return Collections.singletonList(extendedSubstitution); } - + + @Override public boolean isLeftOrRightAssigning() { final Term left = getTerms().get(0); final Term right = getTerms().get(1); @@ -181,33 +191,20 @@ public boolean isLeftOrRightAssigning() { private Term evaluateTerm(Term term) { // Evaluate arithmetics. if (term instanceof ArithmeticTerm) { - Integer result = ArithmeticTerm.evaluateGroundTerm(term); + Integer result = Terms.evaluateGroundTerm(term); if (result == null) { return null; } - return ConstantTerm.getInstance(result); + return Terms.newConstant(result); } return term; } private boolean compare(Term x, Term y) { - final int comparisonResult = x.compareTo(y); - ComparisonOperator operator = isNegated() ? getAtom().operator.getNegation() : getAtom().operator; - switch (operator) { - case EQ: - return comparisonResult == 0; - case LT: - return comparisonResult < 0; - case GT: - return comparisonResult > 0; - case LE: - return comparisonResult <= 0; - case GE: - return comparisonResult >= 0; - case NE: - return comparisonResult != 0; - default: - throw new UnsupportedOperationException("Unknown comparison operator requested!"); + if (this.isNegated()) { + return getAtom().getOperator().negate().compare(x, y); + } else { + return getAtom().getOperator().compare(x, y); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ExternalLiteral.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/ExternalLiteralImpl.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ExternalLiteral.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/ExternalLiteralImpl.java index 6141d77e5..bcd1b7e0a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/ExternalLiteral.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/ExternalLiteralImpl.java @@ -1,19 +1,19 @@ /** * Copyright (c) 2017-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. - * + * 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 @@ -25,7 +25,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.common.atoms; +package at.ac.tuwien.kr.alpha.commons.literals; import java.util.ArrayList; import java.util.Collections; @@ -33,23 +33,28 @@ import java.util.List; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ExternalLiteral; +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.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.atoms.AbstractAtom; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; /** - * Contains a potentially negated {@link ExternalAtom}. + * Contains a potentially negated {@link ExternalAtomImpl}. */ -public class ExternalLiteral extends FixedInterpretationLiteral { +class ExternalLiteralImpl extends AbstractLiteral implements ExternalLiteral { - public ExternalLiteral(ExternalAtom atom, boolean positive) { + ExternalLiteralImpl(ExternalAtom atom, boolean positive) { super(atom, positive); } @Override public ExternalAtom getAtom() { - return (ExternalAtom) atom; + return (ExternalAtom) super.getAtom(); } /** @@ -57,16 +62,16 @@ public ExternalAtom getAtom() { * is inverted */ @Override - public ExternalLiteral negate() { - return new ExternalLiteral(getAtom(), !positive); + public ExternalLiteralImpl negate() { + return new ExternalLiteralImpl(getAtom(), this.isNegated()); } /** - * @see Atom#substitute(Substitution) + * @see AbstractAtom#substitute(BasicSubstitution) */ @Override - public ExternalLiteral substitute(Substitution substitution) { - return new ExternalLiteral(getAtom().substitute(substitution), positive); + public ExternalLiteralImpl substitute(Substitution substitution) { + return new ExternalLiteralImpl((ExternalAtom) getAtom().substitute(substitution), !this.isNegated()); } @Override @@ -75,7 +80,7 @@ public Set getBindingVariables() { // and there are no binding variables (like for ordinary atoms). // If the external atom is positive, then variables of output are binding. - if (!positive) { + if (this.isNegated()) { return Collections.emptySet(); } @@ -106,7 +111,7 @@ public Set getNonBindingVariables() { // If the external atom is negative, then all variables of input and output are // non-binding. - if (!positive) { + if (this.isNegated()) { for (Term out : output) { if (out instanceof VariableTerm) { nonbindingVariables.add((VariableTerm) out); @@ -141,7 +146,7 @@ public List getSatisfyingSubstitutions(Substitution partialSubstit /** * Checks whether this negated external literal is satisfied. - * + * * Note that this method must only be called on negated external literals. * In that case, the literal itself does not bind any output variables, * i.e. the underlying atom is satisfied iff the output terms obtained by @@ -154,9 +159,9 @@ public List getSatisfyingSubstitutions(Substitution partialSubstit * substitution has already been applied to them. That assumption is safe since * in case of a negated external literal, the output variables are always * non-binding. - * + * * @param externalMethodResult The term lists obtained from evaluating the external atom - * (i.e. calling the java method) encapsulated by this literal + * (i.e. calling the java method) encapsulated by this literal * @return true iff no list in externalMethodResult equals the external atom's output term * list as substituted by the grounder, false otherwise */ @@ -191,7 +196,7 @@ private List buildSubstitutionsForOutputs(Substitution partialSubs "Predicate " + getPredicate().getName() + " returned " + bindings.size() + " terms when at least " + externalAtomOutputTerms.size() + " were expected."); } - Substitution ith = new Substitution(partialSubstitution); + BasicSubstitution ith = new BasicSubstitution(partialSubstitution); boolean skip = false; for (int i = 0; i < externalAtomOutputTerms.size(); i++) { Term out = externalAtomOutputTerms.get(i); diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/Literals.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/Literals.java new file mode 100644 index 000000000..a7ec8a770 --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/literals/Literals.java @@ -0,0 +1,38 @@ +package at.ac.tuwien.kr.alpha.commons.literals; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +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.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.ExternalLiteral; + +public final class Literals { + + private Literals() { + throw new AssertionError("Cannot instantiate utility class"); + } + + public static BasicLiteral fromAtom(BasicAtom atom, boolean positive) { + return new BasicLiteralImpl(atom, positive); + } + + public static AggregateLiteral fromAtom(AggregateAtom atom, boolean positive) { + return new AggregateLiteralImpl(atom, positive); + } + + public static ComparisonLiteral fromAtom(ComparisonAtom atom, boolean positive) { + return new ComparisonLiteralImpl(atom, positive); + } + + public static ExternalLiteral fromAtom(ExternalAtom atom, boolean positive) { + return new ExternalLiteralImpl(atom, positive); + } + + public static ComparisonLiteral newComparisonLiteral(ComparisonAtom atom, boolean positive) { + return new ComparisonLiteralImpl(atom, positive); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/ChoiceHead.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/ChoiceHeadImpl.java similarity index 71% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/ChoiceHead.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/ChoiceHeadImpl.java index 46620fce1..7c81d7357 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/ChoiceHead.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/ChoiceHeadImpl.java @@ -1,20 +1,22 @@ -package at.ac.tuwien.kr.alpha.common.rule.head; +package at.ac.tuwien.kr.alpha.commons.rules.heads; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import static at.ac.tuwien.kr.alpha.commons.util.Util.join; import java.util.List; -import static at.ac.tuwien.kr.alpha.Util.join; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead; +import at.ac.tuwien.kr.alpha.api.terms.Term; /** * Represents the head of a choice rule. * - * Copyright (c) 2017-2019, the Alpha Team. + * Copyright (c) 2017-2021, the Alpha Team. */ -public class ChoiceHead extends Head { +class ChoiceHeadImpl implements ChoiceHead { + private final List choiceElements; private final Term lowerBound; @@ -23,11 +25,11 @@ public class ChoiceHead extends Head { private final Term upperBound; private final ComparisonOperator upperOp; - public static class ChoiceElement { - public final Atom choiceAtom; + static class ChoiceElementImpl implements ChoiceElement { + public final BasicAtom choiceAtom; public final List conditionLiterals; - public ChoiceElement(Atom choiceAtom, List conditionLiterals) { + public ChoiceElementImpl(BasicAtom choiceAtom, List conditionLiterals) { this.choiceAtom = choiceAtom; this.conditionLiterals = conditionLiterals; } @@ -42,29 +44,45 @@ public String toString() { return join(result + " : ", conditionLiterals, ""); } + + @Override + public BasicAtom getChoiceAtom() { + return choiceAtom; + } + + @Override + public List getConditionLiterals() { + return conditionLiterals; + } } + @Override public ComparisonOperator getLowerOperator() { return lowerOp; } + @Override public ComparisonOperator getUpperOperator() { return upperOp; } + @Override public List getChoiceElements() { return choiceElements; } + @Override public Term getLowerBound() { return lowerBound; } + @Override public Term getUpperBound() { return upperBound; } - public ChoiceHead(List choiceElements, Term lowerBound, ComparisonOperator lowerOp, Term upperBound, ComparisonOperator upperOp) { + ChoiceHeadImpl(List choiceElements, Term lowerBound, ComparisonOperator lowerOp, Term upperBound, + ComparisonOperator upperOp) { this.choiceElements = choiceElements; this.lowerBound = lowerBound; this.lowerOp = lowerOp; @@ -109,10 +127,10 @@ public boolean equals(Object obj) { if (obj == null) { return false; } - if (!(obj instanceof ChoiceHead)) { + if (!(obj instanceof ChoiceHeadImpl)) { return false; } - ChoiceHead other = (ChoiceHead) obj; + ChoiceHeadImpl other = (ChoiceHeadImpl) obj; if (this.choiceElements == null) { if (other.choiceElements != null) { return false; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/DisjunctiveHead.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/DisjunctiveHeadImpl.java similarity index 69% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/DisjunctiveHead.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/DisjunctiveHeadImpl.java index 11f0e365d..bc33e8f17 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/DisjunctiveHead.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/DisjunctiveHeadImpl.java @@ -1,18 +1,20 @@ -package at.ac.tuwien.kr.alpha.common.rule.head; +package at.ac.tuwien.kr.alpha.commons.rules.heads; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; +import static at.ac.tuwien.kr.alpha.commons.util.Util.join; import java.util.List; -import static at.ac.tuwien.kr.alpha.Util.join; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.rules.heads.DisjunctiveHead; /** * Copyright (c) 2017, the Alpha Team. */ -public class DisjunctiveHead extends Head { - public final List disjunctiveAtoms; +class DisjunctiveHeadImpl implements DisjunctiveHead { + + final List disjunctiveAtoms; - public DisjunctiveHead(List disjunctiveAtoms) { + DisjunctiveHeadImpl(List disjunctiveAtoms) { this.disjunctiveAtoms = disjunctiveAtoms; if (disjunctiveAtoms != null && disjunctiveAtoms.size() > 1) { throw new UnsupportedOperationException("Disjunction in rule heads is not yet supported"); @@ -49,10 +51,10 @@ public boolean equals(Object obj) { if (obj == null) { return false; } - if (!(obj instanceof DisjunctiveHead)) { + if (!(obj instanceof DisjunctiveHeadImpl)) { return false; } - DisjunctiveHead other = (DisjunctiveHead) obj; + DisjunctiveHeadImpl other = (DisjunctiveHeadImpl) obj; if (this.disjunctiveAtoms == null) { if (other.disjunctiveAtoms != null) { return false; diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/Heads.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/Heads.java new file mode 100644 index 000000000..9e529a7e7 --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/Heads.java @@ -0,0 +1,33 @@ +package at.ac.tuwien.kr.alpha.commons.rules.heads; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead.ChoiceElement; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.rules.heads.ChoiceHeadImpl.ChoiceElementImpl; + +public final class Heads { + + private Heads() { + throw new AssertionError("Cannot instantiate utility class"); + } + + public static NormalHead newNormalHead(BasicAtom atom) { + return new NormalHeadImpl(atom); + } + + public static ChoiceHead newChoiceHead(List choiceElements, Term lowerBound, ComparisonOperator lowerOp, Term upperBound, + ComparisonOperator upperOp) { + return new ChoiceHeadImpl(choiceElements, lowerBound, lowerOp, upperBound, upperOp); + } + + public static ChoiceElement newChoiceElement(BasicAtom choiceAtom, List conditionLiterals) { + return new ChoiceElementImpl(choiceAtom, conditionLiterals); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/NormalHead.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/NormalHeadImpl.java similarity index 67% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/NormalHead.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/NormalHeadImpl.java index cb88e8229..2cdfc4404 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/NormalHead.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/rules/heads/NormalHeadImpl.java @@ -1,25 +1,28 @@ -package at.ac.tuwien.kr.alpha.common.rule.head; +package at.ac.tuwien.kr.alpha.commons.rules.heads; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; /** * Represents a normal head, i.e., a head that is an Atom. * Copyright (c) 2019, the Alpha Team. */ -public class NormalHead extends Head { +class NormalHeadImpl implements NormalHead { - private final Atom atom; + private final BasicAtom atom; - public NormalHead(Atom atom) { + NormalHeadImpl(BasicAtom atom) { this.atom = atom; } // Note that at some point in the future it might make sense to have this method directly in Head + @Override public boolean isGround() { return atom.isGround(); } - public Atom getAtom() { + @Override + public BasicAtom getAtom() { return atom; } @@ -44,10 +47,10 @@ public boolean equals(Object obj) { if (obj == null) { return false; } - if (!(obj instanceof NormalHead)) { + if (!(obj instanceof NormalHeadImpl)) { return false; } - NormalHead other = (NormalHead) obj; + NormalHeadImpl other = (NormalHeadImpl) obj; if (this.atom == null) { if (other.atom != null) { return false; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Substitution.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/BasicSubstitution.java similarity index 77% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/Substitution.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/BasicSubstitution.java index c90bb4846..df8d26d6a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Substitution.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/BasicSubstitution.java @@ -25,15 +25,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.grounder; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramPartParser; +package at.ac.tuwien.kr.alpha.commons.substitutions; import java.util.List; import java.util.Map; @@ -41,33 +33,39 @@ import java.util.Set; import java.util.TreeMap; -import static at.ac.tuwien.kr.alpha.Util.oops; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +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.api.terms.FunctionTerm; +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.util.Util; -public class Substitution { +public class BasicSubstitution implements at.ac.tuwien.kr.alpha.api.grounder.Substitution { - private static final ProgramPartParser PROGRAM_PART_PARSER = new ProgramPartParser(); - public static final Substitution EMPTY_SUBSTITUTION = new Substitution() { + public static final Substitution EMPTY_SUBSTITUTION = new BasicSubstitution() { @Override public > Term put(VariableTerm variableTerm, Term groundTerm) { - throw oops("Should not be called on EMPTY_SUBSTITUTION"); + throw Util.oops("Should not be called on EMPTY_SUBSTITUTION"); } }; protected TreeMap substitution; - private Substitution(TreeMap substitution) { + private BasicSubstitution(TreeMap substitution) { if (substitution == null) { - throw oops("Substitution is null."); + throw Util.oops("Substitution is null."); } this.substitution = substitution; } - public Substitution() { + public BasicSubstitution() { this(new TreeMap<>()); } - public Substitution(Substitution clone) { - this(new TreeMap<>(clone.substitution)); + public BasicSubstitution(Substitution clone) { + this(new TreeMap<>(clone.getSubstitution())); } public static Substitution specializeSubstitution(Literal literal, Instance instance, Substitution substitution) { @@ -78,7 +76,8 @@ public static Substitution specializeSubstitution(Literal literal, Instance inst * Helper class to lazily clone the input substitution of Substitution.specializeSubstitution only when needed. */ private static class SpecializationHelper { - Substitution updatedSubstitution; // Is null for as long as the given partial substitution is not extended, afterwards holds the updated/extended/specialized substitution. + Substitution updatedSubstitution; // Is null for as long as the given partial substitution is not extended, afterwards holds the + // updated/extended/specialized substitution. Substitution unify(List termList, Instance instance, Substitution partialSubstitution) { for (int i = 0; i < termList.size(); i++) { @@ -104,7 +103,11 @@ boolean unifyTerms(Term termNonGround, Term termGround, Substitution partialSubs VariableTerm variableTerm = (VariableTerm) termNonGround; // Left term is variable, bind it to the right term. Use original substitution if it has // not been cloned yet. - Term bound = (updatedSubstitution == null ? partialSubstitution : updatedSubstitution).eval(variableTerm); // Get variable binding, either from input substitution if it has not been updated yet, or from the cloned/updated substitution. + Term bound = (updatedSubstitution == null ? partialSubstitution : updatedSubstitution).eval(variableTerm); // Get variable binding, either + // from input substitution if it + // has not been updated yet, or + // from the cloned/updated + // substitution. if (bound != null) { // Variable is already bound, return true if binding is the same as the current ground term. return termGround == bound; @@ -112,7 +115,7 @@ boolean unifyTerms(Term termNonGround, Term termGround, Substitution partialSubs // Record new variable binding. if (updatedSubstitution == null) { // Clone substitution if it was not yet updated. - updatedSubstitution = new Substitution(partialSubstitution); + updatedSubstitution = new BasicSubstitution(partialSubstitution); } updatedSubstitution.put(variableTerm, termGround); return true; @@ -152,30 +155,33 @@ boolean unifyTerms(Term termNonGround, Term termGround, Substitution partialSubs * @param instance the ground instance to unify the atom with. * @param substitution the (partial) substitution for the atom. This is left unchanged in all cases. * @return null if the unification/specialization fails, otherwise it is a unifying substitution. If the - * parameter substitution already is a unifier, it is returned. If the unifying substitution is an - * extension of the input substitution, a new substitution will be returned. + * parameter substitution already is a unifier, it is returned. If the unifying substitution is an + * extension of the input substitution, a new substitution will be returned. */ public static Substitution specializeSubstitution(Atom atom, Instance instance, Substitution substitution) { return new SpecializationHelper().unify(atom.getTerms(), instance, substitution); } /** - * This method should be used to obtain the {@link Term} to be used in place of a given {@link VariableTerm} under this substitution. + * This method should be used to obtain the {@link AbstractTerm} to be used in place of a given {@link VariableTermImpl} under this + * substitution. * * @param variableTerm the variable term to substitute, if possible * @return a constant term if the substitution contains the given variable, {@code null} otherwise. */ + @Override public Term eval(VariableTerm variableTerm) { return this.substitution.get(variableTerm); } + @Override public > Term put(VariableTerm variableTerm, Term groundTerm) { if (!groundTerm.isGround()) { - throw oops("Right-hand term is not ground."); + throw Util.oops("Right-hand term is not ground."); } Term alreadyAssigned = substitution.get(variableTerm); if (alreadyAssigned != null && alreadyAssigned != groundTerm) { - throw oops("Variable is already assigned to another term."); + throw Util.oops("Variable is already assigned to another term."); } // Note: We're destroying type information here. return substitution.put(variableTerm, groundTerm); @@ -185,6 +191,7 @@ public boolean isEmpty() { return substitution.isEmpty(); } + @Override public boolean isVariableSet(VariableTerm variable) { return substitution.get(variable) != null; } @@ -214,19 +221,6 @@ public String toString() { return ret.toString(); } - public static Substitution fromString(String substitution) { - String bare = substitution.substring(1, substitution.length() - 1); - String[] assignments = bare.split(","); - Substitution ret = new Substitution(); - for (String assignment : assignments) { - String[] keyVal = assignment.split("->"); - VariableTerm variable = VariableTerm.getInstance(keyVal[0]); - Term assignedTerm = PROGRAM_PART_PARSER.parseTerm(keyVal[1]); - ret.put(variable, assignedTerm); - } - return ret; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -236,7 +230,7 @@ public boolean equals(Object o) { return false; } - Substitution that = (Substitution) o; + BasicSubstitution that = (BasicSubstitution) o; return Objects.equals(substitution, that.substitution); } @@ -245,4 +239,11 @@ public boolean equals(Object o) { public int hashCode() { return substitution != null ? substitution.hashCode() : 0; } + + + @Override + public TreeMap getSubstitution() { + return this.substitution; + } + } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Instance.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/Instance.java similarity index 76% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/Instance.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/Instance.java index 480d58d80..aa707ff36 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Instance.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/Instance.java @@ -1,19 +1,20 @@ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.commons.substitutions; -import static at.ac.tuwien.kr.alpha.Util.join; +import static at.ac.tuwien.kr.alpha.commons.util.Util.join; import java.util.Arrays; import java.util.List; -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.Term; +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.util.Util; /** * An instance is a positional association of terms, e.g., representing a variable substitution, or a ground instance of * a predicate. * Copyright (c) 2016, the Alpha Team. */ +// TODO probably shouldn't be published API public class Instance { public final List terms; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Unifier.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/Unifier.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/Unifier.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/Unifier.java index 7b5bf3e09..06033cf51 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Unifier.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/substitutions/Unifier.java @@ -1,6 +1,6 @@ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.commons.substitutions; -import static at.ac.tuwien.kr.alpha.Util.oops; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.ArrayList; import java.util.HashSet; @@ -9,15 +9,16 @@ import java.util.Set; import java.util.TreeMap; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; /** * A variable substitution allowing variables to occur on the right-hand side. Chains of variable substitutions are * resolved automatically, i.e., adding the substitutions {@literal (X -> A)} and {@literal (A -> d)} results in {@literal (X -> d)}, {@literal (A -> d)}. * Copyright (c) 2018-2020, the Alpha Team. */ -public class Unifier extends Substitution { +public class Unifier extends BasicSubstitution { private final TreeMap> rightHandVariableOccurrences; @@ -38,11 +39,10 @@ public Unifier(Unifier clone) { } public Unifier(Substitution clone) { - this(new TreeMap<>(clone.substitution), new TreeMap<>()); + this(new TreeMap<>(clone.getSubstitution()), new TreeMap<>()); } - - public Unifier extendWith(Substitution extension) { + public Unifier extendWith(BasicSubstitution extension) { for (Map.Entry extensionVariable : extension.substitution.entrySet()) { this.put(extensionVariable.getKey(), extensionVariable.getValue()); } @@ -50,7 +50,9 @@ public Unifier extendWith(Substitution extension) { } /** - * Returns a list of all variables occurring in that unifier, i.e., variables that are mapped and those that occur (nested) in the right-hand side of the unifier. + * Returns a list of all variables occurring in that unifier, i.e., variables that are mapped and those that occur (nested) in the + * right-hand side of the unifier. + * * @return the list of variables occurring somewhere in the unifier. */ @Override @@ -63,7 +65,6 @@ public Set getMappedVariables() { return ret; } - @Override public > Term put(VariableTerm variableTerm, Term term) { // If term is not ground, store it for right-hand side reverse-lookup. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/Term.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/AbstractTerm.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/common/terms/Term.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/AbstractTerm.java index 490fb46b8..5db258d85 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/Term.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/AbstractTerm.java @@ -1,10 +1,14 @@ -package at.ac.tuwien.kr.alpha.common.terms; +package at.ac.tuwien.kr.alpha.commons.terms; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.Map; +import java.util.Set; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +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.FunctionTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; //@formatter:off /** @@ -31,10 +35,10 @@ * Copyright (c) 2016-2020, the Alpha Team. */ //@formatter:on -public abstract class Term implements Comparable { - public abstract boolean isGround(); +abstract class AbstractTerm implements Term { - public abstract List getOccurringVariables(); + @Override + public abstract Set getOccurringVariables(); /** * Applies a substitution, result may be nonground. @@ -42,15 +46,15 @@ public abstract class Term implements Comparable { * @param substitution the variable substitution to apply. * @return the non-substitute term where all variable substitutions have been applied. */ + @Override public abstract Term substitute(Substitution substitution); private static int priority(Term term) { - final Class clazz = term.getClass(); - if (clazz.equals(ConstantTerm.class)) { + if (term instanceof ConstantTerm) { return 1; - } else if (clazz.equals(FunctionTerm.class)) { + } else if (term instanceof FunctionTerm) { return 2; - } else if (clazz.equals(VariableTerm.class)) { + } else if (term instanceof VariableTerm) { return 3; } throw new UnsupportedOperationException("Can only compare constant term, function terms and variable terms among each other."); @@ -61,33 +65,42 @@ public int compareTo(Term o) { return o == null ? 1 : Integer.compare(priority(this), priority(o)); } + @Override + public abstract boolean isGround(); + /** * Rename all variables occurring in this Term by prefixing their name. * * @param renamePrefix the name to prefix all occurring variables. * @return the term with all variables renamed. */ + @Override public abstract Term renameVariables(String renamePrefix); - public abstract Term normalizeVariables(String renamePrefix, RenameCounter counter); + @Override + public abstract Term normalizeVariables(String renamePrefix, Term.RenameCounter counter); - public static class RenameCounter { + public static class RenameCounterImpl implements Term.RenameCounter { int counter; final HashMap renamedVariables; - public RenameCounter(int startingValue) { + public RenameCounterImpl(int startingValue) { counter = startingValue; renamedVariables = new HashMap<>(); } - } - - public static List renameTerms(List terms, String prefix, int counterStartingValue) { - List renamedTerms = new ArrayList<>(terms.size()); - Term.RenameCounter renameCounter = new Term.RenameCounter(counterStartingValue); - for (Term term : terms) { - renamedTerms.add(term.normalizeVariables(prefix, renameCounter)); + + @Override + public Map getRenamedVariables() { + return renamedVariables; + } + + @Override + public int getAndIncrement() { + int retVal = counter; + counter++; + return retVal; } - return renamedTerms; + } @Override diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/ArithmeticTerm.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/ArithmeticTermImpl.java similarity index 58% rename from src/main/java/at/ac/tuwien/kr/alpha/common/terms/ArithmeticTerm.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/ArithmeticTermImpl.java index eb8a62e16..fd2b780aa 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/ArithmeticTerm.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/ArithmeticTermImpl.java @@ -25,40 +25,41 @@ * 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.common.terms; +package at.ac.tuwien.kr.alpha.commons.terms; -import com.google.common.math.IntMath; - -import java.util.ArrayList; import java.util.LinkedHashSet; -import java.util.List; +import java.util.Set; -import at.ac.tuwien.kr.alpha.common.Interner; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticOperator; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm; +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.util.Interner; /** * This class represents an arithmetic expression occurring as a term. * Copyright (c) 2017-2019, the Alpha Team. */ -public class ArithmeticTerm extends Term { - private static final Interner INTERNER = new Interner<>(); +class ArithmeticTermImpl extends AbstractTerm implements ArithmeticTerm { + private static final Interner INTERNER = new Interner<>(); protected final Term left; private final ArithmeticOperator arithmeticOperator; private final Term right; - private ArithmeticTerm(Term left, ArithmeticOperator arithmeticOperator, Term right) { + private ArithmeticTermImpl(Term left, ArithmeticOperator arithmeticOperator, Term right) { this.left = left; this.arithmeticOperator = arithmeticOperator; this.right = right; } - public static Term getInstance(Term left, ArithmeticOperator arithmeticOperator, Term right) { + static Term getInstance(Term left, ArithmeticOperator arithmeticOperator, Term right) { // Evaluate ground arithmetic terms immediately and return result. if (left.isGround() && right.isGround()) { - Integer result = new ArithmeticTerm(left, arithmeticOperator, right).evaluateExpression(); - return ConstantTerm.getInstance(result); + Integer result = new ArithmeticTermImpl(left, arithmeticOperator, right).evaluateExpression(); + return ConstantTermImpl.getInstance(result); } - return INTERNER.intern(new ArithmeticTerm(left, arithmeticOperator, right)); + return INTERNER.intern(new ArithmeticTermImpl(left, arithmeticOperator, right)); } @Override @@ -67,10 +68,10 @@ public boolean isGround() { } @Override - public List getOccurringVariables() { + public Set getOccurringVariables() { LinkedHashSet occurringVariables = new LinkedHashSet<>(left.getOccurringVariables()); occurringVariables.addAll(right.getOccurringVariables()); - return new ArrayList<>(occurringVariables); + return occurringVariables; } @Override @@ -84,41 +85,11 @@ public Term renameVariables(String renamePrefix) { } @Override - public Term normalizeVariables(String renamePrefix, RenameCounter counter) { + public Term normalizeVariables(String renamePrefix, Term.RenameCounter counter) { Term normalizedLeft = left.normalizeVariables(renamePrefix, counter); Term normalizedRight = right.normalizeVariables(renamePrefix, counter); - return ArithmeticTerm.getInstance(normalizedLeft, arithmeticOperator, normalizedRight); - - } - - public static Integer evaluateGroundTerm(Term term) { - if (!term.isGround()) { - throw new RuntimeException("Cannot evaluate arithmetic term since it is not ground: " + term); - } - return evaluateGroundTermHelper(term); - } - - private static Integer evaluateGroundTermHelper(Term term) { - if (term instanceof ConstantTerm - && ((ConstantTerm) term).getObject() instanceof Integer) { - // Extract integer from the constant. - return (Integer) ((ConstantTerm) term).getObject(); - } else if (term instanceof ArithmeticTerm) { - return ((ArithmeticTerm) term).evaluateExpression(); - } else { - // ASP Core 2 standard allows non-integer terms in arithmetic expressions, result is to simply ignore the ground - // instance. - return null; - } - } + return ArithmeticTermImpl.getInstance(normalizedLeft, arithmeticOperator, normalizedRight); - Integer evaluateExpression() { - Integer leftInt = evaluateGroundTermHelper(left); - Integer rightInt = evaluateGroundTermHelper(right); - if (leftInt == null || rightInt == null) { - return null; - } - return arithmeticOperator.eval(leftInt, rightInt); } @Override @@ -135,7 +106,7 @@ public boolean equals(Object o) { return false; } - ArithmeticTerm that = (ArithmeticTerm) o; + ArithmeticTermImpl that = (ArithmeticTermImpl) o; if (left != that.left) { return false; @@ -150,80 +121,51 @@ public boolean equals(Object o) { public int hashCode() { return 31 * (31 * left.hashCode() + arithmeticOperator.hashCode()) + right.hashCode(); } - - public Term getLeft() { - return left; - } - - public ArithmeticOperator getArithmeticOperator() { + + @Override + public ArithmeticOperator getOperator() { return arithmeticOperator; } - - public Term getRight() { + + @Override + public Term getLeftOperand() { + return left; + } + + @Override + public Term getRightOperand() { return right; } - public enum ArithmeticOperator { - PLUS("+"), - MINUS("-"), - TIMES("*"), - DIV("/"), - POWER("**"), - MODULO("\\"), - BITXOR("^"); - - private String asString; - - ArithmeticOperator(String asString) { - this.asString = asString; - } - - @Override - public String toString() { - return asString; - } - - public Integer eval(Integer left, Integer right) { - switch (this) { - case PLUS: - return left + right; - case MINUS: - return left - right; - case TIMES: - return left * right; - case DIV: - return left / right; - case POWER: - return IntMath.checkedPow(left, right); - case MODULO: - return left % right; - case BITXOR: - return left ^ right; - default: - throw new RuntimeException("Unknown arithmetic operator encountered."); - - } + @Override + public Integer evaluateExpression() { + Integer leftInt = Terms.evaluateGroundTermHelper(left); + Integer rightInt = Terms.evaluateGroundTermHelper(right); + if (leftInt == null || rightInt == null) { + return null; } + return arithmeticOperator.eval(leftInt, rightInt); } - - public static class MinusTerm extends ArithmeticTerm { + + // Note: It doesn't seem like this class is really needed, could be handled by an if in ArithmeticTermImpl#getInstance. + public static class MinusTerm extends ArithmeticTermImpl { private MinusTerm(Term term) { super(term, null, null); } - public static Term getInstance(Term term) { + static Term getInstance(Term term) { // Evaluate ground arithmetic terms immediately and return result. if (term.isGround()) { - Integer result = evaluateGroundTermHelper(term) * -1; - return ConstantTerm.getInstance(result); + Integer result = Terms.evaluateGroundTerm(term) * -1; + return ConstantTermImpl.getInstance(result); } return INTERNER.intern(new MinusTerm(term)); } @Override - Integer evaluateExpression() { - return evaluateGroundTermHelper(left) * -1; + public Integer evaluateExpression() { + return Terms.evaluateGroundTermHelper(left) * -1; } @Override @@ -232,7 +174,7 @@ public boolean isGround() { } @Override - public List getOccurringVariables() { + public Set getOccurringVariables() { return left.getOccurringVariables(); } @@ -247,7 +189,7 @@ public Term renameVariables(String renamePrefix) { } @Override - public Term normalizeVariables(String renamePrefix, RenameCounter counter) { + public Term normalizeVariables(String renamePrefix, Term.RenameCounter counter) { Term normalizedLeft = left.normalizeVariables(renamePrefix, counter); return MinusTerm.getInstance(normalizedLeft); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/ConstantTerm.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/ConstantTermImpl.java similarity index 67% rename from src/main/java/at/ac/tuwien/kr/alpha/common/terms/ConstantTerm.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/ConstantTermImpl.java index 98e035e16..4dcaec598 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/ConstantTerm.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/ConstantTermImpl.java @@ -1,33 +1,36 @@ -package at.ac.tuwien.kr.alpha.common.terms; - -import at.ac.tuwien.kr.alpha.common.Interner; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.commons.terms; import java.util.Collections; -import java.util.List; +import java.util.Set; + +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.util.Interner; /** * Copyright (c) 2016-2020, the Alpha Team. */ -public class ConstantTerm> extends Term { - private static final Interner> INTERNER = new Interner<>(); +class ConstantTermImpl> extends AbstractTerm implements ConstantTerm { + private static final Interner> INTERNER = new Interner<>(); private final T object; private final boolean symbolic; - private ConstantTerm(T object, boolean symbolic) { + private ConstantTermImpl(T object, boolean symbolic) { this.object = object; this.symbolic = symbolic; } @SuppressWarnings("unchecked") - public static > ConstantTerm getInstance(T symbol) { - return (ConstantTerm) INTERNER.intern(new ConstantTerm<>(symbol, false)); + public static > ConstantTermImpl getInstance(T symbol) { + return (ConstantTermImpl) INTERNER.intern(new ConstantTermImpl<>(symbol, false)); } @SuppressWarnings("unchecked") - public static > ConstantTerm getSymbolicInstance(String symbol) { - return (ConstantTerm) INTERNER.intern(new ConstantTerm<>(symbol, true)); + public static > ConstantTermImpl getSymbolicInstance(String symbol) { + return (ConstantTermImpl) INTERNER.intern(new ConstantTermImpl<>(symbol, true)); } @Override @@ -36,8 +39,8 @@ public boolean isGround() { } @Override - public List getOccurringVariables() { - return Collections.emptyList(); + public Set getOccurringVariables() { + return Collections.emptySet(); } @Override @@ -67,7 +70,7 @@ public boolean equals(Object o) { return false; } - ConstantTerm that = (ConstantTerm) o; + ConstantTermImpl that = (ConstantTermImpl) o; if (this.symbolic != that.symbolic) { return false; } @@ -86,7 +89,7 @@ public int hashCode() { * Establishes "priority" for ordering of constant terms depending on the type * of the corresponding object according to ASP-Core-2.03c. */ - private static final int priority(final Class clazz, ConstantTerm term) { + private static final int priority(final Class clazz, ConstantTermImpl term) { if (clazz.equals(Integer.class)) { return 1; } else if (clazz.equals(String.class)) { @@ -102,11 +105,11 @@ public int compareTo(Term o) { return 0; } - if (!(o instanceof ConstantTerm)) { + if (!(o instanceof ConstantTermImpl)) { return super.compareTo(o); } - ConstantTerm other = (ConstantTerm) o; + ConstantTermImpl other = (ConstantTermImpl) o; // We will perform an unchecked cast. // Because of type erasure, we cannot know the exact type @@ -138,20 +141,22 @@ public int compareTo(Term o) { } @Override - public Term renameVariables(String renamePrefix) { + public AbstractTerm renameVariables(String renamePrefix) { // Constant contains no variables, hence stays the same. return this; } @Override - public Term normalizeVariables(String renamePrefix, RenameCounter counter) { + public AbstractTerm normalizeVariables(String renamePrefix, Term.RenameCounter counter) { return this; } + @Override public T getObject() { return object; } + @Override public boolean isSymbolic() { return this.symbolic; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/FunctionTerm.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/FunctionTermImpl.java similarity index 56% rename from src/main/java/at/ac/tuwien/kr/alpha/common/terms/FunctionTerm.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/FunctionTermImpl.java index 9e3847ac4..14b8535de 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/FunctionTerm.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/FunctionTermImpl.java @@ -1,23 +1,30 @@ -package at.ac.tuwien.kr.alpha.common.terms; - -import at.ac.tuwien.kr.alpha.common.Interner; -import at.ac.tuwien.kr.alpha.grounder.Substitution; - -import java.util.*; - -import static at.ac.tuwien.kr.alpha.Util.join; +package at.ac.tuwien.kr.alpha.commons.terms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.util.Interner; +import at.ac.tuwien.kr.alpha.commons.util.Util; /** * Copyright (c) 2016-2017, the Alpha Team. */ -public class FunctionTerm extends Term { - private static final Interner INTERNER = new Interner<>(); +class FunctionTermImpl extends AbstractTerm implements FunctionTerm { + private static final Interner INTERNER = new Interner<>(); private final String symbol; private final List terms; private final boolean ground; - private FunctionTerm(String symbol, List terms) { + private FunctionTermImpl(String symbol, List terms) { if (symbol == null) { throw new IllegalArgumentException(); } @@ -35,18 +42,20 @@ private FunctionTerm(String symbol, List terms) { this.ground = ground; } - public static FunctionTerm getInstance(String functionSymbol, List termList) { - return INTERNER.intern(new FunctionTerm(functionSymbol, termList)); + public static FunctionTermImpl getInstance(String functionSymbol, List termList) { + return INTERNER.intern(new FunctionTermImpl(functionSymbol, termList)); } - public static FunctionTerm getInstance(String functionSymbol, Term... terms) { + public static FunctionTermImpl getInstance(String functionSymbol, Term... terms) { return getInstance(functionSymbol, Arrays.asList(terms)); } + @Override public List getTerms() { return terms; } + @Override public String getSymbol() { return symbol; } @@ -57,8 +66,8 @@ public boolean isGround() { } @Override - public List getOccurringVariables() { - LinkedList vars = new LinkedList<>(); + public Set getOccurringVariables() { + Set vars = new LinkedHashSet<>(); for (Term term : terms) { vars.addAll(term.getOccurringVariables()); } @@ -66,12 +75,12 @@ public List getOccurringVariables() { } @Override - public FunctionTerm substitute(Substitution substitution) { + public FunctionTermImpl substitute(Substitution substitution) { List groundTermList = new ArrayList<>(terms.size()); for (Term term : terms) { groundTermList.add(term.substitute(substitution)); } - return FunctionTerm.getInstance(symbol, groundTermList); + return FunctionTermImpl.getInstance(symbol, groundTermList); } @Override @@ -80,7 +89,7 @@ public String toString() { return symbol; } - return join(symbol + "(", terms, ")"); + return Util.join(symbol + "(", terms, ")"); } @Override @@ -92,7 +101,7 @@ public boolean equals(Object o) { return false; } - FunctionTerm that = (FunctionTerm) o; + FunctionTermImpl that = (FunctionTermImpl) o; if (!symbol.equals(that.symbol)) { return false; @@ -111,11 +120,11 @@ public int compareTo(Term o) { return 0; } - if (!(o instanceof FunctionTerm)) { + if (!(o instanceof FunctionTermImpl)) { return super.compareTo(o); } - FunctionTerm other = (FunctionTerm)o; + FunctionTermImpl other = (FunctionTermImpl) o; if (terms.size() != other.terms.size()) { return terms.size() - other.terms.size(); @@ -139,19 +148,19 @@ public int compareTo(Term o) { @Override public Term renameVariables(String renamePrefix) { - ArrayList renamedTerms = new ArrayList<>(terms.size()); + List renamedTerms = new ArrayList<>(terms.size()); for (Term term : terms) { renamedTerms.add(term.renameVariables(renamePrefix)); } - return FunctionTerm.getInstance(symbol, renamedTerms); + return FunctionTermImpl.getInstance(symbol, renamedTerms); } @Override - public Term normalizeVariables(String renamePrefix, RenameCounter counter) { + public Term normalizeVariables(String renamePrefix, Term.RenameCounter counter) { List normalizedTerms = new ArrayList<>(terms.size()); for (Term term : terms) { normalizedTerms.add(term.normalizeVariables(renamePrefix, counter)); } - return FunctionTerm.getInstance(symbol, normalizedTerms); + return FunctionTermImpl.getInstance(symbol, normalizedTerms); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/IntervalTerm.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/IntervalTerm.java similarity index 76% rename from src/main/java/at/ac/tuwien/kr/alpha/common/terms/IntervalTerm.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/IntervalTerm.java index 4a67b43e0..069a47382 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/IntervalTerm.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/IntervalTerm.java @@ -1,19 +1,21 @@ -package at.ac.tuwien.kr.alpha.common.terms; +package at.ac.tuwien.kr.alpha.commons.terms; -import at.ac.tuwien.kr.alpha.common.Interner; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import java.util.LinkedHashSet; +import java.util.Set; -import java.util.LinkedList; -import java.util.List; - -import static at.ac.tuwien.kr.alpha.Util.oops; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.util.Interner; +import at.ac.tuwien.kr.alpha.commons.util.Util; /** * An IntervalTerm represents the shorthand notation for a set of rules where all elements in this interval occur once, e.g., fact(2..5). * An IntervalTerm is a meta-term and the grounder must replace it with its corresponding set of facts or rules. * Copyright (c) 2017, the Alpha Team. */ -public class IntervalTerm extends Term { +public class IntervalTerm extends AbstractTerm { private static final Interner INTERNER = new Interner<>(); private final Term lowerBoundTerm; private final Term upperBoundTerm; @@ -53,14 +55,14 @@ public boolean isGround() { public int getLowerBound() { if (!isGround()) { - throw oops("Cannot get the lower bound of non-ground interval"); + throw Util.oops("Cannot get the lower bound of non-ground interval"); } return this.lowerBound; } public int getUpperBound() { if (!isGround()) { - throw oops("Cannot get the upper bound of non-ground interval"); + throw Util.oops("Cannot get the upper bound of non-ground interval"); } return this.upperBound; } @@ -74,13 +76,13 @@ public Term getUpperBoundTerm() { } @Override - public List getOccurringVariables() { - LinkedList variables = new LinkedList<>(); + public Set getOccurringVariables() { + Set variables = new LinkedHashSet<>(); if (lowerBoundTerm instanceof VariableTerm) { - variables.add((VariableTerm) lowerBoundTerm); + variables.add((VariableTermImpl) lowerBoundTerm); } if (upperBoundTerm instanceof VariableTerm) { - variables.add((VariableTerm) upperBoundTerm); + variables.add((VariableTermImpl) upperBoundTerm); } return variables; } @@ -132,7 +134,7 @@ public Term renameVariables(String renamePrefix) { } @Override - public Term normalizeVariables(String renamePrefix, RenameCounter counter) { + public Term normalizeVariables(String renamePrefix, Term.RenameCounter counter) { return IntervalTerm.getInstance( lowerBoundTerm.normalizeVariables(renamePrefix, counter), upperBoundTerm.normalizeVariables(renamePrefix, counter)); @@ -146,8 +148,8 @@ public Term normalizeVariables(String renamePrefix, RenameCounter counter) { public static boolean termContainsIntervalTerm(Term term) { if (term instanceof IntervalTerm) { return true; - } else if (term instanceof FunctionTerm) { - return functionTermContainsIntervals((FunctionTerm) term); + } else if (term instanceof FunctionTermImpl) { + return functionTermContainsIntervals((FunctionTermImpl) term); } else { return false; } @@ -159,7 +161,7 @@ public static boolean functionTermContainsIntervals(FunctionTerm functionTerm) { if (term instanceof IntervalTerm) { return true; } - if (term instanceof FunctionTerm && functionTermContainsIntervals((FunctionTerm) term)) { + if (term instanceof FunctionTermImpl && functionTermContainsIntervals((FunctionTerm) term)) { return true; } } diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/Terms.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/Terms.java new file mode 100644 index 000000000..b02e00c7b --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/Terms.java @@ -0,0 +1,120 @@ +package at.ac.tuwien.kr.alpha.commons.terms; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticOperator; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.Unifier; +import at.ac.tuwien.kr.alpha.commons.terms.ArithmeticTermImpl.MinusTerm; + +/** + * Convenience methods for {@link Term}s. The methods provided here are an + * attempt to avoid repeating commonly used code snippets, like wrapping sets of + * values in {@link Term}s and creating lists of those terms, etc. + * + * Copyright (c) 2020, the Alpha Team. + */ +public final class Terms { + + /** + * Since this is purely a utility class, it may not be instantiated. + * + * @throws AssertionError if called + */ + private Terms() { + throw new AssertionError(Terms.class.getSimpleName() + " is a non-instantiable utility class!"); + } + + public static > ConstantTerm newConstant(T constantObject) { + return ConstantTermImpl.getInstance(constantObject); + } + + public static ConstantTerm newSymbolicConstant(String symbol) { + return ConstantTermImpl.getSymbolicInstance(symbol); + } + + public static VariableTerm newVariable(String varName) { + return VariableTermImpl.getInstance(varName); + } + + public static VariableTerm newAnonymousVariable() { + return VariableTermImpl.getAnonymousInstance(); + } + + public static FunctionTerm newFunctionTerm(String functionSymbol, List functionArgs) { + return FunctionTermImpl.getInstance(functionSymbol, functionArgs); + } + + public static FunctionTerm newFunctionTerm(String functionSmybol, Term... functionArgs) { + return FunctionTermImpl.getInstance(functionSmybol, functionArgs); + } + + public static Term newArithmeticTerm(Term leftOperand, ArithmeticOperator operator, Term rightOperand) { + return ArithmeticTermImpl.getInstance(leftOperand, operator, rightOperand); + } + + // TODO see comment in MinusTerm, should be merged with normal arithmetic term! + public static Term newMinusTerm(Term negatedTerm) { + return MinusTerm.getInstance(negatedTerm); + } + + @SafeVarargs + public static > List> asTermList(T... values) { + List> retVal = new ArrayList<>(); + for (T value : values) { + retVal.add(ConstantTermImpl.getInstance(value)); + } + return retVal; + } + + public static List renameTerms(List terms, String prefix, int counterStartingValue) { + List renamedTerms = new ArrayList<>(terms.size()); + AbstractTerm.RenameCounterImpl renameCounter = new AbstractTerm.RenameCounterImpl(counterStartingValue); + for (Term term : terms) { + renamedTerms.add(term.normalizeVariables(prefix, renameCounter)); + } + return renamedTerms; + } + + /** + * Renames variables in given set of terms. + * @param varNamePrefix + * @return + */ + public static Substitution renameVariables(Set terms, String varNamePrefix) { + Unifier renamingSubstitution = new Unifier(); + int counter = 0; + for (VariableTerm variable : terms) { + renamingSubstitution.put(variable, Terms.newVariable(varNamePrefix + counter++)); + } + return renamingSubstitution; + } + + public static Integer evaluateGroundTerm(Term term) { + if (!term.isGround()) { + throw new RuntimeException("Cannot evaluate arithmetic term since it is not ground: " + term); + } + return evaluateGroundTermHelper(term); + } + + static Integer evaluateGroundTermHelper(Term term) { + if (term instanceof ConstantTerm + && ((ConstantTerm) term).getObject() instanceof Integer) { + // Extract integer from the constant. + return (Integer) ((ConstantTerm) term).getObject(); + } else if (term instanceof ArithmeticTerm) { + return ((ArithmeticTerm) term).evaluateExpression(); + } else { + // ASP Core 2 standard allows non-integer terms in arithmetic expressions, result is to simply ignore the ground instance. + return null; + } + } + +} diff --git a/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/VariableTermImpl.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/VariableTermImpl.java new file mode 100644 index 000000000..5e892b480 --- /dev/null +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/terms/VariableTermImpl.java @@ -0,0 +1,111 @@ +package at.ac.tuwien.kr.alpha.commons.terms; + +import java.util.Collections; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.util.IntIdGenerator; +import at.ac.tuwien.kr.alpha.commons.util.Interner; + +/** + * Copyright (c) 2016-2017, the Alpha Team. + */ +class VariableTermImpl extends AbstractTerm implements VariableTerm { + private static final Interner INTERNER = new Interner<>(); + + private static final String ANONYMOUS_VARIABLE_PREFIX = "_"; + private static final IntIdGenerator ANONYMOUS_VARIABLE_COUNTER = new IntIdGenerator(); + + private final String variableName; + + private VariableTermImpl(String variableName) { + this.variableName = variableName; + } + + public static VariableTermImpl getInstance(String variableName) { + return INTERNER.intern(new VariableTermImpl(variableName)); + } + + public static VariableTermImpl getAnonymousInstance() { + return getInstance(ANONYMOUS_VARIABLE_PREFIX + ANONYMOUS_VARIABLE_COUNTER.getNextId()); + } + + @Override + public boolean isGround() { + return false; + } + + @Override + public Set getOccurringVariables() { + return Collections.singleton(this); + } + + @Override + public Term substitute(Substitution substitution) { + Term groundTerm = substitution.eval(this); + if (groundTerm == null) { + // If variable is not substituted, keep term as is. + return this; + } + return groundTerm; + } + + @Override + public String toString() { + return variableName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + VariableTermImpl that = (VariableTermImpl) o; + + return variableName.equals(that.variableName); + } + + @Override + public int hashCode() { + return variableName.hashCode(); + } + + // TODO not sure if this makes sense (cast to VariableTerm interface instead?) + @Override + public int compareTo(Term o) { + if (this == o) { + return 0; + } + + if (!(o instanceof VariableTermImpl)) { + return super.compareTo(o); + } + + VariableTermImpl other = (VariableTermImpl) o; + return variableName.compareTo(other.variableName); + } + + @Override + public AbstractTerm renameVariables(String renamePrefix) { + return VariableTermImpl.getInstance(renamePrefix + variableName); + } + + @Override + public Term normalizeVariables(String renamePrefix, Term.RenameCounter counter) { + VariableTerm renamedThis = counter.getRenamedVariables().get(this); + if (renamedThis != null) { + return renamedThis; + } else { + VariableTerm renamedVariable = VariableTermImpl.getInstance(renamePrefix + counter.getAndIncrement()); + counter.getRenamedVariables().put(this, renamedVariable); + return renamedVariable; + } + } +} \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/query/AnswerSetQuery.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/AnswerSetQueryImpl.java similarity index 78% rename from src/main/java/at/ac/tuwien/kr/alpha/api/query/AnswerSetQuery.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/AnswerSetQueryImpl.java index 74db5479b..ccb89f6c5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/query/AnswerSetQuery.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/AnswerSetQueryImpl.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.api.query; +package at.ac.tuwien.kr.alpha.commons.util; import java.util.Collections; import java.util.HashMap; @@ -6,22 +6,23 @@ import java.util.Map; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.AnswerSetQuery; +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.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; /** * A query for ASP atoms matching a set of filter predicates. */ -public final class AnswerSetQuery implements java.util.function.Predicate { +public final class AnswerSetQueryImpl implements AnswerSetQuery { private final Predicate predicate; private Map> filters = new HashMap<>(); - private AnswerSetQuery(Predicate pred) { + private AnswerSetQueryImpl(Predicate pred) { this.predicate = pred; } @@ -31,8 +32,8 @@ private AnswerSetQuery(Predicate pred) { * @param predicate the predicate to match against * @return a new AnswerSetQuery matching against the given predicate */ - public static AnswerSetQuery forPredicate(Predicate predicate) { - return new AnswerSetQuery(predicate); + public static AnswerSetQueryImpl forPredicate(Predicate predicate) { + return new AnswerSetQueryImpl(predicate); } /** @@ -43,7 +44,8 @@ public static AnswerSetQuery forPredicate(Predicate predicate) { * @param filter the test predicate to use on terms * @return this AnswerSetQuery with the additional filter added */ - public AnswerSetQuery withFilter(int termIdx, java.util.function.Predicate filter) { + @Override + public AnswerSetQueryImpl withFilter(int termIdx, java.util.function.Predicate filter) { if (termIdx >= this.predicate.getArity()) { throw new IndexOutOfBoundsException( "Predicate " + this.predicate.getName() + " has arity " + this.predicate.getArity() + ", term index " + termIdx + " is invalid!"); @@ -64,8 +66,9 @@ public AnswerSetQuery withFilter(int termIdx, java.util.function.Predicate * @param str * @return */ - public AnswerSetQuery withConstantEquals(int termIdx, String str) { - return this.withFilter(termIdx, AnswerSetQuery.constantTermEquals(str)); + @Override + public AnswerSetQueryImpl withConstantEquals(int termIdx, String str) { + return this.withFilter(termIdx, AnswerSetQueryImpl.constantTermEquals(str)); } /** @@ -75,7 +78,8 @@ public AnswerSetQuery withConstantEquals(int termIdx, String str) { * @param str * @return */ - public AnswerSetQuery withStringEquals(int termIdx, String str) { + @Override + public AnswerSetQueryImpl withStringEquals(int termIdx, String str) { return this.withFilter(termIdx, (term) -> { if (!(term instanceof ConstantTerm)) { return false; @@ -95,7 +99,8 @@ public AnswerSetQuery withStringEquals(int termIdx, String str) { * @param funcArity * @return */ - public AnswerSetQuery withFunctionTerm(int termIdx, String funcSymbol, int funcArity) { + @Override + public AnswerSetQueryImpl withFunctionTerm(int termIdx, String funcSymbol, int funcArity) { java.util.function.Predicate isFunction = (term) -> { if (!(term instanceof FunctionTerm)) { return false; @@ -119,7 +124,8 @@ public AnswerSetQuery withFunctionTerm(int termIdx, String funcSymbol, int funcA * @param otherTerm * @return */ - public AnswerSetQuery withTermEquals(int termIdx, Term otherTerm) { + @Override + public AnswerSetQueryImpl withTermEquals(int termIdx, Term otherTerm) { java.util.function.Predicate isEqual = (term) -> { return term.equals(otherTerm); }; @@ -156,6 +162,7 @@ public boolean test(Atom atom) { * @param as * @return */ + @Override public List applyTo(AnswerSet as) { if (!as.getPredicates().contains(this.predicate)) { return Collections.emptyList(); @@ -165,7 +172,7 @@ public List applyTo(AnswerSet as) { private static java.util.function.Predicate constantTermEquals(final String str) { java.util.function.Predicate equalsGivenString = (t) -> { - return AnswerSetQuery.constantTermEquals(t, str); + return AnswerSetQueryImpl.constantTermEquals(t, str); }; return equalsGivenString; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/IntIdGenerator.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/IntIdGenerator.java similarity index 85% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/IntIdGenerator.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/IntIdGenerator.java index 7e5aade1d..df044d1b7 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/IntIdGenerator.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/IntIdGenerator.java @@ -1,6 +1,6 @@ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.commons.util; -import static at.ac.tuwien.kr.alpha.Util.oops; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; /** * Generates unique, sequential integers starting at 0, i.e., it maintains a counter that is incremented for each getNextId(). diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/Interner.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/Interner.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/common/Interner.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/Interner.java index debfa2423..b398507c8 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/Interner.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/Interner.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.commons.util; import java.lang.ref.WeakReference; import java.util.WeakHashMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/SimpleAnswerSetFormatter.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/SimpleAnswerSetFormatter.java similarity index 79% rename from src/main/java/at/ac/tuwien/kr/alpha/common/SimpleAnswerSetFormatter.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/SimpleAnswerSetFormatter.java index 35139441f..8725fefc1 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/SimpleAnswerSetFormatter.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/SimpleAnswerSetFormatter.java @@ -1,11 +1,14 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.commons.util; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.util.AnswerSetFormatter; public class SimpleAnswerSetFormatter implements AnswerSetFormatter { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/Util.java b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/Util.java similarity index 98% rename from src/main/java/at/ac/tuwien/kr/alpha/Util.java rename to alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/Util.java index d4efae105..6e0c7ff8f 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/Util.java +++ b/alpha-commons/src/main/java/at/ac/tuwien/kr/alpha/commons/util/Util.java @@ -25,14 +25,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; - -import org.stringtemplate.v4.ST; -import org.stringtemplate.v4.STGroup; -import org.stringtemplate.v4.STGroupFile; +package at.ac.tuwien.kr.alpha.commons.util; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -46,6 +41,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; +import org.stringtemplate.v4.STGroupFile; + +// TODO shouldn't be public API public class Util { private static final String LITERATE_INDENT = " "; @@ -114,7 +114,7 @@ public static Stream literate(Stream input) { }); } - public static ReadableByteChannel streamToChannel(Stream lines) throws IOException { + public static ReadableByteChannel streamToChannel(Stream lines) { return Channels.newChannel(new ByteArrayInputStream(lines.collect(Collectors.joining(System.lineSeparator())).getBytes(StandardCharsets.UTF_8))); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/BasicAnswerSetTest.java b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/BasicAnswerSetTest.java similarity index 57% rename from src/test/java/at/ac/tuwien/kr/alpha/common/BasicAnswerSetTest.java rename to alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/BasicAnswerSetTest.java index c1fa0665f..5c1de5dcf 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/BasicAnswerSetTest.java +++ b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/BasicAnswerSetTest.java @@ -1,6 +1,5 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.commons; -import static at.ac.tuwien.kr.alpha.common.terms.ConstantTerm.getInstance; import static java.util.Arrays.asList; import static java.util.Collections.singleton; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,9 +13,12 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; /** * Copyright (c) 2016, the Alpha Team. @@ -25,47 +27,47 @@ public class BasicAnswerSetTest { @Test public void areAnswerSetsEqual() { - Predicate a = Predicate.getInstance("a", 0); - Predicate foo = Predicate.getInstance("foo", 1); + Predicate a = Predicates.getPredicate("a", 0); + Predicate foo = Predicates.getPredicate("foo", 1); SortedSet fooAndA = new TreeSet<>(asList(foo, a)); - Predicate q = Predicate.getInstance("q", 0); - Predicate p = Predicate.getInstance("p", 1); + Predicate q = Predicates.getPredicate("q", 0); + Predicate p = Predicates.getPredicate("p", 1); SortedSet qAndP = new TreeSet<>(asList(q, p)); - ConstantTerm bar = getInstance("bar"); - ConstantTerm baz = getInstance("baz"); + ConstantTerm bar = Terms.newConstant("bar"); + ConstantTerm baz = Terms.newConstant("baz"); Map> inst1 = new HashMap<>(); - inst1.put(a, new TreeSet<>(singleton(new BasicAtom(a)))); + inst1.put(a, new TreeSet<>(singleton(Atoms.newBasicAtom(a)))); inst1.put(foo, new TreeSet<>(asList( - new BasicAtom(foo, bar), - new BasicAtom(foo, baz) + Atoms.newBasicAtom(foo, bar), + Atoms.newBasicAtom(foo, baz) ))); // as1 = { a, foo(bar), foo(baz) } Map> inst2 = new HashMap<>(); - inst2.put(a, new TreeSet<>(singleton(new BasicAtom(a)))); + inst2.put(a, new TreeSet<>(singleton(Atoms.newBasicAtom(a)))); inst2.put(foo, new TreeSet<>(asList( - new BasicAtom(foo, baz), - new BasicAtom(foo, bar) + Atoms.newBasicAtom(foo, baz), + Atoms.newBasicAtom(foo, bar) ))); // as1 = { a, foo(baz), foo(bar) } Map> inst3 = new HashMap<>(); - inst3.put(q, new TreeSet<>(singleton(new BasicAtom(q)))); + inst3.put(q, new TreeSet<>(singleton(Atoms.newBasicAtom(q)))); inst3.put(p, new TreeSet<>(asList( - new BasicAtom(p, bar), - new BasicAtom(p, baz) + Atoms.newBasicAtom(p, bar), + Atoms.newBasicAtom(p, baz) ))); // as3 = { q, p(bar), p(baz) } Map> inst4 = new HashMap<>(); - inst4.put(a, new TreeSet<>(singleton(new BasicAtom(a)))); + inst4.put(a, new TreeSet<>(singleton(Atoms.newBasicAtom(a)))); inst4.put(foo, new TreeSet<>(asList( - new BasicAtom(foo, bar), - new BasicAtom(foo, baz), - new BasicAtom(foo, getInstance("batsinga")) + Atoms.newBasicAtom(foo, bar), + Atoms.newBasicAtom(foo, baz), + Atoms.newBasicAtom(foo, Terms.newConstant("batsinga")) ))); // as4 = { a, foo(bar), foo(baz), foo(batsinga) } @@ -82,4 +84,4 @@ public void areAnswerSetsEqual() { assertNotEquals(answerSets.get(0), answerSets.get(2)); assertNotEquals(answerSets.get(0), answerSets.get(3)); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/TermTest.java b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TermTest.java similarity index 56% rename from src/test/java/at/ac/tuwien/kr/alpha/common/TermTest.java rename to alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TermTest.java index aefea937e..ea0ebcfc1 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/TermTest.java +++ b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TermTest.java @@ -1,23 +1,25 @@ -package at.ac.tuwien.kr.alpha.common; - -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; +package at.ac.tuwien.kr.alpha.commons.terms; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.Test; +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; + /** - * Copyright (c) 2016, the Alpha Team. + * Copyright (c) 2016-2021, the Alpha Team. */ +// TODO maybe this should actually work against the AbstractTerm type since it tests properties of interned terms which is not part of the public Term interface public class TermTest { @Test @@ -25,37 +27,37 @@ public void testTermReferenceEquality() { // Terms must have a unique representation so that reference comparison is // sufficient to check // whether two terms are equal. - ConstantTerm ta1 = ConstantTerm.getInstance("a"); - ConstantTerm ta2 = ConstantTerm.getInstance("a"); + ConstantTerm ta1 = Terms.newConstant("a"); + ConstantTerm ta2 = Terms.newConstant("a"); assertTrue(ta1 == ta2, "Two instances of ConstantTerms for the same term symbol must be the same object"); List termList = new LinkedList<>(); termList.add(ta1); termList.add(ta2); - FunctionTerm ft1 = FunctionTerm.getInstance("f", termList); + FunctionTermImpl ft1 = FunctionTermImpl.getInstance("f", termList); List termList2 = new LinkedList<>(); termList2.add(ta1); termList2.add(ta2); - FunctionTerm ft2 = FunctionTerm.getInstance("f", termList2); + FunctionTermImpl ft2 = FunctionTermImpl.getInstance("f", termList2); assertTrue(ft1 == ft2, "Two instances of FunctionTerms for the same term symbol and equal term lists must be the same object"); } @Test public void testTermVariableOccurrences() { - ConstantTerm ta = ConstantTerm.getInstance("a"); - VariableTerm tx = VariableTerm.getInstance("X"); - FunctionTerm tf = FunctionTerm.getInstance("f", ta, tx); - List occurringVariables = tf.getOccurringVariables(); + ConstantTerm ta = Terms.newConstant("a"); + VariableTerm tx = VariableTermImpl.getInstance("X"); + FunctionTermImpl tf = FunctionTermImpl.getInstance("f", ta, tx); + Set occurringVariables = tf.getOccurringVariables(); - assertEquals(tx, occurringVariables.get(0), "Variable occurring as subterm must be reported as occurring variable."); + assertEquals(tx, new ArrayList<>(occurringVariables).get(0), "Variable occurring as subterm must be reported as occurring variable."); } @Test public void testTermOrdering() { - Term cts = ConstantTerm.getInstance("abc"); - Term cti = ConstantTerm.getInstance(2); - Term cto = ConstantTerm.getInstance(new UUID(0, 0)); - Term ft = FunctionTerm.getInstance("f", ConstantTerm.getInstance("a")); + Term cts = Terms.newConstant("abc"); + Term cti = Terms.newConstant(2); + Term cto = Terms.newConstant(new UUID(0, 0)); + Term ft = FunctionTermImpl.getInstance("f", Terms.newConstant("a")); assertTrue(cts.compareTo(cti) > 0); assertTrue(cti.compareTo(cts) < 0); @@ -73,12 +75,12 @@ public void testTermOrdering() { @Test public void testStringVsConstantSymbolEquality() { String theString = "string"; - ConstantTerm stringConstant = ConstantTerm.getInstance(theString); - ConstantTerm constantSymbol = ConstantTerm.getSymbolicInstance(theString); + ConstantTerm stringConstant = Terms.newConstant(theString); + ConstantTerm constantSymbol = Terms.newSymbolicConstant(theString); // Reference equality must hold for both the string constant and the constant // symbol. - assertTrue(stringConstant == ConstantTerm.getInstance(theString)); - ConstantTerm sameConstantSymbol = ConstantTerm.getSymbolicInstance(theString); + assertTrue(stringConstant == Terms.newConstant(theString)); + ConstantTerm sameConstantSymbol = Terms.newSymbolicConstant(theString); assertTrue(constantSymbol == sameConstantSymbol); // Make sure both hashCode and equals understand that stringConstant and // constantSymbol are NOT the same thing! diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/terms/TermsTest.java b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TermsTest.java similarity index 56% rename from src/test/java/at/ac/tuwien/kr/alpha/common/terms/TermsTest.java rename to alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TermsTest.java index 8e32f4b52..4c4600dc8 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/terms/TermsTest.java +++ b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TermsTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.terms; +package at.ac.tuwien.kr.alpha.commons.terms; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -6,18 +6,20 @@ import org.junit.jupiter.api.Test; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; + public class TermsTest { @Test public void integersAsTermList() { List> intTerms = Terms.asTermList(1, 2, 3, 4, 5, 6); assertEquals(6, intTerms.size()); - assertEquals(ConstantTerm.getInstance(1), intTerms.get(0)); - assertEquals(ConstantTerm.getInstance(2), intTerms.get(1)); - assertEquals(ConstantTerm.getInstance(3), intTerms.get(2)); - assertEquals(ConstantTerm.getInstance(4), intTerms.get(3)); - assertEquals(ConstantTerm.getInstance(5), intTerms.get(4)); - assertEquals(ConstantTerm.getInstance(6), intTerms.get(5)); + assertEquals(Terms.newConstant(1), intTerms.get(0)); + assertEquals(Terms.newConstant(2), intTerms.get(1)); + assertEquals(Terms.newConstant(3), intTerms.get(2)); + assertEquals(Terms.newConstant(4), intTerms.get(3)); + assertEquals(Terms.newConstant(5), intTerms.get(4)); + assertEquals(Terms.newConstant(6), intTerms.get(5)); } @Test diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/terms/TestMinusTerm.java b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TestMinusTerm.java similarity index 75% rename from src/test/java/at/ac/tuwien/kr/alpha/common/terms/TestMinusTerm.java rename to alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TestMinusTerm.java index 054ea7f91..ea7a02728 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/terms/TestMinusTerm.java +++ b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/terms/TestMinusTerm.java @@ -23,14 +23,16 @@ * 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.common.terms; +package at.ac.tuwien.kr.alpha.commons.terms; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm.MinusTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term.RenameCounter; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.Term.RenameCounter; +import at.ac.tuwien.kr.alpha.commons.terms.AbstractTerm.RenameCounterImpl; +import at.ac.tuwien.kr.alpha.commons.terms.ArithmeticTermImpl.MinusTerm; /** * Tests {@link MinusTerm} @@ -38,18 +40,18 @@ public class TestMinusTerm { private final String renamePrefix = "Renamed"; - private final RenameCounter counter = new RenameCounter(0); + private final RenameCounter counter = new RenameCounterImpl(0); @Test public void testNormalizeVariablesNoVariable() { - Term m2 = MinusTerm.getInstance(ConstantTerm.getInstance(2)); + Term m2 = MinusTerm.getInstance(ConstantTermImpl.getInstance(2)); assertEquals(m2, m2.normalizeVariables(renamePrefix, counter)); } @Test public void testNormalizeVariablesWithVariable() { - Term mX = MinusTerm.getInstance(VariableTerm.getInstance("X")); - Term expected = MinusTerm.getInstance(VariableTerm.getInstance(renamePrefix + 0)); + Term mX = MinusTerm.getInstance(VariableTermImpl.getInstance("X")); + Term expected = MinusTerm.getInstance(VariableTermImpl.getInstance(renamePrefix + 0)); assertEquals(expected, mX.normalizeVariables(renamePrefix, counter)); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/api/query/AnswerSetQueryTest.java b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/util/AnswerSetQueryTest.java similarity index 58% rename from src/test/java/at/ac/tuwien/kr/alpha/api/query/AnswerSetQueryTest.java rename to alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/util/AnswerSetQueryTest.java index c106a861a..cc81e6af9 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/api/query/AnswerSetQueryTest.java +++ b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/util/AnswerSetQueryTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.api.query; +package at.ac.tuwien.kr.alpha.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -11,15 +11,16 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; -import at.ac.tuwien.kr.alpha.common.BasicAnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.commons.AnswerSets; +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; public class AnswerSetQueryTest { @@ -34,10 +35,10 @@ public void matchPredicate() { .symbolicInstance("x"); //@formatter:on AnswerSet as = bld.build(); - List queryResult = as.query(AnswerSetQuery.forPredicate(Predicate.getInstance("p", 1))); + List queryResult = as.query(AnswerSetQueryImpl.forPredicate(Predicates.getPredicate("p", 1))); assertEquals(2, queryResult.size()); for (Atom a : queryResult) { - assertTrue(a.getPredicate().equals(Predicate.getInstance("p", 1))); + assertTrue(a.getPredicate().equals(Predicates.getPredicate("p", 1))); } } @@ -48,8 +49,8 @@ public void matchSymbolicConstant() { .symbolicInstance("a") .instance("a"); AnswerSet as = bld.build(); - AnswerSetQuery constantQuery = AnswerSetQuery - .forPredicate(Predicate.getInstance("p", 1)) + AnswerSetQueryImpl constantQuery = AnswerSetQueryImpl + .forPredicate(Predicates.getPredicate("p", 1)) .withConstantEquals(0, "a"); List queryResult = as.query(constantQuery); assertEquals(1, queryResult.size()); @@ -62,8 +63,8 @@ public void matchString() { .symbolicInstance("a") .instance("a"); AnswerSet as = bld.build(); - AnswerSetQuery stringQuery = AnswerSetQuery - .forPredicate(Predicate.getInstance("p", 1)) + AnswerSetQueryImpl stringQuery = AnswerSetQueryImpl + .forPredicate(Predicates.getPredicate("p", 1)) .withStringEquals(0, "a"); List queryResult = as.query(stringQuery); assertEquals(1, queryResult.size()); @@ -83,7 +84,7 @@ public void matchEvenIntegers() { String strValue = ((ConstantTerm) term).getObject().toString(); return strValue.matches("[0-9]+"); }; - AnswerSetQuery evenIntegers = AnswerSetQuery.forPredicate(Predicate.getInstance("p", 1)) + AnswerSetQueryImpl evenIntegers = AnswerSetQueryImpl.forPredicate(Predicates.getPredicate("p", 1)) .withFilter(0, isInteger.and( (term) -> Integer.valueOf(((ConstantTerm) term).getObject().toString()) % 2 == 0)); List queryResult = as.query(evenIntegers); @@ -96,12 +97,12 @@ public void matchEvenIntegers() { @Test public void matchXWithFuncTerm() { - Predicate p = Predicate.getInstance("p", 2); - Atom a1 = new BasicAtom(p, ConstantTerm.getSymbolicInstance("x"), FunctionTerm.getInstance("f", ConstantTerm.getSymbolicInstance("x"))); - Atom a2 = new BasicAtom(p, ConstantTerm.getSymbolicInstance("y"), FunctionTerm.getInstance("f", ConstantTerm.getSymbolicInstance("y"))); - Atom a3 = new BasicAtom(p, ConstantTerm.getSymbolicInstance("y"), FunctionTerm.getInstance("f", ConstantTerm.getSymbolicInstance("x"))); - Atom a4 = new BasicAtom(p, ConstantTerm.getSymbolicInstance("x"), FunctionTerm.getInstance("f", ConstantTerm.getSymbolicInstance("y"))); - Atom a5 = new BasicAtom(p, ConstantTerm.getSymbolicInstance("x"), ConstantTerm.getSymbolicInstance("f")); + Predicate p = Predicates.getPredicate("p", 2); + Atom a1 = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("x"), Terms.newFunctionTerm("f", Terms.newSymbolicConstant("x"))); + Atom a2 = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("y"), Terms.newFunctionTerm("f", Terms.newSymbolicConstant("y"))); + Atom a3 = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("y"), Terms.newFunctionTerm("f", Terms.newSymbolicConstant("x"))); + Atom a4 = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("x"), Terms.newFunctionTerm("f", Terms.newSymbolicConstant("y"))); + Atom a5 = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("x"), Terms.newFunctionTerm("f")); SortedSet predicates = new TreeSet<>(); predicates.add(p); Map> instances = new HashMap<>(); @@ -112,8 +113,8 @@ public void matchXWithFuncTerm() { ps.add(a4); ps.add(a5); instances.put(p, ps); - AnswerSet as = new BasicAnswerSet(predicates, instances); - AnswerSetQuery query = AnswerSetQuery.forPredicate(Predicate.getInstance("p", 2)).withConstantEquals(0, "x").withFunctionTerm(1, "f", 1); + AnswerSet as = AnswerSets.newAnswerSet(predicates, instances); + AnswerSetQueryImpl query = AnswerSetQueryImpl.forPredicate(Predicates.getPredicate("p", 2)).withConstantEquals(0, "x").withFunctionTerm(1, "f", 1); List queryResult = as.query(query); assertEquals(2, queryResult.size()); } @@ -126,11 +127,11 @@ public void matchTerm() { .instance("bla").symbolicInstance("blubb"); AnswerSet as = bld.build(); - AnswerSetQuery equalTerm = AnswerSetQuery.forPredicate(Predicate.getInstance("p", 1)).withTermEquals(0, ConstantTerm.getInstance(1)); + AnswerSetQueryImpl equalTerm = AnswerSetQueryImpl.forPredicate(Predicates.getPredicate("p", 1)).withTermEquals(0, Terms.newConstant(1)); List queryResult = as.query(equalTerm); assertEquals(1, queryResult.size()); Atom retrievedAtom = queryResult.get(0); - assertTrue(retrievedAtom.getTerms().get(0).equals(ConstantTerm.getInstance(1))); + assertTrue(retrievedAtom.getTerms().get(0).equals(Terms.newConstant(1))); } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/UtilTest.java b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/util/UtilTest.java similarity index 91% rename from src/test/java/at/ac/tuwien/kr/alpha/UtilTest.java rename to alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/util/UtilTest.java index 0dc7e5f14..5482e713e 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/UtilTest.java +++ b/alpha-commons/src/test/java/at/ac/tuwien/kr/alpha/commons/util/UtilTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha; +package at.ac.tuwien.kr.alpha.commons.util; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/alpha-core/.gitignore b/alpha-core/.gitignore new file mode 100644 index 000000000..84c048a73 --- /dev/null +++ b/alpha-core/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/benchmarks/omiga/omiga-testcases.tar.gz b/alpha-core/benchmarks/omiga/omiga-testcases.tar.gz similarity index 100% rename from benchmarks/omiga/omiga-testcases.tar.gz rename to alpha-core/benchmarks/omiga/omiga-testcases.tar.gz diff --git a/benchmarks/omiga/omiga-testcases/3col/3col-10-18.txt b/alpha-core/benchmarks/omiga/omiga-testcases/3col/3col-10-18.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/3col/3col-10-18.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/3col/3col-10-18.txt diff --git a/benchmarks/omiga/omiga-testcases/3col/3col-20-38.txt b/alpha-core/benchmarks/omiga/omiga-testcases/3col/3col-20-38.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/3col/3col-20-38.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/3col/3col-20-38.txt diff --git a/benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-30.txt b/alpha-core/benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-30.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-30.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-30.txt diff --git a/benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-50.txt b/alpha-core/benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-50.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-50.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/cutedge/cutedge-100-50.txt diff --git a/benchmarks/omiga/omiga-testcases/locstrat/locstrat-200.txt b/alpha-core/benchmarks/omiga/omiga-testcases/locstrat/locstrat-200.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/locstrat/locstrat-200.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/locstrat/locstrat-200.txt diff --git a/benchmarks/omiga/omiga-testcases/locstrat/locstrat-400.txt b/alpha-core/benchmarks/omiga/omiga-testcases/locstrat/locstrat-400.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/locstrat/locstrat-400.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/locstrat/locstrat-400.txt diff --git a/benchmarks/omiga/omiga-testcases/reach/reach-1.txt b/alpha-core/benchmarks/omiga/omiga-testcases/reach/reach-1.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/reach/reach-1.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/reach/reach-1.txt diff --git a/benchmarks/omiga/omiga-testcases/reach/reach-4.txt b/alpha-core/benchmarks/omiga/omiga-testcases/reach/reach-4.txt similarity index 100% rename from benchmarks/omiga/omiga-testcases/reach/reach-4.txt rename to alpha-core/benchmarks/omiga/omiga-testcases/reach/reach-4.txt diff --git a/benchmarks/siemens/racks/racks.lp b/alpha-core/benchmarks/siemens/racks/racks.lp similarity index 100% rename from benchmarks/siemens/racks/racks.lp rename to alpha-core/benchmarks/siemens/racks/racks.lp diff --git a/alpha-core/build.gradle.kts b/alpha-core/build.gradle.kts new file mode 100644 index 000000000..51cdb7b8a --- /dev/null +++ b/alpha-core/build.gradle.kts @@ -0,0 +1,61 @@ +plugins { + id("antlr") + id("alpha.java-library-conventions") +} + +val antlrVersion = "4.7" +// Keep this in sync with antlr version to avoid multiple versions in classpath +val stringtemplateVersion = "4.0.8" + +dependencies { + api(project(":alpha-api")) + api(project(":alpha-commons")) + + // We need to give the ANTLR Plugin a hint. + antlr("org.antlr:antlr4:${antlrVersion}") + + // Re-introduce antlr4-runtime as compile dependency. + implementation("org.antlr:antlr4-runtime:${antlrVersion}") + + implementation("org.antlr:ST4:${stringtemplateVersion}") +} + +//tasks.withType(AntlrTask) { +tasks.generateGrammarSource { + // See https://github.com/antlr/antlr4/blob/master/doc/tool-options.md + arguments.addAll(listOf( + "-visitor", + "-no-listener", + "-long-messages", + "-package", "at.ac.tuwien.kr.alpha.core.antlr", + "-Werror", + "-Xlog", + "-lib", "src/main/antlr/at/ac/tuwien/kr/alpha/core/antlr" + )) +} + +tasks.test { + useJUnitPlatform() + + configure { + // Here, we exclude ANTLR generated classes from coverage analysis, + // but not from report generation. + // Exclusion from report generation is done in tasks.jacocoTestReport + excludes = listOf("at.ac.tuwien.kr.alpha.core.antlr.*") + } + + finalizedBy(tasks.jacocoTestReport) +} + +tasks.jacocoTestReport { + reports { + xml.required.set(true) + } + + classDirectories.setFrom(classDirectories.map { + // Here, we exclude ANTLR generated classes from report generation, + // but not from coverage analysis. + // Exclusion from coverage analysis is done in tasks.test + fileTree(it).exclude("at/ac/tuwien/kr/alpha/core/antlr/**") + }) +} diff --git a/src/main/antlr/at/ac/tuwien/kr/alpha/antlr/ASPCore2.g4 b/alpha-core/src/main/antlr/at/ac/tuwien/kr/alpha/core/antlr/ASPCore2.g4 similarity index 100% rename from src/main/antlr/at/ac/tuwien/kr/alpha/antlr/ASPCore2.g4 rename to alpha-core/src/main/antlr/at/ac/tuwien/kr/alpha/core/antlr/ASPCore2.g4 diff --git a/src/main/antlr/at/ac/tuwien/kr/alpha/antlr/ASPLexer.g4 b/alpha-core/src/main/antlr/at/ac/tuwien/kr/alpha/core/antlr/ASPLexer.g4 similarity index 100% rename from src/main/antlr/at/ac/tuwien/kr/alpha/antlr/ASPLexer.g4 rename to alpha-core/src/main/antlr/at/ac/tuwien/kr/alpha/core/antlr/ASPLexer.g4 diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/ChoiceAtom.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/ChoiceAtom.java similarity index 64% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/ChoiceAtom.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/ChoiceAtom.java index 6584eaa94..5c6af0bde 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/ChoiceAtom.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/ChoiceAtom.java @@ -25,35 +25,38 @@ * 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.grounder.atoms; - -import static at.ac.tuwien.kr.alpha.Util.join; +package at.ac.tuwien.kr.alpha.core.atoms; import java.util.Collections; import java.util.List; +import java.util.Set; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.literals.Literal; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; -public class ChoiceAtom extends Atom { +public class ChoiceAtom implements Atom { - public static final Predicate ON = Predicate.getInstance("ChoiceOn", 1, true, true); - public static final Predicate OFF = Predicate.getInstance("ChoiceOff", 1, true, true); + public static final Predicate ON = Predicates.getPredicate("ChoiceOn", 1, true, true); + public static final Predicate OFF = Predicates.getPredicate("ChoiceOff", 1, true, true); private final Predicate predicate; - private final List terms; + private final ConstantTerm term; - private ChoiceAtom(Predicate predicate, Term term) { + private ChoiceAtom(Predicate predicate, ConstantTerm term) { this.predicate = predicate; - this.terms = Collections.singletonList(term); + this.term = term; } private ChoiceAtom(Predicate predicate, int id) { - this(predicate, ConstantTerm.getInstance(Integer.toString(id))); + this(predicate, Terms.newConstant(Integer.toString(id))); } public static ChoiceAtom on(int id) { @@ -71,7 +74,7 @@ public Predicate getPredicate() { @Override public List getTerms() { - return terms; + return Collections.singletonList(term); } @Override @@ -86,13 +89,13 @@ public Literal toLiteral(boolean negated) { } @Override - public Atom substitute(Substitution substitution) { + public ChoiceAtom substitute(Substitution substitution) { return this; } @Override public String toString() { - return join(predicate.getName() + "(", terms, ")"); + return Util.join(predicate.getName() + "(", getTerms(), ")"); } @Override @@ -105,7 +108,7 @@ public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((this.predicate == null) ? 0 : this.predicate.hashCode()); - result = prime * result + ((this.terms == null) ? 0 : this.terms.hashCode()); + result = prime * result + ((this.getTerms() == null) ? 0 : this.getTerms().hashCode()); return result; } @@ -128,13 +131,23 @@ public boolean equals(Object obj) { } else if (!this.predicate.equals(other.predicate)) { return false; } - if (this.terms == null) { - if (other.terms != null) { + if (this.getTerms() == null) { + if (other.getTerms() != null) { return false; } - } else if (!this.terms.equals(other.terms)) { + } else if (!this.getTerms().equals(other.getTerms())) { return false; } return true; } + + @Override + public Set getOccurringVariables() { + return Collections.emptySet(); + } + + @Override + public Atom renameVariables(String newVariablePrefix) { + throw new UnsupportedOperationException("ChoiceAtom does not have any variables to rename!"); + } } \ No newline at end of file diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/EnumerationAtom.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/EnumerationAtom.java new file mode 100644 index 000000000..d66f1989a --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/EnumerationAtom.java @@ -0,0 +1,171 @@ +package at.ac.tuwien.kr.alpha.core.atoms; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.atoms.BasicAtom; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.AbstractAtom; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; + +/** + * Represents a ground-instance enumeration atom of form: + * enum(enumId, groundTerm, sequenceNo). + * + * The semantics of this is: + * if enum(A,T1, N1) and enum(A,T2,N2) are both true and T1 != T2, then N1 != N2. + * Furthermore, If enum(A,T1,N1) is true with N1 > 0 then enum(A,T2,N1 - 1) is true for some T1 != T2 and + * both, T1 and T2, are ground instances the grounder encountered during the search so far. + * + * Copyright (c) 2017, the Alpha Team. + */ +public class EnumerationAtom extends AbstractAtom implements BasicAtom { + public static final Predicate ENUMERATION_PREDICATE = Predicates.getPredicate("_Enumeration", 3); + private static final HashMap> ENUMERATIONS = new HashMap<>(); + + private final Term enumIdTerm; + private final Term valueTerm; + private final VariableTerm indexTerm; + + public EnumerationAtom(Term enumIdTerm, Term valueTerm, VariableTerm indexTerm) { + this.enumIdTerm = enumIdTerm; + this.valueTerm = valueTerm; + this.indexTerm = indexTerm; + } + + public static void resetEnumerations() { + ENUMERATIONS.clear(); + } + + private Integer getEnumerationIndex(Term identifier, Term enumerationTerm) { + ENUMERATIONS.putIfAbsent(identifier, new HashMap<>()); + HashMap enumeratedTerms = ENUMERATIONS.get(identifier); + Integer assignedInteger = enumeratedTerms.get(enumerationTerm); + if (assignedInteger == null) { + int enumerationIndex = enumeratedTerms.size() + 1; + enumeratedTerms.put(enumerationTerm, enumerationIndex); + return enumerationIndex; + } else { + return assignedInteger; + } + + } + + /** + * Based on a given substitution, substitutes the first two terms of this {@link EnumerationAtom} with the values from the substitution, + * and returns a new substitution with all mappings from the input substitution plus a binding for the third term of the enum atom to the + * integer index that is mapped to the first two terms in the internal ENUMERATIONS map. + * + * @param substitution an input substitution which must provide ground terms for the first two terms of the enumeration atom. + * @return a new substitution where the third term of the enumeration atom is bound to an integer. + */ + public Substitution addEnumerationIndexToSubstitution(Substitution substitution) { + Term idTerm = this.getTerms().get(0).substitute(substitution); + Term enumerationTerm = this.getTerms().get(1).substitute(substitution); + if (!enumerationTerm.isGround()) { + throw new RuntimeException("Enumeration term is not ground after substitution. Should not happen."); + } + Integer enumerationIndex = getEnumerationIndex(idTerm, enumerationTerm); + BasicSubstitution retVal = new BasicSubstitution(substitution); + retVal.put((VariableTerm) getTerms().get(2), Terms.newConstant(enumerationIndex)); + return retVal; + } + + @Override + public EnumerationAtom substitute(Substitution substitution) { + Term substEnumIdTerm = enumIdTerm.substitute(substitution); + Term substValueTerm = valueTerm.substitute(substitution); + Term substIndexTerm = indexTerm.substitute(substitution); + return new EnumerationAtom(substEnumIdTerm, substValueTerm, (VariableTerm) substIndexTerm); + } + + @Override + public EnumerationLiteral toLiteral(boolean positive) { + if (!positive) { + throw Util.oops("IntervalLiteral cannot be negated"); + } + return new EnumerationLiteral(this); + } + + @Override + public EnumerationLiteral toLiteral() { + return toLiteral(true); + } + + @Override + public Predicate getPredicate() { + return ENUMERATION_PREDICATE; + } + + @Override + public List getTerms() { + List lst = new ArrayList<>(); + lst.add(enumIdTerm); + lst.add(valueTerm); + lst.add(indexTerm); + return lst; + } + + @Override + public boolean isGround() { + // An enumeration atom always has a variable as its third argument which represents the internal index of the atom (i.e. enumeration value). + // It is therefore, by definition, not ground. + return false; + } + + @Override + public Set getOccurringVariables() { + return toLiteral().getOccurringVariables(); + } + + @Override + public Atom renameVariables(String newVariablePrefix) { + return this.substitute(Terms.renameVariables(getOccurringVariables(), newVariablePrefix)); + } + + @Override + public EnumerationAtom withTerms(List terms) { + if (terms.size() != 3) { + throw new IllegalArgumentException("EnumerationAtom must have exactly 3 terms!"); + } + if (!(terms.get(2) instanceof VariableTerm)) { + throw new IllegalArgumentException("Third argument of EnumerationAtom must be a variable!"); + } + return new EnumerationAtom(terms.get(0), terms.get(1), (VariableTerm) terms.get(2)); + } + + @Override + public Atom normalizeVariables(String prefix, int counterStartingValue) { + List renamedTerms = Terms.renameTerms(getTerms(), prefix, counterStartingValue); + return withTerms(renamedTerms); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + EnumerationAtom that = (EnumerationAtom) o; + + return ENUMERATION_PREDICATE.equals(that.getPredicate()) && this.getTerms().equals(that.getTerms()); + } + + @Override + public int hashCode() { + return 31 * ENUMERATION_PREDICATE.hashCode() + getTerms().hashCode(); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/EnumerationLiteral.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/EnumerationLiteral.java similarity index 75% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/EnumerationLiteral.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/EnumerationLiteral.java index ae19a9e15..f45e5032d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/EnumerationLiteral.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/EnumerationLiteral.java @@ -1,18 +1,18 @@ -package at.ac.tuwien.kr.alpha.grounder.atoms; - -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.core.atoms; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.literals.AbstractLiteral; + /** * Copyright (c) 2018, the Alpha Team. */ -public class EnumerationLiteral extends BasicLiteral { +public class EnumerationLiteral extends AbstractLiteral { public EnumerationLiteral(EnumerationAtom atom) { super(atom, true); @@ -35,7 +35,7 @@ public EnumerationLiteral substitute(Substitution substitution) { @Override public Set getBindingVariables() { - return Collections.singleton((VariableTerm)getTerms().get(2)); + return Collections.singleton((VariableTerm) getTerms().get(2)); } @Override @@ -52,7 +52,7 @@ public Set getNonBindingVariables() { return ret; } - + public Substitution addEnumerationIndexToSubstitution(Substitution partialSubstitution) { return this.getAtom().addEnumerationIndexToSubstitution(partialSubstitution); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/IntervalAtom.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/IntervalAtom.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/IntervalAtom.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/IntervalAtom.java index 13c6aaadf..4c0236f95 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/IntervalAtom.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/IntervalAtom.java @@ -25,21 +25,21 @@ * 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.grounder.atoms; - -import static at.ac.tuwien.kr.alpha.Util.join; -import static at.ac.tuwien.kr.alpha.Util.oops; +package at.ac.tuwien.kr.alpha.core.atoms; import java.util.Arrays; import java.util.List; -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.VariableNormalizableAtom; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom; +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.AbstractAtom; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; /** * Helper for treating IntervalTerms in rules. @@ -53,8 +53,8 @@ * * Copyright (c) 2017, the Alpha Team. */ -public class IntervalAtom extends Atom implements VariableNormalizableAtom { - private static final Predicate PREDICATE = Predicate.getInstance("_interval", 2, true); +public class IntervalAtom extends AbstractAtom implements VariableNormalizableAtom { + private static final Predicate PREDICATE = Predicates.getPredicate("_interval", 2, true); private final List terms; @@ -85,7 +85,7 @@ public boolean isGround() { @Override public IntervalLiteral toLiteral(boolean positive) { if (!positive) { - throw oops("IntervalLiteral cannot be negated"); + throw Util.oops("IntervalLiteral cannot be negated"); } return new IntervalLiteral(this); } @@ -97,7 +97,7 @@ public IntervalLiteral toLiteral() { @Override public String toString() { - return join(PREDICATE.getName() + "(", terms, ")"); + return Util.join(PREDICATE.getName() + "(", terms, ")"); } @Override @@ -126,7 +126,7 @@ public IntervalAtom substitute(Substitution substitution) { @Override public IntervalAtom normalizeVariables(String prefix, int counterStartingValue) { - List renamedTerms = Term.renameTerms(terms, prefix, counterStartingValue); + List renamedTerms = Terms.renameTerms(terms, prefix, counterStartingValue); return new IntervalAtom((IntervalTerm) renamedTerms.get(0), renamedTerms.get(1)); } @@ -140,4 +140,5 @@ public Atom withTerms(List newTerms) { } return new IntervalAtom((IntervalTerm) newTerms.get(0), newTerms.get(1)); } + } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/IntervalLiteral.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/IntervalLiteral.java similarity index 77% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/IntervalLiteral.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/IntervalLiteral.java index f055e86b7..b0f142c94 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/IntervalLiteral.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/IntervalLiteral.java @@ -25,30 +25,34 @@ * 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.grounder.atoms; - -import at.ac.tuwien.kr.alpha.common.atoms.FixedInterpretationLiteral; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import com.google.common.collect.Sets; +package at.ac.tuwien.kr.alpha.core.atoms; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; +import com.google.common.collect.Sets; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.literals.FixedInterpretationLiteral; +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.literals.AbstractLiteral; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; + /** * @see IntervalAtom */ -public class IntervalLiteral extends FixedInterpretationLiteral { +public class IntervalLiteral extends AbstractLiteral implements FixedInterpretationLiteral { public IntervalLiteral(IntervalAtom atom) { super(atom, true); } - + @Override public IntervalAtom getAtom() { return (IntervalAtom) atom; @@ -68,19 +72,21 @@ private List getIntervalSubstitutions(Substitution partialSubstitu if (intervalRepresentingVariable instanceof VariableTerm) { // Still a variable, generate all elements in the interval. for (int i = intervalTerm.getLowerBound(); i <= intervalTerm.getUpperBound(); i++) { - Substitution ith = new Substitution(partialSubstitution); - ith.put((VariableTerm) intervalRepresentingVariable, ConstantTerm.getInstance(i)); + Substitution ith = new BasicSubstitution(partialSubstitution); + ith.put((VariableTerm) intervalRepresentingVariable, Terms.newConstant(i)); substitutions.add(ith); } return substitutions; } else { // The intervalRepresentingVariable is bound already, check if it is in the interval. if (!(intervalRepresentingVariable instanceof ConstantTerm) - || !(((ConstantTerm) intervalRepresentingVariable).getObject() instanceof Integer)) { + || !(((ConstantTerm) intervalRepresentingVariable).getObject() instanceof Integer)) { // Term is not bound to an integer constant, not in the interval. return Collections.emptyList(); } - Integer integer = (Integer) ((ConstantTerm) intervalRepresentingVariable).getObject(); + // TODO to avoid that type of unchecked cast, we may want interval terms to not extend AbstractTerm + @SuppressWarnings("unchecked") + Integer integer = ((ConstantTerm) intervalRepresentingVariable).getObject(); if (intervalTerm.getLowerBound() <= integer && integer <= intervalTerm.getUpperBound()) { return Collections.singletonList(partialSubstitution); } @@ -109,7 +115,7 @@ public List getSatisfyingSubstitutions(Substitution partialSubstit // Generate all substitutions for the interval representing variable. return groundInterval.getIntervalSubstitutions(partialSubstitution); } - + @Override public IntervalLiteral substitute(Substitution substitution) { return new IntervalLiteral(getAtom().substitute(substitution)); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/Literals.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/Literals.java similarity index 98% rename from src/main/java/at/ac/tuwien/kr/alpha/common/Literals.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/Literals.java index 8c703a54b..8c34bb1b0 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/Literals.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/Literals.java @@ -25,7 +25,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.common; +package at.ac.tuwien.kr.alpha.core.atoms; /** * Provides methods to convert atoms to literals and vice versa, diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/RuleAtom.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/RuleAtom.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/RuleAtom.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/RuleAtom.java index ff6f7a90e..605bc8dfb 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/RuleAtom.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/atoms/RuleAtom.java @@ -25,27 +25,30 @@ * 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.grounder.atoms; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.core.atoms; import java.util.Arrays; +import java.util.Collections; import java.util.List; - -import static at.ac.tuwien.kr.alpha.common.terms.ConstantTerm.getInstance; +import java.util.Set; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.literals.Literal; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; /** * Atoms corresponding to rule bodies use this predicate, first term is rule number, * second is a term containing variable substitutions. */ -public class RuleAtom extends Atom { - public static final Predicate PREDICATE = Predicate.getInstance("_R_", 2, true, true); +public class RuleAtom implements Atom { + public static final Predicate PREDICATE = Predicates.getPredicate("_R_", 2, true, true); private final List> terms; @@ -57,12 +60,10 @@ private RuleAtom(List> terms) { this.terms = terms; } - public RuleAtom(InternalRule nonGroundRule, Substitution substitution) { + public RuleAtom(CompiledRule nonGroundRule, Substitution substitution) { this(Arrays.asList( - getInstance(Integer.toString(nonGroundRule.getRuleId())), - getInstance(substitution.toString()) - ) - ); + Terms.newConstant(Integer.toString(nonGroundRule.getRuleId())), + Terms.newConstant(substitution.toString()))); } @Override @@ -80,7 +81,7 @@ public boolean isGround() { // NOTE: Both terms are ConstantTerms, which are ground by definition. return true; } - + @Override public Literal toLiteral(boolean positive) { throw new UnsupportedOperationException("RuleAtom cannot be literalized"); @@ -119,4 +120,15 @@ public String toString() { public Atom withTerms(List terms) { throw new UnsupportedOperationException("RuleAtoms do not support setting of terms!"); } + + @Override + public Set getOccurringVariables() { + // RuleAtom has 2 terms which are both constants + return Collections.emptySet(); + } + + @Override + public Atom renameVariables(String newVariablePrefix) { + throw new UnsupportedOperationException("RuleAtom does not have any variables to rename!"); + } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/Assignment.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/Assignment.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/common/Assignment.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/Assignment.java index b5aa1c6cf..47ae1790a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/Assignment.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/Assignment.java @@ -25,15 +25,15 @@ * 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.common; +package at.ac.tuwien.kr.alpha.core.common; -import at.ac.tuwien.kr.alpha.solver.Antecedent; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isNegated; import java.util.Set; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.isNegated; +import at.ac.tuwien.kr.alpha.core.solver.Antecedent; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; public interface Assignment { Entry get(int atom); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/AtomStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java similarity index 92% rename from src/main/java/at/ac/tuwien/kr/alpha/common/AtomStore.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java index ec8278b82..e55c6fcfb 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/AtomStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStore.java @@ -25,15 +25,15 @@ * 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.common; +package at.ac.tuwien.kr.alpha.core.common; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.solver.AtomCounter; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isNegated; import java.util.Iterator; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.isNegated; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.solver.AtomCounter; /** * Translates atoms between integer (solver) and object (grounder) representation. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/AtomStoreImpl.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/common/AtomStoreImpl.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java index 1e94e8381..4f9cf9a55 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/AtomStoreImpl.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/AtomStoreImpl.java @@ -25,19 +25,20 @@ * 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.common; +package at.ac.tuwien.kr.alpha.core.common; + -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.grounder.IntIdGenerator; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import at.ac.tuwien.kr.alpha.solver.AtomCounter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import static at.ac.tuwien.kr.alpha.Util.oops; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.commons.util.IntIdGenerator; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import at.ac.tuwien.kr.alpha.core.atoms.RuleAtom; +import at.ac.tuwien.kr.alpha.core.solver.AtomCounter; /** * This class stores ground atoms and provides the translation from an (integer) atomId to a (structured) predicate instance. @@ -115,7 +116,7 @@ public Atom get(int atom) { try { return atomIdsToInternalBasicAtoms.get(atom); } catch (IndexOutOfBoundsException e) { - throw oops("Unknown atom ID encountered: " + atom, e); + throw Util.oops("Unknown atom ID encountered: " + atom, e); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/IntIterator.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/IntIterator.java similarity index 88% rename from src/main/java/at/ac/tuwien/kr/alpha/common/IntIterator.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/IntIterator.java index 0e7c0790e..0b0eba55c 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/IntIterator.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/IntIterator.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.core.common; /** * An iterator returning raw int integers instead of Integer objects (for efficiency). diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/NoGood.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/NoGood.java similarity index 89% rename from src/main/java/at/ac/tuwien/kr/alpha/common/NoGood.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/NoGood.java index 84e70cd0e..3575669ba 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/NoGood.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/NoGood.java @@ -25,18 +25,25 @@ * 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.common; - -import at.ac.tuwien.kr.alpha.solver.Antecedent; +package at.ac.tuwien.kr.alpha.core.common; + +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isNegated; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.negateLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.positiveLiteral; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type.INTERNAL; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type.LEARNT; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type.STATIC; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type.SUPPORT; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.stream.IntStream; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static at.ac.tuwien.kr.alpha.common.NoGoodInterface.Type.*; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import at.ac.tuwien.kr.alpha.core.solver.Antecedent; public class NoGood implements NoGoodInterface, Comparable { public static final int HEAD = 0; @@ -58,7 +65,7 @@ private NoGood(Type type, int[] literals, boolean head) { this.type = type; this.head = head; if (head && !isNegated(literals[0])) { - throw oops("Head is not negative"); + throw Util.oops("Head is not negative"); } // HINT: this might decrease performance if NoGoods are mostly small. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/NoGoodInterface.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/NoGoodInterface.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/common/NoGoodInterface.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/NoGoodInterface.java index 95157630e..1832098c7 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/NoGoodInterface.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/NoGoodInterface.java @@ -25,9 +25,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.common; +package at.ac.tuwien.kr.alpha.core.common; -import at.ac.tuwien.kr.alpha.solver.Antecedent; +import at.ac.tuwien.kr.alpha.core.solver.Antecedent; public interface NoGoodInterface extends Iterable { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/Truth.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/Truth.java similarity index 81% rename from src/main/java/at/ac/tuwien/kr/alpha/common/Truth.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/Truth.java index 58283a094..2a1f017be 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/Truth.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/Truth.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.core.common; /** * Represents truth value that can be converted to a Boolean truth value. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BinaryPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/BinaryPredicateInterpretation.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BinaryPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/BinaryPredicateInterpretation.java index aabd4f55b..d0f62b756 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BinaryPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/BinaryPredicateInterpretation.java @@ -25,12 +25,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.common.fixedinterpretations; - -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; import java.util.List; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; + public class BinaryPredicateInterpretation extends NonBindingPredicateInterpretation { private final java.util.function.BiPredicate predicate; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BindingMethodPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/BindingMethodPredicateInterpretation.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BindingMethodPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/BindingMethodPredicateInterpretation.java index ffa76a477..a73aae4b2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/BindingMethodPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/BindingMethodPredicateInterpretation.java @@ -25,7 +25,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.common.fixedinterpretations; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.StringUtils; @@ -35,8 +35,9 @@ import java.util.List; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.BindingPredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; public class BindingMethodPredicateInterpretation implements BindingPredicateInterpretation { private final Method method; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/IntPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/IntPredicateInterpretation.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/IntPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/IntPredicateInterpretation.java index 908f34a35..dd8acc05e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/IntPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/IntPredicateInterpretation.java @@ -25,12 +25,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.common.fixedinterpretations; - -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; import java.util.List; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; + public class IntPredicateInterpretation extends NonBindingPredicateInterpretation { private final java.util.function.IntPredicate predicate; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/LongPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/LongPredicateInterpretation.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/LongPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/LongPredicateInterpretation.java index e572b78db..e5ef94663 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/LongPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/LongPredicateInterpretation.java @@ -25,12 +25,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.common.fixedinterpretations; - -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; import java.util.List; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; + public class LongPredicateInterpretation extends NonBindingPredicateInterpretation { private final java.util.function.LongPredicate predicate; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/MethodPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/MethodPredicateInterpretation.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/MethodPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/MethodPredicateInterpretation.java index 622efdaa4..ff7dc78f6 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/MethodPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/MethodPredicateInterpretation.java @@ -25,11 +25,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.common.fixedinterpretations; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; import org.apache.commons.lang3.ClassUtils; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/NonBindingPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/NonBindingPredicateInterpretation.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/NonBindingPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/NonBindingPredicateInterpretation.java index 66faab911..53ad2350b 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/NonBindingPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/NonBindingPredicateInterpretation.java @@ -25,10 +25,11 @@ * 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.common.fixedinterpretations; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/SuppliedPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/SuppliedPredicateInterpretation.java similarity index 88% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/SuppliedPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/SuppliedPredicateInterpretation.java index 33e91817b..a29adffbf 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/SuppliedPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/SuppliedPredicateInterpretation.java @@ -25,10 +25,11 @@ * 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.common.fixedinterpretations; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.BindingPredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; import java.util.List; import java.util.Set; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/UnaryPredicateInterpretation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/UnaryPredicateInterpretation.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/UnaryPredicateInterpretation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/UnaryPredicateInterpretation.java index fca1f5484..5e90b4712 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/UnaryPredicateInterpretation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/common/fixedinterpretations/UnaryPredicateInterpretation.java @@ -25,12 +25,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.common.fixedinterpretations; - -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +package at.ac.tuwien.kr.alpha.core.common.fixedinterpretations; import java.util.List; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; + public class UnaryPredicateInterpretation extends NonBindingPredicateInterpretation { private final java.util.function.Predicate predicate; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/ComponentGraph.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/ComponentGraphImpl.java similarity index 59% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/ComponentGraph.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/ComponentGraphImpl.java index 34096e4f6..1021acb81 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/ComponentGraph.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/ComponentGraphImpl.java @@ -23,11 +23,14 @@ * 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.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; import org.apache.commons.lang3.StringUtils; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -38,50 +41,52 @@ /** * Representation of an {@link InternalProgram}'s component graph, i.e. the directed acyclic graph resulting from condensing the program's - * {@link DependencyGraph} into its strongly connected components. Needed in order to calculate stratifications from which an evaluation order for the - * {@link at.ac.tuwien.kr.alpha.grounder.transformation.StratifiedEvaluation} transformation can be derived. + * {@link DependencyGraphImpl} into its strongly connected components. Needed in order to calculate stratifications from which an evaluation order for the + * {@link at.ac.tuwien.kr.alpha.core.programs.transformation.StratifiedEvaluation} transformation can be derived. * * Copyright (c) 2019-2020, the Alpha Team. */ -public final class ComponentGraph { +public final class ComponentGraphImpl implements ComponentGraph { private final ArrayList components; private final List entryPoints; - private ComponentGraph(ArrayList components, List entryPoints) { + private ComponentGraphImpl(ArrayList components, List entryPoints) { this.components = components; this.entryPoints = entryPoints; } /** - * Creates a new {@link ComponentGraph} based on a dependency graph and an {@link StronglyConnectedComponentsAlgorithm.SccResult} representing the + * Creates a new {@link ComponentGraphImpl} based on a dependency graph and an {@link StronglyConnectedComponentsAlgorithm.SccResult} representing the * result of calculating the dependency graph's strongly connected components (SCCs). * * @param dg the dependency graph backing this component graph. * @param sccResult the SCC calculation result for the dependency graph in question. - * @return a new {@link ComponentGraph} representing the strongly connected components of the given dependency graph. + * @return a new {@link ComponentGraphImpl} representing the strongly connected components of the given dependency graph. */ - public static ComponentGraph buildComponentGraph(DependencyGraph dg, StronglyConnectedComponentsAlgorithm.SccResult sccResult) { - return new ComponentGraph.Builder(dg, sccResult).build(); + public static ComponentGraphImpl buildComponentGraph(DependencyGraph dg, StronglyConnectedComponentsAlgorithm.SccResult sccResult) { + return new ComponentGraphImpl.Builder(dg, sccResult).build(); } + @Override public List getComponents() { return Collections.unmodifiableList(components); } + @Override public List getEntryPoints() { return Collections.unmodifiableList(entryPoints); } - public static class SCComponent { + public static class SCComponentImpl implements ComponentGraph.SCComponent { - private final int id; - private final List nodes; - private final Map dependencyIds; - private final Set dependentIds; - private final boolean hasNegativeCycle; + private final int id; + private final List nodes; + private final Map dependencyIds; + private final Set dependentIds; + private final boolean hasNegativeCycle; - private SCComponent(int id, List nodes, Map dependencyIds, Set dependentIds, boolean hasNegativeCycle) { + private SCComponentImpl(int id, List nodes, Map dependencyIds, Set dependentIds, boolean hasNegativeCycle) { this.id = id; this.nodes = nodes; this.dependencyIds = dependencyIds; @@ -89,10 +94,12 @@ private SCComponent(int id, List nodes, Map dependencyId this.hasNegativeCycle = hasNegativeCycle; } + @Override public Map getDependencyIds() { return Collections.unmodifiableMap(dependencyIds); } + @Override public Set getDependentIds() { return Collections.unmodifiableSet(dependentIds); } @@ -102,33 +109,36 @@ public String toString() { return "SCComponent{" + StringUtils.join(nodes, ",") + "}"; } + @Override public boolean hasNegativeCycle() { return hasNegativeCycle; } - public List getNodes() { + @Override + public List getNodes() { return nodes; } + @Override public int getId() { return id; } private static class Builder { - private int id; - private List nodes; - private Map dependencyIds = new HashMap<>(); - private Set dependentIds = new HashSet<>(); - private boolean hasNegativeCycle; + private int id; + private List nodes; + private Map dependencyIds = new HashMap<>(); + private Set dependentIds = new HashSet<>(); + private boolean hasNegativeCycle; - private Builder(int id, List nodes) { + private Builder(int id, List nodes) { this.nodes = nodes; this.id = id; } - private SCComponent build() { - return new SCComponent(id, nodes, dependencyIds, dependentIds, hasNegativeCycle); + private SCComponentImpl build() { + return new SCComponentImpl(id, nodes, dependencyIds, dependentIds, hasNegativeCycle); } } @@ -137,11 +147,11 @@ private SCComponent build() { private static class Builder { - private DependencyGraph depGraph; - private List> componentMap; - private Map nodesByComponentId; - private ArrayList componentBuilders = new ArrayList<>(); - private ArrayList components = new ArrayList<>(); + private DependencyGraph depGraph; + private List> componentMap; + private Map nodesByComponentId; + private ArrayList componentBuilders = new ArrayList<>(); + private ArrayList components = new ArrayList<>(); private Builder(DependencyGraph dg, StronglyConnectedComponentsAlgorithm.SccResult sccResult) { this.depGraph = dg; @@ -149,23 +159,23 @@ private Builder(DependencyGraph dg, StronglyConnectedComponentsAlgorithm.SccResu this.nodesByComponentId = sccResult.nodesByComponentId; } - private ComponentGraph build() { + private ComponentGraphImpl build() { // Create a ComponentBuilder for each component. for (int i = 0; i < componentMap.size(); i++) { - componentBuilders.add(new SCComponent.Builder(i, componentMap.get(i))); + componentBuilders.add(new SCComponentImpl.Builder(i, componentMap.get(i))); } // Iterate and register each edge of every component. for (int i = 0; i < componentBuilders.size(); i++) { - SCComponent.Builder builder = componentBuilders.get(i); - for (Node node : builder.nodes) { - for (Edge edge : depGraph.getAdjancencyMap().get(node)) { + SCComponentImpl.Builder builder = componentBuilders.get(i); + for (DependencyGraph.Node node : builder.nodes) { + for (DependencyGraph.Edge edge : depGraph.getAdjancencyMap().get(node)) { registerEdge(i, edge); } } } // Build each component and identify starting components. List startingPoints = new ArrayList<>(); - for (SCComponent.Builder builder : componentBuilders) { + for (SCComponentImpl.Builder builder : componentBuilders) { SCComponent tmpComponent = builder.build(); components.add(tmpComponent); // Component is starting if it has no dependencies. @@ -173,10 +183,10 @@ private ComponentGraph build() { startingPoints.add(tmpComponent); } } - return new ComponentGraph(components, startingPoints); + return new ComponentGraphImpl(components, startingPoints); } - private void registerEdge(int srcComponentId, Edge edge) { + private void registerEdge(int srcComponentId, DependencyGraph.Edge edge) { int destComponentId = nodesByComponentId.get(edge.getTarget()); if (srcComponentId == destComponentId) { // Record negative self-loop. @@ -184,9 +194,9 @@ private void registerEdge(int srcComponentId, Edge edge) { componentBuilders.get(srcComponentId).hasNegativeCycle = true; } } else { - SCComponent.Builder srcComponentBld = componentBuilders.get(srcComponentId); + SCComponentImpl.Builder srcComponentBld = componentBuilders.get(srcComponentId); srcComponentBld.dependentIds.add(destComponentId); - SCComponent.Builder destComponentBld = componentBuilders.get(destComponentId); + SCComponentImpl.Builder destComponentBld = componentBuilders.get(destComponentId); boolean isPositiveDep = true; if (destComponentBld.dependencyIds.containsKey(srcComponentId)) { isPositiveDep = destComponentBld.dependencyIds.get(srcComponentId); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/DependencyGraph.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/DependencyGraphImpl.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/DependencyGraph.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/DependencyGraphImpl.java index f0a6e2b2e..e2e2200af 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/DependencyGraph.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/DependencyGraphImpl.java @@ -23,15 +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.common.depgraph; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.FixedInterpretationLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package at.ac.tuwien.kr.alpha.core.depgraph; import java.util.ArrayList; import java.util.Collection; @@ -40,43 +32,56 @@ import java.util.List; import java.util.Map; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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.programs.literals.FixedInterpretationLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; + /** - * Internal representation of an {@link at.ac.tuwien.kr.alpha.common.program.InternalProgram}'s dependency graph. The dependency graph tracks dependencies - * between rules of a program. Each {@link Node} of the graph represents a {@link Predicate} occurring in the program. A node has an incoming {@link Edge} for + * Internal representation of an {@link at.ac.tuwien.kr.alpha.core.programs.InternalProgram}'s dependency graph. The dependency graph tracks dependencies + * between rules of a program. Each {@link NodeImpl} of the graph represents a {@link Predicate} occurring in the program. A node has an incoming {@link EdgeImpl} for * every {@link Literal} in some rule body that depends on it, i.e. the predicate of the literal in question is the same as that of the node. The "sign" flag of - * an {@link Edge} indicates whether the dependency is a positive or negative one, i.e. if the atom in question is preceded by a "not". + * an {@link EdgeImpl} indicates whether the dependency is a positive or negative one, i.e. if the atom in question is preceded by a "not". * * Note that constraints are represented by one dummy predicate (named "constr_{num}"). Each constraint node has a negative edge to itself to express the * notation of a constraint ":- a, b." as "x :- a, b, not x.". * * Copyright (c) 2019-2020, the Alpha Team. */ -public final class DependencyGraph { +public final class DependencyGraphImpl implements DependencyGraph { - private static final Logger LOGGER = LoggerFactory.getLogger(DependencyGraph.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DependencyGraphImpl.class); /* * Maps nodes to outgoing edges of that node. - * Note: using List rather than Map as one node may have positive and negative edges to + * Note: using List rather than Map as one node may have positive and negative edges to * another. */ private final Map> adjacencyMap; private final Map nodesByPredicate; - private DependencyGraph(Map> adjacencyMap, Map nodesByPredicate) { + private DependencyGraphImpl(Map> adjacencyMap, Map nodesByPredicate) { this.adjacencyMap = adjacencyMap; this.nodesByPredicate = nodesByPredicate; } - public static DependencyGraph buildDependencyGraph(Map nonGroundRules) { - return new DependencyGraph.Builder(nonGroundRules.values()).build(); + public static DependencyGraphImpl buildDependencyGraph(Map nonGroundRules) { + return new DependencyGraphImpl.Builder(nonGroundRules.values()).build(); } + @Override public Node getNodeForPredicate(Predicate p) { return nodesByPredicate.get(p); } + @Override public Map> getAdjancencyMap() { return Collections.unmodifiableMap(adjacencyMap); } @@ -86,18 +91,18 @@ private static class Builder { private static final String CONSTRAINT_PREDICATE_FORMAT = "[constr_%d]"; private int constraintNumber; - private Collection rules; + private Collection rules; private Map> adjacentNodesMap = new HashMap<>(); - private Map nodesByPredicate = new HashMap<>(); + private Map nodesByPredicate = new HashMap<>(); - private Builder(Collection rules) { + private Builder(Collection rules) { this.rules = rules; this.constraintNumber = 0; } - private DependencyGraph build() { - for (InternalRule rule : rules) { + private DependencyGraphImpl build() { + for (CompiledRule rule : rules) { LOGGER.debug("Processing rule: {}", rule); Node headNode = handleRuleHead(rule); for (Literal literal : rule.getBody()) { @@ -109,17 +114,17 @@ private DependencyGraph build() { handleRuleBodyLiteral(headNode, literal); } } - return new DependencyGraph(adjacentNodesMap, nodesByPredicate); + return new DependencyGraphImpl(adjacentNodesMap, nodesByPredicate); } - private Node handleRuleHead(InternalRule rule) { + private Node handleRuleHead(CompiledRule rule) { LOGGER.trace("Processing head of rule: {}", rule); Node headNode; if (rule.isConstraint()) { Predicate pred = generateConstraintDummyPredicate(); - headNode = new Node(pred); + headNode = new NodeImpl(pred); List dependencies = new ArrayList<>(); - dependencies.add(new Edge(headNode, false)); + dependencies.add(new EdgeImpl(headNode, false)); if (adjacentNodesMap.containsKey(headNode)) { throw new IllegalStateException("Dependency graph already contains node for constraint " + pred.toString() + "!"); } @@ -129,7 +134,7 @@ private Node handleRuleHead(InternalRule rule) { Atom head = rule.getHeadAtom(); Predicate pred = head.getPredicate(); if (!nodesByPredicate.containsKey(pred)) { - headNode = new Node(pred); + headNode = new NodeImpl(pred); adjacentNodesMap.put(headNode, new ArrayList<>()); nodesByPredicate.put(pred, headNode); } else { @@ -146,7 +151,7 @@ private void handleRuleBodyLiteral(Node headNode, Literal lit) { if (!nodesByPredicate.containsKey(bodyPred)) { LOGGER.trace("Creating new node for bodyPred {}", bodyPred); dependants = new ArrayList<>(); - bodyNode = new Node(bodyPred); + bodyNode = new NodeImpl(bodyPred); nodesByPredicate.put(bodyPred, bodyNode); adjacentNodesMap.put(bodyNode, dependants); } else { @@ -154,7 +159,7 @@ private void handleRuleBodyLiteral(Node headNode, Literal lit) { bodyNode = nodesByPredicate.get(bodyPred); dependants = adjacentNodesMap.get(bodyNode); } - Edge tmpEdge = new Edge(headNode, !lit.isNegated()); + Edge tmpEdge = new EdgeImpl(headNode, !lit.isNegated()); if (!dependants.contains(tmpEdge)) { LOGGER.trace("Adding dependency: {} -> {} ({})", bodyNode.getPredicate(), headNode.getPredicate(), tmpEdge.getSign() ? "+" : "-"); dependants.add(tmpEdge); @@ -163,7 +168,7 @@ private void handleRuleBodyLiteral(Node headNode, Literal lit) { } private Predicate generateConstraintDummyPredicate() { - return Predicate.getInstance(String.format(DependencyGraph.Builder.CONSTRAINT_PREDICATE_FORMAT, ++constraintNumber), 0); + return Predicates.getPredicate(String.format(DependencyGraphImpl.Builder.CONSTRAINT_PREDICATE_FORMAT, ++constraintNumber), 0); } } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/DepthFirstSearchAlgorithm.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/DepthFirstSearchAlgorithm.java similarity index 74% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/DepthFirstSearchAlgorithm.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/DepthFirstSearchAlgorithm.java index 02b0347e1..30cbef60c 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/DepthFirstSearchAlgorithm.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/DepthFirstSearchAlgorithm.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.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; + +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; import java.util.ArrayList; import java.util.Deque; @@ -41,9 +43,9 @@ */ class DepthFirstSearchAlgorithm { - private Set discoveredNodes; // The "gray" nodes that have been seen but not fully processed yet. - private Deque finishedNodes; // The "black" nodes that have been processed. - private Map> depthFirstReachable; // Per root node, all others that are reachable from it. + private Set discoveredNodes; // The "gray" nodes that have been seen but not fully processed yet. + private Deque finishedNodes; // The "black" nodes that have been processed. + private Map> depthFirstReachable; // Per root node, all others that are reachable from it. private DepthFirstSearchAlgorithm() { discoveredNodes = new HashSet<>(); @@ -52,7 +54,7 @@ private DepthFirstSearchAlgorithm() { depthFirstReachable.put(null, new ArrayList<>()); } - public static DfsResult performDfs(Map> graph) { + public static DfsResult performDfs(Map> graph) { return performDfs(graph.keySet().iterator(), graph); } @@ -67,14 +69,14 @@ public static DfsResult performDfs(Map> graph) { * @return a {@link DfsResult} holding all nodes in the sequence they were finished and per root node all its * depth-first reachable nodes. */ - public static DfsResult performDfs(Iterator nodeVisitIt, Map> graph) { + public static DfsResult performDfs(Iterator nodeVisitIt, Map> graph) { DepthFirstSearchAlgorithm algorithm = new DepthFirstSearchAlgorithm(); return algorithm.performDepthFirstSearchAlgorithm(nodeVisitIt, graph); } - private DfsResult performDepthFirstSearchAlgorithm(Iterator nodeVisitIt, Map> graph) { + private DfsResult performDepthFirstSearchAlgorithm(Iterator nodeVisitIt, Map> graph) { while (nodeVisitIt.hasNext()) { - Node currentNode = nodeVisitIt.next(); + DependencyGraph.Node currentNode = nodeVisitIt.next(); if (!discoveredNodes.contains(currentNode)) { depthFirstReachable.get(null).add(currentNode); dfsVisit(currentNode, currentNode, graph); @@ -86,7 +88,7 @@ private DfsResult performDepthFirstSearchAlgorithm(Iterator nodeVisitIt, M return dfsResult; } - private void dfsVisit(Node currNode, Node rootNode, Map> graph) { + private void dfsVisit(DependencyGraph.Node currNode, DependencyGraph.Node rootNode, Map> graph) { discoveredNodes.add(currNode); // Record root-reachability of current node. @@ -95,9 +97,9 @@ private void dfsVisit(Node currNode, Node rootNode, Map> graph) } depthFirstReachable.get(rootNode).add(currNode); - for (Edge edge : graph.get(currNode)) { + for (DependencyGraph.Edge edge : graph.get(currNode)) { // Proceed with adjacent (i.e., deeper) nodes first. - Node tmpNeighbor = edge.getTarget(); + DependencyGraph.Node tmpNeighbor = edge.getTarget(); if (!discoveredNodes.contains(tmpNeighbor)) { dfsVisit(tmpNeighbor, rootNode, graph); } @@ -111,7 +113,7 @@ private void dfsVisit(Node currNode, Node rootNode, Map> graph) * - per root node all reachable other nodes (including the root itself). */ static class DfsResult { - Deque finishedNodes; - Map> depthFirstReachable; + Deque finishedNodes; + Map> depthFirstReachable; } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/Edge.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/EdgeImpl.java similarity index 84% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/Edge.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/EdgeImpl.java index f286020b7..b56e2d968 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/Edge.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/EdgeImpl.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.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; + +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; /** * An edge in a dependency graph to be used in adjacency lists (i.e., only the target of the edge is recorded). Edges @@ -31,10 +33,10 @@ * * Copyright (c) 2019-2020, the Alpha Team. */ -public class Edge { +public class EdgeImpl implements DependencyGraph.Edge { - private final Node target; - private final boolean sign; + private final DependencyGraph.Node target; + private final boolean sign; /** * Creates a new edge for a dependency graph. Read as "target depends on source". The sign indicates whether the @@ -44,17 +46,17 @@ public class Edge { * @param target the target node. * @param sign the polarity of the edge. */ - public Edge(Node target, boolean sign) { + public EdgeImpl(DependencyGraph.Node target, boolean sign) { this.target = target; this.sign = sign; } @Override public boolean equals(Object o) { - if (!(o instanceof Edge)) { + if (!(o instanceof DependencyGraph.Edge)) { return false; } - Edge other = (Edge) o; + EdgeImpl other = (EdgeImpl) o; return this.target.equals(other.target) && this.sign == other.sign; } @@ -68,10 +70,12 @@ public String toString() { return "(" + (sign ? "+" : "-") + ") ---> " + target.toString(); } - public Node getTarget() { + @Override + public DependencyGraph.Node getTarget() { return target; } + @Override public boolean getSign() { return sign; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/Node.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/NodeImpl.java similarity index 85% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/Node.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/NodeImpl.java index 58ad1a0f8..e0f4d43d0 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/Node.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/NodeImpl.java @@ -23,9 +23,10 @@ * 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.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; -import at.ac.tuwien.kr.alpha.common.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; /** * A node in a dependency graph. One node references exactly one predicate. This means that all rule heads deriving the @@ -34,20 +35,20 @@ * * Copyright (c) 2017-2020, the Alpha Team. */ -public class Node { +public class NodeImpl implements DependencyGraph.Node { private final Predicate predicate; - public Node(Predicate predicate) { + public NodeImpl(Predicate predicate) { this.predicate = predicate; } @Override public boolean equals(Object o) { - if (!(o instanceof Node)) { + if (!(o instanceof NodeImpl)) { return false; } - return predicate.equals(((Node) o).predicate); + return predicate.equals(((NodeImpl) o).predicate); } @Override @@ -60,10 +61,12 @@ public String toString() { return "Node{" + predicate.toString() + "}"; } + @Override public String getLabel() { return predicate.toString(); } + @Override public Predicate getPredicate() { return predicate; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/StratificationAlgorithm.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/StratificationAlgorithm.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/StratificationAlgorithm.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/StratificationAlgorithm.java index cab16a8a9..bd7814d88 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/StratificationAlgorithm.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/StratificationAlgorithm.java @@ -23,9 +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.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph.SCComponent; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +33,7 @@ import java.util.List; /** - * Algorithm for finding a stratification of a given {@link ComponentGraph}. + * Algorithm for finding a stratification of a given {@link ComponentGraphImpl}. * * Copyright (c) 2019-2020, the Alpha Team. */ @@ -43,9 +43,9 @@ public class StratificationAlgorithm { private ComponentGraph componentGraph; - private final boolean[] visitedComponents; // Marks visited components. - private final boolean[] isUnstratifiableComponent; // Marks those known to be not stratifiable (may be due to parent not being stratifiable). - private final SCComponent[] componentEvaluationSequence; // Store the topological order of all components. + private final boolean[] visitedComponents; // Marks visited components. + private final boolean[] isUnstratifiableComponent; // Marks those known to be not stratifiable (may be due to parent not being stratifiable). + private final ComponentGraph.SCComponent[] componentEvaluationSequence; // Store the topological order of all components. private int doneComponents; private int numComponents; @@ -56,7 +56,7 @@ private StratificationAlgorithm(ComponentGraph cg) { numComponents = cg.getComponents().size(); visitedComponents = new boolean[numComponents]; isUnstratifiableComponent = new boolean[numComponents]; - componentEvaluationSequence = new SCComponent[numComponents]; + componentEvaluationSequence = new ComponentGraph.SCComponent[numComponents]; } /** @@ -68,22 +68,22 @@ private StratificationAlgorithm(ComponentGraph cg) { * @param cg the graph of strongly-connected-components (that must be acyclic). * @return a list of all stratifiable components in the order that they can be evaluated. */ - public static List calculateStratification(ComponentGraph cg) { + public static List calculateStratification(ComponentGraph cg) { return new StratificationAlgorithm(cg).runStratification(); } - private List runStratification() { + private List runStratification() { LOGGER.debug("Initial call to stratify with entry points!"); // Compute topological order and mark unstratifiable components. - for (SCComponent component : componentGraph.getEntryPoints()) { + for (ComponentGraph.SCComponent component : componentGraph.getEntryPoints()) { topoSort(component, false); } // Extract list of stratifiable components. - List stratifiableComponentsSequence = new ArrayList<>(); - for (SCComponent component : componentEvaluationSequence) { + List stratifiableComponentsSequence = new ArrayList<>(); + for (ComponentGraph.SCComponent component : componentEvaluationSequence) { if (!isUnstratifiableComponent[component.getId()]) { stratifiableComponentsSequence.add(component); } @@ -92,7 +92,7 @@ private List runStratification() { return stratifiableComponentsSequence; } - private void topoSort(SCComponent component, boolean hasUnstratifiableParent) { + private void topoSort(ComponentGraph.SCComponent component, boolean hasUnstratifiableParent) { // We compute a topological ordering using a depth-first search where for any node its position in the // topological ordering is the reverse of its finishing time (i.e., last-finishing node comes first). diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/StronglyConnectedComponentsAlgorithm.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/StronglyConnectedComponentsAlgorithm.java similarity index 62% rename from src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/StronglyConnectedComponentsAlgorithm.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/StronglyConnectedComponentsAlgorithm.java index 0854e7f3d..894a22ee5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/depgraph/StronglyConnectedComponentsAlgorithm.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/depgraph/StronglyConnectedComponentsAlgorithm.java @@ -23,29 +23,28 @@ * 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.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; + + +import java.util.*; /** - * Algorithm to find strongly connected components of a given {@link DependencyGraph}. + * Algorithm to find strongly connected components of a given {@link DependencyGraphImpl}. * * Copyright (c) 2019-2020, the Alpha Team. */ public class StronglyConnectedComponentsAlgorithm { - private Map nodesByComponentId = new HashMap<>(); + private Map nodesByComponentId = new HashMap<>(); /** - * Calculates the strongly connected components of the given {@link DependencyGraph} according to the algorithm + * Calculates the strongly connected components of the given {@link DependencyGraphImpl} according to the algorithm * given in "Introduction to algorithms" by Cormen, Leiserson, Rivest, and Stein * (aka Kosajaru-algorithm). * - * @param dg the {@link DependencyGraph} for which to compute the strongly-connected components. + * @param dg the {@link DependencyGraphImpl} for which to compute the strongly-connected components. * @return an {@link SccResult} containing a list of all strongly-connected components and a mapping of each * node to the component it belongs to. */ @@ -56,25 +55,25 @@ public static SccResult findStronglyConnectedComponents(DependencyGraph dg) { private SccResult runStronglyConnectedComponentsAlgorithm(DependencyGraph dg) { // Find al SCCs with Kosajaru's algorithm. DepthFirstSearchAlgorithm.DfsResult intermediateResult = DepthFirstSearchAlgorithm.performDfs(dg.getAdjancencyMap()); - Map> transposedNodes = transposeGraph(dg.getAdjancencyMap()); - Deque finishedNodes = intermediateResult.finishedNodes; + Map> transposedNodes = transposeGraph(dg.getAdjancencyMap()); + Deque finishedNodes = intermediateResult.finishedNodes; DepthFirstSearchAlgorithm.DfsResult finalResult = DepthFirstSearchAlgorithm.performDfs(finishedNodes.descendingIterator(), transposedNodes); // Extract components. - List> componentMap = extractComponents(finalResult); + List> componentMap = extractComponents(finalResult); return new SccResult(componentMap, nodesByComponentId); } - private List> extractComponents(DepthFirstSearchAlgorithm.DfsResult dfsResult) { + private List> extractComponents(DepthFirstSearchAlgorithm.DfsResult dfsResult) { // Each node reachable from "null" in the DfsResult points to a different strongly-connected component. - List> componentMap = new ArrayList<>(); - for (Node componentRoot : dfsResult.depthFirstReachable.get(null)) { + List> componentMap = new ArrayList<>(); + for (DependencyGraph.Node componentRoot : dfsResult.depthFirstReachable.get(null)) { int componentId = componentMap.size(); // Note: every node inside a component is reachable from its root, even the root itself. - List nodesInComponent = dfsResult.depthFirstReachable.get(componentRoot); - for (Node node : nodesInComponent) { + List nodesInComponent = dfsResult.depthFirstReachable.get(componentRoot); + for (DependencyGraph.Node node : nodesInComponent) { nodesByComponentId.put(node, componentId); } - List componentMembers = new ArrayList<>(nodesInComponent); + List componentMembers = new ArrayList<>(nodesInComponent); componentMap.add(componentMembers); } return componentMap; @@ -83,33 +82,33 @@ private List> extractComponents(DepthFirstSearchAlgorithm.DfsResult d /** * Transposes the given dependency graph, i.e. reverses the direction of each edge. */ - private static Map> transposeGraph(Map> graph) { - Map> transposed = new HashMap<>(); - for (Map.Entry> entry : graph.entrySet()) { - Node srcNode = entry.getKey(); + private static Map> transposeGraph(Map> graph) { + Map> transposed = new HashMap<>(); + for (Map.Entry> entry : graph.entrySet()) { + DependencyGraph.Node srcNode = entry.getKey(); if (!transposed.containsKey(srcNode)) { transposed.put(srcNode, new ArrayList<>()); } - for (Edge e : entry.getValue()) { - Node targetNode = e.getTarget(); + for (DependencyGraph.Edge e : entry.getValue()) { + DependencyGraph.Node targetNode = e.getTarget(); if (!transposed.containsKey(e.getTarget())) { transposed.put(targetNode, new ArrayList<>()); } - transposed.get(targetNode).add(new Edge(srcNode, e.getSign())); + transposed.get(targetNode).add(new EdgeImpl(srcNode, e.getSign())); } } return transposed; } /** - * Represents the result of a search for strongly connected components on a {@link DependencyGraph}. + * Represents the result of a search for strongly connected components on a {@link DependencyGraphImpl}. */ public static class SccResult { - final List> stronglyConnectedComponents; // List of strongly-connected-components (each component being a list of nodes). - final Map nodesByComponentId; // Reverse association of stronglyConnectedComponents. + final List> stronglyConnectedComponents; // List of strongly-connected-components (each component being a list of nodes). + final Map nodesByComponentId; // Reverse association of stronglyConnectedComponents. - SccResult(List> components, Map nodesByComponentId) { + SccResult(List> components, Map nodesByComponentId) { this.stronglyConnectedComponents = components; this.nodesByComponentId = nodesByComponentId; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/externals/stdlib/AspStandardLibrary.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/externals/AspStandardLibrary.java similarity index 98% rename from src/main/java/at/ac/tuwien/kr/alpha/api/externals/stdlib/AspStandardLibrary.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/externals/AspStandardLibrary.java index 973e738de..30aad5eed 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/externals/stdlib/AspStandardLibrary.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/externals/AspStandardLibrary.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.api.externals.stdlib; +package at.ac.tuwien.kr.alpha.core.externals; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -32,8 +32,8 @@ import java.util.Set; import at.ac.tuwien.kr.alpha.api.externals.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Terms; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; /** * Collection of methods that can be used as external atoms from ASP programs. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Externals.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/externals/Externals.java similarity index 79% rename from src/main/java/at/ac/tuwien/kr/alpha/api/externals/Externals.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/externals/Externals.java index 9f2f459b1..a4e02806a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/externals/Externals.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/externals/Externals.java @@ -1,17 +1,17 @@ /** * Copyright (c) 2020, 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,22 +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.api.externals; - -import at.ac.tuwien.kr.alpha.api.externals.stdlib.AspStandardLibrary; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.BinaryPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.BindingMethodPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.IntPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.LongPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.MethodPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.SuppliedPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.UnaryPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import org.reflections.Reflections; -import org.reflections.scanners.MethodAnnotationsScanner; +package at.ac.tuwien.kr.alpha.core.externals; import java.lang.reflect.Method; import java.util.ArrayList; @@ -49,6 +34,24 @@ import java.util.Map; import java.util.Set; +import org.reflections.Reflections; +import org.reflections.scanners.MethodAnnotationsScanner; + +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.externals.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +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.common.fixedinterpretations.BinaryPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.BindingMethodPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.IntPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.LongPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.MethodPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.SuppliedPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.UnaryPredicateInterpretation; + public final class Externals { // Private constructor since this is a utility class. @@ -106,7 +109,7 @@ public static PredicateInterpretation processPredicateMethod(Method method) { } throw new IllegalArgumentException("Passed method has unexpected return type. Should be either boolean or start with " - + PredicateInterpretation.EVALUATE_RETURN_TYPE_NAME_PREFIX + "."); + + PredicateInterpretation.EVALUATE_RETURN_TYPE_NAME_PREFIX + "."); } public static PredicateInterpretation processPredicate(java.util.function.Predicate predicate) { @@ -134,7 +137,7 @@ public static PredicateInterpretation processPredicate(java.util.function.Suppli * Every item in the collection is wrapped in a {@link ConstantTerm}, which is the argument of a unary predicate whose * symbol is the class name of the given class (i.e. the declared type of objects inside the collection), modified to * start with a lower-case letter. - * + * * @param the type of the objects to use as facts * @param classOfExtFacts the {@link Class} object of the value type * @param extFacts a {@link Collection} of objects of type classOfExtFacts @@ -146,7 +149,7 @@ public static > List asFacts(Class classOfExtFa String javaName = classOfExtFacts.getSimpleName(); String name = javaName.substring(0, 1).toLowerCase() + javaName.substring(1); // Camel-cased, but starting with lower case letter. for (T instance : extFacts) { - retVal.add(new BasicAtom(at.ac.tuwien.kr.alpha.common.Predicate.getInstance(name, 1), ConstantTerm.getInstance(instance))); + retVal.add(Atoms.newBasicAtom(Predicates.getPredicate(name, 1), Terms.newConstant(instance))); } return retVal; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/AbstractGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/AbstractGrounder.java similarity index 77% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/AbstractGrounder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/AbstractGrounder.java index 0d75fb5a3..7c5cdd7cd 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/AbstractGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/AbstractGrounder.java @@ -1,6 +1,6 @@ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import at.ac.tuwien.kr.alpha.common.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; /** * Copyright (c) 2016, the Alpha Team. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/BridgedGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/BridgedGrounder.java similarity index 65% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/BridgedGrounder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/BridgedGrounder.java index 55c04d942..406ced3b0 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/BridgedGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/BridgedGrounder.java @@ -1,14 +1,15 @@ -package at.ac.tuwien.kr.alpha.grounder; - -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.bridges.Bridge; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.HashSet; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.commons.util.IntIdGenerator; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.grounder.bridges.Bridge; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; + public abstract class BridgedGrounder extends AbstractGrounder { protected final Bridge[] bridges; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/ChoiceRecorder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/ChoiceRecorder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java index c807e0bae..19b012b41 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/ChoiceRecorder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceRecorder.java @@ -25,19 +25,21 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; + +import at.ac.tuwien.kr.alpha.commons.util.IntIdGenerator; +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 at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import java.util.*; -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static at.ac.tuwien.kr.alpha.grounder.atoms.ChoiceAtom.off; -import static at.ac.tuwien.kr.alpha.grounder.atoms.ChoiceAtom.on; +import static at.ac.tuwien.kr.alpha.core.atoms.ChoiceAtom.off; +import static at.ac.tuwien.kr.alpha.core.atoms.ChoiceAtom.on; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.*; import static java.util.Collections.emptyList; public class ChoiceRecorder { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/FactIntervalEvaluator.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/FactIntervalEvaluator.java similarity index 83% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/FactIntervalEvaluator.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/FactIntervalEvaluator.java index d22f549c8..197df1254 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/FactIntervalEvaluator.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/FactIntervalEvaluator.java @@ -1,15 +1,16 @@ -package at.ac.tuwien.kr.alpha.grounder; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; + /** * Helper functions to evaluate facts potentially containing intervals. * Copyright (c) 2017, the Alpha Team. @@ -18,6 +19,7 @@ public class FactIntervalEvaluator { /** * Helper to construct Instances from a fact that may contain intervals. + * * @param fact the fact potentially containing intervals. * @return all instances stemming from unfolding the intervals. */ @@ -61,7 +63,7 @@ private static List unrollInstances(Term[] currentTerms, int currentPo for (int i = lower; i <= upper; i++) { Term[] clonedTerms = currentTerms.clone(); - clonedTerms[currentPosition] = ConstantTerm.getInstance(i); + clonedTerms[currentPosition] = Terms.newConstant(i); instances.addAll(unrollInstances(clonedTerms, currentPosition + 1)); } return instances; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/FilteringGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/FilteringGrounder.java similarity index 77% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/FilteringGrounder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/FilteringGrounder.java index c5a5e82e4..9e428542a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/FilteringGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/FilteringGrounder.java @@ -1,6 +1,6 @@ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import at.ac.tuwien.kr.alpha.common.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; /** * Copyright (c) 2016, the Alpha Team. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Grounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/Grounder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java index 41849fa53..2c697f955 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Grounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Grounder.java @@ -25,18 +25,19 @@ * 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.grounder; - -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.IntIterator; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import org.apache.commons.lang3.tuple.Pair; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.Map; import java.util.Set; +import org.apache.commons.lang3.tuple.Pair; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.IntIterator; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + public interface Grounder { /** * Translates an answer-set represented by true atom IDs into its logical representation. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/GrounderFactory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/GrounderFactory.java similarity index 73% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/GrounderFactory.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/GrounderFactory.java index 5c3afda3a..1228c74b5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/GrounderFactory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/GrounderFactory.java @@ -25,30 +25,32 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.config.InputConfig; -import at.ac.tuwien.kr.alpha.grounder.bridges.Bridge; -import at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.api.config.InputConfig; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.grounder.bridges.Bridge; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; public final class GrounderFactory { - public static Grounder getInstance(String name, InternalProgram program, AtomStore atomStore, java.util.function.Predicate filter, GrounderHeuristicsConfiguration heuristicsConfiguration, boolean debugInternalChecks, Bridge... bridges) { + public static Grounder getInstance(String name, CompiledProgram program, AtomStore atomStore, java.util.function.Predicate filter, + GrounderHeuristicsConfiguration heuristicsConfiguration, boolean debugInternalChecks, Bridge... bridges) { switch (name.toLowerCase()) { case "naive": return new NaiveGrounder(program, atomStore, filter, heuristicsConfiguration, debugInternalChecks, bridges); } throw new IllegalArgumentException("Unknown grounder requested."); } - - public static Grounder getInstance(String name, InternalProgram program, AtomStore atomStore, java.util.function.Predicate filter, + + public static Grounder getInstance(String name, CompiledProgram program, AtomStore atomStore, java.util.function.Predicate filter, GrounderHeuristicsConfiguration heuristicsConfiguration, boolean debugInternalChecks) { return getInstance(name, program, atomStore, filter, heuristicsConfiguration, debugInternalChecks, new Bridge[] {}); } - - public static Grounder getInstance(String name, InternalProgram program, AtomStore atomStore, boolean debugInternalChecks) { - return getInstance(name, program, atomStore, InputConfig.DEFAULT_FILTER, new GrounderHeuristicsConfiguration(), debugInternalChecks); + + public static Grounder getInstance(String name, CompiledProgram program, AtomStore atomStore, boolean debugInternalChecks) { + return getInstance(name, program, atomStore, InputConfig.DEFAULT_FILTER, + new GrounderHeuristicsConfiguration(), debugInternalChecks); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/IndexedInstanceStorage.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/IndexedInstanceStorage.java similarity index 92% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/IndexedInstanceStorage.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/IndexedInstanceStorage.java index d20481674..2be5302a5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/IndexedInstanceStorage.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/IndexedInstanceStorage.java @@ -25,7 +25,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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.ArrayList; import java.util.Collections; @@ -36,9 +36,10 @@ import java.util.Map; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.Term; +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.substitutions.Instance; /** * A storage for instances with a certain arity, where each position of the instance can be indexed. @@ -83,7 +84,7 @@ public void markRecentlyAddedInstancesDone() { public void addIndexPosition(int position) { if (position < 0 || position > predicate.getArity() - 1) { throw new RuntimeException("Requested to create indices for attribute out of range." + - "IndexedInstanceStorage: " + this + " requested indices position: " + position); + "IndexedInstanceStorage: " + this + " requested indices position: " + position); } // Add index indices.set(position, new LinkedHashMap<>()); @@ -99,13 +100,14 @@ public void addIndexPosition(int position) { public void removeIndexPosition(int position) { if (position < 0 || position > predicate.getArity() - 1) { throw new RuntimeException("Requested to create indices for attribute out of range." + - "IndexedInstanceStorage: " + this + " requested indices position: " + position); + "IndexedInstanceStorage: " + this + " requested indices position: " + position); } indices.set(position, null); } /** * Returns whether an instance is already contained in the storage. + * * @param instance the instance to check for containment. * @return true if the instance is already contained in the storage. */ @@ -116,8 +118,8 @@ public boolean containsInstance(Instance instance) { public void addInstance(Instance instance) { if (instance.terms.size() != predicate.getArity()) { throw new RuntimeException("Instance length does not match arity of IndexedInstanceStorage: " + - "instance size: " + instance.terms.size() - + " IndexedInstanceStorage: " + this); + "instance size: " + instance.terms.size() + + " IndexedInstanceStorage: " + this); } instances.add(instance); recentlyAddedInstances.add(instance); @@ -129,7 +131,7 @@ public void addInstance(Instance instance) { } posIndex.putIfAbsent(instance.terms.get(i), new ArrayList<>()); ArrayList matchingInstancesAtPos = posIndex.get(instance.terms.get(i)); - matchingInstancesAtPos.add(instance); // Add instance + matchingInstancesAtPos.add(instance); // Add instance } } @@ -145,7 +147,7 @@ public void removeInstance(Instance instance) { continue; } ArrayList matchingInstancesAtPos = posIndex.get(instance.terms.get(i)); - matchingInstancesAtPos.remove(instance); // Remove instance + matchingInstancesAtPos.remove(instance); // Remove instance // If there are no more instances having the term at the current position, // remove the entry from the hash. @@ -163,6 +165,7 @@ public List getRecentlyAddedInstances() { /** * Returns a list of all instances having the given term at the given position. Returns null if no such * instances exist. + * * @param term * @param position * @return @@ -176,7 +179,6 @@ public List getInstancesMatchingAtPosition(Term term, int position) { return matchingInstances == null ? Collections.emptyList() : matchingInstances; } - private int getMostSelectiveGroundTermPosition(Atom atom) { int smallestNumberOfInstances = Integer.MAX_VALUE; int mostSelectiveTermPosition = -1; @@ -218,4 +220,4 @@ public Set getAllInstances() { public String toString() { return (positive ? "+" : "-") + predicate; } -} \ No newline at end of file +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/NaiveGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java similarity index 84% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/NaiveGrounder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java index 8a54946a4..1e498d50d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/NaiveGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounder.java @@ -1,19 +1,19 @@ /** * Copyright (c) 2016-2019, 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. - * + * 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 @@ -25,15 +25,10 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; import java.util.ArrayList; import java.util.Collection; @@ -48,31 +43,39 @@ import java.util.SortedSet; import java.util.TreeSet; -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.BasicAnswerSet; -import at.ac.tuwien.kr.alpha.common.IntIterator; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.atoms.ChoiceAtom; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import at.ac.tuwien.kr.alpha.grounder.bridges.Bridge; -import at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration; -import at.ac.tuwien.kr.alpha.grounder.instantiation.AssignmentStatus; -import at.ac.tuwien.kr.alpha.grounder.instantiation.BindingResult; -import at.ac.tuwien.kr.alpha.grounder.instantiation.DefaultLazyGroundingInstantiationStrategy; -import at.ac.tuwien.kr.alpha.grounder.instantiation.LiteralInstantiationResult; -import at.ac.tuwien.kr.alpha.grounder.instantiation.LiteralInstantiator; -import at.ac.tuwien.kr.alpha.grounder.structure.AnalyzeUnjustified; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.AnswerSets; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import at.ac.tuwien.kr.alpha.core.atoms.ChoiceAtom; +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.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.IntIterator; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface; +import at.ac.tuwien.kr.alpha.core.grounder.bridges.Bridge; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.AssignmentStatus; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.DefaultLazyGroundingInstantiationStrategy; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.LiteralInstantiationResult; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.LiteralInstantiator; +import at.ac.tuwien.kr.alpha.core.grounder.structure.AnalyzeUnjustified; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; /** * A semi-naive grounder. @@ -87,14 +90,14 @@ public class NaiveGrounder extends BridgedGrounder implements ProgramAnalyzingGr private final NogoodRegistry registry = new NogoodRegistry(); final NoGoodGenerator noGoodGenerator; private final ChoiceRecorder choiceRecorder; - private final InternalProgram program; + private final CompiledProgram program; private final AnalyzeUnjustified analyzeUnjustified; private final Map> factsFromProgram; private final Map> rulesUsingPredicateWorkingMemory = new HashMap<>(); - private final Map knownNonGroundRules; + private final Map knownNonGroundRules; - private ArrayList fixedRules = new ArrayList<>(); + private ArrayList fixedRules = new ArrayList<>(); private LinkedHashSet removeAfterObtainingNewNoGoods = new LinkedHashSet<>(); private final boolean debugInternalChecks; @@ -105,16 +108,16 @@ public class NaiveGrounder extends BridgedGrounder implements ProgramAnalyzingGr private final LiteralInstantiator ruleInstantiator; private final DefaultLazyGroundingInstantiationStrategy instantiationStrategy; - public NaiveGrounder(InternalProgram program, AtomStore atomStore, boolean debugInternalChecks, Bridge... bridges) { + public NaiveGrounder(CompiledProgram program, AtomStore atomStore, boolean debugInternalChecks, Bridge... bridges) { this(program, atomStore, new GrounderHeuristicsConfiguration(), debugInternalChecks, bridges); } - private NaiveGrounder(InternalProgram program, AtomStore atomStore, GrounderHeuristicsConfiguration heuristicsConfiguration, boolean debugInternalChecks, + private NaiveGrounder(CompiledProgram program, AtomStore atomStore, GrounderHeuristicsConfiguration heuristicsConfiguration, boolean debugInternalChecks, Bridge... bridges) { this(program, atomStore, p -> true, heuristicsConfiguration, debugInternalChecks, bridges); } - NaiveGrounder(InternalProgram program, AtomStore atomStore, java.util.function.Predicate filter, + NaiveGrounder(CompiledProgram program, AtomStore atomStore, java.util.function.Predicate filter, GrounderHeuristicsConfiguration heuristicsConfiguration, boolean debugInternalChecks, Bridge... bridges) { super(filter, bridges); this.atomStore = atomStore; @@ -130,7 +133,7 @@ private NaiveGrounder(InternalProgram program, AtomStore atomStore, GrounderHeur this.initializeFactsAndRules(); - final Set uniqueGroundRulePerGroundHead = getRulesWithUniqueHead(); + final Set uniqueGroundRulePerGroundHead = getRulesWithUniqueHead(); choiceRecorder = new ChoiceRecorder(atomStore); noGoodGenerator = new NoGoodGenerator(atomStore, choiceRecorder, factsFromProgram, this.program, uniqueGroundRulePerGroundHead); @@ -159,7 +162,7 @@ private void initializeFactsAndRules() { workingMemory.initialize(ChoiceAtom.ON); // Initialize rules and constraints in working memory. - for (InternalRule nonGroundRule : program.getRulesById().values()) { + for (CompiledRule nonGroundRule : program.getRulesById().values()) { // Create working memories for all predicates occurring in the rule. for (Predicate predicate : nonGroundRule.getOccurringPredicates()) { // FIXME: this also contains interval/builtin predicates that are not needed. @@ -167,30 +170,30 @@ private void initializeFactsAndRules() { } // If the rule has fixed ground instantiations, it is not registered but grounded once like facts. - if (nonGroundRule.getGroundingOrders().fixedInstantiation()) { + if (nonGroundRule.getGroundingInfo().hasFixedInstantiation()) { fixedRules.add(nonGroundRule); continue; } // Register each starting literal at the corresponding working memory. - for (Literal literal : nonGroundRule.getGroundingOrders().getStartingLiterals()) { + for (Literal literal : nonGroundRule.getGroundingInfo().getStartingLiterals()) { registerLiteralAtWorkingMemory(literal, nonGroundRule); } } } - private Set getRulesWithUniqueHead() { + private Set getRulesWithUniqueHead() { // FIXME: below optimisation (adding support nogoods if there is only one rule instantiation per unique atom over the interpretation) could // be done as a transformation (adding a non-ground constraint corresponding to the nogood that is generated by the grounder). // Record all unique rule heads. - final Set uniqueGroundRulePerGroundHead = new HashSet<>(); + final Set uniqueGroundRulePerGroundHead = new HashSet<>(); - for (Map.Entry> headDefiningRules : program.getPredicateDefiningRules().entrySet()) { + for (Map.Entry> headDefiningRules : program.getPredicateDefiningRules().entrySet()) { if (headDefiningRules.getValue().size() != 1) { continue; } - InternalRule nonGroundRule = headDefiningRules.getValue().iterator().next(); + CompiledRule nonGroundRule = headDefiningRules.getValue().iterator().next(); // Check that all variables of the body also occur in the head (otherwise grounding is not unique). Atom headAtom = nonGroundRule.getHeadAtom(); @@ -221,7 +224,7 @@ private Set getRulesWithUniqueHead() { * * @param nonGroundRule the rule in which the literal occurs. */ - private void registerLiteralAtWorkingMemory(Literal literal, InternalRule nonGroundRule) { + private void registerLiteralAtWorkingMemory(Literal literal, CompiledRule nonGroundRule) { if (literal.isNegated()) { throw new RuntimeException("Literal to register is negated. Should not happen."); } @@ -275,15 +278,15 @@ public AnswerSet assignmentToAnswerSet(Iterable trueAtoms) { predicateInstances.putIfAbsent(factPredicate, new TreeSet<>()); for (Instance factInstance : facts.getValue()) { SortedSet instances = predicateInstances.get(factPredicate); - instances.add(new BasicAtom(factPredicate, factInstance.terms)); + instances.add(Atoms.newBasicAtom(factPredicate, factInstance.terms)); } } if (knownPredicates.isEmpty()) { - return BasicAnswerSet.EMPTY; + return AnswerSets.EMPTY_SET; } - return new BasicAnswerSet(knownPredicates, predicateInstances); + return AnswerSets.newAnswerSet(knownPredicates, predicateInstances); } /** @@ -299,10 +302,10 @@ protected HashMap bootstrap() { workingMemory.addInstances(predicate, true, factsFromProgram.get(predicate)); } - for (InternalRule nonGroundRule : fixedRules) { + for (CompiledRule nonGroundRule : fixedRules) { // Generate NoGoods for all rules that have a fixed grounding. - RuleGroundingOrder groundingOrder = nonGroundRule.getGroundingOrders().getFixedGroundingOrder(); - BindingResult bindingResult = getGroundInstantiations(nonGroundRule, groundingOrder, new Substitution(), null); + RuleGroundingOrder groundingOrder = nonGroundRule.getGroundingInfo().getFixedGroundingOrder(); + BindingResult bindingResult = getGroundInstantiations(nonGroundRule, groundingOrder, new BasicSubstitution(), null); groundAndRegister(nonGroundRule, bindingResult.getGeneratedSubstitutions(), groundNogoods); } @@ -334,14 +337,14 @@ public Map getNoGoods(Assignment currentAssignment) { for (FirstBindingAtom firstBindingAtom : firstBindingAtoms) { // Use the recently added instances from the modified working memory to construct an initial substitution - InternalRule nonGroundRule = firstBindingAtom.rule; + CompiledRule nonGroundRule = firstBindingAtom.rule; // Generate substitutions from each recent instance. for (Instance instance : modifiedWorkingMemory.getRecentlyAddedInstances()) { // Check instance if it matches with the atom. - final Substitution unifier = Substitution.specializeSubstitution(firstBindingAtom.startingLiteral, instance, - Substitution.EMPTY_SUBSTITUTION); + final Substitution unifier = BasicSubstitution.specializeSubstitution(firstBindingAtom.startingLiteral, instance, + BasicSubstitution.EMPTY_SUBSTITUTION); if (unifier == null) { continue; @@ -349,7 +352,7 @@ public Map getNoGoods(Assignment currentAssignment) { final BindingResult bindingResult = getGroundInstantiations( nonGroundRule, - nonGroundRule.getGroundingOrders().orderStartingFrom(firstBindingAtom.startingLiteral), + nonGroundRule.getGroundingInfo().orderStartingFrom(firstBindingAtom.startingLiteral), unifier, currentAssignment); @@ -397,7 +400,7 @@ public Map getNoGoods(Assignment currentAssignment) { * @param substitutions the substitutions to be applied. * @param newNoGoods a set of nogoods to which newly generated nogoods will be added. */ - private void groundAndRegister(final InternalRule nonGroundRule, final List substitutions, final Map newNoGoods) { + private void groundAndRegister(final CompiledRule nonGroundRule, final List substitutions, final Map newNoGoods) { for (Substitution substitution : substitutions) { List generatedNoGoods = noGoodGenerator.generateNoGoodsFromGroundSubstitution(nonGroundRule, substitution); registry.register(generatedNoGoods, newNoGoods); @@ -410,7 +413,7 @@ public int register(NoGood noGood) { } // Ideally, this method should be private. It's only visible because NaiveGrounderTest needs to access it. - BindingResult getGroundInstantiations(InternalRule rule, RuleGroundingOrder groundingOrder, Substitution partialSubstitution, + BindingResult getGroundInstantiations(CompiledRule rule, RuleGroundingOrder groundingOrder, Substitution partialSubstitution, Assignment currentAssignment) { int tolerance = heuristicsConfiguration.getTolerance(rule.isConstraint()); if (tolerance < 0) { @@ -435,13 +438,13 @@ BindingResult getGroundInstantiations(InternalRule rule, RuleGroundingOrder grou } /** - * Helper method used by {@link NaiveGrounder#bindNextAtomInRule(RuleGroundingOrder, int, int, int, Substitution)}. - * - * Takes an ImmutablePair of a {@link Substitution} and an accompanying {@link AssignmentStatus} and calls + * Helper method used by {@link NaiveGrounder#bindNextAtomInRule(RuleGroundingOrderImpl, int, int, int, BasicSubstitution)}. + * + * Takes an ImmutablePair of a {@link BasicSubstitution} and an accompanying {@link AssignmentStatus} and calls * bindNextAtomInRule for the next literal in the grounding order. * If the assignment status for the last bound literal was {@link AssignmentStatus#UNASSIGNED}, the remainingTolerance * parameter is decreased by 1. If the remaining tolerance drops below zero, this method returns an empty {@link BindingResult}. - * + * * @param groundingOrder * @param orderPosition * @param originalTolerance @@ -491,12 +494,12 @@ private BindingResult pushBackAndBindNextAtomInRule(RuleGroundingOrder grounding //@formatter:off /** - * Computes ground substitutions for a literal based on a {@link RuleGroundingOrder} and a {@link Substitution}. - * + * Computes ground substitutions for a literal based on a {@link RuleGroundingOrderImpl} and a {@link BasicSubstitution}. + * * Computes ground substitutions for the literal at position orderPosition of groundingOrder * Actual substitutions are computed by this grounder's {@link LiteralInstantiator}. - * - * @param groundingOrder a {@link RuleGroundingOrder} representing the body literals of a rule in the + * + * @param groundingOrder a {@link RuleGroundingOrderImpl} representing the body literals of a rule in the * sequence in which the should be bound during grounding. * @param orderPosition the current position within groundingOrder, indicates which literal should be bound * @param originalTolerance the original tolerance of the used grounding heuristic @@ -585,7 +588,7 @@ public void forgetAssignment(int[] atomIds) { } @Override - public InternalRule getNonGroundRule(Integer ruleId) { + public CompiledRule getNonGroundRule(Integer ruleId) { return knownNonGroundRules.get(ruleId); } @@ -617,8 +620,8 @@ 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 Predicate#isSolverInternal()} (except {@link RuleAtom}s, which are allowed). - * + * atoms which are not {@link PredicateImpl#isSolverInternal()} (except {@link RuleAtom}s, which are allowed). + * * @param newNoGoods */ private void checkTypesOfNoGoods(Collection newNoGoods) { @@ -635,10 +638,10 @@ private void checkTypesOfNoGoods(Collection newNoGoods) { } private static class FirstBindingAtom { - final InternalRule rule; + final CompiledRule rule; final Literal startingLiteral; - FirstBindingAtom(InternalRule rule, Literal startingLiteral) { + FirstBindingAtom(CompiledRule rule, Literal startingLiteral) { this.rule = rule; this.startingLiteral = startingLiteral; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/NoGoodGenerator.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java similarity index 83% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/NoGoodGenerator.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java index 75a27929d..3d97e7fa6 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/NoGoodGenerator.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGenerator.java @@ -25,11 +25,11 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.common.Literals.negateLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.negateLiteral; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -40,16 +40,18 @@ import java.util.Map; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.FixedInterpretationLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.atoms.EnumerationAtom; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.literals.FixedInterpretationLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; +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 at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; /** * Class to generate ground NoGoods out of non-ground rules and grounding substitutions. @@ -59,10 +61,10 @@ public class NoGoodGenerator { private final AtomStore atomStore; private final ChoiceRecorder choiceRecorder; private final Map> factsFromProgram; - private final InternalProgram programAnalysis; - private final Set uniqueGroundRulePerGroundHead; + private final CompiledProgram programAnalysis; + private final Set uniqueGroundRulePerGroundHead; - NoGoodGenerator(AtomStore atomStore, ChoiceRecorder recorder, Map> factsFromProgram, InternalProgram programAnalysis, Set uniqueGroundRulePerGroundHead) { + NoGoodGenerator(AtomStore atomStore, ChoiceRecorder recorder, Map> factsFromProgram, CompiledProgram programAnalysis, Set uniqueGroundRulePerGroundHead) { this.atomStore = atomStore; this.choiceRecorder = recorder; this.factsFromProgram = factsFromProgram; @@ -80,7 +82,7 @@ public class NoGoodGenerator { * Assumption: atoms with fixed interpretation evaluate to true under the substitution. * @return a list of the NoGoods corresponding to the ground rule. */ - List generateNoGoodsFromGroundSubstitution(final InternalRule nonGroundRule, final Substitution substitution) { + List generateNoGoodsFromGroundSubstitution(final CompiledRule nonGroundRule, final Substitution substitution) { final List posLiterals = collectPosLiterals(nonGroundRule, substitution); final List negLiterals = collectNegLiterals(nonGroundRule, substitution); @@ -138,7 +140,7 @@ List generateNoGoodsFromGroundSubstitution(final InternalRule nonGroundR return result; } - List collectNegLiterals(final InternalRule nonGroundRule, final Substitution substitution) { + List collectNegLiterals(final CompiledRule nonGroundRule, final Substitution substitution) { final List bodyLiteralsNegative = new ArrayList<>(); for (Literal lit : nonGroundRule.getNegativeBody()) { Atom groundAtom = lit.getAtom().substitute(substitution); @@ -160,7 +162,7 @@ List collectNegLiterals(final InternalRule nonGroundRule, final Substit return bodyLiteralsNegative; } - private List collectPosLiterals(final InternalRule nonGroundRule, final Substitution substitution) { + private List collectPosLiterals(final CompiledRule nonGroundRule, final Substitution substitution) { final List bodyLiteralsPositive = new ArrayList<>(); for (Literal lit : nonGroundRule.getPositiveBody()) { if (lit instanceof FixedInterpretationLiteral) { @@ -197,7 +199,7 @@ private List collectPosLiterals(final InternalRule nonGroundRule, final } private boolean existsRuleWithPredicateInHead(final Predicate predicate) { - final HashSet definingRules = programAnalysis.getPredicateDefiningRules().get(predicate); + final HashSet definingRules = programAnalysis.getPredicateDefiningRules().get(predicate); return definingRules != null && !definingRules.isEmpty(); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/NogoodRegistry.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java similarity index 88% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/NogoodRegistry.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java index 43fdd9fce..970ab86e6 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/NogoodRegistry.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/NogoodRegistry.java @@ -1,10 +1,11 @@ -package at.ac.tuwien.kr.alpha.grounder; - -import at.ac.tuwien.kr.alpha.common.NoGood; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.LinkedHashMap; import java.util.Map; +import at.ac.tuwien.kr.alpha.commons.util.IntIdGenerator; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + public class NogoodRegistry { private static final IntIdGenerator ID_GENERATOR = new IntIdGenerator(); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/ProgramAnalyzingGrounder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ProgramAnalyzingGrounder.java similarity index 73% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/ProgramAnalyzingGrounder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ProgramAnalyzingGrounder.java index 0ff1f153e..d64388123 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/ProgramAnalyzingGrounder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/ProgramAnalyzingGrounder.java @@ -1,12 +1,12 @@ -package at.ac.tuwien.kr.alpha.grounder; - -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; + /** * Copyright (c) 2017, the Alpha Team. */ @@ -32,5 +32,5 @@ public interface ProgramAnalyzingGrounder extends Grounder { * @param ruleId the id of the rule. * @return the corresponding NonGroundRule. */ - InternalRule getNonGroundRule(Integer ruleId); + CompiledRule getNonGroundRule(Integer ruleId); } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingInfo.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingInfo.java new file mode 100644 index 000000000..a4e41e69e --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingInfo.java @@ -0,0 +1,20 @@ +package at.ac.tuwien.kr.alpha.core.grounder; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; + +public interface RuleGroundingInfo { + + boolean hasFixedInstantiation(); + + // TODO this should be an Optional + RuleGroundingOrder getFixedGroundingOrder(); + + List getStartingLiterals(); + + RuleGroundingOrder orderStartingFrom(Literal startingLiteral); + + void computeGroundingOrders(); + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrders.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingInfoImpl.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrders.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingInfoImpl.java index 6d903d938..7ec5430f3 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrders.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingInfoImpl.java @@ -25,7 +25,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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.ArrayList; import java.util.Collection; @@ -37,10 +37,10 @@ import java.util.List; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; /** * Provides the grounder with information on the order to ground the literals in the body of a rule. @@ -60,16 +60,16 @@ * Note that rules with self-joins (rules with p(X,Y), p(A,B) in their body) make it necessary that every positive * literal (whose interpretation is not fixed) is a starting literal, at least for the current grounding procedure. */ -public class RuleGroundingOrders { - private final InternalRule internalRule; - HashMap groundingOrders; +public class RuleGroundingInfoImpl implements RuleGroundingInfo { + private final CompiledRule internalRule; + HashMap groundingOrders; private HashMap literalSelectivity; private List startingLiterals; private final boolean fixedGroundingInstantiation; - private RuleGroundingOrder fixedGroundingOrder; + private RuleGroundingOrderImpl fixedGroundingOrder; - public RuleGroundingOrders(InternalRule internalRule) { + public RuleGroundingInfoImpl(CompiledRule internalRule) { this.internalRule = internalRule; this.literalSelectivity = new HashMap<>(); resetLiteralSelectivity(); @@ -86,25 +86,25 @@ private void resetLiteralSelectivity() { /** * Computes starting literals and indicates whether there is a fixed ground instantiation for this rule. + * * @return true iff the rule has a fixed ground instantiation. */ private boolean computeStartingLiterals() { LinkedHashSet fixedStartingLiterals = new LinkedHashSet<>(); LinkedHashSet ordinaryStartingLiterals = new LinkedHashSet<>(); - + // If the rule is ground, every body literal is a starting literal and the ground instantiation is fixed. if (internalRule.isGround()) { startingLiterals = new LinkedList<>(internalRule.getBody()); return true; } - + // Check each literal in the rule body whether it is eligible. for (Literal literal : internalRule.getBody()) { // Only literals that need no variables already bound can start grounding. if (literal.getNonBindingVariables().size() != 0) { continue; } - if (literal.getAtom() instanceof BasicAtom && !literal.isNegated()) { // Positive BasicAtom is the main/ordinary case. ordinaryStartingLiterals.add(literal); @@ -127,6 +127,7 @@ private boolean computeStartingLiterals() { } } + @Override public List getStartingLiterals() { return Collections.unmodifiableList(startingLiterals); } @@ -135,23 +136,27 @@ public void updateLiteralSelectivity(Literal literal, int numGivenTuples, int nu // TODO: add old selectivity (with a decay factor) and new selectivity. } - public RuleGroundingOrder orderStartingFrom(Literal startingLiteral) { + @Override + public RuleGroundingOrderImpl orderStartingFrom(Literal startingLiteral) { return groundingOrders.get(startingLiteral); } - + @Override public RuleGroundingOrder getFixedGroundingOrder() { return fixedGroundingOrder; } /** * States whether the rule is without positive ordinary atoms, as for example in: p(Y) :- X = 1..3, not q(X), Y = X + 2, &ext[X,Y](). + * * @return true if the rule has a (limited number of) fixed grounding instantiation(s). */ - public boolean fixedInstantiation() { + @Override + public boolean hasFixedInstantiation() { return fixedGroundingInstantiation; } + @Override public void computeGroundingOrders() { if (fixedGroundingInstantiation) { // Fixed grounding is only evaluated once and not depending on a starting variable, just use the first. @@ -177,13 +182,14 @@ private void computeGroundingOrder(Literal startingLiteral) { } else { literalsOrder = new ArrayList<>(bodyLiterals.size() - 1); } - + int position = 0; int positionLastVarBound = -1; while (!remainingLiterals.isEmpty()) { Literal nextGroundingLiteral = selectNextGroundingLiteral(remainingLiterals, boundVariables); if (nextGroundingLiteral == null) { - throw new RuntimeException("Could not find a grounding order for rule " + internalRule + " with starting literal: " + startingLiteral + ". Rule is not safe."); + throw new RuntimeException( + "Could not find a grounding order for rule " + internalRule + " with starting literal: " + startingLiteral + ". Rule is not safe."); } remainingLiterals.remove(nextGroundingLiteral); boolean boundNewVars = boundVariables.addAll(nextGroundingLiteral.getBindingVariables()); @@ -194,9 +200,9 @@ private void computeGroundingOrder(Literal startingLiteral) { position++; } if (fixedGroundingInstantiation) { - fixedGroundingOrder = new RuleGroundingOrder(null, literalsOrder, positionLastVarBound, internalRule.isGround()); + fixedGroundingOrder = new RuleGroundingOrderImpl(null, literalsOrder, positionLastVarBound, internalRule.isGround()); } - groundingOrders.put(startingLiteral, new RuleGroundingOrder(startingLiteral, literalsOrder, positionLastVarBound, internalRule.isGround())); + groundingOrders.put(startingLiteral, new RuleGroundingOrderImpl(startingLiteral, literalsOrder, positionLastVarBound, internalRule.isGround())); } private Literal selectNextGroundingLiteral(LinkedHashSet remainingLiterals, Set boundVariables) { @@ -213,8 +219,8 @@ private Literal selectNextGroundingLiteral(LinkedHashSet remainingLiter Float selectivity = literalSelectivity.get(literal); boolean sharesVariables = sharesVariables(boundVariables, literal.getBindingVariables(), literal.getNonBindingVariables()); if (bestLiteral == null - || sharesVariables && selectivity < bestSelectivity - || sharesVariables && !bestLiteralSharesVariables) { + || sharesVariables && selectivity < bestSelectivity + || sharesVariables && !bestLiteralSharesVariables) { bestLiteral = literal; bestSelectivity = selectivity; bestLiteralSharesVariables = sharesVariables; diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrder.java new file mode 100644 index 000000000..8558e8ebe --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrder.java @@ -0,0 +1,18 @@ +package at.ac.tuwien.kr.alpha.core.grounder; + +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; + +// TODO should we really expose this?? pretty specific to how our grounder works +public interface RuleGroundingOrder { + + Literal getStartingLiteral(); + + Literal getLiteralAtOrderPosition(int pos); + + RuleGroundingOrder pushBack(int pos); + + void considerUntilCurrentEnd(); + + int getPositionFromWhichAllVarsAreBound(); + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrderImpl.java similarity index 85% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrderImpl.java index 602a7aedf..bd7c8ffa1 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrderImpl.java @@ -23,18 +23,18 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.ArrayList; import java.util.List; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; /** - * A grounding order computed by {@link RuleGroundingOrders} for a specific {@link InternalRule} and a specific starting literal. + * A grounding order computed by {@link RuleGroundingInfoImpl} for a specific {@link InternalRule} and a specific starting literal. */ -public class RuleGroundingOrder { +public class RuleGroundingOrderImpl implements RuleGroundingOrder{ private Literal startingLiteral; private List otherLiterals; @@ -42,7 +42,7 @@ public class RuleGroundingOrder { private int stopBindingAtOrderPosition; private final boolean ground; - RuleGroundingOrder(Literal startingLiteral, List otherLiterals, int positionLastVarBound, boolean isGround) { + RuleGroundingOrderImpl(Literal startingLiteral, List otherLiterals, int positionLastVarBound, boolean isGround) { super(); this.startingLiteral = startingLiteral; this.otherLiterals = otherLiterals; @@ -51,7 +51,7 @@ public class RuleGroundingOrder { this.ground = isGround; } - private RuleGroundingOrder(RuleGroundingOrder otherRuleGroundingOrder) { + private RuleGroundingOrderImpl(RuleGroundingOrderImpl otherRuleGroundingOrder) { this(otherRuleGroundingOrder.startingLiteral, new ArrayList<>(otherRuleGroundingOrder.otherLiterals), otherRuleGroundingOrder.positionLastVarBound, otherRuleGroundingOrder.ground); this.stopBindingAtOrderPosition = otherRuleGroundingOrder.stopBindingAtOrderPosition; } @@ -66,6 +66,7 @@ private RuleGroundingOrder(RuleGroundingOrder otherRuleGroundingOrder) { * @param orderPosition zero-based index into list of literals except the starting literal * @return the literal at the given position, or {@code null} if it is already known that this literal is not able to yield new bindings */ + @Override public Literal getLiteralAtOrderPosition(int orderPosition) { if (orderPosition >= stopBindingAtOrderPosition) { return null; @@ -76,6 +77,7 @@ public Literal getLiteralAtOrderPosition(int orderPosition) { /** * @return the zero-based position from which on all variables are bound in list of literals except the starting literal */ + @Override public int getPositionFromWhichAllVarsAreBound() { return positionLastVarBound + 1; } @@ -112,19 +114,22 @@ public String toString() { * @return a new grounding order in which the atom is pushed back, * or {@code null} if the position of the grounding order after which no new bindings can be found has been reached. */ - public RuleGroundingOrder pushBack(int orderPosition) { + @Override + public RuleGroundingOrderImpl pushBack(int orderPosition) { if (orderPosition >= stopBindingAtOrderPosition - 1) { return null; } - RuleGroundingOrder reorderedGroundingOrder = new RuleGroundingOrder(this); + RuleGroundingOrderImpl reorderedGroundingOrder = new RuleGroundingOrderImpl(this); reorderedGroundingOrder.otherLiterals.add(otherLiterals.get(orderPosition)); return reorderedGroundingOrder; } + @Override public void considerUntilCurrentEnd() { this.stopBindingAtOrderPosition = this.otherLiterals.size(); } + @Override public Literal getStartingLiteral() { return this.startingLiteral; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Unification.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Unification.java similarity index 89% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/Unification.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Unification.java index b8548b971..ab2647942 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/Unification.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/Unification.java @@ -25,22 +25,21 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.Set; -import static at.ac.tuwien.kr.alpha.Util.oops; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.Unifier; /** - * Helper methods for unification and instantiation of two given atoms. - * - * Copyright (c) 2017-2021, the Alpha Team. + * Copyright (c) 2017, the Alpha Team. */ public class Unification { @@ -123,16 +122,16 @@ private static boolean unifyTerms(Term left, Term right, Unifier currentSubstitu // ArithmeticTerms are similar to FunctionTerms, i.e. if the operator is the same and its subterms unify, the ArithmeticTerms unify. final ArithmeticTerm leftArithmeticTerm = (ArithmeticTerm) leftSubs; final ArithmeticTerm rightArithmeticTerm = (ArithmeticTerm) rightSubs; - if (!leftArithmeticTerm.getArithmeticOperator().equals(rightArithmeticTerm.getArithmeticOperator())) { + if (!leftArithmeticTerm.getOperator().equals(rightArithmeticTerm.getOperator())) { return false; } - final Term leftTermLeftSubterm = leftArithmeticTerm.getLeft(); - final Term rightTermLeftSubterm = rightArithmeticTerm.getLeft(); + final Term leftTermLeftSubterm = leftArithmeticTerm.getLeftOperand(); + final Term rightTermLeftSubterm = rightArithmeticTerm.getLeftOperand(); if (!unifyTerms(leftTermLeftSubterm, rightTermLeftSubterm, currentSubstitution, keepLeftAsIs)) { return false; } - final Term leftTermRightSubterm = leftArithmeticTerm.getRight(); - final Term rightTermRightSubterm = rightArithmeticTerm.getRight(); + final Term leftTermRightSubterm = leftArithmeticTerm.getRightOperand(); + final Term rightTermRightSubterm = rightArithmeticTerm.getRightOperand(); if (!unifyTerms(leftTermRightSubterm, rightTermRightSubterm, currentSubstitution, keepLeftAsIs)) { return false; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/WorkingMemory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/WorkingMemory.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java index 438fa2238..549feddf0 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/WorkingMemory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/WorkingMemory.java @@ -25,7 +25,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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import java.util.HashMap; import java.util.HashSet; @@ -34,9 +34,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; +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.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; public class WorkingMemory { protected HashMap> workingMemory = new HashMap<>(); diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/bridges/Bridge.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/bridges/Bridge.java new file mode 100644 index 000000000..2d0beedb2 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/bridges/Bridge.java @@ -0,0 +1,12 @@ +package at.ac.tuwien.kr.alpha.core.grounder.bridges; + +import at.ac.tuwien.kr.alpha.commons.util.IntIdGenerator; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; + +import java.util.Collection; + +public interface Bridge { + Collection getRules(Assignment assignment, AtomStore atomStore, IntIdGenerator intIdGenerator); +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/AbstractLiteralInstantiationStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/AbstractLiteralInstantiationStrategy.java similarity index 89% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/AbstractLiteralInstantiationStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/AbstractLiteralInstantiationStrategy.java index 787cb9510..9547b94dd 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/AbstractLiteralInstantiationStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/AbstractLiteralInstantiationStrategy.java @@ -23,22 +23,24 @@ * 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.grounder.instantiation; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import org.apache.commons.lang3.tuple.ImmutablePair; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; + /** * Abstract base implementation of {@link LiteralInstantiationStrategy} that outlines a basic workflow for * {@link LiteralInstantiationStrategy#getTruthForGroundLiteral(Literal)} and - * {@link LiteralInstantiationStrategy#getAcceptedSubstitutions(Literal, Substitution)} while leaving details of when an atom is true and + * {@link LiteralInstantiationStrategy#getAcceptedSubstitutions(Literal, BasicSubstitution)} while leaving details of when an atom is true and * which {@link AssignmentStatus}es to consider valid for getAcceptedSubstitutions to implementations. * * Copyright (c) 2020, the Alpha Team. @@ -62,7 +64,7 @@ public final AssignmentStatus getTruthForGroundLiteral(Literal groundLiteral) { } /** - * See {@link LiteralInstantiationStrategy#getAcceptedSubstitutions(Literal, Substitution)}. + * See {@link LiteralInstantiationStrategy#getAcceptedSubstitutions(Literal, BasicSubstitution)}. * * A very general implementation of the basic steps needed to obtain ground substitutions for a positive literal. * Potentially valid ground instances are obtained using {@link AbstractLiteralInstantiationStrategy#computeCandidateInstances(Atom)}, then @@ -105,14 +107,14 @@ protected final List> buildSubstit Substitution currentInstanceSubstitution; Atom atomForCurrentInstance; for (Instance instance : candidateInstances) { - currentInstanceSubstitution = Substitution.specializeSubstitution(atomToSubstitute, instance, partialSubstitution); + currentInstanceSubstitution = BasicSubstitution.specializeSubstitution(atomToSubstitute, instance, partialSubstitution); if (currentInstanceSubstitution == null) { // Instance does not unify with partialSubstitution, move on to the next instance. continue; } // At this point, we know that the substitution works out. // Now check whether the resulting Atom has an acceptable AssignmentStatus. - atomForCurrentInstance = new BasicAtom(atomToSubstitute.getPredicate(), atomToSubstitute.getTerms()) + atomForCurrentInstance = Atoms.newBasicAtom(atomToSubstitute.getPredicate(), atomToSubstitute.getTerms()) .substitute(currentInstanceSubstitution); AssignmentStatus assignmentStatus = this.getAssignmentStatusForAtom(atomForCurrentInstance); if (!this.assignmentStatusAccepted(assignmentStatus)) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/AssignmentStatus.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/AssignmentStatus.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/AssignmentStatus.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/AssignmentStatus.java index 8555e91c6..2f9290d51 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/AssignmentStatus.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/AssignmentStatus.java @@ -23,10 +23,10 @@ * 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.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; /** * Helper type to represent truth values as understood by a {@link Grounder} and {@link LiteralInstantiator}. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/BindingResult.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/BindingResult.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/BindingResult.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/BindingResult.java index 34ff021bf..c20ff1b67 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/BindingResult.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/BindingResult.java @@ -23,13 +23,13 @@ * 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.grounder.instantiation; - -import at.ac.tuwien.kr.alpha.grounder.Substitution; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import java.util.ArrayList; import java.util.List; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; + /** * Contains substitutions produced for generating ground substitutions of a rule, * and for every substitution the number of positive body atoms still unassigned in the respective ground rule. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/DefaultLazyGroundingInstantiationStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/DefaultLazyGroundingInstantiationStrategy.java similarity index 84% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/DefaultLazyGroundingInstantiationStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/DefaultLazyGroundingInstantiationStrategy.java index a57aa1699..621e4616b 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/DefaultLazyGroundingInstantiationStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/DefaultLazyGroundingInstantiationStrategy.java @@ -23,29 +23,30 @@ * 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.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import java.util.LinkedHashSet; import java.util.Map; -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.grounder.IndexedInstanceStorage; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import at.ac.tuwien.kr.alpha.grounder.NaiveGrounder; -import at.ac.tuwien.kr.alpha.grounder.WorkingMemory; -import at.ac.tuwien.kr.alpha.solver.Solver; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.api.Solver; +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.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.grounder.IndexedInstanceStorage; +import at.ac.tuwien.kr.alpha.core.grounder.NaiveGrounder; +import at.ac.tuwien.kr.alpha.core.grounder.WorkingMemory; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; /** * Implementation of {@link AbstractLiteralInstantiationStrategy} designed for use in {@link NaiveGrounder}. * * The instantiation strategy shares a {@link WorkingMemory}, an {@link AtomStore}, an {@link Assignment}, a {@link Map} of atoms that were - * facts of the currently grounded program, as well as a list of {@link Atom}s that should be lazily deleted from the working memory, with + * facts of the currently grounded program, as well as a list of {@link AbstractAtom}s that should be lazily deleted from the working memory, + * with * the grounder. * * The working memory and the facts map are maintained by the grounder and are being read by @@ -54,10 +55,12 @@ * are added by the instantiation strategy. The {@link Assignment} reflects the {@link Solver}s "current view of the world". It is used by * {@link DefaultLazyGroundingInstantiationStrategy} to determine {@link AssignmentStatus}es for atoms. * - * A specialty of this implementation is that - since deletion of obsolete {@link Atom}s from {@link NaiveGrounder}s {@link WorkingMemory} + * A specialty of this implementation is that - since deletion of obsolete {@link AbstractAtom}s from {@link NaiveGrounder}s + * {@link WorkingMemory} * happens lazily (i.e. at the end of each run of {@link NaiveGrounder#getNoGoods(Assignment)}) - it maintains a set of "stale" atoms that * is shared with the grounder. Specifically, whenever {@link DefaultLazyGroundingInstantiationStrategy#getAssignmentStatusForAtom(Atom)} - * determines that an {@link Atom} is {@link AssignmentStatus#UNASSIGNED} or {@link AssignmentStatus#FALSE}, that {@link Atom} is added to + * determines that an {@link AbstractAtom} is {@link AssignmentStatus#UNASSIGNED} or {@link AssignmentStatus#FALSE}, that {@link AbstractAtom} is + * added to * the stale atom set, which in turn is processed by the grounder, which then deletes the respective atoms from the working memory. * * Copyright (c) 2020, the Alpha Team. @@ -87,7 +90,7 @@ protected Iterable computeCandidateInstances(Atom partiallyGroundAtom) //@formatter:off /** - * Computes the {@link AssignmentStatus} for a given {@link Atom} a. + * Computes the {@link AssignmentStatus} for a given {@link AbstractAtom} a. * * The atom a is {@link AssignmentStatus#TRUE} iff *

    @@ -100,8 +103,8 @@ protected Iterable computeCandidateInstances(Atom partiallyGroundAtom) * An atom is {@link AssignmentStatus#UNASSIGNED} iff it has no {@link ThriceTruth} assigned to it in the current assignment. * An atom is {@link AssignmentStatus#FALSE} iff it is assigned {@link ThriceTruth#FALSE} in the current assignment by the {@link Solver}. * - * Whenever an {@link Atom} is found to be UNASSIGNED or FALSE, - * that {@link Atom} is added to the stale atom set for later deletion from working memory by the grounder. + * Whenever an {@link AbstractAtom} is found to be UNASSIGNED or FALSE, + * that {@link AbstractAtom} is added to the stale atom set for later deletion from working memory by the grounder. */ //@formatter:on @Override diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationResult.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationResult.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationResult.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationResult.java index b02b76096..6d2506543 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationResult.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationResult.java @@ -23,24 +23,27 @@ * 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.grounder.instantiation; - -import org.apache.commons.lang3.tuple.ImmutablePair; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; /** * Representation of the result of instantiating, i.e. finding ground instances for a literal, as performed by - * {@link LiteralInstantiator#instantiateLiteral(at.ac.tuwien.kr.alpha.common.atoms.Literal, Substitution)}. + * {@link LiteralInstantiator#instantiateLiteral(Literal, BasicSubstitution)}. * * A {@link LiteralInstantiationResult} bundles obtained ground substitutions - or the lack thereof, if none exist for a given literal - - * together with status information that can be used by a {@link Grounder} to determine how to proceed when grounding an {@link InternalRule}. + * together with status information that can be used by a {@link Grounder} to determine how to proceed when grounding an + * {@link InternalRule}. * * Copyright (c) 2020, the Alpha Team. */ diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationStrategy.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationStrategy.java index f264d418b..81803642a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationStrategy.java @@ -23,18 +23,19 @@ * 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.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import java.util.List; import org.apache.commons.lang3.tuple.ImmutablePair; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; /** - * A {@link LiteralInstantiationStrategy} finds and validates {@link Substitution}s for {@link Literal}s based on a specific definition of - * when a {@link Substitution} is valid, i.e. what makes a literal "true", "false" or "unassigned". + * A {@link LiteralInstantiationStrategy} finds and validates {@link BasicSubstitution}s for {@link Literal}s based on a specific definition of + * when a {@link BasicSubstitution} is valid, i.e. what makes a literal "true", "false" or "unassigned". * * Copyright (c) 2020, the Alpha Team. */ @@ -49,9 +50,9 @@ public interface LiteralInstantiationStrategy { AssignmentStatus getTruthForGroundLiteral(Literal groundLiteral); /** - * Computes {@link Substitution}s that yield ground instances for a given literal and starting substitution along with the + * Computes {@link BasicSubstitution}s that yield ground instances for a given literal and starting substitution along with the * {@link AssignmentStatus} of respective ground instances. Note that in all implementations it must hold that an {@link AssignmentStatus} - * AS for a {@link Substitution} S as yielded by this method for a {@link Literal} lit is the same as the result of calling + * AS for a {@link BasicSubstitution} S as yielded by this method for a {@link Literal} lit is the same as the result of calling * getTruthForGroundLiteral(lit.substitute(S)), i.e. both methods must yield the same assignment status for the same ground * literal. * diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiator.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiator.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiator.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiator.java index 904caa961..e6fead4c6 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiator.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiator.java @@ -1,17 +1,17 @@ /** * Copyright (c) 2020, 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.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import java.util.List; @@ -31,21 +31,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.FixedInterpretationLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.atoms.EnumerationLiteral; -import at.ac.tuwien.kr.alpha.grounder.atoms.IntervalLiteral; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.ExternalLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.FixedInterpretationLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.core.atoms.EnumerationLiteral; +import at.ac.tuwien.kr.alpha.core.atoms.IntervalLiteral; /** * Provides ground instantiations for literals. - * + * * This class is intended to be used for grounding and other use cases where ground instantiations of literals need to be computed and * serves as an abstraction layer to decouple the knowledge of how to ground literals from the overall (rule-)grounding workflow. The task of * actually finding fitting ground substitutions is mostly delegated to a {@link LiteralInstantiationStrategy}. - * + * * Copyright (c) 2020, the Alpha Team. */ public class LiteralInstantiator { @@ -56,7 +57,7 @@ public class LiteralInstantiator { /** * Creates a new {@link LiteralInstantiator} with the given {@link LiteralInstantiationStrategy}. - * + * * @param instantiationStrategy the instantiation strategy to use for this instantiator */ public LiteralInstantiator(LiteralInstantiationStrategy instantiationStrategy) { @@ -64,12 +65,12 @@ public LiteralInstantiator(LiteralInstantiationStrategy instantiationStrategy) { } /** - * Instantiates a literal using an existing {@link Substitution} as starting point. - * + * Instantiates a literal using an existing {@link BasicSubstitution} as starting point. + * * This method is intended to be called as part of a larger rule instantiation (i.e. grounding) workflow in order to find ground * instantiations of literals, i.e. extensions of the given partial substitution that yield useable ground instances for the given literal. * These substitutions (if any exist) are wrapped together with some additional status information in a {@link LiteralInstantiationResult}. - * + * * @param lit the literal for which to find substitutions that yield ground instances * @param partialSubstitution a substitution that serves as a starting point. May be empty. * @return a {@link LiteralInstantiationResult} containing ground substitutions - if any exist - along with some metadata for the grounder @@ -92,7 +93,7 @@ public LiteralInstantiationResult instantiateLiteral(Literal lit, Substitution p /** * Calculates satisfying substitutions for a given {@link FixedInterpretationLiteral} based on a partial substitution. This method assumes * that the partial substitution has not been applied to the passed literal. - * + * * @param lit the (fixed interpretation) literal for which to calculate substitutions * @param partialSubstitution * @return a LiteralInstantiationResult representing the result of the search for substitutions @@ -106,16 +107,16 @@ private LiteralInstantiationResult instantiateFixedInterpretationLiteral(FixedIn } else { substitutions = substitutedLiteral.getSatisfyingSubstitutions(partialSubstitution); return substitutions.isEmpty() ? LiteralInstantiationResult.stopBinding() - : LiteralInstantiationResult.continueBindingWithTrueSubstitutions(substitutions); + : LiteralInstantiationResult.continueBindingWithTrueSubstitutions(substitutions); } } /** - * Calculates a substitution that adds an enumeration index (see {@link EnumerationLiteral#addEnumerationIndexToSubstitution(Substitution)}) + * Calculates a substitution that adds an enumeration index (see {@link EnumerationLiteral#addEnumerationIndexToSubstitution(BasicSubstitution)}) * to the given partial substitution. Due to the special nature of enumeration literals, this method will always return * {@link LiteralInstantiationResult.Type#CONTINUE} as its result type. This method assumes that the partial substitution has * not been applied to the passed literal. - * + * * @param lit an enumeration literal * @param partialSubstitution */ @@ -130,7 +131,7 @@ private LiteralInstantiationResult instantiateEnumerationLiteral(EnumerationLite * this instantiators {@link LiteralInstantiationStrategy}. If the literal is only partially ground after applying the partial substitution, * ground substitutions are looked up using the instantiators {@link LiteralInstantiationStrategy}. This method assumes that the partial * substitution has not been applied to the passed literal. - * + * * @param lit * @param partialSubstitution */ @@ -168,7 +169,7 @@ private LiteralInstantiationResult instantiateBasicLiteral(Literal lit, Substitu /** * Helper method for instantiateLiteral to determine whether a {@link FixedInterpretationLiteral} may have substitutions later * on and should therefore be pushed back in the grounding order. - * + * * Any {@link FixedInterpretationLiteral} that does not fulfil any of the following conditions is "pushed back" in the * grounding order because it cannot be used to generate substitutions now but maybe later: *

      @@ -177,15 +178,15 @@ private LiteralInstantiationResult instantiateBasicLiteral(Literal lit, Substitu *
    • the literal is an {@link IntervalLiteral} representing a ground interval term
    • *
    • the literal is an {@link ExternalLiteral}.
    • *
    - * + * * @param lit a {@link FixedInterpretationLiteral} that is substituted with the partial substitution passed into * instantiateLiteral */ private boolean shouldPushBackFixedInterpretationLiteral(FixedInterpretationLiteral lit) { return !(lit.isGround() || - (lit instanceof ComparisonLiteral && ((ComparisonLiteral) lit).isLeftOrRightAssigning()) || - (lit instanceof IntervalLiteral && lit.getTerms().get(0).isGround()) || - (lit instanceof ExternalLiteral)); + (lit instanceof ComparisonLiteral && ((ComparisonLiteral) lit).isLeftOrRightAssigning()) || + (lit instanceof IntervalLiteral && lit.getTerms().get(0).isGround()) || + (lit instanceof ExternalLiteral)); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/WorkingMemoryBasedInstantiationStrategy.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/WorkingMemoryBasedInstantiationStrategy.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/WorkingMemoryBasedInstantiationStrategy.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/WorkingMemoryBasedInstantiationStrategy.java index 7c2889570..ceb2811e8 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/instantiation/WorkingMemoryBasedInstantiationStrategy.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/WorkingMemoryBasedInstantiationStrategy.java @@ -23,12 +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.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import at.ac.tuwien.kr.alpha.grounder.WorkingMemory; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.core.grounder.WorkingMemory; /** * A very basic implementation of {@link AbstractLiteralInstantiationStrategy} that determines truth of an atom solely based on the atom's diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/structure/AnalyzeUnjustified.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/structure/AnalyzeUnjustified.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java index 658429f70..cb12167db 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/structure/AnalyzeUnjustified.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustified.java @@ -1,9 +1,6 @@ -package at.ac.tuwien.kr.alpha.grounder.structure; +package at.ac.tuwien.kr.alpha.core.grounder.structure; -import static at.ac.tuwien.kr.alpha.Util.oops; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.ArrayList; import java.util.Collections; @@ -16,34 +13,39 @@ import java.util.NoSuchElementException; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import at.ac.tuwien.kr.alpha.grounder.Unification; -import at.ac.tuwien.kr.alpha.grounder.Unifier; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.commons.substitutions.Unifier; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.grounder.Unification; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; /** * Copyright (c) 2018-2020, the Alpha Team. */ public class AnalyzeUnjustified { private static final Logger LOGGER = LoggerFactory.getLogger(AnalyzeUnjustified.class); - private final InternalProgram programAnalysis; + private final CompiledProgram programAnalysis; private final AtomStore atomStore; private final Map> factsFromProgram; private int renamingCounter; private int padDepth; - public AnalyzeUnjustified(InternalProgram programAnalysis, AtomStore atomStore, Map> factsFromProgram) { + public AnalyzeUnjustified(CompiledProgram programAnalysis, AtomStore atomStore, Map> factsFromProgram) { this.programAnalysis = programAnalysis; this.atomStore = atomStore; this.factsFromProgram = factsFromProgram; @@ -113,8 +115,7 @@ private ReturnExplainUnjust explainUnjust(LitSet x, Assignment currentAssignment // Construct set of all 'rules' such that head unifies with p. List rulesUnifyingWithP = rulesHeadUnifyingWith(p); log("Rules unifying with {} are {}", p, rulesUnifyingWithP); - rulesLoop: - for (RuleAndUnifier ruleUnifier : rulesUnifyingWithP) { + rulesLoop: for (RuleAndUnifier ruleUnifier : rulesUnifyingWithP) { Unifier sigma = ruleUnifier.unifier; Set bodyR = ruleUnifier.ruleBody; Atom sigmaHr = ruleUnifier.originalHead.substitute(sigma); @@ -207,7 +208,7 @@ private Set unjustCover(List vB, Set vY, Set int chosenLiteralPos = 0; // Find a body literal that is not a ComparisonLiteral, because these do not generate/have atoms assigned. for (int i = 0; i < vB.size(); i++) { - if (!(vB.get(i) instanceof ComparisonLiteral)) { + if (!(vB.get(i) instanceof ComparisonLiteral)) { // TODO: Should this be FixedInterpretationLiteral instead?? chosenLiteralPos = i; break; } @@ -221,8 +222,7 @@ private Set unjustCover(List vB, Set vY, Set log("Checking atoms over predicate: {}", b.getPredicate()); AssignedAtomsIterator assignedAtomsOverPredicate = getAssignedAtomsOverPredicate(b.getPredicate()); - atomLoop: - while (assignedAtomsOverPredicate.hasNext()) { + atomLoop: while (assignedAtomsOverPredicate.hasNext()) { Atom atom = assignedAtomsOverPredicate.next(); // Check that atom is justified/true. log("Checking atom: {}", atom); @@ -248,7 +248,7 @@ private Set unjustCover(List vB, Set vY, Set for (Unifier sigmaN : vN) { ArrayList occurringVariables = new ArrayList<>(variablesOccurringInSigma); occurringVariables.addAll(sigmaN.getMappedVariables()); - BasicAtom genericAtom = new BasicAtom(Predicate.getInstance("_", occurringVariables.size(), true), occurringVariables); + BasicAtom genericAtom = Atoms.newBasicAtom(Predicates.getPredicate("_", occurringVariables.size(), true), occurringVariables); Atom genericSubstituted = genericAtom.substitute(sigmaN).renameVariables("_analyzeTest"); if (Unification.instantiate(genericSubstituted, genericAtom.substitute(sigma)) != null) { log("Atom {} is excluded by: {} via {}", genericSubstituted, sigmaN, sigma); @@ -321,7 +321,7 @@ public Atom next() { return assignedAtomsIterator.next(); } if (factsIterator.hasNext()) { - return new BasicAtom(predicate, factsIterator.next().terms); + return Atoms.newBasicAtom(predicate, factsIterator.next().terms); } throw new NoSuchElementException(); } @@ -331,7 +331,7 @@ private List rulesHeadUnifyingWith(Atom p) { List rulesWithUnifier = new ArrayList<>(); Predicate predicate = p.getPredicate(); - + ArrayList definingRulesAndFacts = new ArrayList<>(); // Get facts over the same predicate. LinkedHashSet factInstances = factsFromProgram.get(predicate); @@ -341,9 +341,9 @@ private List rulesHeadUnifyingWith(Atom p) { } } - HashSet rulesDefiningPredicate = programAnalysis.getPredicateDefiningRules().get(predicate); + HashSet rulesDefiningPredicate = programAnalysis.getPredicateDefiningRules().get(predicate); if (rulesDefiningPredicate != null) { - for (InternalRule nonGroundRule : rulesDefiningPredicate) { + for (CompiledRule nonGroundRule : rulesDefiningPredicate) { definingRulesAndFacts.add(new FactOrNonGroundRule(nonGroundRule)); } } @@ -353,12 +353,12 @@ private List rulesHeadUnifyingWith(Atom p) { Atom headAtom; if (isNonGroundRule) { // First rename all variables in the rule. - InternalRule rule = factOrNonGroundRule.nonGroundRule.renameVariables("_" + renamingCounter++); + CompiledRule rule = factOrNonGroundRule.nonGroundRule.renameVariables("_" + renamingCounter++); renamedBody = rule.getBody(); headAtom = rule.getHeadAtom(); } else { // Create atom and empty rule body out of instance. - headAtom = new BasicAtom(p.getPredicate(), factOrNonGroundRule.factInstance.terms); + headAtom = Atoms.newBasicAtom(p.getPredicate(), factOrNonGroundRule.factInstance.terms); renamedBody = Collections.emptySet(); } // Unify rule head with literal to justify. @@ -406,14 +406,14 @@ public String toString() { private static class FactOrNonGroundRule { final Instance factInstance; - final InternalRule nonGroundRule; + final CompiledRule nonGroundRule; private FactOrNonGroundRule(Instance factInstance) { this.factInstance = factInstance; this.nonGroundRule = null; } - private FactOrNonGroundRule(InternalRule nonGroundRule) { + private FactOrNonGroundRule(CompiledRule nonGroundRule) { this.nonGroundRule = nonGroundRule; this.factInstance = null; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/structure/LitSet.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/LitSet.java similarity index 92% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/structure/LitSet.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/LitSet.java index 2e415af08..4bcf9646d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/structure/LitSet.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/grounder/structure/LitSet.java @@ -1,16 +1,16 @@ -package at.ac.tuwien.kr.alpha.grounder.structure; +package at.ac.tuwien.kr.alpha.core.grounder.structure; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.VariableNormalizableAtom; -import at.ac.tuwien.kr.alpha.grounder.Unifier; -import at.ac.tuwien.kr.alpha.grounder.Unification; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; -import static at.ac.tuwien.kr.alpha.Util.oops; +import at.ac.tuwien.kr.alpha.api.programs.VariableNormalizableAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.commons.substitutions.Unifier; +import at.ac.tuwien.kr.alpha.core.grounder.Unification; /** * Copyright (c) 2018, the Alpha Team. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/CustomErrorListener.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/CustomErrorListener.java similarity index 95% rename from src/main/java/at/ac/tuwien/kr/alpha/CustomErrorListener.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/CustomErrorListener.java index 29b9adf3f..c13992bb5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/CustomErrorListener.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/CustomErrorListener.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha; +package at.ac.tuwien.kr.alpha.core.parser; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.RecognitionException; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/InlineDirectives.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/InlineDirectivesImpl.java similarity index 61% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/InlineDirectives.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/InlineDirectivesImpl.java index f6fc42ffb..c04de330c 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/InlineDirectives.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/InlineDirectivesImpl.java @@ -1,24 +1,24 @@ -package at.ac.tuwien.kr.alpha.grounder.parser; +package at.ac.tuwien.kr.alpha.core.parser; import java.util.LinkedHashMap; import java.util.Map; +import at.ac.tuwien.kr.alpha.api.programs.InlineDirectives; + /** * Stores directives appearing in the ASP program. Each directive starts with # and ends with . - * Copyright (c) 2017, the Alpha Team. + * Copyright (c) 2017 - 2021, the Alpha Team. */ -public class InlineDirectives { - - public enum DIRECTIVE { - enum_predicate_is - } +public class InlineDirectivesImpl implements InlineDirectives { private final LinkedHashMap directives = new LinkedHashMap<>(); + @Override public String getDirectiveValue(DIRECTIVE directive) { return directives.get(directive); } + @Override public void addDirective(DIRECTIVE directive, String value) { if (directives.get(directive) != null) { throw new RuntimeException("Inline directive multiply defined."); @@ -26,9 +26,15 @@ public void addDirective(DIRECTIVE directive, String value) { directives.put(directive, value); } + @Override public void accumulate(InlineDirectives other) { - for (Map.Entry directiveEntry : other.directives.entrySet()) { + for (Map.Entry directiveEntry : other.getDirectives().entrySet()) { addDirective(directiveEntry.getKey(), directiveEntry.getValue()); } } + + @Override + public LinkedHashMap getDirectives() { + return this.directives; + } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ParseTreeVisitor.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ParseTreeVisitor.java similarity index 72% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ParseTreeVisitor.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ParseTreeVisitor.java index 2f12d49c7..1498a4f0c 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ParseTreeVisitor.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ParseTreeVisitor.java @@ -1,19 +1,19 @@ /** * Copyright (c) 2016-2018, 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. - * + * 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 @@ -25,39 +25,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.grounder.parser; - -import at.ac.tuwien.kr.alpha.antlr.ASPCore2BaseVisitor; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Lexer; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Parser; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.BasicAnswerSet; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.ChoiceHead; -import at.ac.tuwien.kr.alpha.common.rule.head.Head; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import org.antlr.v4.runtime.RuleContext; -import org.antlr.v4.runtime.tree.TerminalNode; +package at.ac.tuwien.kr.alpha.core.parser; + +import static java.util.Collections.emptyList; import java.util.ArrayList; import java.util.Collections; @@ -69,7 +39,43 @@ import java.util.TreeMap; import java.util.TreeSet; -import static java.util.Collections.emptyList; +import org.antlr.v4.runtime.RuleContext; +import org.antlr.v4.runtime.tree.TerminalNode; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.InlineDirectives; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +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.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead.ChoiceElement; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticOperator; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.AnswerSets; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2BaseVisitor; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Lexer; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Parser; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; /** * Copyright (c) 2016-2018, the Alpha Team. @@ -138,7 +144,7 @@ public AnswerSet visitAnswer_set(ASPCore2Parser.Answer_setContext ctx) { } - return new BasicAnswerSet(predicates, predicateInstances); + return AnswerSets.newAnswerSet(predicates, predicateInstances); } @Override @@ -156,7 +162,7 @@ public InputProgram visitProgram(ASPCore2Parser.ProgramContext ctx) { if (ctx.statements() == null) { return InputProgram.EMPTY; } - inlineDirectives = new InlineDirectives(); + inlineDirectives = new InlineDirectivesImpl(); programBuilder = InputProgram.builder(); visitStatements(ctx.statements()); programBuilder.addInlineDirectives(inlineDirectives); @@ -219,7 +225,7 @@ public Head visitDisjunction(ASPCore2Parser.DisjunctionContext ctx) { if (ctx.disjunction() != null) { throw notSupported(ctx); } - return new NormalHead(visitClassical_literal(ctx.classical_literal())); + return Heads.newNormalHead(visitClassical_literal(ctx.classical_literal())); } @Override @@ -246,11 +252,11 @@ public Head visitChoice(ASPCore2Parser.ChoiceContext ctx) { ut = (Term) visit(ctx.ut); uop = visitBinop(ctx.uop); } - return new ChoiceHead(visitChoice_elements(ctx.choice_elements()), lt, lop, ut, uop); + return Heads.newChoiceHead(visitChoice_elements(ctx.choice_elements()), lt, lop, ut, uop); } @Override - public List visitChoice_elements(ASPCore2Parser.Choice_elementsContext ctx) { + public List visitChoice_elements(ASPCore2Parser.Choice_elementsContext ctx) { // choice_elements : choice_element (SEMICOLON choice_elements)?; List choiceElements; if (ctx.choice_elements() != null) { @@ -265,11 +271,11 @@ public List visitChoice_elements(ASPCore2Parser.Choice @Override public ChoiceHead.ChoiceElement visitChoice_element(ASPCore2Parser.Choice_elementContext ctx) { // choice_element : classical_literal (COLON naf_literals?)?; - BasicAtom atom = (BasicAtom) visitClassical_literal(ctx.classical_literal()); + BasicAtom atom = visitClassical_literal(ctx.classical_literal()); if (ctx.naf_literals() != null) { - return new ChoiceHead.ChoiceElement(atom, visitNaf_literals(ctx.naf_literals())); + return Heads.newChoiceElement(atom, visitNaf_literals(ctx.naf_literals())); } else { - return new ChoiceHead.ChoiceElement(atom, Collections.emptyList()); + return Heads.newChoiceElement(atom, Collections.emptyList()); } } @@ -331,7 +337,7 @@ public AggregateLiteral visitAggregate(ASPCore2Parser.AggregateContext ctx) { } AggregateAtom.AggregateFunctionSymbol aggregateFunction = visitAggregate_function(ctx.aggregate_function()); List aggregateElements = visitAggregate_elements(ctx.aggregate_elements()); - return new AggregateAtom(lop, lt, uop, ut, aggregateFunction, aggregateElements).toLiteral(isPositive); + return Atoms.newAggregateAtom(lop, lt, uop, ut, aggregateFunction, aggregateElements).toLiteral(isPositive); } @Override @@ -350,9 +356,9 @@ public AggregateAtom.AggregateElement visitAggregate_element(ASPCore2Parser.Aggr // aggregate_element : basic_terms? (COLON naf_literals?)?; List basicTerms = ctx.basic_terms() != null ? visitBasic_terms(ctx.basic_terms()) : null; if (ctx.naf_literals() != null) { - return new AggregateAtom.AggregateElement(basicTerms, visitNaf_literals(ctx.naf_literals())); + return Atoms.newAggregateElement(basicTerms, visitNaf_literals(ctx.naf_literals())); } - return new AggregateAtom.AggregateElement(basicTerms, Collections.emptyList()); + return Atoms.newAggregateElement(basicTerms, Collections.emptyList()); } @Override @@ -379,16 +385,16 @@ public Term visitBasic_term(ASPCore2Parser.Basic_termContext ctx) { public Term visitGround_term(ASPCore2Parser.Ground_termContext ctx) { // ground_term : ID | QUOTED_STRING | MINUS? NUMBER; if (ctx.ID() != null) { - return ConstantTerm.getSymbolicInstance(ctx.ID().getText()); + return Terms.newSymbolicConstant(ctx.ID().getText()); } else if (ctx.QUOTED_STRING() != null) { String quotedString = ctx.QUOTED_STRING().getText(); - return ConstantTerm.getInstance(quotedString.substring(1, quotedString.length() - 1)); + return Terms.newConstant(quotedString.substring(1, quotedString.length() - 1)); } else { int multiplier = 1; if (ctx.MINUS() != null) { multiplier = -1; } - return ConstantTerm.getInstance(multiplier * Integer.parseInt(ctx.NUMBER().getText())); + return Terms.newConstant(multiplier * Integer.parseInt(ctx.NUMBER().getText())); } } @@ -396,9 +402,9 @@ public Term visitGround_term(ASPCore2Parser.Ground_termContext ctx) { public Term visitVariable_term(ASPCore2Parser.Variable_termContext ctx) { // variable_term : VARIABLE | ANONYMOUS_VARIABLE; if (ctx.VARIABLE() != null) { - return VariableTerm.getInstance(ctx.VARIABLE().getText()); + return Terms.newVariable(ctx.VARIABLE().getText()); } else { - return VariableTerm.getAnonymousInstance(); + return Terms.newAnonymousVariable(); } } @@ -422,17 +428,17 @@ public AggregateAtom.AggregateFunctionSymbol visitAggregate_function(ASPCore2Par public ComparisonOperator visitBinop(ASPCore2Parser.BinopContext ctx) { // binop : EQUAL | UNEQUAL | LESS | GREATER | LESS_OR_EQ | GREATER_OR_EQ; if (ctx.EQUAL() != null) { - return ComparisonOperator.EQ; + return ComparisonOperators.EQ; } else if (ctx.UNEQUAL() != null) { - return ComparisonOperator.NE; + return ComparisonOperators.NE; } else if (ctx.LESS() != null) { - return ComparisonOperator.LT; + return ComparisonOperators.LT; } else if (ctx.LESS_OR_EQ() != null) { - return ComparisonOperator.LE; + return ComparisonOperators.LE; } else if (ctx.GREATER() != null) { - return ComparisonOperator.GT; + return ComparisonOperators.GT; } else if (ctx.GREATER_OR_EQ() != null) { - return ComparisonOperator.GE; + return ComparisonOperators.GE; } else { throw notSupported(ctx); } @@ -441,11 +447,10 @@ public ComparisonOperator visitBinop(ASPCore2Parser.BinopContext ctx) { @Override public ComparisonAtom visitBuiltin_atom(ASPCore2Parser.Builtin_atomContext ctx) { // builtin_atom : term binop term; - return new ComparisonAtom( - (Term) visit(ctx.term(0)), - (Term) visit(ctx.term(1)), - visitBinop(ctx.binop()) - ); + return Atoms.newComparisonAtom( + (Term) visit(ctx.term(0)), + (Term) visit(ctx.term(1)), + visitBinop(ctx.binop())); } @Override @@ -453,11 +458,11 @@ public Literal visitNaf_literal(ASPCore2Parser.Naf_literalContext ctx) { // naf_literal : NAF? (external_atom | classical_literal | builtin_atom); boolean isCurrentLiteralNegated = ctx.NAF() != null; if (ctx.builtin_atom() != null) { - return new ComparisonLiteral(visitBuiltin_atom(ctx.builtin_atom()), !isCurrentLiteralNegated); + return Literals.fromAtom(visitBuiltin_atom(ctx.builtin_atom()), !isCurrentLiteralNegated); } else if (ctx.classical_literal() != null) { - return new BasicLiteral(visitClassical_literal(ctx.classical_literal()), !isCurrentLiteralNegated); + return Literals.fromAtom(visitClassical_literal(ctx.classical_literal()), !isCurrentLiteralNegated); } else if (ctx.external_atom() != null) { - return new ExternalLiteral(visitExternal_atom(ctx.external_atom()), !isCurrentLiteralNegated); + return Literals.fromAtom(visitExternal_atom(ctx.external_atom()), !isCurrentLiteralNegated); } throw notSupported(ctx); } @@ -470,7 +475,7 @@ public BasicAtom visitClassical_literal(ASPCore2Parser.Classical_literalContext } final List terms = visitTerms(ctx.terms()); - return new BasicAtom(Predicate.getInstance(ctx.ID().getText(), terms.size()), terms); + return Atoms.newBasicAtom(Predicates.getPredicate(ctx.ID().getText(), terms.size()), terms); } @Override @@ -490,24 +495,24 @@ public List visitTerms(ASPCore2Parser.TermsContext ctx) { } @Override - public ConstantTerm visitTerm_number(ASPCore2Parser.Term_numberContext ctx) { - return ConstantTerm.getInstance(Integer.parseInt(ctx.NUMBER().getText())); + public ConstantTerm visitTerm_number(ASPCore2Parser.Term_numberContext ctx) { + return Terms.newConstant(Integer.parseInt(ctx.NUMBER().getText())); } @Override - public ConstantTerm visitTerm_const(ASPCore2Parser.Term_constContext ctx) { - return ConstantTerm.getSymbolicInstance(ctx.ID().getText()); + public ConstantTerm visitTerm_const(ASPCore2Parser.Term_constContext ctx) { + return Terms.newSymbolicConstant(ctx.ID().getText()); } @Override - public ConstantTerm visitTerm_string(ASPCore2Parser.Term_stringContext ctx) { + public ConstantTerm visitTerm_string(ASPCore2Parser.Term_stringContext ctx) { String quotedString = ctx.QUOTED_STRING().getText().replace("\\\"", "\""); - return ConstantTerm.getInstance(quotedString.substring(1, quotedString.length() - 1)); + return Terms.newConstant(quotedString.substring(1, quotedString.length() - 1)); } @Override public FunctionTerm visitTerm_func(ASPCore2Parser.Term_funcContext ctx) { - return FunctionTerm.getInstance(ctx.ID().getText(), visitTerms(ctx.terms())); + return Terms.newFunctionTerm(ctx.ID().getText(), visitTerms(ctx.terms())); } @Override @@ -516,7 +521,7 @@ public VariableTerm visitTerm_anonymousVariable(ASPCore2Parser.Term_anonymousVar throw notSupported(ctx); } - return VariableTerm.getAnonymousInstance(); + return Terms.newAnonymousVariable(); } @Override @@ -525,7 +530,7 @@ public VariableTerm visitTerm_variable(ASPCore2Parser.Term_variableContext ctx) throw notSupported(ctx); } - return VariableTerm.getInstance(ctx.VARIABLE().getText()); + return Terms.newVariable(ctx.VARIABLE().getText()); } @Override @@ -550,12 +555,11 @@ public ExternalAtom visitExternal_atom(ASPCore2Parser.External_atomContext ctx) List outputTerms = visitTerms(ctx.output); - return new ExternalAtom( - Predicate.getInstance(predicateName, outputTerms.size()), - interpretation, - visitTerms(ctx.input), - outputTerms - ); + return Atoms.newExternalAtom( + Predicates.getPredicate(predicateName, outputTerms.size()), + interpretation, + visitTerms(ctx.input), + outputTerms); } @Override @@ -564,42 +568,42 @@ public IntervalTerm visitTerm_interval(ASPCore2Parser.Term_intervalContext ctx) ASPCore2Parser.IntervalContext ictx = ctx.interval(); String lowerText = ictx.lower.getText(); String upperText = ictx.upper.getText(); - Term lower = ictx.lower.getType() == ASPCore2Lexer.NUMBER ? ConstantTerm.getInstance(Integer.parseInt(lowerText)) : VariableTerm.getInstance(lowerText); - Term upper = ictx.upper.getType() == ASPCore2Lexer.NUMBER ? ConstantTerm.getInstance(Integer.parseInt(upperText)) : VariableTerm.getInstance(upperText); + Term lower = ictx.lower.getType() == ASPCore2Lexer.NUMBER ? Terms.newConstant(Integer.parseInt(lowerText)) : Terms.newVariable(lowerText); + Term upper = ictx.upper.getType() == ASPCore2Lexer.NUMBER ? Terms.newConstant(Integer.parseInt(upperText)) : Terms.newVariable(upperText); return IntervalTerm.getInstance(lower, upper); } @Override public Object visitTerm_minusArithTerm(ASPCore2Parser.Term_minusArithTermContext ctx) { // | MINUS term - return ArithmeticTerm.MinusTerm.getInstance((Term) visit(ctx.term())); + return Terms.newMinusTerm((Term) visit(ctx.term())); } @Override public Object visitTerm_timesdivmodArithTerm(ASPCore2Parser.Term_timesdivmodArithTermContext ctx) { // | term (TIMES | DIV | MODULO) term - ArithmeticTerm.ArithmeticOperator op = ctx.TIMES() != null ? ArithmeticTerm.ArithmeticOperator.TIMES - : ctx.DIV() != null ? ArithmeticTerm.ArithmeticOperator.DIV : ArithmeticTerm.ArithmeticOperator.MODULO; - return ArithmeticTerm.getInstance((Term) visit(ctx.term(0)), op, (Term) visit(ctx.term(1))); + ArithmeticOperator op = ctx.TIMES() != null ? ArithmeticOperator.TIMES + : ctx.DIV() != null ? ArithmeticOperator.DIV : ArithmeticOperator.MODULO; + return Terms.newArithmeticTerm((Term) visit(ctx.term(0)), op, (Term) visit(ctx.term(1))); } @Override public Object visitTerm_plusminusArithTerm(ASPCore2Parser.Term_plusminusArithTermContext ctx) { // | term (PLUS | MINUS) term - ArithmeticTerm.ArithmeticOperator op = ctx.PLUS() != null ? ArithmeticTerm.ArithmeticOperator.PLUS : ArithmeticTerm.ArithmeticOperator.MINUS; - return ArithmeticTerm.getInstance((Term) visit(ctx.term(0)), op, (Term) visit(ctx.term(1))); + ArithmeticOperator op = ctx.PLUS() != null ? ArithmeticOperator.PLUS : ArithmeticOperator.MINUS; + return Terms.newArithmeticTerm((Term) visit(ctx.term(0)), op, (Term) visit(ctx.term(1))); } @Override public Object visitTerm_powerArithTerm(ASPCore2Parser.Term_powerArithTermContext ctx) { // | term POWER term - ArithmeticTerm.ArithmeticOperator op = ArithmeticTerm.ArithmeticOperator.POWER; - return ArithmeticTerm.getInstance((Term) visit(ctx.term(0)), op, (Term) visit(ctx.term(1))); + ArithmeticOperator op = ArithmeticOperator.POWER; + return Terms.newArithmeticTerm((Term) visit(ctx.term(0)), op, (Term) visit(ctx.term(1))); } @Override public Object visitTerm_bitxorArithTerm(ASPCore2Parser.Term_bitxorArithTermContext ctx) { // | term BITXOR term - return ArithmeticTerm.getInstance((Term) visit(ctx.term(0)), ArithmeticTerm.ArithmeticOperator.BITXOR, (Term) visit(ctx.term(1))); + return Terms.newArithmeticTerm((Term) visit(ctx.term(0)), ArithmeticOperator.BITXOR, (Term) visit(ctx.term(1))); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ProgramParser.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ProgramParserImpl.java similarity index 52% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ProgramParser.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ProgramParserImpl.java index 7bea8f5a2..2b7d82905 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ProgramParser.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ProgramParserImpl.java @@ -1,4 +1,11 @@ -package at.ac.tuwien.kr.alpha.grounder.parser; +package at.ac.tuwien.kr.alpha.core.parser; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.antlr.v4.runtime.BailErrorStrategy; import org.antlr.v4.runtime.CharStream; @@ -9,35 +16,36 @@ import org.antlr.v4.runtime.atn.PredictionMode; import org.antlr.v4.runtime.misc.ParseCancellationException; -import java.io.IOException; -import java.util.Collections; -import java.util.Map; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Lexer; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Parser; +import at.ac.tuwien.kr.alpha.core.externals.Externals; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; -import at.ac.tuwien.kr.alpha.CustomErrorListener; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Lexer; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Parser; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; +public class ProgramParserImpl implements ProgramParser { -public class ProgramParser { - private final Map externals; + private final Map preloadedExternals = new HashMap<>(); - public ProgramParser(Map externals) { - this.externals = externals; + public ProgramParserImpl() { + this.preloadedExternals.putAll(Externals.getStandardLibraryExternals()); } - public ProgramParser() { - this(Collections.emptyMap()); + public ProgramParserImpl(Map externals) { + this(); + this.preloadedExternals.putAll(externals); + } + + @Override + public ASPCore2Program parse(String s) { + return parse(s, Collections.emptyMap()); } - public InputProgram parse(String s) { + @Override + public ASPCore2Program parse(String s, Map externals) { try { - return parse(CharStreams.fromString(s)); - } catch (IOException e) { - // In this case we assume that something went fundamentally - // wrong when using a String as input. The caller probably - // assumes that I/O on a String should always be fine. - throw new RuntimeException("Encountered I/O-related exception while parsing a String.", e); + return parse(CharStreams.fromString(s), externals); } catch (RecognitionException | ParseCancellationException e) { // If there were issues parsing the given string, we // throw something that suggests that the input string @@ -46,7 +54,11 @@ public InputProgram parse(String s) { } } - public InputProgram parse(CharStream stream) throws IOException { + public ASPCore2Program parse(CharStream stream) { + return parse(stream, Collections.emptyMap()); + } + + public ASPCore2Program parse(CharStream stream, Map externals) { //@formatter:off /* * // In order to require less memory: use unbuffered streams and avoid constructing a full parse tree. @@ -104,8 +116,45 @@ public InputProgram parse(CharStream stream) throws IOException { throw new ParseCancellationException(); } + // The union of this parser's preloaded externals and the (program-specific) externals passed to the parse method + Map knownExternals; + if (externals != null && !externals.isEmpty()) { + knownExternals = new HashMap<>(preloadedExternals); + knownExternals.putAll(externals); + } else { + knownExternals = preloadedExternals; + } + // Construct internal program representation. - ParseTreeVisitor visitor = new ParseTreeVisitor(externals); + ParseTreeVisitor visitor = new ParseTreeVisitor(knownExternals); return visitor.translate(programContext); } + + @Override + public ASPCore2Program parse(InputStream programSource, Map externalPredicateDefinitions) throws IOException { + return parse(CharStreams.fromStream(programSource), externalPredicateDefinitions); + } + + @Override + public ASPCore2Program parse(Path programPath, Map externalPredicateDefinitions) throws IOException { + return parse(CharStreams.fromPath(programPath), externalPredicateDefinitions); + } + + @Override + public ASPCore2Program parse(Map externalPredicateDefinitions, Path... programSources) throws IOException { + InputProgram.Builder bld = InputProgram.builder(); + for (Path src : programSources) { + bld.accumulate(parse(src, externalPredicateDefinitions)); + } + return bld.build(); + } + + @Override + public ASPCore2Program parse(Iterable programSources, Map externalPredicateDefinitions) throws IOException { + InputProgram.Builder bld = InputProgram.builder(); + for (Path src : programSources) { + bld.accumulate(parse(src, externalPredicateDefinitions)); + } + return bld.build(); + } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ProgramPartParser.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ProgramPartParser.java similarity index 84% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ProgramPartParser.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ProgramPartParser.java index 56593b6a3..bc2690666 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/parser/ProgramPartParser.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/parser/ProgramPartParser.java @@ -26,23 +26,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.grounder.parser; +package at.ac.tuwien.kr.alpha.core.parser; + +import java.util.Collections; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Lexer; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Parser; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.Term; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.misc.ParseCancellationException; -import java.util.Collections; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Lexer; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Parser; /** - * A parser that, in contrast to {@link ProgramParser}, does not parse full programs but only program parts like + * A parser that, in contrast to {@link ProgramParserImpl}, does not parse full programs but only program parts like * atoms, terms and such. */ public class ProgramPartParser { @@ -55,7 +56,7 @@ public Term parseTerm(String s) { public BasicAtom parseBasicAtom(String s) { final ASPCore2Parser parser = getASPCore2Parser(s); - return (BasicAtom)parse(parser.classical_literal()); + return (BasicAtom) parse(parser.classical_literal()); } public Literal parseLiteral(String s) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/program/AbstractProgram.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/AbstractProgram.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/common/program/AbstractProgram.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/AbstractProgram.java index 05fb07ea1..31a3617af 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/program/AbstractProgram.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/AbstractProgram.java @@ -1,21 +1,22 @@ -package at.ac.tuwien.kr.alpha.common.program; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.rule.AbstractRule; -import at.ac.tuwien.kr.alpha.common.rule.head.Head; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; +package at.ac.tuwien.kr.alpha.core.programs; import java.util.Collections; import java.util.List; +import at.ac.tuwien.kr.alpha.api.programs.InlineDirectives; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.commons.util.Util; + /** * The parent type for all kinds of programs. Defines a program's basic structure (facts + rules + inlineDirectives) - * - * @param the type of rule a program permits. This needs to be determined by implementations based on which syntax constructs an implementation permits - * Copyright (c) 2019, the Alpha Team. + * + * @param the type of rule a program permits. This needs to be determined by implementations based on which syntax constructs an + * implementation permits + * Copyright (c) 2019, the Alpha Team. */ -public abstract class AbstractProgram> { +public abstract class AbstractProgram> { private final List rules; private final List facts; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/program/AnalyzedProgram.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/AnalyzedProgram.java similarity index 52% rename from src/main/java/at/ac/tuwien/kr/alpha/common/program/AnalyzedProgram.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/AnalyzedProgram.java index 1494729fe..c6e68c7ee 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/program/AnalyzedProgram.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/AnalyzedProgram.java @@ -1,13 +1,17 @@ -package at.ac.tuwien.kr.alpha.common.program; +package at.ac.tuwien.kr.alpha.core.programs; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.DependencyGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.StronglyConnectedComponentsAlgorithm; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.core.depgraph.DependencyGraphImpl; import org.apache.commons.lang3.tuple.ImmutablePair; -import java.util.List; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.core.depgraph.ComponentGraphImpl; +import at.ac.tuwien.kr.alpha.core.depgraph.StronglyConnectedComponentsAlgorithm; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; /** @@ -18,22 +22,22 @@ public class AnalyzedProgram extends InternalProgram { private final DependencyGraph dependencyGraph; - private final ComponentGraph componentGraph; + private final ComponentGraph componentGraph; - public AnalyzedProgram(List rules, List facts) { + public AnalyzedProgram(List rules, List facts) { super(rules, facts); - dependencyGraph = DependencyGraph.buildDependencyGraph(getRulesById()); + dependencyGraph = DependencyGraphImpl.buildDependencyGraph(getRulesById()); componentGraph = buildComponentGraph(dependencyGraph); } public static AnalyzedProgram analyzeNormalProgram(NormalProgram prog) { - ImmutablePair, List> rulesAndFacts = InternalProgram.internalizeRulesAndFacts(prog); + ImmutablePair, List> rulesAndFacts = InternalProgram.internalizeRulesAndFacts(prog); return new AnalyzedProgram(rulesAndFacts.left, rulesAndFacts.right); } private ComponentGraph buildComponentGraph(DependencyGraph depGraph) { StronglyConnectedComponentsAlgorithm.SccResult sccResult = StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(depGraph); - return ComponentGraph.buildComponentGraph(depGraph, sccResult); + return ComponentGraphImpl.buildComponentGraph(depGraph, sccResult); } public ComponentGraph getComponentGraph() { diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/CompiledProgram.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/CompiledProgram.java new file mode 100644 index 000000000..ab307bb67 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/CompiledProgram.java @@ -0,0 +1,20 @@ +package at.ac.tuwien.kr.alpha.core.programs; + +import java.util.LinkedHashSet; +import java.util.Map; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.Program; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; + +public interface CompiledProgram extends Program { + + Map> getPredicateDefiningRules(); + + Map> getFactsByPredicate(); + + Map getRulesById(); + + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/program/InputProgram.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/InputProgram.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/common/program/InputProgram.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/InputProgram.java index 2869e2adf..e9ba20032 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/program/InputProgram.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/InputProgram.java @@ -1,19 +1,19 @@ /** * Copyright (c) 2019, 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. - * + * 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 @@ -25,51 +25,54 @@ * 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.common.program; +package at.ac.tuwien.kr.alpha.core.programs; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.InlineDirectives; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.core.parser.InlineDirectivesImpl; /** * Alpha-internal representation of an ASP program, i.e., a set of ASP rules. - * + *

    * Copyright (c) 2017-2019, the Alpha Team. */ -public class InputProgram extends AbstractProgram { +public class InputProgram extends AbstractProgram> implements ASPCore2Program{ - public static final InputProgram EMPTY = new InputProgram(Collections.emptyList(), Collections.emptyList(), new InlineDirectives()); + public static final InputProgram EMPTY = new InputProgram(Collections.emptyList(), Collections.emptyList(), new InlineDirectivesImpl()); - public InputProgram(List rules, List facts, InlineDirectives inlineDirectives) { + public InputProgram(List> rules, List facts, InlineDirectives inlineDirectives) { super(rules, facts, inlineDirectives); } public InputProgram() { - super(new ArrayList<>(), new ArrayList<>(), new InlineDirectives()); + super(new ArrayList<>(), new ArrayList<>(), new InlineDirectivesImpl()); } public static Builder builder() { return new Builder(); } - public static Builder builder(InputProgram prog) { + public static Builder builder(ASPCore2Program prog) { return new Builder(prog); } /** - * Builder for more complex program construction scenarios, ensuring that an @{link InputProgram} is immutable + * Builder for more complex program construction scenarios, ensuring that an {@link InputProgram} is immutable */ public static class Builder { - private List rules = new ArrayList<>(); + private List> rules = new ArrayList<>(); private List facts = new ArrayList<>(); - private InlineDirectives inlineDirectives = new InlineDirectives(); + private InlineDirectives inlineDirectives = new InlineDirectivesImpl(); - public Builder(InputProgram prog) { + public Builder(ASPCore2Program prog) { this.addRules(prog.getRules()); this.addFacts(prog.getFacts()); this.addInlineDirectives(prog.getInlineDirectives()); @@ -79,12 +82,12 @@ public Builder() { } - public Builder addRules(List rules) { + public Builder addRules(List> rules) { this.rules.addAll(rules); return this; } - public Builder addRule(BasicRule r) { + public Builder addRule(Rule r) { this.rules.add(r); return this; } @@ -104,7 +107,7 @@ public Builder addInlineDirectives(InlineDirectives inlineDirectives) { return this; } - public Builder accumulate(InputProgram prog) { + public Builder accumulate(ASPCore2Program prog) { return this.addRules(prog.getRules()).addFacts(prog.getFacts()).addInlineDirectives(prog.getInlineDirectives()); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/program/InternalProgram.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/InternalProgram.java similarity index 54% rename from src/main/java/at/ac/tuwien/kr/alpha/common/program/InternalProgram.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/InternalProgram.java index 0a710e48b..bca2f97cc 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/program/InternalProgram.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/InternalProgram.java @@ -1,12 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.program; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.grounder.FactIntervalEvaluator; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import org.apache.commons.lang3.tuple.ImmutablePair; +package at.ac.tuwien.kr.alpha.core.programs; import java.util.ArrayList; import java.util.Collections; @@ -15,34 +7,48 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +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.rules.NormalRule; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.core.grounder.FactIntervalEvaluator; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; + /** * A program in the internal representation needed for grounder and solver, i.e.: rules must have normal heads, all * aggregates must be rewritten, all intervals must be preprocessed (into interval atoms), and equality predicates must * be rewritten. - * - * Copyright (c) 2017-2020, the Alpha Team. + *

    + * Copyright (c) 2017-2021, the Alpha Team. */ -public class InternalProgram extends AbstractProgram { +public class InternalProgram extends AbstractProgram implements CompiledProgram { - private final Map> predicateDefiningRules = new LinkedHashMap<>(); + private final Map> predicateDefiningRules = new LinkedHashMap<>(); private final Map> factsByPredicate = new LinkedHashMap<>(); - private final Map rulesById = new LinkedHashMap<>(); + private final Map rulesById = new LinkedHashMap<>(); - public InternalProgram(List rules, List facts) { + public InternalProgram(List rules, List facts) { super(rules, facts, null); recordFacts(facts); recordRules(rules); } - static ImmutablePair, List> internalizeRulesAndFacts(NormalProgram normalProgram) { - List internalRules = new ArrayList<>(); + static ImmutablePair, List> internalizeRulesAndFacts(NormalProgram normalProgram) { + List internalRules = new ArrayList<>(); List facts = new ArrayList<>(normalProgram.getFacts()); - for (NormalRule r : normalProgram.getRules()) { + for (Rule r : normalProgram.getRules()) { if (r.getBody().isEmpty()) { if (!r.getHead().isGround()) { throw new IllegalArgumentException("InternalProgram does not support non-ground rules with empty bodies! (Head = " + r.getHead().toString() + ")"); } - facts.add(r.getHeadAtom()); + facts.add(r.getHead().getAtom()); } else { internalRules.add(InternalRule.fromNormalRule(r)); } @@ -51,7 +57,7 @@ static ImmutablePair, List> internalizeRulesAndFacts(No } public static InternalProgram fromNormalProgram(NormalProgram normalProgram) { - ImmutablePair, List> rulesAndFacts = InternalProgram.internalizeRulesAndFacts(normalProgram); + ImmutablePair, List> rulesAndFacts = InternalProgram.internalizeRulesAndFacts(normalProgram); return new InternalProgram(rulesAndFacts.left, rulesAndFacts.right); } @@ -64,8 +70,8 @@ private void recordFacts(List facts) { } } - private void recordRules(List rules) { - for (InternalRule rule : rules) { + private void recordRules(List rules) { + for (CompiledRule rule : rules) { rulesById.put(rule.getRuleId(), rule); if (!rule.isConstraint()) { recordDefiningRule(rule.getHeadAtom().getPredicate(), rule); @@ -73,21 +79,32 @@ private void recordRules(List rules) { } } - private void recordDefiningRule(Predicate headPredicate, InternalRule rule) { + private void recordDefiningRule(Predicate headPredicate, CompiledRule rule) { predicateDefiningRules.putIfAbsent(headPredicate, new LinkedHashSet<>()); predicateDefiningRules.get(headPredicate).add(rule); } - public Map> getPredicateDefiningRules() { + @Override + public Map> getPredicateDefiningRules() { return Collections.unmodifiableMap(predicateDefiningRules); } + @Override public Map> getFactsByPredicate() { return Collections.unmodifiableMap(factsByPredicate); } - public Map getRulesById() { + @Override + public Map getRulesById() { return Collections.unmodifiableMap(rulesById); } + public NormalProgram toNormalProgram() { + List normalRules = new ArrayList<>(); + for (CompiledRule rule : getRules()) { + normalRules.add(new NormalRuleImpl(rule.getHead(), new ArrayList<>(rule.getBody()))); + } + return new NormalProgramImpl(normalRules, getFacts(), getInlineDirectives()); + } + } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/NormalProgramImpl.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/NormalProgramImpl.java new file mode 100644 index 000000000..dc886e47a --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/NormalProgramImpl.java @@ -0,0 +1,34 @@ +package at.ac.tuwien.kr.alpha.core.programs; + +import java.util.ArrayList; +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.InlineDirectives; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.rules.NormalRule; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; + +/** + * A program that only contains NormalRules. + * + * Copyright (c) 2019, the Alpha Team. + */ +public class NormalProgramImpl extends AbstractProgram implements NormalProgram { + + public NormalProgramImpl(List rules, List facts, InlineDirectives inlineDirectives) { + super(rules, facts, inlineDirectives); + } + + public static NormalProgramImpl fromInputProgram(ASPCore2Program inputProgram) { + List normalRules = new ArrayList<>(); + for (Rule r : inputProgram.getRules()) { + normalRules.add(NormalRuleImpl.fromBasicRule(r)); + } + return new NormalProgramImpl(normalRules, inputProgram.getFacts(), inputProgram.getInlineDirectives()); + } + +} diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/Programs.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/Programs.java new file mode 100644 index 000000000..e467c657f --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/Programs.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.kr.alpha.core.programs; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.antlr.v4.runtime.CharStreams; + +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; + +public class Programs { + + private Programs() { + throw new AssertionError("This is a pure utility class and should therefore not be instantiated!"); + } + + public static ASPCore2Program fromInputStream(InputStream is, Map externals) throws IOException { + ProgramParserImpl parser = new ProgramParserImpl(); + return parser.parse(CharStreams.fromStream(is), externals); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ArithmeticTermsRewriting.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ArithmeticTermsRewriting.java similarity index 72% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ArithmeticTermsRewriting.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ArithmeticTermsRewriting.java index 19ee47381..026cde8c5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ArithmeticTermsRewriting.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ArithmeticTermsRewriting.java @@ -1,23 +1,28 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; - -import static at.ac.tuwien.kr.alpha.Util.oops; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import java.util.ArrayList; import java.util.List; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +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.rules.NormalRule; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import at.ac.tuwien.kr.alpha.core.programs.NormalProgramImpl; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; /** * Transforms rules such that arithmetic terms only occur in comparison predicates. @@ -47,7 +52,7 @@ public NormalProgram apply(NormalProgram inputProgram) { return inputProgram; } // Create new program with rewritten rules. - return new NormalProgram(rewrittenRules, inputProgram.getFacts(), inputProgram.getInlineDirectives()); + return new NormalProgramImpl(rewrittenRules, inputProgram.getFacts(), inputProgram.getInlineDirectives()); } /** @@ -62,9 +67,9 @@ private NormalRule rewriteRule(NormalRule inputProgramRule) { List rewrittenBodyLiterals = new ArrayList<>(); // Rewrite head. if (!inputProgramRule.isConstraint()) { - Atom headAtom = inputProgramRule.getHeadAtom(); + BasicAtom headAtom = inputProgramRule.getHeadAtom(); if (containsArithmeticTermsToRewrite(headAtom)) { - rewrittenHead = new NormalHead(rewriteAtom(headAtom, rewrittenBodyLiterals)); + rewrittenHead = Heads.newNormalHead((BasicAtom) rewriteAtom(headAtom, rewrittenBodyLiterals)); } else { rewrittenHead = inputProgramRule.getHead(); } @@ -78,7 +83,7 @@ private NormalRule rewriteRule(NormalRule inputProgramRule) { } rewrittenBodyLiterals.add(rewriteAtom(literal.getAtom(), rewrittenBodyLiterals).toLiteral(!literal.isNegated())); } - return new NormalRule(rewrittenHead, rewrittenBodyLiterals); + return new NormalRuleImpl(rewrittenHead, rewrittenBodyLiterals); } /** @@ -110,8 +115,8 @@ private Term rewriteArithmeticSubterms(Term term, List bodyLiterals) { } // Switch on term type. if (term instanceof ArithmeticTerm) { - VariableTerm replacementVariable = VariableTerm.getInstance(ARITHMETIC_VARIABLES_PREFIX + numArithmeticVariables++); - bodyLiterals.add(new ComparisonAtom(replacementVariable, term, ComparisonOperator.EQ).toLiteral()); + VariableTerm replacementVariable = Terms.newVariable(ARITHMETIC_VARIABLES_PREFIX + numArithmeticVariables++); + bodyLiterals.add(Atoms.newComparisonAtom(replacementVariable, term, ComparisonOperators.EQ).toLiteral()); return replacementVariable; } else if (term instanceof VariableTerm || term instanceof ConstantTerm) { return term; @@ -121,15 +126,15 @@ private Term rewriteArithmeticSubterms(Term term, List bodyLiterals) { for (Term subterm : termList) { rewrittenTermList.add(rewriteArithmeticSubterms(subterm, bodyLiterals)); } - return FunctionTerm.getInstance(((FunctionTerm) term).getSymbol(), rewrittenTermList); + return Terms.newFunctionTerm(((FunctionTerm) term).getSymbol(), rewrittenTermList); } else { - throw oops("Rewriting unknown Term type: " + term.getClass()); + throw Util.oops("Rewriting unknown Term type: " + term.getClass()); } } private Atom rewriteAtom(Atom atomToRewrite, List bodyLiterals) { if (atomToRewrite instanceof ComparisonAtom) { - throw oops("Trying to rewrite ComparisonAtom."); + throw Util.oops("Trying to rewrite ComparisonAtom."); } List rewrittenTerms = new ArrayList<>(); for (Term atomTerm : atomToRewrite.getTerms()) { @@ -168,7 +173,7 @@ private boolean containsArithmeticTerm(Term term) { } else if (term instanceof IntervalTerm) { return containsArithmeticTerm(((IntervalTerm) term).getLowerBoundTerm()) || containsArithmeticTerm(((IntervalTerm) term).getUpperBoundTerm()); } else { - throw oops("Unexpected term type: " + term.getClass()); + throw Util.oops("Unexpected term type: " + term.getClass()); } } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ChoiceHeadToNormal.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ChoiceHeadToNormal.java similarity index 59% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ChoiceHeadToNormal.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ChoiceHeadToNormal.java index a38bcce0c..f54778b8c 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ChoiceHeadToNormal.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ChoiceHeadToNormal.java @@ -25,40 +25,46 @@ * 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.grounder.transformation; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.ChoiceHead; -import at.ac.tuwien.kr.alpha.common.rule.head.Head; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead.ChoiceElement; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +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.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; + /** - * Copyright (c) 2017-2020, the Alpha Team. + * Copyright (c) 2017-2021, the Alpha Team. */ -public class ChoiceHeadToNormal extends ProgramTransformation { +// TODO this could already give NormalProgram as result type +public class ChoiceHeadToNormal extends ProgramTransformation { private final static String PREDICATE_NEGATION_PREFIX = "_n"; @Override - public InputProgram apply(InputProgram inputProgram) { + public ASPCore2Program apply(ASPCore2Program inputProgram) { InputProgram.Builder programBuilder = InputProgram.builder(); - List additionalRules = new ArrayList<>(); + List> additionalRules = new ArrayList<>(); - List srcRules = new ArrayList<>(inputProgram.getRules()); - Iterator ruleIterator = srcRules.iterator(); + List> srcRules = new ArrayList<>(inputProgram.getRules()); + Iterator> ruleIterator = srcRules.iterator(); while (ruleIterator.hasNext()) { - BasicRule rule = ruleIterator.next(); + Rule rule = ruleIterator.next(); Head ruleHead = rule.getHead(); if (!(ruleHead instanceof ChoiceHead)) { @@ -76,13 +82,13 @@ public InputProgram apply(InputProgram inputProgram) { } // Only rewrite rules with a choice in their head. - for (ChoiceHead.ChoiceElement choiceElement : choiceHead.getChoiceElements()) { + for (ChoiceElement choiceElement : choiceHead.getChoiceElements()) { // Create two guessing rules for each choiceElement. // Construct common body to both rules. - Atom head = choiceElement.choiceAtom; + BasicAtom head = choiceElement.getChoiceAtom(); List ruleBody = new ArrayList<>(rule.getBody()); - ruleBody.addAll(choiceElement.conditionLiterals); + ruleBody.addAll(choiceElement.getConditionLiterals()); if (containsIntervalTerms(head)) { throw new RuntimeException("Program contains a choice rule with interval terms in its head. This is not supported (yet)."); @@ -91,20 +97,20 @@ public InputProgram apply(InputProgram inputProgram) { // Construct head atom for the choice. Predicate headPredicate = head.getPredicate(); - Predicate negPredicate = Predicate.getInstance(PREDICATE_NEGATION_PREFIX + headPredicate.getName(), headPredicate.getArity() + 1, true); + Predicate negPredicate = Predicates.getPredicate(PREDICATE_NEGATION_PREFIX + headPredicate.getName(), headPredicate.getArity() + 1, true); List headTerms = new ArrayList<>(head.getTerms()); - headTerms.add(0, ConstantTerm.getInstance("1")); // FIXME: when introducing classical negation, this is 1 for classical positive atoms and 0 for + headTerms.add(0, Terms.newConstant("1")); // FIXME: when introducing classical negation, this is 1 for classical positive atoms and 0 for // classical negative atoms. - Atom negHead = new BasicAtom(negPredicate, headTerms); + BasicAtom negHead = Atoms.newBasicAtom(negPredicate, headTerms); // Construct two guessing rules. List guessingRuleBodyWithNegHead = new ArrayList<>(ruleBody); - guessingRuleBodyWithNegHead.add(new BasicAtom(head.getPredicate(), head.getTerms()).toLiteral(false)); - additionalRules.add(new BasicRule(new NormalHead(negHead), guessingRuleBodyWithNegHead)); + guessingRuleBodyWithNegHead.add(Atoms.newBasicAtom(head.getPredicate(), head.getTerms()).toLiteral(false)); + additionalRules.add(new BasicRule(Heads.newNormalHead(negHead), guessingRuleBodyWithNegHead)); List guessingRuleBodyWithHead = new ArrayList<>(ruleBody); - guessingRuleBodyWithHead.add(new BasicAtom(negPredicate, headTerms).toLiteral(false)); - additionalRules.add(new BasicRule(new NormalHead(head), guessingRuleBodyWithHead)); + guessingRuleBodyWithHead.add(Atoms.newBasicAtom(negPredicate, headTerms).toLiteral(false)); + additionalRules.add(new BasicRule(Heads.newNormalHead(head), guessingRuleBodyWithHead)); // TODO: when cardinality constraints are possible, process the boundaries by adding a constraint with a cardinality check. } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/EnumerationRewriting.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/EnumerationRewriting.java similarity index 54% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/EnumerationRewriting.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/EnumerationRewriting.java index f080496e7..ca1c6a54a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/EnumerationRewriting.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/EnumerationRewriting.java @@ -1,21 +1,27 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; +package at.ac.tuwien.kr.alpha.core.programs.transformation; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.grounder.atoms.EnumerationAtom; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import static at.ac.tuwien.kr.alpha.Util.oops; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.programs.literals.BasicLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +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.Predicates; +import at.ac.tuwien.kr.alpha.core.atoms.EnumerationAtom; +import at.ac.tuwien.kr.alpha.core.parser.InlineDirectivesImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; /** * Rewrites the ordinary atom whose name is given in the input program by the enumeration directive #enum_atom_is into @@ -23,24 +29,25 @@ * * Copyright (c) 2017-2020, the Alpha Team. */ -public class EnumerationRewriting extends ProgramTransformation { +// TODO this should happen during/after internalization +public class EnumerationRewriting extends ProgramTransformation { @Override - public InputProgram apply(InputProgram inputProgram) { + public ASPCore2Program apply(ASPCore2Program inputProgram) { // Read enumeration predicate from directive. - String enumDirective = inputProgram.getInlineDirectives().getDirectiveValue(InlineDirectives.DIRECTIVE.enum_predicate_is); + String enumDirective = inputProgram.getInlineDirectives().getDirectiveValue(InlineDirectivesImpl.DIRECTIVE.enum_predicate_is); if (enumDirective == null) { // Directive not set, nothing to rewrite. return inputProgram; } - Predicate enumPredicate = Predicate.getInstance(enumDirective, 3); + Predicate enumPredicate = Predicates.getPredicate(enumDirective, 3); InputProgram.Builder programBuilder = InputProgram.builder().addInlineDirectives(inputProgram.getInlineDirectives()); checkFactsAreEnumerationFree(inputProgram.getFacts(), enumPredicate); programBuilder.addFacts(inputProgram.getFacts()); - List srcRules = new ArrayList<>(inputProgram.getRules()); + List> srcRules = new ArrayList<>(inputProgram.getRules()); programBuilder.addRules(rewriteRules(srcRules, enumPredicate)); return programBuilder.build(); } @@ -53,9 +60,9 @@ private void checkFactsAreEnumerationFree(List srcFacts, Predicate enumPre } } - private List rewriteRules(List srcRules, Predicate enumPredicate) { - List rewrittenRules = new ArrayList<>(); - for (BasicRule rule : srcRules) { + private List> rewriteRules(List> srcRules, Predicate enumPredicate) { + List> rewrittenRules = new ArrayList<>(); + for (Rule rule : srcRules) { if (rule.getHead() != null && !(rule.getHead() instanceof NormalHead)) { throw oops("Encountered rule whose head is not normal: " + rule); } @@ -74,8 +81,12 @@ private List rewriteRules(List srcRules, Predicate enumPre if (!basicLiteral.getPredicate().equals(enumPredicate)) { continue; } + // basicLiteral is an enumeration literal (i.e. predicate is marked as enum using directive) rit.remove(); - rewrittenLiterals.add(new EnumerationAtom(basicLiteral.getAtom().getTerms()).toLiteral()); + Term enumIdTerm = basicLiteral.getAtom().getTerms().get(0); + Term valueTerm = basicLiteral.getAtom().getTerms().get(1); + VariableTerm indexTerm = (VariableTerm) basicLiteral.getAtom().getTerms().get(2); + rewrittenLiterals.add(new EnumerationAtom(enumIdTerm, valueTerm, indexTerm).toLiteral()); } modifiedBodyLiterals.addAll(rewrittenLiterals); rewrittenRules.add(new BasicRule(rule.getHead(), modifiedBodyLiterals)); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/IntervalTermToIntervalAtom.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/IntervalTermToIntervalAtom.java similarity index 74% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/IntervalTermToIntervalAtom.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/IntervalTermToIntervalAtom.java index c0702d05a..36920ec71 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/IntervalTermToIntervalAtom.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/IntervalTermToIntervalAtom.java @@ -25,26 +25,31 @@ * 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.grounder.transformation; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.atoms.IntervalAtom; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +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.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.NormalRule; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.atoms.IntervalAtom; +import at.ac.tuwien.kr.alpha.core.programs.NormalProgramImpl; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; + /** * Rewrites all interval terms in a rule into a new variable and an IntervalAtom. * Literals of the form "X = A..B" are rewritten with X being used directly and no new variable being introduced. @@ -71,8 +76,10 @@ private static NormalRule rewriteIntervalSpecifications(NormalRule rule) { rewrittenBody.add(rewrittenLiteral); } } - NormalHead rewrittenHead = rule.isConstraint() ? null : - new NormalHead(rewriteLiteral(rule.getHeadAtom().toLiteral(), intervalReplacements).getAtom()); + // Note that this cast is safe: NormalHead can only have a BasicAtom, so literalizing and getting back the Atom destroys type information, + // but should never yield anything other than a BasicAtom + NormalHead rewrittenHead = rule.isConstraint() ? null + : Heads.newNormalHead((BasicAtom) rewriteLiteral(rule.getHead().getAtom().toLiteral(), intervalReplacements).getAtom()); // If intervalReplacements is empty, no IntervalTerms have been found, keep rule as is. if (intervalReplacements.isEmpty()) { @@ -83,25 +90,27 @@ private static NormalRule rewriteIntervalSpecifications(NormalRule rule) { for (Map.Entry interval : intervalReplacements.entrySet()) { rewrittenBody.add(new IntervalAtom(interval.getValue(), interval.getKey()).toLiteral()); } - return new NormalRule(rewrittenHead, rewrittenBody); + return new NormalRuleImpl(rewrittenHead, rewrittenBody); } /** * Replaces every IntervalTerm by a new variable and returns a mapping of the replaced VariableTerm -> IntervalTerm. + * * @return the rewritten literal or null if the literal should be dropped from the final rule. */ private static Literal rewriteLiteral(Literal lit, Map intervalReplacement) { - // Treat special case: if the literal is of the form "X = A .. B", use X in the interval replacement directly and drop the equality from the final rule. - if (lit instanceof ComparisonLiteral && ((ComparisonLiteral)lit).isNormalizedEquality()) { + // Treat special case: if the literal is of the form "X = A .. B", use X in the interval replacement directly and drop the equality from the + // final rule. + if (lit instanceof ComparisonLiteral && ((ComparisonLiteral) lit).isNormalizedEquality()) { ComparisonAtom equalityLiteral = (ComparisonAtom) lit.getAtom(); if (equalityLiteral.getTerms().get(0) instanceof VariableTerm && equalityLiteral.getTerms().get(1) instanceof IntervalTerm) { // Literal is of the form "X = A .. B". - intervalReplacement.put((VariableTerm)equalityLiteral.getTerms().get(0), (IntervalTerm)equalityLiteral.getTerms().get(1)); + intervalReplacement.put((VariableTerm) equalityLiteral.getTerms().get(0), (IntervalTerm) equalityLiteral.getTerms().get(1)); return null; } if (equalityLiteral.getTerms().get(1) instanceof VariableTerm && equalityLiteral.getTerms().get(0) instanceof IntervalTerm) { // Literal is of the form "A .. B = X". - intervalReplacement.put((VariableTerm)equalityLiteral.getTerms().get(1), (IntervalTerm)equalityLiteral.getTerms().get(0)); + intervalReplacement.put((VariableTerm) equalityLiteral.getTerms().get(1), (IntervalTerm) equalityLiteral.getTerms().get(0)); return null; } } @@ -111,7 +120,7 @@ private static Literal rewriteLiteral(Literal lit, Map { +public class NormalizeProgramTransformation extends ProgramTransformation { private final AggregateRewritingConfig aggregateRewritingCfg; @@ -21,20 +21,20 @@ public NormalizeProgramTransformation(AggregateRewritingConfig aggregateCfg) { } @Override - public NormalProgram apply(InputProgram inputProgram) { - InputProgram tmpPrg; + public NormalProgram apply(ASPCore2Program inputProgram) { + ASPCore2Program tmpPrg; // Remove variable equalities. tmpPrg = new VariableEqualityRemoval().apply(inputProgram); // Transform choice rules. tmpPrg = new ChoiceHeadToNormal().apply(tmpPrg); - // Transform cardinality aggregates. + // Transform aggregates. tmpPrg = new AggregateRewriting(aggregateRewritingCfg.isUseSortingGridEncoding(), aggregateRewritingCfg.isSupportNegativeValuesInSums()).apply(tmpPrg); // Transform enumeration atoms. tmpPrg = new EnumerationRewriting().apply(tmpPrg); EnumerationAtom.resetEnumerations(); // Construct the normal program. - NormalProgram retVal = NormalProgram.fromInputProgram(tmpPrg); + NormalProgram retVal = NormalProgramImpl.fromInputProgram(tmpPrg); // Transform intervals. retVal = new IntervalTermToIntervalAtom().apply(retVal); // Rewrite ArithmeticTerms. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/PredicateInternalizer.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/PredicateInternalizer.java similarity index 50% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/PredicateInternalizer.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/PredicateInternalizer.java index 07934643e..6a71a1092 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/PredicateInternalizer.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/PredicateInternalizer.java @@ -1,17 +1,22 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import java.util.ArrayList; import java.util.List; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.Head; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.BasicLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; /** * @@ -21,24 +26,23 @@ */ public class PredicateInternalizer { - - public static InputProgram makePrefixedPredicatesInternal(InputProgram program, String prefix) { + public static ASPCore2Program makePrefixedPredicatesInternal(ASPCore2Program program, String prefix) { InputProgram.Builder prgBuilder = InputProgram.builder(); for (Atom atom : program.getFacts()) { if (atom.getPredicate().getName().startsWith(prefix)) { - prgBuilder.addFact(PredicateInternalizer.makePredicateInternal(atom)); + prgBuilder.addFact(PredicateInternalizer.makePredicateInternal((BasicAtom) atom)); } else { prgBuilder.addFact(atom); } } - for (BasicRule rule : program.getRules()) { + for (Rule rule : program.getRules()) { prgBuilder.addRule(PredicateInternalizer.makePrefixedPredicatesInternal(rule, prefix)); } prgBuilder.addInlineDirectives(program.getInlineDirectives()); return prgBuilder.build(); } - public static BasicRule makePrefixedPredicatesInternal(BasicRule rule, String prefix) { + public static Rule makePrefixedPredicatesInternal(Rule rule, String prefix) { Head newHead = null; if (rule.getHead() != null) { if (!(rule.getHead() instanceof NormalHead)) { @@ -46,7 +50,7 @@ public static BasicRule makePrefixedPredicatesInternal(BasicRule rule, String pr } NormalHead head = (NormalHead) rule.getHead(); if (head.getAtom().getPredicate().getName().startsWith(prefix)) { - newHead = new NormalHead(makePredicateInternal(head.getAtom())); + newHead = Heads.newNormalHead(makePredicateInternal(head.getAtom())); } else { newHead = head; } @@ -56,7 +60,7 @@ public static BasicRule makePrefixedPredicatesInternal(BasicRule rule, String pr // Only rewrite BasicAtoms. if (bodyElement instanceof BasicLiteral) { if (bodyElement.getAtom().getPredicate().getName().startsWith(prefix)) { - newBody.add(makePredicateInternal(bodyElement.getAtom()).toLiteral(!bodyElement.isNegated())); + newBody.add(makePredicateInternal((BasicAtom) bodyElement.getAtom()).toLiteral(!bodyElement.isNegated())); } else { newBody.add(bodyElement); } @@ -68,8 +72,8 @@ public static BasicRule makePrefixedPredicatesInternal(BasicRule rule, String pr return new BasicRule(newHead, newBody); } - private static Atom makePredicateInternal(Atom atom) { - Predicate newInternalPredicate = Predicate.getInstance(atom.getPredicate().getName(), atom.getPredicate().getArity(), true); - return new BasicAtom(newInternalPredicate, atom.getTerms()); + private static BasicAtom makePredicateInternal(BasicAtom atom) { + Predicate newInternalPredicate = Predicates.getPredicate(atom.getPredicate().getName(), atom.getPredicate().getArity(), true); + return Atoms.newBasicAtom(newInternalPredicate, atom.getTerms()); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ProgramTransformation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ProgramTransformation.java new file mode 100644 index 000000000..0b7d4e7f1 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ProgramTransformation.java @@ -0,0 +1,13 @@ +package at.ac.tuwien.kr.alpha.core.programs.transformation; + +import at.ac.tuwien.kr.alpha.api.programs.Program; +import at.ac.tuwien.kr.alpha.api.rules.Rule; + +/** + * Copyright (c) 2017-2019, the Alpha Team. + */ +public abstract class ProgramTransformation>, O extends Program>> { + + public abstract O apply(I inputProgram); + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java similarity index 80% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java index 36cba1580..9dfc543e2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluation.java @@ -1,30 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph.SCComponent; -import at.ac.tuwien.kr.alpha.common.depgraph.Node; -import at.ac.tuwien.kr.alpha.common.depgraph.StratificationAlgorithm; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.IndexedInstanceStorage; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import at.ac.tuwien.kr.alpha.grounder.RuleGroundingOrder; -import at.ac.tuwien.kr.alpha.grounder.RuleGroundingOrders; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.WorkingMemory; -import at.ac.tuwien.kr.alpha.grounder.instantiation.AssignmentStatus; -import at.ac.tuwien.kr.alpha.grounder.instantiation.LiteralInstantiationResult; -import at.ac.tuwien.kr.alpha.grounder.instantiation.LiteralInstantiator; -import at.ac.tuwien.kr.alpha.grounder.instantiation.WorkingMemoryBasedInstantiationStrategy; -import org.apache.commons.collections4.SetUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import java.util.ArrayList; import java.util.Collections; @@ -37,6 +11,33 @@ import java.util.Set; import java.util.Stack; +import org.apache.commons.collections4.SetUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.core.depgraph.StratificationAlgorithm; +import at.ac.tuwien.kr.alpha.core.grounder.IndexedInstanceStorage; +import at.ac.tuwien.kr.alpha.core.grounder.RuleGroundingInfo; +import at.ac.tuwien.kr.alpha.core.grounder.RuleGroundingOrder; +import at.ac.tuwien.kr.alpha.core.grounder.WorkingMemory; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.AssignmentStatus; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.LiteralInstantiationResult; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.LiteralInstantiator; +import at.ac.tuwien.kr.alpha.core.grounder.instantiation.WorkingMemoryBasedInstantiationStrategy; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; + /** * Evaluates the stratifiable part of a given (analyzed) ASP program. * @@ -47,7 +48,7 @@ public class StratifiedEvaluation extends ProgramTransformation> predicateDefiningRules; + private Map> predicateDefiningRules; private Map> modifiedInLastEvaluationRun = new HashMap<>(); @@ -62,7 +63,7 @@ public class StratifiedEvaluation extends ProgramTransformation strata = StratificationAlgorithm.calculateStratification(componentGraph); + List strata = StratificationAlgorithm.calculateStratification(componentGraph); predicateDefiningRules = inputProgram.getPredicateDefiningRules(); // Set up list of atoms which are known to be true - these will be expand by the evaluation. @@ -73,7 +74,7 @@ public InternalProgram apply(AnalyzedProgram inputProgram) { } // Create working memories for all predicates occurring in each rule. - for (InternalRule nonGroundRule : inputProgram.getRulesById().values()) { + for (CompiledRule nonGroundRule : inputProgram.getRulesById().values()) { for (Predicate predicate : nonGroundRule.getOccurringPredicates()) { workingMemory.initialize(predicate); } @@ -85,13 +86,13 @@ public InternalProgram apply(AnalyzedProgram inputProgram) { literalInstantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(workingMemory)); // Evaluate the program part covered by the calculated stratification. - for (SCComponent currComponent : strata) { + for (ComponentGraph.SCComponent currComponent : strata) { evaluateComponent(currComponent); } // Build the program resulting from evaluating the stratified part. additionalFacts.addAll(inputProgram.getFacts()); // Add original input facts to newly derived ones. - List outputRules = new ArrayList<>(); + List outputRules = new ArrayList<>(); inputProgram.getRulesById().entrySet().stream().filter((entry) -> !solvedRuleIds.contains(entry.getKey())) .forEach((entry) -> outputRules.add(entry.getValue())); @@ -99,7 +100,7 @@ public InternalProgram apply(AnalyzedProgram inputProgram) { return new InternalProgram(outputRules, additionalFacts); } - private void evaluateComponent(SCComponent comp) { + private void evaluateComponent(ComponentGraph.SCComponent comp) { LOGGER.debug("Evaluating component {}", comp); ComponentEvaluationInfo evaluationInfo = getRulesToEvaluate(comp); if (evaluationInfo.isEmpty()) { @@ -114,7 +115,7 @@ private void evaluateComponent(SCComponent comp) { for (IndexedInstanceStorage instanceStorage : workingMemory.modified()) { // Directly record all newly derived instances as additional facts. for (Instance recentlyAddedInstance : instanceStorage.getRecentlyAddedInstances()) { - additionalFacts.add(new BasicAtom(instanceStorage.getPredicate(), recentlyAddedInstance.terms)); + additionalFacts.add(Atoms.newBasicAtom(instanceStorage.getPredicate(), recentlyAddedInstance.terms)); } instanceStorage.markRecentlyAddedInstancesDone(); } @@ -134,7 +135,7 @@ private void evaluateComponent(SCComponent comp) { for (IndexedInstanceStorage instanceStorage : workingMemory.modified()) { // Directly record all newly derived instances as additional facts. for (Instance recentlyAddedInstance : instanceStorage.getRecentlyAddedInstances()) { - additionalFacts.add(new BasicAtom(instanceStorage.getPredicate(), recentlyAddedInstance.terms)); + additionalFacts.add(Atoms.newBasicAtom(instanceStorage.getPredicate(), recentlyAddedInstance.terms)); } modifiedInLastEvaluationRun.putIfAbsent(instanceStorage.getPredicate(), new LinkedHashSet<>()); modifiedInLastEvaluationRun.get(instanceStorage.getPredicate()).addAll(instanceStorage.getRecentlyAddedInstances()); @@ -148,10 +149,10 @@ private void evaluateComponent(SCComponent comp) { .forEach((rule) -> solvedRuleIds.add(rule.getRuleId())); } - private void evaluateRules(Set rules, boolean isInitialRun) { + private void evaluateRules(Set rules, boolean isInitialRun) { workingMemory.reset(); LOGGER.debug("Starting component evaluation run..."); - for (InternalRule r : rules) { + for (CompiledRule r : rules) { evaluateRule(r, !isInitialRun); } } @@ -161,9 +162,9 @@ private void evaluateRules(Set rules, boolean isInitialRun) { * of rules to the "modifiedInLastEvaluationRun" map in order to "bootstrap" incremental grounding, i.e. making sure * that those instances are taken into account for ground substitutions by evaluateRule. */ - private void prepareInitialEvaluation(Set rulesToEvaluate) { + private void prepareInitialEvaluation(Set rulesToEvaluate) { modifiedInLastEvaluationRun = new HashMap<>(); - for (InternalRule rule : rulesToEvaluate) { + for (CompiledRule rule : rulesToEvaluate) { // Register rule head instances. Predicate headPredicate = rule.getHeadAtom().getPredicate(); IndexedInstanceStorage headInstances = workingMemory.get(headPredicate, true); @@ -183,7 +184,7 @@ private void prepareInitialEvaluation(Set rulesToEvaluate) { } } - private void evaluateRule(InternalRule rule, boolean checkAllStartingLiterals) { + private void evaluateRule(CompiledRule rule, boolean checkAllStartingLiterals) { LOGGER.debug("Evaluating rule {}", rule); List satisfyingSubstitutions = calculateSatisfyingSubstitutionsForRule(rule, checkAllStartingLiterals); for (Substitution subst : satisfyingSubstitutions) { @@ -191,15 +192,15 @@ private void evaluateRule(InternalRule rule, boolean checkAllStartingLiterals) { } } - private List calculateSatisfyingSubstitutionsForRule(InternalRule rule, boolean checkAllStartingLiterals) { + private List calculateSatisfyingSubstitutionsForRule(CompiledRule rule, boolean checkAllStartingLiterals) { LOGGER.debug("Grounding rule {}", rule); - RuleGroundingOrders groundingOrders = rule.getGroundingOrders(); + RuleGroundingInfo groundingOrders = rule.getGroundingInfo(); // Treat rules with fixed instantiation first. - LOGGER.debug("Is fixed rule? {}", rule.getGroundingOrders().fixedInstantiation()); - if (groundingOrders.fixedInstantiation()) { + LOGGER.debug("Is fixed rule? {}", rule.getGroundingInfo().hasFixedInstantiation()); + if (groundingOrders.hasFixedInstantiation()) { RuleGroundingOrder fixedGroundingOrder = groundingOrders.getFixedGroundingOrder(); - return calcSubstitutionsWithGroundingOrder(fixedGroundingOrder, Collections.singletonList(new Substitution())); + return calcSubstitutionsWithGroundingOrder(fixedGroundingOrder, Collections.singletonList(new BasicSubstitution())); } List startingLiterals = groundingOrders.getStartingLiterals(); @@ -236,7 +237,7 @@ private List substituteFromRecentlyAddedInstances(Literal lit) { return Collections.emptyList(); } for (Instance instance : instances) { - Substitution unifyingSubstitution = Substitution.specializeSubstitution(lit, instance, Substitution.EMPTY_SUBSTITUTION); + Substitution unifyingSubstitution = BasicSubstitution.specializeSubstitution(lit, instance, BasicSubstitution.EMPTY_SUBSTITUTION); if (unifyingSubstitution != null) { retVal.add(unifyingSubstitution); } @@ -295,7 +296,7 @@ private List calcSubstitutionsWithGroundingOrder(RuleGroundingOrde return fullSubstitutions; } - private void fireRule(InternalRule rule, Substitution substitution) { + private void fireRule(CompiledRule rule, Substitution substitution) { Atom newAtom = rule.getHeadAtom().substitute(substitution); if (!newAtom.isGround()) { throw new IllegalStateException("Trying to fire rule " + rule.toString() + " with incompatible substitution " + substitution.toString()); @@ -304,25 +305,25 @@ private void fireRule(InternalRule rule, Substitution substitution) { workingMemory.addInstance(newAtom, true); } - private ComponentEvaluationInfo getRulesToEvaluate(SCComponent comp) { - Set nonRecursiveRules = new HashSet<>(); - Set recursiveRules = new HashSet<>(); + private ComponentEvaluationInfo getRulesToEvaluate(ComponentGraph.SCComponent comp) { + Set nonRecursiveRules = new HashSet<>(); + Set recursiveRules = new HashSet<>(); // Collect all predicates occurring in heads of rules of the given component. Set headPredicates = new HashSet<>(); - for (Node node : comp.getNodes()) { + for (DependencyGraph.Node node : comp.getNodes()) { headPredicates.add(node.getPredicate()); } // Check each predicate whether its defining rules depend on some of the head predicates, i.e., whether there is a // cycle. for (Predicate headPredicate : headPredicates) { - HashSet definingRules = predicateDefiningRules.get(headPredicate); + HashSet definingRules = predicateDefiningRules.get(headPredicate); if (definingRules == null) { // Predicate only occurs in facts, skip. continue; } // Note: here we assume that all rules defining a predicate belong to the same SC component. - for (InternalRule rule : definingRules) { + for (CompiledRule rule : definingRules) { boolean isRuleRecursive = false; for (Literal lit : rule.getPositiveBody()) { if (headPredicates.contains(lit.getPredicate())) { @@ -351,10 +352,10 @@ private ComponentEvaluationInfo getRulesToEvaluate(SCComponent comp) { * Copyright (c) 2020, the Alpha Team. */ private class ComponentEvaluationInfo { - final Set nonRecursiveRules; - final Set recursiveRules; + final Set nonRecursiveRules; + final Set recursiveRules; - ComponentEvaluationInfo(Set nonRecursive, Set recursive) { + ComponentEvaluationInfo(Set nonRecursive, Set recursive) { nonRecursiveRules = Collections.unmodifiableSet(nonRecursive); recursiveRules = Collections.unmodifiableSet(recursive); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/VariableEqualityRemoval.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/VariableEqualityRemoval.java similarity index 82% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/VariableEqualityRemoval.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/VariableEqualityRemoval.java index 357b6d7cd..1e1ae53a3 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/VariableEqualityRemoval.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/VariableEqualityRemoval.java @@ -25,18 +25,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.grounder.transformation; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.DisjunctiveHead; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Unifier; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import java.util.ArrayList; import java.util.Arrays; @@ -48,23 +37,38 @@ import java.util.List; import java.util.Map; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.DisjunctiveHead; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +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.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.substitutions.Unifier; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; + /** * Removes variable equalities from rules by replacing one variable with the other. * * Copyright (c) 2017-2021, the Alpha Team. */ -public class VariableEqualityRemoval extends ProgramTransformation { +public class VariableEqualityRemoval extends ProgramTransformation { @Override - public InputProgram apply(InputProgram inputProgram) { - List rewrittenRules = new ArrayList<>(); - for (BasicRule rule : inputProgram.getRules()) { + public ASPCore2Program apply(ASPCore2Program inputProgram) { + List> rewrittenRules = new ArrayList<>(); + for (Rule rule : inputProgram.getRules()) { rewrittenRules.add(findAndReplaceVariableEquality(rule)); } return new InputProgram(rewrittenRules, inputProgram.getFacts(), inputProgram.getInlineDirectives()); } - private BasicRule findAndReplaceVariableEquality(BasicRule rule) { + private Rule findAndReplaceVariableEquality(Rule rule) { // Collect all equal variables. HashMap> variableToEqualVariables = new LinkedHashMap<>(); HashSet equalitiesToRemove = new HashSet<>(); @@ -112,7 +116,7 @@ private BasicRule findAndReplaceVariableEquality(BasicRule rule) { if (!rule.isConstraint() && rule.getHead() instanceof DisjunctiveHead) { throw new UnsupportedOperationException("VariableEqualityRemoval cannot be applied to rule with DisjunctiveHead, yet."); } - NormalHead rewrittenHead = rule.isConstraint() ? null : new NormalHead(((NormalHead)rule.getHead()).getAtom()); + NormalHead rewrittenHead = rule.isConstraint() ? null : Heads.newNormalHead(((NormalHead)rule.getHead()).getAtom()); // Use substitution for actual replacement. Unifier replacementSubstitution = new Unifier(); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateLiteralSplitting.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateLiteralSplitting.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateLiteralSplitting.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateLiteralSplitting.java index 374d553a3..457d41daa 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateLiteralSplitting.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateLiteralSplitting.java @@ -1,16 +1,21 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; - -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import org.apache.commons.lang3.tuple.ImmutablePair; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; + /** * Splits aggregate literals with both "lower" and "upper" bound operators into literals with only one operator each. * @@ -34,7 +39,7 @@ private AggregateLiteralSplitting() { throw new UnsupportedOperationException("Utility class - cannot instantiate!"); } - public static List split(BasicRule sourceRule) { + public static List> split(Rule sourceRule) { // Check if body contains aggregates that need to be split. for (Literal lit : sourceRule.getBody()) { if (lit instanceof AggregateLiteral && shouldRewrite((AggregateLiteral) lit)) { @@ -45,7 +50,7 @@ public static List split(BasicRule sourceRule) { return Collections.singletonList(sourceRule); } - private static List splitAggregatesInRule(BasicRule sourceRule) { + private static List> splitAggregatesInRule(Rule sourceRule) { // Rule contains some aggregates that need splitting. // Aggregates may require splitting in two literals, or in two rules. List commonBodyLiterals = new ArrayList<>(); @@ -64,7 +69,7 @@ private static List splitAggregatesInRule(BasicRule sourceRule) { List commonBody = new ArrayList<>(commonBodyLiterals); commonBody.addAll(twoLiteralsSplitAggregates); List> rewrittenBodies = new ArrayList<>(); - rewrittenBodies.add(commonBody); // Initialize list of rules with the common body. + rewrittenBodies.add(commonBody); // Initialize list of rules with the common body. // For n twoRulesSplitAggregates we need 2^n rules, so // for each of the n pairs in twoRulesSplitAggregates we duplicate the list of rewritten bodies. for (ImmutablePair ruleSplitAggregate : twoRulesSplitAggregates) { @@ -79,21 +84,22 @@ private static List splitAggregatesInRule(BasicRule sourceRule) { } } // Third, turn computed bodies into rules again. - List rewrittenRules = new ArrayList<>(); + List> rewrittenRules = new ArrayList<>(); for (List rewrittenBody : rewrittenBodies) { rewrittenRules.add(new BasicRule(sourceRule.getHead(), rewrittenBody)); } return rewrittenRules; } - private static void splitCombinedAggregateLiteral(Literal literal, List twoLiteralsSplitAggregates, List> twoRulesSplitAggregates) { + private static void splitCombinedAggregateLiteral(Literal literal, List twoLiteralsSplitAggregates, + List> twoRulesSplitAggregates) { AggregateLiteral aggLit = (AggregateLiteral) literal; ImmutablePair splitAggregate = splitCombinedAggregateAtom(aggLit.getAtom()); if (literal.isNegated()) { // Negated aggregate require splitting in two rules. twoRulesSplitAggregates.add(new ImmutablePair<>( - splitAggregate.left.toLiteral(false), - splitAggregate.right.toLiteral(false))); + splitAggregate.left.toLiteral(false), + splitAggregate.right.toLiteral(false))); } else { // Positive aggregate requires two literals in the body. twoLiteralsSplitAggregates.add(splitAggregate.left.toLiteral(true)); @@ -106,30 +112,28 @@ private static boolean shouldRewrite(AggregateLiteral lit) { } private static ImmutablePair splitCombinedAggregateAtom(AggregateAtom atom) { - AggregateAtom leftHandAtom = new AggregateAtom(atom.getLowerBoundOperator(), atom.getLowerBoundTerm(), atom.getAggregatefunction(), + AggregateAtom leftHandAtom = Atoms.newAggregateAtom(atom.getLowerBoundOperator(), atom.getLowerBoundTerm(), atom.getAggregateFunction(), atom.getAggregateElements()); - AggregateAtom rightHandAtom = new AggregateAtom(switchOperands(atom.getUpperBoundOperator()), atom.getUpperBoundTerm(), - atom.getAggregatefunction(), atom.getAggregateElements()); + AggregateAtom rightHandAtom = Atoms.newAggregateAtom(switchOperands(atom.getUpperBoundOperator()), atom.getUpperBoundTerm(), + atom.getAggregateFunction(), atom.getAggregateElements()); return new ImmutablePair<>(leftHandAtom, rightHandAtom); } private static ComparisonOperator switchOperands(ComparisonOperator op) { - switch (op) { - case EQ: - return op; - case NE: - return op; - case LT: - return ComparisonOperator.GT; - case LE: - return ComparisonOperator.GE; - case GT: - return ComparisonOperator.LT; - case GE: - return ComparisonOperator.LE; - default: - throw new IllegalArgumentException("Unsupported ComparisonOperator " + op + "!"); + if (op.equals(ComparisonOperators.EQ)) { + return op; + } else if (op.equals(ComparisonOperators.NE)) { + return op; + } else if (op.equals(ComparisonOperators.LT)) { + return ComparisonOperators.GT; + } else if (op.equals(ComparisonOperators.LE)) { + return ComparisonOperators.GE; + } else if (op.equals(ComparisonOperators.GT)) { + return ComparisonOperators.LT; + } else if (op.equals(ComparisonOperators.GE)) { + return ComparisonOperators.LE; + } else { + throw new IllegalArgumentException("Unsupported ComparisonOperator " + op + "!"); } } - } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateOperatorNormalization.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateOperatorNormalization.java new file mode 100644 index 000000000..6f5cc37de --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateOperatorNormalization.java @@ -0,0 +1,121 @@ +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.atoms.ComparisonAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticOperator; +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.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; + +/** + * Transforms an {@link InputProgram} such that, for all aggregate (body-)literals, only the comparison operators "=" + * and "<=" are used. + * + * Rewriting of "#count" and "#sum" aggregates is done using the following equivalences: + *

      + *
    • X < #aggr{...} == XP <= #aggr{...}, XP = X + 1
    • + *
    • X != #aggr{...} == not X = #aggr{...}
    • + *
    • X > #aggr{...} == not X <= #aggr{...}
    • + *
    • X >= #aggr{...} == not XP <= #aggr{...}, XP = X + 1
    • + *
    • not X < #aggr{...} == not XP <= #aggr{...}, XP = X + 1
    • + *
    • not X != #aggr{...} == X = #aggr{...}
    • + *
    • not X > #aggr{...} == X <= #aggr{...}
    • + *
    • not X >= #aggr{...} == XP <= #aggr{...}, XP = X + 1
    • + *
    + * Operators for "#min" and "#max" aggregates are not rewritten. + * + * Note that input programs must only contain aggregate literals of form VAR OP #aggr{...}, i.e. with only + * a left term and operator. When preprocessing programs, apply this transformation AFTER + * {@link at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateLiteralSplitting}. + * + * Copyright (c) 2020-2021, the Alpha Team. + */ +public final class AggregateOperatorNormalization { + + private AggregateOperatorNormalization() { + throw new UnsupportedOperationException("Utility class - cannot instantiate!"); + } + + public static Rule normalize(Rule rule) { + List rewrittenBody = new ArrayList<>(); + for (Literal lit : rule.getBody()) { + rewrittenBody.addAll(rewriteLiteral(lit)); + } + return new BasicRule(rule.getHead(), rewrittenBody); + } + + private static List rewriteLiteral(Literal lit) { + if (lit instanceof AggregateLiteral) { + return rewriteAggregateOperator((AggregateLiteral) lit); + } else { + return Collections.singletonList(lit); + } + } + + private static List rewriteAggregateOperator(AggregateLiteral lit) { + AggregateAtom atom = lit.getAtom(); + if (lit.getAtom().getAggregateFunction() == AggregateFunctionSymbol.MIN || lit.getAtom().getAggregateFunction() == AggregateFunctionSymbol.MAX) { + // No operator normalization needed for #min/#max aggregates. + return Collections.singletonList(lit); + } + if (atom.getLowerBoundOperator().equals(ComparisonOperators.EQ) || atom.getLowerBoundOperator().equals(ComparisonOperators.LE)) { + // Nothing to do for operator "=" or "<=". + return Collections.singletonList(lit); + } else { + List retVal = new ArrayList<>(); + VariableTerm decrementedBound; + ComparisonOperator lowerBoundOp = atom.getLowerBoundOperator(); + if (lowerBoundOp.equals(ComparisonOperators.LT)) { + decrementedBound = Terms.newAnonymousVariable(); + retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.LE, decrementedBound, atom, !lit.isNegated())); + retVal.add(createPlusOneTerm(atom.getLowerBoundTerm(), decrementedBound)); + } else if (lowerBoundOp.equals(ComparisonOperators.NE)) { + retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.EQ, atom.getLowerBoundTerm(), atom, lit.isNegated())); + } else if (lowerBoundOp.equals(ComparisonOperators.GT)) { + retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.LE, atom.getLowerBoundTerm(), atom, lit.isNegated())); + } else if (lowerBoundOp.equals(ComparisonOperators.GE)) { + decrementedBound = Terms.newAnonymousVariable(); + retVal.add(createLowerBoundedAggregateLiteral(ComparisonOperators.LE, decrementedBound, atom, lit.isNegated())); + retVal.add(createPlusOneTerm(atom.getLowerBoundTerm(), decrementedBound)); + } else { + throw new IllegalStateException("No operator rewriting logic available for literal: " + lit); + } + return retVal; + } + } + + private static AggregateLiteral createLowerBoundedAggregateLiteral(ComparisonOperator op, Term lowerBoundTerm, AggregateAtom aggregateAtom, + boolean isNegated) { + return Literals.fromAtom(Atoms.newAggregateAtom(op, lowerBoundTerm, aggregateAtom.getAggregateFunction(), + aggregateAtom.getAggregateElements()), isNegated); + } + + /** + * Creates a new {@link Literal} that assigns the given target variable to the given (integer) term plus one. + * + * @param term + * @param targetVariable + * @return + */ + private static Literal createPlusOneTerm(Term term, VariableTerm targetVariable) { + Term increment = Terms.newArithmeticTerm(term, ArithmeticOperator.PLUS, Terms.newConstant(1)); + ComparisonAtom atom = Atoms.newComparisonAtom(targetVariable, increment, ComparisonOperators.EQ); + return atom.toLiteral(); + } + +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewriting.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewriting.java similarity index 71% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewriting.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewriting.java index 923c035d4..a810ee3db 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewriting.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewriting.java @@ -1,32 +1,36 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; - -import org.apache.commons.lang3.tuple.ImmutablePair; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.grounder.transformation.ProgramTransformation; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingContext.AggregateInfo; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders.AbstractAggregateEncoder; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders.CountEncoder; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders.MinMaxEncoder; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders.SumEncoder; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.ProgramTransformation; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders.AbstractAggregateEncoder; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders.CountEncoder; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders.MinMaxEncoder; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders.SumEncoder; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; /** * Rewrites {@link AggregateLiteral}s in programs to semantically equivalent, aggregate-free sub-programs. * * Copyright (c) 2020, the Alpha Team. */ -public class AggregateRewriting extends ProgramTransformation { +public class AggregateRewriting extends ProgramTransformation { private final AbstractAggregateEncoder countEqualsEncoder; private final AbstractAggregateEncoder countLessOrEqualEncoder; @@ -67,14 +71,14 @@ public AggregateRewriting(boolean useSortingCircuit, boolean supportNegativeInte * deriving the result literal is added that is semantically equivalent to the replaced aggregate literal. */ @Override - public InputProgram apply(InputProgram inputProgram) { + public ASPCore2Program apply(ASPCore2Program inputProgram) { AggregateRewritingContext ctx = new AggregateRewritingContext(); - List outputRules = new ArrayList<>(); - for (BasicRule inputRule : inputProgram.getRules()) { + List> outputRules = new ArrayList<>(); + for (Rule inputRule : inputProgram.getRules()) { // Split literals with two operators. - for (BasicRule splitRule : AggregateLiteralSplitting.split(inputRule)) { + for (Rule splitRule : AggregateLiteralSplitting.split(inputRule)) { // Normalize operators on aggregate literals after splitting. - BasicRule operatorNormalizedRule = AggregateOperatorNormalization.normalize(splitRule); + Rule operatorNormalizedRule = AggregateOperatorNormalization.normalize(splitRule); boolean hasAggregate = ctx.registerRule(operatorNormalizedRule); // Only keep rules without aggregates. The ones with aggregates are registered in the context and taken care of later. if (!hasAggregate) { @@ -99,9 +103,9 @@ public InputProgram apply(InputProgram inputProgram) { private AbstractAggregateEncoder getEncoderForAggregateFunction(AggregateFunctionSymbol function, ComparisonOperator operator) { switch (function) { case COUNT: - if (operator == ComparisonOperator.EQ) { + if (operator.equals(ComparisonOperators.EQ)) { return countEqualsEncoder; - } else if (operator == ComparisonOperator.LE) { + } else if (operator.equals(ComparisonOperators.LE)) { return countLessOrEqualEncoder; } else { throw new UnsupportedOperationException("No fitting encoder for aggregate function " + function + "and operator " + operator + "!"); @@ -111,9 +115,9 @@ private AbstractAggregateEncoder getEncoderForAggregateFunction(AggregateFunctio case MAX: return maxEncoder; case SUM: - if (operator == ComparisonOperator.EQ) { + if (operator.equals(ComparisonOperators.EQ)) { return sumEqualsEncoder; - } else if (operator == ComparisonOperator.LE) { + } else if (operator.equals(ComparisonOperators.LE)) { return sumLessOrEqualEncoder; } else { throw new UnsupportedOperationException("No fitting encoder for aggregate function " + function + "and operator " + operator + "!"); @@ -130,14 +134,14 @@ private AbstractAggregateEncoder getEncoderForAggregateFunction(AggregateFunctio * @param ctx the {@link AggregateRewritingContext} containing information about all aggregates. * @return for each rule, its rewritten version where aggregates are replaced with output atoms of the encoding. */ - private static List rewriteRulesWithAggregates(AggregateRewritingContext ctx) { - List rewrittenRules = new ArrayList<>(); - for (BasicRule rule : ctx.getRulesWithAggregates()) { + private static List> rewriteRulesWithAggregates(AggregateRewritingContext ctx) { + List> rewrittenRules = new ArrayList<>(); + for (Rule rule : ctx.getRulesWithAggregates()) { List rewrittenBody = new ArrayList<>(); for (Literal lit : rule.getBody()) { if (lit instanceof AggregateLiteral) { AggregateInfo aggregateInfo = ctx.getAggregateInfo((AggregateLiteral) lit); - rewrittenBody.add(new BasicLiteral(aggregateInfo.getOutputAtom(), !lit.isNegated())); + rewrittenBody.add(Literals.fromAtom(aggregateInfo.getOutputAtom(), !lit.isNegated())); } else { rewrittenBody.add(lit); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingContext.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingContext.java similarity index 79% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingContext.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingContext.java index 603b5a484..fa704b3ab 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingContext.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingContext.java @@ -1,9 +1,6 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; -import static at.ac.tuwien.kr.alpha.Util.oops; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.stringtemplate.v4.ST; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; import java.util.ArrayList; import java.util.Collections; @@ -14,19 +11,23 @@ import java.util.Map; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.stringtemplate.v4.ST; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; /** * Holds all information about aggregate literals that need to be rewritten within a program. @@ -44,7 +45,7 @@ public final class AggregateRewritingContext { private int idCounter; private Map aggregateInfos = new HashMap<>(); // Maps aggregate literals to their respective AggregateInfo. private Map, Set> aggregateFunctionsToRewrite = new LinkedHashMap<>(); - private List rulesWithAggregates = new ArrayList<>(); + private List> rulesWithAggregates = new ArrayList<>(); public AggregateRewritingContext() { idCounter = 0; @@ -58,7 +59,7 @@ public AggregateRewritingContext() { * @param rule * @return true if the given rule contains one or more aggregate literals, false otherwise */ - public boolean registerRule(BasicRule rule) { + public boolean registerRule(Rule rule) { AggregateRewritingRuleAnalysis ruleAnalysis = AggregateRewritingRuleAnalysis.analyzeRuleDependencies(rule); if (ruleAnalysis.aggregatesInRule.isEmpty()) { // Rule has no aggregates. @@ -86,21 +87,21 @@ public boolean registerRule(BasicRule rule) { private void registerAggregateLiteral(AggregateLiteral lit, Set globalVariables) { AggregateAtom atom = lit.getAtom(); - String id = atom.getAggregatefunction().toString().toLowerCase() + "_" + (++idCounter); + String id = atom.getAggregateFunction().toString().toLowerCase() + "_" + (++idCounter); AggregateInfo info = new AggregateInfo(id, lit, globalVariables); if (aggregateInfos.containsKey(lit)) { throw oops("AggregateInfo for AggregateLiteral already existing."); } aggregateInfos.put(lit, info); - aggregateFunctionsToRewrite.putIfAbsent(new ImmutablePair<>(atom.getAggregatefunction(), atom.getLowerBoundOperator()), new LinkedHashSet<>()); - aggregateFunctionsToRewrite.get(new ImmutablePair<>(atom.getAggregatefunction(), atom.getLowerBoundOperator())).add(info); + aggregateFunctionsToRewrite.putIfAbsent(new ImmutablePair<>(atom.getAggregateFunction(), atom.getLowerBoundOperator()), new LinkedHashSet<>()); + aggregateFunctionsToRewrite.get(new ImmutablePair<>(atom.getAggregateFunction(), atom.getLowerBoundOperator())).add(info); } AggregateInfo getAggregateInfo(AggregateLiteral aggregateLiteral) { return aggregateInfos.get(aggregateLiteral); } - List getRulesWithAggregates() { + List> getRulesWithAggregates() { return rulesWithAggregates; } @@ -133,9 +134,9 @@ public static class AggregateInfo { private Term buildArguments() { Term argumentTerm; if (globalVariables.isEmpty()) { - argumentTerm = ConstantTerm.getSymbolicInstance(new ST(AGGREGATE_ARGS_NOARGS_CONST).add("id", id).render()); + argumentTerm = Terms.newSymbolicConstant(new ST(AGGREGATE_ARGS_NOARGS_CONST).add("id", id).render()); } else { - argumentTerm = FunctionTerm.getInstance(new ST(AGGREGATE_ARGS_FUNCTION_SYMBOL).add("id", id).render(), + argumentTerm = Terms.newFunctionTerm(new ST(AGGREGATE_ARGS_FUNCTION_SYMBOL).add("id", id).render(), new ArrayList<>(globalVariables)); } return argumentTerm; @@ -155,7 +156,7 @@ private BasicAtom buildOutputAtom() { String outputPredicateName = new ST(AGGREGATE_RESULT_TEMPLATE).add("id", id).render(); Term argumentTerm = aggregateArguments; Term resultTerm = literal.getAtom().getLowerBoundTerm(); - return new BasicAtom(Predicate.getInstance(outputPredicateName, 2, true), argumentTerm, resultTerm); + return Atoms.newBasicAtom(Predicates.getPredicate(outputPredicateName, 2, true), argumentTerm, resultTerm); } private void addDependency(Literal dependency) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingRuleAnalysis.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingRuleAnalysis.java similarity index 86% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingRuleAnalysis.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingRuleAnalysis.java index e10973500..fd97d61be 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingRuleAnalysis.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingRuleAnalysis.java @@ -1,13 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; - -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import org.apache.commons.collections4.SetUtils; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import java.util.ArrayList; import java.util.Collections; @@ -17,6 +8,17 @@ import java.util.Map; import java.util.Set; +import org.apache.commons.collections4.SetUtils; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; + /** * Analyses a rule and records occurring aggregates and for each aggregate its global variables and its dependencies on * other literals. @@ -25,21 +27,22 @@ */ // Should be private, but needs to be visible to tests. class AggregateRewritingRuleAnalysis { - private final BasicRule rule; + private final Rule rule; final Map> globalVariablesPerAggregate = new LinkedHashMap<>(); final Map> dependenciesPerAggregate = new LinkedHashMap<>(); final List aggregatesInRule = new ArrayList<>(); - private AggregateRewritingRuleAnalysis(BasicRule rule) { + private AggregateRewritingRuleAnalysis(Rule rule) { this.rule = rule; } /** * Analyze the given rule and record its global variables and dependencies. + * * @param rule * @return */ - static AggregateRewritingRuleAnalysis analyzeRuleDependencies(BasicRule rule) { + static AggregateRewritingRuleAnalysis analyzeRuleDependencies(Rule rule) { AggregateRewritingRuleAnalysis ruleAnalysis = new AggregateRewritingRuleAnalysis(rule); ruleAnalysis.findGlobalVariablesPerAggregate(); ruleAnalysis.analyzeRuleDependencies(); @@ -64,7 +67,6 @@ private void analyzeRuleDependencies() { } } - /** * Recursively looks for literals in searchScope that bind the variables in the set * varsToBind, i.e. any literal lit that has any variable var in question in its @@ -77,15 +79,15 @@ private void analyzeRuleDependencies() { // Note: This algorithm has potentially exponential time complexity. Tuning potential definitely exists, but // performance optimization seems non-trivial. private static void findBindingLiterals(Set varsToBind, Set varsBoundSoFar, Set foundSoFar, - Set searchScope, - Map> aggregatesWithGlobalVars) { + Set searchScope, + Map> aggregatesWithGlobalVars) { int newlyBoundVars = 0; Set furtherVarsToBind = new HashSet<>(); for (VariableTerm varToBind : varsToBind) { for (Literal lit : searchScope) { Set bindingVars = lit.getBindingVariables(); Set nonBindingVars = (lit instanceof AggregateLiteral) ? aggregatesWithGlobalVars.get((AggregateLiteral) lit) - : lit.getNonBindingVariables(); + : lit.getNonBindingVariables(); if (bindingVars.contains(varToBind)) { varsBoundSoFar.add(varToBind); foundSoFar.add(lit); @@ -115,7 +117,7 @@ private void findGlobalVariablesPerAggregate() { // inside aggregate elements. Set globalVariables = new HashSet<>(); if (!rule.isConstraint()) { - NormalHead head = (NormalHead)rule.getHead(); // Head must be normal at this point. + NormalHead head = (NormalHead) rule.getHead(); // Head must be normal at this point. globalVariables.addAll(head.getAtom().getOccurringVariables()); } for (Literal literal : rule.getBody()) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/AbstractAggregateEncoder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/AbstractAggregateEncoder.java similarity index 58% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/AbstractAggregateEncoder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/AbstractAggregateEncoder.java index 7ed1faced..1e257d30a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/AbstractAggregateEncoder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/AbstractAggregateEncoder.java @@ -1,26 +1,31 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders; - -import org.apache.commons.collections4.ListUtils; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders; import java.util.ArrayList; import java.util.List; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateElement; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; -import at.ac.tuwien.kr.alpha.grounder.transformation.PredicateInternalizer; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import org.apache.commons.collections4.ListUtils; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateElement; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.parser.InlineDirectivesImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.PredicateInternalizer; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; /** * Abstract base class for aggregate encoders. An aggregate encoder provides an encoding for a given aggregate literal, @@ -46,7 +51,7 @@ protected AbstractAggregateEncoder(AggregateFunctionSymbol aggregateFunctionToEn * @param aggregatesToEncode the aggregates to encode. * @return all rules encoding the given aggregates as an {@link InputProgram}. */ - public InputProgram encodeAggregateLiterals(Set aggregatesToEncode) { + public ASPCore2Program encodeAggregateLiterals(Set aggregatesToEncode) { InputProgram.Builder programBuilder = InputProgram.builder(); for (AggregateInfo aggregateInfo : aggregatesToEncode) { programBuilder.accumulate(encodeAggregateLiteral(aggregateInfo)); @@ -60,24 +65,24 @@ public InputProgram encodeAggregateLiterals(Set aggregatesToEncod * @param aggregateToEncode * @return */ - public InputProgram encodeAggregateLiteral(AggregateInfo aggregateToEncode) { + public ASPCore2Program encodeAggregateLiteral(AggregateInfo aggregateToEncode) { AggregateLiteral literalToEncode = aggregateToEncode.getLiteral(); - if (literalToEncode.getAtom().getAggregatefunction() != this.aggregateFunctionToEncode) { + if (literalToEncode.getAtom().getAggregateFunction() != this.aggregateFunctionToEncode) { throw new IllegalArgumentException( - "Encoder " + this.getClass().getSimpleName() + " cannot encode aggregate function " + literalToEncode.getAtom().getAggregatefunction()); + "Encoder " + this.getClass().getSimpleName() + " cannot encode aggregate function " + literalToEncode.getAtom().getAggregateFunction()); } if (!this.acceptedOperators.contains(literalToEncode.getAtom().getLowerBoundOperator())) { throw new IllegalArgumentException("Encoder " + this.getClass().getSimpleName() + " cannot encode aggregate function " - + literalToEncode.getAtom().getAggregatefunction() + " with operator " + literalToEncode.getAtom().getLowerBoundOperator()); + + literalToEncode.getAtom().getAggregateFunction() + " with operator " + literalToEncode.getAtom().getLowerBoundOperator()); } String aggregateId = aggregateToEncode.getId(); - InputProgram literalEncoding = PredicateInternalizer.makePrefixedPredicatesInternal(encodeAggregateResult(aggregateToEncode), aggregateId); - List elementEncodingRules = new ArrayList<>(); + ASPCore2Program literalEncoding = PredicateInternalizer.makePrefixedPredicatesInternal(encodeAggregateResult(aggregateToEncode), aggregateId); + List> elementEncodingRules = new ArrayList<>(); for (AggregateElement elementToEncode : literalToEncode.getAtom().getAggregateElements()) { - BasicRule elementRule = encodeAggregateElement(aggregateToEncode, elementToEncode); + Rule elementRule = encodeAggregateElement(aggregateToEncode, elementToEncode); elementEncodingRules.add(PredicateInternalizer.makePrefixedPredicatesInternal(elementRule, aggregateId)); } - return new InputProgram(ListUtils.union(literalEncoding.getRules(), elementEncodingRules), literalEncoding.getFacts(), new InlineDirectives()); + return new InputProgram(ListUtils.union(literalEncoding.getRules(), elementEncodingRules), literalEncoding.getFacts(), new InlineDirectivesImpl()); } /** @@ -88,17 +93,18 @@ public InputProgram encodeAggregateLiteral(AggregateInfo aggregateToEncode) { * @param aggregateToEncode * @return */ - protected abstract InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode); + protected abstract ASPCore2Program encodeAggregateResult(AggregateInfo aggregateToEncode); /** * Encodes individual aggregate elements. For each aggregate element, a rule is created that fires for each tuple matching the element. + * * @param aggregateInfo * @param element * @return */ - protected BasicRule encodeAggregateElement(AggregateInfo aggregateInfo, AggregateElement element) { - Atom headAtom = buildElementRuleHead(aggregateInfo.getId(), element, aggregateInfo.getAggregateArguments()); - return new BasicRule(new NormalHead(headAtom), + protected Rule encodeAggregateElement(AggregateInfo aggregateInfo, AggregateElement element) { + BasicAtom headAtom = buildElementRuleHead(aggregateInfo.getId(), element, aggregateInfo.getAggregateArguments()); + return new BasicRule(Heads.newNormalHead(headAtom), ListUtils.union(element.getElementLiterals(), new ArrayList<>(aggregateInfo.getDependencies()))); } @@ -113,10 +119,10 @@ protected BasicRule encodeAggregateElement(AggregateInfo aggregateInfo, Aggregat * @param aggregateArguments * @return */ - protected Atom buildElementRuleHead(String aggregateId, AggregateElement element, Term aggregateArguments) { - Predicate headPredicate = Predicate.getInstance(this.getElementTuplePredicateSymbol(aggregateId), 2); - FunctionTerm elementTuple = FunctionTerm.getInstance(ELEMENT_TUPLE_FUNCTION_SYMBOL, element.getElementTerms()); - return new BasicAtom(headPredicate, aggregateArguments, elementTuple); + protected BasicAtom buildElementRuleHead(String aggregateId, AggregateElement element, Term aggregateArguments) { + Predicate headPredicate = Predicates.getPredicate(this.getElementTuplePredicateSymbol(aggregateId), 2); + FunctionTerm elementTuple = Terms.newFunctionTerm(ELEMENT_TUPLE_FUNCTION_SYMBOL, element.getElementTerms()); + return Atoms.newBasicAtom(headPredicate, aggregateArguments, elementTuple); } protected String getElementTuplePredicateSymbol(String aggregateId) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/CountEncoder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/CountEncoder.java similarity index 63% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/CountEncoder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/CountEncoder.java index d1d6cd2f4..0789c0330 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/CountEncoder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/CountEncoder.java @@ -1,11 +1,12 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders; import org.stringtemplate.v4.ST; import org.stringtemplate.v4.STGroup; -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.util.Util; public final class CountEncoder extends StringtemplateBasedAggregateEncoder { @@ -21,11 +22,11 @@ private CountEncoder(ComparisonOperator acceptedOperator, ST encodingTemplate) { } public static CountEncoder buildCountLessOrEqualEncoder(boolean useSortingGrid) { - return new CountEncoder(ComparisonOperator.LE, useSortingGrid ? CNT_LE_SORTING_GRID_TEMPLATE : CNT_LE_COUNTING_GRID_TEMPLATE); + return new CountEncoder(ComparisonOperators.LE, useSortingGrid ? CNT_LE_SORTING_GRID_TEMPLATE : CNT_LE_COUNTING_GRID_TEMPLATE); } public static CountEncoder buildCountEqualsEncoder() { - return new CountEncoder(ComparisonOperator.EQ, CNT_EQ_TEMPLATE); + return new CountEncoder(ComparisonOperators.EQ, CNT_EQ_TEMPLATE); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/MinMaxEncoder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/MinMaxEncoder.java similarity index 61% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/MinMaxEncoder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/MinMaxEncoder.java index a992318a6..8e007f78b 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/MinMaxEncoder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/MinMaxEncoder.java @@ -1,29 +1,35 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders; - -import org.apache.commons.collections4.SetUtils; -import org.stringtemplate.v4.ST; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders; import java.util.ArrayList; import java.util.List; -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateElement; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import org.apache.commons.collections4.SetUtils; +import org.stringtemplate.v4.ST; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateElement; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; public class MinMaxEncoder extends AbstractAggregateEncoder { @@ -53,17 +59,17 @@ public class MinMaxEncoder extends AbstractAggregateEncoder { ); //@formatter:on - private final ProgramParser parser = new ProgramParser(); + private final ProgramParser parser = new ProgramParserImpl(); public MinMaxEncoder(AggregateFunctionSymbol func) { - super(func, SetUtils.hashSet(ComparisonOperator.values())); + super(func, SetUtils.hashSet(ComparisonOperators.operators())); if (!(func == AggregateFunctionSymbol.MAX || func == AggregateFunctionSymbol.MIN)) { throw new IllegalArgumentException("Encoder " + this.getClass().getSimpleName() + " can only encode min/max aggregates!"); } } @Override - protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { + protected ASPCore2Program encodeAggregateResult(AggregateInfo aggregateToEncode) { ST encodingTemplate = null; if (this.getAggregateFunctionToEncode() == AggregateFunctionSymbol.MAX) { encodingTemplate = new ST(MAX_LITERAL_ENCODING); @@ -79,10 +85,10 @@ protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { ComparisonOperator cmpOp = atom.getLowerBoundOperator(); encodingTemplate.add("id", id); encodingTemplate.add("aggregate_result", resultName); - if (cmpOp == ComparisonOperator.EQ) { + if (cmpOp.equals(ComparisonOperators.EQ)) { // Aggregate to encode binds a variable, use appropriate result rule. ST resultRuleTemplate = new ST(BINDING_LITERAL_RESULT_RULE); - resultRuleTemplate.add("agg_func", atom.getAggregatefunction().toString().toLowerCase()); + resultRuleTemplate.add("agg_func", atom.getAggregateFunction().toString().toLowerCase()); resultRuleTemplate.add("id", id); resultRuleTemplate.add("aggregate_result", resultName); return parser.parse(encodingTemplate.render() + resultRuleTemplate.render()); @@ -101,13 +107,13 @@ protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { * $id$_$agg_func$_element_tuple($args$, AGG_VAL), * $dependencies;separator=\", \"$." */ - NormalHead resultRuleHead = new NormalHead( - new BasicAtom(Predicate.getInstance(resultName, 2), aggregateToEncode.getAggregateArguments(), atom.getLowerBoundTerm())); + NormalHead resultRuleHead = Heads.newNormalHead( + Atoms.newBasicAtom(Predicates.getPredicate(resultName, 2), aggregateToEncode.getAggregateArguments(), atom.getLowerBoundTerm())); List resultRuleBody = new ArrayList<>(); - VariableTerm aggregateValue = VariableTerm.getInstance("_AGG_VAL"); - ComparisonLiteral aggregateValueComparison = new ComparisonLiteral(new ComparisonAtom(atom.getLowerBoundTerm(), aggregateValue, cmpOp), true); - Literal aggregateResult = new BasicAtom(Predicate.getInstance( - id + "_" + atom.getAggregatefunction().toString().toLowerCase() + "_element_tuple", 2), + VariableTerm aggregateValue = Terms.newVariable("_AGG_VAL"); + ComparisonLiteral aggregateValueComparison = Literals.fromAtom(Atoms.newComparisonAtom(atom.getLowerBoundTerm(), aggregateValue, cmpOp), true); + Literal aggregateResult = Atoms.newBasicAtom(Predicates.getPredicate( + id + "_" + atom.getAggregateFunction().toString().toLowerCase() + "_element_tuple", 2), aggregateToEncode.getAggregateArguments(), aggregateValue).toLiteral(); resultRuleBody.add(aggregateResult); resultRuleBody.add(aggregateValueComparison); @@ -121,10 +127,10 @@ protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { } @Override - protected Atom buildElementRuleHead(String aggregateId, AggregateElement element, Term aggregateArguments) { - Predicate headPredicate = Predicate.getInstance(this.getElementTuplePredicateSymbol(aggregateId), 2); + protected BasicAtom buildElementRuleHead(String aggregateId, AggregateElement element, Term aggregateArguments) { + Predicate headPredicate = Predicates.getPredicate(this.getElementTuplePredicateSymbol(aggregateId), 2); Term elementTerm = element.getElementTerms().get(0); - return new BasicAtom(headPredicate, aggregateArguments, elementTerm); + return Atoms.newBasicAtom(headPredicate, aggregateArguments, elementTerm); } } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/StringtemplateBasedAggregateEncoder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/StringtemplateBasedAggregateEncoder.java similarity index 57% rename from src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/StringtemplateBasedAggregateEncoder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/StringtemplateBasedAggregateEncoder.java index 561a3dc0a..ad8a9c932 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/StringtemplateBasedAggregateEncoder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/StringtemplateBasedAggregateEncoder.java @@ -1,22 +1,29 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders; + +import java.util.ArrayList; +import java.util.Collections; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.grounder.transformation.EnumerationRewriting; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingContext.AggregateInfo; import org.apache.commons.collections4.ListUtils; import org.stringtemplate.v4.ST; -import java.util.ArrayList; -import java.util.Collections; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.parser.InlineDirectivesImpl; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.EnumerationRewriting; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; /** * Abstract base class for aggregate encoders making use of stringtemplates in their rewriting workflow. @@ -30,16 +37,16 @@ */ public abstract class StringtemplateBasedAggregateEncoder extends AbstractAggregateEncoder { - private final ProgramParser parser = new ProgramParser(); + private final ProgramParser parser = new ProgramParserImpl(); private final ST encodingTemplate; private final boolean needsBoundRule; protected StringtemplateBasedAggregateEncoder(AggregateFunctionSymbol aggregateFunctionToEncode, ComparisonOperator acceptedOperator, ST encodingTemplate) { super(aggregateFunctionToEncode, Collections.singleton(acceptedOperator)); this.encodingTemplate = encodingTemplate; - if (acceptedOperator == ComparisonOperator.EQ) { + if (acceptedOperator.equals(ComparisonOperators.EQ)) { this.needsBoundRule = false; - } else if (acceptedOperator == ComparisonOperator.LE) { + } else if (acceptedOperator.equals(ComparisonOperators.LE)) { this.needsBoundRule = true; } else { throw new IllegalArgumentException("This encoder is incompatible with comparison operator: " + acceptedOperator); @@ -47,7 +54,7 @@ protected StringtemplateBasedAggregateEncoder(AggregateFunctionSymbol aggregateF } @Override - protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { + protected ASPCore2Program encodeAggregateResult(AggregateInfo aggregateToEncode) { String aggregateId = aggregateToEncode.getId(); /* @@ -55,7 +62,7 @@ protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { * The bound is (in case of encodings for "<=" comparisons) the value that should be tested for being a lower bound, or * else zero. */ - BasicRule boundRule = null; + Rule boundRule = null; if (this.needsBoundRule) { boundRule = this.buildBoundRule(aggregateToEncode); } else { @@ -75,27 +82,27 @@ protected InputProgram encodeAggregateResult(AggregateInfo aggregateToEncode) { String coreEncodingAsp = coreEncodingTemplate.render(); // Create the basic program - InputProgram coreEncoding = new EnumerationRewriting().apply(parser.parse(coreEncodingAsp)); + ASPCore2Program coreEncoding = new EnumerationRewriting().apply(parser.parse(coreEncodingAsp)); // Add the programatically created bound rule and return return new InputProgram(ListUtils.union(coreEncoding.getRules(), Collections.singletonList(boundRule)), coreEncoding.getFacts(), - new InlineDirectives()); + new InlineDirectivesImpl()); } private String getBoundPredicateName(String aggregateId) { return aggregateId + "_bound"; } - private BasicRule buildZeroBoundRule(AggregateInfo aggregateToEncode) { - BasicAtom bound = new BasicAtom(Predicate.getInstance(getBoundPredicateName(aggregateToEncode.getId()), 2), - aggregateToEncode.getAggregateArguments(), ConstantTerm.getInstance(0)); - return new BasicRule(new NormalHead(bound), new ArrayList<>(aggregateToEncode.getDependencies())); + private Rule buildZeroBoundRule(AggregateInfo aggregateToEncode) { + BasicAtom bound = Atoms.newBasicAtom(Predicates.getPredicate(getBoundPredicateName(aggregateToEncode.getId()), 2), + aggregateToEncode.getAggregateArguments(), Terms.newConstant(0)); + return new BasicRule(Heads.newNormalHead(bound), new ArrayList<>(aggregateToEncode.getDependencies())); } - private BasicRule buildBoundRule(AggregateInfo aggregateToEncode) { - BasicAtom bound = new BasicAtom(Predicate.getInstance(getBoundPredicateName(aggregateToEncode.getId()), 2), + private Rule buildBoundRule(AggregateInfo aggregateToEncode) { + BasicAtom bound = Atoms.newBasicAtom(Predicates.getPredicate(getBoundPredicateName(aggregateToEncode.getId()), 2), aggregateToEncode.getAggregateArguments(), aggregateToEncode.getLiteral().getAtom().getLowerBoundTerm()); - return new BasicRule(new NormalHead(bound), new ArrayList<>(aggregateToEncode.getDependencies())); + return new BasicRule(Heads.newNormalHead(bound), new ArrayList<>(aggregateToEncode.getDependencies())); } } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/SumEncoder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/SumEncoder.java new file mode 100644 index 000000000..0a12b8752 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/encoders/SumEncoder.java @@ -0,0 +1,59 @@ +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.encoders; + +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateElement; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; + +/** + * Aggregate encoder handling sum aggregates. + * + * Copyright (c) 2020, the Alpha Team. + */ +public final class SumEncoder extends StringtemplateBasedAggregateEncoder { + + private static final STGroup AGGREGATE_ENCODINGS = Util.loadStringTemplateGroup( + SumEncoder.class.getResource("/stringtemplates/aggregate-encodings.stg")); + + private static final ST SUM_LE_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_le"); + private static final ST SUM_EQ_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_eq"); + + private static final ST NON_NEG_ELEMENTS_SUM_LE_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_le_no_negative_elements"); + private static final ST NON_NEG_ELEMENTS_SUM_EQ_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_eq_no_negative_elements"); + + private SumEncoder(ComparisonOperator acceptedOperator, ST encodingTemplate) { + super(AggregateFunctionSymbol.SUM, acceptedOperator, encodingTemplate); + } + + public static SumEncoder buildSumLessOrEqualEncoder(boolean supportNegativeIntegers) { + return new SumEncoder(ComparisonOperators.LE, supportNegativeIntegers ? SUM_LE_TEMPLATE : NON_NEG_ELEMENTS_SUM_LE_TEMPLATE); + } + + public static SumEncoder buildSumEqualsEncoder(boolean supportNegativeIntegers) { + return new SumEncoder(ComparisonOperators.EQ, supportNegativeIntegers ? SUM_EQ_TEMPLATE : NON_NEG_ELEMENTS_SUM_EQ_TEMPLATE); + } + + /** + * In contrast to encoders for other aggregate functions, the "element tuple" atom for sum encodings is ternary - apart + * from the aggregate arguments and the variable tuple identifying the aggregated element, it also holds the value to + * add to the result sum as its third argument. + */ + @Override + protected BasicAtom buildElementRuleHead(String aggregateId, AggregateElement element, Term aggregateArguments) { + Predicate headPredicate = Predicates.getPredicate(this.getElementTuplePredicateSymbol(aggregateId), 3); + FunctionTerm elementTuple = Terms.newFunctionTerm(AbstractAggregateEncoder.ELEMENT_TUPLE_FUNCTION_SYMBOL, element.getElementTerms()); + return Atoms.newBasicAtom(headPredicate, aggregateArguments, elementTuple, element.getElementTerms().get(0)); + } + +} \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/AbstractRule.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/AbstractRule.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/AbstractRule.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/AbstractRule.java index cb1356d2e..50d78db70 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/AbstractRule.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/AbstractRule.java @@ -1,9 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.rule; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.head.Head; -import org.apache.commons.collections4.SetUtils; +package at.ac.tuwien.kr.alpha.core.rules; import java.util.Collections; import java.util.LinkedHashSet; @@ -11,6 +6,13 @@ import java.util.Objects; import java.util.Set; +import org.apache.commons.collections4.SetUtils; + +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.commons.util.Util; + /** * An abstract representation of a rule with a specific type of @{link Head} (type parameter H) * @@ -18,7 +20,7 @@ * * Copyright (c) 2017-2019, the Alpha Team. */ -public abstract class AbstractRule { +public abstract class AbstractRule implements Rule { private final H head; private final Set bodyLiteralsPositive; @@ -80,6 +82,7 @@ private boolean isSafe() { */ } + @Override public boolean isConstraint() { return head == null; } @@ -89,18 +92,22 @@ public String toString() { return Util.join((isConstraint() ? "" : head.toString() + " ") + ":- ", getBody(), "."); } + @Override public H getHead() { return head; } + @Override public Set getBody() { return SetUtils.union(this.bodyLiteralsPositive, this.bodyLiteralsNegative); } + @Override public Set getPositiveBody() { return this.bodyLiteralsPositive; } + @Override public Set getNegativeBody() { return this.bodyLiteralsNegative; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/BasicRule.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/BasicRule.java similarity index 70% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/BasicRule.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/BasicRule.java index edd2bd381..1a2cab45e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/BasicRule.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/BasicRule.java @@ -25,32 +25,24 @@ * 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.common.rule; +package at.ac.tuwien.kr.alpha.core.rules; -import java.util.ArrayList; import java.util.List; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.head.Head; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; /** - * Represents a non-ground rule or a constraint. A @{link BasicRule} has a general {@link Head}, meaning both choice - * heads and disjunctive heads are permissible. - * This implementation represents a rule after being parsed from a given ASP program, but before being transformed into - * a @{link NormalRule}. + * Represents a non-ground rule or a constraint. A {@link BasicRule} has a general {@link Head}, meaning both choice heads and disjunctive + * heads are permissible. + * This implementation represents a rule after being parsed from a given ASP program, but before being transformed into a + * {@link NormalRuleImpl}. */ -public class BasicRule extends AbstractRule { +public class BasicRule extends AbstractRule implements Rule { public BasicRule(Head head, List body) { super(head, body); } - public static BasicRule getInstance(Head head, Literal... body) { - List bodyLst = new ArrayList<>(); - for (Literal lit : body) { - bodyLst.add(lit); - } - return new BasicRule(head, bodyLst); - } - } diff --git a/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/CompiledRule.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/CompiledRule.java new file mode 100644 index 000000000..b15dfbc41 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/CompiledRule.java @@ -0,0 +1,20 @@ +package at.ac.tuwien.kr.alpha.core.rules; + +import java.util.List; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.rules.NormalRule; +import at.ac.tuwien.kr.alpha.core.grounder.RuleGroundingInfo; + +public interface CompiledRule extends NormalRule { + + int getRuleId(); + + List getOccurringPredicates(); + + RuleGroundingInfo getGroundingInfo(); + + CompiledRule renameVariables(String str); + + boolean isGround(); +} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/InternalRule.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/InternalRule.java similarity index 73% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/InternalRule.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/InternalRule.java index a6e21a6d3..9a72fca12 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/InternalRule.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/InternalRule.java @@ -25,28 +25,31 @@ * 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.common.rule; - -import com.google.common.annotations.VisibleForTesting; +package at.ac.tuwien.kr.alpha.core.rules; import java.util.ArrayList; import java.util.List; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.IntIdGenerator; -import at.ac.tuwien.kr.alpha.grounder.RuleGroundingOrders; -import at.ac.tuwien.kr.alpha.grounder.Unifier; +import com.google.common.annotations.VisibleForTesting; + +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.substitutions.Unifier; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.IntIdGenerator; +import at.ac.tuwien.kr.alpha.core.grounder.RuleGroundingInfoImpl; /** * Represents a normal rule or a constraint for the semi-naive grounder. * A normal rule has no head atom if it represents a constraint, otherwise it has one atom in its head. */ -public class InternalRule extends NormalRule { +public class InternalRule extends NormalRuleImpl implements CompiledRule { private static final IntIdGenerator ID_GENERATOR = new IntIdGenerator(); @@ -54,7 +57,7 @@ public class InternalRule extends NormalRule { private final List occurringPredicates; - private final RuleGroundingOrders groundingOrders; + private final RuleGroundingInfoImpl groundingOrders; public InternalRule(NormalHead head, List body) { super(head, body); @@ -80,7 +83,7 @@ public InternalRule(NormalHead head, List body) { // proper place to put it // this.checkSafety(); - this.groundingOrders = new RuleGroundingOrders(this); + this.groundingOrders = new RuleGroundingInfoImpl(this); this.groundingOrders.computeGroundingOrders(); } @@ -89,8 +92,8 @@ public static void resetIdGenerator() { InternalRule.ID_GENERATOR.resetGenerator(); } - public static InternalRule fromNormalRule(NormalRule rule) { - return new InternalRule(rule.isConstraint() ? null : new NormalHead(rule.getHeadAtom()), new ArrayList<>(rule.getBody())); + public static CompiledRule fromNormalRule(Rule rule) { + return new InternalRule(rule.isConstraint() ? null : Heads.newNormalHead(rule.getHead().getAtom()), new ArrayList<>(rule.getBody())); } /** @@ -100,9 +103,10 @@ public static InternalRule fromNormalRule(NormalRule rule) { * @param newVariablePostfix * @return */ + @Override public InternalRule renameVariables(String newVariablePostfix) { List occurringVariables = new ArrayList<>(); - Atom headAtom = this.getHeadAtom(); + BasicAtom headAtom = this.getHeadAtom(); occurringVariables.addAll(headAtom.getOccurringVariables()); for (Literal literal : this.getBody()) { occurringVariables.addAll(literal.getOccurringVariables()); @@ -110,28 +114,31 @@ public InternalRule renameVariables(String newVariablePostfix) { Unifier variableReplacement = new Unifier(); for (VariableTerm occurringVariable : occurringVariables) { final String newVariableName = occurringVariable.toString() + newVariablePostfix; - variableReplacement.put(occurringVariable, VariableTerm.getInstance(newVariableName)); + variableReplacement.put(occurringVariable, Terms.newVariable(newVariableName)); } - Atom renamedHeadAtom = headAtom.substitute(variableReplacement); + BasicAtom renamedHeadAtom = headAtom.substitute(variableReplacement); ArrayList renamedBody = new ArrayList<>(this.getBody().size()); for (Literal literal : this.getBody()) { renamedBody.add(literal.substitute(variableReplacement)); } - return new InternalRule(new NormalHead(renamedHeadAtom), renamedBody); + return new InternalRule(Heads.newNormalHead(renamedHeadAtom), renamedBody); } /** * Returns the predicates occurring in this rule. * @return a list of all predicates occurring in the rule (may contain duplicates and builtin atoms). */ + @Override public List getOccurringPredicates() { return this.occurringPredicates; } - public RuleGroundingOrders getGroundingOrders() { + @Override + public RuleGroundingInfoImpl getGroundingInfo() { return this.groundingOrders; } + @Override public int getRuleId() { return this.ruleId; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/NormalRule.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/NormalRuleImpl.java similarity index 51% rename from src/main/java/at/ac/tuwien/kr/alpha/common/rule/NormalRule.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/NormalRuleImpl.java index 7eac409eb..c75bdcbc9 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/NormalRule.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/rules/NormalRuleImpl.java @@ -1,34 +1,38 @@ -package at.ac.tuwien.kr.alpha.common.rule; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; +package at.ac.tuwien.kr.alpha.core.rules; import java.util.ArrayList; import java.util.List; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.NormalRule; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.rules.heads.NormalHead; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.util.Util; + /** * A rule that has a normal head, i.e. just one head atom, no disjunction or choice heads allowed. * Currently, any constructs such as aggregates, intervals, etc. in the rule body are allowed. * * Copyright (c) 2019, the Alpha Team. */ -public class NormalRule extends AbstractRule { +public class NormalRuleImpl extends AbstractRule implements NormalRule { - public NormalRule(NormalHead head, List body) { + public NormalRuleImpl(NormalHead head, List body) { super(head, body); } - public static NormalRule fromBasicRule(BasicRule rule) { - Atom headAtom = null; + public static NormalRuleImpl fromBasicRule(Rule rule) { + BasicAtom headAtom = null; if (!rule.isConstraint()) { if (!(rule.getHead() instanceof NormalHead)) { throw Util.oops("Trying to construct a NormalRule from rule with non-normal head! Head type is: " + rule.getHead().getClass().getSimpleName()); } headAtom = ((NormalHead) rule.getHead()).getAtom(); } - return new NormalRule(headAtom != null ? new NormalHead(headAtom) : null, new ArrayList<>(rule.getBody())); + return new NormalRuleImpl(headAtom != null ? Heads.newNormalHead(headAtom) : null, new ArrayList<>(rule.getBody())); } public boolean isGround() { @@ -43,7 +47,8 @@ public boolean isGround() { return true; } - public Atom getHeadAtom() { + @Override + public BasicAtom getHeadAtom() { return this.isConstraint() ? null : this.getHead().getAtom(); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/AbstractSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AbstractSolver.java similarity index 79% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/AbstractSolver.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AbstractSolver.java index 254d0ed05..9cbc497e5 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/AbstractSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AbstractSolver.java @@ -1,13 +1,14 @@ -package at.ac.tuwien.kr.alpha.solver; - -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.grounder.Grounder; +package at.ac.tuwien.kr.alpha.core.solver; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; + /** * Copyright (c) 2016, the Alpha Team. */ diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/Antecedent.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Antecedent.java similarity index 83% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/Antecedent.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Antecedent.java index c841ecc0e..e62b1aa3e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/Antecedent.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Antecedent.java @@ -1,7 +1,7 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; /** - * An interface to reasons of implications as used internally by the solver. This is a lightweight {@link at.ac.tuwien.kr.alpha.common.NoGood} that only + * An interface to reasons of implications as used internally by the solver. This is a lightweight {@link at.ac.tuwien.kr.alpha.core.common.NoGood} that only * provides an array of literals (in some order) and has an activity that may change. * * Copyright (c) 2019, the Alpha Team. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/AtomCounter.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java similarity index 81% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/AtomCounter.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java index c0f422695..753f04a8a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/AtomCounter.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounter.java @@ -23,9 +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.solver; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; +package at.ac.tuwien.kr.alpha.core.solver; import java.util.ArrayList; import java.util.Collections; @@ -33,24 +31,26 @@ import java.util.List; import java.util.Map; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; + /** - * Counts the number of ground atoms stored for each type (i.e., subclass of {@link Atom}. + * Counts the number of ground atoms stored for each type (i.e., subclass of {@link AbstractAtom}. * For every atom, only the counter for one class (the most specific one) is incremented, * not the counters for more general classes of which the atom is also an instance. */ public class AtomCounter { - private final Map, Integer> countByType = new HashMap<>(); + private final Map countByType = new HashMap<>(); public void add(Atom atom) { - countByType.compute(atom.getClass(), (k, v) -> (v == null) ? 1 : v + 1); + countByType.compute(atom.getClass().getSimpleName(), (k, v) -> (v == null) ? 1 : v + 1); } /** * @param type the class of atoms to count * @return the number of atoms of the given type */ - public int getNumberOfAtoms(Class type) { + public int getNumberOfAtoms(String type) { return countByType.getOrDefault(type, 0); } @@ -59,8 +59,8 @@ public int getNumberOfAtoms(Class type) { */ public String getStatsByType() { List statsList = new ArrayList<>(); - for (Map.Entry, Integer> entry : countByType.entrySet()) { - statsList.add(entry.getKey().getSimpleName() + ": " + entry.getValue()); + for (Map.Entry entry : countByType.entrySet()) { + statsList.add(entry.getKey() + ": " + entry.getValue()); } Collections.sort(statsList); return String.join(" ", statsList); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/Atoms.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Atoms.java similarity index 69% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/Atoms.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Atoms.java index de6f02a6a..9ba91dbfa 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/Atoms.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Atoms.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; public final class Atoms { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/BinaryNoGoodPropagationEstimation.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/BinaryNoGoodPropagationEstimation.java similarity index 65% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/BinaryNoGoodPropagationEstimation.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/BinaryNoGoodPropagationEstimation.java index 168f6daa8..53f8224ff 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/BinaryNoGoodPropagationEstimation.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/BinaryNoGoodPropagationEstimation.java @@ -23,10 +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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import java.util.Arrays; -import java.util.stream.Collectors; +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; /** * Offers methods to estimate the effect of propagating binary nogoods. @@ -37,42 +36,19 @@ public interface BinaryNoGoodPropagationEstimation { * Uses {@code strategy} to estimate the number of direct consequences of propagating binary nogoods after assigning * {@code truth} to {@code atom}. * - * If {@code strategy} is {@link Strategy#BinaryNoGoodPropagation}, {@code truth} is assigned to {@code atom}, + * If {@code strategy} is {@link BinaryNoGoodPropagationEstimationStrategy#BinaryNoGoodPropagation}, {@code truth} is assigned to {@code atom}, * only binary nogoods are propagated, a backtrack is executed, and the number of atoms that have been assigned * additionally during this process is returned. * - * If {@code strategy} is {@link Strategy#CountBinaryWatches}, on the other hand, the number of binary watches on + * If {@code strategy} is {@link BinaryNoGoodPropagationEstimationStrategy#CountBinaryWatches}, on the other hand, the number of binary watches on * the literal given by {@code atom} and {@code truth} is returned. * * @param atom the atom to estimate effects for * @param truth gives, together with {@code atom}, a literal to estimate effects for - * @param strategy the strategy to use for estimation. If {@link Strategy#BinaryNoGoodPropagation} is given but - * no binary nogoods exist, {@link Strategy#CountBinaryWatches} will be used instead. + * @param strategy the strategy to use for estimation. If {@link BinaryNoGoodPropagationEstimationStrategy#BinaryNoGoodPropagation} is given but + * no binary nogoods exist, {@link BinaryNoGoodPropagationEstimationStrategy#CountBinaryWatches} will be used instead. * @return an estimate on the effects of propagating binary nogoods after assigning {@code truth} to {@code atom}. */ - int estimate(int atom, boolean truth, Strategy strategy); - - /** - * Strategies to estimate the amount of influence of a literal. - */ - public enum Strategy { - /** - * Counts binary watches involving the literal under consideration - */ - CountBinaryWatches, - - /** - * Assigns true to the literal under consideration, then does propagation only on binary nogoods - * and counts how many other atoms are assigned during this process, then backtracks - */ - BinaryNoGoodPropagation; - - /** - * @return a comma-separated list of names of known heuristics - */ - public static String listAllowedValues() { - return Arrays.stream(values()).map(Strategy::toString).collect(Collectors.joining(", ")); - } - } + int estimate(int atom, boolean truth, BinaryNoGoodPropagationEstimationStrategy strategy); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/Checkable.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Checkable.java similarity index 88% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/Checkable.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Checkable.java index 369389d50..cb9040063 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/Checkable.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Checkable.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; /** * Marks classes that implement some "checking" logic that can perform diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/Choice.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Choice.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/Choice.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Choice.java index bdaa9e188..10b398dda 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/Choice.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/Choice.java @@ -25,10 +25,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.isPositive; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; class Choice { private final int atom; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/ChoiceInfluenceManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/ChoiceInfluenceManager.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java index 62624eecd..8ab9088d3 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/ChoiceInfluenceManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceInfluenceManager.java @@ -25,19 +25,23 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.arrayGrowthSize; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.MBT; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; - -import static at.ac.tuwien.kr.alpha.Util.arrayGrowthSize; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.MBT; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; - /** * Manages influence of atoms on the activity of certain other atoms. Can be used for either choice points or heuristic atoms. * diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/ChoiceManager.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java similarity index 97% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/ChoiceManager.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java index ab9d1e7d0..8d8edcbb3 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/ChoiceManager.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManager.java @@ -25,12 +25,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.NoGood; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +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; @@ -42,8 +40,11 @@ import java.util.Stack; import java.util.stream.Collectors; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; /** * This class provides functionality for choice point management, detection of active choice points, etc. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/ConflictCause.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ConflictCause.java similarity index 95% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/ConflictCause.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ConflictCause.java index b9b72ca58..a459b49fd 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/ConflictCause.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ConflictCause.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; /** * Indicates the presence of a conflict and contains its reason in terms of a violated Antecedent. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/DefaultSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/DefaultSolver.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java index ea3e6c1da..b6d952e23 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/DefaultSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/DefaultSolver.java @@ -25,30 +25,15 @@ * 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.solver; - -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.grounder.ProgramAnalyzingGrounder; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristic; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory; -import at.ac.tuwien.kr.alpha.solver.heuristics.ChainedBranchingHeuristics; -import at.ac.tuwien.kr.alpha.solver.heuristics.HeuristicsConfiguration; -import at.ac.tuwien.kr.alpha.solver.heuristics.NaiveHeuristic; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package at.ac.tuwien.kr.alpha.core.solver; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToNegatedLiteral; +import static at.ac.tuwien.kr.alpha.core.solver.NoGoodStore.LBD_NO_VALUE; +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; @@ -61,23 +46,38 @@ import java.util.Set; import java.util.function.Consumer; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToNegatedLiteral; -import static at.ac.tuwien.kr.alpha.solver.NoGoodStore.LBD_NO_VALUE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; -import static at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristic.DEFAULT_CHOICE_LITERAL; -import static at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult.UNSAT; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.StatisticsReportingSolver; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +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; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.ProgramAnalyzingGrounder; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.BranchingHeuristic; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.BranchingHeuristicFactory; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.ChainedBranchingHeuristics; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.HeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.NaiveHeuristic; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner; +import at.ac.tuwien.kr.alpha.core.util.Substitutions; /** - * The default solver employed in Alpha. - * The core algorithm is a DPLL-style loop employing conflict-driven learning and lazy-grounding of nogoods. + * The new default solver employed in Alpha. * * Copyright (c) 2016-2021, the Alpha Team. */ -public class DefaultSolver extends AbstractSolver implements SolverMaintainingStatistics { +public class DefaultSolver extends AbstractSolver implements StatisticsReportingSolver { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSolver.class); private final NoGoodStore store; @@ -380,9 +380,9 @@ private boolean treatConflictAfterClosing(Antecedent violatedNoGood) { // 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(); - InternalRule nonGroundRule = analyzingGrounder.getNonGroundRule(Integer.parseInt(ruleId)); + CompiledRule nonGroundRule = analyzingGrounder.getNonGroundRule(Integer.parseInt(ruleId)); String substitution = (String) ((ConstantTerm)atom.getTerms().get(1)).getObject(); - Substitution groundingSubstitution = Substitution.fromString(substitution); + Substitution groundingSubstitution = Substitutions.fromString(substitution); // 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); @@ -438,7 +438,7 @@ private boolean backtrack() { final Choice backtrackedChoice = choiceManager.backtrack(); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Backtracked choice atom is {}={}@{}.", backtrackedChoice.getAtom(), - backtrackedChoice.getTruthValue() ? TRUE : FALSE, previousDecisionLevel); + backtrackedChoice.getTruthValue() ? ThriceTruth.TRUE : ThriceTruth.FALSE, previousDecisionLevel); } // Construct inverse choice, if choice can be inverted. @@ -565,7 +565,6 @@ public int getNumberOfDeletedNoGoods() { return ((NoGoodStoreAlphaRoaming)store).getLearnedNoGoodDeletion().getNumberOfDeletedNoGoods(); } - @Override public NoGoodCounter getNoGoodCounter() { return store.getNoGoodCounter(); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/LearnedNoGoodDeletion.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/LearnedNoGoodDeletion.java similarity index 95% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/LearnedNoGoodDeletion.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/LearnedNoGoodDeletion.java index a17264654..f77211baa 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/LearnedNoGoodDeletion.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/LearnedNoGoodDeletion.java @@ -1,16 +1,17 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.Assignment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.kr.alpha.core.common.Assignment; + +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; + import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; - /** * Realizes a learned NoGood deletion strategy based on LBD and activity of NoGoods. * diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/NaiveNoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/NaiveNoGoodStore.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java index 28af2719c..7eb8bc6a2 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/NaiveNoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStore.java @@ -25,16 +25,17 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.NoGood; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.kr.alpha.core.common.NoGood; + import java.util.HashMap; -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.*; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.*; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.*; public class NaiveNoGoodStore implements NoGoodStore { private static final Logger LOGGER = LoggerFactory.getLogger(NaiveNoGoodStore.class); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/NaiveSolver.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveSolver.java similarity index 95% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/NaiveSolver.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveSolver.java index bd122ed8e..12507f071 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/NaiveSolver.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NaiveSolver.java @@ -25,22 +25,31 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; + +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isNegated; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; +import static java.lang.Math.abs; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.function.Consumer; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.IntIterator; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.grounder.Grounder; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; -import java.util.function.Consumer; - -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static java.lang.Math.abs; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.IntIterator; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; /** * Copyright (c) 2016-2020, the Alpha Team. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodCounter.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodCounter.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java index 432419ab1..3ff15e8e8 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodCounter.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodCounter.java @@ -23,15 +23,15 @@ * 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.solver; - -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface.Type; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface; +package at.ac.tuwien.kr.alpha.core.solver; import java.util.ArrayList; import java.util.List; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type; + /** * Maintains statistics on numbers of various types of {@link NoGood}s. */ diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodStore.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodStore.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java index 7cd516b40..ec70069c1 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodStore.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStore.java @@ -1,6 +1,6 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGood; /** * An interface defining the use of a NoGood store. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodStoreAlphaRoaming.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java similarity index 95% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodStoreAlphaRoaming.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java index e2f256c5d..8b4d1977e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/NoGoodStoreAlphaRoaming.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoaming.java @@ -25,32 +25,34 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface.Type; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import static at.ac.tuwien.kr.alpha.Util.arrayGrowthSize; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.common.Literals.isNegated; -import static at.ac.tuwien.kr.alpha.common.Literals.isPositive; -import static at.ac.tuwien.kr.alpha.common.Literals.literalToString; -import static at.ac.tuwien.kr.alpha.common.NoGood.HEAD; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.MBT; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; +import static at.ac.tuwien.kr.alpha.commons.util.Util.arrayGrowthSize; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isNegated; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.literalToString; +import static at.ac.tuwien.kr.alpha.core.common.NoGood.HEAD; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.MBT; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; /** * NoGoodStore using for each NoGood three watches, two ordinary ones and an alpha watch. @@ -72,9 +74,9 @@ public class NoGoodStoreAlphaRoaming implements NoGoodStore, BinaryNoGoodPropaga private final WritableAssignment assignment; private final LearnedNoGoodDeletion learnedNoGoodDeletion; - @SuppressWarnings("unchecked") + @SuppressWarnings(value = {"rawtypes", "unchecked"}) private ArrayList[] watches = new ArrayList[0]; - @SuppressWarnings("unchecked") + @SuppressWarnings(value = {"rawtypes", "unchecked"}) private ArrayList[] watchesAlpha = new ArrayList[0]; private BinaryWatchList[] binaryWatches = new BinaryWatchList[0]; private int maxAtomId; @@ -95,7 +97,7 @@ public NoGoodStoreAlphaRoaming(WritableAssignment assignment) { this(assignment, false); } - @SuppressWarnings("unchecked") + @SuppressWarnings(value = {"rawtypes", "unchecked"}) void clear() { assignment.clear(); learnedNoGoodDeletion.reset(); @@ -210,6 +212,7 @@ public ConflictCause add(int id, NoGood noGood, int lbd) { return conflictCause; } + @Override public ConflictCause add(int id, NoGood noGood) { return add(id, noGood, -1); } @@ -816,16 +819,11 @@ private void clearAlphaWatchList(int literal) { } @Override - public int estimate(int atom, boolean truth, Strategy strategy) { - switch (strategy) { - case BinaryNoGoodPropagation: - if (hasBinaryNoGoods) { - return estimateEffectsOfBinaryNoGoodPropagation(atom, truth) - 1; - } - case CountBinaryWatches: - default: - return getNumberOfBinaryWatches(atom, truth); + public int estimate(int atom, boolean truth, BinaryNoGoodPropagationEstimationStrategy strategy) { + if (BinaryNoGoodPropagationEstimationStrategy.BinaryNoGoodPropagation.equals(strategy)) { + return estimateEffectsOfBinaryNoGoodPropagation(atom, truth) - 1; } + return getNumberOfBinaryWatches(atom, truth); } private int getNumberOfBinaryWatches(int atom, boolean truth) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/PerformanceLog.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java similarity index 98% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/PerformanceLog.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.java index a653b8021..d9153e729 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/PerformanceLog.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/PerformanceLog.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.solver; +package at.ac.tuwien.kr.alpha.core.solver; import org.slf4j.Logger; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/ShallowAntecedent.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ShallowAntecedent.java similarity index 88% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/ShallowAntecedent.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ShallowAntecedent.java index 54be1ceca..5aac8d900 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/ShallowAntecedent.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ShallowAntecedent.java @@ -1,6 +1,6 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.Util.oops; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; /** * Represents a shallow {@link Antecedent} that must be instantiated before use. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/SolverFactory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/SolverFactory.java similarity index 88% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/SolverFactory.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/SolverFactory.java index 414d30c31..e6af12d0a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/SolverFactory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/SolverFactory.java @@ -25,13 +25,14 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.solver.heuristics.HeuristicsConfiguration; -import at.ac.tuwien.kr.alpha.solver.heuristics.HeuristicsConfigurationBuilder; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.HeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.HeuristicsConfigurationBuilder; import java.util.Random; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/ThriceTruth.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ThriceTruth.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/ThriceTruth.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ThriceTruth.java index ade2ccb9c..929d93ec0 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/ThriceTruth.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/ThriceTruth.java @@ -25,9 +25,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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.Truth; +import at.ac.tuwien.kr.alpha.core.common.Truth; public enum ThriceTruth implements Truth { TRUE("T", true), diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/TrailAssignment.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/TrailAssignment.java similarity index 95% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/TrailAssignment.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/TrailAssignment.java index 12cb759ae..9194925d8 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/TrailAssignment.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/TrailAssignment.java @@ -25,22 +25,31 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.arrayGrowthSize; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; +import static at.ac.tuwien.kr.alpha.core.solver.Atoms.isAtom; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.MBT; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.IntIterator; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; - -import static at.ac.tuwien.kr.alpha.Util.arrayGrowthSize; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static at.ac.tuwien.kr.alpha.solver.Atoms.isAtom; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.*; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.IntIterator; /** * An implementation of Assignment using a trail (of literals) and arrays as underlying structures for storing diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/WatchedNoGood.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/WatchedNoGood.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/WatchedNoGood.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/WatchedNoGood.java index 4395d9ed5..50fde0e88 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/WatchedNoGood.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/WatchedNoGood.java @@ -25,15 +25,15 @@ * 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.solver; - -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface; +package at.ac.tuwien.kr.alpha.core.solver; import java.util.Iterator; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.literalToString; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.literalToString; public final class WatchedNoGood implements NoGoodInterface, Antecedent { private int activity; @@ -151,10 +151,12 @@ public Iterator iterator() { return new Iterator() { private int i; + @Override public boolean hasNext() { return literals.length > i; } + @Override public Integer next() { return literals[i++]; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/WritableAssignment.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/WritableAssignment.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/WritableAssignment.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/WritableAssignment.java index 125ee17fb..6ee85f3f7 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/WritableAssignment.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/WritableAssignment.java @@ -25,13 +25,13 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.NoGood; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.isPositive; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; public interface WritableAssignment extends Assignment { /** diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ActivityBasedBranchingHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ActivityBasedBranchingHeuristic.java similarity index 97% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ActivityBasedBranchingHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ActivityBasedBranchingHeuristic.java index dd17bb114..161f03bc4 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ActivityBasedBranchingHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ActivityBasedBranchingHeuristic.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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; /** * A heuristic that selects an atom to choose on by maintaining activity values for literals. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaActiveRuleHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaActiveRuleHeuristic.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaActiveRuleHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaActiveRuleHeuristic.java index b2b76ba26..f42aa1ee9 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaActiveRuleHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaActiveRuleHeuristic.java @@ -23,15 +23,15 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; -import java.util.Random; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; +import java.util.Random; /** * A variant of {@link DependencyDrivenHeuristic} that counts the activity of non-body-representing atoms towards bodies of rules in which they occur. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaHeadMustBeTrueHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaHeadMustBeTrueHeuristic.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaHeadMustBeTrueHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaHeadMustBeTrueHeuristic.java index 52df83cd4..b14bc9d1e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaHeadMustBeTrueHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaHeadMustBeTrueHeuristic.java @@ -23,12 +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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; import java.util.Comparator; import java.util.Optional; @@ -38,7 +38,7 @@ /** * A variant of {@link DependencyDrivenHeuristic} that prefers to choose atoms representing bodies of rules whose heads - * are assigned {@link at.ac.tuwien.kr.alpha.solver.ThriceTruth#MBT}. + * are assigned {@link at.ac.tuwien.kr.alpha.core.solver.ThriceTruth#MBT}. */ public class AlphaHeadMustBeTrueHeuristic extends DependencyDrivenHeuristic { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaRandomSignHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaRandomSignHeuristic.java similarity index 85% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaRandomSignHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaRandomSignHeuristic.java index f14a96b17..4e2cbc238 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaRandomSignHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaRandomSignHeuristic.java @@ -23,16 +23,16 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; -import java.util.Random; +import static at.ac.tuwien.kr.alpha.core.solver.Atoms.isAtom; -import static at.ac.tuwien.kr.alpha.solver.Atoms.isAtom; +import java.util.Random; public class AlphaRandomSignHeuristic extends DependencyDrivenHeuristic { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMin.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java similarity index 92% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMin.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java index 48e523932..0581e6cca 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMin.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMin.java @@ -23,24 +23,25 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; + +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; import java.util.stream.Stream; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; /** * The BerkMin heuristic, as described in (but adapted for lazy grounding): diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMinLiteral.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMinLiteral.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java index b916b1b7c..b523480bf 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMinLiteral.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinLiteral.java @@ -25,18 +25,18 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; + +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; import java.util.Deque; import java.util.LinkedList; import java.util.Random; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; - /** * A BerkMin-like heuristics that uses activity of literals and a fixed-size queue instead of a stack of NoGoods. * Copyright (c) 2017-2018, the Alpha Team. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java index 78be2e6de..2e0bb219d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristic.java @@ -23,14 +23,14 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner; -import java.util.Collection; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; +import java.util.Collection; /** * A heuristic that selects an atom to choose on. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristicFactory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristicFactory.java similarity index 78% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristicFactory.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristicFactory.java index e84f9b0a1..29f995071 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristicFactory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristicFactory.java @@ -23,67 +23,17 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; - -import java.util.Arrays; import java.util.List; import java.util.Random; -import java.util.stream.Collectors; - -public final class BranchingHeuristicFactory { - /** - * The available domain-independent heuristics. - * Some are deprecated because they perform poorly and have not been improved for some time, - * however the code is kept for now so that it stays compatible when interfaces are refactored. - */ - public enum Heuristic { - NAIVE, - BERKMIN, - BERKMINLITERAL, - @Deprecated - DD, - @Deprecated - DD_SUM, - @Deprecated - DD_AVG, - @Deprecated - DD_MAX, - @Deprecated - DD_MIN, - @Deprecated - DD_PYRO, - @Deprecated - GDD, - @Deprecated - GDD_SUM, - @Deprecated - GDD_AVG, - @Deprecated - GDD_MAX, - @Deprecated - GDD_MIN, - @Deprecated - GDD_PYRO, - @Deprecated - ALPHA_ACTIVE_RULE, - @Deprecated - ALPHA_HEAD_MBT, - VSIDS, - GDD_VSIDS; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; - /** - * @return a comma-separated list of names of known heuristics - */ - public static String listAllowedValues() { - return Arrays.stream(values()).map(Heuristic::toString).collect(Collectors.joining(", ")); - } - } +public final class BranchingHeuristicFactory { public static BranchingHeuristic getInstance(HeuristicsConfiguration heuristicsConfiguration, Grounder grounder, WritableAssignment assignment, ChoiceManager choiceManager, Random random) { BranchingHeuristic heuristicWithoutReplay = getInstanceWithoutReplay(heuristicsConfiguration, grounder, assignment, choiceManager, random); diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ChainedBranchingHeuristics.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ChainedBranchingHeuristics.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java index 6d6eb8761..729386635 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ChainedBranchingHeuristics.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ChainedBranchingHeuristics.java @@ -23,14 +23,14 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; -import java.util.*; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; -import static at.ac.tuwien.kr.alpha.Util.oops; +import java.util.*; /** * A "chained" list of branching heuristics in which the entry at position n+1 is used as a fallback if the entry at position n cannot make a decision. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenHeuristic.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenHeuristic.java index e24f29da0..7d594fbcf 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenHeuristic.java @@ -23,17 +23,18 @@ * 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.solver.heuristics; - -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProvider; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; + +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProvider; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; + import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.HashSetValuedHashMap; import org.slf4j.Logger; @@ -43,9 +44,9 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.*; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; /** * The BerkMin variants {@link BerkMin} and {@link BerkMinLiteral} suffer from the fact that choice points diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenPyroHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenPyroHeuristic.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenPyroHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenPyroHeuristic.java index 181a2299b..ce73f0d6d 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenPyroHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenPyroHeuristic.java @@ -23,11 +23,11 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; import java.util.Random; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenVSIDS.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenVSIDS.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenVSIDS.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenVSIDS.java index e579d2871..1487116a1 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/DependencyDrivenVSIDS.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/DependencyDrivenVSIDS.java @@ -23,11 +23,11 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; import java.util.Random; @@ -46,11 +46,11 @@ */ public class DependencyDrivenVSIDS extends VSIDS { - public DependencyDrivenVSIDS(Assignment assignment, ChoiceManager choiceManager, int decayPeriod, double decayFactor, Random random, BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public DependencyDrivenVSIDS(Assignment assignment, ChoiceManager choiceManager, int decayPeriod, double decayFactor, Random random, BinaryNoGoodPropagationEstimationStrategy momsStrategy) { super(assignment, choiceManager, new HeapOfActiveChoicePoints(decayPeriod, decayFactor, choiceManager), momsStrategy); } - public DependencyDrivenVSIDS(Assignment assignment, ChoiceManager choiceManager, Random random, BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public DependencyDrivenVSIDS(Assignment assignment, ChoiceManager choiceManager, Random random, BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this(assignment, choiceManager, DEFAULT_DECAY_PERIOD, DEFAULT_DECAY_FACTOR, random, momsStrategy); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/GeneralizedDependencyDrivenHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/GeneralizedDependencyDrivenHeuristic.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/GeneralizedDependencyDrivenHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/GeneralizedDependencyDrivenHeuristic.java index 3b6defcf1..9243c3589 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/GeneralizedDependencyDrivenHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/GeneralizedDependencyDrivenHeuristic.java @@ -23,19 +23,19 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; + +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; import java.util.HashSet; import java.util.Random; import java.util.Set; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; - /** * {@link DependencyDrivenHeuristic} needs to know a lot about the structure of nogoods, i.e. the role their members play in rules. * However, the solving component of Alpha usually deals only with nogoods and cannot naturally access this information. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/GeneralizedDependencyDrivenPyroHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/GeneralizedDependencyDrivenPyroHeuristic.java similarity index 91% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/GeneralizedDependencyDrivenPyroHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/GeneralizedDependencyDrivenPyroHeuristic.java index e8deefa8b..f4c8e71f7 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/GeneralizedDependencyDrivenPyroHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/GeneralizedDependencyDrivenPyroHeuristic.java @@ -23,11 +23,11 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProviderFactory.BodyActivityType; import java.util.Random; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveAtoms.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java similarity index 93% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveAtoms.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java index 858b9ec91..94421084f 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveAtoms.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtoms.java @@ -23,23 +23,25 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; + +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type; +import at.ac.tuwien.kr.alpha.core.solver.BinaryNoGoodPropagationEstimation; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceInfluenceManager; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface.Type; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.ChoiceInfluenceManager; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; + import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.PriorityQueue; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; - /** * Manages a heap of atoms that are assigned an activity, such that the most active atom * resides at the top of the heap. @@ -273,7 +275,7 @@ public void callbackOnChanged(int atom, boolean active) { } } - public void setMOMsStrategy(BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public void setMOMsStrategy(BinaryNoGoodPropagationEstimationStrategy momsStrategy) { if (moms != null) { moms.setStrategy(momsStrategy); } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveChoicePoints.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java similarity index 92% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveChoicePoints.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java index 94c768bee..24644e69b 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveChoicePoints.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveChoicePoints.java @@ -23,18 +23,19 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; + +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.HashSetValuedHashMap; import java.util.HashSet; import java.util.Set; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; /** * Extends {@code HeapOfActiveAtoms} by a mechanism that, diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicsConfiguration.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicsConfiguration.java similarity index 82% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicsConfiguration.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicsConfiguration.java index 160283324..cd7365988 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicsConfiguration.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicsConfiguration.java @@ -23,10 +23,10 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation.Strategy; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory.Heuristic; +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.api.config.Heuristic; import java.util.List; @@ -36,14 +36,14 @@ public class HeuristicsConfiguration { private Heuristic heuristic; - private Strategy momsStrategy; + private BinaryNoGoodPropagationEstimationStrategy momsStrategy; private List replayChoices; /** * @param heuristic * @param momsStrategy * @param replayChoices */ - public HeuristicsConfiguration(Heuristic heuristic, Strategy momsStrategy, List replayChoices) { + public HeuristicsConfiguration(Heuristic heuristic, BinaryNoGoodPropagationEstimationStrategy momsStrategy, List replayChoices) { super(); this.heuristic = heuristic; this.momsStrategy = momsStrategy; @@ -67,14 +67,14 @@ public void setHeuristic(Heuristic heuristic) { /** * @return the momsStrategy */ - public Strategy getMomsStrategy() { + public BinaryNoGoodPropagationEstimationStrategy getMomsStrategy() { return momsStrategy; } /** * @param momsStrategy the momsStrategy to set */ - public void setMomsStrategy(Strategy momsStrategy) { + public void setMomsStrategy(BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this.momsStrategy = momsStrategy; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicsConfigurationBuilder.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicsConfigurationBuilder.java similarity index 87% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicsConfigurationBuilder.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicsConfigurationBuilder.java index 8e68582b6..f7f89b990 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicsConfigurationBuilder.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicsConfigurationBuilder.java @@ -23,10 +23,10 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory.Heuristic; +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.api.config.Heuristic; import java.util.List; @@ -36,7 +36,7 @@ public class HeuristicsConfigurationBuilder { private Heuristic heuristic; - private BinaryNoGoodPropagationEstimation.Strategy momsStrategy; + private BinaryNoGoodPropagationEstimationStrategy momsStrategy; private List replayChoices; /** @@ -50,7 +50,7 @@ public HeuristicsConfigurationBuilder setHeuristic(Heuristic heuristic) { /** * @param momsStrategy the momsStrategy to set */ - public HeuristicsConfigurationBuilder setMomsStrategy(BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public HeuristicsConfigurationBuilder setMomsStrategy(BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this.momsStrategy = momsStrategy; return this; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/MOMs.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/MOMs.java similarity index 71% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/MOMs.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/MOMs.java index fd49def05..f108114ba 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/MOMs.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/MOMs.java @@ -23,10 +23,10 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation.Strategy; +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.core.solver.BinaryNoGoodPropagationEstimation; /** * The well-known MOMs (Maximum Occurrences in clauses of Minimum size) heuristic @@ -34,17 +34,17 @@ * This implementation is inspired by the MOMs implementation in clasp * but differs from it in several ways, e.g.: *
      - *
    • The default strategy is {@link Strategy#CountBinaryWatches}, not {@link Strategy#BinaryNoGoodPropagation}.
    • - *
    • {@link Strategy#BinaryNoGoodPropagation} does not do only one iteration of propagation, but exhaustive propagation.
    • + *
    • The default strategy is {@link BinaryNoGoodPropagationEstimationStrategy#CountBinaryWatches}, not {@link BinaryNoGoodPropagationEstimationStrategy#BinaryNoGoodPropagation}.
    • + *
    • {@link BinaryNoGoodPropagationEstimationStrategy#BinaryNoGoodPropagation} does not do only one iteration of propagation, but exhaustive propagation.
    • *
    * */ public class MOMs { - static final Strategy DEFAULT_STRATEGY = Strategy.CountBinaryWatches; + static final BinaryNoGoodPropagationEstimationStrategy DEFAULT_STRATEGY = BinaryNoGoodPropagationEstimationStrategy.CountBinaryWatches; private BinaryNoGoodPropagationEstimation bnpEstimation; - private Strategy strategy = DEFAULT_STRATEGY; + private BinaryNoGoodPropagationEstimationStrategy strategy = DEFAULT_STRATEGY; public MOMs(BinaryNoGoodPropagationEstimation bnpEstimation) { super(); @@ -61,7 +61,7 @@ public double getScore(Integer atom) { return ((s1 * s2) << 10) + s1 + s2; } - public void setStrategy(Strategy strategy) { + public void setStrategy(BinaryNoGoodPropagationEstimationStrategy strategy) { this.strategy = strategy != null ? strategy : DEFAULT_STRATEGY; } diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/NaiveHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/NaiveHeuristic.java similarity index 84% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/NaiveHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/NaiveHeuristic.java index 506cc345c..d77a7349f 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/NaiveHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/NaiveHeuristic.java @@ -25,18 +25,18 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; -import java.util.Collection; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; +import java.util.Collection; /** - * The default heuristic that had been used by {@link at.ac.tuwien.kr.alpha.solver.DefaultSolver} before {@link BerkMin} was implemented. + * The default heuristic that had been used by {@link at.ac.tuwien.kr.alpha.core.solver.DefaultSolver} before {@link BerkMin} was implemented. * */ public class NaiveHeuristic implements BranchingHeuristic { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ReplayHeuristic.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ReplayHeuristic.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ReplayHeuristic.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ReplayHeuristic.java index cda9f35ac..e2b2f3e2a 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/ReplayHeuristic.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ReplayHeuristic.java @@ -23,12 +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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; import java.util.Iterator; import java.util.List; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/VSIDS.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java similarity index 90% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/VSIDS.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java index 16b5f0daa..bb29d6e14 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/VSIDS.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDS.java @@ -23,26 +23,29 @@ * 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.solver.heuristics; - -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.BinaryNoGoodPropagationEstimation; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.heuristics.activity.BodyActivityProvider; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.HashSetValuedHashMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.arrayGrowthSize; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.isPositive; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import static at.ac.tuwien.kr.alpha.Util.arrayGrowthSize; -import static at.ac.tuwien.kr.alpha.common.Literals.*; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.multimap.HashSetValuedHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.config.BinaryNoGoodPropagationEstimationStrategy; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.heuristics.activity.BodyActivityProvider; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; /** * This implementation is inspired by the VSIDS implementation in clasp. @@ -86,18 +89,18 @@ public class VSIDS implements ActivityBasedBranchingHeuristic { */ protected final MultiValuedMap headToBodies = new HashSetValuedHashMap<>(); - protected VSIDS(Assignment assignment, ChoiceManager choiceManager, HeapOfActiveAtoms heapOfActiveAtoms, BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + protected VSIDS(Assignment assignment, ChoiceManager choiceManager, HeapOfActiveAtoms heapOfActiveAtoms, BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this.assignment = assignment; this.choiceManager = choiceManager; this.heapOfActiveAtoms = heapOfActiveAtoms; this.heapOfActiveAtoms.setMOMsStrategy(momsStrategy); } - public VSIDS(Assignment assignment, ChoiceManager choiceManager, int decayPeriod, double decayFactor, BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public VSIDS(Assignment assignment, ChoiceManager choiceManager, int decayPeriod, double decayFactor, BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this(assignment, choiceManager, new HeapOfActiveAtoms(decayPeriod, decayFactor, choiceManager), momsStrategy); } - public VSIDS(Assignment assignment, ChoiceManager choiceManager, BinaryNoGoodPropagationEstimation.Strategy momsStrategy) { + public VSIDS(Assignment assignment, ChoiceManager choiceManager, BinaryNoGoodPropagationEstimationStrategy momsStrategy) { this(assignment, choiceManager, DEFAULT_DECAY_PERIOD, DEFAULT_DECAY_FACTOR, momsStrategy); } @@ -216,6 +219,7 @@ protected void incrementSignCounter(int literal) { signBalances[atom] += sign ? 1 : -1; } + @Override public void growForMaxAtomId(int maxAtomId) { // Grow arrays only if needed. if (signBalances.length > maxAtomId) { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/AvgBodyActivityProvider.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/AvgBodyActivityProvider.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/AvgBodyActivityProvider.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/AvgBodyActivityProvider.java index 35a5c1f0e..21a60b594 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/AvgBodyActivityProvider.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/AvgBodyActivityProvider.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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/BodyActivityProvider.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/BodyActivityProvider.java similarity index 94% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/BodyActivityProvider.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/BodyActivityProvider.java index 7591eea47..ff4503f9e 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/BodyActivityProvider.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/BodyActivityProvider.java @@ -23,13 +23,13 @@ * 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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; -import java.util.Map; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; +import java.util.Map; public abstract class BodyActivityProvider { diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/BodyActivityProviderFactory.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/BodyActivityProviderFactory.java similarity index 97% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/BodyActivityProviderFactory.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/BodyActivityProviderFactory.java index f3ded2a85..185553c55 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/BodyActivityProviderFactory.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/BodyActivityProviderFactory.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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/DefaultBodyActivityProvider.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/DefaultBodyActivityProvider.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/DefaultBodyActivityProvider.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/DefaultBodyActivityProvider.java index a2e599790..f2d20ccfb 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/DefaultBodyActivityProvider.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/DefaultBodyActivityProvider.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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/MaxBodyActivityProvider.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/MaxBodyActivityProvider.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/MaxBodyActivityProvider.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/MaxBodyActivityProvider.java index 324c4ccce..6ae1c23e7 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/MaxBodyActivityProvider.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/MaxBodyActivityProvider.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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/MinBodyActivityProvider.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/MinBodyActivityProvider.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/MinBodyActivityProvider.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/MinBodyActivityProvider.java index 33d73c237..9542ff912 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/MinBodyActivityProvider.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/MinBodyActivityProvider.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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/SumBodyActivityProvider.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/SumBodyActivityProvider.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/SumBodyActivityProvider.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/SumBodyActivityProvider.java index 4cb116748..0388f60ea 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/heuristics/activity/SumBodyActivityProvider.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/activity/SumBodyActivityProvider.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.solver.heuristics.activity; +package at.ac.tuwien.kr.alpha.core.solver.heuristics.activity; import org.apache.commons.collections4.MultiValuedMap; diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/learning/GroundConflictNoGoodLearner.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/learning/GroundConflictNoGoodLearner.java similarity index 96% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/learning/GroundConflictNoGoodLearner.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/learning/GroundConflictNoGoodLearner.java index d5b26f9bf..3224be049 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/learning/GroundConflictNoGoodLearner.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/learning/GroundConflictNoGoodLearner.java @@ -25,13 +25,14 @@ * 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.solver.learning; +package at.ac.tuwien.kr.alpha.core.solver.learning; + +import at.ac.tuwien.kr.alpha.core.common.Assignment; +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.solver.Antecedent; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.Antecedent; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,9 +40,9 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static at.ac.tuwien.kr.alpha.Util.oops; -import static at.ac.tuwien.kr.alpha.common.Literals.*; -import static at.ac.tuwien.kr.alpha.solver.NoGoodStore.LBD_NO_VALUE; +import static at.ac.tuwien.kr.alpha.commons.util.Util.oops; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.*; +import static at.ac.tuwien.kr.alpha.core.solver.NoGoodStore.LBD_NO_VALUE; /** * Conflict-driven learning on ground clauses. diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/learning/ResolutionSequence.java b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/learning/ResolutionSequence.java similarity index 61% rename from src/main/java/at/ac/tuwien/kr/alpha/solver/learning/ResolutionSequence.java rename to alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/learning/ResolutionSequence.java index 66f870674..060773dc0 100644 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/learning/ResolutionSequence.java +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/solver/learning/ResolutionSequence.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver.learning; +package at.ac.tuwien.kr.alpha.core.solver.learning; /** * Copyright (c) 2016, the Alpha Team. 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 new file mode 100644 index 000000000..40470cf09 --- /dev/null +++ b/alpha-core/src/main/java/at/ac/tuwien/kr/alpha/core/util/Substitutions.java @@ -0,0 +1,31 @@ +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.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.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) { + 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/src/main/resources/stringtemplates/aggregate-encodings.stg b/alpha-core/src/main/resources/stringtemplates/aggregate-encodings.stg similarity index 100% rename from src/main/resources/stringtemplates/aggregate-encodings.stg rename to alpha-core/src/main/resources/stringtemplates/aggregate-encodings.stg diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/atoms/AtomsTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/atoms/AtomsTest.java similarity index 66% rename from src/test/java/at/ac/tuwien/kr/alpha/common/atoms/AtomsTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/atoms/AtomsTest.java index 2b29747e5..602bb960f 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/atoms/AtomsTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/atoms/AtomsTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.atoms; +package at.ac.tuwien.kr.alpha.core.atoms; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -13,12 +13,17 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.externals.Externals; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; import at.ac.tuwien.kr.alpha.api.externals.Predicate; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.externals.Externals; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; /** * Test for basic functionality of various implementations of {@link Atom}. @@ -28,12 +33,13 @@ public class AtomsTest { private final ProgramParser parser; + private Map externals; public AtomsTest() throws NoSuchMethodException, SecurityException { - Map externals = new HashMap<>(); + externals = new HashMap<>(); externals.put("isFoo", Externals.processPredicateMethod(AtomsTest.class.getMethod("isFoo", int.class))); externals.put("extWithOutput", Externals.processPredicateMethod(AtomsTest.class.getMethod("extWithOutput", int.class))); - parser = new ProgramParser(externals); + parser = new ProgramParserImpl(); } @Predicate @@ -45,42 +51,42 @@ public static final boolean isFoo(int bar) { public static final Set>> extWithOutput(int in) { Set>> retVal = new HashSet<>(); List> lst = new ArrayList<>(); - lst.add(ConstantTerm.getSymbolicInstance(Integer.toString(in))); + lst.add(Terms.newConstant(in)); retVal.add(lst); return retVal; } @Test public void testIsBasicAtomGround() { - InputProgram p = parser.parse("bla(blubb, foo(bar))."); + ASPCore2Program p = parser.parse("bla(blubb, foo(bar))."); Atom a = p.getFacts().get(0); assertBasicAtomGround(a, true); - InputProgram p1 = parser.parse("foo(1, 2, 3, \"bar\")."); + ASPCore2Program p1 = parser.parse("foo(1, 2, 3, \"bar\")."); Atom a1 = p1.getFacts().get(0); assertBasicAtomGround(a1, true); - InputProgram p2 = parser.parse("foo(BAR)."); + ASPCore2Program p2 = parser.parse("foo(BAR)."); Atom a2 = p2.getFacts().get(0); assertBasicAtomGround(a2, false); - InputProgram p3 = parser.parse("foo(b, a, r(\"bla\", BLUBB))."); + ASPCore2Program p3 = parser.parse("foo(b, a, r(\"bla\", BLUBB))."); Atom a3 = p3.getFacts().get(0); assertBasicAtomGround(a3, false); } @Test public void testAreBasicAtomsEqual() { - InputProgram p1 = parser.parse("bla(blubb, foo(bar)). bla(blubb, foo(bar))."); + ASPCore2Program p1 = parser.parse("bla(blubb, foo(bar)). bla(blubb, foo(bar))."); Atom a1 = p1.getFacts().get(0); Atom a2 = p1.getFacts().get(1); assertEquals(a1, a2); - InputProgram p2 = parser.parse("foo(1, 2, 3, \"bar\"). foo(1, 2, 3, \"bar\")."); + ASPCore2Program p2 = parser.parse("foo(1, 2, 3, \"bar\"). foo(1, 2, 3, \"bar\")."); Atom a3 = p2.getFacts().get(0); Atom a4 = p2.getFacts().get(1); assertEquals(a3, a4); - InputProgram p3 = parser.parse("foo(BAR). foo(BAR)."); + ASPCore2Program p3 = parser.parse("foo(BAR). foo(BAR)."); Atom a5 = p3.getFacts().get(0); Atom a6 = p3.getFacts().get(1); assertEquals(a5, a6); - InputProgram p4 = parser.parse("foo(b, a, r(\"bla\", BLUBB)). foo(b, a, r(\"bla\", BLUBB))."); + ASPCore2Program p4 = parser.parse("foo(b, a, r(\"bla\", BLUBB)). foo(b, a, r(\"bla\", BLUBB))."); Atom a7 = p4.getFacts().get(0); Atom a8 = p4.getFacts().get(1); assertEquals(a7, a8); @@ -95,13 +101,13 @@ public void testAreBasicAtomsEqual() { @Test public void testIsExternalAtomGround() { - InputProgram p1 = parser.parse("a :- &isFoo[1]."); + ASPCore2Program p1 = parser.parse("a :- &isFoo[1].", externals); Atom ext1 = p1.getRules().get(0).getBody().stream().findFirst().get().getAtom(); assertExternalAtomGround(ext1, true); - InputProgram p2 = parser.parse("a :- &isFoo[bar(1)]."); + ASPCore2Program p2 = parser.parse("a :- &isFoo[bar(1)].", externals); Atom ext2 = p2.getRules().get(0).getBody().stream().findFirst().get().getAtom(); assertExternalAtomGround(ext2, true); - InputProgram p3 = parser.parse("a :- &isFoo[BLA]."); + ASPCore2Program p3 = parser.parse("a :- &isFoo[BLA].", externals); Atom ext3 = p3.getRules().get(0).getBody().stream().findFirst().get().getAtom(); assertExternalAtomGround(ext3, false); } @@ -109,9 +115,9 @@ public void testIsExternalAtomGround() { @Test @SuppressWarnings("unlikely-arg-type") public void testAreExternalAtomsEqual() { - InputProgram p1 = parser.parse("a :- &isFoo[1]."); + ASPCore2Program p1 = parser.parse("a :- &isFoo[1].", externals); Atom ext1 = p1.getRules().get(0).getBody().stream().findFirst().get().getAtom(); - InputProgram p2 = parser.parse("a :- &isFoo[1]."); + ASPCore2Program p2 = parser.parse("a :- &isFoo[1].", externals); Atom ext2 = p2.getRules().get(0).getBody().stream().findFirst().get().getAtom(); assertEquals(ext1, ext2); assertEquals(ext2, ext1); @@ -123,7 +129,7 @@ public void testAreExternalAtomsEqual() { @Test public void testExternalHasOutput() { - InputProgram p = parser.parse("a:- &extWithOutput[1](OUT)."); + ASPCore2Program p = parser.parse("a:- &extWithOutput[1](OUT).", externals); Atom ext = p.getRules().get(0).getBody().stream().findFirst().get().getAtom(); assertExternalAtomGround(ext, false); assertTrue(((ExternalAtom) ext).hasOutput()); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/atoms/LiteralBindingNonBindingVariablesTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/atoms/LiteralBindingNonBindingVariablesTest.java similarity index 80% rename from src/test/java/at/ac/tuwien/kr/alpha/common/atoms/LiteralBindingNonBindingVariablesTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/atoms/LiteralBindingNonBindingVariablesTest.java index 1f0f131bd..5b0370e9e 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/atoms/LiteralBindingNonBindingVariablesTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/atoms/LiteralBindingNonBindingVariablesTest.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.common.atoms; +package at.ac.tuwien.kr.alpha.core.atoms; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -37,12 +37,16 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.IntPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.IntPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; /** * Tests the behaviour of {@link Literal#getBindingVariables()} and {@link Literal#getNonBindingVariables()} @@ -52,7 +56,7 @@ public class LiteralBindingNonBindingVariablesTest { private final Map externals = new HashMap<>(); - private final ProgramParser parser = new ProgramParser(externals); + private final ProgramParser parser = new ProgramParserImpl(); @Test public void testPositiveBasicLiteral() { @@ -72,8 +76,8 @@ public void testNegativeBasicLiteral() { @Test public void testPositiveComparisonLiteral_EQ_LeftAssigning() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), Y = 5.").getRules().get(0); - Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperator.EQ.predicate()).findFirst().get(); + Rule rule = parser.parse("p(X) :- q(X,Y), Y = 5.").getRules().get(0); + Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperators.EQ.toPredicate()).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables(), "Y"); expectVariables(literal.getNonBindingVariables()); @@ -81,7 +85,7 @@ public void testPositiveComparisonLiteral_EQ_LeftAssigning() { @Test public void testNegativeComparisonLiteral_EQ_LeftAssigning() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), not Y = 5.").getRules().get(0); + Rule rule = parser.parse("p(X) :- q(X,Y), not Y = 5.").getRules().get(0); Literal literal = rule.getNegativeBody().stream().findFirst().get(); assertEquals(true, literal.isNegated()); expectVariables(literal.getBindingVariables()); @@ -90,8 +94,8 @@ public void testNegativeComparisonLiteral_EQ_LeftAssigning() { @Test public void testPositiveComparisonLiteral_EQ_RightAssigning() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), 5 = Y.").getRules().get(0); - Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperator.EQ.predicate()).findFirst().get(); + Rule rule = parser.parse("p(X) :- q(X,Y), 5 = Y.").getRules().get(0); + Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperators.EQ.toPredicate()).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables(), "Y"); expectVariables(literal.getNonBindingVariables()); @@ -108,8 +112,8 @@ public void testNegativeComparisonLiteral_EQ_RightAssigning() { @Test @Disabled("Literals of this kind are compiled away by VariableEqualityRemoval") public void testPositiveComparisonLiteral_EQ_Bidirectional() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), X = Y.").getRules().get(0); - Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperator.EQ.predicate()).findFirst().get(); + Rule rule = parser.parse("p(X) :- q(X,Y), X = Y.").getRules().get(0); + Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperators.EQ.toPredicate()).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables()); expectVariables(literal.getNonBindingVariables(), "X", "Y"); @@ -125,8 +129,8 @@ public void testNegativeComparisonLiteral_EQ_Bidirectional() { @Test public void testPositiveComparisonLiteral_NEQ_LeftAssigning() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), Y != 5.").getRules().get(0); - Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperator.NE.predicate()).findFirst().get(); + Rule rule = parser.parse("p(X) :- q(X,Y), Y != 5.").getRules().get(0); + Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperators.NE.toPredicate()).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables()); expectVariables(literal.getNonBindingVariables(), "Y"); @@ -142,8 +146,8 @@ public void testNegativeComparisonLiteral_NEQ_LeftAssigning() { @Test public void testPositiveComparisonLiteral_NEQ_RightAssigning() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), 5 != Y.").getRules().get(0); - Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperator.NE.predicate()).findFirst().get(); + Rule rule = parser.parse("p(X) :- q(X,Y), 5 != Y.").getRules().get(0); + Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperators.NE.toPredicate()).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables()); expectVariables(literal.getNonBindingVariables(), "Y"); @@ -159,8 +163,8 @@ public void testNegativeComparisonLiteral_NEQ_RightAssigning() { @Test public void testPositiveComparisonLiteral_NEQ_Bidirectional() { - BasicRule rule = parser.parse("p(X) :- q(X,Y), X != Y.").getRules().get(0); - Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperator.NE.predicate()).findFirst().get(); + Rule rule = parser.parse("p(X) :- q(X,Y), X != Y.").getRules().get(0); + Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate() == ComparisonOperators.NE.toPredicate()).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables()); expectVariables(literal.getNonBindingVariables(), "X", "Y"); @@ -178,7 +182,7 @@ public void testNegativeComparisonLiteral_NEQ_Bidirectional() { @Test public void testPositiveExternalLiteral() { externals.put("ext", new IntPredicateInterpretation(i -> i > 0)); - BasicRule rule = parser.parse("p(X) :- q(Y), &ext[Y](X).").getRules().get(0); + Rule rule = parser.parse("p(X) :- q(Y), &ext[Y](X).", externals).getRules().get(0); Literal literal = rule.getBody().stream().filter((lit) -> lit.getPredicate().getName().equals("ext")).findFirst().get(); assertEquals(false, literal.isNegated()); expectVariables(literal.getBindingVariables(), "X"); @@ -188,7 +192,7 @@ public void testPositiveExternalLiteral() { @Test public void testNegativeExternalLiteral() { externals.put("ext", new IntPredicateInterpretation(i -> i > 0)); - Literal literal = parser.parse("p(X) :- q(Y), not &ext[Y](X).").getRules().get(0).getNegativeBody().stream().findFirst().get(); + Literal literal = parser.parse("p(X) :- q(Y), not &ext[Y](X).", externals).getRules().get(0).getNegativeBody().stream().findFirst().get(); assertEquals(true, literal.isNegated()); expectVariables(literal.getBindingVariables()); expectVariables(literal.getNonBindingVariables(), "X", "Y"); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/NoGoodTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/NoGoodTest.java similarity index 90% rename from src/test/java/at/ac/tuwien/kr/alpha/common/NoGoodTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/NoGoodTest.java index 89247245f..e448d058f 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/NoGoodTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/NoGoodTest.java @@ -1,7 +1,5 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.core.common; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToNegatedLiteral; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -13,6 +11,8 @@ import org.junit.jupiter.api.Test; +import at.ac.tuwien.kr.alpha.core.atoms.Literals; + public class NoGoodTest { /** * Constructs an array of literals with the new representation (least-significant bit is polarity, other bits @@ -24,13 +24,13 @@ public class NoGoodTest { public static int[] fromOldLiterals(int... literals) { int[] newLiterals = new int[literals.length]; for (int i = 0; i < literals.length; i++) { - newLiterals[i] = literals[i] >= 0 ? atomToLiteral(literals[i]) : atomToNegatedLiteral(-literals[i]); + newLiterals[i] = literals[i] >= 0 ? Literals.atomToLiteral(literals[i]) : Literals.atomToNegatedLiteral(-literals[i]); } return newLiterals; } public static int fromOldLiterals(int literal) { - return literal >= 0 ? atomToLiteral(literal) : atomToNegatedLiteral(-literal); + return literal >= 0 ? Literals.atomToLiteral(literal) : Literals.atomToNegatedLiteral(-literal); } @Test @@ -111,4 +111,4 @@ public void noGoodsInHashMap() { noGoodIdentifiers.put(ng3, 5); assertEquals(2, noGoodIdentifiers.size()); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/ProgramTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/ProgramTest.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/common/ProgramTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/ProgramTest.java index 37a6fecad..9ced45803 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/ProgramTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/ProgramTest.java @@ -23,20 +23,20 @@ * 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.common; +package at.ac.tuwien.kr.alpha.core.common; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; public class ProgramTest { @Test public void testToString() { - InputProgram parsedProgram = new ProgramParser().parse( + ASPCore2Program parsedProgram = new ProgramParserImpl().parse( "p(a)." + System.lineSeparator() + "q(X) :- p(X)." + System.lineSeparator() + "p(b)."); diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/RuleTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/RuleTest.java new file mode 100644 index 000000000..0c637cb1a --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/RuleTest.java @@ -0,0 +1,55 @@ +package at.ac.tuwien.kr.alpha.core.common; + + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; + +/** + * Copyright (c) 2018, the Alpha Team. + */ +public class RuleTest { + + private final ProgramParserImpl parser = new ProgramParserImpl(); + + @Test + public void renameVariables() { + String originalRule = "p(X,Y) :- a, f(Z) = 1, q(X,g(Y),Z), dom(A)."; + Rule rule = parser.parse(originalRule).getRules().get(0); + CompiledRule normalRule = InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(rule)); + CompiledRule renamedRule = normalRule.renameVariables("_13"); + Rule expectedRenamedRule = parser.parse("p(X_13, Y_13) :- a, f(Z_13) = 1, q(X_13, g(Y_13), Z_13), dom(A_13).").getRules().get(0); + CompiledRule expectedRenamedNormalRule = InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(expectedRenamedRule)); + assertEquals(expectedRenamedNormalRule.toString(), renamedRule.toString()); + } + + @Test + public void testRulesEqual() { + ASPCore2Program p1 = parser.parse("p(X, Y) :- bla(X), blub(Y), foo(X, Y), not bar(X)."); + Rule r1 = p1.getRules().get(0); + ASPCore2Program p2 = parser.parse("p(X, Y) :- bla(X), blub(Y), foo(X, Y), not bar(X)."); + Rule r2 = p2.getRules().get(0); + ASPCore2Program p3 = parser.parse("p(X, Y) :- bla(X), blub(X), foo(X, X), not bar(X)."); + Rule r3 = p3.getRules().get(0); + assertTrue(r1.equals(r2)); + assertTrue(r2.equals(r1)); + assertTrue(r1.hashCode() == r2.hashCode()); + assertFalse(r1.equals(r3)); + assertFalse(r3.equals(r1)); + assertTrue(r1.hashCode() != r3.hashCode()); + assertFalse(r2.equals(r3)); + assertFalse(r3.equals(r2)); + assertTrue(r2.hashCode() != r3.hashCode()); + } + +} \ No newline at end of file diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/AnswerSetFormatterTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/SimpleAnswerSetFormatterTest.java similarity index 57% rename from src/test/java/at/ac/tuwien/kr/alpha/common/AnswerSetFormatterTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/SimpleAnswerSetFormatterTest.java index 1ffbf023c..0b14388ad 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/AnswerSetFormatterTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/common/SimpleAnswerSetFormatterTest.java @@ -1,10 +1,15 @@ -package at.ac.tuwien.kr.alpha.common; +package at.ac.tuwien.kr.alpha.core.common; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -public class AnswerSetFormatterTest { +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.util.AnswerSetFormatter; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.commons.util.SimpleAnswerSetFormatter; + +public class SimpleAnswerSetFormatterTest { @Test public void basicFormatterWithSeparator() { diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/depgraph/DependencyGraphTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/depgraph/DependencyGraphImplTest.java similarity index 68% rename from src/test/java/at/ac/tuwien/kr/alpha/common/depgraph/DependencyGraphTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/depgraph/DependencyGraphImplTest.java index 91ee5730d..65e4f32ae 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/depgraph/DependencyGraphTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/depgraph/DependencyGraphImplTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,15 +10,24 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.test.util.DependencyGraphUtils; - -public class DependencyGraphTest { - +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph.Node; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.test.util.DependencyGraphUtils; + +public class DependencyGraphImplTest { + + private ProgramParser parser = new ProgramParserImpl(); + private NormalizeProgramTransformation normalizeTransform = new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); + // Currently not used anywhere, but keep as it might come in handy @SuppressWarnings("unused") private static String generateRandomProgram(int numRules, int numPredicates, int maxRuleBodyLiterals) { @@ -49,25 +58,23 @@ private static String generateRandomProgram(int numRules, int numPredicates, int @Test public void edgesEqualTest() { - Predicate testPredicate = Predicate.getInstance("test", 2, false, false); - Edge e1 = new Edge(new Node(testPredicate), true); - Edge e2 = new Edge(new Node(testPredicate), true); + Predicate testPredicate = Predicates.getPredicate("test", 2, false, false); + EdgeImpl e1 = new EdgeImpl(new NodeImpl(testPredicate), true); + EdgeImpl e2 = new EdgeImpl(new NodeImpl(testPredicate), true); assertEquals(e1, e2); } @Test public void reachabilityCheckSimpleTest() { - Alpha system = new Alpha(); - - InputProgram prog = system.readProgramString("b :- a.", null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse("b :- a."); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - Node a = dg.getNodeForPredicate(Predicate.getInstance("a", 0)); - Node b = dg.getNodeForPredicate(Predicate.getInstance("b", 0)); + Node a = dg.getNodeForPredicate(Predicates.getPredicate("a", 0)); + Node b = dg.getNodeForPredicate(Predicates.getPredicate("b", 0)); - Node nonExistent = new Node(Predicate.getInstance("notHere", 0)); + NodeImpl nonExistent = new NodeImpl(Predicates.getPredicate("notHere", 0)); assertTrue(DependencyGraphUtils.isReachableFrom(a, a, dg)); assertTrue(DependencyGraphUtils.isReachableFrom(b, a, dg)); @@ -82,15 +89,15 @@ public void reachabilityCheckWithHopsTest() { bld.append("b :- a.").append("\n"); bld.append("c :- b.").append("\n"); bld.append("d :- c.").append("\n"); - Alpha system = new Alpha(); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - Node a = dg.getNodeForPredicate(Predicate.getInstance("a", 0)); - Node b = dg.getNodeForPredicate(Predicate.getInstance("b", 0)); - Node c = dg.getNodeForPredicate(Predicate.getInstance("c", 0)); - Node d = dg.getNodeForPredicate(Predicate.getInstance("d", 0)); + Node a = dg.getNodeForPredicate(Predicates.getPredicate("a", 0)); + Node b = dg.getNodeForPredicate(Predicates.getPredicate("b", 0)); + Node c = dg.getNodeForPredicate(Predicates.getPredicate("c", 0)); + Node d = dg.getNodeForPredicate(Predicates.getPredicate("d", 0)); assertTrue(DependencyGraphUtils.isReachableFrom(d, a, dg)); assertTrue(DependencyGraphUtils.isReachableFrom(c, a, dg)); @@ -117,18 +124,18 @@ public void reachabilityWithCyclesTest() { bld.append("d :- c.").append("\n"); bld.append("a :- d.").append("\n"); bld.append("x :- d, f1."); - Alpha system = new Alpha(); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - Node a = dg.getNodeForPredicate(Predicate.getInstance("a", 0)); - Node b = dg.getNodeForPredicate(Predicate.getInstance("b", 0)); - Node c = dg.getNodeForPredicate(Predicate.getInstance("c", 0)); - Node d = dg.getNodeForPredicate(Predicate.getInstance("d", 0)); - Node f1 = dg.getNodeForPredicate(Predicate.getInstance("f1", 0)); - Node x = dg.getNodeForPredicate(Predicate.getInstance("x", 0)); - Node notInGraph = new Node(Predicate.getInstance("notInGraph", 0)); + Node a = dg.getNodeForPredicate(Predicates.getPredicate("a", 0)); + Node b = dg.getNodeForPredicate(Predicates.getPredicate("b", 0)); + Node c = dg.getNodeForPredicate(Predicates.getPredicate("c", 0)); + Node d = dg.getNodeForPredicate(Predicates.getPredicate("d", 0)); + Node f1 = dg.getNodeForPredicate(Predicates.getPredicate("f1", 0)); + Node x = dg.getNodeForPredicate(Predicates.getPredicate("x", 0)); + Node notInGraph = new NodeImpl(Predicates.getPredicate("notInGraph", 0)); assertTrue(DependencyGraphUtils.isReachableFrom(d, a, dg)); assertTrue(DependencyGraphUtils.isReachableFrom(c, a, dg)); @@ -157,19 +164,20 @@ public void stronglyConnectedComponentsSimpleTest() { StringBuilder bld = new StringBuilder(); bld.append("b :- a.").append("\n"); bld.append("a :- b.").append("\n"); - Alpha system = new Alpha(); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - Node a = dg.getNodeForPredicate(Predicate.getInstance("a", 0)); - Node b = dg.getNodeForPredicate(Predicate.getInstance("b", 0)); + Node a = dg.getNodeForPredicate(Predicates.getPredicate("a", 0)); + Node b = dg.getNodeForPredicate(Predicates.getPredicate("b", 0)); List componentA = new ArrayList<>(); componentA.add(a); assertTrue(DependencyGraphUtils.areStronglyConnected(componentA, dg)); assertFalse(DependencyGraphUtils.isStronglyConnectedComponent(componentA, dg)); + List componentB = new ArrayList<>(); componentB.add(b); assertTrue(DependencyGraphUtils.areStronglyConnected(componentB, dg)); @@ -196,23 +204,22 @@ public void stronglyConnectedComponentsMultipleComponentsTest() { "y :- b, d, x.\n" + "z :- x, y, z."; - Alpha system = new Alpha(); - InputProgram prog = system.readProgramString(inputProgram); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(inputProgram); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - Node f0 = dg.getNodeForPredicate(Predicate.getInstance("f0", 0)); - Node f1 = dg.getNodeForPredicate(Predicate.getInstance("f1", 0)); - Node f2 = dg.getNodeForPredicate(Predicate.getInstance("f2", 0)); - Node f3 = dg.getNodeForPredicate(Predicate.getInstance("f3", 0)); - Node a = dg.getNodeForPredicate(Predicate.getInstance("a", 0)); - Node b = dg.getNodeForPredicate(Predicate.getInstance("b", 0)); - Node c = dg.getNodeForPredicate(Predicate.getInstance("c", 0)); - Node d = dg.getNodeForPredicate(Predicate.getInstance("d", 0)); - Node x = dg.getNodeForPredicate(Predicate.getInstance("x", 0)); - Node y = dg.getNodeForPredicate(Predicate.getInstance("y", 0)); - Node z = dg.getNodeForPredicate(Predicate.getInstance("z", 0)); + Node f0 = dg.getNodeForPredicate(Predicates.getPredicate("f0", 0)); + Node f1 = dg.getNodeForPredicate(Predicates.getPredicate("f1", 0)); + Node f2 = dg.getNodeForPredicate(Predicates.getPredicate("f2", 0)); + Node f3 = dg.getNodeForPredicate(Predicates.getPredicate("f3", 0)); + Node a = dg.getNodeForPredicate(Predicates.getPredicate("a", 0)); + Node b = dg.getNodeForPredicate(Predicates.getPredicate("b", 0)); + Node c = dg.getNodeForPredicate(Predicates.getPredicate("c", 0)); + Node d = dg.getNodeForPredicate(Predicates.getPredicate("d", 0)); + Node x = dg.getNodeForPredicate(Predicates.getPredicate("x", 0)); + Node y = dg.getNodeForPredicate(Predicates.getPredicate("y", 0)); + Node z = dg.getNodeForPredicate(Predicates.getPredicate("z", 0)); StronglyConnectedComponentsAlgorithm.SccResult sccResult = StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg); Map nodesByComponent = sccResult.nodesByComponentId; diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/depgraph/StratificationAlgorithmTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/depgraph/StratificationAlgorithmTest.java similarity index 58% rename from src/test/java/at/ac/tuwien/kr/alpha/common/depgraph/StratificationAlgorithmTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/depgraph/StratificationAlgorithmTest.java index e861c0ecf..c50acaf9b 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/depgraph/StratificationAlgorithmTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/depgraph/StratificationAlgorithmTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.depgraph; +package at.ac.tuwien.kr.alpha.core.depgraph; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -7,16 +7,25 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.depgraph.ComponentGraph.SCComponent; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; - +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph.SCComponent; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph.Node; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; public class StratificationAlgorithmTest { + private ProgramParser parser = new ProgramParserImpl(); + private NormalizeProgramTransformation normalizeTransform = new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); + private boolean predicateIsBeforePredicateInOrder(Predicate predBefore, Predicate predAfter, List order) { boolean foundPredBefore = false; for (SCComponent component : order) { @@ -35,16 +44,15 @@ private boolean predicateIsBeforePredicateInOrder(Predicate predBefore, Predicat @Test public void stratifyOneRuleTest() { - Alpha system = new Alpha(); - InputProgram prog = system.readProgramString("a :- b.", null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse("a :- b."); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate a = Predicate.getInstance("a", 0); - Predicate b = Predicate.getInstance("b", 0); + Predicate a = Predicates.getPredicate("a", 0); + Predicate b = Predicates.getPredicate("b", 0); assertEquals(2, strata.size()); assertTrue(predicateIsBeforePredicateInOrder(b, a, strata)); @@ -52,20 +60,19 @@ public void stratifyOneRuleTest() { @Test public void stratifyTwoRulesTest() { - Alpha system = new Alpha(); StringBuilder bld = new StringBuilder(); bld.append("b :- a.").append("\n"); bld.append("c :- b.").append("\n"); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate a = Predicate.getInstance("a", 0); - Predicate b = Predicate.getInstance("b", 0); - Predicate c = Predicate.getInstance("c", 0); + Predicate a = Predicates.getPredicate("a", 0); + Predicate b = Predicates.getPredicate("b", 0); + Predicate c = Predicates.getPredicate("c", 0); assertEquals(3, strata.size()); assertTrue(predicateIsBeforePredicateInOrder(a, b, strata)); @@ -75,24 +82,23 @@ public void stratifyTwoRulesTest() { @Test public void stratifyWithNegativeDependencyTest() { - Alpha system = new Alpha(); StringBuilder bld = new StringBuilder(); bld.append("b :- a.").append("\n"); bld.append("c :- b.").append("\n"); bld.append("d :- not c.").append("\n"); bld.append("e :- d.").append("\n"); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate a = Predicate.getInstance("a", 0); - Predicate b = Predicate.getInstance("b", 0); - Predicate c = Predicate.getInstance("c", 0); - Predicate d = Predicate.getInstance("d", 0); - Predicate e = Predicate.getInstance("e", 0); + Predicate a = Predicates.getPredicate("a", 0); + Predicate b = Predicates.getPredicate("b", 0); + Predicate c = Predicates.getPredicate("c", 0); + Predicate d = Predicates.getPredicate("d", 0); + Predicate e = Predicates.getPredicate("e", 0); assertEquals(5, strata.size()); assertTrue(predicateIsBeforePredicateInOrder(a, b, strata)); @@ -103,19 +109,18 @@ public void stratifyWithNegativeDependencyTest() { @Test public void stratifyWithPositiveCycleTest() { - Alpha system = new Alpha(); StringBuilder bld = new StringBuilder(); bld.append("ancestor_of(X, Y) :- parent_of(X, Y)."); bld.append("ancestor_of(X, Z) :- parent_of(X, Y), ancestor_of(Y, Z)."); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate ancestorOf = Predicate.getInstance("ancestor_of", 2); - Predicate parentOf = Predicate.getInstance("parent_of", 2); + Predicate ancestorOf = Predicates.getPredicate("ancestor_of", 2); + Predicate parentOf = Predicates.getPredicate("parent_of", 2); assertEquals(2, strata.size()); assertTrue(predicateIsBeforePredicateInOrder(parentOf, ancestorOf, strata)); @@ -123,7 +128,6 @@ public void stratifyWithPositiveCycleTest() { @Test public void stratifyLargeGraphTest() { - Alpha system = new Alpha(); StringBuilder bld = new StringBuilder(); bld.append("b :- a."); bld.append("c :- b."); @@ -140,20 +144,20 @@ public void stratifyLargeGraphTest() { bld.append("n :- m, not i, not j."); bld.append("p :- not m, not n."); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate a = Predicate.getInstance("a", 0); - Predicate b = Predicate.getInstance("b", 0); - Predicate c = Predicate.getInstance("c", 0); - Predicate d = Predicate.getInstance("d", 0); - Predicate e = Predicate.getInstance("e", 0); - Predicate f = Predicate.getInstance("f", 0); - Predicate h = Predicate.getInstance("h", 0); + Predicate a = Predicates.getPredicate("a", 0); + Predicate b = Predicates.getPredicate("b", 0); + Predicate c = Predicates.getPredicate("c", 0); + Predicate d = Predicates.getPredicate("d", 0); + Predicate e = Predicates.getPredicate("e", 0); + Predicate f = Predicates.getPredicate("f", 0); + Predicate h = Predicates.getPredicate("h", 0); assertTrue(predicateIsBeforePredicateInOrder(a, h, strata)); assertTrue(predicateIsBeforePredicateInOrder(b, h, strata)); @@ -168,7 +172,6 @@ public void stratifyLargeGraphTest() { @Test public void stratifyAvoidDuplicatesTest() { - Alpha system = new Alpha(); StringBuilder bld = new StringBuilder(); bld.append("b :- a."); bld.append("c :- b."); @@ -185,21 +188,20 @@ public void stratifyAvoidDuplicatesTest() { bld.append("n :- m, not i, not j."); bld.append("p :- not m, not n."); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate a = Predicate.getInstance("a", 0); - Predicate b = Predicate.getInstance("b", 0); - Predicate c = Predicate.getInstance("c", 0); - Predicate d = Predicate.getInstance("d", 0); - Predicate e = Predicate.getInstance("e", 0); - Predicate f = Predicate.getInstance("f", 0); - Predicate h = Predicate.getInstance("h", 0); - + Predicate a = Predicates.getPredicate("a", 0); + Predicate b = Predicates.getPredicate("b", 0); + Predicate c = Predicates.getPredicate("c", 0); + Predicate d = Predicates.getPredicate("d", 0); + Predicate e = Predicates.getPredicate("e", 0); + Predicate f = Predicates.getPredicate("f", 0); + Predicate h = Predicates.getPredicate("h", 0); assertEquals(7, strata.size()); assertTrue(predicateIsBeforePredicateInOrder(a, b, strata)); @@ -213,22 +215,21 @@ public void stratifyAvoidDuplicatesTest() { @Test public void avoidDuplicatesTest1() { - Alpha system = new Alpha(); StringBuilder bld = new StringBuilder(); bld.append("b :- a."); bld.append("c :- b."); bld.append("c :- a."); - InputProgram prog = system.readProgramString(bld.toString(), null); - NormalProgram normalProg = system.normalizeProgram(prog); + ASPCore2Program prog = parser.parse(bld.toString()); + NormalProgram normalProg = normalizeTransform.apply(prog); AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalProg); DependencyGraph dg = analyzed.getDependencyGraph(); - ComponentGraph cg = ComponentGraph.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); + ComponentGraph cg = ComponentGraphImpl.buildComponentGraph(dg, StronglyConnectedComponentsAlgorithm.findStronglyConnectedComponents(dg)); List strata = StratificationAlgorithm.calculateStratification(cg); - Predicate a = Predicate.getInstance("a", 0); - Predicate b = Predicate.getInstance("b", 0); - Predicate c = Predicate.getInstance("c", 0); + Predicate a = Predicates.getPredicate("a", 0); + Predicate b = Predicates.getPredicate("b", 0); + Predicate c = Predicates.getPredicate("c", 0); assertTrue(predicateIsBeforePredicateInOrder(a, b, strata)); assertTrue(predicateIsBeforePredicateInOrder(b, c, strata)); diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/externals/AspStandardLibraryTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/externals/AspStandardLibraryTest.java new file mode 100644 index 000000000..2e2e954ce --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/externals/AspStandardLibraryTest.java @@ -0,0 +1,107 @@ +package at.ac.tuwien.kr.alpha.core.externals; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; + +public class AspStandardLibraryTest { + + @Test + public void parseDateTime1() { + Set>> dtSubstitution = AspStandardLibrary.datetimeParse("20.05.2020 01:19:13", "dd.MM.yyyy HH:mm:ss"); + assertEquals(1, dtSubstitution.size()); + List> dtTerms = dtSubstitution.stream().findFirst().get(); + assertEquals(6, dtTerms.size()); + assertEquals(Terms.newConstant(2020), dtTerms.get(0)); + assertEquals(Terms.newConstant(5), dtTerms.get(1)); + assertEquals(Terms.newConstant(20), dtTerms.get(2)); + assertEquals(Terms.newConstant(1), dtTerms.get(3)); + assertEquals(Terms.newConstant(19), dtTerms.get(4)); + assertEquals(Terms.newConstant(13), dtTerms.get(5)); + } + + @Test + public void parseDateTime2() { + Set>> dtSubstitution = AspStandardLibrary.datetimeParse("07/2123/18 22/37/01", "MM/yyyy/dd HH/mm/ss"); + assertEquals(1, dtSubstitution.size()); + List> dtTerms = dtSubstitution.stream().findFirst().get(); + assertEquals(6, dtTerms.size()); + assertEquals(Terms.newConstant(2123), dtTerms.get(0)); + assertEquals(Terms.newConstant(7), dtTerms.get(1)); + assertEquals(Terms.newConstant(18), dtTerms.get(2)); + assertEquals(Terms.newConstant(22), dtTerms.get(3)); + assertEquals(Terms.newConstant(37), dtTerms.get(4)); + assertEquals(Terms.newConstant(1), dtTerms.get(5)); + } + + @Test + public void parseDateTime3() { + Set>> dtSubstitution = AspStandardLibrary.datetimeParse("\"03,12,2019\", \"11:00:00\"", + "\"dd,MM,yyyy\", \"HH:mm:ss\""); + assertEquals(1, dtSubstitution.size()); + List> dtTerms = dtSubstitution.stream().findFirst().get(); + assertEquals(6, dtTerms.size()); + assertEquals(Terms.newConstant(2019), dtTerms.get(0)); + assertEquals(Terms.newConstant(12), dtTerms.get(1)); + assertEquals(Terms.newConstant(3), dtTerms.get(2)); + assertEquals(Terms.newConstant(11), dtTerms.get(3)); + assertEquals(Terms.newConstant(0), dtTerms.get(4)); + assertEquals(Terms.newConstant(0), dtTerms.get(5)); + } + + @Test + public void datetimeBefore() { + assertTrue(AspStandardLibrary.datetimeIsBefore(1990, 2, 14, 15, 16, 17, 1990, 3, 1, 0, 59, 1)); + assertFalse(AspStandardLibrary.datetimeIsBefore(2015, 5, 13, 12, 1, 33, 2003, 1, 1, 0, 0, 1)); + assertFalse(AspStandardLibrary.datetimeIsBefore(2022, 2, 22, 22, 22, 22, 2022, 2, 22, 22, 22, 22)); + } + + @Test + public void datetimeEqual() { + assertTrue(AspStandardLibrary.datetimeIsEqual(1990, 2, 14, 15, 16, 17, 1990, 2, 14, 15, 16, 17)); + assertFalse(AspStandardLibrary.datetimeIsEqual(2015, 5, 13, 12, 1, 33, 2003, 1, 1, 0, 0, 1)); + } + + @Test + public void datetimeBeforeOrEqual() { + assertTrue(AspStandardLibrary.datetimeIsBeforeOrEqual(1990, 2, 14, 15, 16, 17, 1990, 3, 1, 0, 59, 1)); + assertFalse(AspStandardLibrary.datetimeIsBeforeOrEqual(2015, 5, 13, 12, 1, 33, 2003, 1, 1, 0, 0, 1)); + assertTrue(AspStandardLibrary.datetimeIsBeforeOrEqual(2022, 2, 22, 22, 22, 22, 2022, 2, 22, 22, 22, 22)); + + } + + @Test + public void matchesRegex() { + assertTrue(AspStandardLibrary.stringMatchesRegex("Blaaaaa Blubbb!!", "Bla+ Blub+!!")); + assertFalse(AspStandardLibrary.stringMatchesRegex("Foobar", "Bla+ Blub+!!")); + } + + @Test + public void stringLength() { + Set>> result = AspStandardLibrary.stringLength("A String of length 21"); + assertEquals(1, result.size()); + List> lengthTerms = result.stream().findFirst().get(); + assertEquals(1, lengthTerms.size()); + ConstantTerm lenTerm = lengthTerms.get(0); + assertEquals(Terms.newConstant(21), lenTerm); + } + + @Test + public void stringConcat() { + Set>> result = AspStandardLibrary.stringConcat("Foo", "bar"); + assertEquals(1, result.size()); + List> concatTerms = result.stream().findFirst().get(); + assertEquals(1, concatTerms.size()); + ConstantTerm concat = concatTerms.get(0); + assertEquals(Terms.newConstant("Foobar"), concat); + } + +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/ChoiceGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java similarity index 76% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/ChoiceGrounder.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java index e090fec20..66374d312 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/ChoiceGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/ChoiceGrounder.java @@ -25,26 +25,14 @@ * 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.grounder; - -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.BasicAnswerSet; -import at.ac.tuwien.kr.alpha.common.IntIterator; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.grounder.atoms.ChoiceAtom; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; +package at.ac.tuwien.kr.alpha.core.grounder; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.entriesToMap; +import static at.ac.tuwien.kr.alpha.commons.util.Util.entry; +import static at.ac.tuwien.kr.alpha.core.common.NoGood.headFirst; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; +import static java.util.Arrays.asList; +import static java.util.Collections.singleton; import java.util.Arrays; import java.util.Collections; @@ -56,12 +44,28 @@ import java.util.TreeSet; import java.util.stream.Stream; -import static at.ac.tuwien.kr.alpha.Util.entriesToMap; -import static at.ac.tuwien.kr.alpha.Util.entry; -import static at.ac.tuwien.kr.alpha.common.NoGood.headFirst; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; -import static java.util.Arrays.asList; -import static java.util.Collections.singleton; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.commons.AnswerSets; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.core.atoms.ChoiceAtom; +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.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.IntIterator; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; /** * Represents a small ASP program with choices {@code { aa :- not bb. bb :- not aa. }}. @@ -110,12 +114,12 @@ public class ChoiceGrounder implements Grounder { entry(ATOM_BR1, ATOM_DIS_BR1), entry(ATOM_BR2, ATOM_DIS_BR2) ).collect(entriesToMap()); - private static Atom atomAA = new BasicAtom(Predicate.getInstance("aa", 0)); - private static Atom atomBB = new BasicAtom(Predicate.getInstance("bb", 0)); - private static BasicRule ruleAA = new BasicRule(new NormalHead(atomAA), Collections.singletonList(new BasicAtom(Predicate.getInstance("bb", 0)).toLiteral(false))); - private static BasicRule ruleBB = new BasicRule(new NormalHead(atomBB), Collections.singletonList(new BasicAtom(Predicate.getInstance("aa", 0)).toLiteral(false))); - private static Atom rule1 = new RuleAtom(InternalRule.fromNormalRule(NormalRule.fromBasicRule(ruleAA)), new Substitution()); - private static Atom rule2 = new RuleAtom(InternalRule.fromNormalRule(NormalRule.fromBasicRule(ruleBB)), new Substitution()); + private static BasicAtom atomAA = Atoms.newBasicAtom(Predicates.getPredicate("aa", 0)); + private static BasicAtom atomBB = Atoms.newBasicAtom(Predicates.getPredicate("bb", 0)); + private static BasicRule ruleAA = new BasicRule(Heads.newNormalHead(atomAA), Collections.singletonList(Atoms.newBasicAtom(Predicates.getPredicate("bb", 0)).toLiteral(false))); + private static BasicRule ruleBB = new BasicRule(Heads.newNormalHead(atomBB), Collections.singletonList(Atoms.newBasicAtom(Predicates.getPredicate("aa", 0)).toLiteral(false))); + private static Atom rule1 = new RuleAtom(InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(ruleAA)), new BasicSubstitution()); + private static Atom rule2 = new RuleAtom(InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(ruleBB)), new BasicSubstitution()); private static Atom atomEnBR1 = ChoiceAtom.on(1); private static Atom atomEnBR2 = ChoiceAtom.on(2); private static Atom atomDisBR1 = ChoiceAtom.off(3); @@ -152,13 +156,13 @@ public AnswerSet assignmentToAnswerSet(Iterable trueAtoms) { // Add the atom instances Map> predicateInstances = new HashMap<>(); for (Predicate trueAtomPredicate : trueAtomPredicates) { - BasicAtom basicAtom = new BasicAtom(trueAtomPredicate); + BasicAtom basicAtom = Atoms.newBasicAtom(trueAtomPredicate); predicateInstances.put(trueAtomPredicate, new TreeSet<>(singleton(basicAtom))); } // Note: This grounder only deals with 0-ary predicates, i.e., every atom is a predicate and there is // only one predicate instance representing 0 terms. - return new BasicAnswerSet(trueAtomPredicates, predicateInstances); + return AnswerSets.newAnswerSet(trueAtomPredicates, predicateInstances); } @Override diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/DummyGrounder.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java similarity index 75% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/DummyGrounder.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java index 4ab84e0b2..669e6037f 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/DummyGrounder.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/DummyGrounder.java @@ -25,25 +25,14 @@ * 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.grounder; - -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.BasicAnswerSet; -import at.ac.tuwien.kr.alpha.common.IntIterator; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; +package at.ac.tuwien.kr.alpha.core.grounder; + +import static at.ac.tuwien.kr.alpha.commons.util.Util.entriesToMap; +import static at.ac.tuwien.kr.alpha.commons.util.Util.entry; +import static at.ac.tuwien.kr.alpha.core.common.NoGood.headFirst; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; +import static java.util.Collections.singleton; +import static java.util.Collections.singletonList; import java.util.Arrays; import java.util.Collections; @@ -55,12 +44,27 @@ import java.util.TreeSet; import java.util.stream.Stream; -import static at.ac.tuwien.kr.alpha.Util.entriesToMap; -import static at.ac.tuwien.kr.alpha.Util.entry; -import static at.ac.tuwien.kr.alpha.common.NoGood.headFirst; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.commons.AnswerSets; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +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.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.IntIterator; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; /** * Represents a small ASP program {@code { c :- a, b. a. b. }}. @@ -87,11 +91,11 @@ public class DummyGrounder implements Grounder { private final AtomStore atomStore; private final java.util.function.Predicate filter; private byte[] currentTruthValues = new byte[]{-2, -1, -1, -1, -1}; - private static Atom atomAA = new BasicAtom(Predicate.getInstance("a", 0)); - private static Atom atomBB = new BasicAtom(Predicate.getInstance("b", 0)); - private static Atom atomCC = new BasicAtom(Predicate.getInstance("c", 0)); - private static BasicRule ruleABC = new BasicRule(new NormalHead(atomCC), Arrays.asList(atomAA.toLiteral(), atomBB.toLiteral())); - private static Atom rule1 = new RuleAtom(InternalRule.fromNormalRule(NormalRule.fromBasicRule(ruleABC)), new Substitution()); + private static Atom atomAA = Atoms.newBasicAtom(Predicates.getPredicate("a", 0)); + private static Atom atomBB = Atoms.newBasicAtom(Predicates.getPredicate("b", 0)); + private static BasicAtom atomCC = Atoms.newBasicAtom(Predicates.getPredicate("c", 0)); + private static BasicRule ruleABC = new BasicRule(Heads.newNormalHead(atomCC), Arrays.asList(atomAA.toLiteral(), atomBB.toLiteral())); + private static Atom rule1 = new RuleAtom(InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(ruleABC)), new BasicSubstitution()); private Set returnedNogoods = new HashSet<>(); public DummyGrounder(AtomStore atomStore) { @@ -142,11 +146,11 @@ public AnswerSet assignmentToAnswerSet(Iterable trueAtoms) { // Add the atom instances Map> predicateInstances = new HashMap<>(); for (Predicate trueAtomPredicate : trueAtomPredicates) { - BasicAtom internalBasicAtom = new BasicAtom(trueAtomPredicate); + BasicAtom internalBasicAtom = Atoms.newBasicAtom(trueAtomPredicate); predicateInstances.put(trueAtomPredicate, new TreeSet<>(singleton(internalBasicAtom))); } - return new BasicAnswerSet(trueAtomPredicates, predicateInstances); + return AnswerSets.newAnswerSet(trueAtomPredicates, predicateInstances); } @Override diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/IndexedInstanceStorageTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/IndexedInstanceStorageTest.java similarity index 84% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/IndexedInstanceStorageTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/IndexedInstanceStorageTest.java index 6e40f42a5..8e29122e6 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/IndexedInstanceStorageTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/IndexedInstanceStorageTest.java @@ -25,7 +25,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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -36,8 +36,10 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; /** * Copyright (c) 2016, the Alpha Team. @@ -45,15 +47,15 @@ public class IndexedInstanceStorageTest { @Test public void testIndexedInstanceStorage() { - IndexedInstanceStorage storage = new IndexedInstanceStorage(Predicate.getInstance("p", 4), true); + IndexedInstanceStorage storage = new IndexedInstanceStorage(Predicates.getPredicate("p", 4), true); storage.addIndexPosition(0); storage.addIndexPosition(2); - ConstantTerm t0 = ConstantTerm.getInstance("0"); - ConstantTerm t1 = ConstantTerm.getInstance("1"); - ConstantTerm t2 = ConstantTerm.getInstance("2"); - ConstantTerm t3 = ConstantTerm.getInstance("3"); - ConstantTerm t4 = ConstantTerm.getInstance("4"); - ConstantTerm t5 = ConstantTerm.getInstance("5"); + ConstantTerm t0 = Terms.newConstant("0"); + ConstantTerm t1 = Terms.newConstant("1"); + ConstantTerm t2 = Terms.newConstant("2"); + ConstantTerm t3 = Terms.newConstant("3"); + ConstantTerm t4 = Terms.newConstant("4"); + ConstantTerm t5 = Terms.newConstant("5"); Instance badInst1 = new Instance(t1, t1, t0); Instance badInst2 = new Instance(t5, t5, t5, t5, t5); @@ -95,4 +97,4 @@ public void testIndexedInstanceStorage() { assertEquals(matching1.size(), 0); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/NaiveGrounderTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounderTest.java similarity index 66% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/NaiveGrounderTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounderTest.java index 07acca9d0..4321d27da 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/NaiveGrounderTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/NaiveGrounderTest.java @@ -23,42 +23,50 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.atom; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.atom; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration; -import at.ac.tuwien.kr.alpha.grounder.instantiation.BindingResult; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramPartParser; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +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.Assignment; +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 at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.programs.transformation.StratifiedEvaluation; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; /** * Tests {@link NaiveGrounder} @@ -69,8 +77,10 @@ * If unit tests in this class begin to fail due to such improvements to preprocessing, this issue must be addressed. */ public class NaiveGrounderTest { - private static final ProgramParser PROGRAM_PARSER = new ProgramParser(); + private static final ProgramParser PROGRAM_PARSER = new ProgramParserImpl(); private static final ProgramPartParser PROGRAM_PART_PARSER = new ProgramPartParser(); + private static final NormalizeProgramTransformation NORMALIZE_TRANSFORM = new NormalizeProgramTransformation( + SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); final Literal litP1X = PROGRAM_PART_PARSER.parseLiteral("p1(X)"); final Literal litP2X = PROGRAM_PART_PARSER.parseLiteral("p2(X)"); @@ -90,13 +100,12 @@ public void resetRuleIdGenerator() { */ @Test public void groundRuleAlreadyGround() { - Alpha system = new Alpha(); - InputProgram program = PROGRAM_PARSER.parse("a :- not b. " + ASPCore2Program program = PROGRAM_PARSER.parse("a :- not b. " + "b :- not a. " + "c :- b."); - NormalProgram normal = system.normalizeProgram(program); - InternalProgram prog = system.performProgramPreprocessing(InternalProgram.fromNormalProgram(normal)); - + NormalProgram normal = NORMALIZE_TRANSFORM.apply(program); + CompiledProgram prog = new StratifiedEvaluation().apply(AnalyzedProgram.analyzeNormalProgram(normal)); + AtomStore atomStore = new AtomStoreImpl(); Grounder grounder = GrounderFactory.getInstance("naive", prog, atomStore, true); Map noGoods = grounder.getNoGoods(new TrailAssignment(atomStore)); @@ -112,14 +121,13 @@ public void groundRuleAlreadyGround() { */ @Test public void groundRuleWithLongerBodyAlreadyGround() { - Alpha system = new Alpha(); - InputProgram program = PROGRAM_PARSER.parse("a :- not b. " + ASPCore2Program program = PROGRAM_PARSER.parse("a :- not b. " + "b :- not a. " + "c :- b. " + "d :- b, c. "); - NormalProgram normal = system.normalizeProgram(program); - InternalProgram prog = system.performProgramPreprocessing(InternalProgram.fromNormalProgram(normal)); - + NormalProgram normal = NORMALIZE_TRANSFORM.apply(program); + InternalProgram prog = new StratifiedEvaluation().apply(AnalyzedProgram.analyzeNormalProgram(normal)); + AtomStore atomStore = new AtomStoreImpl(); Grounder grounder = GrounderFactory.getInstance("naive", prog, atomStore, true); Map noGoods = grounder.getNoGoods(new TrailAssignment(atomStore)); @@ -139,13 +147,12 @@ public void groundRuleWithLongerBodyAlreadyGround() { */ @Test public void groundConstraintAlreadyGround() { - Alpha system = new Alpha(); - InputProgram program = PROGRAM_PARSER.parse("a :- not b. " + ASPCore2Program program = PROGRAM_PARSER.parse("a :- not b. " + "b :- not a. " + ":- b."); - NormalProgram normal = system.normalizeProgram(program); - InternalProgram prog = system.performProgramPreprocessing(InternalProgram.fromNormalProgram(normal)); - + NormalProgram normal = NORMALIZE_TRANSFORM.apply(program); + InternalProgram prog = new StratifiedEvaluation().apply(AnalyzedProgram.analyzeNormalProgram(normal)); + AtomStore atomStore = new AtomStoreImpl(); Grounder grounder = GrounderFactory.getInstance("naive", prog, atomStore, true); Map noGoods = grounder.getNoGoods(new TrailAssignment(atomStore)); @@ -155,34 +162,35 @@ public void groundConstraintAlreadyGround() { @Test public void avoidDeadEndsWithPermissiveGrounderHeuristicForP1() { - RuleGroundingOrder groundingOrderP1 = new RuleGroundingOrder(litP1X, + RuleGroundingOrderImpl groundingOrderP1 = new RuleGroundingOrderImpl(litP1X, Arrays.asList(litP2X, litQ2Y, litQ1Y), -1, false); testDeadEnd("p1", groundingOrderP1, true); } @Test public void avoidDeadEndsWithPermissiveGrounderHeuristicForQ1() { - RuleGroundingOrder groundingOrderQ1 = new RuleGroundingOrder(litQ1Y, + RuleGroundingOrderImpl groundingOrderQ1 = new RuleGroundingOrderImpl(litQ1Y, Arrays.asList(litQ2Y, litP2X, litP1X), -1, false); testDeadEnd("q1", groundingOrderQ1, true); } @Test public void noDeadEndWithPermissiveGrounderHeuristicForP1() { - RuleGroundingOrder groundingOrderP1 = new RuleGroundingOrder(litP1X, + RuleGroundingOrderImpl groundingOrderP1 = new RuleGroundingOrderImpl(litP1X, Arrays.asList(litP2X, litQ1Y, litQ2Y), -1, false); testDeadEnd("p1", groundingOrderP1, true); } @Test public void noDeadEndWithPermissiveGrounderHeuristicForQ1() { - RuleGroundingOrder groundingOrderQ1 = new RuleGroundingOrder(litQ1Y, + RuleGroundingOrderImpl groundingOrderQ1 = new RuleGroundingOrderImpl(litQ1Y, Arrays.asList(litQ2Y, litP1X, litP2X), -1, false); testDeadEnd("q1", groundingOrderQ1, true); } /** - * Tests the method {@link NaiveGrounder#getGroundInstantiations(InternalRule, RuleGroundingOrder, Substitution, Assignment)} on a predefined program: + * Tests the method {@link NaiveGrounder#getGroundInstantiations(InternalRule, RuleGroundingOrder, Substitution, Assignment)} on a + * predefined program: * * p1(1). q1(1).
    * x :- p1(X), p2(X), q1(Y), q2(Y).
    @@ -195,35 +203,33 @@ public void noDeadEndWithPermissiveGrounderHeuristicForQ1() { * It is then asserted that ground instantiations are produced if and only if {@code expectNoGoods} is true. * * @param predicateNameOfStartingLiteral the predicate name of the starting literal, either "p1" or "q1". - * @param groundingOrder a grounding order for the first rule in the predefined program that starts with the literal - * whose predicate name is {@code predicateNameOfStartingLiteral}. - * @param expectNoGoods {@code true} iff ground instantiations are expected to be produced under the conditions - * described above. + * @param groundingOrder a grounding order for the first rule in the predefined program that starts with the literal + * whose predicate name is {@code predicateNameOfStartingLiteral}. + * @param expectNoGoods {@code true} iff ground instantiations are expected to be produced under the conditions + * described above. */ - private void testDeadEnd(String predicateNameOfStartingLiteral, RuleGroundingOrder groundingOrder, boolean expectNoGoods) { + private void testDeadEnd(String predicateNameOfStartingLiteral, RuleGroundingOrderImpl groundingOrder, boolean expectNoGoods) { String aspStr = "p1(1). q1(1). " + "x :- p1(X), p2(X), q1(Y), q2(Y). " + "p2(X) :- something(X). " + "q2(X) :- something(X). "; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram program = InternalProgram.fromNormalProgram( - system.normalizeProgram( - system.readProgramString(aspStr) - ) - ); + CompiledProgram program = InternalProgram.fromNormalProgram( + NORMALIZE_TRANSFORM.apply( + PROGRAM_PARSER.parse(aspStr))); AtomStore atomStore = new AtomStoreImpl(); - NaiveGrounder grounder = (NaiveGrounder) GrounderFactory.getInstance("naive", program, atomStore, p -> true, GrounderHeuristicsConfiguration.permissive(), true); + NaiveGrounder grounder = (NaiveGrounder) GrounderFactory.getInstance("naive", program, atomStore, p -> true, + GrounderHeuristicsConfiguration.permissive(), true); - InternalRule nonGroundRule = grounder.getNonGroundRule(0); + CompiledRule nonGroundRule = grounder.getNonGroundRule(0); String strLiteral = "p1".equals(predicateNameOfStartingLiteral) ? "p1(X)" : "p1(Y)"; final Literal startingLiteral = PROGRAM_PART_PARSER.parseLiteral(strLiteral); - nonGroundRule.getGroundingOrders().groundingOrders.put(startingLiteral, groundingOrder); + ((RuleGroundingInfoImpl) nonGroundRule.getGroundingInfo()).groundingOrders.put(startingLiteral, groundingOrder); grounder.bootstrap(); TrailAssignment currentAssignment = new TrailAssignment(atomStore); - final Substitution subst1 = Substitution.specializeSubstitution(startingLiteral, new Instance(ConstantTerm.getInstance(1)), Substitution.EMPTY_SUBSTITUTION); + final Substitution subst1 = BasicSubstitution.specializeSubstitution(startingLiteral, new Instance(Terms.newConstant(1)), + BasicSubstitution.EMPTY_SUBSTITUTION); final BindingResult bindingResult = grounder.getGroundInstantiations(nonGroundRule, groundingOrder, subst1, currentAssignment); assertEquals(expectNoGoods, bindingResult.size() > 0); @@ -231,7 +237,7 @@ private void testDeadEnd(String predicateNameOfStartingLiteral, RuleGroundingOrd @Test public void testGroundingOfRuleSwitchedOffByFalsePositiveBody() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X). " + "b(X) :- something(X). "); testIfGrounderGroundsRule(program, 0, litAX, 1, ThriceTruth.FALSE, false); @@ -239,7 +245,7 @@ public void testGroundingOfRuleSwitchedOffByFalsePositiveBody() { @Test public void testGroundingOfRuleNotSwitchedOffByTruePositiveBody() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X). " + "b(X) :- something(X). "); testIfGrounderGroundsRule(program, 0, litAX, 1, ThriceTruth.TRUE, true); @@ -248,7 +254,7 @@ public void testGroundingOfRuleNotSwitchedOffByTruePositiveBody() { @Test @Disabled("Currently, rule grounding is not switched off by a true negative body atom") public void testGroundingOfRuleSwitchedOffByTrueNegativeBody() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), not b(X). " + "b(X) :- something(X). "); testIfGrounderGroundsRule(program, 0, litAX, 1, ThriceTruth.TRUE, false); @@ -256,7 +262,7 @@ public void testGroundingOfRuleSwitchedOffByTrueNegativeBody() { @Test public void testGroundingOfRuleNotSwitchedOffByFalseNegativeBody() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), not b(X). " + "b(X) :- something(X). "); @@ -270,44 +276,46 @@ public void testGroundingOfRuleNotSwitchedOffByFalseNegativeBody() { * {@code bTruth}. * It is asserted that ground instantiations are produced if and only if {@code expectNoGoods} is true. */ - private void testIfGrounderGroundsRule(InputProgram program, int ruleID, Literal startingLiteral, int startingInstance, ThriceTruth bTruth, boolean expectNoGoods) { - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(program)); + private void testIfGrounderGroundsRule(ASPCore2Program program, int ruleID, Literal startingLiteral, int startingInstance, ThriceTruth bTruth, + boolean expectNoGoods) { + CompiledProgram internalPrg = InternalProgram.fromNormalProgram(NORMALIZE_TRANSFORM.apply(program)); AtomStore atomStore = new AtomStoreImpl(); TrailAssignment currentAssignment = new TrailAssignment(atomStore); - NaiveGrounder grounder = (NaiveGrounder) GrounderFactory.getInstance("naive", internalPrg, atomStore, p -> true, GrounderHeuristicsConfiguration.permissive(), true); + NaiveGrounder grounder = (NaiveGrounder) GrounderFactory.getInstance("naive", internalPrg, atomStore, p -> true, + GrounderHeuristicsConfiguration.permissive(), true); int b = atomStore.putIfAbsent(atom("b", 1)); currentAssignment.growForMaxAtomId(); currentAssignment.assign(b, bTruth); grounder.bootstrap(); - final InternalRule nonGroundRule = grounder.getNonGroundRule(ruleID); - final Substitution substStartingLiteral = Substitution.specializeSubstitution(startingLiteral, new Instance(ConstantTerm.getInstance(startingInstance)), Substitution.EMPTY_SUBSTITUTION); - final BindingResult bindingResult = grounder.getGroundInstantiations(nonGroundRule, nonGroundRule.getGroundingOrders().groundingOrders.get(startingLiteral), substStartingLiteral, currentAssignment); + final CompiledRule nonGroundRule = grounder.getNonGroundRule(ruleID); + final Substitution substStartingLiteral = BasicSubstitution.specializeSubstitution(startingLiteral, new Instance(Terms.newConstant(startingInstance)), + BasicSubstitution.EMPTY_SUBSTITUTION); + final BindingResult bindingResult = grounder.getGroundInstantiations(nonGroundRule, nonGroundRule.getGroundingInfo().orderStartingFrom(startingLiteral), + substStartingLiteral, currentAssignment); assertEquals(expectNoGoods, bindingResult.size() > 0); } - + @Test public void testPermissiveGrounderHeuristicTolerance_0_reject() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X). " + "b(X) :- something(X)."); testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 0, false, Arrays.asList(1)); } - + @Test public void testPermissiveGrounderHeuristicTolerance_1_accept() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X). " + "b(X) :- something(X)."); testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 1, true, Arrays.asList(1)); } - + @Test public void testPermissiveGrounderHeuristicTolerance_1_reject() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X), b(X+1). " + "b(X) :- something(X)."); testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 1, false, Arrays.asList(2)); @@ -315,7 +323,7 @@ public void testPermissiveGrounderHeuristicTolerance_1_reject() { @Test public void testPermissiveGrounderHeuristicTolerance_2_accept() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X), b(X+1). " + "b(X) :- something(X)."); testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 2, true, Arrays.asList(2)); @@ -323,23 +331,24 @@ public void testPermissiveGrounderHeuristicTolerance_2_accept() { @Test public void testPermissiveGrounderHeuristicTolerance_1_accept_two_substitutions() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X,Y). " + "b(X,Y) :- something(X,Y)."); - testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 1, new ThriceTruth[] {TRUE, TRUE}, 2, true, Arrays.asList(0, 0)); + testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 1, new ThriceTruth[] {ThriceTruth.TRUE, ThriceTruth.TRUE }, 2, true, + Arrays.asList(0, 0)); } @Test public void testPermissiveGrounderHeuristicTolerance_1_accept_accept_two_substitutions_with_different_remaining_tolerances() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(1), b(X,Y). " + "b(X,Y) :- something(X,Y)."); - testPermissiveGrounderHeuristicTolerance(program, 0, litA1, 1, 1, new ThriceTruth[] {null, null}, 2, true, Arrays.asList(1, 1)); + testPermissiveGrounderHeuristicTolerance(program, 0, litA1, 1, 1, new ThriceTruth[] {null, null }, 2, true, Arrays.asList(1, 1)); } @Test public void testPermissiveGrounderHeuristicTolerance_2_reject() { - InputProgram program = PROGRAM_PARSER.parse("a(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). " + "c(X) :- a(X), b(X), b(X+1), b(X+2). " + "b(X) :- something(X)."); testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 2, false, Arrays.asList(3)); @@ -347,14 +356,16 @@ public void testPermissiveGrounderHeuristicTolerance_2_reject() { @Test public void testPermissiveGrounderHeuristicTolerance_2_accept_multiple_facts_of_same_variable() { - InputProgram program = PROGRAM_PARSER.parse("a(1). b(1). " + ASPCore2Program program = PROGRAM_PARSER.parse("a(1). b(1). " + "c(X) :- a(X), b(X), b(X+1), b(X+2). " + "b(X) :- something(X)."); testPermissiveGrounderHeuristicTolerance(program, 0, litAX, 1, 2, true, Arrays.asList(2)); } - private void testPermissiveGrounderHeuristicTolerance(InputProgram program, int ruleID, Literal startingLiteral, int startingInstance, int tolerance, boolean expectNoGoods, List expectedNumbersOfUnassignedPositiveBodyAtoms) { - testPermissiveGrounderHeuristicTolerance(program, ruleID, startingLiteral, startingInstance, tolerance, new ThriceTruth[]{}, 1, expectNoGoods, expectedNumbersOfUnassignedPositiveBodyAtoms); + private void testPermissiveGrounderHeuristicTolerance(ASPCore2Program program, int ruleID, Literal startingLiteral, int startingInstance, int tolerance, + boolean expectNoGoods, List expectedNumbersOfUnassignedPositiveBodyAtoms) { + testPermissiveGrounderHeuristicTolerance(program, ruleID, startingLiteral, startingInstance, tolerance, new ThriceTruth[] {}, 1, expectNoGoods, + expectedNumbersOfUnassignedPositiveBodyAtoms); } /** @@ -363,22 +374,21 @@ private void testPermissiveGrounderHeuristicTolerance(InputProgram program, int * unified with the numeric instance {@code startingInstance} is used as starting literal and the following * additional conditions are established: *
      - *
    • The atoms {@code b([startingInstance], 1), ..., b([startingInstance], n)} are added to the grounder's - * working memory without changing the assignment, where {@code arityOfB-1} occurences of {@code startingInstance} - * are used instead of {@code [startingInstance]} and {@code n} is the length of the {@code truthsOfB} array. - * For example, if the length of {@code truthsOfB} is 2 and {@code arityOfB} is also 2, these atoms are - * {@code b(1,1), b(1,2)}. - *
    • - *
    • The same atoms are assigned the truth values in the {@code truthsOfB} array.
    • + *
    • The atoms {@code b([startingInstance], 1), ..., b([startingInstance], n)} are added to the grounder's + * working memory without changing the assignment, where {@code arityOfB-1} occurences of {@code startingInstance} + * are used instead of {@code [startingInstance]} and {@code n} is the length of the {@code truthsOfB} array. + * For example, if the length of {@code truthsOfB} is 2 and {@code arityOfB} is also 2, these atoms are + * {@code b(1,1), b(1,2)}. + *
    • + *
    • The same atoms are assigned the truth values in the {@code truthsOfB} array.
    • *
    * It is asserted that ground instantiations are produced if and only if {@code expectNoGoods} is true. * If ground instantiations are produced, it is also asserted that the numbers of unassigned positive body atoms * determined by {@code getGroundInstantiations} match those given in {@code expectedNumbersOfUnassignedPositiveBodyAtoms}. */ - private void testPermissiveGrounderHeuristicTolerance(InputProgram program, int ruleID, Literal startingLiteral, int startingInstance, int tolerance, ThriceTruth[] truthsOfB, int arityOfB, boolean expectNoGoods, List expectedNumbersOfUnassignedPositiveBodyAtoms) { - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(program)); + private void testPermissiveGrounderHeuristicTolerance(ASPCore2Program program, int ruleID, Literal startingLiteral, int startingInstance, int tolerance, + ThriceTruth[] truthsOfB, int arityOfB, boolean expectNoGoods, List expectedNumbersOfUnassignedPositiveBodyAtoms) { + CompiledProgram internalPrg = InternalProgram.fromNormalProgram(NORMALIZE_TRANSFORM.apply(program)); AtomStore atomStore = new AtomStoreImpl(); TrailAssignment currentAssignment = new TrailAssignment(atomStore); GrounderHeuristicsConfiguration heuristicConfiguration = GrounderHeuristicsConfiguration.getInstance(tolerance, tolerance); @@ -396,9 +406,11 @@ private void testPermissiveGrounderHeuristicTolerance(InputProgram program, int assign(currentAssignment, bAtomIDs, truthsOfB); grounder.bootstrap(); - final InternalRule nonGroundRule = grounder.getNonGroundRule(ruleID); - final Substitution substStartingLiteral = Substitution.specializeSubstitution(startingLiteral, new Instance(ConstantTerm.getInstance(startingInstance)), Substitution.EMPTY_SUBSTITUTION); - final BindingResult bindingResult = grounder.getGroundInstantiations(nonGroundRule, nonGroundRule.getGroundingOrders().groundingOrders.get(startingLiteral), substStartingLiteral, currentAssignment); + final CompiledRule nonGroundRule = grounder.getNonGroundRule(ruleID); + final Substitution substStartingLiteral = BasicSubstitution.specializeSubstitution(startingLiteral, new Instance(Terms.newConstant(startingInstance)), + BasicSubstitution.EMPTY_SUBSTITUTION); + final BindingResult bindingResult = grounder.getGroundInstantiations(nonGroundRule, nonGroundRule.getGroundingInfo().orderStartingFrom(startingLiteral), + substStartingLiteral, currentAssignment); assertEquals(expectNoGoods, bindingResult.size() > 0); if (bindingResult.size() > 0) { assertEquals(expectedNumbersOfUnassignedPositiveBodyAtoms, bindingResult.getNumbersOfUnassignedPositiveBodyAtoms()); @@ -429,7 +441,7 @@ private void addAtomsToWorkingMemoryWithoutChangingTheAssignment(AtomStore atomS TrailAssignment temporaryAssignment = new TrailAssignment(atomStore); temporaryAssignment.growForMaxAtomId(); for (int b : atomIDs) { - temporaryAssignment.assign(b, TRUE); + temporaryAssignment.assign(b, ThriceTruth.TRUE); } grounder.updateAssignment(temporaryAssignment.getNewPositiveAssignmentsIterator()); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/NoGoodGeneratorTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGeneratorTest.java similarity index 53% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/NoGoodGeneratorTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGeneratorTest.java index 0479c42ae..e5d44ded9 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/NoGoodGeneratorTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/NoGoodGeneratorTest.java @@ -23,38 +23,47 @@ * 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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +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.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.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; /** * Tests {@link NoGoodGenerator} */ public class NoGoodGeneratorTest { - private static final ProgramParser PARSER = new ProgramParser(); + private static final ProgramParser PARSER = new ProgramParserImpl(); + private static final NormalizeProgramTransformation NORMALIZE_TRANSFORM = new NormalizeProgramTransformation( + SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); - private static final ConstantTerm A = ConstantTerm.getSymbolicInstance("a"); - private static final ConstantTerm B = ConstantTerm.getSymbolicInstance("b"); + private static final ConstantTerm A = Terms.newSymbolicConstant("a"); + private static final ConstantTerm B = Terms.newSymbolicConstant("b"); - private static final VariableTerm X = VariableTerm.getInstance("X"); - private static final VariableTerm Y = VariableTerm.getInstance("Y"); + private static final VariableTerm X = Terms.newVariable("X"); + private static final VariableTerm Y = Terms.newVariable("Y"); /** * Calls {@link NoGoodGenerator#collectNegLiterals(InternalRule, Substitution)}, which puts the atom occurring @@ -62,23 +71,22 @@ public class NoGoodGeneratorTest { */ @Test public void collectNeg_ContainsOnlyPositiveLiterals() { - Alpha system = new Alpha(); - InputProgram input = PARSER.parse("p(a,b). " - + "q(a,b) :- not nq(a,b). " + ASPCore2Program input = PARSER.parse("p(a,b). " + + "q(a,b) :- not nq(a,b). " + "nq(a,b) :- not q(a,b)."); - NormalProgram normal = system.normalizeProgram(input); - InternalProgram program = InternalProgram.fromNormalProgram(normal); + NormalProgram normal = NORMALIZE_TRANSFORM.apply(input); + CompiledProgram program = InternalProgram.fromNormalProgram(normal); - InternalRule rule = program.getRules().get(1); + CompiledRule rule = program.getRules().get(1); AtomStore atomStore = new AtomStoreImpl(); Grounder grounder = GrounderFactory.getInstance("naive", program, atomStore, true); NoGoodGenerator noGoodGenerator = ((NaiveGrounder) grounder).noGoodGenerator; - Substitution substitution = new Substitution(); + Substitution substitution = new BasicSubstitution(); substitution.put(X, A); substitution.put(Y, B); List collectedNeg = noGoodGenerator.collectNegLiterals(rule, substitution); assertEquals(1, collectedNeg.size()); - String negAtomString = atomStore.atomToString(atomOf(collectedNeg.get(0))); + String negAtomString = atomStore.atomToString(Literals.atomOf(collectedNeg.get(0))); assertEquals("q(a, b)", negAtomString); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrderTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrderTest.java similarity index 56% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrderTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrderTest.java index c512ff0d3..b8964e9b6 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/RuleGroundingOrderTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/RuleGroundingOrderTest.java @@ -25,83 +25,85 @@ * 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.grounder; - - +package at.ac.tuwien.kr.alpha.core.grounder; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.util.function.Function; + import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramPartParser; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; /** * Copyright (c) 2017-2019, the Alpha Team. */ public class RuleGroundingOrderTest { - private static final ProgramPartParser PROGRAM_PART_PARSER = new ProgramPartParser(); + private static final ProgramParser PARSER = new ProgramParserImpl(); + private static final NormalizeProgramTransformation NORMALIZE_TRANSFORM = new NormalizeProgramTransformation( + SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); + private static final Function PARSE_AND_PREPROCESS = (str) -> { + return InternalProgram.fromNormalProgram(NORMALIZE_TRANSFORM.apply(PARSER.parse(str))); + }; + private static final ProgramPartParser PROGRAM_PART_PARSER = new ProgramPartParser(); @Test public void groundingOrder() { String aspStr = "h(X,C) :- p(X,Y), q(A,B), r(Y,A), s(C)." + "j(A,B,X,Y) :- r1(A,B), r1(X,Y), r1(A,X), r1(B,Y), A = B." + "p(a) :- b = a."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - InternalRule rule0 = internalPrg.getRules().get(0); - RuleGroundingOrders rgo0 = new RuleGroundingOrders(rule0); + CompiledProgram prog = PARSE_AND_PREPROCESS.apply(aspStr); + CompiledRule rule0 = prog.getRules().get(0); + RuleGroundingInfo rgo0 = new RuleGroundingInfoImpl(rule0); rgo0.computeGroundingOrders(); assertEquals(4, rgo0.getStartingLiterals().size()); - InternalRule rule1 = internalPrg.getRules().get(1); - RuleGroundingOrders rgo1 = new RuleGroundingOrders(rule1); + CompiledRule rule1 = prog.getRules().get(1); + RuleGroundingInfo rgo1 = new RuleGroundingInfoImpl(rule1); rgo1.computeGroundingOrders(); assertEquals(4, rgo1.getStartingLiterals().size()); - InternalRule rule2 = internalPrg.getRules().get(2); - RuleGroundingOrders rgo2 = new RuleGroundingOrders(rule2); + CompiledRule rule2 = prog.getRules().get(2); + RuleGroundingInfo rgo2 = new RuleGroundingInfoImpl(rule2); rgo2.computeGroundingOrders(); - assertTrue(rgo2.fixedInstantiation()); + assertTrue(rgo2.hasFixedInstantiation()); } @Test public void groundingOrderUnsafe() { assertThrows(RuntimeException.class, () -> { String aspStr = "h(X,C) :- X = Y, Y = C .. 3, C = X."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - computeGroundingOrdersForRule(internalPrg, 0); + CompiledProgram prog = PARSE_AND_PREPROCESS.apply(aspStr); + computeGroundingOrdersForRule(prog, 0); }); } - + @Test public void testPositionFromWhichAllVarsAreBound_ground() { String aspStr = "a :- b, not c."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - RuleGroundingOrders rgo0 = computeGroundingOrdersForRule(internalPrg, 0); + CompiledProgram internalPrg = PARSE_AND_PREPROCESS.apply(aspStr); + RuleGroundingInfo rgo0 = computeGroundingOrdersForRule(internalPrg, 0); assertEquals(0, rgo0.getFixedGroundingOrder().getPositionFromWhichAllVarsAreBound()); } - + @Test public void testPositionFromWhichAllVarsAreBound_simpleNonGround() { String aspStr = "a(X) :- b(X), not c(X)."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - RuleGroundingOrders rgo0 = computeGroundingOrdersForRule(internalPrg, 0); + CompiledProgram internalPrg = PARSE_AND_PREPROCESS.apply(aspStr); + RuleGroundingInfo rgo0 = computeGroundingOrdersForRule(internalPrg, 0); assertEquals(1, rgo0.getStartingLiterals().size()); for (Literal startingLiteral : rgo0.getStartingLiterals()) { assertEquals(0, rgo0.orderStartingFrom(startingLiteral).getPositionFromWhichAllVarsAreBound()); @@ -111,10 +113,8 @@ public void testPositionFromWhichAllVarsAreBound_simpleNonGround() { @Test public void testPositionFromWhichAllVarsAreBound_longerSimpleNonGround() { String aspStr = "a(X) :- b(X), c(X), d(X), not e(X)."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - RuleGroundingOrders rgo0 = computeGroundingOrdersForRule(internalPrg, 0); + CompiledProgram internalPrg = PARSE_AND_PREPROCESS.apply(aspStr); + RuleGroundingInfo rgo0 = computeGroundingOrdersForRule(internalPrg, 0); assertEquals(3, rgo0.getStartingLiterals().size()); for (Literal startingLiteral : rgo0.getStartingLiterals()) { assertEquals(0, rgo0.orderStartingFrom(startingLiteral).getPositionFromWhichAllVarsAreBound()); @@ -124,17 +124,22 @@ public void testPositionFromWhichAllVarsAreBound_longerSimpleNonGround() { @Test public void testToString_longerSimpleNonGround() { String aspStr = "a(X) :- b(X), c(X), d(X), not e(X)."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - RuleGroundingOrders rgo0 = computeGroundingOrdersForRule(internalPrg, 0); + CompiledProgram internalPrg = PARSE_AND_PREPROCESS.apply(aspStr); + RuleGroundingInfo rgo0 = computeGroundingOrdersForRule(internalPrg, 0); assertEquals(3, rgo0.getStartingLiterals().size()); for (Literal startingLiteral : rgo0.getStartingLiterals()) { switch (startingLiteral.getPredicate().getName()) { - case "b": assertEquals("b(X) : | c(X), d(X), not e(X)", rgo0.orderStartingFrom(startingLiteral).toString()); break; - case "c": assertEquals("c(X) : | b(X), d(X), not e(X)", rgo0.orderStartingFrom(startingLiteral).toString()); break; - case "d": assertEquals("d(X) : | b(X), c(X), not e(X)", rgo0.orderStartingFrom(startingLiteral).toString()); break; - default: fail("Unexpected starting literal: " + startingLiteral); + case "b": + assertEquals("b(X) : | c(X), d(X), not e(X)", rgo0.orderStartingFrom(startingLiteral).toString()); + break; + case "c": + assertEquals("c(X) : | b(X), d(X), not e(X)", rgo0.orderStartingFrom(startingLiteral).toString()); + break; + case "d": + assertEquals("d(X) : | b(X), c(X), not e(X)", rgo0.orderStartingFrom(startingLiteral).toString()); + break; + default: + fail("Unexpected starting literal: " + startingLiteral); } } } @@ -142,11 +147,9 @@ public void testToString_longerSimpleNonGround() { @Test public void testPositionFromWhichAllVarsAreBound_joinedNonGround() { String aspStr = "a(X) :- b(X), c(X,Y), d(X,Z), not e(X)."; - Alpha system = new Alpha(); - system.getConfig().setEvaluateStratifiedPart(false); - InternalProgram internalPrg = InternalProgram.fromNormalProgram(system.normalizeProgram(system.readProgramString(aspStr))); - RuleGroundingOrders rgo0 = computeGroundingOrdersForRule(internalPrg, 0); -final Literal litBX = PROGRAM_PART_PARSER.parseLiteral("b(X)"); + CompiledProgram internalPrg = PARSE_AND_PREPROCESS.apply(aspStr); + RuleGroundingInfo rgo0 = computeGroundingOrdersForRule(internalPrg, 0); + final Literal litBX = PROGRAM_PART_PARSER.parseLiteral("b(X)"); final Literal litCXY = PROGRAM_PART_PARSER.parseLiteral("c(X,Y)"); final Literal litDXZ = PROGRAM_PART_PARSER.parseLiteral("d(X,Z)"); assertTrue(2 <= rgo0.orderStartingFrom(litBX).getPositionFromWhichAllVarsAreBound()); @@ -154,9 +157,9 @@ public void testPositionFromWhichAllVarsAreBound_joinedNonGround() { assertTrue(1 <= rgo0.orderStartingFrom(litDXZ).getPositionFromWhichAllVarsAreBound()); } - private RuleGroundingOrders computeGroundingOrdersForRule(InternalProgram program, int ruleIndex) { - InternalRule rule = program.getRules().get(ruleIndex); - RuleGroundingOrders rgo = new RuleGroundingOrders(rule); + private RuleGroundingInfo computeGroundingOrdersForRule(CompiledProgram program, int ruleIndex) { + CompiledRule rule = program.getRules().get(ruleIndex); + RuleGroundingInfo rgo = new RuleGroundingInfoImpl(rule); rgo.computeGroundingOrders(); return rgo; } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/RuleToStringTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/RuleToStringTest.java similarity index 76% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/RuleToStringTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/RuleToStringTest.java index e6f653a97..38f8db22a 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/RuleToStringTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/RuleToStringTest.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.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -31,17 +31,21 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; /** * Tests {@link BasicRule#toString()} and {@link InternalRule#toString()}. */ public class RuleToStringTest { - private final ProgramParser parser = new ProgramParser(); + private final ProgramParser parser = new ProgramParserImpl(); @Test public void positiveRuleToString() { @@ -84,19 +88,19 @@ public void nonGroundConstraintToString() { } private void parseSingleRuleAndCheckToString(String rule) { - BasicRule parsedRule = parseSingleRule(rule); + Rule parsedRule = parseSingleRule(rule); assertEquals(rule, parsedRule.toString()); } private void constructNonGroundRuleAndCheckToString(String textualRule) { - InternalRule nonGroundRule = InternalRule.fromNormalRule(NormalRule.fromBasicRule(parseSingleRule(textualRule))); + CompiledRule nonGroundRule = InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(parseSingleRule(textualRule))); assertEquals(textualRule, nonGroundRule.toString()); } - private BasicRule parseSingleRule(String rule) { - InputProgram program = parser.parse(rule); - List rules = program.getRules(); + private Rule parseSingleRule(String rule) { + ASPCore2Program program = parser.parse(rule); + List> rules = program.getRules(); assertEquals(1, rules.size(), "Number of rules"); return rules.get(0); } -} \ No newline at end of file +} diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/SubstitutionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/SubstitutionTest.java new file mode 100644 index 000000000..2fc8f87a2 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/SubstitutionTest.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2016-2018, 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.grounder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +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.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; +import at.ac.tuwien.kr.alpha.core.rules.NormalRuleImpl; +import at.ac.tuwien.kr.alpha.core.test.util.SubstitutionTestUtil; +import at.ac.tuwien.kr.alpha.core.util.Substitutions; + +public class SubstitutionTest { + private static final ProgramParser PARSER = new ProgramParserImpl(); + + private static final ConstantTerm A = Terms.newSymbolicConstant("a"); + private static final ConstantTerm B = Terms.newSymbolicConstant("b"); + private static final ConstantTerm C = Terms.newSymbolicConstant("c"); + + private static final VariableTerm X = Terms.newVariable("X"); + private static final VariableTerm Y = Terms.newVariable("Y"); + private static final BasicAtom PX = Atoms.newBasicAtom(Predicates.getPredicate("p", 1), X); + private static final BasicAtom PY = Atoms.newBasicAtom(Predicates.getPredicate("p", 1), Y); + private static final Instance PA = new Instance(A); + private static final Instance PB = new Instance(B); + + @Test + public void putSimpleBinding() { + Substitution substitution = new BasicSubstitution(); + substitution.put(Y, A); + assertEquals(A, substitution.eval(Y)); + } + + @Test + public void specializeTermsSimpleBinding() { + Substitution substitution = BasicSubstitution.specializeSubstitution(PY, PA, BasicSubstitution.EMPTY_SUBSTITUTION); + assertEquals(A, substitution.eval(Y)); + } + + @Test + public void specializeTermsFunctionTermBinding() { + Substitution substitution = new BasicSubstitution(); + substitution.put(Y, A); + + FunctionTerm groundFunctionTerm = Terms.newFunctionTerm("f", B, C); + Instance qfBC = new Instance(groundFunctionTerm); + Term nongroundFunctionTerm = Terms.newFunctionTerm("f", B, X); + BasicAtom qfBX = Atoms.newBasicAtom(Predicates.getPredicate("q", 1), nongroundFunctionTerm); + + Substitution substitution1 = BasicSubstitution.specializeSubstitution(qfBX, qfBC, substitution); + + assertEquals(C, substitution1.eval(X)); + assertEquals(A, substitution1.eval(Y)); + } + + @Test + public void substitutePositiveBasicAtom() { + substituteBasicAtomLiteral(false); + } + + @Test + public void substituteNegativeBasicAtom() { + substituteBasicAtomLiteral(true); + } + + @Test + public void groundAndPrintRule() { + Rule rule = PARSER.parse("x :- p(X,Y), not q(X,Y).").getRules().get(0); + CompiledRule nonGroundRule = InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(rule)); + Substitution substitution1 = BasicSubstitution.specializeSubstitution(PX, PA, BasicSubstitution.EMPTY_SUBSTITUTION); + Substitution substitution2 = BasicSubstitution.specializeSubstitution(PY, PB, substitution1); + String printedString = SubstitutionTestUtil.groundAndPrintRule(nonGroundRule, substitution2); + assertEquals("x :- p(a, b), not q(a, b).", printedString); + } + + @Test + public void specializeBasicAtom() { + Predicate p = Predicates.getPredicate("p", 2); + BasicAtom atom = Atoms.newBasicAtom(p, Arrays.asList(X, Y)); + Instance instance = new Instance(A, B); + Substitution substitution = BasicSubstitution.specializeSubstitution(atom, instance, BasicSubstitution.EMPTY_SUBSTITUTION); + BasicAtom substituted = atom.substitute(substitution); + assertEquals(p, substituted.getPredicate()); + assertEquals(A, substituted.getTerms().get(0)); + assertEquals(B, substituted.getTerms().get(1)); + } + + private void substituteBasicAtomLiteral(boolean negated) { + Predicate p = Predicates.getPredicate("p", 2); + BasicAtom atom = Atoms.newBasicAtom(p, Arrays.asList(X, Y)); + Literal literal = Literals.fromAtom(atom, !negated); + Substitution substitution = new BasicSubstitution(); + substitution.put(X, A); + substitution.put(Y, B); + literal = literal.substitute(substitution); + assertEquals(p, literal.getPredicate()); + assertEquals(A, literal.getTerms().get(0)); + assertEquals(B, literal.getTerms().get(1)); + assertEquals(negated, literal.isNegated()); + } + + @Test + public void groundLiteralToString_PositiveBasicAtom() { + groundLiteralToString(false); + } + + @Test + public void groundLiteralToString_NegativeBasicAtom() { + groundLiteralToString(true); + } + + private void groundLiteralToString(boolean negated) { + Predicate p = Predicates.getPredicate("p", 2); + BasicAtom atom = Atoms.newBasicAtom(p, Arrays.asList(X, Y)); + Substitution substitution1 = BasicSubstitution.specializeSubstitution(PX, PA, BasicSubstitution.EMPTY_SUBSTITUTION); + Substitution substitution = BasicSubstitution.specializeSubstitution(PY, PB, substitution1); + String printedString = SubstitutionTestUtil.groundLiteralToString(atom.toLiteral(!negated), substitution, true); + assertEquals((negated ? "not " : "") + "p(a, b)", printedString); + } + + @Test + public void substitutionFromString() { + Rule rule = PARSER.parse("x :- p(X,Y), not q(X,Y).").getRules().get(0); + CompiledRule nonGroundRule = InternalRule.fromNormalRule(NormalRuleImpl.fromBasicRule(rule)); + Substitution substitution1 = BasicSubstitution.specializeSubstitution(PX, PA, BasicSubstitution.EMPTY_SUBSTITUTION); + Substitution substitution = BasicSubstitution.specializeSubstitution(PY, PB, substitution1); + RuleAtom ruleAtom = new RuleAtom(nonGroundRule, substitution); + String substitutionString = (String) ((ConstantTerm) ruleAtom.getTerms().get(1)).getObject(); + Substitution fromString = Substitutions.fromString(substitutionString); + assertEquals(substitution, fromString); + } +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/UnificationTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/UnificationTest.java similarity index 81% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/UnificationTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/UnificationTest.java index 647696928..7492fc3d7 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/UnificationTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/UnificationTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -6,10 +6,10 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramPartParser; - +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.commons.substitutions.Unifier; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser; /** * Copyright (c) 2021, the Alpha Team. @@ -25,7 +25,7 @@ public void simpleGroundUnification() { Unifier unifier = Unification.unifyAtoms(pa, pX); assertNotNull(unifier); assertEquals(1, unifier.getMappedVariables().size()); - assertEquals("abc", unifier.eval(VariableTerm.getInstance("X")).toString()); + assertEquals("abc", unifier.eval(Terms.newVariable("X")).toString()); } @Test @@ -35,8 +35,8 @@ public void unificationBothSides() { Unifier unifier = Unification.unifyAtoms(left, right); assertNotNull(unifier); assertEquals(2, unifier.getMappedVariables().size()); - assertEquals("d", unifier.eval(VariableTerm.getInstance("X")).toString()); - assertEquals("1", unifier.eval(VariableTerm.getInstance("Y")).toString()); + assertEquals("d", unifier.eval(Terms.newVariable("X")).toString()); + assertEquals("1", unifier.eval(Terms.newVariable("Y")).toString()); } @Test @@ -46,14 +46,14 @@ public void unificationNonGround() { Unifier unifier = Unification.unifyAtoms(left, right); assertNotNull(unifier); assertEquals(3, unifier.getMappedVariables().size()); - assertEquals("13", unifier.eval(VariableTerm.getInstance("Y")).toString()); + assertEquals("13", unifier.eval(Terms.newVariable("Y")).toString()); // Check that the unifier sets X=Z by either mapping X -> Z or Z -> X. - if (unifier.eval(VariableTerm.getInstance("X")) != null) { + if (unifier.eval(Terms.newVariable("X")) != null) { // X is mapped, it must map to Z now. - assertEquals("Z", unifier.eval(VariableTerm.getInstance("X")).toString()); + assertEquals("Z", unifier.eval(Terms.newVariable("X")).toString()); } else { // X is not mapped, so Z must map to X. - assertEquals("X", unifier.eval(VariableTerm.getInstance("Z")).toString()); + assertEquals("X", unifier.eval(Terms.newVariable("Z")).toString()); } } @@ -108,4 +108,4 @@ public void nonunificationNested() { Unifier unifier = Unification.unifyAtoms(left, right); assertNull(unifier); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/UnifierTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/UnifierTest.java similarity index 68% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/UnifierTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/UnifierTest.java index 5fc102ec6..d0a0aaf62 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/UnifierTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/UnifierTest.java @@ -26,44 +26,46 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.grounder; +package at.ac.tuwien.kr.alpha.core.grounder; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +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.Unifier; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; public class UnifierTest extends SubstitutionTest { @Test public void extendUnifier() { - VariableTerm varX = VariableTerm.getInstance("X"); - VariableTerm varY = VariableTerm.getInstance("Y"); + VariableTerm varX = Terms.newVariable("X"); + VariableTerm varY = Terms.newVariable("Y"); Unifier sub1 = new Unifier(); sub1.put(varX, varY); Unifier sub2 = new Unifier(); - sub2.put(varY, ConstantTerm.getInstance("a")); + sub2.put(varY, Terms.newConstant("a")); sub1.extendWith(sub2); BasicAtom atom1 = parseAtom("p(X)"); Atom atomSubstituted = atom1.substitute(sub1); - assertEquals(ConstantTerm.getInstance("a"), atomSubstituted.getTerms().get(0)); + assertEquals(Terms.newConstant("a"), atomSubstituted.getTerms().get(0)); } @Test public void mergeUnifierIntoLeft() { - VariableTerm varX = VariableTerm.getInstance("X"); - VariableTerm varY = VariableTerm.getInstance("Y"); - VariableTerm varZ = VariableTerm.getInstance("Z"); - Term constA = ConstantTerm.getInstance("a"); + VariableTerm varX = Terms.newVariable("X"); + VariableTerm varY = Terms.newVariable("Y"); + VariableTerm varZ = Terms.newVariable("Z"); + Term constA = Terms.newConstant("a"); Unifier left = new Unifier(); left.put(varX, varY); left.put(varZ, varY); @@ -75,8 +77,8 @@ public void mergeUnifierIntoLeft() { } private BasicAtom parseAtom(String atom) { - ProgramParser programParser = new ProgramParser(); - InputProgram program = programParser.parse(atom + "."); + ProgramParser programParser = new ProgramParserImpl(); + ASPCore2Program program = programParser.parse(atom + "."); return (BasicAtom) program.getFacts().get(0); } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/heuristics/GrounderHeuristicConfigurationTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/heuristics/GrounderHeuristicConfigurationTest.java similarity index 93% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/heuristics/GrounderHeuristicConfigurationTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/heuristics/GrounderHeuristicConfigurationTest.java index c1a478edb..29cbb57fa 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/heuristics/GrounderHeuristicConfigurationTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/heuristics/GrounderHeuristicConfigurationTest.java @@ -23,17 +23,19 @@ * 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.grounder.heuristics; +package at.ac.tuwien.kr.alpha.core.grounder.heuristics; -import static at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration.PERMISSIVE_STRING; -import static at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration.STRICT_STRING; +import static at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration.PERMISSIVE_STRING; +import static at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration.STRICT_STRING; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; +import at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration; + /** * Tests {@link GrounderHeuristicsConfiguration} */ diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationStrategyTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationStrategyTest.java similarity index 73% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationStrategyTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationStrategyTest.java index 9b016a6e2..6604e3300 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiationStrategyTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiationStrategyTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -10,51 +10,53 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.NaiveGrounder; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.WorkingMemory; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +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.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +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.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.grounder.NaiveGrounder; +import at.ac.tuwien.kr.alpha.core.grounder.WorkingMemory; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; public class LiteralInstantiationStrategyTest { @Test public void workingMemoryBasedInstantiationAcceptLiteral() { - Predicate p = Predicate.getInstance("p", 1); + Predicate p = Predicates.getPredicate("p", 1); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(p); - workingMemory.addInstance(new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")), true); + workingMemory.addInstance(Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")), true); LiteralInstantiationStrategy strategy = new WorkingMemoryBasedInstantiationStrategy(workingMemory); - Literal positiveAcceptedLiteral = new BasicLiteral( - new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")), true); + Literal positiveAcceptedLiteral = Literals.fromAtom( + Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")), true); assertEquals(AssignmentStatus.TRUE, strategy.getTruthForGroundLiteral(positiveAcceptedLiteral)); - Literal negativeAcceptedLiteral = new BasicLiteral( - new BasicAtom(p, ConstantTerm.getSymbolicInstance("b")), false); + Literal negativeAcceptedLiteral = Literals.fromAtom( + Atoms.newBasicAtom(p, Terms.newSymbolicConstant("b")), false); assertEquals(AssignmentStatus.TRUE, strategy.getTruthForGroundLiteral(negativeAcceptedLiteral)); } @Test public void workingMemoryBasedInstantiationRejectLiteral() { - Predicate p = Predicate.getInstance("p", 1); + Predicate p = Predicates.getPredicate("p", 1); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(p); - workingMemory.addInstance(new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")), true); + workingMemory.addInstance(Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")), true); LiteralInstantiationStrategy strategy = new WorkingMemoryBasedInstantiationStrategy(workingMemory); - Literal positiveRejectedLiteral = new BasicLiteral( - new BasicAtom(p, ConstantTerm.getSymbolicInstance("b")), true); + Literal positiveRejectedLiteral = Literals.fromAtom( + Atoms.newBasicAtom(p, Terms.newSymbolicConstant("b")), true); assertEquals(AssignmentStatus.FALSE, strategy.getTruthForGroundLiteral(positiveRejectedLiteral)); - Literal negativeRejectedLiteral = new BasicLiteral( - new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")), false); + Literal negativeRejectedLiteral = Literals.fromAtom( + Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")), false); assertEquals(AssignmentStatus.FALSE, strategy.getTruthForGroundLiteral(negativeRejectedLiteral)); } @@ -70,17 +72,16 @@ public void workingMemoryBasedInstantiationRejectLiteral() { */ @Test public void defaultLazyGroundingNoAssignmentGroundLiteral() { - Predicate p = Predicate.getInstance("p", 1); - BasicAtom pOfA = new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")); + Predicate p = Predicates.getPredicate("p", 1); + BasicAtom pOfA = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")); WorkingMemory workingMemory = new WorkingMemory(); LinkedHashSet staleSet = new LinkedHashSet<>(); DefaultLazyGroundingInstantiationStrategy strategy = new DefaultLazyGroundingInstantiationStrategy(workingMemory, new AtomStoreImpl(), Collections.emptyMap(), false); strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(null); - - AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(new BasicLiteral(pOfA, true)); + AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(Literals.fromAtom(pOfA, true)); assertEquals(AssignmentStatus.TRUE, assignmentStatus); assertTrue(staleSet.isEmpty()); } @@ -98,26 +99,26 @@ public void defaultLazyGroundingNoAssignmentGroundLiteral() { */ @Test public void defaultLazyGroundingNoAssignmentSubstituteNonGroundLiteral() { - Predicate q = Predicate.getInstance("q", 2); - BasicAtom nonGroundAtom = new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), VariableTerm.getInstance("X")); + Predicate q = Predicates.getPredicate("q", 2); + BasicAtom nonGroundAtom = Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newVariable("X")); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(q); - workingMemory.addInstance(new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")), true); + workingMemory.addInstance(Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")), true); LinkedHashSet staleSet = new LinkedHashSet<>(); DefaultLazyGroundingInstantiationStrategy strategy = new DefaultLazyGroundingInstantiationStrategy(workingMemory, new AtomStoreImpl(), Collections.emptyMap(), false); strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(null); - List> result = strategy.getAcceptedSubstitutions(new BasicLiteral(nonGroundAtom, true), - new Substitution()); + List> result = strategy.getAcceptedSubstitutions(Literals.fromAtom(nonGroundAtom, true), + new BasicSubstitution()); assertEquals(1, result.size()); ImmutablePair substitutionInfo = result.get(0); Substitution substitution = substitutionInfo.left; AssignmentStatus assignmentStatus = substitutionInfo.right; assertEquals(AssignmentStatus.TRUE, assignmentStatus); - assertTrue(substitution.isVariableSet(VariableTerm.getInstance("X"))); - assertEquals(ConstantTerm.getSymbolicInstance("b"), substitution.eval(VariableTerm.getInstance("X"))); + assertTrue(substitution.isVariableSet(Terms.newVariable("X"))); + assertEquals(Terms.newSymbolicConstant("b"), substitution.eval(Terms.newVariable("X"))); assertTrue(staleSet.isEmpty()); } @@ -133,8 +134,8 @@ public void defaultLazyGroundingNoAssignmentSubstituteNonGroundLiteral() { */ @Test public void defaultLazyGroundingCheckUnassignedGroundLiteral() { - Predicate p = Predicate.getInstance("p", 1); - BasicAtom pOfA = new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")); + Predicate p = Predicates.getPredicate("p", 1); + BasicAtom pOfA = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")); WorkingMemory workingMemory = new WorkingMemory(); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); @@ -144,7 +145,7 @@ public void defaultLazyGroundingCheckUnassignedGroundLiteral() { strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(new BasicLiteral(pOfA, true)); + AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(Literals.fromAtom(pOfA, true)); assertEquals(AssignmentStatus.UNASSIGNED, assignmentStatus); assertEquals(1, staleSet.size()); @@ -163,8 +164,8 @@ public void defaultLazyGroundingCheckUnassignedGroundLiteral() { */ @Test public void defaultLazyGroundingCheckFalseGroundLiteral() { - Predicate p = Predicate.getInstance("p", 1); - BasicAtom pOfA = new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")); + Predicate p = Predicates.getPredicate("p", 1); + BasicAtom pOfA = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")); WorkingMemory workingMemory = new WorkingMemory(); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); @@ -177,7 +178,7 @@ public void defaultLazyGroundingCheckFalseGroundLiteral() { strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(new BasicLiteral(pOfA, true)); + AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(Literals.fromAtom(pOfA, true)); assertEquals(AssignmentStatus.FALSE, assignmentStatus); assertEquals(1, staleSet.size()); @@ -196,8 +197,8 @@ public void defaultLazyGroundingCheckFalseGroundLiteral() { */ @Test public void defaultLazyGroundingCheckTrueGroundLiteral() { - Predicate p = Predicate.getInstance("p", 1); - BasicAtom pOfA = new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")); + Predicate p = Predicates.getPredicate("p", 1); + BasicAtom pOfA = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")); WorkingMemory workingMemory = new WorkingMemory(); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); @@ -209,8 +210,8 @@ public void defaultLazyGroundingCheckTrueGroundLiteral() { Collections.emptyMap(), false); strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - - AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(new BasicLiteral(pOfA, true)); + + AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(Literals.fromAtom(pOfA, true)); assertEquals(AssignmentStatus.TRUE, assignmentStatus); assertTrue(staleSet.isEmpty()); @@ -228,8 +229,8 @@ public void defaultLazyGroundingCheckTrueGroundLiteral() { */ @Test public void defaultLazyGroundingCheckMustBeTrueGroundLiteral() { - Predicate p = Predicate.getInstance("p", 1); - BasicAtom pOfA = new BasicAtom(p, ConstantTerm.getSymbolicInstance("a")); + Predicate p = Predicates.getPredicate("p", 1); + BasicAtom pOfA = Atoms.newBasicAtom(p, Terms.newSymbolicConstant("a")); WorkingMemory workingMemory = new WorkingMemory(); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); @@ -242,7 +243,7 @@ public void defaultLazyGroundingCheckMustBeTrueGroundLiteral() { strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(new BasicLiteral(pOfA, true)); + AssignmentStatus assignmentStatus = strategy.getTruthForGroundLiteral(Literals.fromAtom(pOfA, true)); assertEquals(AssignmentStatus.TRUE, assignmentStatus); assertTrue(staleSet.isEmpty()); @@ -261,11 +262,11 @@ public void defaultLazyGroundingCheckMustBeTrueGroundLiteral() { */ @Test public void defaultLazyGroundingSubstituteNonGroundLiteralWithUnassignedInstance() { - Predicate q = Predicate.getInstance("q", 2); - BasicAtom nonGroundAtom = new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), VariableTerm.getInstance("X")); + Predicate q = Predicates.getPredicate("q", 2); + BasicAtom nonGroundAtom = Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newVariable("X")); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(q); - workingMemory.addInstance(new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")), true); + workingMemory.addInstance(Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")), true); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); LinkedHashSet staleSet = new LinkedHashSet<>(); @@ -274,18 +275,18 @@ public void defaultLazyGroundingSubstituteNonGroundLiteralWithUnassignedInstance strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - List> result = strategy.getAcceptedSubstitutions(new BasicLiteral(nonGroundAtom, true), - new Substitution()); + List> result = strategy.getAcceptedSubstitutions(Literals.fromAtom(nonGroundAtom, true), + new BasicSubstitution()); assertEquals(1, result.size()); ImmutablePair substitutionInfo = result.get(0); Substitution substitution = substitutionInfo.left; AssignmentStatus assignmentStatus = substitutionInfo.right; assertEquals(AssignmentStatus.UNASSIGNED, assignmentStatus); - assertTrue(substitution.isVariableSet(VariableTerm.getInstance("X"))); - assertEquals(ConstantTerm.getSymbolicInstance("b"), substitution.eval(VariableTerm.getInstance("X"))); + assertTrue(substitution.isVariableSet(Terms.newVariable("X"))); + assertEquals(Terms.newSymbolicConstant("b"), substitution.eval(Terms.newVariable("X"))); assertEquals(1, staleSet.size()); - assertTrue(staleSet.contains(new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")))); + assertTrue(staleSet.contains(Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")))); } /** @@ -300,14 +301,14 @@ public void defaultLazyGroundingSubstituteNonGroundLiteralWithUnassignedInstance */ @Test public void defaultLazyGroundingSubstituteNonGroundLiteralWithTrueInstance() { - Predicate q = Predicate.getInstance("q", 2); - BasicAtom nonGroundAtom = new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), VariableTerm.getInstance("X")); + Predicate q = Predicates.getPredicate("q", 2); + BasicAtom nonGroundAtom = Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newVariable("X")); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(q); - workingMemory.addInstance(new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")), true); + workingMemory.addInstance(Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")), true); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); - BasicAtom groundAtom = new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")); + BasicAtom groundAtom = Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")); atomStore.putIfAbsent(groundAtom); assignment.growForMaxAtomId(); assignment.assign(atomStore.get(groundAtom), ThriceTruth.TRUE); @@ -317,15 +318,15 @@ public void defaultLazyGroundingSubstituteNonGroundLiteralWithTrueInstance() { strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - List> result = strategy.getAcceptedSubstitutions(new BasicLiteral(nonGroundAtom, true), - new Substitution()); + List> result = strategy.getAcceptedSubstitutions(Literals.fromAtom(nonGroundAtom, true), + new BasicSubstitution()); assertEquals(1, result.size()); ImmutablePair substitutionInfo = result.get(0); Substitution substitution = substitutionInfo.left; AssignmentStatus assignmentStatus = substitutionInfo.right; assertEquals(AssignmentStatus.TRUE, assignmentStatus); - assertTrue(substitution.isVariableSet(VariableTerm.getInstance("X"))); - assertEquals(ConstantTerm.getSymbolicInstance("b"), substitution.eval(VariableTerm.getInstance("X"))); + assertTrue(substitution.isVariableSet(Terms.newVariable("X"))); + assertEquals(Terms.newSymbolicConstant("b"), substitution.eval(Terms.newVariable("X"))); assertTrue(staleSet.isEmpty()); } @@ -341,14 +342,14 @@ public void defaultLazyGroundingSubstituteNonGroundLiteralWithTrueInstance() { */ @Test public void defaultLazyGroundingSubstituteNonGroundLiteralWithFalseInstance() { - Predicate q = Predicate.getInstance("q", 2); - BasicAtom nonGroundAtom = new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), VariableTerm.getInstance("X")); + Predicate q = Predicates.getPredicate("q", 2); + BasicAtom nonGroundAtom = Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newVariable("X")); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(q); - workingMemory.addInstance(new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")), true); + workingMemory.addInstance(Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")), true); AtomStore atomStore = new AtomStoreImpl(); WritableAssignment assignment = new TrailAssignment(atomStore); - BasicAtom groundAtom = new BasicAtom(q, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getSymbolicInstance("b")); + BasicAtom groundAtom = Atoms.newBasicAtom(q, Terms.newSymbolicConstant("a"), Terms.newSymbolicConstant("b")); atomStore.putIfAbsent(groundAtom); assignment.growForMaxAtomId(); assignment.assign(atomStore.get(groundAtom), ThriceTruth.FALSE); @@ -358,8 +359,8 @@ public void defaultLazyGroundingSubstituteNonGroundLiteralWithFalseInstance() { strategy.setStaleWorkingMemoryEntries(staleSet); strategy.setCurrentAssignment(assignment); - List> result = strategy.getAcceptedSubstitutions(new BasicLiteral(nonGroundAtom, true), - new Substitution()); + List> result = strategy.getAcceptedSubstitutions(Literals.fromAtom(nonGroundAtom, true), + new BasicSubstitution()); assertTrue(result.isEmpty()); assertEquals(1, staleSet.size()); @@ -367,4 +368,3 @@ public void defaultLazyGroundingSubstituteNonGroundLiteralWithFalseInstance() { } } - \ No newline at end of file diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiatorTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiatorTest.java similarity index 53% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiatorTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiatorTest.java index 5c65425b3..5e3622252 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/instantiation/LiteralInstantiatorTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/instantiation/LiteralInstantiatorTest.java @@ -1,37 +1,36 @@ -package at.ac.tuwien.kr.alpha.grounder.instantiation; +package at.ac.tuwien.kr.alpha.core.grounder.instantiation; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.WorkingMemory; -import at.ac.tuwien.kr.alpha.grounder.atoms.EnumerationAtom; -import at.ac.tuwien.kr.alpha.grounder.atoms.EnumerationLiteral; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +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.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +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.EnumerationAtom; +import at.ac.tuwien.kr.alpha.core.atoms.EnumerationLiteral; +import at.ac.tuwien.kr.alpha.core.grounder.WorkingMemory; public class LiteralInstantiatorTest { @Test public void instantiateSatisfiedFixedInterpretationLiteral() { - ComparisonAtom equalsThree = new ComparisonAtom(ConstantTerm.getInstance(3), VariableTerm.getInstance("THREE"), ComparisonOperator.EQ); - Literal lit = new ComparisonLiteral(equalsThree, true); - Substitution substitution = new Substitution(); + ComparisonAtom equalsThree = Atoms.newComparisonAtom(Terms.newConstant(3), Terms.newVariable("THREE"), ComparisonOperators.EQ); + Literal lit = Literals.fromAtom(equalsThree, true); + Substitution substitution = new BasicSubstitution(); LiteralInstantiator instantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(null)); LiteralInstantiationResult result = instantiator.instantiateLiteral(lit, substitution); assertEquals(LiteralInstantiationResult.Type.CONTINUE, result.getType()); @@ -39,17 +38,17 @@ public void instantiateSatisfiedFixedInterpretationLiteral() { assertEquals(1, resultSubstitutions.size()); assertEquals(AssignmentStatus.TRUE, resultSubstitutions.get(0).right); Substitution extendedSubstitution = resultSubstitutions.get(0).left; - assertTrue(extendedSubstitution.isVariableSet(VariableTerm.getInstance("THREE"))); - assertEquals(ConstantTerm.getInstance(3), extendedSubstitution.eval(VariableTerm.getInstance("THREE"))); + assertTrue(extendedSubstitution.isVariableSet(Terms.newVariable("THREE"))); + assertEquals(Terms.newConstant(3), extendedSubstitution.eval(Terms.newVariable("THREE"))); } @Test public void instantiateUnsatisfiedFixedInterpretationLiteral() { - ComparisonAtom fiveEqualsThree = new ComparisonAtom(VariableTerm.getInstance("FIVE"), VariableTerm.getInstance("THREE"), ComparisonOperator.EQ); - Literal lit = new ComparisonLiteral(fiveEqualsThree, true); - Substitution substitution = new Substitution(); - substitution.put(VariableTerm.getInstance("FIVE"), ConstantTerm.getInstance(5)); - substitution.put(VariableTerm.getInstance("THREE"), ConstantTerm.getInstance(3)); + ComparisonAtom fiveEqualsThree = Atoms.newComparisonAtom(Terms.newVariable("FIVE"), Terms.newVariable("THREE"), ComparisonOperators.EQ); + Literal lit = Literals.fromAtom(fiveEqualsThree, true); + Substitution substitution = new BasicSubstitution(); + substitution.put(Terms.newVariable("FIVE"), Terms.newConstant(5)); + substitution.put(Terms.newVariable("THREE"), Terms.newConstant(3)); LiteralInstantiator instantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(null)); LiteralInstantiationResult result = instantiator.instantiateLiteral(lit, substitution); assertEquals(LiteralInstantiationResult.Type.STOP_BINDING, result.getType()); @@ -57,18 +56,14 @@ public void instantiateUnsatisfiedFixedInterpretationLiteral() { @Test public void instantiateEnumLiteral() { - VariableTerm enumTerm = VariableTerm.getInstance("E"); - VariableTerm idTerm = VariableTerm.getInstance("X"); - VariableTerm indexTerm = VariableTerm.getInstance("I"); - List termList = new ArrayList<>(); - termList.add(enumTerm); - termList.add(idTerm); - termList.add(indexTerm); - EnumerationAtom enumAtom = new EnumerationAtom(termList); + VariableTerm enumTerm = Terms.newVariable("E"); + VariableTerm idTerm = Terms.newVariable("X"); + VariableTerm indexTerm = Terms.newVariable("I"); + EnumerationAtom enumAtom = new EnumerationAtom(enumTerm, idTerm, indexTerm); EnumerationLiteral lit = new EnumerationLiteral(enumAtom); - Substitution substitution = new Substitution(); - substitution.put(enumTerm, ConstantTerm.getSymbolicInstance("enum1")); - substitution.put(idTerm, ConstantTerm.getSymbolicInstance("someElement")); + Substitution substitution = new BasicSubstitution(); + substitution.put(enumTerm, Terms.newSymbolicConstant("enum1")); + substitution.put(idTerm, Terms.newSymbolicConstant("someElement")); LiteralInstantiator instantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(null)); LiteralInstantiationResult result = instantiator.instantiateLiteral(lit, substitution); assertEquals(LiteralInstantiationResult.Type.CONTINUE, result.getType()); @@ -80,16 +75,16 @@ public void instantiateEnumLiteral() { @Test public void workingMemoryBasedVerifyPositiveGroundLiteralSatisfied() { - Predicate p = Predicate.getInstance("p", 2); + Predicate p = Predicates.getPredicate("p", 2); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(p); - workingMemory.addInstance(new BasicAtom(p, ConstantTerm.getSymbolicInstance("x"), ConstantTerm.getSymbolicInstance("y")), true); - VariableTerm x = VariableTerm.getInstance("X"); - VariableTerm y = VariableTerm.getInstance("Y"); - Literal lit = new BasicLiteral(new BasicAtom(p, x, y), true); - Substitution substitution = new Substitution(); - substitution.put(x, ConstantTerm.getSymbolicInstance("x")); - substitution.put(y, ConstantTerm.getSymbolicInstance("y")); + workingMemory.addInstance(Atoms.newBasicAtom(p, Terms.newSymbolicConstant("x"), Terms.newSymbolicConstant("y")), true); + VariableTerm x = Terms.newVariable("X"); + VariableTerm y = Terms.newVariable("Y"); + Literal lit = Literals.fromAtom(Atoms.newBasicAtom(p, x, y), true); + Substitution substitution = new BasicSubstitution(); + substitution.put(x, Terms.newSymbolicConstant("x")); + substitution.put(y, Terms.newSymbolicConstant("y")); LiteralInstantiator instantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(workingMemory)); LiteralInstantiationResult result = instantiator.instantiateLiteral(lit, substitution); assertEquals(LiteralInstantiationResult.Type.CONTINUE, result.getType()); @@ -104,15 +99,15 @@ public void workingMemoryBasedVerifyPositiveGroundLiteralSatisfied() { @Test public void workingMemoryBasedVerifyPositiveGroundLiteralUnsatisfied() { - Predicate p = Predicate.getInstance("p", 2); + Predicate p = Predicates.getPredicate("p", 2); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(p); - VariableTerm x = VariableTerm.getInstance("X"); - VariableTerm y = VariableTerm.getInstance("Y"); - Literal lit = new BasicLiteral(new BasicAtom(p, x, y), true); - Substitution substitution = new Substitution(); - substitution.put(x, ConstantTerm.getSymbolicInstance("x")); - substitution.put(y, ConstantTerm.getSymbolicInstance("y")); + VariableTerm x = Terms.newVariable("X"); + VariableTerm y = Terms.newVariable("Y"); + Literal lit = Literals.fromAtom(Atoms.newBasicAtom(p, x, y), true); + Substitution substitution = new BasicSubstitution(); + substitution.put(x, Terms.newSymbolicConstant("x")); + substitution.put(y, Terms.newSymbolicConstant("y")); LiteralInstantiator instantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(workingMemory)); LiteralInstantiationResult result = instantiator.instantiateLiteral(lit, substitution); // With the given input substitution, lit is ground, but not satisfied - @@ -123,16 +118,16 @@ public void workingMemoryBasedVerifyPositiveGroundLiteralUnsatisfied() { @Test public void workingMemoryBasedInstantiatePositiveBasicLiteral() { - Predicate p = Predicate.getInstance("p", 2); + Predicate p = Predicates.getPredicate("p", 2); WorkingMemory workingMemory = new WorkingMemory(); workingMemory.initialize(p); - workingMemory.addInstance(new BasicAtom(p, ConstantTerm.getSymbolicInstance("x"), ConstantTerm.getSymbolicInstance("y")), true); - workingMemory.addInstance(new BasicAtom(p, ConstantTerm.getSymbolicInstance("x"), ConstantTerm.getSymbolicInstance("z")), true); - VariableTerm x = VariableTerm.getInstance("X"); - VariableTerm y = VariableTerm.getInstance("Y"); - Literal lit = new BasicLiteral(new BasicAtom(p, x, y), true); - Substitution substitution = new Substitution(); - substitution.put(x, ConstantTerm.getSymbolicInstance("x")); + workingMemory.addInstance(Atoms.newBasicAtom(p, Terms.newSymbolicConstant("x"), Terms.newSymbolicConstant("y")), true); + workingMemory.addInstance(Atoms.newBasicAtom(p, Terms.newSymbolicConstant("x"), Terms.newSymbolicConstant("z")), true); + VariableTerm x = Terms.newVariable("X"); + VariableTerm y = Terms.newVariable("Y"); + Literal lit = Literals.fromAtom(Atoms.newBasicAtom(p, x, y), true); + Substitution substitution = new BasicSubstitution(); + substitution.put(x, Terms.newSymbolicConstant("x")); LiteralInstantiator instantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(workingMemory)); LiteralInstantiationResult result = instantiator.instantiateLiteral(lit, substitution); assertEquals(LiteralInstantiationResult.Type.CONTINUE, result.getType()); @@ -143,9 +138,9 @@ public void workingMemoryBasedInstantiatePositiveBasicLiteral() { for (ImmutablePair resultSubstitution : substitutions) { assertTrue(resultSubstitution.left.isVariableSet(y)); assertEquals(AssignmentStatus.TRUE, resultSubstitution.right); - if (resultSubstitution.left.eval(y).equals(ConstantTerm.getSymbolicInstance("y"))) { + if (resultSubstitution.left.eval(y).equals(Terms.newSymbolicConstant("y"))) { ySubstituted = true; - } else if (resultSubstitution.left.eval(y).equals(ConstantTerm.getSymbolicInstance("z"))) { + } else if (resultSubstitution.left.eval(y).equals(Terms.newSymbolicConstant("z"))) { zSubstituted = true; } else { fail("Invalid substitution for variable Y"); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/structure/AnalyzeUnjustifiedTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustifiedTest.java similarity index 67% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/structure/AnalyzeUnjustifiedTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustifiedTest.java index ebd22ddb7..87097ecad 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/structure/AnalyzeUnjustifiedTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/grounder/structure/AnalyzeUnjustifiedTest.java @@ -25,7 +25,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.grounder.structure; +package at.ac.tuwien.kr.alpha.core.grounder.structure; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -33,54 +33,59 @@ import java.util.Arrays; import java.util.Collections; import java.util.Set; +import java.util.function.Function; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.grounder.NaiveGrounder; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +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.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.grounder.NaiveGrounder; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; /** * Copyright (c) 2018-2020, the Alpha Team. */ public class AnalyzeUnjustifiedTest { - private final ProgramParser parser = new ProgramParser(); + private final ProgramParser parser = new ProgramParserImpl(); + private final NormalizeProgramTransformation normalize = new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); + private final Function parseAndPreprocess = (str) -> { + return InternalProgram.fromNormalProgram(normalize.apply(parser.parse(str))); + }; @Test public void justifySimpleRules() { - Alpha system = new Alpha(); String program = "p(X) :- q(X)." + "q(X) :- p(X)." + "q(5) :- r." + "r :- not nr." + "nr :- not r." + ":- not p(5)."; - InputProgram parsedProgram = parser.parse(program); - NormalProgram normal = system.normalizeProgram(parsedProgram); - InternalProgram internalProgram = InternalProgram.fromNormalProgram(normal); + CompiledProgram internalProgram = parseAndPreprocess.apply(program); AtomStore atomStore = new AtomStoreImpl(); NaiveGrounder grounder = new NaiveGrounder(internalProgram, atomStore, true); grounder.getNoGoods(null); TrailAssignment assignment = new TrailAssignment(atomStore); - int rId = atomStore.get(new BasicAtom(Predicate.getInstance("r", 0))); - int nrId = atomStore.get(new BasicAtom(Predicate.getInstance("nr", 0))); + int rId = atomStore.get(Atoms.newBasicAtom(Predicates.getPredicate("r", 0))); + int nrId = atomStore.get(Atoms.newBasicAtom(Predicates.getPredicate("nr", 0))); assignment.growForMaxAtomId(); assignment.assign(rId, ThriceTruth.FALSE); assignment.assign(nrId, ThriceTruth.TRUE); - BasicAtom p5 = new BasicAtom(Predicate.getInstance("p", 1), Collections.singletonList(ConstantTerm.getInstance(5))); + BasicAtom p5 = Atoms.newBasicAtom(Predicates.getPredicate("p", 1), Collections.singletonList(Terms.newConstant(5))); assignment.assign(atomStore.get(p5), ThriceTruth.MBT); Set reasons = grounder.justifyAtom(atomStore.get(p5), assignment); assertFalse(reasons.isEmpty()); @@ -88,7 +93,6 @@ public void justifySimpleRules() { @Test public void justifyLargerRules() { - Alpha system = new Alpha(); String program = "p(X) :- q(X,Y), r(Y), not s(X,Y)." + "{ q(1,X)} :- dom(X)." + "dom(1..3)." + @@ -96,9 +100,7 @@ public void justifyLargerRules() { "{r(2)}." + "{s(1,2)}." + ":- not p(1)."; - InputProgram parsedProgram = parser.parse(program); - NormalProgram normal = system.normalizeProgram(parsedProgram); - InternalProgram internalProgram = InternalProgram.fromNormalProgram(normal); + CompiledProgram internalProgram = parseAndPreprocess.apply(program); AtomStore atomStore = new AtomStoreImpl(); NaiveGrounder grounder = new NaiveGrounder(internalProgram, atomStore, true); grounder.getNoGoods(null); @@ -129,16 +131,13 @@ public void justifyLargerRules() { @Test public void justifyMultipleReasons() { - Alpha system = new Alpha(); String program = "n(a). n(b). n(c). n(d). n(e)." + "s(a,b). s(b,c). s(c,d). s(d,e)." + "{ q(X) } :- n(X)." + "p(X) :- q(X)." + "p(X) :- p(Y), s(Y,X)." + ":- not p(c)."; - InputProgram parsedProgram = parser.parse(program); - NormalProgram normal = system.normalizeProgram(parsedProgram); - InternalProgram internalProgram = InternalProgram.fromNormalProgram(normal); + CompiledProgram internalProgram = parseAndPreprocess.apply(program); AtomStore atomStore = new AtomStoreImpl(); NaiveGrounder grounder = new NaiveGrounder(internalProgram, atomStore, true); grounder.getNoGoods(null); @@ -161,12 +160,12 @@ public void justifyMultipleReasons() { assignment.assign(qdId, ThriceTruth.FALSE); assignment.assign(qeId, ThriceTruth.FALSE); - Predicate nq = Predicate.getInstance("_nq", 2, true); - Atom nqa = new BasicAtom(nq, Arrays.asList(ConstantTerm.getInstance("1"), ConstantTerm.getSymbolicInstance("a"))); - Atom nqb = new BasicAtom(nq, Arrays.asList(ConstantTerm.getInstance("1"), ConstantTerm.getSymbolicInstance("b"))); - Atom nqc = new BasicAtom(nq, Arrays.asList(ConstantTerm.getInstance("1"), ConstantTerm.getSymbolicInstance("c"))); - Atom nqd = new BasicAtom(nq, Arrays.asList(ConstantTerm.getInstance("1"), ConstantTerm.getSymbolicInstance("d"))); - Atom nqe = new BasicAtom(nq, Arrays.asList(ConstantTerm.getInstance("1"), ConstantTerm.getSymbolicInstance("e"))); + Predicate nq = Predicates.getPredicate("_nq", 2, true); + Atom nqa = Atoms.newBasicAtom(nq, Arrays.asList(Terms.newConstant("1"), Terms.newSymbolicConstant("a"))); + Atom nqb = Atoms.newBasicAtom(nq, Arrays.asList(Terms.newConstant("1"), Terms.newSymbolicConstant("b"))); + Atom nqc = Atoms.newBasicAtom(nq, Arrays.asList(Terms.newConstant("1"), Terms.newSymbolicConstant("c"))); + Atom nqd = Atoms.newBasicAtom(nq, Arrays.asList(Terms.newConstant("1"), Terms.newSymbolicConstant("d"))); + Atom nqe = Atoms.newBasicAtom(nq, Arrays.asList(Terms.newConstant("1"), Terms.newSymbolicConstant("e"))); int nqaId = atomStore.get(nqa); int nqbId = atomStore.get(nqb); int nqcId = atomStore.get(nqc); @@ -187,7 +186,6 @@ public void justifyMultipleReasons() { @Test public void justifyNegatedFactsRemovedFromReasons() { - Alpha system = new Alpha(); String program = "forbidden(2,9). forbidden(1,9)." + "p(X) :- q(X)." + "q(X) :- p(X)." + @@ -195,25 +193,23 @@ public void justifyNegatedFactsRemovedFromReasons() { "r :- not nr, not forbidden(2,9), not forbidden(1,9)." + "nr :- not r." + ":- not p(5)."; - InputProgram parsedProgram = parser.parse(program); - NormalProgram normal = system.normalizeProgram(parsedProgram); - InternalProgram internalProgram = InternalProgram.fromNormalProgram(normal); + CompiledProgram internalProgram = parseAndPreprocess.apply(program); AtomStore atomStore = new AtomStoreImpl(); NaiveGrounder grounder = new NaiveGrounder(internalProgram, atomStore, true); grounder.getNoGoods(null); TrailAssignment assignment = new TrailAssignment(atomStore); - int rId = atomStore.get(new BasicAtom(Predicate.getInstance("r", 0))); - int nrId = atomStore.get(new BasicAtom(Predicate.getInstance("nr", 0))); + int rId = atomStore.get(Atoms.newBasicAtom(Predicates.getPredicate("r", 0))); + int nrId = atomStore.get(Atoms.newBasicAtom(Predicates.getPredicate("nr", 0))); assignment.growForMaxAtomId(); assignment.assign(rId, ThriceTruth.FALSE); assignment.assign(nrId, ThriceTruth.TRUE); - BasicAtom p5 = new BasicAtom(Predicate.getInstance("p", 1), Collections.singletonList(ConstantTerm.getInstance(5))); + BasicAtom p5 = Atoms.newBasicAtom(Predicates.getPredicate("p", 1), Collections.singletonList(Terms.newConstant(5))); assignment.assign(atomStore.get(p5), ThriceTruth.MBT); Set reasons = grounder.justifyAtom(atomStore.get(p5), assignment); assertFalse(reasons.isEmpty()); for (Literal literal : reasons) { // Check that facts are not present in justification. - assertNotEquals(literal.getPredicate(), Predicate.getInstance("forbidden", 2)); + assertNotEquals(literal.getPredicate(), Predicates.getPredicate("forbidden", 2)); } } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/antlr/ParserTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/parser/ParserTest.java similarity index 67% rename from src/test/java/at/ac/tuwien/kr/alpha/antlr/ParserTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/parser/ParserTest.java index fcd4f9ffd..d63009bbb 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/antlr/ParserTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/parser/ParserTest.java @@ -25,12 +25,27 @@ * 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.antlr; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +package at.ac.tuwien.kr.alpha.core.parser; + +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.InlineDirectives; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.heads.ChoiceHead; +import at.ac.tuwien.kr.alpha.api.terms.FunctionTerm; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.terms.IntervalTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.commons.util.Util; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.channels.ReadableByteChannel; @@ -40,37 +55,20 @@ import java.util.Optional; import java.util.stream.Stream; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.junit.jupiter.api.Test; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.head.ChoiceHead; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.IntervalTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Copyright (c) 2016, the Alpha Team. */ public class ParserTest { - private final ProgramParser parser = new ProgramParser(); + private final ProgramParserImpl parser = new ProgramParserImpl(); @Test public void parseFact() { - InputProgram parsedProgram = parser.parse("p(a,b)."); + ASPCore2Program parsedProgram = parser.parse("p(a,b)."); assertEquals(1, parsedProgram.getFacts().size(), "Program contains one fact."); assertEquals("p", parsedProgram.getFacts().get(0).getPredicate().getName(), "Predicate name of fact is p."); @@ -81,7 +79,7 @@ public void parseFact() { @Test public void parseFactWithFunctionTerms() { - InputProgram parsedProgram = parser.parse("p(f(a),g(h(Y)))."); + ASPCore2Program parsedProgram = parser.parse("p(f(a),g(h(Y)))."); assertEquals(1, parsedProgram.getFacts().size(), "Program contains one fact."); assertEquals("p", parsedProgram.getFacts().get(0).getPredicate().getName(), "Predicate name of fact is p."); @@ -92,7 +90,7 @@ public void parseFactWithFunctionTerms() { @Test public void parseSmallProgram() { - InputProgram parsedProgram = parser.parse( + ASPCore2Program parsedProgram = parser.parse( "a :- b, not d." + System.lineSeparator() + "c(X) :- p(X,a,_), q(Xaa,xaa)." + System.lineSeparator() + ":- f(Y)."); @@ -109,7 +107,7 @@ public void parseBadSyntax() { @Test public void parseBuiltinAtom() { - InputProgram parsedProgram = parser.parse("a :- p(X), X != Y, q(Y)."); + ASPCore2Program parsedProgram = parser.parse("a :- p(X), X != Y, q(Y)."); assertEquals(1, parsedProgram.getRules().size()); assertEquals(3, parsedProgram.getRules().get(0).getBody().size()); } @@ -124,39 +122,39 @@ public void parseProgramWithDisjunctionInHead() { @Test public void parseInterval() { - InputProgram parsedProgram = parser.parse("fact(2..5). p(X) :- q(a, 3 .. X)."); + ASPCore2Program parsedProgram = parser.parse("fact(2..5). p(X) :- q(a, 3 .. X)."); IntervalTerm factInterval = (IntervalTerm) parsedProgram.getFacts().get(0).getTerms().get(0); - assertTrue(factInterval.equals(IntervalTerm.getInstance(ConstantTerm.getInstance(2), ConstantTerm.getInstance(5)))); - IntervalTerm bodyInterval = (IntervalTerm) ((Literal) parsedProgram.getRules().get(0).getBody().stream().findFirst().get()).getTerms().get(1); - assertTrue(bodyInterval.equals(IntervalTerm.getInstance(ConstantTerm.getInstance(3), VariableTerm.getInstance("X")))); + assertTrue(factInterval.equals(IntervalTerm.getInstance(Terms.newConstant(2), Terms.newConstant(5)))); + IntervalTerm bodyInterval = (IntervalTerm) parsedProgram.getRules().get(0).getBody().stream().findFirst().get().getTerms().get(1); + assertTrue(bodyInterval.equals(IntervalTerm.getInstance(Terms.newConstant(3), Terms.newVariable("X")))); } @Test public void parseChoiceRule() { - InputProgram parsedProgram = parser.parse("dom(1). dom(2). { a ; b } :- dom(X)."); + ASPCore2Program parsedProgram = parser.parse("dom(1). dom(2). { a ; b } :- dom(X)."); ChoiceHead choiceHead = (ChoiceHead) parsedProgram.getRules().get(0).getHead(); assertEquals(2, choiceHead.getChoiceElements().size()); - assertTrue(choiceHead.getChoiceElements().get(0).choiceAtom.toString().equals("a")); - assertTrue(choiceHead.getChoiceElements().get(1).choiceAtom.toString().equals("b")); + assertTrue(choiceHead.getChoiceElements().get(0).getChoiceAtom().toString().equals("a")); + assertTrue(choiceHead.getChoiceElements().get(1).getChoiceAtom().toString().equals("b")); assertEquals(null, choiceHead.getLowerBound()); assertEquals(null, choiceHead.getUpperBound()); } @Test public void parseChoiceRuleBounded() { - InputProgram parsedProgram = parser.parse("dom(1). dom(2). 1 < { a: p(v,w), not r; b } <= 13 :- dom(X). foo."); + ASPCore2Program parsedProgram = parser.parse("dom(1). dom(2). 1 < { a: p(v,w), not r; b } <= 13 :- dom(X). foo."); ChoiceHead choiceHead = (ChoiceHead) parsedProgram.getRules().get(0).getHead(); assertEquals(2, choiceHead.getChoiceElements().size()); - assertTrue(choiceHead.getChoiceElements().get(0).choiceAtom.toString().equals("a")); - assertTrue(choiceHead.getChoiceElements().get(1).choiceAtom.toString().equals("b")); - List conditionalLiterals = choiceHead.getChoiceElements().get(0).conditionLiterals; + assertTrue(choiceHead.getChoiceElements().get(0).getChoiceAtom().toString().equals("a")); + assertTrue(choiceHead.getChoiceElements().get(1).getChoiceAtom().toString().equals("b")); + List conditionalLiterals = choiceHead.getChoiceElements().get(0).getConditionLiterals(); assertEquals(2, conditionalLiterals.size()); assertFalse(conditionalLiterals.get(0).isNegated()); assertTrue(conditionalLiterals.get(1).isNegated()); - assertEquals(ConstantTerm.getInstance(1), choiceHead.getLowerBound()); - assertEquals(ComparisonOperator.LT, choiceHead.getLowerOperator()); - assertEquals(ConstantTerm.getInstance(13), choiceHead.getUpperBound()); - assertEquals(ComparisonOperator.LE, choiceHead.getUpperOperator()); + assertEquals(Terms.newConstant(1), choiceHead.getLowerBound()); + assertEquals(ComparisonOperators.LT, choiceHead.getLowerOperator()); + assertEquals(Terms.newConstant(13), choiceHead.getUpperBound()); + assertEquals(ComparisonOperators.LE, choiceHead.getUpperOperator()); } @Test @@ -168,7 +166,7 @@ public void literate() throws IOException { "", "Test!"))); - final String actual = new ProgramParser().parse(CharStreams.fromChannel(input)).toString(); + final String actual = new ProgramParserImpl().parse(CharStreams.fromChannel(input)).toString(); final String expected = "p(a)." + System.lineSeparator(); assertEquals(expected, actual); @@ -194,7 +192,7 @@ public void testMissingDotNotIgnored() { @Test public void parseEnumerationDirective() { - InputProgram parsedProgram = parser.parse("p(a,1)." + + ASPCore2Program parsedProgram = parser.parse("p(a,1)." + "# enumeration_predicate_is mune." + "r(X) :- p(X), mune(X)." + "p(b,2)."); @@ -204,18 +202,18 @@ public void parseEnumerationDirective() { @Test public void cardinalityAggregate() { - InputProgram parsedProgram = parser.parse("num(K) :- K <= #count {X,Y,Z : p(X,Y,Z) }, dom(K)."); + ASPCore2Program parsedProgram = parser.parse("num(K) :- K <= #count {X,Y,Z : p(X,Y,Z) }, dom(K)."); Optional optionalBodyElement = parsedProgram.getRules().get(0).getBody().stream().filter((lit) -> lit instanceof AggregateLiteral).findFirst(); assertTrue(optionalBodyElement.isPresent()); Literal bodyElement = optionalBodyElement.get(); AggregateLiteral parsedAggregate = (AggregateLiteral) bodyElement; - VariableTerm x = VariableTerm.getInstance("X"); - VariableTerm y = VariableTerm.getInstance("Y"); - VariableTerm z = VariableTerm.getInstance("Z"); + VariableTerm x = Terms.newVariable("X"); + VariableTerm y = Terms.newVariable("Y"); + VariableTerm z = Terms.newVariable("Z"); List basicTerms = Arrays.asList(x, y, z); - AggregateAtom.AggregateElement aggregateElement = new AggregateAtom.AggregateElement(basicTerms, - Collections.singletonList(new BasicAtom(Predicate.getInstance("p", 3), x, y, z).toLiteral())); - AggregateAtom expectedAggregate = new AggregateAtom(ComparisonOperator.LE, VariableTerm.getInstance("K"), null, null, + AggregateAtom.AggregateElement aggregateElement = Atoms.newAggregateElement(basicTerms, + Collections.singletonList(Atoms.newBasicAtom(Predicates.getPredicate("p", 3), x, y, z).toLiteral())); + AggregateAtom expectedAggregate = Atoms.newAggregateAtom(ComparisonOperators.LE, Terms.newVariable("K"), null, null, AggregateAtom.AggregateFunctionSymbol.COUNT, Collections.singletonList(aggregateElement)); assertEquals(expectedAggregate, parsedAggregate.getAtom()); } @@ -223,7 +221,7 @@ public void cardinalityAggregate() { @Test public void stringWithEscapedQuotes() throws IOException { CharStream stream = CharStreams.fromStream(ParserTest.class.getResourceAsStream("/escaped_quotes.asp")); - InputProgram prog = parser.parse(stream); + ASPCore2Program prog = parser.parse(stream); assertEquals(1, prog.getFacts().size()); Atom stringAtom = prog.getFacts().get(0); String stringWithQuotes = stringAtom.getTerms().get(0).toString(); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/ArithmeticTermsRewritingTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ArithmeticTermsRewritingTest.java similarity index 66% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/ArithmeticTermsRewritingTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ArithmeticTermsRewritingTest.java index c69e68d57..17ade9d66 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/ArithmeticTermsRewritingTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ArithmeticTermsRewritingTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import static java.util.stream.Collectors.toList; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -11,18 +11,20 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.externals.Externals; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; import at.ac.tuwien.kr.alpha.api.externals.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Terms; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.ExternalAtom; +import at.ac.tuwien.kr.alpha.api.programs.literals.ExternalLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.NormalRule; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.externals.Externals; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.NormalProgramImpl; /** * Copyright (c) 2021, the Alpha Team. @@ -30,7 +32,7 @@ public class ArithmeticTermsRewritingTest { private final Map externalsOfThisClass = Externals.scan(ArithmeticTermsRewritingTest.class); - private final ProgramParser parser = new ProgramParser(externalsOfThisClass); // Create parser that knows an implementation of external atom &extArithTest[](). + private final ProgramParser parser = new ProgramParserImpl(externalsOfThisClass); // Create parser that knows an implementation of external atom &extArithTest[](). @Predicate(name = "extArithTest") public static Set>> externalForArithmeticTermsRewriting(Integer in) { @@ -41,7 +43,7 @@ public static Set>> externalForArithmeticTermsRewriti @Test public void rewriteRule() { - NormalProgram inputProgram = NormalProgram.fromInputProgram(parser.parse("p(X+1) :- q(Y/2), r(f(X*2),Y), X-2 = Y*3, X = 0..9.")); + NormalProgram inputProgram = NormalProgramImpl.fromInputProgram(parser.parse("p(X+1) :- q(Y/2), r(f(X*2),Y), X-2 = Y*3, X = 0..9.")); assertEquals(1, inputProgram.getRules().size()); ArithmeticTermsRewriting arithmeticTermsRewriting = new ArithmeticTermsRewriting(); NormalProgram rewrittenProgram = arithmeticTermsRewriting.apply(inputProgram); @@ -54,7 +56,7 @@ public void rewriteRule() { @Test public void rewriteExternalAtom() { - NormalProgram inputProgram = NormalProgram.fromInputProgram(parser.parse("p :- Y = 13, &extArithTest[Y*5](Y-4).")); + NormalProgram inputProgram = NormalProgramImpl.fromInputProgram(parser.parse("p :- Y = 13, &extArithTest[Y*5](Y-4).")); assertEquals(1, inputProgram.getRules().size()); ArithmeticTermsRewriting arithmeticTermsRewriting = new ArithmeticTermsRewriting(); NormalProgram rewrittenProgram = arithmeticTermsRewriting.apply(inputProgram); @@ -70,4 +72,4 @@ public void rewriteExternalAtom() { assertTrue(rewrittenExternal.getOutput().get(0) instanceof VariableTerm); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/ProgramTransformationTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ProgramTransformationTest.java similarity index 69% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/ProgramTransformationTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ProgramTransformationTest.java index 171f9d95e..f11692dcf 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/ProgramTransformationTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/ProgramTransformationTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -12,11 +12,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.api.externals.Externals; -import at.ac.tuwien.kr.alpha.common.program.AbstractProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.core.externals.Externals; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.NormalProgramImpl; public class ProgramTransformationTest { @@ -24,7 +25,7 @@ public class ProgramTransformationTest { private static final String TESTFILES_PATH = "/transform-test/"; - private Alpha alpha = new Alpha(); + private static final ProgramParser PARSER = new ProgramParserImpl(); private ChoiceHeadToNormal choiceToNormal = new ChoiceHeadToNormal(); private IntervalTermToIntervalAtom intervalRewriting = new IntervalTermToIntervalAtom(); @@ -42,12 +43,12 @@ private static String readTestResource(String resource) throws IOException { return bld.toString(); } - private , O extends AbstractProgram> void genericTransformationTest(ProgramTransformation transform, - Function prepareFunc, String resourceSet) { + private , O extends Program> void genericTransformationTest(ProgramTransformation transform, + Function prepareFunc, String resourceSet) { try { String inputCode = ProgramTransformationTest.readTestResource(resourceSet + ".in"); String expectedResult = ProgramTransformationTest.readTestResource(resourceSet + ".out"); - InputProgram inputProg = alpha.readProgramString(inputCode, Externals.scan(ProgramTransformationTest.class)); + ASPCore2Program inputProg = PARSER.parse(inputCode, Externals.scan(ProgramTransformationTest.class)); I transformInput = prepareFunc.apply(inputProg); String beforeTransformProg = transformInput.toString(); O transformedProg = transform.apply(transformInput); @@ -66,17 +67,17 @@ public void choiceHeadToNormalSimpleTest() { @Test public void intervalTermToIntervalAtomSimpleTest() { - genericTransformationTest(intervalRewriting, NormalProgram::fromInputProgram, "interval.1"); + genericTransformationTest(intervalRewriting, NormalProgramImpl::fromInputProgram, "interval.1"); } @Test public void intervalTermToIntervalAtomExternalAtomTest() { - genericTransformationTest(intervalRewriting, NormalProgram::fromInputProgram, "interval-external_atom"); + genericTransformationTest(intervalRewriting, NormalProgramImpl::fromInputProgram, "interval-external_atom"); } @Test public void intervalTermToIntervalAtomComparisonAtomTest() { - genericTransformationTest(intervalRewriting, NormalProgram::fromInputProgram, "interval-comparison_atom"); + genericTransformationTest(intervalRewriting, NormalProgramImpl::fromInputProgram, "interval-comparison_atom"); } @SuppressWarnings("unused") @@ -86,4 +87,4 @@ public static boolean sayTrue(int val) { return true; } -} +} \ No newline at end of file diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluationRegressionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluationRegressionTest.java similarity index 72% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluationRegressionTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluationRegressionTest.java index a73a9ff92..b2450e02f 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluationRegressionTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluationRegressionTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -7,7 +7,6 @@ import java.util.List; import java.util.Set; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.jupiter.params.ParameterizedTest; @@ -16,16 +15,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.test.util.TestUtils; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +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.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.GrounderFactory; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.solver.SolverFactory; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; public class StratifiedEvaluationRegressionTest { @@ -51,31 +58,31 @@ public class StratifiedEvaluationRegressionTest { private static final String EQUALITY_ASP = "equal :- 1 = 1."; private static final String EQUALITY_WITH_VAR_ASP = "a(1). a(2). a(3). b(X) :- a(X), X = 1. c(X) :- a(X), X = 2. d(X) :- X = 3, a(X)."; - private static final ImmutablePair, Consumer>> BASIC_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> BASIC_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramBasic, StratifiedEvaluationRegressionTest::verifyAnswerSetsBasic); - private static final ImmutablePair, Consumer>> BASIC_MULTI_INSTANCE_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> BASIC_MULTI_INSTANCE_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramBasicMultiInstance, StratifiedEvaluationRegressionTest::verifyAnswerSetsBasicMultiInstance); - private static final ImmutablePair, Consumer>> BASIC_NEGATION_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> BASIC_NEGATION_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramBasicNegation, StratifiedEvaluationRegressionTest::verifyAnswerSetsBasicNegation); - private static final ImmutablePair, Consumer>> PART_STRATIFIED_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> PART_STRATIFIED_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramPartStratified, StratifiedEvaluationRegressionTest::verifyAnswerSetsPartStratified); - private static final ImmutablePair, Consumer>> POSITIVE_RECURSIVE_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> POSITIVE_RECURSIVE_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramPositiveRecursive, StratifiedEvaluationRegressionTest::verifyAnswerSetsPositiveRecursive); - private static final ImmutablePair, Consumer>> EMPTY_PROG_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> EMPTY_PROG_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramEmptyProg, StratifiedEvaluationRegressionTest::verifyAnswerSetsEmptyProg); - private static final ImmutablePair, Consumer>> FACTS_ONLY_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> FACTS_ONLY_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramFactsOnly, StratifiedEvaluationRegressionTest::verifyAnswerSetsFactsOnly); - private static final ImmutablePair, Consumer>> STRATIFIED_NO_FACTS_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> STRATIFIED_NO_FACTS_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramStratNoFacts, StratifiedEvaluationRegressionTest::verifyAnswerSetsStratNoFacts); - private static final ImmutablePair, Consumer>> STRATIFIED_W_FACTS_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> STRATIFIED_W_FACTS_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramStratWithFacts, StratifiedEvaluationRegressionTest::verifyAnswerSetsStratWithFacts); - private static final ImmutablePair, Consumer>> EQUALITY_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> EQUALITY_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramEquality, StratifiedEvaluationRegressionTest::verifyAnswerSetsEquality); - private static final ImmutablePair, Consumer>> EQUALITY_WITH_VAR_VERIFIERS = new ImmutablePair<>( + private static final ImmutablePair, Consumer>> EQUALITY_WITH_VAR_VERIFIERS = new ImmutablePair<>( StratifiedEvaluationRegressionTest::verifyProgramEqualityWithVar, StratifiedEvaluationRegressionTest::verifyAnswerSetsEqualityWithVar); public static List params() { - List, Consumer>>>> testCases = new ArrayList<>(); + List, Consumer>>>> testCases = new ArrayList<>(); List paramList = new ArrayList<>(); testCases.add(new ImmutablePair<>(BASIC_TEST_ASP, BASIC_VERIFIERS)); testCases.add(new ImmutablePair<>(BASIC_MULTI_INSTANCE_ASP, BASIC_MULTI_INSTANCE_VERIFIERS)); @@ -94,20 +101,25 @@ public static List params() { } @ParameterizedTest - @MethodSource("at.ac.tuwien.kr.alpha.grounder.transformation.StratifiedEvaluationRegressionTest#params") - public void runTest(String aspString, Consumer programVerifier, Consumer> resultVerifier) { - String aspStr = aspString; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(aspStr); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); + @MethodSource("at.ac.tuwien.kr.alpha.core.programs.transformation.StratifiedEvaluationRegressionTest#params") + public void runTest(String aspString, Consumer programVerifier, Consumer> resultVerifier) { + // Parse and pre-evaulate program + ProgramParser parser = new ProgramParserImpl(); + ASPCore2Program prog = parser.parse(aspString); + AnalyzedProgram analyzed = AnalyzedProgram + .analyzeNormalProgram(new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG).apply(prog)); + CompiledProgram evaluated = new StratifiedEvaluation().apply(analyzed); + // Verify stratified evaluation result programVerifier.accept(evaluated); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + // Solve remaining program + AtomStore atomStore = new AtomStoreImpl(); + Grounder grounder = GrounderFactory.getInstance("naive", evaluated, atomStore, false); + Solver solver = SolverFactory.getInstance(new SystemConfig(), atomStore, grounder); + Set answerSets = solver.collectSet(); resultVerifier.accept(answerSets); } - private static void verifyProgramBasic(InternalProgram evaluated) { + private static void verifyProgramBasic(CompiledProgram evaluated) { TestUtils.assertFactsContainedInProgram(evaluated, TestUtils.basicAtomWithSymbolicTerms("a"), TestUtils.basicAtomWithSymbolicTerms("b")); assertEquals(2, evaluated.getFacts().size()); assertTrue(evaluated.getRules().size() == 0); @@ -117,7 +129,7 @@ private static void verifyAnswerSetsBasic(Set answerSets) { TestUtils.assertAnswerSetsEqual("a, b", answerSets); } - private static void verifyProgramBasicMultiInstance(InternalProgram evaluated) { + private static void verifyProgramBasicMultiInstance(CompiledProgram evaluated) { TestUtils.assertFactsContainedInProgram(evaluated, TestUtils.basicAtomWithSymbolicTerms("q", "a"), TestUtils.basicAtomWithSymbolicTerms("q", "b")); assertTrue(evaluated.getRules().size() == 0); } @@ -126,7 +138,7 @@ private static void verifyAnswerSetsBasicMultiInstance(Set answerSets TestUtils.assertAnswerSetsEqual("p(a), p(b), q(a), q(b)", answerSets); } - private static void verifyProgramBasicNegation(InternalProgram evaluated) { + private static void verifyProgramBasicNegation(CompiledProgram evaluated) { TestUtils.assertFactsContainedInProgram(evaluated, TestUtils.basicAtomWithSymbolicTerms("s", "a", "b"), TestUtils.basicAtomWithSymbolicTerms("s", "a", "d")); assertEquals(7, evaluated.getFacts().size()); @@ -137,7 +149,7 @@ private static void verifyAnswerSetsBasicNegation(Set answerSets) { TestUtils.assertAnswerSetsEqual("p(a), q(b), p(c), q(d), r(c), s(a,b), s(a,d)", answerSets); } - private static void verifyProgramPartStratified(InternalProgram evaluated) { + private static void verifyProgramPartStratified(CompiledProgram evaluated) { TestUtils.assertFactsContainedInProgram(evaluated, TestUtils.basicAtomWithSymbolicTerms("p", "a"), TestUtils.basicAtomWithSymbolicTerms("q", "a"), TestUtils.basicAtomWithSymbolicTerms("p", "b"), TestUtils.basicAtomWithSymbolicTerms("m", "c"), TestUtils.basicAtomWithSymbolicTerms("n", "d"), TestUtils.basicAtomWithSymbolicTerms("r", "a"), @@ -152,15 +164,15 @@ private static void verifyAnswerSetsPartStratified(Set answerSets) { "p(a), q(a), p(b), m(c), n(d), r(a), s(a,c,d), t(a,b), or(a)" }, answerSets); } - private static void verifyProgramPositiveRecursive(InternalProgram evaluated) { - Predicate num = Predicate.getInstance("num", 1); - TestUtils.assertFactsContainedInProgram(evaluated, new BasicAtom(Predicate.getInstance("max_num", 1), ConstantTerm.getInstance(10)), - new BasicAtom(num, ConstantTerm.getInstance(0)), - new BasicAtom(num, ConstantTerm.getInstance(1)), new BasicAtom(num, ConstantTerm.getInstance(2)), - new BasicAtom(num, ConstantTerm.getInstance(3)), new BasicAtom(num, ConstantTerm.getInstance(4)), - new BasicAtom(num, ConstantTerm.getInstance(5)), new BasicAtom(num, ConstantTerm.getInstance(6)), - new BasicAtom(num, ConstantTerm.getInstance(7)), new BasicAtom(num, ConstantTerm.getInstance(8)), - new BasicAtom(num, ConstantTerm.getInstance(9)), new BasicAtom(num, ConstantTerm.getInstance(10))); + private static void verifyProgramPositiveRecursive(CompiledProgram evaluated) { + Predicate num = Predicates.getPredicate("num", 1); + TestUtils.assertFactsContainedInProgram(evaluated, Atoms.newBasicAtom(Predicates.getPredicate("max_num", 1), Terms.newConstant(10)), + Atoms.newBasicAtom(num, Terms.newConstant(0)), + Atoms.newBasicAtom(num, Terms.newConstant(1)), Atoms.newBasicAtom(num, Terms.newConstant(2)), + Atoms.newBasicAtom(num, Terms.newConstant(3)), Atoms.newBasicAtom(num, Terms.newConstant(4)), + Atoms.newBasicAtom(num, Terms.newConstant(5)), Atoms.newBasicAtom(num, Terms.newConstant(6)), + Atoms.newBasicAtom(num, Terms.newConstant(7)), Atoms.newBasicAtom(num, Terms.newConstant(8)), + Atoms.newBasicAtom(num, Terms.newConstant(9)), Atoms.newBasicAtom(num, Terms.newConstant(10))); LOGGER.debug("Recursive program evaluated is:\n{}", evaluated.toString()); assertEquals(0, evaluated.getRules().size()); } @@ -169,7 +181,7 @@ private static void verifyAnswerSetsPositiveRecursive(Set answerSets) TestUtils.assertAnswerSetsEqual("max_num(10), num(0), num(1), num(2), num(3), num(4), num(5), num(6), num(7), num(8), num(9), num(10)", answerSets); } - private static void verifyProgramEmptyProg(InternalProgram evaluated) { + private static void verifyProgramEmptyProg(CompiledProgram evaluated) { assertTrue(evaluated.getRules().isEmpty()); assertTrue(evaluated.getRulesById().isEmpty()); assertTrue(evaluated.getPredicateDefiningRules().isEmpty()); @@ -182,7 +194,7 @@ private static void verifyAnswerSetsEmptyProg(Set answerSets) { assertTrue(answerSets.iterator().next().isEmpty()); } - private static void verifyProgramFactsOnly(InternalProgram evaluated) { + private static void verifyProgramFactsOnly(CompiledProgram evaluated) { assertTrue(evaluated.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("a"))); assertTrue(evaluated.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("b"))); assertTrue(evaluated.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("c"))); @@ -196,7 +208,7 @@ private static void verifyAnswerSetsFactsOnly(Set answerSets) { TestUtils.assertAnswerSetsEqual("a, b, c, p(a), q(b,c), r(c,c,a), s(b)", answerSets); } - private static void verifyProgramStratNoFacts(InternalProgram evaluated) { + private static void verifyProgramStratNoFacts(CompiledProgram evaluated) { assertTrue(evaluated.getFacts().isEmpty()); } @@ -205,7 +217,7 @@ private static void verifyAnswerSetsStratNoFacts(Set answerSets) { assertTrue(answerSets.iterator().next().isEmpty()); } - private static void verifyProgramStratWithFacts(InternalProgram evaluated) { + private static void verifyProgramStratWithFacts(CompiledProgram evaluated) { // rules should all be taken care of at this point assertTrue(evaluated.getRules().isEmpty()); assertTrue(evaluated.getRulesById().isEmpty()); @@ -227,7 +239,7 @@ private static void verifyAnswerSetsStratWithFacts(Set answerSets) { TestUtils.assertAnswerSetsEqual("req(a), req(b), incomp(b), base(a), depend_base(a,a), dep_b_hlp(a), depend_further(a)", answerSets); } - private static void verifyProgramEquality(InternalProgram evaluated) { + private static void verifyProgramEquality(CompiledProgram evaluated) { assertEquals(0, evaluated.getRules().size()); assertTrue(evaluated.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("equal"))); } @@ -236,11 +248,11 @@ private static void verifyAnswerSetsEquality(Set answerSets) { TestUtils.assertAnswerSetsEqual("equal", answerSets); } - private static void verifyProgramEqualityWithVar(InternalProgram evaluated) { + private static void verifyProgramEqualityWithVar(CompiledProgram evaluated) { assertEquals(0, evaluated.getRules().size()); - assertTrue(evaluated.getFacts().contains(new BasicAtom(Predicate.getInstance("a", 1), ConstantTerm.getInstance(1)))); - assertTrue(evaluated.getFacts().contains(new BasicAtom(Predicate.getInstance("c", 1), ConstantTerm.getInstance(2)))); - assertTrue(evaluated.getFacts().contains(new BasicAtom(Predicate.getInstance("d", 1), ConstantTerm.getInstance(3)))); + assertTrue(evaluated.getFacts().contains(Atoms.newBasicAtom(Predicates.getPredicate("a", 1), Terms.newConstant(1)))); + assertTrue(evaluated.getFacts().contains(Atoms.newBasicAtom(Predicates.getPredicate("c", 1), Terms.newConstant(2)))); + assertTrue(evaluated.getFacts().contains(Atoms.newBasicAtom(Predicates.getPredicate("d", 1), Terms.newConstant(3)))); } private static void verifyAnswerSetsEqualityWithVar(Set answerSets) { diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluationTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluationTest.java similarity index 53% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluationTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluationTest.java index dc4932785..939bded78 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/StratifiedEvaluationTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/StratifiedEvaluationTest.java @@ -25,7 +25,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.grounder.transformation; +package at.ac.tuwien.kr.alpha.core.programs.transformation; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -33,41 +33,60 @@ import java.io.IOException; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; +import java.util.function.Function; -import org.antlr.v4.runtime.CharStreams; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.api.externals.Externals; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.program.Programs; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.config.InputConfig; -import at.ac.tuwien.kr.alpha.grounder.Instance; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.test.util.TestUtils; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.substitutions.Instance; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +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.externals.Externals; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.GrounderFactory; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.Programs; +import at.ac.tuwien.kr.alpha.core.solver.SolverFactory; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; public class StratifiedEvaluationTest { + private final ProgramParser parser = new ProgramParserImpl(); + private final NormalizeProgramTransformation normalizer = new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); + private final StratifiedEvaluation evaluator = new StratifiedEvaluation(); + private final Function parseAndEvaluate = (str) -> { + return evaluator.apply(AnalyzedProgram.analyzeNormalProgram(normalizer.apply(parser.parse(str)))); + }; + + private final Function> solveCompiledProg = (prog) -> { + AtomStore atomStore = new AtomStoreImpl(); + Grounder grounder = GrounderFactory.getInstance("naive", prog, atomStore, false); + Solver solver = SolverFactory.getInstance(new SystemConfig(), atomStore, grounder); + return solver.collectSet(); + }; + @Test public void testDuplicateFacts() { String aspStr = "p(a). p(b). q(b). q(X) :- p(X)."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(aspStr); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); + CompiledProgram evaluated = parseAndEvaluate.apply(aspStr); Instance qOfB = new Instance(TestUtils.basicAtomWithSymbolicTerms("q", "b").getTerms()); - Set facts = evaluated.getFactsByPredicate().get(at.ac.tuwien.kr.alpha.common.Predicate.getInstance("q", 1)); + Set facts = evaluated.getFactsByPredicate().get(Predicates.getPredicate("q", 1)); int numQOfB = 0; for (Instance at : facts) { if (at.equals(qOfB)) { @@ -80,11 +99,7 @@ public void testDuplicateFacts() { @Test public void testEqualityWithConstantTerms() { String aspStr = "equal :- 1 = 1."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(aspStr); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); + CompiledProgram evaluated = parseAndEvaluate.apply(aspStr); Atom equal = TestUtils.basicAtomWithSymbolicTerms("equal"); assertTrue(evaluated.getFacts().contains(equal)); } @@ -92,48 +107,32 @@ public void testEqualityWithConstantTerms() { @Test public void testEqualityWithVarTerms() { String aspStr = "a(1). a(2). a(3). b(X) :- a(X), X = 1. c(X) :- a(X), X = 2. d(X) :- X = 3, a(X)."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(aspStr); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + CompiledProgram evaluated = parseAndEvaluate.apply(aspStr); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("a(1), a(2), a(3), b(1), c(2), d(3)", answerSets); } @Test public void testNonGroundableRule() { String asp = "p(a). q(a, b). s(X, Y) :- p(X), q(X, Y), r(Y)."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(asp); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + CompiledProgram evaluated = parseAndEvaluate.apply(asp); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("p(a), q(a,b)", answerSets); } @Test public void testCountAggregate() { String asp = "a. b :- 1 <= #count { 1 : a }."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(asp); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + CompiledProgram evaluated = parseAndEvaluate.apply(asp); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("a, b", answerSets); } @Test public void testIntervalFact() { String asp = "a(1..3)."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(asp); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + CompiledProgram evaluated = parseAndEvaluate.apply(asp); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("a(1), a(2), a(3)", answerSets); } @@ -143,26 +142,17 @@ public void testAggregateSpecial() { + "{ chosenThing(X) : thing(X) }.\n" + "chosenSomething :- chosenThing(X).\n" + ":- not chosenSomething.\n" + ":- chosenThing(X), chosenThing(Y), X != Y.\n" + "allThings :- 3 <= #count{ X : thing(X)}. \n" + "chosenMaxThing :- allThings, chosenThing(3).\n" + ":- not chosenMaxThing."; - Alpha system = new Alpha(); - // system.getConfig().setUseNormalizationGrid(true); - InputProgram prg = system.readProgramString(asp); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); + CompiledProgram evaluated = parseAndEvaluate.apply(asp); assertTrue(evaluated.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("allThings"))); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("allThings, thing(1), thing(2), thing(3), chosenMaxThing, chosenSomething, chosenThing(3)", answerSets); } @Test public void testNegatedFixedInterpretationLiteral() { String asp = "stuff(1). stuff(2). smallStuff(X) :- stuff(X), not X > 1."; - Alpha system = new Alpha(); - InputProgram prg = system.readProgramString(asp); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); - Set answerSets = system.solve(evaluated).collect(Collectors.toSet()); + CompiledProgram evaluated = parseAndEvaluate.apply(asp); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("stuff(1), stuff(2), smallStuff(1)", answerSets); } @@ -175,14 +165,12 @@ public static boolean sayTrue(Object o) { @Test public void testNegatedExternalLiteral() throws Exception { String asp = "claimedTruth(bla). truth(X) :- claimedTruth(X), &sayTrue[X]. lie(X) :- claimedTruth(X), not &sayTrue[X]."; - Alpha alpha = new Alpha(); - InputConfig inputCfg = InputConfig.forString(asp); - inputCfg.addPredicateMethod("sayTrue", Externals.processPredicateMethod(this.getClass().getMethod("sayTrue", Object.class))); - InputProgram input = alpha.readProgram(inputCfg); - NormalProgram normal = alpha.normalizeProgram(input); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); - Set answerSets = alpha.solve(evaluated).collect(Collectors.toSet()); + Map externals = new HashMap<>(); + externals.put("sayTrue", Externals.processPredicateMethod(this.getClass().getMethod("sayTrue", Object.class))); + ProgramParser parserWithExternals = new ProgramParserImpl(); + AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normalizer.apply(parserWithExternals.parse(asp, externals))); + CompiledProgram evaluated = new StratifiedEvaluation().apply(analyzed); + Set answerSets = solveCompiledProg.apply(evaluated); TestUtils.assertAnswerSetsEqual("claimedTruth(bla), truth(bla)", answerSets); } @@ -192,11 +180,8 @@ public void testNegatedExternalLiteral() throws Exception { */ @Test public void testPartnerUnitsProblemTopologicalOrder() throws IOException { - Alpha system = new Alpha(); - InputProgram prg = new ProgramParser().parse(CharStreams.fromStream(this.getClass().getResourceAsStream("/partial-eval/pup_topological_order.asp"))); - NormalProgram normal = system.normalizeProgram(prg); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(normal); - InternalProgram evaluated = new StratifiedEvaluation().apply(analyzed); + ASPCore2Program prg = parser.parse(StratifiedEvaluationTest.class.getResourceAsStream("/partial-eval/pup_topological_order.asp")); + CompiledProgram evaluated = new StratifiedEvaluation().apply(AnalyzedProgram.analyzeNormalProgram(normalizer.apply(prg))); assertTrue(evaluated.getRules().isEmpty(), "Not all rules eliminated by stratified evaluation"); assertEquals(57, evaluated.getFacts().size()); } @@ -216,16 +201,18 @@ public void testNegatedLiteralInRecursiveRule() throws IOException { + "inc_value(4), inc_value(5), inc_value(6), inc_value(7), " + "inc_value(8)"; //@formatter:on - InputProgram prog = Programs.fromInputStream( + ASPCore2Program prog = Programs.fromInputStream( StratifiedEvaluationTest.class.getResourceAsStream("/partial-eval/recursive_w_negated_condition.asp"), new HashMap<>()); - Alpha systemStratified = new Alpha(); - systemStratified.getConfig().setEvaluateStratifiedPart(true); - Set asStrat = systemStratified.solve(prog).collect(Collectors.toSet()); + + // Run stratified evaluation and solve + CompiledProgram inputStratEval = new StratifiedEvaluation().apply(AnalyzedProgram.analyzeNormalProgram(normalizer.apply(prog))); + Set asStrat = solveCompiledProg.apply(inputStratEval); TestUtils.assertAnswerSetsEqual(expectedAnswerSet, asStrat); - Alpha systemNoStratEval = new Alpha(); - systemNoStratEval.getConfig().setEvaluateStratifiedPart(false); - Set as = systemNoStratEval.solve(prog).collect(Collectors.toSet()); + + // Solve without stratified evaluation + CompiledProgram inputNoStratEval = InternalProgram.fromNormalProgram(normalizer.apply(prog)); + Set as = solveCompiledProg.apply(inputNoStratEval); TestUtils.assertAnswerSetsEqual(expectedAnswerSet, as); } @@ -258,15 +245,11 @@ public void testRecursiveRanking() { " thing_rank(Y, K),\n" + " R = K + 1."; //@formatter:on - Alpha alpha = new Alpha(); - InputProgram prog = alpha.readProgramString(asp); - AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(alpha.normalizeProgram(prog)); - StratifiedEvaluation evaluation = new StratifiedEvaluation(); - InternalProgram evaluated = evaluation.apply(analyzed); - Predicate rank = Predicate.getInstance("thing_rank", 2); - BasicAtom rank1 = new BasicAtom(rank, ConstantTerm.getSymbolicInstance("a"), ConstantTerm.getInstance(1)); - BasicAtom rank2 = new BasicAtom(rank, ConstantTerm.getSymbolicInstance("b"), ConstantTerm.getInstance(2)); - BasicAtom rank3 = new BasicAtom(rank, ConstantTerm.getSymbolicInstance("c"), ConstantTerm.getInstance(3)); + CompiledProgram evaluated = parseAndEvaluate.apply(asp); + Predicate rank = Predicates.getPredicate("thing_rank", 2); + BasicAtom rank1 = Atoms.newBasicAtom(rank, Terms.newSymbolicConstant("a"), Terms.newConstant(1)); + BasicAtom rank2 = Atoms.newBasicAtom(rank, Terms.newSymbolicConstant("b"), Terms.newConstant(2)); + BasicAtom rank3 = Atoms.newBasicAtom(rank, Terms.newSymbolicConstant("c"), Terms.newConstant(3)); List evaluatedFacts = evaluated.getFacts(); assertTrue(evaluatedFacts.contains(rank1)); assertTrue(evaluatedFacts.contains(rank2)); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateLiteralSplittingTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateLiteralSplittingTest.java similarity index 71% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateLiteralSplittingTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateLiteralSplittingTest.java index 473e40292..4670282dd 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateLiteralSplittingTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateLiteralSplittingTest.java @@ -1,14 +1,15 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - import java.util.List; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.test.util.RuleParser; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.core.test.util.RuleParser; public class AggregateLiteralSplittingTest { @@ -42,32 +43,32 @@ public class AggregateLiteralSplittingTest { @Test public void singlePositiveLiteral() { - BasicRule inputRule = RuleParser.parse(LITERAL_SPLITTING_POS1_ASP); - BasicRule expectedRewrittenRule = RuleParser + Rule inputRule = RuleParser.parse(LITERAL_SPLITTING_POS1_ASP); + Rule expectedRewrittenRule = RuleParser .parse("count_between :- X < #count{N : thing2(N)}, Y > #count{N : thing2(N)}, X = #count{ K : thing1(K) }, Y = #count{ L : thing3(L) }."); - List rewritten = AggregateLiteralSplitting.split(inputRule); + List> rewritten = AggregateLiteralSplitting.split(inputRule); assertEquals(1, rewritten.size()); assertEquals(expectedRewrittenRule, rewritten.get(0)); } @Test public void multiplePositiveLiterals() { - BasicRule inputRule = RuleParser.parse(LITERAL_SPLITTING_POS2_ASP); - BasicRule expectedRewrittenRule = RuleParser + Rule inputRule = RuleParser.parse(LITERAL_SPLITTING_POS2_ASP); + Rule expectedRewrittenRule = RuleParser .parse("count_between :- X < #count{N : thing2(N)}, Y > #count{N : thing2(N)}, Y < #count{L : thing3(L)}, Z = #count{L : thing3(L)}, dom(X), dom1(Y)."); - List rewritten = AggregateLiteralSplitting.split(inputRule); + List> rewritten = AggregateLiteralSplitting.split(inputRule); assertEquals(1, rewritten.size()); assertEquals(expectedRewrittenRule, rewritten.get(0)); } @Test public void singleNegativeLiteral() { - BasicRule inputRule = RuleParser.parse(LITERAL_SPLITTING_NEG1_ASP); - BasicRule expectedRewrittenRule1 = RuleParser + Rule inputRule = RuleParser.parse(LITERAL_SPLITTING_NEG1_ASP); + Rule expectedRewrittenRule1 = RuleParser .parse("count_not_between :- dom(X), dom(Y), not X < #count{N : thing(N)}."); - BasicRule expectedRewrittenRule2 = RuleParser + Rule expectedRewrittenRule2 = RuleParser .parse("count_not_between :- dom(X), dom(Y), not Y > #count{N : thing(N)}."); - List rewritten = AggregateLiteralSplitting.split(inputRule); + List> rewritten = AggregateLiteralSplitting.split(inputRule); assertEquals(2, rewritten.size()); assertTrue(rewritten.contains(expectedRewrittenRule1)); assertTrue(rewritten.contains(expectedRewrittenRule2)); @@ -75,16 +76,16 @@ public void singleNegativeLiteral() { @Test public void multipleNegativeLiterals() { - BasicRule inputRule = RuleParser.parse(LITERAL_SPLITTING_NEG2_ASP); - BasicRule expectedRewrittenRule1 = RuleParser + Rule inputRule = RuleParser.parse(LITERAL_SPLITTING_NEG2_ASP); + Rule expectedRewrittenRule1 = RuleParser .parse("count_not_between :- dom(X), dom(Y), dom(U), dom(V), not X < #count{N : thing(N)}, not U < #count{K : thing(K)}."); - BasicRule expectedRewrittenRule2 = RuleParser + Rule expectedRewrittenRule2 = RuleParser .parse("count_not_between :- dom(X), dom(Y), dom(U), dom(V), not X < #count{N : thing(N)}, not V > #count{K : thing(K)}."); - BasicRule expectedRewrittenRule3 = RuleParser + Rule expectedRewrittenRule3 = RuleParser .parse("count_not_between :- dom(X), dom(Y), dom(U), dom(V), not Y > #count{N : thing(N)}, not U < #count{K : thing(K)}."); - BasicRule expectedRewrittenRule4 = RuleParser + Rule expectedRewrittenRule4 = RuleParser .parse("count_not_between :- dom(X), dom(Y), dom(U), dom(V), not Y > #count{N : thing(N)}, not V > #count{K : thing(K)}."); - List rewritten = AggregateLiteralSplitting.split(inputRule); + List> rewritten = AggregateLiteralSplitting.split(inputRule); assertEquals(4, rewritten.size()); assertTrue(rewritten.contains(expectedRewrittenRule1)); assertTrue(rewritten.contains(expectedRewrittenRule2)); @@ -94,12 +95,12 @@ public void multipleNegativeLiterals() { @Test public void negativeAndPositiveLiteral() { - BasicRule inputRule = RuleParser.parse(LITERAL_SPLITTING_NEG_POS_ASP); - BasicRule expectedRewrittenRule1 = RuleParser + Rule inputRule = RuleParser.parse(LITERAL_SPLITTING_NEG_POS_ASP); + Rule expectedRewrittenRule1 = RuleParser .parse("count_between_and_not_between(U, V, X, Y) :- dom(X), dom(Y), dom(U), dom(V), not X < #count{N : thing(N)}, U < #count{K : thing(K)}, V > #count{K : thing(K)}."); - BasicRule expectedRewrittenRule2 = RuleParser + Rule expectedRewrittenRule2 = RuleParser .parse("count_between_and_not_between(U, V, X, Y) :- dom(X), dom(Y), dom(U), dom(V), not Y > #count{N : thing(N)}, U < #count{K : thing(K)}, V > #count{K : thing(K)}."); - List rewritten = AggregateLiteralSplitting.split(inputRule); + List> rewritten = AggregateLiteralSplitting.split(inputRule); assertEquals(2, rewritten.size()); assertTrue(rewritten.contains(expectedRewrittenRule1)); assertTrue(rewritten.contains(expectedRewrittenRule2)); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateOperatorNormalizationTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateOperatorNormalizationTest.java similarity index 52% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateOperatorNormalizationTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateOperatorNormalizationTest.java index c76d2f559..2b06fab31 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateOperatorNormalizationTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateOperatorNormalizationTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -6,16 +6,18 @@ import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm.ArithmeticOperator; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.test.util.RuleParser; +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.ComparisonLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticOperator; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticTerm; +import at.ac.tuwien.kr.alpha.api.terms.Term; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.test.util.RuleParser; public class AggregateOperatorNormalizationTest { @@ -40,69 +42,69 @@ public class AggregateOperatorNormalizationTest { @Test public void gtPositive() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GT_POS_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - BasicRule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), not X <= #count{N : thing(N)}."); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GT_POS_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + Rule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), not X <= #count{N : thing(N)}."); assertEquals(expectedRewrittenRule, rewritten); } @Test public void ltPositive() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_LT_POS_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - assertOperatorNormalized(rewritten, ComparisonOperator.LE, true); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_LT_POS_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + assertOperatorNormalized(rewritten, ComparisonOperators.LE, true); assertAggregateBoundIncremented(inputRule, rewritten); } @Test public void nePositive() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_NE_POS_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - BasicRule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), not X = #count{N : thing(N)}."); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_NE_POS_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + Rule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), not X = #count{N : thing(N)}."); assertEquals(expectedRewrittenRule, rewritten); } @Test public void gePositive() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GE_POS_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - assertOperatorNormalized(rewritten, ComparisonOperator.LE, false); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GE_POS_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + assertOperatorNormalized(rewritten, ComparisonOperators.LE, false); assertAggregateBoundIncremented(inputRule, rewritten); } @Test public void ltNegative() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_LT_NEG_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - assertOperatorNormalized(rewritten, ComparisonOperator.LE, false); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_LT_NEG_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + assertOperatorNormalized(rewritten, ComparisonOperators.LE, false); assertAggregateBoundIncremented(inputRule, rewritten); } @Test public void neNegative() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_NE_NEG_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - BasicRule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), X = #count{N : thing(N)}."); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_NE_NEG_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + Rule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), X = #count{N : thing(N)}."); assertEquals(expectedRewrittenRule, rewritten); } @Test public void gtNegative() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GT_NEG_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - BasicRule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), X <= #count{N : thing(N)}."); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GT_NEG_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + Rule expectedRewrittenRule = RuleParser.parse("bla :- dom(X), X <= #count{N : thing(N)}."); assertEquals(expectedRewrittenRule, rewritten); } @Test public void geNegative() { - BasicRule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GE_NEG_ASP); - BasicRule rewritten = AggregateOperatorNormalization.normalize(inputRule); - assertOperatorNormalized(rewritten, ComparisonOperator.LE, true); + Rule inputRule = RuleParser.parse(OPERATOR_NORMALIZATION_GE_NEG_ASP); + Rule rewritten = AggregateOperatorNormalization.normalize(inputRule); + assertOperatorNormalized(rewritten, ComparisonOperators.LE, true); assertAggregateBoundIncremented(inputRule, rewritten); } - private static void assertOperatorNormalized(BasicRule rewrittenRule, ComparisonOperator expectedRewrittenOperator, + private static void assertOperatorNormalized(Rule rewrittenRule, ComparisonOperator expectedRewrittenOperator, boolean expectedRewrittenLiteralPositive) { AggregateLiteral rewrittenAggregate = null; for (Literal lit : rewrittenRule.getBody()) { @@ -115,7 +117,7 @@ private static void assertOperatorNormalized(BasicRule rewrittenRule, Comparison assertTrue(expectedRewrittenLiteralPositive == !rewrittenAggregate.isNegated()); } - private static void assertAggregateBoundIncremented(BasicRule sourceRule, BasicRule rewrittenRule) { + private static void assertAggregateBoundIncremented(Rule sourceRule, Rule rewrittenRule) { AggregateLiteral sourceAggregate = null; for (Literal lit : sourceRule.getBody()) { if (lit instanceof AggregateLiteral) { @@ -136,9 +138,9 @@ private static void assertAggregateBoundIncremented(BasicRule sourceRule, BasicR Term comparisonRightHandTerm = addedComparisonLiteral.getAtom().getTerms().get(1); assertTrue(comparisonRightHandTerm instanceof ArithmeticTerm); ArithmeticTerm incrementTerm = (ArithmeticTerm) comparisonRightHandTerm; - assertEquals(ArithmeticOperator.PLUS, incrementTerm.getArithmeticOperator()); - assertEquals(ConstantTerm.getInstance(1), incrementTerm.getRight()); - assertEquals(sourceAggregate.getAtom().getLowerBoundTerm(), incrementTerm.getLeft()); + assertEquals(ArithmeticOperator.PLUS, incrementTerm.getOperator()); + assertEquals(Terms.newConstant(1), incrementTerm.getRightOperand()); + assertEquals(sourceAggregate.getAtom().getLowerBoundTerm(), incrementTerm.getLeftOperand()); } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingContextTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingContextTest.java similarity index 82% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingContextTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingContextTest.java index 67228064c..b5603a9cf 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingContextTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingContextTest.java @@ -1,22 +1,25 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.junit.jupiter.api.Test; - import java.util.Map; import java.util.Set; import java.util.function.Predicate; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateRewritingContext.AggregateInfo; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.ComparisonOperator; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.api.terms.VariableTerm; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates.AggregateRewritingContext.AggregateInfo; public class AggregateRewritingContextTest { @@ -55,9 +58,9 @@ public class AggregateRewritingContextTest { //@formatter:on private static final AggregateRewritingContext rewritingContextForAspString(String asp) { - InputProgram program = new Alpha().readProgramString(asp); + ASPCore2Program program = new ProgramParserImpl().parse(asp); AggregateRewritingContext ctx = new AggregateRewritingContext(); - for (BasicRule rule : program.getRules()) { + for (Rule rule : program.getRules()) { ctx.registerRule(rule); } return ctx; @@ -68,7 +71,7 @@ public void minEqAggregateNoGlobalVars() { AggregateRewritingContext ctx = rewritingContextForAspString(CTX_TEST_MIN_EQ_ASP); Map, Set> functionsToRewrite = ctx.getAggregateFunctionsToRewrite(); assertEquals(1, functionsToRewrite.size()); - ImmutablePair minEq = new ImmutablePair<>(AggregateFunctionSymbol.MIN, ComparisonOperator.EQ); + ImmutablePair minEq = new ImmutablePair<>(AggregateFunctionSymbol.MIN, ComparisonOperators.EQ); assertTrue(functionsToRewrite.containsKey(minEq)); Set minEqAggregateInfos = functionsToRewrite.get(minEq); assertEquals(1, minEqAggregateInfos.size()); @@ -81,7 +84,7 @@ public void countEqAggregateNoGlobalVars() { AggregateRewritingContext ctx = rewritingContextForAspString(CTX_TEST_CNT_EQ_ASP); Map, Set> functionsToRewrite = ctx.getAggregateFunctionsToRewrite(); assertEquals(1, functionsToRewrite.size()); - ImmutablePair cntEq = new ImmutablePair<>(AggregateFunctionSymbol.COUNT, ComparisonOperator.EQ); + ImmutablePair cntEq = new ImmutablePair<>(AggregateFunctionSymbol.COUNT, ComparisonOperators.EQ); assertTrue(functionsToRewrite.containsKey(cntEq)); Set cntEqAggregateInfos = functionsToRewrite.get(cntEq); assertEquals(1, cntEqAggregateInfos.size()); @@ -94,8 +97,8 @@ public void countEqMaxEqGlobalVars() { AggregateRewritingContext ctx = rewritingContextForAspString(CTX_TEST_GRAPH_ASP); Map, Set> functionsToRewrite = ctx.getAggregateFunctionsToRewrite(); assertEquals(2, functionsToRewrite.size()); - ImmutablePair cntEq = new ImmutablePair<>(AggregateFunctionSymbol.COUNT, ComparisonOperator.EQ); - ImmutablePair maxEq = new ImmutablePair<>(AggregateFunctionSymbol.MAX, ComparisonOperator.EQ); + ImmutablePair cntEq = new ImmutablePair<>(AggregateFunctionSymbol.COUNT, ComparisonOperators.EQ); + ImmutablePair maxEq = new ImmutablePair<>(AggregateFunctionSymbol.MAX, ComparisonOperators.EQ); assertTrue(functionsToRewrite.containsKey(cntEq)); assertTrue(functionsToRewrite.containsKey(maxEq)); Set cntEqIds = functionsToRewrite.get(cntEq); @@ -110,10 +113,10 @@ public void countEqMaxEqGlobalVars() { if (globalVars.size() != 2) { return false; } - if (!globalVars.contains(VariableTerm.getInstance("G"))) { + if (!globalVars.contains(Terms.newVariable("G"))) { return false; } - if (!globalVars.contains(VariableTerm.getInstance("V"))) { + if (!globalVars.contains(Terms.newVariable("V"))) { return false; } return true; @@ -126,10 +129,10 @@ public void countEqMaxEqGlobalVars() { if (globalVars.size() != 2) { return false; } - if (!globalVars.contains(VariableTerm.getInstance("G"))) { + if (!globalVars.contains(Terms.newVariable("G"))) { return false; } - if (!globalVars.contains(VariableTerm.getInstance("DMAX"))) { + if (!globalVars.contains(Terms.newVariable("DMAX"))) { return false; } return true; diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingRuleAnalysisTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingRuleAnalysisTest.java similarity index 63% rename from src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingRuleAnalysisTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingRuleAnalysisTest.java index 7e03f303a..a37c217d3 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingRuleAnalysisTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingRuleAnalysisTest.java @@ -1,34 +1,30 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateElement; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm.ArithmeticOperator; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.test.util.RuleParser; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateElement; +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom.AggregateFunctionSymbol; +import at.ac.tuwien.kr.alpha.api.programs.literals.AggregateLiteral; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.api.terms.ArithmeticOperator; +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.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.test.util.RuleParser; public class AggregateRewritingRuleAnalysisTest { @@ -81,7 +77,7 @@ public void nonBindingAggregateNoGlobals1() { Set dependencies = analysis.dependenciesPerAggregate.get(aggregate); assertEquals(1, dependencies.size()); - Literal pXY = new BasicLiteral(new BasicAtom(Predicate.getInstance("p", 2), VariableTerm.getInstance("X"), VariableTerm.getInstance("Y")), true); + Literal pXY = Literals.fromAtom(Atoms.newBasicAtom(Predicates.getPredicate("p", 2), Terms.newVariable("X"), Terms.newVariable("Y")), true); assertTrue(dependencies.contains(pXY)); } @@ -98,21 +94,21 @@ public void nonBindingAggregateNoGlobals2() { Set dependencies = analysis.dependenciesPerAggregate.get(aggregate); assertEquals(3, dependencies.size()); - Literal threePlusY = new ComparisonLiteral( - new ComparisonAtom(VariableTerm.getInstance("X"), - ArithmeticTerm.getInstance(ConstantTerm.getInstance(3), ArithmeticOperator.PLUS, VariableTerm.getInstance("Y")), - ComparisonOperator.EQ), + Literal threePlusY = Literals.fromAtom( + Atoms.newComparisonAtom(Terms.newVariable("X"), + Terms.newArithmeticTerm(Terms.newConstant(3), ArithmeticOperator.PLUS, Terms.newVariable("Y")), + ComparisonOperators.EQ), true); assertTrue(dependencies.contains(threePlusY)); - Literal zPlusFour = new ComparisonLiteral( - new ComparisonAtom(VariableTerm.getInstance("Y"), - ArithmeticTerm.getInstance(VariableTerm.getInstance("Z"), ArithmeticOperator.PLUS, ConstantTerm.getInstance(4)), - ComparisonOperator.EQ), + Literal zPlusFour = Literals.fromAtom( + Atoms.newComparisonAtom(Terms.newVariable("Y"), + Terms.newArithmeticTerm(Terms.newVariable("Z"), ArithmeticOperator.PLUS, Terms.newConstant(4)), + ComparisonOperators.EQ), true); assertTrue(dependencies.contains(zPlusFour)); - Literal rSZ = new BasicLiteral(new BasicAtom(Predicate.getInstance("r", 2), VariableTerm.getInstance("S"), VariableTerm.getInstance("Z")), true); + Literal rSZ = Literals.fromAtom(Atoms.newBasicAtom(Predicates.getPredicate("r", 2), Terms.newVariable("S"), Terms.newVariable("Z")), true); assertTrue(dependencies.contains(rSZ)); } @@ -127,17 +123,17 @@ public void bindingAggregateWithGlobals1() { assertFalse(analysis.dependenciesPerAggregate.get(aggregate).isEmpty()); Set globalVars = analysis.globalVariablesPerAggregate.get(aggregate); - assertTrue(globalVars.contains(VariableTerm.getInstance("G"))); - assertTrue(globalVars.contains(VariableTerm.getInstance("V"))); + assertTrue(globalVars.contains(Terms.newVariable("G"))); + assertTrue(globalVars.contains(Terms.newVariable("V"))); Set dependencies = analysis.dependenciesPerAggregate.get(aggregate); assertEquals(2, dependencies.size()); - Literal graph = new BasicLiteral(new BasicAtom(Predicate.getInstance("graph", 1), VariableTerm.getInstance("G")), true); + Literal graph = Literals.fromAtom(Atoms.newBasicAtom(Predicates.getPredicate("graph", 1), Terms.newVariable("G")), true); assertTrue(dependencies.contains(graph)); - Literal graphVertex = new BasicLiteral( - new BasicAtom(Predicate.getInstance("graph_vertex", 2), VariableTerm.getInstance("G"), VariableTerm.getInstance("V")), true); + Literal graphVertex = Literals.fromAtom( + Atoms.newBasicAtom(Predicates.getPredicate("graph_vertex", 2), Terms.newVariable("G"), Terms.newVariable("V")), true); assertTrue(dependencies.contains(graphVertex)); } @@ -148,42 +144,42 @@ public void bindingAggregateWithGlobals2() { assertEquals(2, analysis.dependenciesPerAggregate.size()); // Verify correct analysis of max aggregate - List vertexDegreeTerms = Collections.singletonList(VariableTerm.getInstance("DV")); - Literal vertexDegreeLiteral = new BasicLiteral(new BasicAtom(Predicate.getInstance("graph_vertex_degree", 3), VariableTerm.getInstance("G"), - VariableTerm.getInstance("V"), VariableTerm.getInstance("DV")), true); + List vertexDegreeTerms = Collections.singletonList(Terms.newVariable("DV")); + Literal vertexDegreeLiteral = Literals.fromAtom(Atoms.newBasicAtom(Predicates.getPredicate("graph_vertex_degree", 3), Terms.newVariable("G"), + Terms.newVariable("V"), Terms.newVariable("DV")), true); List vertexDegreeLiterals = Collections.singletonList(vertexDegreeLiteral); - AggregateElement vertexDegree = new AggregateElement(vertexDegreeTerms, vertexDegreeLiterals); - AggregateLiteral maxAggregate = new AggregateLiteral( - new AggregateAtom(ComparisonOperator.EQ, VariableTerm.getInstance("DMAX"), AggregateFunctionSymbol.MAX, + AggregateElement vertexDegree = Atoms.newAggregateElement(vertexDegreeTerms, vertexDegreeLiterals); + AggregateLiteral maxAggregate = Literals.fromAtom( + Atoms.newAggregateAtom(ComparisonOperators.EQ, Terms.newVariable("DMAX"), AggregateFunctionSymbol.MAX, Collections.singletonList(vertexDegree)), true); assertTrue(analysis.globalVariablesPerAggregate.containsKey(maxAggregate)); Set maxAggrGlobalVars = analysis.globalVariablesPerAggregate.get(maxAggregate); assertEquals(1, maxAggrGlobalVars.size()); - assertTrue(maxAggrGlobalVars.contains(VariableTerm.getInstance("G"))); + assertTrue(maxAggrGlobalVars.contains(Terms.newVariable("G"))); assertTrue(analysis.dependenciesPerAggregate.containsKey(maxAggregate)); Set maxAggrDependencies = analysis.dependenciesPerAggregate.get(maxAggregate); assertEquals(1, maxAggrDependencies.size()); - Literal graph = new BasicLiteral(new BasicAtom(Predicate.getInstance("graph", 1), VariableTerm.getInstance("G")), true); + Literal graph = Literals.fromAtom(Atoms.newBasicAtom(Predicates.getPredicate("graph", 1), Terms.newVariable("G")), true); assertTrue(maxAggrDependencies.contains(graph)); // Verify correct analysis of count aggregate - List maxVertexDegreeTerms = Collections.singletonList(VariableTerm.getInstance("V")); - Literal maxVertexDegreeLiteral = new BasicLiteral(new BasicAtom(Predicate.getInstance("graph_vertex_degree", 3), VariableTerm.getInstance("G"), - VariableTerm.getInstance("V"), VariableTerm.getInstance("DMAX")), true); + List maxVertexDegreeTerms = Collections.singletonList(Terms.newVariable("V")); + Literal maxVertexDegreeLiteral = Literals.fromAtom(Atoms.newBasicAtom(Predicates.getPredicate("graph_vertex_degree", 3), Terms.newVariable("G"), + Terms.newVariable("V"), Terms.newVariable("DMAX")), true); List maxVertexDegreeLiterals = Collections.singletonList(maxVertexDegreeLiteral); - AggregateElement maxVertexDegree = new AggregateElement(maxVertexDegreeTerms, maxVertexDegreeLiterals); - AggregateLiteral countAggregate = new AggregateLiteral( - new AggregateAtom(ComparisonOperator.EQ, VariableTerm.getInstance("N"), AggregateFunctionSymbol.COUNT, + AggregateElement maxVertexDegree = Atoms.newAggregateElement(maxVertexDegreeTerms, maxVertexDegreeLiterals); + AggregateLiteral countAggregate = Literals.fromAtom( + Atoms.newAggregateAtom(ComparisonOperators.EQ, Terms.newVariable("N"), AggregateFunctionSymbol.COUNT, Collections.singletonList(maxVertexDegree)), true); assertTrue(analysis.globalVariablesPerAggregate.containsKey(countAggregate)); Set cntAggrGlobalVars = analysis.globalVariablesPerAggregate.get(countAggregate); assertEquals(2, cntAggrGlobalVars.size()); - assertTrue(cntAggrGlobalVars.contains(VariableTerm.getInstance("G"))); - assertTrue(cntAggrGlobalVars.contains(VariableTerm.getInstance("DMAX"))); + assertTrue(cntAggrGlobalVars.contains(Terms.newVariable("G"))); + assertTrue(cntAggrGlobalVars.contains(Terms.newVariable("DMAX"))); assertTrue(analysis.dependenciesPerAggregate.containsKey(countAggregate)); Set cntAggrDependencies = analysis.dependenciesPerAggregate.get(countAggregate); @@ -200,7 +196,7 @@ public void bindingAggregateGlobalsNotIncluded() { // Check that the #max aggregate does not include "not p(X)" as its dependency. for (Map.Entry> aggregateDependencies : analysis.dependenciesPerAggregate.entrySet()) { - if (aggregateDependencies.getKey().getAtom().getAggregatefunction() == AggregateFunctionSymbol.MAX) { + if (aggregateDependencies.getKey().getAtom().getAggregateFunction() == AggregateFunctionSymbol.MAX) { for (Literal dependency : aggregateDependencies.getValue()) { assertFalse(dependency.isNegated()); } diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingTest.java new file mode 100644 index 000000000..d514d90bd --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/programs/transformation/aggregates/AggregateRewritingTest.java @@ -0,0 +1,252 @@ +package at.ac.tuwien.kr.alpha.core.programs.transformation.aggregates; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.function.Function; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +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.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.GrounderFactory; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.solver.SolverFactory; + +public class AggregateRewritingTest { + + private static final ProgramParser PARSER = new ProgramParserImpl(); + private static final Function> NORMALIZE_AND_SOLVE = (str) -> { + SystemConfig cfg = new SystemConfig(); + ASPCore2Program prog = PARSER.parse(str); + NormalProgram normalized = new NormalizeProgramTransformation(cfg.getAggregateRewritingConfig()).apply(prog); + CompiledProgram compiled = InternalProgram.fromNormalProgram(normalized); + AtomStore atomStore = new AtomStoreImpl(); + Grounder grounder = GrounderFactory.getInstance("naive", compiled, atomStore, cfg.isDebugInternalChecks()); + Solver solver = SolverFactory.getInstance(cfg, atomStore, grounder); + return solver.collectList(); + }; + + //@formatter:off + // Smoke-test case for "X <= #count{...}" aggregate + private static final String CNT_LE1_ASP = + "thing(75..76)." + + "candidate(2..4)." + + "cnt_le(N) :- N <= #count{X : thing(X)}, candidate(N)."; + // Smoke-test case for "X = #count{...}" aggregate + private static final String CNT_EQ1_ASP = + "thing(4..6)." + + "cnt_things(N) :- N = #count{X : thing(X)}."; + // Smoke-test case for non-binding min aggregate + private static final String MIN_GT1_ASP = + "thing(4). thing(7). thing(13). thing(3). " + + "acceptable(8). acceptable(10). acceptable(5). " + + "greater_min_acceptable(T) :- thing(T), T > #min{ A : acceptable(A) }."; + // Smoke-test case for "X = #sum{...}" aggregate + private static final String SUM_EQ1_ASP = + "thing(2). thing(4). thing(6)." + + "sum_things(S) :- S = #sum{K : thing(K)}."; + // Smoke-test case for "X = #sum{...}" aggregate + private static final String SUM_LE1_ASP = + "thing(2). thing(4). thing(6). bound(11)." + + "bound_le_sum(B) :- B <= #sum{K : thing(K)}, bound(B)."; + + // Basic ASP representation of a triangular undirected graph, used across multiple test cases + private static final String TEST_GRAPH_ASP = + "graph(g1)." + + "graph_undirected(g1)." + + "graph_vertex(g1, 1)." + + "graph_vertex(g1, 2)." + + "graph_vertex(g1 ,3)." + + "graph_edge(g1, e(1, 2))." + + "graph_edge(g1, e(2, 3))." + + "graph_edge(g1, e(3, 1))." + + "graph_directed(G) :- graph(G), not graph_undirected(G)." + + "err_directedness(G) :- graph(G), graph_directed(G), graph_undirected(G)." + + "err_directedness(G) :- graph(G), not graph_directed(G), not graph_undirected(G)." + + ":- err_directedness(_)." + + "err_undirected_edges(G, V1, V2) :- graph_edge(G, e(V1, V2)), graph_edge(G, e(V2, V1))." + + ":- err_undirected_edges(_, _, _)."; + private static final String VERTEX_DEGREE_ASP = TEST_GRAPH_ASP + + "graph_vertex_degree(G, V, D) :-" + + " graph(G)," + + " graph_vertex(G, V)," + + " D = #count{ VN : graph_edge(G, e(V, VN)); VN : graph_edge(G, e(VN, V)) }."; + private static final String NUM_MAX_DEGREE_VERTICES_ASP = VERTEX_DEGREE_ASP + + "graph_max_degree_vertices(G, DMAX, N) :-" + + " graph(G)," + + " DMAX = #max{ DV : graph_vertex_degree(G, V, DV)}," + + " N = #count{ V : graph_vertex_degree(G, V, DMAX)}."; + private static final String COMPLEX_EQUALITY_WITH_GLOBALS = + "p(1..10)." + + "q :- X = #count { Y : p( Y ) }, X = #count { Z : p( Z ) }," + + " Y = #count { X : p( X ) }, 1 <= #count { X : p( X ) }, Z = #max { W : p( W ) }."; + //@formatter:on + + @Test + public void countLeSortingGridSimple() { + List answerSets = NORMALIZE_AND_SOLVE.apply(CNT_LE1_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate thing = Predicates.getPredicate("thing", 1); + Predicate candidate = Predicates.getPredicate("candidate", 1); + Predicate cntLe = Predicates.getPredicate("cnt_le", 1); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(75)))); + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(76)))); + + assertTrue(answerSet.getPredicateInstances(candidate).contains(Atoms.newBasicAtom(candidate, Terms.newConstant(2)))); + assertTrue(answerSet.getPredicateInstances(candidate).contains(Atoms.newBasicAtom(candidate, Terms.newConstant(3)))); + assertTrue(answerSet.getPredicateInstances(candidate).contains(Atoms.newBasicAtom(candidate, Terms.newConstant(4)))); + + assertTrue(answerSet.getPredicates().contains(cntLe)); + assertTrue(answerSet.getPredicateInstances(cntLe).contains(Atoms.newBasicAtom(cntLe, Terms.newConstant(2)))); + } + + @Test + public void countEqSimple() { + List answerSets = NORMALIZE_AND_SOLVE.apply(CNT_EQ1_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate thing = Predicates.getPredicate("thing", 1); + Predicate cntThings = Predicates.getPredicate("cnt_things", 1); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(4)))); + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(5)))); + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(6)))); + + assertTrue(answerSet.getPredicates().contains(cntThings)); + assertTrue(answerSet.getPredicateInstances(cntThings).contains(Atoms.newBasicAtom(cntThings, Terms.newConstant(3)))); + } + + @Test + public void countLeCountingGridSimple() { + List answerSets = NORMALIZE_AND_SOLVE.apply(CNT_LE1_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate thing = Predicates.getPredicate("thing", 1); + Predicate candidate = Predicates.getPredicate("candidate", 1); + Predicate cntLe = Predicates.getPredicate("cnt_le", 1); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(75)))); + assertTrue(answerSet.getPredicateInstances(thing).contains(Atoms.newBasicAtom(thing, Terms.newConstant(76)))); + + assertTrue(answerSet.getPredicateInstances(candidate).contains(Atoms.newBasicAtom(candidate, Terms.newConstant(2)))); + assertTrue(answerSet.getPredicateInstances(candidate).contains(Atoms.newBasicAtom(candidate, Terms.newConstant(3)))); + assertTrue(answerSet.getPredicateInstances(candidate).contains(Atoms.newBasicAtom(candidate, Terms.newConstant(4)))); + + assertTrue(answerSet.getPredicates().contains(cntLe)); + assertTrue(answerSet.getPredicateInstances(cntLe).contains(Atoms.newBasicAtom(cntLe, Terms.newConstant(2)))); + } + + @Test + public void countEqGlobalVars() { + List answerSets = NORMALIZE_AND_SOLVE.apply(VERTEX_DEGREE_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate vertexDegree = Predicates.getPredicate("graph_vertex_degree", 3); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicates().contains(vertexDegree)); + assertTrue(answerSet.getPredicateInstances(vertexDegree) + .contains(Atoms.newBasicAtom(vertexDegree, Terms.newSymbolicConstant("g1"), Terms.newConstant(1), Terms.newConstant(2)))); + assertTrue(answerSet.getPredicateInstances(vertexDegree) + .contains(Atoms.newBasicAtom(vertexDegree, Terms.newSymbolicConstant("g1"), Terms.newConstant(2), Terms.newConstant(2)))); + assertTrue(answerSet.getPredicateInstances(vertexDegree) + .contains(Atoms.newBasicAtom(vertexDegree, Terms.newSymbolicConstant("g1"), Terms.newConstant(3), Terms.newConstant(2)))); + } + + @Test + // Test "count eq" and "max eq" together with global vars + public void graphVerticesOfMaxDegree() { + List answerSets = NORMALIZE_AND_SOLVE.apply(NUM_MAX_DEGREE_VERTICES_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate maxDegreeVertices = Predicates.getPredicate("graph_max_degree_vertices", 3); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicates().contains(maxDegreeVertices)); + assertTrue(answerSet.getPredicateInstances(maxDegreeVertices) + .contains(Atoms.newBasicAtom(maxDegreeVertices, Terms.newSymbolicConstant("g1"), Terms.newConstant(2), Terms.newConstant(3)))); + } + + @Test + public void greaterMin() { + List answerSets = NORMALIZE_AND_SOLVE.apply(MIN_GT1_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate greaterMin = Predicates.getPredicate("greater_min_acceptable", 1); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicates().contains(greaterMin)); + assertTrue(answerSet.getPredicateInstances(greaterMin).contains(Atoms.newBasicAtom(greaterMin, Terms.newConstant(7)))); + assertTrue(answerSet.getPredicateInstances(greaterMin).contains(Atoms.newBasicAtom(greaterMin, Terms.newConstant(13)))); + } + + @Test + public void sumEquals1() { + List answerSets = NORMALIZE_AND_SOLVE.apply(SUM_EQ1_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate sumThings = Predicates.getPredicate("sum_things", 1); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicates().contains(sumThings)); + assertEquals(1, answerSet.getPredicateInstances(sumThings).size()); + assertTrue(answerSet.getPredicateInstances(sumThings).contains(Atoms.newBasicAtom(sumThings, Terms.newConstant(12)))); + } + + @Test + public void sumLessOrEqual1() { + List answerSets = NORMALIZE_AND_SOLVE.apply(SUM_LE1_ASP); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate boundLe = Predicates.getPredicate("bound_le_sum", 1); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicates().contains(boundLe)); + assertTrue(answerSet.getPredicateInstances(boundLe).contains(Atoms.newBasicAtom(boundLe, Terms.newConstant(11)))); + } + + @Test + @Disabled("Open issue, as dependency analysis includes cyclic output-dependency, which it should not.") + public void setComplexEqualityWithGlobals() { + List answerSets = NORMALIZE_AND_SOLVE.apply(COMPLEX_EQUALITY_WITH_GLOBALS); + assertEquals(1, answerSets.size()); + AnswerSet answerSet = answerSets.get(0); + Predicate q = Predicates.getPredicate("q", 0); + + // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); + + assertTrue(answerSet.getPredicates().contains(q)); + assertTrue(answerSet.getPredicateInstances(q).contains(Atoms.newBasicAtom(q))); + } + +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/AggregateRegressionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AggregateRegressionTest.java similarity index 73% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/AggregateRegressionTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AggregateRegressionTest.java index 7d9c32660..8b12f3866 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/AggregateRegressionTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AggregateRegressionTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -11,7 +11,7 @@ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @ParameterizedTest -@MethodSource("at.ac.tuwien.kr.alpha.solver.RegressionTestConfigProvider#provideAggregateTestConfigs") +@MethodSource("at.ac.tuwien.kr.alpha.core.solver.RegressionTestConfigProvider#provideAggregateTestConfigs") public @interface AggregateRegressionTest { } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/AggregatesTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AggregatesTest.java similarity index 96% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/AggregatesTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AggregatesTest.java index cd1cc9574..10e217154 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/AggregatesTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AggregatesTest.java @@ -23,13 +23,13 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSet; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSets; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSetsWithBase; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.ignoreTestForNaiveSolver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.ignoreTestForSimplifiedSumAggregates; +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.ignoreTestForNaiveSolver; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.ignoreTestForSimplifiedSumAggregates; /** * Tests if correct answer sets for programs containing aggregates are computed. @@ -37,7 +37,7 @@ public class AggregatesTest { private static final String LS = System.lineSeparator(); - + @AggregateRegressionTest public void aggregateCountLeGroundPositive(RegressionTestConfig cfg) { String program = "a." + LS @@ -233,7 +233,7 @@ public void aggregateCountGroundNegative(RegressionTestConfig cfg) { + "c :- 1 <= #count { 1 : a }."; assertRegressionTestAnswerSets(cfg, program, "a,c", "b"); } - + @AggregateRegressionTest public void aggregateCountNonGroundPositive(RegressionTestConfig cfg) { String program = "n(1..3)." + LS @@ -244,7 +244,7 @@ public void aggregateCountNonGroundPositive(RegressionTestConfig cfg) { "", "x(1)", "x(2)", "x(3)", "x(1), x(2)", "x(1), x(3)", "x(2), x(3)", "x(1), x(2), x(3), ok"); } - + @AggregateRegressionTest public void aggregateCountNonGroundLowerAndUpper(RegressionTestConfig cfg) { String program = "n(1..3)." + LS @@ -258,14 +258,14 @@ public void aggregateCountNonGroundLowerAndUpper(RegressionTestConfig cfg) { "", "x(1)", "x(2)", "x(3)", "x(1), x(2), ok", "x(1), x(3), ok", "x(2), x(3), ok", "x(1), x(2), x(3), exceedsMax"); } - + @AggregateRegressionTest public void aggregateSumGroundLower(RegressionTestConfig cfg) { String program = "a." + LS + "b :- 5 <= #sum { 2 : a; 3 }."; assertRegressionTestAnswerSet(cfg, program, "a,b"); } - + @AggregateRegressionTest public void aggregateSumNonGroundLowerAndUpper(RegressionTestConfig cfg) { String program = "n(1..3)." + LS @@ -279,7 +279,7 @@ public void aggregateSumNonGroundLowerAndUpper(RegressionTestConfig cfg) { "", "x(1)", "x(2)", "x(3), ok", "x(1), x(2), ok", "x(1), x(3), ok", "x(2), x(3), exceedsMax", "x(1), x(2), x(3), exceedsMax"); } - + @AggregateRegressionTest public void aggregateSumNonGroundLower(RegressionTestConfig cfg) { String program = "n(1..3)." + LS @@ -311,7 +311,7 @@ public void aggregateSumComputed(RegressionTestConfig cfg) { "x(2), x(3), min(0), min(1), min(2), min(3), min(4), min(5), sum(5)", "x(1), x(2), x(3), min(0), min(1), min(2), min(3), min(4), min(5), min(6), sum(6)"); } - + @AggregateRegressionTest public void aggregateCountGlobalVariable(RegressionTestConfig cfg) { String program = "box(1..2)." + LS @@ -322,7 +322,7 @@ public void aggregateCountGlobalVariable(RegressionTestConfig cfg) { assertRegressionTestAnswerSetsWithBase(cfg, program, "box(1), box(2), in(1,1), in(1,2), in(2,2)", "full(2)"); } - + @AggregateRegressionTest public void aggregateSumGlobalVariable(RegressionTestConfig cfg) { String program = "box(1..2)." + LS diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/AntecedentTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AntecedentTest.java similarity index 95% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/AntecedentTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AntecedentTest.java index 0dce2db91..a2cb52826 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/AntecedentTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AntecedentTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; import java.util.HashSet; diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/ArithmeticTermsTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ArithmeticTermsTest.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/ArithmeticTermsTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ArithmeticTermsTest.java index 6ca16ce0e..b232ba659 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/ArithmeticTermsTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ArithmeticTermsTest.java @@ -1,7 +1,7 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSet; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSetsWithBase; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.assertRegressionTestAnswerSet; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.assertRegressionTestAnswerSetsWithBase; /** * Tests ASP programs containing arithmetic terms at arbitrary positions. diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounterTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounterTests.java new file mode 100644 index 000000000..7e2adb491 --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/AtomCounterTests.java @@ -0,0 +1,140 @@ +/** + * 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 + * 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 static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import at.ac.tuwien.kr.alpha.api.programs.atoms.AggregateAtom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +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.comparisons.ComparisonOperators; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +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.ChoiceAtom; +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.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; +import at.ac.tuwien.kr.alpha.core.rules.InternalRule; + +public class AtomCounterTests { + + private AtomStore atomStore; + + @BeforeEach + public void setUp() { + this.atomStore = new AtomStoreImpl(); + } + + @Test + public void testGetNumberOfAtoms() { + final AtomCounter atomCounter = atomStore.getAtomCounter(); + + expectGetNumberOfAtoms(atomCounter, "BasicAtomImpl", 0); + expectGetNumberOfAtoms(atomCounter, "AggregateAtomImpl", 0); + expectGetNumberOfAtoms(atomCounter, "ChoiceAtom", 0); + expectGetNumberOfAtoms(atomCounter, "RuleAtom", 0); + + createBasicAtom1(); + createBasicAtom2(); + createAggregateAtom(); + createChoiceAtom(); + createRuleAtom(); + + expectGetNumberOfAtoms(atomCounter, "BasicAtomImpl", 2); + expectGetNumberOfAtoms(atomCounter, "AggregateAtomImpl", 1); + expectGetNumberOfAtoms(atomCounter, "ChoiceAtom", 1); + expectGetNumberOfAtoms(atomCounter, "RuleAtom", 1); + } + + @Test + public void testGetStatsByType() { + final AtomCounter atomCounter = atomStore.getAtomCounter(); + + createBasicAtom1(); + createBasicAtom2(); + createAggregateAtom(); + createChoiceAtom(); + createRuleAtom(); + + expectGetStatsByType(atomCounter, "BasicAtomImpl", 2); + expectGetStatsByType(atomCounter, "AggregateAtomImpl", 1); + expectGetStatsByType(atomCounter, "ChoiceAtom", 1); + expectGetStatsByType(atomCounter, "RuleAtom", 1); + } + + private void createBasicAtom1() { + atomStore.putIfAbsent(Atoms.newBasicAtom(Predicates.getPredicate("p", 0))); + } + + private void createBasicAtom2() { + atomStore.putIfAbsent(Atoms.newBasicAtom(Predicates.getPredicate("q", 1), Terms.newConstant(1))); + } + + private void createAggregateAtom() { + final ConstantTerm c1 = Terms.newConstant(1); + final ConstantTerm c2 = Terms.newConstant(2); + final ConstantTerm c3 = Terms.newConstant(3); + List basicTerms = Arrays.asList(c1, c2, c3); + AggregateAtom.AggregateElement aggregateElement = Atoms.newAggregateElement(basicTerms, + Collections.singletonList(Atoms.newBasicAtom(Predicates.getPredicate("p", 3), c1, c2, c3).toLiteral())); + atomStore.putIfAbsent(Atoms.newAggregateAtom(ComparisonOperators.LE, c1, null, null, AggregateAtom.AggregateFunctionSymbol.COUNT, + Collections.singletonList(aggregateElement))); + } + + private void createChoiceAtom() { + atomStore.putIfAbsent(ChoiceAtom.on(1)); + } + + private void createRuleAtom() { + BasicAtom atomAA = Atoms.newBasicAtom(Predicates.getPredicate("aa", 0)); + CompiledRule ruleAA = new InternalRule(Heads.newNormalHead(atomAA), + Collections.singletonList(Atoms.newBasicAtom(Predicates.getPredicate("bb", 0)).toLiteral(false))); + atomStore.putIfAbsent(new RuleAtom(ruleAA, new BasicSubstitution())); + } + + private void expectGetNumberOfAtoms(AtomCounter atomCounter, String classOfAtoms, int expectedNumber) { + assertEquals(expectedNumber, atomCounter.getNumberOfAtoms(classOfAtoms), "Unexpected number of " + classOfAtoms + "s"); + } + + private void expectGetStatsByType(AtomCounter atomCounter, String classOfAtoms, int expectedNumber) { + assertTrue(atomCounter.getStatsByType().contains(classOfAtoms + ": " + expectedNumber), + "Expected number of " + classOfAtoms + "s not contained in stats string"); + } + +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/ChoiceManagerTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManagerTests.java similarity index 71% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/ChoiceManagerTests.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManagerTests.java index 41094f273..0df75abb2 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/ChoiceManagerTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ChoiceManagerTests.java @@ -23,9 +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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collection; @@ -33,17 +33,18 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.grounder.NaiveGrounder; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.NaiveGrounder; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; public class ChoiceManagerTests { private Grounder grounder; @@ -52,11 +53,9 @@ public class ChoiceManagerTests { @BeforeEach public void setUp() { - Alpha system = new Alpha(); String testProgram = "h :- b1, b2, not b3, not b4."; - InputProgram parsedProgram = new ProgramParser().parse(testProgram); - NormalProgram normalProgram = system.normalizeProgram(parsedProgram); - InternalProgram internalProgram = InternalProgram.fromNormalProgram(normalProgram); + ASPCore2Program parsedProgram = new ProgramParserImpl().parse(testProgram); + CompiledProgram internalProgram = InternalProgram.fromNormalProgram(new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG).apply(parsedProgram)); atomStore = new AtomStoreImpl(); grounder = new NaiveGrounder(internalProgram, atomStore, true); WritableAssignment assignment = new TrailAssignment(atomStore); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/HanoiTowerTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/HanoiTowerTest.java similarity index 73% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/HanoiTowerTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/HanoiTowerTest.java index 7c67cc49e..9083e3e6c 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/HanoiTowerTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/HanoiTowerTest.java @@ -23,9 +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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; @@ -33,20 +33,21 @@ import java.util.Optional; import java.util.SortedSet; -import org.antlr.v4.runtime.CharStreams; import org.junit.jupiter.api.Disabled; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.test.util.TestUtils; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Tests {@link AbstractSolver} using some hanoi tower test cases (see https://en.wikipedia.org/wiki/Tower_of_Hanoi). @@ -58,8 +59,6 @@ public class HanoiTowerTest { private static final Logger LOGGER = LoggerFactory.getLogger(HanoiTowerTest.class); private static final int DEBUG_TIMEOUT_FACTOR = 5; - - private final ProgramParser parser = new ProgramParser(); @RegressionTest @Disabled("disabled to save resources during CI") @@ -102,38 +101,38 @@ private void testHanoiTower(int instance, RegressionTestConfig cfg) throws IOExc } private void testHanoiTower(String instance, RegressionTestConfig cfg) throws IOException { - InputProgram.Builder programBuilder = InputProgram.builder(); - programBuilder.accumulate(parser.parse(CharStreams.fromPath(Paths.get("src", "test", "resources", "HanoiTower_Alpha.asp")))); - programBuilder.accumulate(parser.parse(CharStreams.fromPath(Paths.get("src", "test", "resources", "HanoiTower_instances", instance + ".asp")))); - InputProgram program = programBuilder.build(); - Solver solver = TestUtils.buildSolverForRegressionTest(program, cfg); + ASPCore2Program prog = new ProgramParserImpl().parse( + Paths.get("src", "test", "resources", "HanoiTower_Alpha.asp"), + Paths.get("src", "test", "resources", "HanoiTower_instances", instance + ".asp")); + Solver solver = TestUtils.buildSolverForRegressionTest(prog, cfg); Optional answerSet = solver.stream().findFirst(); assertTrue(answerSet.isPresent()); - checkGoal(program, answerSet.get()); + checkGoal(prog, answerSet.get()); } /** - * Conducts a very simple, non-comprehensive goal check (i.e. it may classify answer sets as correct that are actually wrong) by checking if for every goal/3 + * Conducts a very simple, non-comprehensive goal check (i.e. it may classify answer sets as correct that are actually wrong) by checking if + * for every goal/3 * fact in the input there is a corresponding on/3 atom in the output. */ - private void checkGoal(InputProgram parsedProgram, AnswerSet answerSet) { - Predicate ongoal = Predicate.getInstance("ongoal", 2); - Predicate on = Predicate.getInstance("on", 3); + private void checkGoal(ASPCore2Program parsedProgram, AnswerSet answerSet) { + Predicate ongoal = Predicates.getPredicate("ongoal", 2); + Predicate on = Predicates.getPredicate("on", 3); int steps = getSteps(parsedProgram); SortedSet onInstancesInAnswerSet = answerSet.getPredicateInstances(on); for (Atom atom : parsedProgram.getFacts()) { if (atom.getPredicate().getName().equals(ongoal.getName()) && atom.getPredicate().getArity() == ongoal.getArity()) { Term expectedTop = atom.getTerms().get(0); Term expectedBottom = atom.getTerms().get(1); - Term expectedSteps = ConstantTerm.getInstance(steps); - Atom expectedAtom = new BasicAtom(on, expectedSteps, expectedBottom, expectedTop); + Term expectedSteps = Terms.newConstant(steps); + Atom expectedAtom = Atoms.newBasicAtom(on, expectedSteps, expectedBottom, expectedTop); assertTrue(onInstancesInAnswerSet.contains(expectedAtom), "Answer set does not contain " + expectedAtom); } } } - private int getSteps(InputProgram parsedProgram) { - Predicate steps = Predicate.getInstance("steps", 1); + private int getSteps(ASPCore2Program parsedProgram) { + Predicate steps = Predicates.getPredicate("steps", 1); for (Atom atom : parsedProgram.getFacts()) { if (atom.getPredicate().getName().equals(steps.getName()) && atom.getPredicate().getArity() == steps.getArity()) { return Integer.valueOf(atom.getTerms().get(0).toString()); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/HeadBodyTransformationTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/HeadBodyTransformationTests.java similarity index 93% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/HeadBodyTransformationTests.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/HeadBodyTransformationTests.java index fccae0ca2..07839eda8 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/HeadBodyTransformationTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/HeadBodyTransformationTests.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.solver; +package at.ac.tuwien.kr.alpha.core.solver; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -36,10 +36,11 @@ import org.junit.jupiter.api.Disabled; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.test.util.TestUtils; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Tests rule transformations described in the following research paper, and their effects on performance: @@ -177,7 +178,7 @@ public void testProgramA_Transformed_N16(RegressionTestConfig cfg) { TestUtils.runWithTimeout(cfg, timeout, DEBUG_TIMEOUT_FACTOR, () -> test(constructProgramA_TransformationA(16), cfg)); } - private void test(InputProgram program, RegressionTestConfig cfg) { + private void test(ASPCore2Program program, RegressionTestConfig cfg) { Solver solver = TestUtils.buildSolverForRegressionTest(program, cfg); Optional answerSet = solver.stream().findFirst(); assertFalse(answerSet.isPresent()); @@ -188,7 +189,7 @@ private void test(InputProgram program, RegressionTestConfig cfg) { * * @param n */ - private InputProgram constructProgramB(int n) { + private ASPCore2Program constructProgramB(int n) { int numberOfRules = 3 * n + 1; List strRules = new ArrayList<>(numberOfRules); strRules.add("x :- not x."); @@ -202,7 +203,7 @@ private InputProgram constructProgramB(int n) { * * @param n */ - private InputProgram constructProgramB_TransformationB(int n) { + private ASPCore2Program constructProgramB_TransformationB(int n) { int numberOfRules = 6 * n + 2; List strRules = new ArrayList<>(numberOfRules); strRules.add("b_notX :- not x."); @@ -217,7 +218,7 @@ private InputProgram constructProgramB_TransformationB(int n) { * * @param n */ - private InputProgram constructProgramA(int n) { + private ASPCore2Program constructProgramA(int n) { int numberOfRules = 4 * n + 1; List strRules = new ArrayList<>(numberOfRules); strRules.add(createXCRule(n)); @@ -231,7 +232,7 @@ private InputProgram constructProgramA(int n) { * * @param n */ - private InputProgram constructProgramA_TransformationA(int n) { + private ASPCore2Program constructProgramA_TransformationA(int n) { int numberOfRules = 7 * n + 2; List strRules = new ArrayList<>(numberOfRules); strRules.addAll(createXCRules_TransformationA(n)); @@ -240,10 +241,10 @@ private InputProgram constructProgramA_TransformationA(int n) { return checkNumberOfRulesAndParse(strRules, numberOfRules); } - private InputProgram checkNumberOfRulesAndParse(List strRules, int numberOfRules) { + private ASPCore2Program checkNumberOfRulesAndParse(List strRules, int numberOfRules) { assertEquals(numberOfRules, strRules.size()); String strProgram = strRules.stream().collect(Collectors.joining(System.lineSeparator())); - InputProgram parsedProgram = new ProgramParser().parse(strProgram); + ASPCore2Program parsedProgram = new ProgramParserImpl().parse(strProgram); assertEquals(numberOfRules, parsedProgram.getRules().size()); return parsedProgram; } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/LearnedNoGoodDeletionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/LearnedNoGoodDeletionTest.java similarity index 93% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/LearnedNoGoodDeletionTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/LearnedNoGoodDeletionTest.java index 3a0ffc751..a4fd12227 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/LearnedNoGoodDeletionTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/LearnedNoGoodDeletionTest.java @@ -25,9 +25,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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -40,11 +40,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.NoGoodInterface.Type; +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 at.ac.tuwien.kr.alpha.core.common.NoGoodInterface.Type; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; public class LearnedNoGoodDeletionTest { @@ -53,7 +53,7 @@ public class LearnedNoGoodDeletionTest { public LearnedNoGoodDeletionTest() { AtomStore atomStore = new AtomStoreImpl(); - AtomStoreTest.fillAtomStore(atomStore, 200); + TestUtils.fillAtomStore(atomStore, 200); WritableAssignment assignment = new TrailAssignment(atomStore); assignment.growForMaxAtomId(); store = new NoGoodStoreAlphaRoaming(assignment); @@ -152,4 +152,4 @@ private Map countNoGoodsByType(NoGoodStore store) { } return counters; } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/NaiveNoGoodStoreTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStoreTest.java similarity index 95% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/NaiveNoGoodStoreTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStoreTest.java index 6d2ebdbe9..b7f29a6ef 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/NaiveNoGoodStoreTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/NaiveNoGoodStoreTest.java @@ -1,12 +1,12 @@ -package at.ac.tuwien.kr.alpha.solver; - -import static at.ac.tuwien.kr.alpha.common.NoGood.fact; -import static at.ac.tuwien.kr.alpha.common.NoGood.headFirst; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; -import static at.ac.tuwien.kr.alpha.solver.AntecedentTest.antecedentsEquals; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.MBT; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; +package at.ac.tuwien.kr.alpha.core.solver; + +import static at.ac.tuwien.kr.alpha.core.common.NoGood.fact; +import static at.ac.tuwien.kr.alpha.core.common.NoGood.headFirst; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; +import static at.ac.tuwien.kr.alpha.core.solver.AntecedentTest.antecedentsEquals; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.MBT; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -17,11 +17,11 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +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 at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Copyright (c) 2017, the Alpha Team. @@ -40,7 +40,7 @@ public NaiveNoGoodStoreTest() { @BeforeEach public void setUp() { store.clear(); - AtomStoreTest.fillAtomStore(atomStore, 200); + TestUtils.fillAtomStore(atomStore, 200); assignment.growForMaxAtomId(); } @@ -596,4 +596,4 @@ public void propagationAtLowerDecisionLevel() { assertEquals(TRUE, entry.getTruth()); assertEquals(2, entry.getDecisionLevel()); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/NoGoodStoreAlphaRoamingTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoamingTest.java similarity index 95% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/NoGoodStoreAlphaRoamingTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoamingTest.java index c278f8909..7c86b69bf 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/NoGoodStoreAlphaRoamingTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/NoGoodStoreAlphaRoamingTest.java @@ -1,12 +1,12 @@ -package at.ac.tuwien.kr.alpha.solver; - -import static at.ac.tuwien.kr.alpha.common.NoGood.fact; -import static at.ac.tuwien.kr.alpha.common.NoGood.headFirst; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; -import static at.ac.tuwien.kr.alpha.solver.AntecedentTest.antecedentsEquals; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.MBT; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; +package at.ac.tuwien.kr.alpha.core.solver; + +import static at.ac.tuwien.kr.alpha.core.common.NoGood.fact; +import static at.ac.tuwien.kr.alpha.core.common.NoGood.headFirst; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; +import static at.ac.tuwien.kr.alpha.core.solver.AntecedentTest.antecedentsEquals; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.MBT; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -17,11 +17,11 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.NoGood; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +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 at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Copyright (c) 2017, the Alpha Team. @@ -34,7 +34,7 @@ public class NoGoodStoreAlphaRoamingTest { public NoGoodStoreAlphaRoamingTest() { atomStore = new AtomStoreImpl(); - AtomStoreTest.fillAtomStore(atomStore, 200); + TestUtils.fillAtomStore(atomStore, 200); assignment = new TrailAssignment(atomStore); assignment.growForMaxAtomId(); store = new NoGoodStoreAlphaRoaming(assignment); @@ -623,4 +623,4 @@ public void alphaWatchNotIgnored() { assertNull(store.propagate()); assertEquals(TRUE, assignment.getTruth(1)); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/OmigaBenchmarksTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/OmigaBenchmarksTest.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/OmigaBenchmarksTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/OmigaBenchmarksTest.java index c9654ea6c..4962ddc4c 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/OmigaBenchmarksTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/OmigaBenchmarksTest.java @@ -23,21 +23,20 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Paths; import java.util.Optional; -import org.antlr.v4.runtime.CharStreams; import org.junit.jupiter.api.Disabled; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.test.util.TestUtils; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Tests {@link AbstractSolver} using Omiga benchmark problems. @@ -49,7 +48,7 @@ public class OmigaBenchmarksTest { private static final Logger LOGGER = LoggerFactory.getLogger(OmigaBenchmarksTest.class); private static final int DEBUG_TIMEOUT_FACTOR = 15; - + @RegressionTest public void test3Col_10_18(RegressionTestConfig cfg) { long timeout = 10000L; @@ -104,9 +103,11 @@ public void testReach_4(RegressionTestConfig cfg) { } private void test(String folder, String aspFileName, RegressionTestConfig cfg) throws IOException { - InputProgram prog = new ProgramParser().parse(CharStreams.fromPath(Paths.get("benchmarks", "omiga", "omiga-testcases", folder, aspFileName))); @SuppressWarnings("unused") - Optional answerSet = TestUtils.buildSolverForRegressionTest(prog, cfg).stream().findFirst(); + Optional answerSet = TestUtils + .buildSolverForRegressionTest( + new ProgramParserImpl().parse(Files.newInputStream(Paths.get("benchmarks", "omiga", "omiga-testcases", folder, aspFileName))), cfg) + .stream().findFirst(); // System.out.println(answerSet); // TODO: check correctness of answer set } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/PartSubpartConfigurationTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/PartSubpartConfigurationTest.java similarity index 95% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/PartSubpartConfigurationTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/PartSubpartConfigurationTest.java index d421de949..f39a9434a 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/PartSubpartConfigurationTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/PartSubpartConfigurationTest.java @@ -23,10 +23,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.collectRegressionTestAnswerSets; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.collectRegressionTestAnswerSets; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import static org.junit.jupiter.api.Assertions.assertFalse; import java.util.ArrayList; diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/PigeonHoleTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/PigeonHoleTest.java similarity index 95% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/PigeonHoleTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/PigeonHoleTest.java index aa2c53f87..d444d5a7e 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/PigeonHoleTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/PigeonHoleTest.java @@ -23,11 +23,11 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.collectRegressionTestAnswerSets; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.ignoreTestForNonDefaultDomainIndependentHeuristics; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.collectRegressionTestAnswerSets; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.ignoreTestForNonDefaultDomainIndependentHeuristics; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.ArrayList; @@ -37,7 +37,7 @@ import org.junit.jupiter.api.Disabled; -import at.ac.tuwien.kr.alpha.common.AnswerSet; +import at.ac.tuwien.kr.alpha.api.AnswerSet; /** * Tests {@link AbstractSolver} using some pigeon-hole test cases (see https://en.wikipedia.org/wiki/Pigeonhole_principle). diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/RacksTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RacksTest.java similarity index 85% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/RacksTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RacksTest.java index c7c965020..1ea2b88ca 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/RacksTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RacksTest.java @@ -23,10 +23,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import java.io.IOException; import java.nio.file.Paths; @@ -36,8 +36,9 @@ import org.antlr.v4.runtime.CharStreams; import org.junit.jupiter.api.Disabled; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; /** * Tests {@link AbstractSolver} using a racks configuration problem. @@ -57,7 +58,7 @@ public void testRacks(RegressionTestConfig cfg) { private void test(RegressionTestConfig cfg) throws IOException { CharStream programInputStream = CharStreams.fromPath( Paths.get("benchmarks", "siemens", "racks", "racks.lp")); - Solver solver = buildSolverForRegressionTest(new ProgramParser().parse(programInputStream), cfg); + Solver solver = buildSolverForRegressionTest(new ProgramParserImpl().parse(programInputStream), cfg); @SuppressWarnings("unused") Optional answerSet = solver.stream().findFirst(); // System.out.println(answerSet); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTest.java similarity index 74% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTest.java index 6c3e9c6db..f6f3e28a2 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.solver; +package at.ac.tuwien.kr.alpha.core.solver; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -11,7 +11,7 @@ @Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @ParameterizedTest -@MethodSource("at.ac.tuwien.kr.alpha.solver.RegressionTestConfigProvider#provideConfigs") +@MethodSource("at.ac.tuwien.kr.alpha.core.solver.RegressionTestConfigProvider#provideConfigs") public @interface RegressionTest { } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTestConfig.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java similarity index 91% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTestConfig.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfig.java index 956b5b88b..73c318012 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory; +import at.ac.tuwien.kr.alpha.api.config.Heuristic; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; public class RegressionTestConfig { @@ -11,7 +11,7 @@ public class RegressionTestConfig { private final String noGoodStoreName; - private final BranchingHeuristicFactory.Heuristic branchingHeuristic; + private final Heuristic branchingHeuristic; private final long seed; @@ -31,7 +31,7 @@ public class RegressionTestConfig { public RegressionTestConfig( String solverName, String grounderName, String noGoodStoreName, - BranchingHeuristicFactory.Heuristic branchingHeuristic, long seed, + Heuristic branchingHeuristic, long seed, boolean debugChecks, String grounderToleranceConstraints, String grounderToleranceRules, boolean disableInstanceRemoval, boolean evaluateStratifiedPart, boolean useSortingGrid, boolean supportNegativeSumElements) { this.solverName = solverName; @@ -77,7 +77,7 @@ public String getNoGoodStoreName() { return this.noGoodStoreName; } - public BranchingHeuristicFactory.Heuristic getBranchingHeuristic() { + public Heuristic getBranchingHeuristic() { return this.branchingHeuristic; } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTestConfigProvider.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java similarity index 84% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTestConfigProvider.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java index f8cff8f70..20f139581 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/RegressionTestConfigProvider.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/RegressionTestConfigProvider.java @@ -1,14 +1,13 @@ -package at.ac.tuwien.kr.alpha.solver; - -import org.junit.jupiter.params.provider.Arguments; +package at.ac.tuwien.kr.alpha.core.solver; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Random; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory.Heuristic; +import org.junit.jupiter.params.provider.Arguments; + +import at.ac.tuwien.kr.alpha.api.config.Heuristic; public class RegressionTestConfigProvider { @@ -19,10 +18,13 @@ public class RegressionTestConfigProvider { 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; - + /** - * Creates a list of {@link RegressionTestConfig}s with all config combinations that are to be tested im methods tagged using "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. + * Creates a list of {@link RegressionTestConfig}s with all config combinations that are to be tested im methods tagged using + * "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() { @@ -59,7 +61,7 @@ private static List buildConfigs() { for (boolean evaluateStratified : evaluateStratifiedValues) { for (boolean enableDebugChecks : enableDebugChecksValues) { configsToTest.add(new RegressionTestConfig( - solverName, grounder, atomStoreName, BranchingHeuristicFactory.Heuristic.valueOf(branchingHeuristicName), + solverName, grounder, atomStoreName, Heuristic.valueOf(branchingHeuristicName), seed, enableDebugChecks, grounderTolerance, gtrValue, disableInstanceRemoval, evaluateStratified, true, true)); } @@ -74,34 +76,35 @@ 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 + * 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) { for (boolean supportNegativeElements : supportNegativeSumElementsValues) { configsToTest.add( new RegressionTestConfig( - DEFAULT_SOLVER_NAME, DEFAULT_GROUNDER_NAME, DEFAULT_ATOM_STORE, BranchingHeuristicFactory.Heuristic.valueOf(DEFAULT_BRANCHING_HEURISTIC), - 0, DEFAULT_ENABLE_DEBUG_CHECKS, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_GROUNDER_TOLERANCE, DEFAULT_DISABLE_INSTANCE_REMOVAL, evalStratified, - useSortingGrid, supportNegativeElements) - ); + 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, + evalStratified, + useSortingGrid, supportNegativeElements)); } } } - - return configsToTest; + + return configsToTest; } - + public static List provideConfigs() { List retVal = new ArrayList<>(); for (RegressionTestConfig cfg : buildConfigs()) { diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/SolverStatisticsTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java similarity index 76% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/SolverStatisticsTests.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java index 32e67e2b7..1afed713b 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/SolverStatisticsTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverStatisticsTests.java @@ -23,9 +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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.buildSolverForRegressionTest; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -33,10 +33,12 @@ import org.junit.jupiter.api.BeforeEach; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.grounder.DummyGrounder; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.StatisticsReportingSolver; +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.grounder.DummyGrounder; public class SolverStatisticsTests { @@ -50,28 +52,28 @@ public void setUp() { @RegressionTest public void checkStatsStringZeroChoices(RegressionTestConfig cfg) { Solver solver = buildSolverForRegressionTest("a.", cfg); - assumeTrue(solver instanceof SolverMaintainingStatistics); + assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckStats(solver, 1, 0, 0, 0, 0, 0, 0, 0); } @RegressionTest public void checkStatsStringOneChoice(RegressionTestConfig cfg) { Solver solver = buildSolverForRegressionTest("a :- not b. b :- not a.", cfg); - assumeTrue(solver instanceof SolverMaintainingStatistics); + assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckStats(solver, 2, 1, 1, 1, 1, 0, 0, 0); } @RegressionTest public void checkNoGoodCounterStatsByTypeUsingDummyGrounder(RegressionTestConfig cfg) { Solver solver = buildSolverForRegressionTest(atomStore, new DummyGrounder(atomStore), cfg); - assumeTrue(solver instanceof SolverMaintainingStatistics); + assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckNoGoodCounterStatsByType(solver, 4, 0, 0, 0); } @RegressionTest public void checkNoGoodCounterStatsByCardinalityUsingDummyGrounder(RegressionTestConfig cfg) { Solver solver = buildSolverForRegressionTest(atomStore, new DummyGrounder(atomStore), cfg); - assumeTrue(solver instanceof SolverMaintainingStatistics); + assumeTrue(solver instanceof StatisticsReportingSolver); collectAnswerSetsAndCheckNoGoodCounterStatsByCardinality(solver, 2, 1, 1); } @@ -79,7 +81,7 @@ private void collectAnswerSetsAndCheckStats(Solver solver, int expectedNumberOfA int expectedNumberOfBacktracksWithinBackjumps, int expectedNumberOfBackjumps, int expectedNumberOfMBTs, int expectedNumberOfConflictsAfterClosing, int expectedNumberOfDeletedNoGoods) { Set answerSets = solver.collectSet(); assertEquals(expectedNumberOfAnswerSets, answerSets.size()); - SolverMaintainingStatistics solverMaintainingStatistics = (SolverMaintainingStatistics) solver; + StatisticsReportingSolver solverMaintainingStatistics = (StatisticsReportingSolver) solver; assertEquals( String.format("g=%d, bt=%d, bj=%d, bt_within_bj=%d, mbt=%d, cac=%d, del_ng=%d", expectedNumberOfGuesses, expectedTotalNumberOfBacktracks, expectedNumberOfBackjumps, expectedNumberOfBacktracksWithinBackjumps, expectedNumberOfMBTs, expectedNumberOfConflictsAfterClosing, expectedNumberOfDeletedNoGoods), @@ -88,14 +90,18 @@ private void collectAnswerSetsAndCheckStats(Solver solver, int expectedNumberOfA private void collectAnswerSetsAndCheckNoGoodCounterStatsByType(Solver solver, int expectedNumberOfStaticNoGoods, int expectedNumberOfSupportNoGoods, int expectedNumberOfLearntNoGoods, int expectedNumberOfInternalNoGoods) { solver.collectSet(); - SolverMaintainingStatistics solverMaintainingStatistics = (SolverMaintainingStatistics) solver; + // Note: This cast is kinda hacky since it assumes a specific implementation rather than an interface. + // To be perfectly clean, we need to introduce an interface in core module that extends StatisticsReportingSolver with getNoGoodCounter() + DefaultSolver solverMaintainingStatistics = (DefaultSolver) solver; final NoGoodCounter noGoodCounter = solverMaintainingStatistics.getNoGoodCounter(); assertEquals("STATIC: " + expectedNumberOfStaticNoGoods + " SUPPORT: " + expectedNumberOfSupportNoGoods + " LEARNT: " + expectedNumberOfLearntNoGoods + " INTERNAL: " + expectedNumberOfInternalNoGoods, noGoodCounter.getStatsByType()); } private void collectAnswerSetsAndCheckNoGoodCounterStatsByCardinality(Solver solver, int expectedNumberOfUnaryNoGoods, int expectedNumberOfBinaryNoGoods, int expectedNumberOfNAryNoGoods) { solver.collectSet(); - SolverMaintainingStatistics solverMaintainingStatistics = (SolverMaintainingStatistics) solver; + // Note: This cast is kinda hacky since it assumes a specific implementation rather than an interface. + // To be perfectly clean, we need to introduce an interface in core module that extends StatisticsReportingSolver with getNoGoodCounter() + DefaultSolver solverMaintainingStatistics = (DefaultSolver) solver; final NoGoodCounter noGoodCounter = solverMaintainingStatistics.getNoGoodCounter(); assertEquals("unary: " + expectedNumberOfUnaryNoGoods + " binary: " + expectedNumberOfBinaryNoGoods + " larger: " + expectedNumberOfNAryNoGoods, noGoodCounter.getStatsByCardinality()); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/SolverTests.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java similarity index 91% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/SolverTests.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java index efc60d417..911a2dd32 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/SolverTests.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/SolverTests.java @@ -25,13 +25,13 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSet; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSets; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.assertRegressionTestAnswerSetsWithBase; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.collectRegressionTestAnswerSets; +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 java.util.Collections.singleton; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -42,19 +42,22 @@ import java.util.Set; import java.util.SortedSet; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.grounder.ChoiceGrounder; -import at.ac.tuwien.kr.alpha.grounder.DummyGrounder; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; -import at.ac.tuwien.kr.alpha.test.util.AnswerSetsParser; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +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.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; +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.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.grounder.ChoiceGrounder; +import at.ac.tuwien.kr.alpha.core.grounder.DummyGrounder; +import at.ac.tuwien.kr.alpha.core.parser.InlineDirectivesImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.test.util.AnswerSetsParser; public class SolverTests { @@ -74,12 +77,12 @@ public int compareTo(Thingy o) { public void testObjectProgram(RegressionTestConfig cfg) { final Thingy thingy = new Thingy(); - final Atom fact = new BasicAtom(Predicate.getInstance("foo", 1), ConstantTerm.getInstance(thingy)); + final Atom fact = Atoms.newBasicAtom(Predicates.getPredicate("foo", 1), Terms.newConstant(thingy)); final InputProgram program = new InputProgram( Collections.emptyList(), Collections.singletonList(fact), - new InlineDirectives() + new InlineDirectivesImpl() ); assertEquals(singleton(new AnswerSetBuilder() @@ -719,8 +722,8 @@ public void instanceEnumerationAtom(RegressionTestConfig cfg) { // Check manually that there is one answer set, wrong_double_occurrence has not been derived, and enum yielded a unique position for each term. assertEquals(1, answerSets.size()); AnswerSet answerSet = answerSets.iterator().next(); - assertEquals(null, answerSet.getPredicateInstances(Predicate.getInstance("wrong_double_occurrence", 0))); - SortedSet positions = answerSet.getPredicateInstances(Predicate.getInstance("unique_position", 2)); + assertEquals(null, answerSet.getPredicateInstances(Predicates.getPredicate("wrong_double_occurrence", 0))); + SortedSet positions = answerSet.getPredicateInstances(Predicates.getPredicate("unique_position", 2)); assertEnumerationPositions(positions, 3); } @@ -736,8 +739,8 @@ public void instanceEnumerationArbitraryTerms(RegressionTestConfig cfg) { // Check manually that there is one answer set, wrong_double_occurrence has not been derived, and enum yielded a unique position for each term. assertEquals(1, answerSets.size()); AnswerSet answerSet = answerSets.iterator().next(); - assertPropositionalPredicateFalse(answerSet, Predicate.getInstance("wrong_double_occurrence", 0)); - SortedSet positions = answerSet.getPredicateInstances(Predicate.getInstance("unique_position", 2)); + assertPropositionalPredicateFalse(answerSet, Predicates.getPredicate("wrong_double_occurrence", 0)); + SortedSet positions = answerSet.getPredicateInstances(Predicates.getPredicate("unique_position", 2)); assertEnumerationPositions(positions, 3); } @@ -754,10 +757,10 @@ public void instanceEnumerationMultipleIdentifiers(RegressionTestConfig cfg) { // Check manually that there is one answer set, wrong_double_occurrence has not been derived, and enum yielded a unique position for each term. assertEquals(1, answerSets.size()); AnswerSet answerSet = answerSets.iterator().next(); - assertPropositionalPredicateFalse(answerSet, Predicate.getInstance("wrong_double_occurrence", 0)); - SortedSet positions = answerSet.getPredicateInstances(Predicate.getInstance("unique_position1", 2)); + assertPropositionalPredicateFalse(answerSet, Predicates.getPredicate("wrong_double_occurrence", 0)); + SortedSet positions = answerSet.getPredicateInstances(Predicates.getPredicate("unique_position1", 2)); assertEnumerationPositions(positions, 4); - SortedSet positions2 = answerSet.getPredicateInstances(Predicate.getInstance("unique_position2", 2)); + SortedSet positions2 = answerSet.getPredicateInstances(Predicates.getPredicate("unique_position2", 2)); assertEnumerationPositions(positions2, 4); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/TestableChoiceManager.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/TestableChoiceManager.java similarity index 97% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/TestableChoiceManager.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/TestableChoiceManager.java index d8923a166..50eaa2443 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/TestableChoiceManager.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/TestableChoiceManager.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.solver; +package at.ac.tuwien.kr.alpha.core.solver; import org.apache.commons.lang3.tuple.Pair; diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringRandomGraphTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringRandomGraphTest.java similarity index 85% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringRandomGraphTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringRandomGraphTest.java index 227741345..2108b65db 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringRandomGraphTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringRandomGraphTest.java @@ -23,10 +23,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import java.util.ArrayList; import java.util.List; @@ -35,14 +35,15 @@ import org.junit.jupiter.api.Disabled; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; public class ThreeColouringRandomGraphTest { @@ -97,7 +98,7 @@ public void testV300E300(RegressionTestConfig cfg) { } private void testThreeColouring(int nVertices, int nEdges, RegressionTestConfig cfg) { - InputProgram tmpPrg = new ProgramParser().parse( + ASPCore2Program tmpPrg = new ProgramParserImpl().parse( "blue(N) :- v(N), not red(N), not green(N)." + "red(N) :- v(N), not blue(N), not green(N)." + "green(N) :- v(N), not red(N), not blue(N)." + @@ -155,8 +156,8 @@ private List createEdges(int vertices, int edges) { private Atom fact(String predicateName, int... iTerms) { List terms = new ArrayList<>(1); for (int i : iTerms) { - terms.add(ConstantTerm.getInstance(i)); + terms.add(Terms.newConstant(i)); } - return new BasicAtom(Predicate.getInstance(predicateName, iTerms.length), terms); + return Atoms.newBasicAtom(Predicates.getPredicate(predicateName, iTerms.length), terms); } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringTestWithRandom.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringTestWithRandom.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringTestWithRandom.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringTestWithRandom.java index 3e7ab9978..d53a0b82d 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringTestWithRandom.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringTestWithRandom.java @@ -23,10 +23,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import java.util.ArrayList; import java.util.Collections; @@ -36,14 +36,17 @@ import org.junit.jupiter.api.Disabled; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; /** * Tests {@link AbstractSolver} using some three-coloring test cases, as described in: @@ -181,7 +184,7 @@ public void testN101(RegressionTestConfig cfg) { } private void testThreeColouring(int n, boolean shuffle, int seed, RegressionTestConfig cfg) { - InputProgram tmpPrg = new ProgramParser() + ASPCore2Program tmpPrg = new ProgramParserImpl() .parse("col(V,C) :- v(V), c(C), not ncol(V,C)." + "ncol(V,C) :- col(V,D), c(C), C != D." + ":- e(V,U), col(V,C), col(U,C)."); InputProgram.Builder prgBuilder = InputProgram.builder().accumulate(tmpPrg); prgBuilder.addFacts(createColors("1", "2", "3")); @@ -200,8 +203,8 @@ private List createColors(String... colours) { List facts = new ArrayList<>(colours.length); for (String colour : colours) { List terms = new ArrayList<>(1); - terms.add(ConstantTerm.getInstance(colour)); - facts.add(new BasicAtom(Predicate.getInstance("c", 1), terms)); + terms.add(Terms.newConstant(colour)); + facts.add(Atoms.newBasicAtom(Predicates.getPredicate("c", 1), terms)); } return facts; } @@ -243,10 +246,10 @@ private List createEdges(int n, boolean shuffle, int seed) { private Atom fact(String predicateName, int... iTerms) { List terms = new ArrayList<>(iTerms.length); - Predicate predicate = Predicate.getInstance(predicateName, iTerms.length); + Predicate predicate = Predicates.getPredicate(predicateName, iTerms.length); for (int i : iTerms) { - terms.add(ConstantTerm.getInstance(i)); + terms.add(Terms.newConstant(i)); } - return new BasicAtom(predicate, terms); + return Atoms.newBasicAtom(predicate, terms); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringWheelTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringWheelTest.java similarity index 81% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringWheelTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringWheelTest.java index 4239474cc..48603e2e8 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/ThreeColouringWheelTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/ThreeColouringWheelTest.java @@ -23,10 +23,10 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.buildSolverForRegressionTest; -import static at.ac.tuwien.kr.alpha.test.util.TestUtils.runWithTimeout; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.buildSolverForRegressionTest; +import static at.ac.tuwien.kr.alpha.core.test.util.TestUtils.runWithTimeout; import java.util.ArrayList; import java.util.List; @@ -34,14 +34,17 @@ import org.junit.jupiter.api.Disabled; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +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.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; /** * Tests {@link AbstractSolver} using some three-coloring test cases, as described in: @@ -95,7 +98,7 @@ public void testN11(RegressionTestConfig cfg) { } private void testThreeColouring(int n, RegressionTestConfig cfg) { - InputProgram tmpPrg = new ProgramParser().parse( + ASPCore2Program tmpPrg = new ProgramParserImpl().parse( "col(V,C) :- v(V), c(C), not ncol(V,C)." + "ncol(V,C) :- col(V,D), c(C), C != D." + ":- e(V,U), col(V,C), col(U,C)."); @@ -124,11 +127,11 @@ private void maybeShuffle(InputProgram program) { private List createColors(String... colours) { List facts = new ArrayList<>(colours.length); - Predicate predicate = Predicate.getInstance("c", 1); + Predicate predicate = Predicates.getPredicate("c", 1); for (String colour : colours) { List terms = new ArrayList<>(1); - terms.add(ConstantTerm.getInstance(colour)); - facts.add(new BasicAtom(predicate, terms)); + terms.add(Terms.newConstant(colour)); + facts.add(Atoms.newBasicAtom(predicate, terms)); } return facts; } @@ -155,10 +158,10 @@ private List createEdges(int n) { private Atom fact(String predicateName, int... iTerms) { List terms = new ArrayList<>(1); - Predicate predicate = Predicate.getInstance(predicateName, iTerms.length); + Predicate predicate = Predicates.getPredicate(predicateName, iTerms.length); for (int i : iTerms) { - terms.add(ConstantTerm.getInstance(i)); + terms.add(Terms.newConstant(i)); } - return new BasicAtom(predicate, terms); + return Atoms.newBasicAtom(predicate, terms); } } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/TrailAssignmentTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/TrailAssignmentTest.java similarity index 90% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/TrailAssignmentTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/TrailAssignmentTest.java index 34b568e5e..72100a72b 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/TrailAssignmentTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/TrailAssignmentTest.java @@ -25,29 +25,28 @@ * 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.solver; +package at.ac.tuwien.kr.alpha.core.solver; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.FALSE; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.MBT; -import static at.ac.tuwien.kr.alpha.solver.ThriceTruth.TRUE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import at.ac.tuwien.kr.alpha.core.common.Assignment; +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.IntIterator; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.IntIterator; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.FALSE; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.MBT; +import static at.ac.tuwien.kr.alpha.core.solver.ThriceTruth.TRUE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Copyright (c) 2018-2020, the Alpha Team. @@ -57,7 +56,7 @@ public class TrailAssignmentTest { public TrailAssignmentTest() { AtomStore atomStore = new AtomStoreImpl(); - AtomStoreTest.fillAtomStore(atomStore, 20); + TestUtils.fillAtomStore(atomStore, 20); assignment = new TrailAssignment(atomStore); } @@ -181,8 +180,8 @@ public void newAssignmentsIteratorAndBacktracking() { newAssignmentsIterator = assignment.getNewPositiveAssignmentsIterator(); - assertEquals(1, (int)newAssignmentsIterator.next()); - assertEquals(2, (int)newAssignmentsIterator.next()); + assertEquals(1, newAssignmentsIterator.next()); + assertEquals(2, newAssignmentsIterator.next()); assertFalse(newAssignmentsIterator.hasNext()); @@ -191,7 +190,7 @@ public void newAssignmentsIteratorAndBacktracking() { assignment.assign(3, FALSE); newAssignmentsIterator = assignment.getNewPositiveAssignmentsIterator(); - assertEquals(3, (int)newAssignmentsIterator.next()); + assertEquals(3, newAssignmentsIterator.next()); assertFalse(newAssignmentsIterator.hasNext()); } @@ -205,8 +204,8 @@ public void newAssignmentsIteratorLowerDecisionLevelAndBacktracking() { assignment.backtrack(); newAssignmentsIterator = assignment.getNewPositiveAssignmentsIterator(); - assertEquals(1, (int)newAssignmentsIterator.next()); - assertEquals(3, (int)newAssignmentsIterator.next()); + assertEquals(1, newAssignmentsIterator.next()); + assertEquals(3, newAssignmentsIterator.next()); assertFalse(newAssignmentsIterator.hasNext()); } @@ -263,4 +262,4 @@ public void numberOfAssignedAtoms() { assignment.assign(5, TRUE); assertEquals(2, assignment.getNumberOfAtomsAssignedSinceLastDecision()); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaHeuristicTestAssumptions.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaHeuristicTestAssumptions.java similarity index 77% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaHeuristicTestAssumptions.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaHeuristicTestAssumptions.java index 4b1555253..b5c7516e0 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/AlphaHeuristicTestAssumptions.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/AlphaHeuristicTestAssumptions.java @@ -23,33 +23,35 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import static at.ac.tuwien.kr.alpha.common.Literals.atomOf; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomOf; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collection; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.grounder.NaiveGrounder; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.solver.NaiveNoGoodStore; -import at.ac.tuwien.kr.alpha.solver.TestableChoiceManager; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +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 at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.NaiveGrounder; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.solver.NaiveNoGoodStore; +import at.ac.tuwien.kr.alpha.core.solver.TestableChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; /** * Tests assumptions made by {@link DependencyDrivenHeuristic} and other domain-independent heuristics. @@ -60,6 +62,13 @@ * */ public class AlphaHeuristicTestAssumptions { + + private final ProgramParser parser = new ProgramParserImpl(); + private final NormalizeProgramTransformation normalizer = new NormalizeProgramTransformation(SystemConfig.DEFAULT_AGGREGATE_REWRITING_CONFIG); + private final Function parseAndPreprocess = (str) -> { + return InternalProgram.fromNormalProgram(normalizer.apply(parser.parse(str))); + }; + private Grounder grounder; private WritableAssignment assignment; private TestableChoiceManager choiceManager; @@ -67,16 +76,13 @@ public class AlphaHeuristicTestAssumptions { @BeforeEach public void setUp() { - Alpha system = new Alpha(); String testProgram = "" + "b1." + "b2." + "{b3}." + "{b4}." + "h :- b1, b2, not b3, not b4."; - InputProgram parsedProgram = new ProgramParser().parse(testProgram); - NormalProgram normal = system.normalizeProgram(parsedProgram); - InternalProgram internalProgram = InternalProgram.fromNormalProgram(normal); + CompiledProgram internalProgram = parseAndPreprocess.apply(testProgram); atomStore = new AtomStoreImpl(); grounder = new NaiveGrounder(internalProgram, atomStore, true); assignment = new TrailAssignment(atomStore); @@ -123,7 +129,7 @@ private void testNumbersOfNoGoods(Predicate isRuleBody) { other++; } } - + System.out.println(noGoods.stream().map(atomStore::noGoodToString).collect(Collectors.joining(", "))); assertEquals(5, bodyNotHead, "Unexpected number of bodyNotHead nogoods"); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMinTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinTest.java similarity index 92% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMinTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinTest.java index d74272b4f..46936c8e0 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/BerkMinTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BerkMinTest.java @@ -23,9 +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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Collection; @@ -35,14 +35,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.NaiveNoGoodStore; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +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 at.ac.tuwien.kr.alpha.core.solver.NaiveNoGoodStore; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Tests {@link BerkMin}. @@ -62,7 +62,7 @@ public class BerkMinTest { @BeforeEach public void setUp() { AtomStore atomStore = new AtomStoreImpl(); - AtomStoreTest.fillAtomStore(atomStore, 2); + TestUtils.fillAtomStore(atomStore, 2); WritableAssignment assignment = new TrailAssignment(atomStore); assignment.growForMaxAtomId(); this.berkmin = new BerkMin( diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristicFactoryTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristicFactoryTest.java similarity index 82% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristicFactoryTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristicFactoryTest.java index 34080fd57..a3c973336 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/BranchingHeuristicFactoryTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/BranchingHeuristicFactoryTest.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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -33,13 +33,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.NoGoodStore; -import at.ac.tuwien.kr.alpha.solver.NoGoodStoreAlphaRoaming; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.api.config.Heuristic; +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.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStore; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStoreAlphaRoaming; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; /** * Tests {@link BranchingHeuristicFactory} @@ -59,7 +60,7 @@ public void setUp() { @Test public void testChainedHeuristicWithReplay() { - HeuristicsConfigurationBuilder builder = new HeuristicsConfigurationBuilder().setHeuristic(BranchingHeuristicFactory.Heuristic.VSIDS).setReplayChoices(Arrays.asList(1, 2, 3)); + HeuristicsConfigurationBuilder builder = new HeuristicsConfigurationBuilder().setHeuristic(Heuristic.VSIDS).setReplayChoices(Arrays.asList(1, 2, 3)); BranchingHeuristic branchingHeuristic = BranchingHeuristicFactory.getInstance(builder.build(), null, null, choiceManager, null); assertEquals(ChainedBranchingHeuristics.class, branchingHeuristic.getClass()); assertTrue(branchingHeuristic instanceof ChainedBranchingHeuristics, "Unexpected type of branchingHeuristic: " + branchingHeuristic.getClass()); @@ -68,7 +69,7 @@ public void testChainedHeuristicWithReplay() { @Test public void testChainedHeuristicWithoutReplay() { - HeuristicsConfigurationBuilder builder = new HeuristicsConfigurationBuilder().setHeuristic(BranchingHeuristicFactory.Heuristic.VSIDS).setReplayChoices(null); + HeuristicsConfigurationBuilder builder = new HeuristicsConfigurationBuilder().setHeuristic(Heuristic.VSIDS).setReplayChoices(null); BranchingHeuristic branchingHeuristic = BranchingHeuristicFactory.getInstance(builder.build(), null, null, choiceManager, null); assertEquals(VSIDS.class, branchingHeuristic.getClass()); } diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveAtomsTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtomsTest.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveAtomsTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtomsTest.java index abb0e9d28..d0c5babe6 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeapOfActiveAtomsTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeapOfActiveAtomsTest.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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -31,14 +31,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.NoGoodStoreAlphaRoaming; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +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 at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStoreAlphaRoaming; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; /** * Tests {@link HeapOfActiveAtoms}, including initial heuristic scores computed by {@link MOMs}. diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicTestUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicTestUtils.java similarity index 82% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicTestUtils.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicTestUtils.java index 680dc6131..0a6606e15 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/HeuristicTestUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/HeuristicTestUtils.java @@ -23,24 +23,24 @@ * 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.solver.heuristics; - -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.NoGoodStoreAlphaRoaming; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +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.solver.NoGoodStoreAlphaRoaming; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; + public class HeuristicTestUtils { static void addNoGoods(AtomStore atomStore, WritableAssignment assignment, NoGoodStoreAlphaRoaming noGoodStore, VSIDS vsids, NoGood... noGoods) { int numberOfAtoms = Arrays.stream(noGoods).flatMapToInt(NoGood::stream).map(Literals::atomOf).max().getAsInt(); - AtomStoreTest.fillAtomStore(atomStore, numberOfAtoms); + TestUtils.fillAtomStore(atomStore, numberOfAtoms); assignment.growForMaxAtomId(); noGoodStore.growForMaxAtomId(numberOfAtoms); vsids.growForMaxAtomId(numberOfAtoms); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/PseudoChoiceManager.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/PseudoChoiceManager.java similarity index 88% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/PseudoChoiceManager.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/PseudoChoiceManager.java index 55c95ccb0..7b081cfd5 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/PseudoChoiceManager.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/PseudoChoiceManager.java @@ -23,11 +23,11 @@ * 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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.NoGoodStore; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.core.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStore; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; /** * A {@link ChoiceManager} for testing purposes that regards all atoms as active choice atoms. diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/ReplayHeuristicTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ReplayHeuristicTest.java similarity index 83% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/ReplayHeuristicTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ReplayHeuristicTest.java index 0c686ddbb..4af6a0e77 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/ReplayHeuristicTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/ReplayHeuristicTest.java @@ -23,9 +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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; -import static at.ac.tuwien.kr.alpha.common.Literals.atomToLiteral; +import static at.ac.tuwien.kr.alpha.core.atoms.Literals.atomToLiteral; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Arrays; @@ -34,13 +34,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.solver.ChoiceManager; -import at.ac.tuwien.kr.alpha.solver.NoGoodStore; -import at.ac.tuwien.kr.alpha.solver.NoGoodStoreAlphaRoaming; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +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.solver.ChoiceManager; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStore; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStoreAlphaRoaming; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; /** * Tests {@link ReplayHeuristic} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/VSIDSTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDSTest.java similarity index 89% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/VSIDSTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDSTest.java index 65ce74e77..aa18db17f 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/heuristics/VSIDSTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/heuristics/VSIDSTest.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.solver.heuristics; +package at.ac.tuwien.kr.alpha.core.solver.heuristics; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -34,15 +34,15 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.Literals; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.NoGoodStoreAlphaRoaming; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; -import at.ac.tuwien.kr.alpha.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +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 at.ac.tuwien.kr.alpha.core.solver.NoGoodStoreAlphaRoaming; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.core.solver.learning.GroundConflictNoGoodLearner.ConflictAnalysisResult; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Tests {@link VSIDS}. @@ -72,7 +72,7 @@ public class VSIDSTest { @BeforeEach public void setUp() { atomStore = new AtomStoreImpl(); - AtomStoreTest.fillAtomStore(atomStore, 4); + TestUtils.fillAtomStore(atomStore, 4); assignment = new TrailAssignment(atomStore); assignment.growForMaxAtomId(); noGoodStore = new NoGoodStoreAlphaRoaming(assignment); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/learning/GroundConflictNoGoodLearnerTest.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/learning/GroundConflictNoGoodLearnerTest.java similarity index 79% rename from src/test/java/at/ac/tuwien/kr/alpha/solver/learning/GroundConflictNoGoodLearnerTest.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/learning/GroundConflictNoGoodLearnerTest.java index 5857985c5..b7ea7ef40 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/learning/GroundConflictNoGoodLearnerTest.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/solver/learning/GroundConflictNoGoodLearnerTest.java @@ -1,7 +1,7 @@ -package at.ac.tuwien.kr.alpha.solver.learning; +package at.ac.tuwien.kr.alpha.core.solver.learning; -import static at.ac.tuwien.kr.alpha.common.NoGoodTest.fromOldLiterals; -import static at.ac.tuwien.kr.alpha.solver.AntecedentTest.antecedentsEquals; +import static at.ac.tuwien.kr.alpha.core.common.NoGoodTest.fromOldLiterals; +import static at.ac.tuwien.kr.alpha.core.solver.AntecedentTest.antecedentsEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -11,17 +11,17 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.AtomStoreTest; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.solver.Antecedent; -import at.ac.tuwien.kr.alpha.solver.ConflictCause; -import at.ac.tuwien.kr.alpha.solver.NoGoodStore; -import at.ac.tuwien.kr.alpha.solver.NoGoodStoreAlphaRoaming; -import at.ac.tuwien.kr.alpha.solver.ThriceTruth; -import at.ac.tuwien.kr.alpha.solver.TrailAssignment; -import at.ac.tuwien.kr.alpha.solver.WritableAssignment; +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 at.ac.tuwien.kr.alpha.core.solver.Antecedent; +import at.ac.tuwien.kr.alpha.core.solver.ConflictCause; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStore; +import at.ac.tuwien.kr.alpha.core.solver.NoGoodStoreAlphaRoaming; +import at.ac.tuwien.kr.alpha.core.solver.ThriceTruth; +import at.ac.tuwien.kr.alpha.core.solver.TrailAssignment; +import at.ac.tuwien.kr.alpha.core.solver.WritableAssignment; +import at.ac.tuwien.kr.alpha.core.test.util.TestUtils; /** * Copyright (c) 2016-2019, the Alpha Team. @@ -34,7 +34,7 @@ public class GroundConflictNoGoodLearnerTest { public GroundConflictNoGoodLearnerTest() { atomStore = new AtomStoreImpl(); - AtomStoreTest.fillAtomStore(atomStore, 20); + TestUtils.fillAtomStore(atomStore, 20); this.assignment = new TrailAssignment(atomStore); this.assignment.growForMaxAtomId(); this.store = new NoGoodStoreAlphaRoaming(assignment); @@ -99,4 +99,4 @@ public void subCurrentDLPropagationWithChoiceCauseOfConflict() { assertEquals(2, conflictAnalysisResult.backjumpLevel); } -} \ No newline at end of file +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/test/util/AnswerSetsParser.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/AnswerSetsParser.java similarity index 83% rename from src/test/java/at/ac/tuwien/kr/alpha/test/util/AnswerSetsParser.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/AnswerSetsParser.java index f20153be7..b78ebc20c 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/test/util/AnswerSetsParser.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/AnswerSetsParser.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.test.util; +package at.ac.tuwien.kr.alpha.core.test.util; import java.util.Collections; import java.util.Set; @@ -11,12 +11,13 @@ import org.antlr.v4.runtime.atn.PredictionMode; import org.antlr.v4.runtime.misc.ParseCancellationException; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Lexer; -import at.ac.tuwien.kr.alpha.antlr.ASPCore2Parser; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.grounder.parser.ParseTreeVisitor; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Lexer; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Parser; +import at.ac.tuwien.kr.alpha.core.parser.ParseTreeVisitor; public class AnswerSetsParser { + private static final ParseTreeVisitor VISITOR = new ParseTreeVisitor(Collections.emptyMap(), false); public static Set parse(String s) { diff --git a/src/test/java/at/ac/tuwien/kr/alpha/test/util/DependencyGraphUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/DependencyGraphUtils.java similarity index 90% rename from src/test/java/at/ac/tuwien/kr/alpha/test/util/DependencyGraphUtils.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/DependencyGraphUtils.java index e4e623a41..93319feee 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/test/util/DependencyGraphUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/DependencyGraphUtils.java @@ -1,14 +1,14 @@ -package at.ac.tuwien.kr.alpha.test.util; - -import at.ac.tuwien.kr.alpha.common.depgraph.DependencyGraph; -import at.ac.tuwien.kr.alpha.common.depgraph.Edge; -import at.ac.tuwien.kr.alpha.common.depgraph.Node; +package at.ac.tuwien.kr.alpha.core.test.util; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph.Edge; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph.Node; + /** * * Copyright (c) 2019-2020, the Alpha Team. diff --git a/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/RuleParser.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/RuleParser.java new file mode 100644 index 000000000..38da4d36d --- /dev/null +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/RuleParser.java @@ -0,0 +1,23 @@ +package at.ac.tuwien.kr.alpha.core.test.util; + +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.rules.Rule; +import at.ac.tuwien.kr.alpha.api.rules.heads.Head; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; + +public class RuleParser { + + public static Rule parse(String str) { + ProgramParser parser = new ProgramParserImpl(); + ASPCore2Program prog = parser.parse(str); + if (!prog.getFacts().isEmpty()) { + throw new IllegalArgumentException("Expected exactly one rule and no facts!"); + } + if (prog.getRules().size() != 1) { + throw new IllegalArgumentException("Expected exactly one rule"); + } + return prog.getRules().get(0); + } + +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/test/util/SubstitutionTestUtil.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/SubstitutionTestUtil.java similarity index 86% rename from src/test/java/at/ac/tuwien/kr/alpha/test/util/SubstitutionTestUtil.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/SubstitutionTestUtil.java index df0526ea5..9da1d7f24 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/test/util/SubstitutionTestUtil.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/SubstitutionTestUtil.java @@ -26,16 +26,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package at.ac.tuwien.kr.alpha.test.util; +package at.ac.tuwien.kr.alpha.core.test.util; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.grounder.Substitution; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.literals.Literal; +import at.ac.tuwien.kr.alpha.core.rules.CompiledRule; public class SubstitutionTestUtil { - public static String groundAndPrintRule(InternalRule rule, Substitution substitution) { + public static String groundAndPrintRule(CompiledRule rule, Substitution substitution) { StringBuilder ret = new StringBuilder(); if (!rule.isConstraint()) { Atom groundHead = rule.getHeadAtom().substitute(substitution); diff --git a/src/test/java/at/ac/tuwien/kr/alpha/test/util/TestUtils.java b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java similarity index 63% rename from src/test/java/at/ac/tuwien/kr/alpha/test/util/TestUtils.java rename to alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java index 9adf681ce..75cbc20df 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/test/util/TestUtils.java +++ b/alpha-core/src/test/java/at/ac/tuwien/kr/alpha/core/test/util/TestUtils.java @@ -1,16 +1,10 @@ -package at.ac.tuwien.kr.alpha.test.util; +package at.ac.tuwien.kr.alpha.core.test.util; import static java.util.Collections.emptySet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.ibm.icu.impl.Assert; - -import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.function.Executable; - import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -21,35 +15,71 @@ import java.util.StringJoiner; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.NoGood; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.AbstractProgram; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.grounder.GrounderFactory; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.grounder.transformation.NormalizeProgramTransformation; -import at.ac.tuwien.kr.alpha.grounder.transformation.StratifiedEvaluation; -import at.ac.tuwien.kr.alpha.solver.RegressionTestConfig; -import at.ac.tuwien.kr.alpha.solver.Solver; -import at.ac.tuwien.kr.alpha.solver.SolverFactory; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.function.Executable; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.config.Heuristic; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.Program; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.programs.atoms.BasicAtom; +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.common.AtomStore; +import at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl; +import at.ac.tuwien.kr.alpha.core.common.NoGood; +import at.ac.tuwien.kr.alpha.core.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.GrounderFactory; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.programs.transformation.StratifiedEvaluation; +import at.ac.tuwien.kr.alpha.core.solver.RegressionTestConfig; +import at.ac.tuwien.kr.alpha.core.solver.SolverFactory; public class TestUtils { + public static void fillAtomStore(AtomStore atomStore, int numberOfAtomsToFill) { + Predicate predA = Predicates.getPredicate("a", 1); + for (int i = 0; i < numberOfAtomsToFill; i++) { + 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++) { + String termString = termStrings[i]; + if (StringUtils.isAllUpperCase(termString.substring(0, 1))) { + terms[i] = Terms.newVariable(termString); + } else { + terms[i] = Terms.newConstant(termString); + } + } + return Atoms.newBasicAtom(Predicates.getPredicate(predicateName, terms.length), terms); + } + + public static Atom atom(String predicateName, int... termInts) { + Term[] terms = new Term[termInts.length]; + for (int i = 0; i < termInts.length; i++) { + terms[i] = Terms.newConstant(termInts[i]); + } + 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) { @@ -100,92 +130,57 @@ public static void assertAnswerSetsEqualWithBase(String base, String[] expectedA TestUtils.assertAnswerSetsEqual(expectedAnswerSets, actual); } - public static void assertFactsContainedInProgram(AbstractProgram prog, Atom... facts) { + public static void assertFactsContainedInProgram(Program prog, Atom... facts) { for (Atom fact : facts) { assertTrue(prog.getFacts().contains(fact)); } } - public static Atom basicAtomWithStringTerms(String predicate, String... terms) { - Predicate pred = Predicate.getInstance(predicate, terms.length); + public static BasicAtom basicAtomWithStringTerms(String predicate, String... terms) { + Predicate pred = Predicates.getPredicate(predicate, terms.length); List trms = new ArrayList<>(); for (String str : terms) { - trms.add(ConstantTerm.getInstance(str)); + trms.add(Terms.newConstant(str)); } - return new BasicAtom(pred, trms); + return Atoms.newBasicAtom(pred, trms); } - public static Atom basicAtomWithSymbolicTerms(String predicate, String... constantSymbols) { - Predicate pred = Predicate.getInstance(predicate, constantSymbols.length); + public static BasicAtom basicAtomWithSymbolicTerms(String predicate, String... constantSymbols) { + Predicate pred = Predicates.getPredicate(predicate, constantSymbols.length); List trms = new ArrayList<>(); for (String str : constantSymbols) { - trms.add(ConstantTerm.getSymbolicInstance(str)); - } - return new BasicAtom(pred, trms); - } - - public static Atom atom(String predicateName, String... termStrings) { - Term[] terms = new Term[termStrings.length]; - for (int i = 0; i < termStrings.length; i++) { - String termString = termStrings[i]; - if (StringUtils.isAllUpperCase(termString.substring(0, 1))) { - terms[i] = VariableTerm.getInstance(termString); - } else { - terms[i] = ConstantTerm.getInstance(termString); - } - } - return new BasicAtom(Predicate.getInstance(predicateName, terms.length), terms); - } - - public static Atom atom(String predicateName, int... termInts) { - Term[] terms = new Term[termInts.length]; - for (int i = 0; i < termInts.length; i++) { - terms[i] = ConstantTerm.getInstance(termInts[i]); - } - return new BasicAtom(Predicate.getInstance(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 assertProgramContainsRule(InputProgram prog, BasicRule containedRule) { - for (BasicRule rule : prog.getRules()) { - if (rule.equals(containedRule)) { - return; - } + trms.add(Terms.newSymbolicConstant(str)); } - Assert.fail("Program should contain rule, but does not! (rule = " + containedRule + ")"); + return Atoms.newBasicAtom(pred, trms); } - private static Solver buildSolverFromSystemConfig(InputProgram prog, SystemConfig cfg) { + private static Solver buildSolverFromSystemConfig(ASPCore2Program prog, SystemConfig cfg) { AtomStore atomStore = new AtomStoreImpl(); NormalProgram normalProg = new NormalizeProgramTransformation(cfg.getAggregateRewritingConfig()).apply(prog); InternalProgram preprocessed = cfg.isEvaluateStratifiedPart() ? new StratifiedEvaluation().apply(AnalyzedProgram.analyzeNormalProgram(normalProg)) : InternalProgram.fromNormalProgram(normalProg); - return SolverFactory.getInstance(cfg, atomStore, - GrounderFactory.getInstance(cfg.getGrounderName(), preprocessed, atomStore, cfg.isDebugInternalChecks())); + return SolverFactory.getInstance(cfg, atomStore, GrounderFactory.getInstance(cfg.getGrounderName(), preprocessed, atomStore, cfg.isDebugInternalChecks())); } - - public static Solver buildSolverForRegressionTest(InputProgram prog, RegressionTestConfig cfg) { + + public static Solver buildSolverForRegressionTest(ASPCore2Program prog, RegressionTestConfig cfg) { return buildSolverFromSystemConfig(prog, cfg.toSystemConfig()); } - + public static Solver buildSolverForRegressionTest(String prog, RegressionTestConfig cfg) { - return buildSolverFromSystemConfig(new ProgramParser().parse(prog), cfg.toSystemConfig()); + 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); } - public static Set collectRegressionTestAnswerSets(InputProgram prog, RegressionTestConfig cfg) { + public static Set collectRegressionTestAnswerSets(ASPCore2Program prog, RegressionTestConfig cfg) { return buildSolverForRegressionTest(prog, cfg).collectSet(); } - + public static Set collectRegressionTestAnswerSets(String aspstr, RegressionTestConfig cfg) { - InputProgram prog = new ProgramParser().parse(aspstr); + ASPCore2Program prog = new ProgramParserImpl().parse(aspstr); return collectRegressionTestAnswerSets(prog, cfg); } @@ -193,28 +188,28 @@ 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() == BranchingHeuristicFactory.Heuristic.VSIDS); + Assumptions.assumeTrue(cfg.getBranchingHeuristic() == Heuristic.VSIDS); } public static void ignoreTestForSimplifiedSumAggregates(RegressionTestConfig cfg) { diff --git a/src/test/resources/HanoiTower_Alpha.asp b/alpha-core/src/test/resources/HanoiTower_Alpha.asp similarity index 100% rename from src/test/resources/HanoiTower_Alpha.asp rename to alpha-core/src/test/resources/HanoiTower_Alpha.asp diff --git a/src/test/resources/HanoiTower_instances/1.asp b/alpha-core/src/test/resources/HanoiTower_instances/1.asp similarity index 100% rename from src/test/resources/HanoiTower_instances/1.asp rename to alpha-core/src/test/resources/HanoiTower_instances/1.asp diff --git a/src/test/resources/HanoiTower_instances/2.asp b/alpha-core/src/test/resources/HanoiTower_instances/2.asp similarity index 100% rename from src/test/resources/HanoiTower_instances/2.asp rename to alpha-core/src/test/resources/HanoiTower_instances/2.asp diff --git a/src/test/resources/HanoiTower_instances/3.asp b/alpha-core/src/test/resources/HanoiTower_instances/3.asp similarity index 100% rename from src/test/resources/HanoiTower_instances/3.asp rename to alpha-core/src/test/resources/HanoiTower_instances/3.asp diff --git a/src/test/resources/HanoiTower_instances/4.asp b/alpha-core/src/test/resources/HanoiTower_instances/4.asp similarity index 100% rename from src/test/resources/HanoiTower_instances/4.asp rename to alpha-core/src/test/resources/HanoiTower_instances/4.asp diff --git a/src/test/resources/HanoiTower_instances/instances.txt b/alpha-core/src/test/resources/HanoiTower_instances/instances.txt similarity index 100% rename from src/test/resources/HanoiTower_instances/instances.txt rename to alpha-core/src/test/resources/HanoiTower_instances/instances.txt diff --git a/src/test/resources/HanoiTower_instances/simple.asp b/alpha-core/src/test/resources/HanoiTower_instances/simple.asp similarity index 100% rename from src/test/resources/HanoiTower_instances/simple.asp rename to alpha-core/src/test/resources/HanoiTower_instances/simple.asp diff --git a/src/test/resources/escaped_quotes.asp b/alpha-core/src/test/resources/escaped_quotes.asp similarity index 100% rename from src/test/resources/escaped_quotes.asp rename to alpha-core/src/test/resources/escaped_quotes.asp diff --git a/src/test/resources/logback.xml b/alpha-core/src/test/resources/logback.xml similarity index 100% rename from src/test/resources/logback.xml rename to alpha-core/src/test/resources/logback.xml diff --git a/src/test/resources/partial-eval/pup_topological_order.asp b/alpha-core/src/test/resources/partial-eval/pup_topological_order.asp similarity index 100% rename from src/test/resources/partial-eval/pup_topological_order.asp rename to alpha-core/src/test/resources/partial-eval/pup_topological_order.asp diff --git a/src/test/resources/partial-eval/recursive_w_negated_condition.asp b/alpha-core/src/test/resources/partial-eval/recursive_w_negated_condition.asp similarity index 100% rename from src/test/resources/partial-eval/recursive_w_negated_condition.asp rename to alpha-core/src/test/resources/partial-eval/recursive_w_negated_condition.asp diff --git a/src/test/resources/show.asp b/alpha-core/src/test/resources/show.asp similarity index 100% rename from src/test/resources/show.asp rename to alpha-core/src/test/resources/show.asp diff --git a/src/test/resources/transform-test/choice-to-normal.1.in b/alpha-core/src/test/resources/transform-test/choice-to-normal.1.in similarity index 100% rename from src/test/resources/transform-test/choice-to-normal.1.in rename to alpha-core/src/test/resources/transform-test/choice-to-normal.1.in diff --git a/src/test/resources/transform-test/choice-to-normal.1.out b/alpha-core/src/test/resources/transform-test/choice-to-normal.1.out similarity index 100% rename from src/test/resources/transform-test/choice-to-normal.1.out rename to alpha-core/src/test/resources/transform-test/choice-to-normal.1.out diff --git a/src/test/resources/transform-test/interval-comparison_atom.in b/alpha-core/src/test/resources/transform-test/interval-comparison_atom.in similarity index 100% rename from src/test/resources/transform-test/interval-comparison_atom.in rename to alpha-core/src/test/resources/transform-test/interval-comparison_atom.in diff --git a/src/test/resources/transform-test/interval-comparison_atom.out b/alpha-core/src/test/resources/transform-test/interval-comparison_atom.out similarity index 100% rename from src/test/resources/transform-test/interval-comparison_atom.out rename to alpha-core/src/test/resources/transform-test/interval-comparison_atom.out diff --git a/src/test/resources/transform-test/interval-external_atom.in b/alpha-core/src/test/resources/transform-test/interval-external_atom.in similarity index 100% rename from src/test/resources/transform-test/interval-external_atom.in rename to alpha-core/src/test/resources/transform-test/interval-external_atom.in diff --git a/src/test/resources/transform-test/interval-external_atom.out b/alpha-core/src/test/resources/transform-test/interval-external_atom.out similarity index 100% rename from src/test/resources/transform-test/interval-external_atom.out rename to alpha-core/src/test/resources/transform-test/interval-external_atom.out diff --git a/src/test/resources/transform-test/interval.1.in b/alpha-core/src/test/resources/transform-test/interval.1.in similarity index 100% rename from src/test/resources/transform-test/interval.1.in rename to alpha-core/src/test/resources/transform-test/interval.1.in diff --git a/src/test/resources/transform-test/interval.1.out b/alpha-core/src/test/resources/transform-test/interval.1.out similarity index 100% rename from src/test/resources/transform-test/interval.1.out rename to alpha-core/src/test/resources/transform-test/interval.1.out diff --git a/alpha-solver/.gitignore b/alpha-solver/.gitignore new file mode 100644 index 000000000..84c048a73 --- /dev/null +++ b/alpha-solver/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/alpha-solver/build.gradle.kts b/alpha-solver/build.gradle.kts new file mode 100644 index 000000000..b0c59c197 --- /dev/null +++ b/alpha-solver/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("alpha.java-library-conventions") +} + +dependencies { + api(project(":alpha-api")) + api(project(":alpha-commons")) + implementation(project(":alpha-core")) +} + +tasks.test { + useJUnitPlatform() +} diff --git a/alpha-solver/src/main/java/at/ac/tuwien/kr/alpha/api/impl/AlphaImpl.java b/alpha-solver/src/main/java/at/ac/tuwien/kr/alpha/api/impl/AlphaImpl.java new file mode 100644 index 000000000..c49a5ca39 --- /dev/null +++ b/alpha-solver/src/main/java/at/ac/tuwien/kr/alpha/api/impl/AlphaImpl.java @@ -0,0 +1,294 @@ +/** + * Copyright (c) 2017-2019, 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.api.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.Channels; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; + +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.DebugSolvingContext; +import at.ac.tuwien.kr.alpha.api.Solver; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +import at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration; +import at.ac.tuwien.kr.alpha.api.config.InputConfig; +import at.ac.tuwien.kr.alpha.api.config.SystemConfig; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.Predicate; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.analysis.ComponentGraph; +import at.ac.tuwien.kr.alpha.api.programs.analysis.DependencyGraph; +import at.ac.tuwien.kr.alpha.commons.util.Util; +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.grounder.Grounder; +import at.ac.tuwien.kr.alpha.core.grounder.GrounderFactory; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.programs.InternalProgram; +import at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation; +import at.ac.tuwien.kr.alpha.core.programs.transformation.StratifiedEvaluation; +import at.ac.tuwien.kr.alpha.core.solver.SolverFactory; + +public class AlphaImpl implements Alpha { + + private static final Logger LOGGER = LoggerFactory.getLogger(AlphaImpl.class); + + private SystemConfig config = new SystemConfig(); // Config is initialized with default values. + private ProgramParser parser = new ProgramParserImpl(); + + public AlphaImpl(SystemConfig cfg) { + this.config = cfg; + } + + public AlphaImpl() { + } + + @Override + public ASPCore2Program readProgram(InputConfig cfg) throws IOException { + InputProgram.Builder prgBuilder = InputProgram.builder(); + ASPCore2Program tmpProg; + if (!cfg.getFiles().isEmpty()) { + tmpProg = readProgramFiles(cfg.isLiterate(), cfg.getPredicateMethods(), cfg.getFiles()); + prgBuilder.accumulate(tmpProg); + } + if (!cfg.getAspStrings().isEmpty()) { + tmpProg = readProgramString(StringUtils.join(cfg.getAspStrings(), System.lineSeparator()), cfg.getPredicateMethods()); + prgBuilder.accumulate(tmpProg); + } + return prgBuilder.build(); + } + + @Override + public ASPCore2Program readProgramFiles(boolean literate, Map externals, List paths) throws IOException { + return readProgramFiles(literate, externals, paths.stream().map(Paths::get).collect(Collectors.toList()).toArray(new Path[] {})); + } + + @Override + public ASPCore2Program readProgramFiles(boolean literate, Map externals, Path... paths) throws IOException { + InputProgram.Builder prgBuilder = InputProgram.builder(); + ASPCore2Program tmpProg; + for (Path path : paths) { + InputStream stream; + if (!literate) { + stream = Files.newInputStream(path); + } else { + stream = Channels.newInputStream(Util.streamToChannel(Util.literate(Files.lines(path)))); + } + tmpProg = parser.parse(stream, externals); + prgBuilder.accumulate(tmpProg); + } + return prgBuilder.build(); + } + + @Override + public ASPCore2Program readProgramString(String aspString, Map externals) { + return parser.parse(aspString, externals); + } + + @Override + public ASPCore2Program readProgramString(String aspString) { + return readProgramString(aspString, Collections.emptyMap()); + } + + @Override + public NormalProgram normalizeProgram(ASPCore2Program program) { + return new NormalizeProgramTransformation(config.getAggregateRewritingConfig()).apply(program); + } + + @VisibleForTesting + InternalProgram performProgramPreprocessing(NormalProgram program) { + LOGGER.debug("Preprocessing InternalProgram!"); + InternalProgram retVal = InternalProgram.fromNormalProgram(program); + if (config.isEvaluateStratifiedPart()) { + AnalyzedProgram analyzed = new AnalyzedProgram(retVal.getRules(), retVal.getFacts()); + retVal = new StratifiedEvaluation().apply(analyzed); + } + return retVal; + } + + /** + * Convenience method - overloaded version of solve({@link InternalProgram}) for cases where details of the + * program analysis and normalization aren't of interest. + */ + @Override + public Stream solve(ASPCore2Program program) { + return solve(program, InputConfig.DEFAULT_FILTER); + } + + /** + * Convenience method - overloaded version of solve({@link InternalProgram}, {@link Predicate}) for cases where + * details of the program analysis and normalization aren't of interest. + */ + @Override + public Stream solve(ASPCore2Program program, java.util.function.Predicate filter) { + NormalProgram normalized = normalizeProgram(program); + return solve(normalized, filter); + } + + @Override + public Stream solve(NormalProgram program) { + return solve(program, InputConfig.DEFAULT_FILTER); + } + + /** + * Convenience method - overloaded version of solve({@link InternalProgram}) for cases where details of the + * program analysis aren't of interest. + */ + @Override + public Stream solve(NormalProgram program, java.util.function.Predicate filter) { + CompiledProgram preprocessed = performProgramPreprocessing(program); + return solve(preprocessed, filter); + } + + /** + * Solves the given program and filters answer sets based on the passed predicate. + * + * @param program an {@link InternalProgram} to solve + * @param filter {@link Predicate} filtering {@at.ac.tuwien.kr.alpha.common.Predicate}s in the returned answer sets + * @return a Stream of answer sets representing stable models of the given program + */ + private Stream solve(CompiledProgram program, java.util.function.Predicate filter) { + Stream retVal = prepareSolverFor(program, filter).stream(); + return config.isSortAnswerSets() ? retVal.sorted() : retVal; + } + + /** + * Prepares a solver (and accompanying grounder) instance pre-loaded with the given program. Use this if the + * solver is needed after reading answer sets (e.g. for obtaining statistics). + * + * @param program the program to solve. + * @param filter a (java util) predicate that filters (asp-)predicates which should be contained in the answer + * set stream from the solver. + * @return a solver (and accompanying grounder) instance pre-loaded with the given program. + */ + private Solver prepareSolverFor(CompiledProgram program, java.util.function.Predicate filter) { + String grounderName = config.getGrounderName(); + boolean doDebugChecks = config.isDebugInternalChecks(); + + GrounderHeuristicsConfiguration grounderHeuristicConfiguration = GrounderHeuristicsConfiguration + .getInstance(config.getGrounderToleranceConstraints(), config.getGrounderToleranceRules()); + grounderHeuristicConfiguration.setAccumulatorEnabled(config.isGrounderAccumulatorEnabled()); + + AtomStore atomStore = new AtomStoreImpl(); + Grounder grounder = GrounderFactory.getInstance(grounderName, program, atomStore, filter, grounderHeuristicConfiguration, doDebugChecks); + + return SolverFactory.getInstance(config, atomStore, grounder); + } + + public void setConfig(SystemConfig config) { + this.config = config; + } + + @Override + public DebugSolvingContext prepareDebugSolve(ASPCore2Program program) { + return prepareDebugSolve(program, InputConfig.DEFAULT_FILTER); + } + + @Override + public DebugSolvingContext prepareDebugSolve(NormalProgram program) { + return prepareDebugSolve(program, InputConfig.DEFAULT_FILTER); + } + + @Override + public DebugSolvingContext prepareDebugSolve(final ASPCore2Program program, java.util.function.Predicate filter) { + return prepareDebugSolve(normalizeProgram(program), filter); + } + + @Override + public DebugSolvingContext prepareDebugSolve(final NormalProgram program, java.util.function.Predicate filter) { + final DependencyGraph depGraph; + final ComponentGraph compGraph; + final AnalyzedProgram analyzed = AnalyzedProgram.analyzeNormalProgram(program); + final NormalProgram preprocessed; + if (this.config.isEvaluateStratifiedPart()) { + preprocessed = new StratifiedEvaluation().apply(analyzed).toNormalProgram(); + } else { + preprocessed = program; + } + depGraph = analyzed.getDependencyGraph(); + compGraph = analyzed.getComponentGraph(); + final Solver solver = prepareSolverFor(analyzed, filter); + return new DebugSolvingContext() { + + @Override + public Solver getSolver() { + return solver; + } + + @Override + public NormalProgram getPreprocessedProgram() { + return preprocessed; + } + + @Override + public NormalProgram getNormalizedProgram() { + return program; + } + + @Override + public DependencyGraph getDependencyGraph() { + return depGraph; + } + + @Override + public ComponentGraph getComponentGraph() { + return compGraph; + } + }; + } + + @Override + public Solver prepareSolverFor(ASPCore2Program program, java.util.function.Predicate filter) { + return prepareSolverFor(normalizeProgram(program), filter); + } + + @Override + public Solver prepareSolverFor(NormalProgram program, java.util.function.Predicate filter) { + return prepareSolverFor(performProgramPreprocessing(program), filter); + } + +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/api/AlphaTest.java b/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/AlphaImplTest.java similarity index 62% rename from src/test/java/at/ac/tuwien/kr/alpha/api/AlphaTest.java rename to alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/AlphaImplTest.java index 3259e6067..176862d40 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/api/AlphaTest.java +++ b/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/AlphaImplTest.java @@ -25,7 +25,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.api; +package at.ac.tuwien.kr.alpha.api.impl; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -37,41 +37,83 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import at.ac.tuwien.kr.alpha.api.externals.Externals; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AnswerSetBuilder; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalAtom; -import at.ac.tuwien.kr.alpha.common.atoms.ExternalLiteral; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.MethodPredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.config.InputConfig; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; -import at.ac.tuwien.kr.alpha.test.util.AnswerSetsParser; -import at.ac.tuwien.kr.alpha.test.util.TestUtils; - -public class AlphaTest { - private static int invocations; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.kr.alpha.api.Alpha; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +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; +import at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program; +import at.ac.tuwien.kr.alpha.api.programs.NormalProgram; +import at.ac.tuwien.kr.alpha.api.programs.ProgramParser; +import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom; +import at.ac.tuwien.kr.alpha.api.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.commons.AnswerSetBuilder; +import at.ac.tuwien.kr.alpha.commons.Predicates; +import at.ac.tuwien.kr.alpha.commons.atoms.Atoms; +import at.ac.tuwien.kr.alpha.commons.literals.Literals; +import at.ac.tuwien.kr.alpha.commons.rules.heads.Heads; +import at.ac.tuwien.kr.alpha.commons.terms.Terms; +import at.ac.tuwien.kr.alpha.core.common.fixedinterpretations.MethodPredicateInterpretation; +import at.ac.tuwien.kr.alpha.core.externals.AspStandardLibrary; +import at.ac.tuwien.kr.alpha.core.externals.Externals; +import at.ac.tuwien.kr.alpha.core.parser.InlineDirectivesImpl; +import at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl; +import at.ac.tuwien.kr.alpha.core.programs.CompiledProgram; +import at.ac.tuwien.kr.alpha.core.programs.InputProgram; +import at.ac.tuwien.kr.alpha.core.rules.BasicRule; + +public class AlphaImplTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(AspStandardLibrary.class); + + //@formatter:off + private static final String STRINGSTUFF_ASP = + "string(\"bla\")." + + "string(\"blubb\")." + + "string(\"foo\")." + + "string(\"bar\")." + + "{ strcat(S1, S2) } :- string(S1), string(S2)." + + "resultstring(SCAT) :- strcat(S1, S2), &stdlib_string_concat[S1, S2](SCAT)." + + ":- resultstring(S), &stdlib_string_length[S](LEN), LEN != 6." + + "containsFoo(S) :- resultstring(S), &stdlib_string_matches_regex[S, \".*foo.*\"]." + + ":- resultstring(S), not containsFoo(S)." + + "has_resultstring :- resultstring(_)." + + ":- not has_resultstring."; + + // same as stringstuff asp, but without the "containsFoo" intermediate predicate + private static final String NEGATED_EXTERNAL_ASP = + "string(\"bla\")." + + "string(\"blubb\")." + + "string(\"foo\")." + + "string(\"bar\")." + + "{ strcat(S1, S2) } :- string(S1), string(S2)." + + "resultstring(SCAT) :- strcat(S1, S2), &stdlib_string_concat[S1, S2](SCAT)." + + ":- resultstring(S), &stdlib_string_length[S](LEN), LEN != 6." + + ":- resultstring(S), not &stdlib_string_matches_regex[S, \".*foo.*\"]." + + "has_resultstring :- resultstring(_)." + + ":- not has_resultstring."; + //@formatter:on + private static int invocations; + @at.ac.tuwien.kr.alpha.api.externals.Predicate public static boolean isOne(int term) { invocations++; @@ -91,10 +133,10 @@ public static boolean thinger(Thingy thingy) { @Test public void withExternal() throws Exception { - Alpha alpha = new Alpha(); + Alpha alpha = new AlphaImpl(); InputConfig inputCfg = InputConfig.forString("a :- &isOne[1]."); inputCfg.addPredicateMethod("isOne", Externals.processPredicateMethod(this.getClass().getMethod("isOne", int.class))); - InputProgram program = alpha.readProgram(inputCfg); + ASPCore2Program program = alpha.readProgram(inputCfg); Set actual = alpha.solve(program).collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").build())); assertEquals(expected, actual); @@ -102,7 +144,7 @@ public void withExternal() throws Exception { @Test public void addsFacts() { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); Thingy a = new Thingy(); Thingy b = new Thingy(); List things = asList(a, b); @@ -115,21 +157,21 @@ public void addsFacts() { @Test public void withExternalTypeConflict() { assertThrows(IllegalArgumentException.class, () -> { - Alpha system = new Alpha(); - InputConfig inputCfg = InputConfig.forString("a :- &isFoo[\"adsfnfdsf\"]."); - inputCfg.addPredicateMethod("isFoo", Externals.processPredicateMethod(this.getClass().getMethod("isFoo", Integer.class))); - Set actual = system.solve(system.readProgram(inputCfg)).collect(Collectors.toSet()); - Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").build())); - assertEquals(expected, actual); - }); + Alpha system = new AlphaImpl(); + InputConfig inputCfg = InputConfig.forString("a :- &isFoo[\"adsfnfdsf\"]."); + inputCfg.addPredicateMethod("isFoo", Externals.processPredicateMethod(this.getClass().getMethod("isFoo", Integer.class))); + Set actual = system.solve(system.readProgram(inputCfg)).collect(Collectors.toSet()); + Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").build())); + assertEquals(expected, actual); +}); } @Test public void smallGraph() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig inputCfg = InputConfig.forString("node(1). node(2). node(3). a :- &connected[1,2]."); inputCfg.addPredicateMethod("connected", Externals.processPredicate((Integer a, Integer b) -> (a == 1 && b == 2) || (b == 2 || b == 3))); - InputProgram program = system.readProgram(inputCfg); + ASPCore2Program program = system.readProgram(inputCfg); Set actual = system.solve(program).collect(Collectors.toSet()); Set expected = AnswerSetsParser.parse("{ a, node(1), node(2), node(3) }"); @@ -138,12 +180,12 @@ public void smallGraph() throws Exception { @Test public void filterOutput() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig inputCfg = InputConfig.forString("node(1). node(2). outgoing13(X) :- node(X), &getLargeGraphEdges(13,X)."); inputCfg.addPredicateMethod("getLargeGraphEdges", - Externals.processPredicate(() -> new HashSet<>(asList(asList(ConstantTerm.getInstance(1), ConstantTerm.getInstance(2)), - asList(ConstantTerm.getInstance(2), ConstantTerm.getInstance(1)), asList(ConstantTerm.getInstance(13), ConstantTerm.getInstance(1)))))); - InputProgram program = system.readProgram(inputCfg); + Externals.processPredicate(() -> new HashSet<>(asList(asList(Terms.newConstant(1), Terms.newConstant(2)), + asList(Terms.newConstant(2), Terms.newConstant(1)), asList(Terms.newConstant(13), Terms.newConstant(1)))))); + ASPCore2Program program = system.readProgram(inputCfg); Set actual = system.solve(program).collect(Collectors.toSet()); Set expected = AnswerSetsParser.parse("{ node(1), node(2), outgoing13(1) }"); assertEquals(expected, actual); @@ -151,10 +193,10 @@ public void filterOutput() throws Exception { @Test public void supplier() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("node(1). a :- &bestNode(X), node(X)."); - cfg.addPredicateMethod("bestNode", Externals.processPredicate(() -> singleton(singletonList(ConstantTerm.getInstance(1))))); - InputProgram prog = system.readProgram(cfg); + cfg.addPredicateMethod("bestNode", Externals.processPredicate(() -> singleton(singletonList(Terms.newConstant(1))))); + ASPCore2Program prog = system.readProgram(cfg); Set expected = AnswerSetsParser.parse("{ node(1), a }"); Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -163,15 +205,15 @@ public void supplier() throws Exception { @at.ac.tuwien.kr.alpha.api.externals.Predicate public static Set>> bestNode() { - return singleton(singletonList(ConstantTerm.getInstance(1))); + return singleton(singletonList(Terms.newConstant(1))); } @Test public void noInput() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("node(1). a :- &bestNode(X), node(X)."); cfg.addPredicateMethod("bestNode", Externals.processPredicateMethod(this.getClass().getMethod("bestNode"))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set expected = AnswerSetsParser.parse("{ node(1), a }"); Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -181,18 +223,18 @@ public void noInput() throws Exception { @Test public void smallGraphWithWrongType() { assertThrows(IllegalArgumentException.class, () -> { - Alpha system = new Alpha(); - InputConfig cfg = InputConfig.forString("a :- &connected[\"hello\",2]."); - cfg.addPredicateMethod("connected", Externals.processPredicate((Integer a, Integer b) -> (a == 1 && b == 2) || (b == 2 || b == 3))); - InputProgram prog = system.readProgram(cfg); - - system.solve(prog).collect(Collectors.toSet()); + Alpha system = new AlphaImpl(); + InputConfig cfg = InputConfig.forString("a :- &connected[\"hello\",2]."); + cfg.addPredicateMethod("connected", Externals.processPredicate((Integer a, Integer b) -> (a == 1 && b == 2) || (b == 2 || b == 3))); + ASPCore2Program prog = system.readProgram(cfg); + + system.solve(prog).collect(Collectors.toSet()); }); } public static Set>> neighbors(int node) { if (node == 1) { - return new HashSet<>(asList(singletonList(ConstantTerm.getInstance(2)), singletonList(ConstantTerm.getInstance(3)))); + return new HashSet<>(asList(singletonList(Terms.newConstant(2)), singletonList(Terms.newConstant(3)))); } return emptySet(); } @@ -207,10 +249,10 @@ public static Set>> coolNode(int node) { @Test @Disabled("Test program is not safe (external lacking output variables). This should throw some exception.") public void smallGraphNoNeighbors() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("noNeighbors(2) :- not &neighbors[2]."); cfg.addPredicateMethod("neighbors", Externals.processPredicateMethod(this.getClass().getMethod("neighbors", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set expected = AnswerSetsParser.parse("{ noNeighbors(2) }"); Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -219,10 +261,10 @@ public void smallGraphNoNeighbors() throws Exception { @Test public void smallGraphCoolNode() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("node(1..2). in(X) :- node(X), &coolNode[X]."); cfg.addPredicateMethod("coolNode", Externals.processPredicateMethod(this.getClass().getMethod("coolNode", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set actual = system.solve(prog).collect(Collectors.toSet()); Set expected = AnswerSetsParser.parse("{ in(1), node(1), node(2) }"); @@ -231,10 +273,10 @@ public void smallGraphCoolNode() throws Exception { @Test public void smallGraphSingleNeighbor() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("node(1..3). in(1,X) :- &neighbors[1](X), node(X)."); cfg.addPredicateMethod("neighbors", Externals.processPredicateMethod(this.getClass().getMethod("neighbors", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set expected = AnswerSetsParser.parse("{ in(1,2), in(1,3), node(1), node(2), node(3) }"); Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -244,10 +286,10 @@ public void smallGraphSingleNeighbor() throws Exception { @Test @Disabled("Test program is not safe (external lacking output variables). This should throw some exception.") public void smallGraphSingleNeighborNoTerm() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("success :- &neighbors[1], not &neighbors[2]."); cfg.addPredicateMethod("neighbors", Externals.processPredicateMethod(this.getClass().getMethod("neighbors", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set expected = AnswerSetsParser.parse("{ success }"); Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -274,14 +316,14 @@ public void withExternalSubtype() throws Exception { SubThingy thingy = new SubThingy(); BasicRule rule = new BasicRule( - new NormalHead(new BasicAtom(Predicate.getInstance("p", 1), ConstantTerm.getInstance("x"))), - singletonList(new ExternalLiteral(new ExternalAtom(Predicate.getInstance("thinger", 1), - new MethodPredicateInterpretation(this.getClass().getMethod("thinger", Thingy.class)), singletonList(ConstantTerm.getInstance(thingy)), + Heads.newNormalHead(Atoms.newBasicAtom(Predicates.getPredicate("p", 1), Terms.newConstant("x"))), + singletonList(Literals.fromAtom(Atoms.newExternalAtom(Predicates.getPredicate("thinger", 1), + new MethodPredicateInterpretation(this.getClass().getMethod("thinger", Thingy.class)), singletonList(Terms.newConstant(thingy)), emptyList()), true))); - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); - InputProgram prog = new InputProgram(new ArrayList<>(singleton(rule)), emptyList(), new InlineDirectives()); + InputProgram prog = new InputProgram(singletonList(rule), emptyList(), new InlineDirectivesImpl()); Set actual = system.solve(prog).collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("p").instance("x").build())); @@ -290,10 +332,10 @@ public void withExternalSubtype() throws Exception { @Test public void withExternalViaAnnotation() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("a :- &isOne[1]."); cfg.addPredicateMethods(Externals.scan(this.getClass())); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set actual = system.solve(prog).collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").build())); @@ -308,18 +350,18 @@ public void withExternalViaAnnotation() throws Exception { @Test public void errorDuplicateExternal() { assertThrows(IllegalArgumentException.class, () -> { - InputConfig cfg = InputConfig.forString("someString."); - cfg.addPredicateMethods(Externals.scan(this.getClass())); - cfg.addPredicateMethods(Externals.scan(this.getClass())); - }); + InputConfig cfg = InputConfig.forString("someString."); + cfg.addPredicateMethods(Externals.scan(this.getClass())); + cfg.addPredicateMethods(Externals.scan(this.getClass())); +}); } @Test public void withNativeExternal() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("a :- &isTwo[2]."); cfg.addPredicateMethod("isTwo", Externals.processPredicate((Integer t) -> t == 2)); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); Set actual = system.solve(prog).collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").build())); @@ -329,10 +371,10 @@ public void withNativeExternal() throws Exception { @Test @Disabled("External atom has state, which is not allowed. Caching of calls makes the number of invocations wrong.") public void withExternalInvocationCounted1() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("a :- &isOne[1], &isOne[1]."); cfg.addPredicateMethod("isOne", Externals.processPredicateMethod(this.getClass().getMethod("isOne", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); int before = invocations; Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -347,10 +389,10 @@ public void withExternalInvocationCounted1() throws Exception { @Test @Disabled("External atom has state, which is not allowed. Caching of calls makes the number of invocations wrong.") public void withExternalInvocationCounted2() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("a. b :- &isOne[1], &isOne[2]."); cfg.addPredicateMethod("isOne", Externals.processPredicateMethod(this.getClass().getMethod("isOne", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); int before = invocations; Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -365,10 +407,10 @@ public void withExternalInvocationCounted2() throws Exception { @Test @Disabled("External atom has state, which is not allowed. Caching of calls makes the number of invocations wrong.") public void withExternalInvocationCounted3() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); InputConfig cfg = InputConfig.forString("a :- &isOne[1], not &isOne[2]."); cfg.addPredicateMethod("isOne", Externals.processPredicateMethod(this.getClass().getMethod("isOne", int.class))); - InputProgram prog = system.readProgram(cfg); + ASPCore2Program prog = system.readProgram(cfg); int before = invocations; Set actual = system.solve(prog).collect(Collectors.toSet()); @@ -379,10 +421,44 @@ public void withExternalInvocationCounted3() throws Exception { Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").build())); assertEquals(expected, actual); } + + @Test + @SuppressWarnings("unchecked") + public void programWithExternalStringStuff() throws IOException { + Alpha alpha = new AlphaImpl(); + ASPCore2Program prog = alpha.readProgram(InputConfig.forString(STRINGSTUFF_ASP)); + Set answerSets = alpha.solve(prog).collect(Collectors.toSet()); + // Verify every result string has length 6 and contains "foo" + for (AnswerSet as : answerSets) { + for (Atom atom : as.getPredicateInstances(Predicates.getPredicate("resultstring", 1))) { + String resultstring = ((ConstantTerm) atom.getTerms().get(0)).getObject(); + assertEquals(6, resultstring.length()); + assertTrue(resultstring.contains("foo")); + } + } + } + + @Test + @SuppressWarnings("unchecked") + public void withNegatedExternal() throws IOException { + Alpha alpha = new AlphaImpl(); + ASPCore2Program prog = alpha.readProgram(InputConfig.forString(NEGATED_EXTERNAL_ASP)); + Set answerSets = alpha.solve(prog).collect(Collectors.toSet()); + assertEquals(31, answerSets.size()); + // Verify every result string has length 6 and contains "foo" + for (AnswerSet as : answerSets) { + for (Atom atom : as.getPredicateInstances(Predicates.getPredicate("resultstring", 1))) { + String resultstring = ((ConstantTerm) atom.getTerms().get(0)).getObject(); + LOGGER.debug("ResultString is {}", resultstring); + assertEquals(6, resultstring.length()); + assertTrue(resultstring.contains("foo")); + } + } + } @Test public void basicUsage() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); Set actual = system.solve(system.readProgram(InputConfig.forString("p(a)."))).collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("p").symbolicInstance("a").build())); assertEquals(expected, actual); @@ -390,7 +466,7 @@ public void basicUsage() throws Exception { @Test public void basicUsageWithString() throws Exception { - Alpha system = new Alpha(); + Alpha system = new AlphaImpl(); Set actual = system.solve(system.readProgram(InputConfig.forString("p(\"a\")."))).collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("p").instance("a").build())); assertEquals(expected, actual); @@ -402,9 +478,9 @@ public void basicUsageWithString() throws Exception { @Test public void filterTest() { String progstr = "a. b. c. d :- c. e(a, b) :- d."; - Alpha system = new Alpha(); - InputProgram prog = system.readProgramString(progstr, null); - Set actual = system.solve(prog, (p) -> p.equals(Predicate.getInstance("a", 0)) || p.equals(Predicate.getInstance("e", 2))) + Alpha system = new AlphaImpl(); + ASPCore2Program prog = system.readProgramString(progstr); + Set actual = system.solve(prog, (p) -> p.equals(Predicates.getPredicate("a", 0)) || p.equals(Predicates.getPredicate("e", 2))) .collect(Collectors.toSet()); Set expected = new HashSet<>(singletonList(new AnswerSetBuilder().predicate("a").predicate("e").symbolicInstance("a", "b").build())); assertEquals(expected, actual); @@ -415,14 +491,15 @@ public void filterTest() { */ @Test public void disableStratifiedEvalTest() { + // Note: This might be cleaner if the test used the debugSolve method from the interface String progstr = "p(a). q(X) :- p(X)."; SystemConfig cfg = new SystemConfig(); cfg.setEvaluateStratifiedPart(false); - Alpha system = new Alpha(cfg); - InputProgram input = system.readProgramString(progstr); + AlphaImpl system = new AlphaImpl(cfg); + ASPCore2Program input = system.readProgramString(progstr); NormalProgram normal = system.normalizeProgram(input); - InternalProgram preprocessed = system.performProgramPreprocessing(InternalProgram.fromNormalProgram(normal)); - assertFalse(preprocessed.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("q", "a")), + CompiledProgram preprocessed = system.performProgramPreprocessing(normal); + assertFalse(preprocessed.getFacts().contains(Atoms.newBasicAtom(Predicates.getPredicate("q", 1), Terms.newSymbolicConstant("a"))), "Preprocessed program contains fact derived from stratifiable rule, but should not!"); } @@ -431,13 +508,14 @@ public void disableStratifiedEvalTest() { */ @Test public void enableStratifiedEvalTest() { + // Note: This might be cleaner if the test used the debugSolve method from the interface String progstr = "p(a). q(X) :- p(X)."; SystemConfig cfg = new SystemConfig(); - Alpha system = new Alpha(cfg); - InputProgram input = system.readProgramString(progstr); + AlphaImpl system = new AlphaImpl(cfg); + ASPCore2Program input = system.readProgramString(progstr); NormalProgram normal = system.normalizeProgram(input); - InternalProgram preprocessed = system.performProgramPreprocessing(InternalProgram.fromNormalProgram(normal)); - assertTrue(preprocessed.getFacts().contains(TestUtils.basicAtomWithSymbolicTerms("q", "a")), + CompiledProgram preprocessed = system.performProgramPreprocessing(normal); + assertTrue(preprocessed.getFacts().contains(Atoms.newBasicAtom(Predicates.getPredicate("q", 1), Terms.newSymbolicConstant("a"))), "Preprocessed program does not contain fact derived from stratifiable rule, but should!"); } @@ -494,14 +572,14 @@ public void problematicRun_3col_1119718541727902_sorted_400() throws IOException cfg.setNogoodStoreName("alpharoaming"); cfg.setDebugInternalChecks(true); cfg.setSeed(1119718541727902L); - final Alpha system = new Alpha(cfg); + final Alpha system = new AlphaImpl(cfg); final Path path = Paths.get("src", "test", "resources", "PreviouslyProblematic").resolve("3col-20-38.txt"); InputConfig inputCfg = new InputConfig(); List files = new ArrayList<>(); files.add(path.toString()); inputCfg.setFiles(files); - InputProgram prog = system.readProgram(inputCfg); + ASPCore2Program prog = system.readProgram(inputCfg); assertFalse(system.solve(prog).sorted().limit(400).collect(Collectors.toList()).isEmpty()); } @@ -514,12 +592,39 @@ private void problematicRun(String program, long seed, int limit) throws IOExcep cfg.setNogoodStoreName("alpharoaming"); cfg.setDebugInternalChecks(true); cfg.setSeed(seed); - final Alpha system = new Alpha(cfg); + final Alpha system = new AlphaImpl(cfg); InputConfig inputCfg = new InputConfig(); List files = new ArrayList<>(); files.add(base.resolve(program).toString()); inputCfg.setFiles(files); - InputProgram prog = system.readProgram(inputCfg); + ASPCore2Program prog = system.readProgram(inputCfg); assertFalse(system.solve(prog).limit(limit).collect(Collectors.toList()).isEmpty()); } + + // Detailed reproduction test-case for github issue #239. + @Test + public void testLearnedUnaryNoGoodCausingOutOfOrderLiteralsConflict() throws IOException { + final ProgramParser parser = new ProgramParserImpl(); + InputProgram.Builder bld = InputProgram.builder(); + bld.accumulate(parser.parse(Files.newInputStream(Paths.get("src", "test", "resources", "HanoiTower_Alpha.asp"), StandardOpenOption.READ))); + bld.accumulate(parser.parse(Files.newInputStream(Paths.get("src", "test", "resources", "HanoiTower_instances", "simple.asp"), StandardOpenOption.READ))); + InputProgram parsedProgram = bld.build(); + + SystemConfig config = new SystemConfig(); + config.setSolverName("default"); + config.setNogoodStoreName("alpharoaming"); + config.setSeed(0); + config.setBranchingHeuristic(Heuristic.valueOf("VSIDS")); + config.setDebugInternalChecks(true); + config.setDisableJustificationSearch(false); + config.setEvaluateStratifiedPart(false); + config.setReplayChoices(Arrays.asList(21, 26, 36, 56, 91, 96, 285, 166, 101, 290, 106, 451, 445, 439, 448, + 433, 427, 442, 421, 415, 436, 409, 430, 397, 391, 424, 385, 379, + 418, 373, 412, 406, 394, 388, 382, 245, 232, 208 + )); + Alpha alpha = new AlphaImpl(config); + Optional answerSet = alpha.solve(parsedProgram).findFirst(); + assertTrue(answerSet.isPresent()); + } + } diff --git a/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/AnswerSetsParser.java b/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/AnswerSetsParser.java new file mode 100644 index 000000000..a197d62e8 --- /dev/null +++ b/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/AnswerSetsParser.java @@ -0,0 +1,45 @@ +package at.ac.tuwien.kr.alpha.api.impl; + +import java.util.Collections; +import java.util.Set; + +import org.antlr.v4.runtime.BailErrorStrategy; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.atn.PredictionMode; +import org.antlr.v4.runtime.misc.ParseCancellationException; + +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Lexer; +import at.ac.tuwien.kr.alpha.core.antlr.ASPCore2Parser; +import at.ac.tuwien.kr.alpha.core.parser.ParseTreeVisitor; + +// TODO this is duplicated from core module, need to pull out test utils into separate testsupport module +public class AnswerSetsParser { + + private static final ParseTreeVisitor VISITOR = new ParseTreeVisitor(Collections.emptyMap(), false); + + public static Set parse(String s) { + try { + return parse(CharStreams.fromString(s)); + } catch (RecognitionException | ParseCancellationException e) { + // If there were issues parsing the given string, we + // throw something that suggests that the input string + // is malformed. + throw new IllegalArgumentException("Could not parse answer sets.", e); + } + } + + public static Set parse(CharStream stream) { + final ASPCore2Parser parser = new ASPCore2Parser(new CommonTokenStream(new ASPCore2Lexer(stream))); + + // Try SLL parsing mode (faster but may terminate incorrectly). + parser.getInterpreter().setPredictionMode(PredictionMode.SLL); + parser.removeErrorListeners(); + parser.setErrorHandler(new BailErrorStrategy()); + + return VISITOR.translate(parser.answer_sets()); + } +} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/FixedInterpretationLiteralsTest.java b/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/FixedInterpretationLiteralsTest.java similarity index 71% rename from src/test/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/FixedInterpretationLiteralsTest.java rename to alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/FixedInterpretationLiteralsTest.java index 1729851be..6d236e447 100644 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/fixedinterpretations/FixedInterpretationLiteralsTest.java +++ b/alpha-solver/src/test/java/at/ac/tuwien/kr/alpha/api/impl/FixedInterpretationLiteralsTest.java @@ -1,4 +1,4 @@ -package at.ac.tuwien.kr.alpha.common.fixedinterpretations; +package at.ac.tuwien.kr.alpha.api.impl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -15,13 +15,16 @@ import org.junit.jupiter.api.Test; import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.api.externals.Externals; -import at.ac.tuwien.kr.alpha.api.externals.stdlib.AspStandardLibrary; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; +import at.ac.tuwien.kr.alpha.api.AnswerSet; +import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation; +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.ConstantTerm; +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.externals.AspStandardLibrary; +import at.ac.tuwien.kr.alpha.core.externals.Externals; public class FixedInterpretationLiteralsTest { @@ -42,12 +45,12 @@ public static Set>> connection(String dummy) { List> l1 = new ArrayList<>(); List> l2 = new ArrayList<>(); List> l3 = new ArrayList<>(); - l1.add(ConstantTerm.getInstance("Klagenfurt")); - l1.add(ConstantTerm.getInstance("Villach")); - l2.add(ConstantTerm.getInstance("Klagenfurt")); - l2.add(ConstantTerm.getInstance("Graz")); - l3.add(ConstantTerm.getInstance("Villach")); - l3.add(ConstantTerm.getInstance("Salzburg")); + l1.add(Terms.newConstant("Klagenfurt")); + l1.add(Terms.newConstant("Villach")); + l2.add(Terms.newConstant("Klagenfurt")); + l2.add(Terms.newConstant("Graz")); + l3.add(Terms.newConstant("Villach")); + l3.add(Terms.newConstant("Salzburg")); retVal.add(l1); retVal.add(l2); retVal.add(l3); @@ -76,7 +79,7 @@ public static Set>> connection(String dummy) { private Map externals; public FixedInterpretationLiteralsTest() { - this.alpha = new Alpha(); + this.alpha = new AlphaImpl(); this.externals = new HashMap<>(); this.externals.putAll(Externals.scan(AspStandardLibrary.class)); this.externals.putAll(Externals.scan(FixedInterpretationLiteralsTest.class)); @@ -87,7 +90,7 @@ public void positiveNumericComparison() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("positive_numeric_comparison", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_numeric_comparison", 0))); } @Test @@ -95,7 +98,7 @@ public void negativeNumericComparison() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("negative_numeric_comparison", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_numeric_comparison", 0))); } @Test @@ -103,7 +106,7 @@ public void positiveUnaryExternal() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("positive_unary_external", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_unary_external", 0))); } @Test @@ -111,7 +114,7 @@ public void negativeUnaryExternal() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("negative_unary_external", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_unary_external", 0))); } @Test @@ -119,7 +122,7 @@ public void positiveExternalWithOutput() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("positive_external_with_output", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_with_output", 0))); } @Test @@ -127,7 +130,7 @@ public void positiveExternalWithOutputDontfire() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertFalse(answerSet.getPredicates().contains(Predicate.getInstance("positive_external_with_output_dontfire", 0))); + assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_with_output_dontfire", 0))); } @Test @@ -135,7 +138,7 @@ public void negativeExternalWithOutput() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("negative_external_with_output", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_with_output", 0))); } @Test @@ -143,7 +146,7 @@ public void negativeExternalWithOutputDontfire() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertFalse(answerSet.getPredicates().contains(Predicate.getInstance("negative_external_with_output_dontfire", 0))); + assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_with_output_dontfire", 0))); } @Test @@ -151,7 +154,7 @@ public void negativeExternalMultioutput() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("negative_external_multioutput", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_multioutput", 0))); } @Test @@ -159,7 +162,7 @@ public void negativeExternalMultioutputDontfire() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertFalse(answerSet.getPredicates().contains(Predicate.getInstance("negative_external_multioutput_dontfire", 0))); + assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_multioutput_dontfire", 0))); } @Test @@ -167,7 +170,7 @@ public void positiveExternalMultioutput() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertTrue(answerSet.getPredicates().contains(Predicate.getInstance("positive_external_multioutput", 0))); + assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_multioutput", 0))); } @Test @@ -175,7 +178,7 @@ public void positiveExternalMultioutputDontfire() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - assertFalse(answerSet.getPredicates().contains(Predicate.getInstance("positive_external_multioutput_dontfire", 0))); + assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_multioutput_dontfire", 0))); } @Test @@ -183,13 +186,13 @@ public void positiveExternalBindingOutput() { Optional answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst(); assertTrue(answer.isPresent()); AnswerSet answerSet = answer.get(); - Predicate pred = Predicate.getInstance("positive_external_binding_output", 2); + Predicate pred = Predicates.getPredicate("positive_external_binding_output", 2); assertTrue(answerSet.getPredicates().contains(pred)); Set instances = answerSet.getPredicateInstances(pred); assertEquals(3, instances.size()); - assertTrue(instances.contains(new BasicAtom(pred, ConstantTerm.getInstance("Klagenfurt"), ConstantTerm.getInstance("Villach")))); - assertTrue(instances.contains(new BasicAtom(pred, ConstantTerm.getInstance("Klagenfurt"), ConstantTerm.getInstance("Graz")))); - assertTrue(instances.contains(new BasicAtom(pred, ConstantTerm.getInstance("Villach"), ConstantTerm.getInstance("Salzburg")))); + assertTrue(instances.contains(Atoms.newBasicAtom(pred, Terms.newConstant("Klagenfurt"), Terms.newConstant("Villach")))); + assertTrue(instances.contains(Atoms.newBasicAtom(pred, Terms.newConstant("Klagenfurt"), Terms.newConstant("Graz")))); + assertTrue(instances.contains(Atoms.newBasicAtom(pred, Terms.newConstant("Villach"), Terms.newConstant("Salzburg")))); } } diff --git a/alpha-solver/src/test/resources/HanoiTower_Alpha.asp b/alpha-solver/src/test/resources/HanoiTower_Alpha.asp new file mode 100644 index 000000000..922962744 --- /dev/null +++ b/alpha-solver/src/test/resources/HanoiTower_Alpha.asp @@ -0,0 +1,98 @@ +% HanoiTower +% Source: ASP Competition 2013 Official (disjunction shifted by ASP Shifter) +% ADAPTIONS FOR ALPHA: +% - replaced "TP1 = T + 1" by "succ(T,TP1)" because arithmetics are not supported +% - replaced "TM1 = T - 1" by "succ(TM1,T)" for the same reason + +peg(1). +peg(2). +peg(3). +peg(4). + +% Read in data +on(0, N1, N) :- on0(N, N1). +onG(K, N1, N) :- ongoal(N, N1), steps(K). + +% Specify valid arrangements of disks +% Basic condition. Smaller disks are on larger ones +:- time(T), on(T, N1, N), N1 >= N. + +% Specify a valid move (only for T (name.equals("NOTICE.txt") || name.equals("NOTICE")) ? "NOTICE." + (i++) + ".txt" : null } - - int j = 1 - rename { name -> (name.equals("LICENSE.txt") || name.equals("LICENSE")) ? "LICENSE." + (j++) + ".txt" : null } - - with jar -} - -jacocoTestReport { - reports { - xml.required = true - html.required = true - } - - // NOTE: Contents of the antlr subpackage are autogenerated (see configuration of - // AntlrTasks above). It does not make sense to include them in our coverage - // report. - afterEvaluate { - getClassDirectories().setFrom(files(classDirectories.files.collect { - fileTree(dir: it, exclude: "at/ac/tuwien/kr/alpha/antlr/**") - })) - } -} - -test { - useJUnitPlatform() - testLogging { - exceptionFormat = 'full' - } - -} - -wrapper { - gradleVersion = '7.3' - distributionType = 'ALL' -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..154e786e7 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + jacoco + + id("com.github.kt3k.coveralls") version "2.12.0" +} + +tasks.wrapper { + gradleVersion = "7.3" + distributionType = Wrapper.DistributionType.ALL +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..c1b2ed676 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral { metadataSources { mavenPom() } } +} diff --git a/buildSrc/src/main/kotlin/alpha.java-application-conventions.gradle.kts b/buildSrc/src/main/kotlin/alpha.java-application-conventions.gradle.kts new file mode 100644 index 000000000..0bb5a3a94 --- /dev/null +++ b/buildSrc/src/main/kotlin/alpha.java-application-conventions.gradle.kts @@ -0,0 +1,4 @@ +plugins { + id("alpha.java-common-conventions") + id("application") +} diff --git a/buildSrc/src/main/kotlin/alpha.java-common-conventions.gradle.kts b/buildSrc/src/main/kotlin/alpha.java-common-conventions.gradle.kts new file mode 100644 index 000000000..79f6bef04 --- /dev/null +++ b/buildSrc/src/main/kotlin/alpha.java-common-conventions.gradle.kts @@ -0,0 +1,70 @@ +import org.gradle.api.JavaVersion +import org.gradle.api.tasks.testing.logging.TestExceptionFormat + +plugins { + id("java") + id("jacoco") + id("checkstyle") + id("maven-publish") +} + +repositories { + mavenCentral { metadataSources { mavenPom() } } +} + +java.sourceCompatibility = JavaVersion.VERSION_1_8 +java.targetCompatibility = JavaVersion.VERSION_1_8 + +dependencies { + implementation("org.apache.commons:commons-collections4:4.4") + implementation("org.apache.commons:commons-lang3:3.12.0") + implementation("org.apache.commons:commons-text:1.9") + + implementation("org.reflections:reflections:0.9.11") + implementation("org.slf4j:slf4j-api:1.7.25") + + // JUnit 5 + val jupiterVersion = "5.7.1" + fun jupiter(component: String): String { + return "org.junit.jupiter:junit-jupiter-${component}:${jupiterVersion}" + } + testImplementation(jupiter("api")) + testImplementation(jupiter("params")) + testImplementation(jupiter("engine")) +} + +// JUnit 5 +tasks.withType { + useJUnitPlatform() + + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } +} + +// Fix checkstyle version. +checkstyle { + toolVersion = "7.6" +} + +tasks.withType { + val compilerArgs = options.compilerArgs + //compilerArgs.add("-Xdoclint:all,-missing") + compilerArgs.add("-Xlint:all") + compilerArgs.add("-Xmaxerrs") + compilerArgs.add("1000") +} + +tasks.jacocoTestReport { + reports { + xml.required.set(true) + } +} + +publishing { + publications { + create("binary") { + from(components["java"]) + } + } +} diff --git a/buildSrc/src/main/kotlin/alpha.java-library-conventions.gradle.kts b/buildSrc/src/main/kotlin/alpha.java-library-conventions.gradle.kts new file mode 100644 index 000000000..b0d16dd23 --- /dev/null +++ b/buildSrc/src/main/kotlin/alpha.java-library-conventions.gradle.kts @@ -0,0 +1,4 @@ +plugins { + id("alpha.java-common-conventions") + id("java-library") +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..d0a2210a4 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +version=0.8-SNAPSHOT +group=at.ac.tuwien.kr.alpha +org.gradle.warning.mode=all \ No newline at end of file diff --git a/gradlew.bat b/gradlew.bat index 107acd32c..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..28bf10ac3 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "alpha" +include("alpha-api", "alpha-cli-app", "alpha-core", "alpha-solver", "alpha-commons") \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java b/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java deleted file mode 100644 index 26770a0e9..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/api/Alpha.java +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Copyright (c) 2017-2019, 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.api; - -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.charset.CodingErrorAction; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.common.program.AnalyzedProgram; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.config.InputConfig; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.grounder.Grounder; -import at.ac.tuwien.kr.alpha.grounder.GrounderFactory; -import at.ac.tuwien.kr.alpha.grounder.heuristics.GrounderHeuristicsConfiguration; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.grounder.transformation.NormalizeProgramTransformation; -import at.ac.tuwien.kr.alpha.grounder.transformation.StratifiedEvaluation; -import at.ac.tuwien.kr.alpha.solver.Solver; -import at.ac.tuwien.kr.alpha.solver.SolverFactory; - -public class Alpha { - - private static final Logger LOGGER = LoggerFactory.getLogger(Alpha.class); - - private SystemConfig config = new SystemConfig(); // The config is initialized with default values. - - public Alpha(SystemConfig cfg) { - this.config = cfg; - } - - public Alpha() { - } - - public InputProgram readProgram(InputConfig cfg) throws IOException { - InputProgram.Builder prgBuilder = InputProgram.builder(); - InputProgram tmpProg; - if (!cfg.getFiles().isEmpty()) { - tmpProg = readProgramFiles(cfg.isLiterate(), cfg.getPredicateMethods(), cfg.getFiles()); - prgBuilder.accumulate(tmpProg); - } - if (!cfg.getAspStrings().isEmpty()) { - tmpProg = readProgramString(StringUtils.join(cfg.getAspStrings(), System.lineSeparator()), cfg.getPredicateMethods()); - prgBuilder.accumulate(tmpProg); - } - return prgBuilder.build(); - } - - public InputProgram readProgramFiles(boolean literate, Map externals, List paths) throws IOException { - return readProgramFiles(literate, externals, paths.stream().map(Paths::get).collect(Collectors.toList()).toArray(new Path[] {})); - } - - public InputProgram readProgramFiles(boolean literate, Map externals, Path... paths) throws IOException { - ProgramParser parser = new ProgramParser(externals); - InputProgram.Builder prgBuilder = InputProgram.builder(); - InputProgram tmpProg; - for (Path path : paths) { - CharStream stream; - if (!literate) { - stream = CharStreams.fromPath(path); - } else { - stream = CharStreams.fromChannel(Util.streamToChannel(Util.literate(Files.lines(path))), 4096, CodingErrorAction.REPLACE, path.toString()); - } - tmpProg = parser.parse(stream); - prgBuilder.accumulate(tmpProg); - } - return prgBuilder.build(); - } - - public InputProgram readProgramString(String aspString, Map externals) { - ProgramParser parser = new ProgramParser(externals); - return parser.parse(aspString); - } - - public InputProgram readProgramString(String aspString) { - return readProgramString(aspString, null); - } - - public NormalProgram normalizeProgram(InputProgram program) { - return new NormalizeProgramTransformation(config.getAggregateRewritingConfig()).apply(program); - } - - public InternalProgram performProgramPreprocessing(InternalProgram program) { - LOGGER.debug("Preprocessing InternalProgram!"); - InternalProgram retVal = program; - if (config.isEvaluateStratifiedPart()) { - AnalyzedProgram analyzed = new AnalyzedProgram(program.getRules(), program.getFacts()); - retVal = new StratifiedEvaluation().apply(analyzed); - } - return retVal; - } - - public InternalProgram performProgramPreprocessing(AnalyzedProgram program) { - LOGGER.debug("Preprocessing AnalyzedProgram!"); - InternalProgram retVal = program; - if (config.isEvaluateStratifiedPart()) { - retVal = new StratifiedEvaluation().apply(program); - } - return retVal; - } - - /** - * Convenience method - overloaded version of solve({@link InternalProgram}) for cases where details of the - * program analysis and normalization aren't of interest. - */ - public Stream solve(InputProgram program) { - return solve(program, InputConfig.DEFAULT_FILTER); - } - - /** - * Convenience method - overloaded version of solve({@link InternalProgram}, {@link Predicate}) for cases where - * details of the program analysis and normalization aren't of interest. - */ - public Stream solve(InputProgram program, java.util.function.Predicate filter) { - NormalProgram normalized = normalizeProgram(program); - return solve(normalized, filter); - } - - /** - * Convenience method - overloaded version of solve({@link InternalProgram}) for cases where details of the - * program analysis aren't of interest. - */ - public Stream solve(NormalProgram program, java.util.function.Predicate filter) { - InternalProgram preprocessed = performProgramPreprocessing(InternalProgram.fromNormalProgram(program)); - return solve(preprocessed, filter); - } - - /** - * Overloaded version of solve({@link InternalProgram}, {@link Predicate}) that uses a default filter (accept - * everything). - * - * @param program the program to solve - * @return a stream of answer sets - */ - public Stream solve(InternalProgram program) { - return solve(program, InputConfig.DEFAULT_FILTER); - } - - /** - * Solves the given program and filters answer sets based on the passed predicate. - * - * @param program an {@link InternalProgram} to solve - * @param filter {@link Predicate} filtering {@at.ac.tuwien.kr.alpha.common.Predicate}s in the returned answer sets - * @return a Stream of answer sets representing stable models of the given program - */ - public Stream solve(InternalProgram program, java.util.function.Predicate filter) { - Stream retVal = prepareSolverFor(program, filter).stream(); - return config.isSortAnswerSets() ? retVal.sorted() : retVal; - } - - /** - * Prepares a solver (and accompanying grounder) instance pre-loaded with the given program. Use this if the - * solver is needed after reading answer sets (e.g. for obtaining statistics). - * - * @param program the program to solve. - * @param filter a (java util) predicate that filters (asp-)predicates which should be contained in the answer - * set stream from the solver. - * @return a solver (and accompanying grounder) instance pre-loaded with the given program. - */ - public Solver prepareSolverFor(InternalProgram program, java.util.function.Predicate filter) { - String grounderName = config.getGrounderName(); - boolean doDebugChecks = config.isDebugInternalChecks(); - - GrounderHeuristicsConfiguration grounderHeuristicConfiguration = GrounderHeuristicsConfiguration - .getInstance(config.getGrounderToleranceConstraints(), config.getGrounderToleranceRules()); - grounderHeuristicConfiguration.setAccumulatorEnabled(config.isGrounderAccumulatorEnabled()); - - AtomStore atomStore = new AtomStoreImpl(); - Grounder grounder = GrounderFactory.getInstance(grounderName, program, atomStore, filter, grounderHeuristicConfiguration, doDebugChecks); - - return SolverFactory.getInstance(config, atomStore, grounder); - } - - public SystemConfig getConfig() { - return config; - } - - public void setConfig(SystemConfig config) { - this.config = config; - } - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSet.java b/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSet.java deleted file mode 100644 index 8fe890d89..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSet.java +++ /dev/null @@ -1,46 +0,0 @@ -package at.ac.tuwien.kr.alpha.common; - -import java.util.List; -import java.util.SortedSet; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.api.query.AnswerSetQuery; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; - -public interface AnswerSet extends Comparable { - SortedSet getPredicates(); - - SortedSet getPredicateInstances(Predicate predicate); - - boolean isEmpty(); - - @Override - default int compareTo(AnswerSet other) { - final SortedSet predicates = this.getPredicates(); - int result = Util.compareSortedSets(predicates, other.getPredicates()); - - if (result != 0) { - return result; - } - - for (Predicate predicate : predicates) { - result = Util.compareSortedSets(this.getPredicateInstances(predicate), other.getPredicateInstances(predicate)); - - if (result != 0) { - return result; - } - } - - return 0; - } - - /** - * Applies a given {@link AnswerSetQuery} to this AnswerSet. - * - * @param query the query to apply - * @return all atoms that are instances of the predicate specified by the query and meet the filters of the query - */ - default List query(AnswerSetQuery query) { - return query.applyTo(this); - } -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSetFormatter.java b/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSetFormatter.java deleted file mode 100644 index 8467cc19b..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/AnswerSetFormatter.java +++ /dev/null @@ -1,6 +0,0 @@ -package at.ac.tuwien.kr.alpha.common; - -@FunctionalInterface -public interface AnswerSetFormatter { - T format(AnswerSet answerSet); -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/ComparisonOperator.java b/src/main/java/at/ac/tuwien/kr/alpha/common/ComparisonOperator.java deleted file mode 100644 index 3aeefc182..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/ComparisonOperator.java +++ /dev/null @@ -1,39 +0,0 @@ -package at.ac.tuwien.kr.alpha.common; - -import static at.ac.tuwien.kr.alpha.Util.oops; - -public enum ComparisonOperator { - EQ("="), - NE("!="), - LT("<"), - GT(">"), - LE("<="), - GE(">="); - - private String asString; - - ComparisonOperator(String asString) { - this.asString = asString; - } - - @Override - public String toString() { - return asString; - } - - public ComparisonOperator getNegation() { - switch (this) { - case EQ: return NE; - case NE: return EQ; - case LT: return GE; - case GT: return LE; - case LE: return GT; - case GE: return LT; - } - throw oops("Unknown binary operator encountered, cannot negate it"); - } - - public Predicate predicate() { - return Predicate.getInstance(this.asString, 2); - } -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/FixedInterpretationLiteral.java b/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/FixedInterpretationLiteral.java deleted file mode 100644 index 835260b72..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/atoms/FixedInterpretationLiteral.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2017-2018, 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.common.atoms; - -import at.ac.tuwien.kr.alpha.grounder.Substitution; - -import java.util.List; - -/** - * Represents a literal whose ground truth value(s) are independent of the - * current assignment. - * Examples of atoms underlying such literals are builtin atoms and external - * atoms. - * Copyright (c) 2017-2018, the Alpha Team. - */ -public abstract class FixedInterpretationLiteral extends Literal { - - public FixedInterpretationLiteral(Atom atom, boolean positive) { - super(atom, positive); - } - - /** - * Creates a list of {@link Substitution}s based on the given partial - * substitution, such that - * this {@link FixedInterpretationLiteral} is true in every returned - * substitution. - * In cases where this is not possible (because of conflicting variable - * assignments in the partial substitution), getSatisfyingSubstitutions is - * required to return an empty list - * - * @param partialSubstitution a partial substitution that is required to bind - * all variables that are non-binding in this literal - * @return a list of substitutions, in each of which this literal is true, or an - * empty list if no such substitution exists - */ - public abstract List getSatisfyingSubstitutions(Substitution partialSubstitution); -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/program/NormalProgram.java b/src/main/java/at/ac/tuwien/kr/alpha/common/program/NormalProgram.java deleted file mode 100644 index 8a7f20122..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/program/NormalProgram.java +++ /dev/null @@ -1,30 +0,0 @@ -package at.ac.tuwien.kr.alpha.common.program; - -import java.util.ArrayList; -import java.util.List; - -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.grounder.parser.InlineDirectives; - -/** - * A program that only contains NormalRules. - * - * Copyright (c) 2019, the Alpha Team. - */ -public class NormalProgram extends AbstractProgram { - - public NormalProgram(List rules, List facts, InlineDirectives inlineDirectives) { - super(rules, facts, inlineDirectives); - } - - public static NormalProgram fromInputProgram(InputProgram inputProgram) { - List normalRules = new ArrayList<>(); - for (BasicRule r : inputProgram.getRules()) { - normalRules.add(NormalRule.fromBasicRule(r)); - } - return new NormalProgram(normalRules, inputProgram.getFacts(), inputProgram.getInlineDirectives()); - } - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/program/Programs.java b/src/main/java/at/ac/tuwien/kr/alpha/common/program/Programs.java deleted file mode 100644 index 1353864ef..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/program/Programs.java +++ /dev/null @@ -1,23 +0,0 @@ -package at.ac.tuwien.kr.alpha.common.program; - -import org.antlr.v4.runtime.CharStreams; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - -import at.ac.tuwien.kr.alpha.common.fixedinterpretations.PredicateInterpretation; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; - -public class Programs { - - private Programs() { - throw new AssertionError("This is a pure utility class and should therefore not be instantiated!"); - } - - public static InputProgram fromInputStream(InputStream is, Map externals) throws IOException { - ProgramParser parser = new ProgramParser(externals); - return parser.parse(CharStreams.fromStream(is)); - } - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/Head.java b/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/Head.java deleted file mode 100644 index 535466cb6..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/rule/head/Head.java +++ /dev/null @@ -1,19 +0,0 @@ -package at.ac.tuwien.kr.alpha.common.rule.head; - -/** - * Represents the head of a rule, i.e., either a choice or a disjunction of atoms, but not both. For normal rules the disjunction contains only one atom. - * - * Copyright (c) 2017-2019, the Alpha Team. - */ -public abstract class Head { - - @Override - public abstract String toString(); - - @Override - public abstract boolean equals(Object o); - - @Override - public abstract int hashCode(); - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/Terms.java b/src/main/java/at/ac/tuwien/kr/alpha/common/terms/Terms.java deleted file mode 100644 index 0e5c36745..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/Terms.java +++ /dev/null @@ -1,33 +0,0 @@ -package at.ac.tuwien.kr.alpha.common.terms; - -import java.util.ArrayList; -import java.util.List; - -/** - * Convenience methods for {@link Term}s. The methods provided here are an - * attempt to avoid repeating commonly used code snippets, like wrapping sets of - * values in {@link Term}s and creating lists of those terms, etc. - * - * Copyright (c) 2020, the Alpha Team. - */ -public final class Terms { - - /** - * Since this is purely a utility class, it may not be instantiated. - * - * @throws AssertionError if called - */ - private Terms() { - throw new AssertionError(Terms.class.getSimpleName() + " is a non-instantiable utility class!"); - } - - @SafeVarargs - public static > List> asTermList(T... values) { - List> retVal = new ArrayList<>(); - for (T value : values) { - retVal.add(ConstantTerm.getInstance(value)); - } - return retVal; - } - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/VariableTerm.java b/src/main/java/at/ac/tuwien/kr/alpha/common/terms/VariableTerm.java deleted file mode 100644 index 8396b4102..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/common/terms/VariableTerm.java +++ /dev/null @@ -1,108 +0,0 @@ -package at.ac.tuwien.kr.alpha.common.terms; - -import at.ac.tuwien.kr.alpha.common.Interner; -import at.ac.tuwien.kr.alpha.grounder.IntIdGenerator; -import at.ac.tuwien.kr.alpha.grounder.Substitution; - -import java.util.Collections; -import java.util.List; - -/** - * Copyright (c) 2016-2017, the Alpha Team. - */ -public class VariableTerm extends Term { - private static final Interner INTERNER = new Interner<>(); - - private static final String ANONYMOUS_VARIABLE_PREFIX = "_"; - private static final IntIdGenerator ANONYMOUS_VARIABLE_COUNTER = new IntIdGenerator(); - - private final String variableName; - - private VariableTerm(String variableName) { - this.variableName = variableName; - } - - public static VariableTerm getInstance(String variableName) { - return INTERNER.intern(new VariableTerm(variableName)); - } - - public static VariableTerm getAnonymousInstance() { - return getInstance(ANONYMOUS_VARIABLE_PREFIX + ANONYMOUS_VARIABLE_COUNTER.getNextId()); - } - - @Override - public boolean isGround() { - return false; - } - - @Override - public List getOccurringVariables() { - return Collections.singletonList(this); - } - - @Override - public Term substitute(Substitution substitution) { - Term groundTerm = substitution.eval(this); - if (groundTerm == null) { - // If variable is not substituted, keep term as is. - return this; - } - return groundTerm; - } - - @Override - public String toString() { - return variableName; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - VariableTerm that = (VariableTerm) o; - - return variableName.equals(that.variableName); - } - - @Override - public int hashCode() { - return variableName.hashCode(); - } - - @Override - public int compareTo(Term o) { - if (this == o) { - return 0; - } - - if (!(o instanceof VariableTerm)) { - return super.compareTo(o); - } - - VariableTerm other = (VariableTerm)o; - return variableName.compareTo(other.variableName); - } - - @Override - public Term renameVariables(String renamePrefix) { - return VariableTerm.getInstance(renamePrefix + variableName); - } - - @Override - public Term normalizeVariables(String renamePrefix, RenameCounter counter) { - VariableTerm renamedThis = counter.renamedVariables.get(this); - if (renamedThis != null) { - return renamedThis; - } else { - VariableTerm renamedVariable = VariableTerm.getInstance(renamePrefix + counter.counter++); - counter.renamedVariables.put(this, renamedVariable); - return renamedVariable; - } - } -} \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/EnumerationAtom.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/EnumerationAtom.java deleted file mode 100644 index 3ba9f5fb8..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/atoms/EnumerationAtom.java +++ /dev/null @@ -1,95 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.atoms; - -import static at.ac.tuwien.kr.alpha.Util.oops; - -import java.util.HashMap; -import java.util.List; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.Substitution; - -/** - * Represents a ground-instance enumeration atom of form: - * enum(enumId, groundTerm, sequenceNo). - * - * The semantics of this is: - * if enum(A,T1, N1) and enum(A,T2,N2) are both true and T1 != T2, then N1 != N2. - * Furthermore, If enum(A,T1,N1) is true with N1 > 0 then enum(A,T2,N1 - 1) is true for some T1 != T2 and - * both, T1 and T2, are ground instances the grounder encountered during the search so far. - * - * Copyright (c) 2017, the Alpha Team. - */ -public class EnumerationAtom extends BasicAtom { - public static final Predicate ENUMERATION_PREDICATE = Predicate.getInstance("_Enumeration", 3); - private static final HashMap> ENUMERATIONS = new HashMap<>(); - - public EnumerationAtom(List terms) { - super(ENUMERATION_PREDICATE, terms); - if (terms.size() != 3) { - throw new RuntimeException("EnumerationAtom must have arity three. Given terms are of wrong size: " + terms); - } - if (!(getTerms().get(2) instanceof VariableTerm)) { - throw new RuntimeException("Third parameter of EnumerationAtom must be a variable: " + terms); - } - } - - public static void resetEnumerations() { - ENUMERATIONS.clear(); - } - - private Integer getEnumerationIndex(Term identifier, Term enumerationTerm) { - ENUMERATIONS.putIfAbsent(identifier, new HashMap<>()); - HashMap enumeratedTerms = ENUMERATIONS.get(identifier); - Integer assignedInteger = enumeratedTerms.get(enumerationTerm); - if (assignedInteger == null) { - int enumerationIndex = enumeratedTerms.size() + 1; - enumeratedTerms.put(enumerationTerm, enumerationIndex); - return enumerationIndex; - } else { - return assignedInteger; - } - - } - - /** - * Based on a given substitution, substitutes the first two terms of this {@link EnumerationAtom} with the values from the substitution, - * and returns a new substitution with all mappings from the input substitution plus a binding for the third term of the enum atom to the - * integer index that is mapped to the first two terms in the internal ENUMERATIONS map. - * - * @param substitution an input substitution which must provide ground terms for the first two terms of the enumeration atom. - * @return a new substitution where the third term of the enumeration atom is bound to an integer. - */ - public Substitution addEnumerationIndexToSubstitution(Substitution substitution) { - Term idTerm = this.getTerms().get(0).substitute(substitution); - Term enumerationTerm = this.getTerms().get(1).substitute(substitution); - if (!enumerationTerm.isGround()) { - throw new RuntimeException("Enumeration term is not ground after substitution. Should not happen."); - } - Integer enumerationIndex = getEnumerationIndex(idTerm, enumerationTerm); - Substitution retVal = new Substitution(substitution); - retVal.put((VariableTerm) getTerms().get(2), ConstantTerm.getInstance(enumerationIndex)); - return retVal; - } - - @Override - public EnumerationAtom substitute(Substitution substitution) { - return new EnumerationAtom(super.substitute(substitution).getTerms()); - } - - @Override - public EnumerationLiteral toLiteral(boolean positive) { - if (!positive) { - throw oops("IntervalLiteral cannot be negated"); - } - return new EnumerationLiteral(this); - } - - @Override - public EnumerationLiteral toLiteral() { - return toLiteral(true); - } -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/bridges/Bridge.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/bridges/Bridge.java deleted file mode 100644 index 15e30600b..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/bridges/Bridge.java +++ /dev/null @@ -1,12 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.bridges; - -import at.ac.tuwien.kr.alpha.common.Assignment; -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.grounder.IntIdGenerator; - -import java.util.Collection; - -public interface Bridge { - Collection getRules(Assignment assignment, AtomStore atomStore, IntIdGenerator intIdGenerator); -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/rete/TupleIndex.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/rete/TupleIndex.java deleted file mode 100644 index 983f771ed..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/rete/TupleIndex.java +++ /dev/null @@ -1,7 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.rete; - -/** - * Copyright (c) 2016, the Alpha Team. - */ -public class TupleIndex { -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/rete/TupleStore.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/rete/TupleStore.java deleted file mode 100644 index 798ad4db0..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/rete/TupleStore.java +++ /dev/null @@ -1,10 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.rete; - -/** - * Copyright (c) 2016, the Alpha Team. - */ -public class TupleStore { - - int arity; - TupleIndex[] tupleIndex; -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ProgramTransformation.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ProgramTransformation.java deleted file mode 100644 index 6aa85027c..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/ProgramTransformation.java +++ /dev/null @@ -1,12 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation; - -import at.ac.tuwien.kr.alpha.common.program.AbstractProgram; - -/** - * Copyright (c) 2017-2019, the Alpha Team. - */ -public abstract class ProgramTransformation, O extends AbstractProgram> { - - public abstract O apply(I inputProgram); - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateOperatorNormalization.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateOperatorNormalization.java deleted file mode 100644 index 26c3f4531..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateOperatorNormalization.java +++ /dev/null @@ -1,123 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; - -import static at.ac.tuwien.kr.alpha.common.ComparisonOperator.EQ; -import static at.ac.tuwien.kr.alpha.common.ComparisonOperator.LE; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.ComparisonAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm; -import at.ac.tuwien.kr.alpha.common.terms.ArithmeticTerm.ArithmeticOperator; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; - -/** - * Transforms an {@link InputProgram} such that, for all aggregate (body-)literals, only the comparison operators "=" - * and "<=" are used. - * - * Rewriting of "#count" and "#sum" aggregates is done using the following equivalences: - *
      - *
    • X < #aggr{...} == XP <= #aggr{...}, XP = X + 1
    • - *
    • X != #aggr{...} == not X = #aggr{...}
    • - *
    • X > #aggr{...} == not X <= #aggr{...}
    • - *
    • X >= #aggr{...} == not XP <= #aggr{...}, XP = X + 1
    • - *
    • not X < #aggr{...} == not XP <= #aggr{...}, XP = X + 1
    • - *
    • not X != #aggr{...} == X = #aggr{...}
    • - *
    • not X > #aggr{...} == X <= #aggr{...}
    • - *
    • not X >= #aggr{...} == XP <= #aggr{...}, XP = X + 1
    • - *
    - * Operators for "#min" and "#max" aggregates are not rewritten. - * - * Note that input programs must only contain aggregate literals of form VAR OP #aggr{...}, i.e. with only - * a left term and operator. When preprocessing programs, apply this transformation AFTER - * {@link at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.AggregateLiteralSplitting}. - * - * Copyright (c) 2020-2021, the Alpha Team. - */ -public final class AggregateOperatorNormalization { - - private AggregateOperatorNormalization() { - throw new UnsupportedOperationException("Utility class - cannot instantiate!"); - } - - public static BasicRule normalize(BasicRule rule) { - List rewrittenBody = new ArrayList<>(); - for (Literal lit : rule.getBody()) { - rewrittenBody.addAll(rewriteLiteral(lit)); - } - return new BasicRule(rule.getHead(), rewrittenBody); - } - - private static List rewriteLiteral(Literal lit) { - if (lit instanceof AggregateLiteral) { - return rewriteAggregateOperator((AggregateLiteral) lit); - } else { - return Collections.singletonList(lit); - } - } - - private static List rewriteAggregateOperator(AggregateLiteral lit) { - AggregateAtom atom = lit.getAtom(); - if (lit.getAtom().getAggregatefunction() == AggregateFunctionSymbol.MIN || lit.getAtom().getAggregatefunction() == AggregateFunctionSymbol.MAX) { - // No operator normalization needed for #min/#max aggregates. - return Collections.singletonList(lit); - } - if (atom.getLowerBoundOperator() == EQ || atom.getLowerBoundOperator() == LE) { - // Nothing to do for operator "=" or "<=". - return Collections.singletonList(lit); - } else { - List retVal = new ArrayList<>(); - VariableTerm decrementedBound; - switch (atom.getLowerBoundOperator()) { - case LT: - decrementedBound = VariableTerm.getAnonymousInstance(); - retVal.add(createLowerBoundedAggregateLiteral(LE, decrementedBound, atom, !lit.isNegated())); - retVal.add(createPlusOneTerm(atom.getLowerBoundTerm(), decrementedBound)); - break; - case NE: - retVal.add(createLowerBoundedAggregateLiteral(EQ, atom.getLowerBoundTerm(), atom, lit.isNegated())); - break; - case GT: - retVal.add(createLowerBoundedAggregateLiteral(LE, atom.getLowerBoundTerm(), atom, lit.isNegated())); - break; - case GE: - decrementedBound = VariableTerm.getAnonymousInstance(); - retVal.add(createLowerBoundedAggregateLiteral(LE, decrementedBound, atom, lit.isNegated())); - retVal.add(createPlusOneTerm(atom.getLowerBoundTerm(), decrementedBound)); - break; - default: - throw new IllegalStateException("No operator rewriting logic available for literal: " + lit); - } - return retVal; - } - } - - private static AggregateLiteral createLowerBoundedAggregateLiteral(ComparisonOperator op, Term lowerBoundTerm, AggregateAtom aggregateAtom, boolean isNegated) { - return new AggregateLiteral(new AggregateAtom(op, lowerBoundTerm, aggregateAtom.getAggregatefunction(), - aggregateAtom.getAggregateElements()), isNegated); - } - - /** - * Creates a new {@link Literal} that assigns the given target variable to the given (integer) term plus one. - * - * @param term - * @param targetVariable - * @return - */ - private static Literal createPlusOneTerm(Term term, VariableTerm targetVariable) { - Term increment = ArithmeticTerm.getInstance(term, ArithmeticOperator.PLUS, ConstantTerm.getInstance(1)); - ComparisonAtom atom = new ComparisonAtom(targetVariable, increment, ComparisonOperator.EQ); - return atom.toLiteral(); - } - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingConfig.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingConfig.java deleted file mode 100644 index 71a4a5c06..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; - -public class AggregateRewritingConfig { - - public static final boolean DEFAULT_USE_SORTING_GRID = true; - public static final boolean DEFAULT_SUPPORT_NEGATIVE_INTEGERS = true; - - private boolean useSortingGridEncoding = DEFAULT_USE_SORTING_GRID; - private boolean supportNegativeValuesInSums = DEFAULT_SUPPORT_NEGATIVE_INTEGERS; - - public boolean isUseSortingGridEncoding() { - return this.useSortingGridEncoding; - } - - public boolean isSupportNegativeValuesInSums() { - return this.supportNegativeValuesInSums; - } - - public void setUseSortingGridEncoding(boolean useSortingGridEncoding) { - this.useSortingGridEncoding = useSortingGridEncoding; - } - - public void setSupportNegativeValuesInSums(boolean supportNegativeValuesInSums) { - this.supportNegativeValuesInSums = supportNegativeValuesInSums; - } - -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/SumEncoder.java b/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/SumEncoder.java deleted file mode 100644 index dbee809ba..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/encoders/SumEncoder.java +++ /dev/null @@ -1,56 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates.encoders; - -import org.stringtemplate.v4.ST; -import org.stringtemplate.v4.STGroup; - -import at.ac.tuwien.kr.alpha.Util; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateElement; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom.AggregateFunctionSymbol; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; - -/** - * Aggregate encoder handling sum aggregates. - * - * Copyright (c) 2020, the Alpha Team. - */ -public final class SumEncoder extends StringtemplateBasedAggregateEncoder { - - private static final STGroup AGGREGATE_ENCODINGS = Util.loadStringTemplateGroup( - SumEncoder.class.getResource("/stringtemplates/aggregate-encodings.stg")); - - private static final ST SUM_LE_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_le"); - private static final ST SUM_EQ_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_eq"); - - private static final ST NON_NEG_ELEMENTS_SUM_LE_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_le_no_negative_elements"); - private static final ST NON_NEG_ELEMENTS_SUM_EQ_TEMPLATE = AGGREGATE_ENCODINGS.getInstanceOf("sum_eq_no_negative_elements"); - - private SumEncoder(ComparisonOperator acceptedOperator, ST encodingTemplate) { - super(AggregateFunctionSymbol.SUM, acceptedOperator, encodingTemplate); - } - - public static SumEncoder buildSumLessOrEqualEncoder(boolean supportNegativeIntegers) { - return new SumEncoder(ComparisonOperator.LE, supportNegativeIntegers ? SUM_LE_TEMPLATE : NON_NEG_ELEMENTS_SUM_LE_TEMPLATE); - } - - public static SumEncoder buildSumEqualsEncoder(boolean supportNegativeIntegers) { - return new SumEncoder(ComparisonOperator.EQ, supportNegativeIntegers ? SUM_EQ_TEMPLATE : NON_NEG_ELEMENTS_SUM_EQ_TEMPLATE); - } - - /** - * In contrast to encoders for other aggregate functions, the "element tuple" atom for sum encodings is ternary - apart - * from the aggregate arguments and the variable tuple identifying the aggregated element, it also holds the value to - * add to the result sum as its third argument. - */ - @Override - protected Atom buildElementRuleHead(String aggregateId, AggregateElement element, Term aggregateArguments) { - Predicate headPredicate = Predicate.getInstance(this.getElementTuplePredicateSymbol(aggregateId), 3); - FunctionTerm elementTuple = FunctionTerm.getInstance(AbstractAggregateEncoder.ELEMENT_TUPLE_FUNCTION_SYMBOL, element.getElementTerms()); - return new BasicAtom(headPredicate, aggregateArguments, elementTuple, element.getElementTerms().get(0)); - } - -} \ No newline at end of file diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/Solver.java b/src/main/java/at/ac/tuwien/kr/alpha/solver/Solver.java deleted file mode 100644 index d6900d382..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/Solver.java +++ /dev/null @@ -1,27 +0,0 @@ -package at.ac.tuwien.kr.alpha.solver; - -import at.ac.tuwien.kr.alpha.common.AnswerSet; - -import java.util.List; -import java.util.Set; -import java.util.Spliterator; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -@FunctionalInterface -public interface Solver { - Spliterator spliterator(); - - default Stream stream() { - return StreamSupport.stream(spliterator(), false); - } - - default Set collectSet() { - return stream().collect(Collectors.toSet()); - } - - default List collectList() { - return stream().collect(Collectors.toList()); - } -} diff --git a/src/main/java/at/ac/tuwien/kr/alpha/solver/SolverMaintainingStatistics.java b/src/main/java/at/ac/tuwien/kr/alpha/solver/SolverMaintainingStatistics.java deleted file mode 100644 index 0c29abef7..000000000 --- a/src/main/java/at/ac/tuwien/kr/alpha/solver/SolverMaintainingStatistics.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2017-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 - * 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.solver; - -import java.io.PrintStream; - -public interface SolverMaintainingStatistics { - - int getNumberOfChoices(); - - int getNumberOfBacktracks(); - - int getNumberOfBacktracksWithinBackjumps(); - - int getNumberOfBackjumps(); - - int getNumberOfBacktracksDueToRemnantMBTs(); - - int getNumberOfDeletedNoGoods(); - - /** - * @return the number of times the solver had to backtrack after closing unassigned atoms - */ - int getNumberOfConflictsAfterClosing(); - - NoGoodCounter getNoGoodCounter(); - - default String getStatisticsString() { - return "g=" + getNumberOfChoices() + ", bt=" + getNumberOfBacktracks() + ", bj=" + getNumberOfBackjumps() + ", bt_within_bj=" - + getNumberOfBacktracksWithinBackjumps() + ", mbt=" + getNumberOfBacktracksDueToRemnantMBTs() + ", cac=" + getNumberOfConflictsAfterClosing() - + ", del_ng=" + getNumberOfDeletedNoGoods(); - } - - default String getStatisticsCSV() { - return String.format("%d,%d,%d,%d,%d,%d,%d", getNumberOfChoices(), getNumberOfBacktracks(), getNumberOfBackjumps(), getNumberOfBacktracksWithinBackjumps(), getNumberOfBacktracksDueToRemnantMBTs(), getNumberOfConflictsAfterClosing(), getNumberOfDeletedNoGoods()); - } - - default void printStatistics(PrintStream out) { - out.println(getStatisticsString()); - } - - default void printStatistics() { - printStatistics(System.out); - } -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/api/externals/stdlib/AspStandardLibraryTest.java b/src/test/java/at/ac/tuwien/kr/alpha/api/externals/stdlib/AspStandardLibraryTest.java deleted file mode 100644 index 498c61557..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/api/externals/stdlib/AspStandardLibraryTest.java +++ /dev/null @@ -1,180 +0,0 @@ -package at.ac.tuwien.kr.alpha.api.externals.stdlib; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.config.InputConfig; - -public class AspStandardLibraryTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(AspStandardLibrary.class); - - //@formatter:off - private static final String STRINGSTUFF_ASP = - "string(\"bla\")." - + "string(\"blubb\")." - + "string(\"foo\")." - + "string(\"bar\")." - + "{ strcat(S1, S2) } :- string(S1), string(S2)." - + "resultstring(SCAT) :- strcat(S1, S2), &stdlib_string_concat[S1, S2](SCAT)." - + ":- resultstring(S), &stdlib_string_length[S](LEN), LEN != 6." - + "containsFoo(S) :- resultstring(S), &stdlib_string_matches_regex[S, \".*foo.*\"]." - + ":- resultstring(S), not containsFoo(S)." - + "has_resultstring :- resultstring(_)." - + ":- not has_resultstring."; - - // same as stringstuff asp, but without the "containsFoo" intermediate predicate - private static final String NEGATED_EXTERNAL_ASP = - "string(\"bla\")." - + "string(\"blubb\")." - + "string(\"foo\")." - + "string(\"bar\")." - + "{ strcat(S1, S2) } :- string(S1), string(S2)." - + "resultstring(SCAT) :- strcat(S1, S2), &stdlib_string_concat[S1, S2](SCAT)." - + ":- resultstring(S), &stdlib_string_length[S](LEN), LEN != 6." - + ":- resultstring(S), not &stdlib_string_matches_regex[S, \".*foo.*\"]." - + "has_resultstring :- resultstring(_)." - + ":- not has_resultstring."; - //@formatter:on - - @Test - public void parseDateTime1() { - Set>> dtSubstitution = AspStandardLibrary.datetimeParse("20.05.2020 01:19:13", "dd.MM.yyyy HH:mm:ss"); - assertEquals(1, dtSubstitution.size()); - List> dtTerms = dtSubstitution.stream().findFirst().get(); - assertEquals(6, dtTerms.size()); - assertEquals(ConstantTerm.getInstance(2020), dtTerms.get(0)); - assertEquals(ConstantTerm.getInstance(5), dtTerms.get(1)); - assertEquals(ConstantTerm.getInstance(20), dtTerms.get(2)); - assertEquals(ConstantTerm.getInstance(1), dtTerms.get(3)); - assertEquals(ConstantTerm.getInstance(19), dtTerms.get(4)); - assertEquals(ConstantTerm.getInstance(13), dtTerms.get(5)); - } - - @Test - public void parseDateTime2() { - Set>> dtSubstitution = AspStandardLibrary.datetimeParse("07/2123/18 22/37/01", "MM/yyyy/dd HH/mm/ss"); - assertEquals(1, dtSubstitution.size()); - List> dtTerms = dtSubstitution.stream().findFirst().get(); - assertEquals(6, dtTerms.size()); - assertEquals(ConstantTerm.getInstance(2123), dtTerms.get(0)); - assertEquals(ConstantTerm.getInstance(7), dtTerms.get(1)); - assertEquals(ConstantTerm.getInstance(18), dtTerms.get(2)); - assertEquals(ConstantTerm.getInstance(22), dtTerms.get(3)); - assertEquals(ConstantTerm.getInstance(37), dtTerms.get(4)); - assertEquals(ConstantTerm.getInstance(1), dtTerms.get(5)); - } - - @Test - public void parseDateTime3() { - Set>> dtSubstitution = AspStandardLibrary.datetimeParse("\"03,12,2019\", \"11:00:00\"", - "\"dd,MM,yyyy\", \"HH:mm:ss\""); - assertEquals(1, dtSubstitution.size()); - List> dtTerms = dtSubstitution.stream().findFirst().get(); - assertEquals(6, dtTerms.size()); - assertEquals(ConstantTerm.getInstance(2019), dtTerms.get(0)); - assertEquals(ConstantTerm.getInstance(12), dtTerms.get(1)); - assertEquals(ConstantTerm.getInstance(3), dtTerms.get(2)); - assertEquals(ConstantTerm.getInstance(11), dtTerms.get(3)); - assertEquals(ConstantTerm.getInstance(0), dtTerms.get(4)); - assertEquals(ConstantTerm.getInstance(0), dtTerms.get(5)); - } - - @Test - public void datetimeBefore() { - assertTrue(AspStandardLibrary.datetimeIsBefore(1990, 2, 14, 15, 16, 17, 1990, 3, 1, 0, 59, 1)); - assertFalse(AspStandardLibrary.datetimeIsBefore(2015, 5, 13, 12, 1, 33, 2003, 1, 1, 0, 0, 1)); - assertFalse(AspStandardLibrary.datetimeIsBefore(2022, 2, 22, 22, 22, 22, 2022, 2, 22, 22, 22, 22)); - } - - @Test - public void datetimeEqual() { - assertTrue(AspStandardLibrary.datetimeIsEqual(1990, 2, 14, 15, 16, 17, 1990, 2, 14, 15, 16, 17)); - assertFalse(AspStandardLibrary.datetimeIsEqual(2015, 5, 13, 12, 1, 33, 2003, 1, 1, 0, 0, 1)); - } - - @Test - public void datetimeBeforeOrEqual() { - assertTrue(AspStandardLibrary.datetimeIsBeforeOrEqual(1990, 2, 14, 15, 16, 17, 1990, 3, 1, 0, 59, 1)); - assertFalse(AspStandardLibrary.datetimeIsBeforeOrEqual(2015, 5, 13, 12, 1, 33, 2003, 1, 1, 0, 0, 1)); - assertTrue(AspStandardLibrary.datetimeIsBeforeOrEqual(2022, 2, 22, 22, 22, 22, 2022, 2, 22, 22, 22, 22)); - - } - - @Test - public void matchesRegex() { - assertTrue(AspStandardLibrary.stringMatchesRegex("Blaaaaa Blubbb!!", "Bla+ Blub+!!")); - assertFalse(AspStandardLibrary.stringMatchesRegex("Foobar", "Bla+ Blub+!!")); - } - - @Test - public void stringLength() { - Set>> result = AspStandardLibrary.stringLength("A String of length 21"); - assertEquals(1, result.size()); - List> lengthTerms = result.stream().findFirst().get(); - assertEquals(1, lengthTerms.size()); - ConstantTerm lenTerm = lengthTerms.get(0); - assertEquals(ConstantTerm.getInstance(21), lenTerm); - } - - @Test - public void stringConcat() { - Set>> result = AspStandardLibrary.stringConcat("Foo", "bar"); - assertEquals(1, result.size()); - List> concatTerms = result.stream().findFirst().get(); - assertEquals(1, concatTerms.size()); - ConstantTerm concat = concatTerms.get(0); - assertEquals(ConstantTerm.getInstance("Foobar"), concat); - } - - @Test - @SuppressWarnings("unchecked") - public void programWithStringStuff() throws IOException { - Alpha alpha = new Alpha(); - InputProgram prog = alpha.readProgram(InputConfig.forString(STRINGSTUFF_ASP)); - Set answerSets = alpha.solve(prog).collect(Collectors.toSet()); - // Verify every result string has length 6 and contains "foo" - for (AnswerSet as : answerSets) { - for (Atom atom : as.getPredicateInstances(Predicate.getInstance("resultstring", 1))) { - String resultstring = ((ConstantTerm) atom.getTerms().get(0)).getObject(); - assertEquals(6, resultstring.length()); - assertTrue(resultstring.contains("foo")); - } - } - } - - @Test - @SuppressWarnings("unchecked") - public void negatedExternal() throws IOException { - Alpha alpha = new Alpha(); - InputProgram prog = alpha.readProgram(InputConfig.forString(NEGATED_EXTERNAL_ASP)); - Set answerSets = alpha.solve(prog).collect(Collectors.toSet()); - assertEquals(31, answerSets.size()); - // Verify every result string has length 6 and contains "foo" - for (AnswerSet as : answerSets) { - for (Atom atom : as.getPredicateInstances(Predicate.getInstance("resultstring", 1))) { - String resultstring = ((ConstantTerm) atom.getTerms().get(0)).getObject(); - LOGGER.debug("ResultString is {}", resultstring); - assertEquals(6, resultstring.length()); - assertTrue(resultstring.contains("foo")); - } - } - } - -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/AtomStoreTest.java b/src/test/java/at/ac/tuwien/kr/alpha/common/AtomStoreTest.java deleted file mode 100644 index 17bce93b8..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/AtomStoreTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package at.ac.tuwien.kr.alpha.common; - -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; - -/** - * Copyright (c) 2018, the Alpha Team. - */ -public class AtomStoreTest { - - public static void fillAtomStore(AtomStore atomStore, int numberOfAtomsToFill) { - Predicate predA = Predicate.getInstance("a", 1); - for (int i = 0; i < numberOfAtomsToFill; i++) { - atomStore.putIfAbsent(new BasicAtom(predA, ConstantTerm.getInstance(i))); - } - } -} \ No newline at end of file diff --git a/src/test/java/at/ac/tuwien/kr/alpha/common/RuleTest.java b/src/test/java/at/ac/tuwien/kr/alpha/common/RuleTest.java deleted file mode 100644 index 4eaf13bab..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/common/RuleTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package at.ac.tuwien.kr.alpha.common; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; - -/** - * Copyright (c) 2018, the Alpha Team. - */ -public class RuleTest { - - private final ProgramParser parser = new ProgramParser(); - - @Test - public void renameVariables() { - String originalRule = "p(X,Y) :- a, f(Z) = 1, q(X,g(Y),Z), dom(A)."; - BasicRule rule = parser.parse(originalRule).getRules().get(0); - InternalRule normalRule = InternalRule.fromNormalRule(NormalRule.fromBasicRule(rule)); - InternalRule renamedRule = normalRule.renameVariables("_13"); - BasicRule expectedRenamedRule = parser.parse("p(X_13, Y_13) :- a, f(Z_13) = 1, q(X_13, g(Y_13), Z_13), dom(A_13).").getRules().get(0); - InternalRule expectedRenamedNormalRule = InternalRule.fromNormalRule(NormalRule.fromBasicRule(expectedRenamedRule)); - assertEquals(expectedRenamedNormalRule.toString(), renamedRule.toString()); - } - - @Test - public void testRulesEqual() { - InputProgram p1 = parser.parse("p(X, Y) :- bla(X), blub(Y), foo(X, Y), not bar(X)."); - BasicRule r1 = p1.getRules().get(0); - InputProgram p2 = parser.parse("p(X, Y) :- bla(X), blub(Y), foo(X, Y), not bar(X)."); - BasicRule r2 = p2.getRules().get(0); - InputProgram p3 = parser.parse("p(X, Y) :- bla(X), blub(X), foo(X, X), not bar(X)."); - BasicRule r3 = p3.getRules().get(0); - assertTrue(r1.equals(r2)); - assertTrue(r2.equals(r1)); - assertTrue(r1.hashCode() == r2.hashCode()); - assertFalse(r1.equals(r3)); - assertFalse(r3.equals(r1)); - assertTrue(r1.hashCode() != r3.hashCode()); - assertFalse(r2.equals(r3)); - assertFalse(r3.equals(r2)); - assertTrue(r2.hashCode() != r3.hashCode()); - } - -} \ No newline at end of file diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/SubstitutionTest.java b/src/test/java/at/ac/tuwien/kr/alpha/grounder/SubstitutionTest.java deleted file mode 100644 index dc9458367..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/SubstitutionTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright (c) 2016-2018, 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.grounder; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Test; - -import java.util.Arrays; - -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicLiteral; -import at.ac.tuwien.kr.alpha.common.atoms.Literal; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.NormalRule; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.FunctionTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.common.terms.VariableTerm; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.test.util.SubstitutionTestUtil; - - -public class SubstitutionTest { - private static final ProgramParser PARSER = new ProgramParser(); - - private static final ConstantTerm A = ConstantTerm.getSymbolicInstance("a"); - private static final ConstantTerm B = ConstantTerm.getSymbolicInstance("b"); - private static final ConstantTerm C = ConstantTerm.getSymbolicInstance("c"); - - private static final VariableTerm X = VariableTerm.getInstance("X"); - private static final VariableTerm Y = VariableTerm.getInstance("Y"); - private static final BasicAtom PX = new BasicAtom(Predicate.getInstance("p", 1), X); - private static final BasicAtom PY = new BasicAtom(Predicate.getInstance("p", 1), Y); - private static final Instance PA = new Instance(A); - private static final Instance PB = new Instance(B); - - @Test - public void putSimpleBinding() { - Substitution substitution = new Substitution(); - substitution.put(Y, A); - assertEquals(A, substitution.eval(Y)); - } - - @Test - public void specializeTermsSimpleBinding() { - Substitution substitution = Substitution.specializeSubstitution(PY, PA, Substitution.EMPTY_SUBSTITUTION); - assertEquals(A, substitution.eval(Y)); - } - - @Test - public void specializeTermsFunctionTermBinding() { - Substitution substitution = new Substitution(); - substitution.put(Y, A); - - FunctionTerm groundFunctionTerm = FunctionTerm.getInstance("f", B, C); - Instance qfBC = new Instance(groundFunctionTerm); - Term nongroundFunctionTerm = FunctionTerm.getInstance("f", B, X); - BasicAtom qfBX = new BasicAtom(Predicate.getInstance("q", 1), nongroundFunctionTerm); - - Substitution substitution1 = Substitution.specializeSubstitution(qfBX, qfBC, substitution); - - assertEquals(C, substitution1.eval(X)); - assertEquals(A, substitution1.eval(Y)); - } - - @Test - public void substitutePositiveBasicAtom() { - substituteBasicAtomLiteral(false); - } - - @Test - public void substituteNegativeBasicAtom() { - substituteBasicAtomLiteral(true); - } - - @Test - public void groundAndPrintRule() { - BasicRule rule = PARSER.parse("x :- p(X,Y), not q(X,Y).").getRules().get(0); - InternalRule nonGroundRule = InternalRule.fromNormalRule(NormalRule.fromBasicRule(rule)); - Substitution substitution1 = Substitution.specializeSubstitution(PX, PA, Substitution.EMPTY_SUBSTITUTION); - Substitution substitution2 = Substitution.specializeSubstitution(PY, PB, substitution1); - String printedString = SubstitutionTestUtil.groundAndPrintRule(nonGroundRule, substitution2); - assertEquals("x :- p(a, b), not q(a, b).", printedString); - } - - @Test - public void specializeBasicAtom() { - Predicate p = Predicate.getInstance("p", 2); - BasicAtom atom = new BasicAtom(p, Arrays.asList(X, Y)); - Instance instance = new Instance(A, B); - Substitution substitution = Substitution.specializeSubstitution(atom, instance, Substitution.EMPTY_SUBSTITUTION); - BasicAtom substituted = atom.substitute(substitution); - assertEquals(p, substituted.getPredicate()); - assertEquals(A, substituted.getTerms().get(0)); - assertEquals(B, substituted.getTerms().get(1)); - } - - private void substituteBasicAtomLiteral(boolean negated) { - Predicate p = Predicate.getInstance("p", 2); - BasicAtom atom = new BasicAtom(p, Arrays.asList(X, Y)); - Literal literal = new BasicLiteral(atom, !negated); - Substitution substitution = new Substitution(); - substitution.put(X, A); - substitution.put(Y, B); - literal = literal.substitute(substitution); - assertEquals(p, literal.getPredicate()); - assertEquals(A, literal.getTerms().get(0)); - assertEquals(B, literal.getTerms().get(1)); - assertEquals(negated, literal.isNegated()); - } - - @Test - public void groundLiteralToString_PositiveBasicAtom() { - groundLiteralToString(false); - } - - @Test - public void groundLiteralToString_NegativeBasicAtom() { - groundLiteralToString(true); - } - - private void groundLiteralToString(boolean negated) { - Predicate p = Predicate.getInstance("p", 2); - BasicAtom atom = new BasicAtom(p, Arrays.asList(X, Y)); - Substitution substitution1 = Substitution.specializeSubstitution(PX, PA, Substitution.EMPTY_SUBSTITUTION); - Substitution substitution = Substitution.specializeSubstitution(PY, PB, substitution1); - String printedString = SubstitutionTestUtil.groundLiteralToString(atom.toLiteral(!negated), substitution, true); - assertEquals((negated ? "not " : "") + "p(a, b)", printedString); - } - - @Test - public void substitutionFromString() { - BasicRule rule = PARSER.parse("x :- p(X,Y), not q(X,Y).").getRules().get(0); - InternalRule nonGroundRule = InternalRule.fromNormalRule(NormalRule.fromBasicRule(rule)); - Substitution substitution1 = Substitution.specializeSubstitution(PX, PA, Substitution.EMPTY_SUBSTITUTION); - Substitution substitution = Substitution.specializeSubstitution(PY, PB, substitution1); - RuleAtom ruleAtom = new RuleAtom(nonGroundRule, substitution); - String substitutionString = (String) ((ConstantTerm) ruleAtom.getTerms().get(1)).getObject(); - Substitution fromString = Substitution.fromString(substitutionString); - assertEquals(substitution, fromString); - } -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingTest.java b/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingTest.java deleted file mode 100644 index 0bb236b7a..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/grounder/transformation/aggregates/AggregateRewritingTest.java +++ /dev/null @@ -1,274 +0,0 @@ -package at.ac.tuwien.kr.alpha.grounder.transformation.aggregates; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.stream.Collectors; - -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.NormalProgram; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; - -public class AggregateRewritingTest { - - //@formatter:off - // Smoke-test case for "X <= #count{...}" aggregate - private static final String CNT_LE1_ASP = - "thing(75..76)." - + "candidate(2..4)." - + "cnt_le(N) :- N <= #count{X : thing(X)}, candidate(N)."; - // Smoke-test case for "X = #count{...}" aggregate - private static final String CNT_EQ1_ASP = - "thing(4..6)." - + "cnt_things(N) :- N = #count{X : thing(X)}."; - // Smoke-test case for non-binding min aggregate - private static final String MIN_GT1_ASP = - "thing(4). thing(7). thing(13). thing(3). " - + "acceptable(8). acceptable(10). acceptable(5). " - + "greater_min_acceptable(T) :- thing(T), T > #min{ A : acceptable(A) }."; - // Smoke-test case for "X = #sum{...}" aggregate - private static final String SUM_EQ1_ASP = - "thing(2). thing(4). thing(6)." - + "sum_things(S) :- S = #sum{K : thing(K)}."; - // Smoke-test case for "X = #sum{...}" aggregate - private static final String SUM_LE1_ASP = - "thing(2). thing(4). thing(6). bound(11)." - + "bound_le_sum(B) :- B <= #sum{K : thing(K)}, bound(B)."; - - // Basic ASP representation of a triangular undirected graph, used across multiple test cases - private static final String TEST_GRAPH_ASP = - "graph(g1)." - + "graph_undirected(g1)." - + "graph_vertex(g1, 1)." - + "graph_vertex(g1, 2)." - + "graph_vertex(g1 ,3)." - + "graph_edge(g1, e(1, 2))." - + "graph_edge(g1, e(2, 3))." - + "graph_edge(g1, e(3, 1))." - + "graph_directed(G) :- graph(G), not graph_undirected(G)." - + "err_directedness(G) :- graph(G), graph_directed(G), graph_undirected(G)." - + "err_directedness(G) :- graph(G), not graph_directed(G), not graph_undirected(G)." - + ":- err_directedness(_)." - + "err_undirected_edges(G, V1, V2) :- graph_edge(G, e(V1, V2)), graph_edge(G, e(V2, V1))." - + ":- err_undirected_edges(_, _, _)."; - private static final String VERTEX_DEGREE_ASP = TEST_GRAPH_ASP - + "graph_vertex_degree(G, V, D) :-" - + " graph(G)," - + " graph_vertex(G, V)," - + " D = #count{ VN : graph_edge(G, e(V, VN)); VN : graph_edge(G, e(VN, V)) }."; - private static final String NUM_MAX_DEGREE_VERTICES_ASP = VERTEX_DEGREE_ASP - + "graph_max_degree_vertices(G, DMAX, N) :-" - + " graph(G)," - + " DMAX = #max{ DV : graph_vertex_degree(G, V, DV)}," - + " N = #count{ V : graph_vertex_degree(G, V, DMAX)}."; - private static final String COMPLEX_EQUALITY_WITH_GLOBALS = - "p(1..10)." - + "q :- X = #count { Y : p( Y ) }, X = #count { Z : p( Z ) }," - + " Y = #count { X : p( X ) }, 1 <= #count { X : p( X ) }, Z = #max { W : p( W ) }."; - //@formatter:on - - @Test - public void countLeSortingGridSimple() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(CNT_LE1_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate thing = Predicate.getInstance("thing", 1); - Predicate candidate = Predicate.getInstance("candidate", 1); - Predicate cntLe = Predicate.getInstance("cnt_le", 1); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(75)))); - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(76)))); - - assertTrue(answerSet.getPredicateInstances(candidate).contains(new BasicAtom(candidate, ConstantTerm.getInstance(2)))); - assertTrue(answerSet.getPredicateInstances(candidate).contains(new BasicAtom(candidate, ConstantTerm.getInstance(3)))); - assertTrue(answerSet.getPredicateInstances(candidate).contains(new BasicAtom(candidate, ConstantTerm.getInstance(4)))); - - assertTrue(answerSet.getPredicates().contains(cntLe)); - assertTrue(answerSet.getPredicateInstances(cntLe).contains(new BasicAtom(cntLe, ConstantTerm.getInstance(2)))); - } - - @Test - public void countEqSimple() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(CNT_EQ1_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate thing = Predicate.getInstance("thing", 1); - Predicate cntThings = Predicate.getInstance("cnt_things", 1); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(4)))); - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(5)))); - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(6)))); - - assertTrue(answerSet.getPredicates().contains(cntThings)); - assertTrue(answerSet.getPredicateInstances(cntThings).contains(new BasicAtom(cntThings, ConstantTerm.getInstance(3)))); - } - - @Test - public void countLeCountingGridSimple() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - alpha.getConfig().getAggregateRewritingConfig().setUseSortingGridEncoding(false); - InputProgram input = alpha.readProgramString(CNT_LE1_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate thing = Predicate.getInstance("thing", 1); - Predicate candidate = Predicate.getInstance("candidate", 1); - Predicate cntLe = Predicate.getInstance("cnt_le", 1); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(75)))); - assertTrue(answerSet.getPredicateInstances(thing).contains(new BasicAtom(thing, ConstantTerm.getInstance(76)))); - - assertTrue(answerSet.getPredicateInstances(candidate).contains(new BasicAtom(candidate, ConstantTerm.getInstance(2)))); - assertTrue(answerSet.getPredicateInstances(candidate).contains(new BasicAtom(candidate, ConstantTerm.getInstance(3)))); - assertTrue(answerSet.getPredicateInstances(candidate).contains(new BasicAtom(candidate, ConstantTerm.getInstance(4)))); - - assertTrue(answerSet.getPredicates().contains(cntLe)); - assertTrue(answerSet.getPredicateInstances(cntLe).contains(new BasicAtom(cntLe, ConstantTerm.getInstance(2)))); - } - - @Test - public void countEqGlobalVars() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(VERTEX_DEGREE_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate vertexDegree = Predicate.getInstance("graph_vertex_degree", 3); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicates().contains(vertexDegree)); - assertTrue(answerSet.getPredicateInstances(vertexDegree) - .contains(new BasicAtom(vertexDegree, ConstantTerm.getSymbolicInstance("g1"), ConstantTerm.getInstance(1), ConstantTerm.getInstance(2)))); - assertTrue(answerSet.getPredicateInstances(vertexDegree) - .contains(new BasicAtom(vertexDegree, ConstantTerm.getSymbolicInstance("g1"), ConstantTerm.getInstance(2), ConstantTerm.getInstance(2)))); - assertTrue(answerSet.getPredicateInstances(vertexDegree) - .contains(new BasicAtom(vertexDegree, ConstantTerm.getSymbolicInstance("g1"), ConstantTerm.getInstance(3), ConstantTerm.getInstance(2)))); - } - - @Test - // Test "count eq" and "max eq" together with global vars - public void graphVerticesOfMaxDegree() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(NUM_MAX_DEGREE_VERTICES_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate maxDegreeVertices = Predicate.getInstance("graph_max_degree_vertices", 3); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicates().contains(maxDegreeVertices)); - assertTrue(answerSet.getPredicateInstances(maxDegreeVertices) - .contains(new BasicAtom(maxDegreeVertices, ConstantTerm.getSymbolicInstance("g1"), ConstantTerm.getInstance(2), ConstantTerm.getInstance(3)))); - } - - @Test - public void greaterMin() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(MIN_GT1_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate greaterMin = Predicate.getInstance("greater_min_acceptable", 1); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicates().contains(greaterMin)); - assertTrue(answerSet.getPredicateInstances(greaterMin).contains(new BasicAtom(greaterMin, ConstantTerm.getInstance(7)))); - assertTrue(answerSet.getPredicateInstances(greaterMin).contains(new BasicAtom(greaterMin, ConstantTerm.getInstance(13)))); - } - - @Test - public void sumEquals1() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(SUM_EQ1_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate sumThings = Predicate.getInstance("sum_things", 1); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicates().contains(sumThings)); - assertEquals(1, answerSet.getPredicateInstances(sumThings).size()); - assertTrue(answerSet.getPredicateInstances(sumThings).contains(new BasicAtom(sumThings, ConstantTerm.getInstance(12)))); - } - - @Test - public void sumLessOrEqual1() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(SUM_LE1_ASP); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate boundLe = Predicate.getInstance("bound_le_sum", 1); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicates().contains(boundLe)); - assertTrue(answerSet.getPredicateInstances(boundLe).contains(new BasicAtom(boundLe, ConstantTerm.getInstance(11)))); - } - - @Test - @Disabled("Open issue, as dependency analysis includes cyclic output-dependency, which it should not.") - public void setComplexEqualityWithGlobals() { - Alpha alpha = new Alpha(); - alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram input = alpha.readProgramString(COMPLEX_EQUALITY_WITH_GLOBALS); - NormalProgram normalized = alpha.normalizeProgram(input); - // System.out.println(normalized); - List answerSets = alpha.solve(normalized, (p) -> true).collect(Collectors.toList()); - assertEquals(1, answerSets.size()); - AnswerSet answerSet = answerSets.get(0); - Predicate q = Predicate.getInstance("q", 0); - - // System.out.println(new SimpleAnswerSetFormatter("\n").format(answerSet)); - - assertTrue(answerSet.getPredicates().contains(q)); - assertTrue(answerSet.getPredicateInstances(q).contains(new BasicAtom(q))); - } - -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/AtomCounterTests.java b/src/test/java/at/ac/tuwien/kr/alpha/solver/AtomCounterTests.java deleted file mode 100644 index 62d16b4a9..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/AtomCounterTests.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * 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 - * 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.solver; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import at.ac.tuwien.kr.alpha.common.AtomStore; -import at.ac.tuwien.kr.alpha.common.AtomStoreImpl; -import at.ac.tuwien.kr.alpha.common.ComparisonOperator; -import at.ac.tuwien.kr.alpha.common.Predicate; -import at.ac.tuwien.kr.alpha.common.atoms.AggregateAtom; -import at.ac.tuwien.kr.alpha.common.atoms.Atom; -import at.ac.tuwien.kr.alpha.common.atoms.BasicAtom; -import at.ac.tuwien.kr.alpha.common.rule.InternalRule; -import at.ac.tuwien.kr.alpha.common.rule.head.NormalHead; -import at.ac.tuwien.kr.alpha.common.terms.ConstantTerm; -import at.ac.tuwien.kr.alpha.common.terms.Term; -import at.ac.tuwien.kr.alpha.grounder.Substitution; -import at.ac.tuwien.kr.alpha.grounder.atoms.ChoiceAtom; -import at.ac.tuwien.kr.alpha.grounder.atoms.RuleAtom; - -public class AtomCounterTests { - - private AtomStore atomStore; - - @BeforeEach - public void setUp() { - this.atomStore = new AtomStoreImpl(); - } - - @Test - public void testGetNumberOfAtoms() { - final AtomCounter atomCounter = atomStore.getAtomCounter(); - - expectGetNumberOfAtoms(atomCounter, BasicAtom.class, 0); - expectGetNumberOfAtoms(atomCounter, AggregateAtom.class, 0); - expectGetNumberOfAtoms(atomCounter, ChoiceAtom.class, 0); - expectGetNumberOfAtoms(atomCounter, RuleAtom.class, 0); - - createBasicAtom1(); - createBasicAtom2(); - createAggregateAtom(); - createChoiceAtom(); - createRuleAtom(); - - expectGetNumberOfAtoms(atomCounter, BasicAtom.class, 2); - expectGetNumberOfAtoms(atomCounter, AggregateAtom.class, 1); - expectGetNumberOfAtoms(atomCounter, ChoiceAtom.class, 1); - expectGetNumberOfAtoms(atomCounter, RuleAtom.class, 1); - } - - @Test - public void testGetStatsByType() { - final AtomCounter atomCounter = atomStore.getAtomCounter(); - - createBasicAtom1(); - createBasicAtom2(); - createAggregateAtom(); - createChoiceAtom(); - createRuleAtom(); - - expectGetStatsByType(atomCounter, BasicAtom.class, 2); - expectGetStatsByType(atomCounter, AggregateAtom.class, 1); - expectGetStatsByType(atomCounter, ChoiceAtom.class, 1); - expectGetStatsByType(atomCounter, RuleAtom.class, 1); - } - - private void createBasicAtom1() { - atomStore.putIfAbsent(new BasicAtom(Predicate.getInstance("p", 0))); - } - - private void createBasicAtom2() { - atomStore.putIfAbsent(new BasicAtom(Predicate.getInstance("q", 1), ConstantTerm.getInstance(1))); - } - - private void createAggregateAtom() { - final ConstantTerm c1 = ConstantTerm.getInstance(1); - final ConstantTerm c2 = ConstantTerm.getInstance(2); - final ConstantTerm c3 = ConstantTerm.getInstance(3); - List basicTerms = Arrays.asList(c1, c2, c3); - AggregateAtom.AggregateElement aggregateElement = new AggregateAtom.AggregateElement(basicTerms, Collections.singletonList(new BasicAtom(Predicate.getInstance("p", 3), c1, c2, c3).toLiteral())); - atomStore.putIfAbsent(new AggregateAtom(ComparisonOperator.LE, c1, null, null, AggregateAtom.AggregateFunctionSymbol.COUNT, Collections.singletonList(aggregateElement))); - } - - private void createChoiceAtom() { - atomStore.putIfAbsent(ChoiceAtom.on(1)); - } - - private void createRuleAtom() { - Atom atomAA = new BasicAtom(Predicate.getInstance("aa", 0)); - InternalRule ruleAA = new InternalRule(new NormalHead(atomAA), Collections.singletonList(new BasicAtom(Predicate.getInstance("bb", 0)).toLiteral(false))); - atomStore.putIfAbsent(new RuleAtom(ruleAA, new Substitution())); - } - - private void expectGetNumberOfAtoms(AtomCounter atomCounter, Class classOfAtoms, int expectedNumber) { - assertEquals(expectedNumber, atomCounter.getNumberOfAtoms(classOfAtoms), "Unexpected number of " + classOfAtoms.getSimpleName() + "s"); - } - - private void expectGetStatsByType(AtomCounter atomCounter, Class classOfAtoms, int expectedNumber) { - assertTrue(atomCounter.getStatsByType().contains(classOfAtoms.getSimpleName() + ": " + expectedNumber), "Expected number of " + classOfAtoms.getSimpleName() + "s not contained in stats string"); - } - -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/DefaultSolverTest.java b/src/test/java/at/ac/tuwien/kr/alpha/solver/DefaultSolverTest.java deleted file mode 100644 index 332bc0641..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/DefaultSolverTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package at.ac.tuwien.kr.alpha.solver; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Optional; - -import org.antlr.v4.runtime.CharStreams; -import org.junit.jupiter.api.Test; - -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.config.SystemConfig; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; -import at.ac.tuwien.kr.alpha.solver.heuristics.BranchingHeuristicFactory; - -public class DefaultSolverTest { - - // Detailed reproduction test-case for github issue #239. - @Test - public void testLearnedUnaryNoGoodCausingOutOfOrderLiteralsConflict() throws IOException { - final ProgramParser parser = new ProgramParser(); - InputProgram.Builder bld = InputProgram.builder(); - bld.accumulate(parser.parse(CharStreams.fromPath(Paths.get("src", "test", "resources", "HanoiTower_Alpha.asp")))); - bld.accumulate(parser.parse(CharStreams.fromPath(Paths.get("src", "test", "resources", "HanoiTower_instances", "simple.asp")))); - InputProgram parsedProgram = bld.build(); - - SystemConfig config = new SystemConfig(); - config.setSolverName("default"); - config.setNogoodStoreName("alpharoaming"); - config.setSeed(0); - config.setBranchingHeuristic(BranchingHeuristicFactory.Heuristic.valueOf("VSIDS")); - config.setDebugInternalChecks(true); - config.setDisableJustificationSearch(false); - config.setEvaluateStratifiedPart(false); - config.setReplayChoices(Arrays.asList(21, 26, 36, 56, 91, 96, 285, 166, 101, 290, 106, 451, 445, 439, 448, - 433, 427, 442, 421, 415, 436, 409, 430, 397, 391, 424, 385, 379, - 418, 373, 412, 406, 394, 388, 382, 245, 232, 208 - )); - Alpha alpha = new Alpha(config); - Optional answerSet = alpha.solve(parsedProgram).findFirst(); - assertTrue(answerSet.isPresent()); - } - -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/solver/HanoiTowerDetailedTest.java b/src/test/java/at/ac/tuwien/kr/alpha/solver/HanoiTowerDetailedTest.java deleted file mode 100644 index fd8906e8c..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/solver/HanoiTowerDetailedTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package at.ac.tuwien.kr.alpha.solver; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Optional; - -import org.antlr.v4.runtime.CharStreams; -import org.junit.jupiter.api.Test; - -import at.ac.tuwien.kr.alpha.api.Alpha; -import at.ac.tuwien.kr.alpha.common.AnswerSet; -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.program.InternalProgram; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; - -/** - * A more fine-grained test, mostly intended for debugging purposes, of the "simple" instance of the Hanoi Tower - * problem. - * - * Copyright (c) 2020, the Alpha Team. - */ -public class HanoiTowerDetailedTest { - - private static final String HANOI_TOWER_SRC = "/HanoiTower_Alpha.asp"; - private static final String SIMPLE_INSTANCE = "/HanoiTower_instances/simple.asp"; - - @Test - public void testHanoiTower() throws IOException { - Alpha alpha = new Alpha(); - // alpha.getConfig().setEvaluateStratifiedPart(false); - InputProgram.Builder programBuilder = InputProgram.builder(); - ProgramParser parser = new ProgramParser(); - InputStream baseProgStream = HanoiTowerDetailedTest.class.getResourceAsStream(HANOI_TOWER_SRC); - InputStream instanceStream = HanoiTowerDetailedTest.class.getResourceAsStream(SIMPLE_INSTANCE); - programBuilder.accumulate(parser.parse(CharStreams.fromStream(baseProgStream))); - programBuilder.accumulate(parser.parse(CharStreams.fromStream(instanceStream))); - InputProgram prog = programBuilder.build(); - InternalProgram preprocessed = InternalProgram.fromNormalProgram(alpha.normalizeProgram(prog)); - Optional solveResult = alpha.solve(preprocessed).findFirst(); - assertTrue(solveResult.isPresent()); - } - -} diff --git a/src/test/java/at/ac/tuwien/kr/alpha/test/util/RuleParser.java b/src/test/java/at/ac/tuwien/kr/alpha/test/util/RuleParser.java deleted file mode 100644 index 6c5727e30..000000000 --- a/src/test/java/at/ac/tuwien/kr/alpha/test/util/RuleParser.java +++ /dev/null @@ -1,21 +0,0 @@ -package at.ac.tuwien.kr.alpha.test.util; - -import at.ac.tuwien.kr.alpha.common.program.InputProgram; -import at.ac.tuwien.kr.alpha.common.rule.BasicRule; -import at.ac.tuwien.kr.alpha.grounder.parser.ProgramParser; - -public class RuleParser { - - public static BasicRule parse(String str) { - ProgramParser parser = new ProgramParser(); - InputProgram prog = parser.parse(str); - if (!prog.getFacts().isEmpty()) { - throw new IllegalArgumentException("Excepted exactly one rule and no facts!"); - } - if (prog.getRules().size() != 1) { - throw new IllegalArgumentException("Excepted exactly one rule"); - } - return prog.getRules().get(0); - } - -}