Search in sources :

Example 1 with BindingResult

use of at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult 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());
    }
}
Also used : Assertions.fail(org.junit.jupiter.api.Assertions.fail) InternalProgram(at.ac.tuwien.kr.alpha.core.programs.InternalProgram) BeforeEach(org.junit.jupiter.api.BeforeEach) Substitution(at.ac.tuwien.kr.alpha.api.grounder.Substitution) Arrays(java.util.Arrays) TrailAssignment(at.ac.tuwien.kr.alpha.core.solver.TrailAssignment) BasicSubstitution(at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution) AnalyzedProgram(at.ac.tuwien.kr.alpha.core.programs.AnalyzedProgram) ThriceTruth(at.ac.tuwien.kr.alpha.core.solver.ThriceTruth) ProgramParser(at.ac.tuwien.kr.alpha.api.programs.ProgramParser) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) NoGood(at.ac.tuwien.kr.alpha.core.common.NoGood) Disabled(org.junit.jupiter.api.Disabled) NormalProgram(at.ac.tuwien.kr.alpha.api.programs.NormalProgram) Terms(at.ac.tuwien.kr.alpha.commons.terms.Terms) ProgramParserImpl(at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl) Map(java.util.Map) BindingResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult) CompiledRule(at.ac.tuwien.kr.alpha.core.rules.CompiledRule) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Literals(at.ac.tuwien.kr.alpha.core.atoms.Literals) CompiledProgram(at.ac.tuwien.kr.alpha.core.programs.CompiledProgram) NormalizeProgramTransformation(at.ac.tuwien.kr.alpha.core.programs.transformation.NormalizeProgramTransformation) Collection(java.util.Collection) GrounderHeuristicsConfiguration(at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration) StratifiedEvaluation(at.ac.tuwien.kr.alpha.core.programs.transformation.StratifiedEvaluation) ProgramPartParser(at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser) TestUtils.atom(at.ac.tuwien.kr.alpha.core.test.util.TestUtils.atom) Test(org.junit.jupiter.api.Test) List(java.util.List) Assignment(at.ac.tuwien.kr.alpha.core.common.Assignment) Instance(at.ac.tuwien.kr.alpha.commons.substitutions.Instance) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) SystemConfig(at.ac.tuwien.kr.alpha.api.config.SystemConfig) ASPCore2Program(at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program) AtomStore(at.ac.tuwien.kr.alpha.core.common.AtomStore) InternalRule(at.ac.tuwien.kr.alpha.core.rules.InternalRule) Collections(java.util.Collections) AtomStoreImpl(at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl) BindingResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult) Instance(at.ac.tuwien.kr.alpha.commons.substitutions.Instance) AtomStoreImpl(at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl) CompiledProgram(at.ac.tuwien.kr.alpha.core.programs.CompiledProgram) TrailAssignment(at.ac.tuwien.kr.alpha.core.solver.TrailAssignment) AtomStore(at.ac.tuwien.kr.alpha.core.common.AtomStore) Substitution(at.ac.tuwien.kr.alpha.api.grounder.Substitution) BasicSubstitution(at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution) GrounderHeuristicsConfiguration(at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration) CompiledRule(at.ac.tuwien.kr.alpha.core.rules.CompiledRule)

Example 2 with BindingResult

use of at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult in project Alpha by alpha-asp.

the class NaiveGrounder method bootstrap.

/**
 * Prepares facts of the input program for joining and derives all NoGoods representing ground rules. May only be called once.
 *
 * @return
 */
protected HashMap<Integer, NoGood> bootstrap() {
    final HashMap<Integer, NoGood> groundNogoods = new LinkedHashMap<>();
    for (Predicate predicate : factsFromProgram.keySet()) {
        // Instead of generating NoGoods, add instance to working memories directly.
        workingMemory.addInstances(predicate, true, factsFromProgram.get(predicate));
    }
    for (CompiledRule nonGroundRule : fixedRules) {
        // Generate NoGoods for all rules that have a fixed grounding.
        RuleGroundingOrder groundingOrder = nonGroundRule.getGroundingInfo().getFixedGroundingOrder();
        BindingResult bindingResult = getGroundInstantiations(nonGroundRule, groundingOrder, new BasicSubstitution(), null);
        groundAndRegister(nonGroundRule, bindingResult.getGeneratedSubstitutions(), groundNogoods);
    }
    fixedRules = null;
    return groundNogoods;
}
Also used : BindingResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult) NoGood(at.ac.tuwien.kr.alpha.core.common.NoGood) CompiledRule(at.ac.tuwien.kr.alpha.core.rules.CompiledRule) BasicSubstitution(at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution) LinkedHashMap(java.util.LinkedHashMap) Predicate(at.ac.tuwien.kr.alpha.api.programs.Predicate)

