use of at.ac.tuwien.kr.alpha.commons.substitutions.Instance in project Alpha by alpha-asp.
the class StratifiedEvaluation method substituteFromRecentlyAddedInstances.
/**
* Use this to find initial substitutions for a starting literal when grounding a rule.
* In order to avoid finding the same ground instantiations of rules again, only look at
* <code>modifiedInLastEvaluationRun</code> to obtain instances.
*
* @param lit the literal to substitute.
* @return valid ground substitutions for the literal based on the recently added instances (i.e. instances derived in
* the last evaluation run).
*/
private List<Substitution> substituteFromRecentlyAddedInstances(Literal lit) {
List<Substitution> retVal = new ArrayList<>();
Set<Instance> instances = modifiedInLastEvaluationRun.get(lit.getPredicate());
if (instances == null) {
return Collections.emptyList();
}
for (Instance instance : instances) {
Substitution unifyingSubstitution = BasicSubstitution.specializeSubstitution(lit, instance, BasicSubstitution.EMPTY_SUBSTITUTION);
if (unifyingSubstitution != null) {
retVal.add(unifyingSubstitution);
}
}
return retVal;
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Instance in project Alpha by alpha-asp.
the class StratifiedEvaluation method apply.
@Override
public // memories created here rather than re-initialize everything.
InternalProgram apply(AnalyzedProgram inputProgram) {
// Calculate a stratification and initialize the working memory.
ComponentGraph componentGraph = inputProgram.getComponentGraph();
List<ComponentGraph.SCComponent> 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.
Map<Predicate, Set<Instance>> knownFacts = new LinkedHashMap<>(inputProgram.getFactsByPredicate());
for (Map.Entry<Predicate, Set<Instance>> entry : knownFacts.entrySet()) {
workingMemory.initialize(entry.getKey());
workingMemory.addInstances(entry.getKey(), true, entry.getValue());
}
// Create working memories for all predicates occurring in each rule.
for (CompiledRule nonGroundRule : inputProgram.getRulesById().values()) {
for (Predicate predicate : nonGroundRule.getOccurringPredicates()) {
workingMemory.initialize(predicate);
}
}
workingMemory.reset();
// Set up literal instantiator.
literalInstantiator = new LiteralInstantiator(new WorkingMemoryBasedInstantiationStrategy(workingMemory));
// Evaluate the program part covered by the calculated stratification.
for (ComponentGraph.SCComponent currComponent : strata) {
evaluateComponent(currComponent);
}
// Build the program resulting from evaluating the stratified part.
// Add original input facts to newly derived ones.
additionalFacts.addAll(inputProgram.getFacts());
List<CompiledRule> outputRules = new ArrayList<>();
inputProgram.getRulesById().entrySet().stream().filter((entry) -> !solvedRuleIds.contains(entry.getKey())).forEach((entry) -> outputRules.add(entry.getValue()));
// NOTE: if InternalProgram requires solved rules, they should be added here.
return new InternalProgram(outputRules, additionalFacts);
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Instance in project Alpha by alpha-asp.
the class StratifiedEvaluation method evaluateComponent.
private void evaluateComponent(ComponentGraph.SCComponent comp) {
LOGGER.debug("Evaluating component {}", comp);
ComponentEvaluationInfo evaluationInfo = getRulesToEvaluate(comp);
if (evaluationInfo.isEmpty()) {
LOGGER.debug("No rules to evaluate for component {}", comp);
return;
}
// Rules outside of dependency cycles only need to be evaluated once.
if (!evaluationInfo.nonRecursiveRules.isEmpty()) {
prepareInitialEvaluation(evaluationInfo.nonRecursiveRules);
evaluateRules(evaluationInfo.nonRecursiveRules, true);
for (IndexedInstanceStorage instanceStorage : workingMemory.modified()) {
// Directly record all newly derived instances as additional facts.
for (Instance recentlyAddedInstance : instanceStorage.getRecentlyAddedInstances()) {
additionalFacts.add(Atoms.newBasicAtom(instanceStorage.getPredicate(), recentlyAddedInstance.terms));
}
instanceStorage.markRecentlyAddedInstancesDone();
}
}
boolean isInitialRun = true;
if (!evaluationInfo.recursiveRules.isEmpty()) {
do {
// evaluate these until nothing new can be derived any more.
if (isInitialRun) {
prepareInitialEvaluation(evaluationInfo.recursiveRules);
}
evaluateRules(evaluationInfo.recursiveRules, isInitialRun);
isInitialRun = false;
modifiedInLastEvaluationRun = new HashMap<>();
// Since we are stratified we never have to backtrack, therefore just collect the added instances.
for (IndexedInstanceStorage instanceStorage : workingMemory.modified()) {
// Directly record all newly derived instances as additional facts.
for (Instance recentlyAddedInstance : instanceStorage.getRecentlyAddedInstances()) {
additionalFacts.add(Atoms.newBasicAtom(instanceStorage.getPredicate(), recentlyAddedInstance.terms));
}
modifiedInLastEvaluationRun.putIfAbsent(instanceStorage.getPredicate(), new LinkedHashSet<>());
modifiedInLastEvaluationRun.get(instanceStorage.getPredicate()).addAll(instanceStorage.getRecentlyAddedInstances());
instanceStorage.markRecentlyAddedInstancesDone();
}
// If the evaluation of rules did not modify the working memory we have a fixed-point.
} while (!workingMemory.modified().isEmpty());
}
LOGGER.debug("Evaluation done - reached a fixed point on component {}", comp);
SetUtils.union(evaluationInfo.nonRecursiveRules, evaluationInfo.recursiveRules).forEach((rule) -> solvedRuleIds.add(rule.getRuleId()));
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Instance in project Alpha by alpha-asp.
the class NaiveGrounderTest method testPermissiveGrounderHeuristicTolerance.
/**
* Tests if {@link NaiveGrounder#getGroundInstantiations(InternalRule, RuleGroundingOrder, Substitution, Assignment)}
* produces ground instantiations for the rule with ID {@code ruleID} in {@code program} when {@code startingLiteral}
* unified with the numeric instance {@code startingInstance} is used as starting literal and the following
* additional conditions are established:
* <ul>
* <li>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)}.
* </li>
* <li>The same atoms are assigned the truth values in the {@code truthsOfB} array.</li>
* </ul>
* 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(ASPCore2Program program, int ruleID, Literal startingLiteral, int startingInstance, int tolerance, ThriceTruth[] truthsOfB, int arityOfB, boolean expectNoGoods, List<Integer> expectedNumbersOfUnassignedPositiveBodyAtoms) {
CompiledProgram internalPrg = InternalProgram.fromNormalProgram(NORMALIZE_TRANSFORM.apply(program));
AtomStore atomStore = new AtomStoreImpl();
TrailAssignment currentAssignment = new TrailAssignment(atomStore);
GrounderHeuristicsConfiguration heuristicConfiguration = GrounderHeuristicsConfiguration.getInstance(tolerance, tolerance);
NaiveGrounder grounder = (NaiveGrounder) GrounderFactory.getInstance("naive", internalPrg, atomStore, p -> true, heuristicConfiguration, true);
int[] bAtomIDs = new int[truthsOfB.length];
for (int i = 0; i < truthsOfB.length; i++) {
int[] bTerms = new int[arityOfB];
for (int n = 0; n < arityOfB; n++) {
bTerms[n] = (n == arityOfB - 1) ? i + 1 : startingInstance;
}
bAtomIDs[i] = atomStore.putIfAbsent(atom("b", bTerms));
}
addAtomsToWorkingMemoryWithoutChangingTheAssignment(atomStore, grounder, bAtomIDs);
assign(currentAssignment, bAtomIDs, truthsOfB);
grounder.bootstrap();
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());
} else {
assertTrue(bindingResult.getNumbersOfUnassignedPositiveBodyAtoms().isEmpty());
}
}
use of at.ac.tuwien.kr.alpha.commons.substitutions.Instance in project Alpha by alpha-asp.
the class SubstitutionTest method specializeTermsFunctionTermBinding.
@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));
}
Aggregations