Example 3 with BindingResult

use of at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult in project Alpha by alpha-asp.

the class NaiveGrounder method bindNextAtomInRule.

// @formatter:off
/**
 * Computes ground substitutions for a literal based on a {@link RuleGroundingOrderImpl} and a {@link BasicSubstitution}.
 *
 * Computes ground substitutions for the literal at position <code>orderPosition</code> of <code>groundingOrder</code>
 * Actual substitutions are computed by this grounder's {@link LiteralInstantiator}.
 *
 * @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 <code>groundingOrder</code>, indicates which literal should be bound
 * @param originalTolerance the original tolerance of the used grounding heuristic
 * @param remainingTolerance the remaining tolerance, determining if binding continues in the presence of substitutions based on unassigned atoms
 * @param partialSubstitution a substitution
 * @return a {@link BindingResult} representing applicable ground substitutions for all literals after orderPosition in groundingOrder
 */
// @formatter:on
private BindingResult bindNextAtomInRule(RuleGroundingOrder groundingOrder, int orderPosition, int originalTolerance, int remainingTolerance, Substitution partialSubstitution) {
    Literal currentLiteral = groundingOrder.getLiteralAtOrderPosition(orderPosition);
    if (currentLiteral == null) {
        LOGGER.trace("No more literals found in grounding order, therefore stopping binding!");
        return BindingResult.singleton(partialSubstitution, originalTolerance - remainingTolerance);
    }
    LOGGER.trace("Binding current literal {} with remaining tolerance {} and partial substitution {}.", currentLiteral, remainingTolerance, partialSubstitution);
    LiteralInstantiationResult instantiationResult = ruleInstantiator.instantiateLiteral(currentLiteral, partialSubstitution);
    switch(instantiationResult.getType()) {
        case CONTINUE:
            /*
				 * Recursively call bindNextAtomInRule for each generated substitution
				 * and the next literal in the grounding order (i.e. advance), thereby reducing remaining
				 * tolerance by 1 iff a substitution uses an unassigned ground atom.
				 * If remainingTolerance falls below zero, an empty {@link BindingResult} is returned.
				 */
            List<ImmutablePair<Substitution, AssignmentStatus>> substitutionInfos = instantiationResult.getSubstitutions();
            LOGGER.trace("Literal instantiator yielded {} substitutions for literal {}.", substitutionInfos.size(), currentLiteral);
            BindingResult retVal = new BindingResult();
            for (ImmutablePair<Substitution, AssignmentStatus> substitutionInfo : substitutionInfos) {
                retVal.add(this.continueBinding(groundingOrder, orderPosition, originalTolerance, remainingTolerance, substitutionInfo));
            }
            return retVal;
        case PUSH_BACK:
            /*
				 * Delegate to pushBackAndBindNextAtomInRule(RuleGroundingOrder, int, int, int, Substitution, Assignment).
				 * Pushes the current literal to the end of the grounding order and calls bindNextAtomInRule with the modified grounding oder.
				 */
            LOGGER.trace("Pushing back literal {} in grounding order.", currentLiteral);
            return pushBackAndBindNextAtomInRule(groundingOrder, orderPosition, originalTolerance, remainingTolerance, partialSubstitution);
        case MAYBE_PUSH_BACK:
            /*
				 * Indicates that the rule instantiator could not find any substitutions for the current literal. If a permissive grounder heuristic is in
				 * use, push the current literal to the end of the grounding order and proceed with the next one, otherwise return an empty BindingResult.
				 */
            if (originalTolerance > 0) {
                LOGGER.trace("No substitutions yielded by literal instantiator for literal {}, but using permissive heuristic, therefore pushing the literal back.", currentLiteral);
                // i.e. it is deemed acceptable to have ground rules where a number of body atoms are not yet assigned a truth value by the solver.
                return pushBackAndBindNextAtomInRule(groundingOrder, orderPosition, originalTolerance, remainingTolerance, partialSubstitution);
            } else {
                LOGGER.trace("No substitutions found for literal {}", currentLiteral);
                return BindingResult.empty();
            }
        case STOP_BINDING:
            LOGGER.trace("No substitutions found for literal {}", currentLiteral);
            return BindingResult.empty();
        default:
            throw Util.oops("Unhandled literal instantiation result type: " + instantiationResult.getType());
    }
}
Also used : BindingResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult) ImmutablePair(org.apache.commons.lang3.tuple.ImmutablePair) Substitution(at.ac.tuwien.kr.alpha.api.grounder.Substitution) BasicSubstitution(at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution) LiteralInstantiationResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.LiteralInstantiationResult) Literal(at.ac.tuwien.kr.alpha.api.programs.literals.Literal) AssignmentStatus(at.ac.tuwien.kr.alpha.core.grounder.instantiation.AssignmentStatus)

Example 4 with BindingResult

use of at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult in project Alpha by alpha-asp.

the class NaiveGrounder method getGroundInstantiations.

// Ideally, this method should be private. It's only visible because NaiveGrounderTest needs to access it.
BindingResult getGroundInstantiations(CompiledRule rule, RuleGroundingOrder groundingOrder, Substitution partialSubstitution, Assignment currentAssignment) {
    int tolerance = heuristicsConfiguration.getTolerance(rule.isConstraint());
    if (tolerance < 0) {
        tolerance = Integer.MAX_VALUE;
    }
    // Update instantiationStrategy with current assignment.
    // Note: Actually the assignment could be an instance variable of the grounder (shared with solver),
    // but this would have a larger impact on grounder/solver communication design as a whole.
    instantiationStrategy.setCurrentAssignment(currentAssignment);
    BindingResult bindingResult = bindNextAtomInRule(groundingOrder, 0, tolerance, tolerance, partialSubstitution);
    if (LOGGER.isDebugEnabled()) {
        for (int i = 0; i < bindingResult.size(); i++) {
            Integer numberOfUnassignedPositiveBodyAtoms = bindingResult.getNumbersOfUnassignedPositiveBodyAtoms().get(i);
            if (numberOfUnassignedPositiveBodyAtoms > 0) {
                LOGGER.debug("Grounded rule in which {} positive atoms are still unassigned: {} (substitution: {})", numberOfUnassignedPositiveBodyAtoms, rule, bindingResult.getGeneratedSubstitutions().get(i));
            }
        }
    }
    return bindingResult;
}
Also used : BindingResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult)

Example 5 with BindingResult

use of at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult in project Alpha by alpha-asp.

the class NaiveGrounder method getNoGoods.

@Override
public Map<Integer, NoGood> getNoGoods(Assignment currentAssignment) {
    // In first call, prepare facts and ground rules.
    final Map<Integer, NoGood> newNoGoods = fixedRules != null ? bootstrap() : new LinkedHashMap<>();
    // Compute new ground rule (evaluate joins with newly changed atoms)
    for (IndexedInstanceStorage modifiedWorkingMemory : workingMemory.modified()) {
        // Skip predicates solely used in the solver which do not occur in rules.
        Predicate workingMemoryPredicate = modifiedWorkingMemory.getPredicate();
        if (workingMemoryPredicate.isSolverInternal()) {
            continue;
        }
        // Iterate over all rules whose body contains the interpretation corresponding to the current workingMemory.
        final ArrayList<FirstBindingAtom> firstBindingAtoms = rulesUsingPredicateWorkingMemory.get(modifiedWorkingMemory);
        // Skip working memories that are not used by any rule.
        if (firstBindingAtoms == null) {
            continue;
        }
        for (FirstBindingAtom firstBindingAtom : firstBindingAtoms) {
            // Use the recently added instances from the modified working memory to construct an initial substitution
            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 = BasicSubstitution.specializeSubstitution(firstBindingAtom.startingLiteral, instance, BasicSubstitution.EMPTY_SUBSTITUTION);
                if (unifier == null) {
                    continue;
                }
                final BindingResult bindingResult = getGroundInstantiations(nonGroundRule, nonGroundRule.getGroundingInfo().orderStartingFrom(firstBindingAtom.startingLiteral), unifier, currentAssignment);
                groundAndRegister(nonGroundRule, bindingResult.getGeneratedSubstitutions(), newNoGoods);
            }
        }
        // Mark instances added by updateAssignment as done
        modifiedWorkingMemory.markRecentlyAddedInstancesDone();
    }
    workingMemory.reset();
    for (Atom removeAtom : removeAfterObtainingNewNoGoods) {
        final IndexedInstanceStorage storage = workingMemory.get(removeAtom, true);
        Instance instance = new Instance(removeAtom.getTerms());
        if (storage.containsInstance(instance)) {
            // permissive grounder heuristics may attempt to remove instances that are not yet in the working memory
            storage.removeInstance(instance);
        }
    }
    // Re-Initialize the stale working memory entries set and pass to instantiation strategy.
    removeAfterObtainingNewNoGoods = new LinkedHashSet<>();
    instantiationStrategy.setStaleWorkingMemoryEntries(removeAfterObtainingNewNoGoods);
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Grounded NoGoods are:");
        for (Map.Entry<Integer, NoGood> noGoodEntry : newNoGoods.entrySet()) {
            LOGGER.debug("{} == {}", noGoodEntry.getValue(), atomStore.noGoodToString(noGoodEntry.getValue()));
        }
        LOGGER.debug("{}", choiceRecorder);
    }
    if (debugInternalChecks) {
        checkTypesOfNoGoods(newNoGoods.values());
    }
    return newNoGoods;
}
Also used : BindingResult(at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult) Instance(at.ac.tuwien.kr.alpha.commons.substitutions.Instance) NoGood(at.ac.tuwien.kr.alpha.core.common.NoGood) ChoiceAtom(at.ac.tuwien.kr.alpha.core.atoms.ChoiceAtom) Atom(at.ac.tuwien.kr.alpha.api.programs.atoms.Atom) RuleAtom(at.ac.tuwien.kr.alpha.core.atoms.RuleAtom) Predicate(at.ac.tuwien.kr.alpha.api.programs.Predicate) Substitution(at.ac.tuwien.kr.alpha.api.grounder.Substitution) BasicSubstitution(at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution) CompiledRule(at.ac.tuwien.kr.alpha.core.rules.CompiledRule) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

BindingResult (at.ac.tuwien.kr.alpha.core.grounder.instantiation.BindingResult)7 BasicSubstitution (at.ac.tuwien.kr.alpha.commons.substitutions.BasicSubstitution)6 Substitution (at.ac.tuwien.kr.alpha.api.grounder.Substitution)5 NoGood (at.ac.tuwien.kr.alpha.core.common.NoGood)5 CompiledRule (at.ac.tuwien.kr.alpha.core.rules.CompiledRule)5 Literal (at.ac.tuwien.kr.alpha.api.programs.literals.Literal)4 Instance (at.ac.tuwien.kr.alpha.commons.substitutions.Instance)4 Map (java.util.Map)4 GrounderHeuristicsConfiguration (at.ac.tuwien.kr.alpha.api.config.GrounderHeuristicsConfiguration)3 SystemConfig (at.ac.tuwien.kr.alpha.api.config.SystemConfig)3 ASPCore2Program (at.ac.tuwien.kr.alpha.api.programs.ASPCore2Program)3 NormalProgram (at.ac.tuwien.kr.alpha.api.programs.NormalProgram)3 ProgramParser (at.ac.tuwien.kr.alpha.api.programs.ProgramParser)3 Terms (at.ac.tuwien.kr.alpha.commons.terms.Terms)3 Literals (at.ac.tuwien.kr.alpha.core.atoms.Literals)3 Assignment (at.ac.tuwien.kr.alpha.core.common.Assignment)3 AtomStore (at.ac.tuwien.kr.alpha.core.common.AtomStore)3 AtomStoreImpl (at.ac.tuwien.kr.alpha.core.common.AtomStoreImpl)3 ProgramParserImpl (at.ac.tuwien.kr.alpha.core.parser.ProgramParserImpl)3 ProgramPartParser (at.ac.tuwien.kr.alpha.core.parser.ProgramPartParser)3