clingo.propagate
Functions and classes to implement custom propagators.
Example
>>> from typing import Sequence
>>> from clingo.control import Control
>>> from clingo.core import Library
>>> from clingo.propagate import PropagateControl, PropagateInit, Propagator
>>> from clingo.symbol import Function
>>>
>>> LIB = Library()
>>>
>>> class AIFFB(Propagator):
... slit_a: int
... slit_b: int
...
... def __init__(self) -> None:
... super().__init__()
... self.slit_a = 0
... self.slit_b = 0
...
... # add watches for atoms `a` and `b`
... def init(self, init: PropagateInit) -> None:
... # get program literals for atoms `a` and `b`
... plit_a = init.base[Function(LIB, "a")].literal
... plit_b = init.base[Function(LIB, "b")].literal
... # get solver literals for program literals `a` and `b`
... self.slit_a = init.solver_literal(plit_a)
... self.slit_b = init.solver_literal(plit_b)
... # add watches for solver literals `a` and `b`
... init.add_watch(self.slit_a)
... init.add_watch(self.slit_b)
...
... # propagate solver literals `a` and `b`
... def propagate(self, control: PropagateControl, changes: Sequence[int]) -> None:
... # if `a` is true imply `b`
... if self.slit_a in changes:
... assert control.assignment.is_true(self.slit_a)
... control.add_clause([-self.slit_a, self.slit_b])
... # if `b` is true imply `a`
... if self.slit_b in changes:
... assert control.assignment.is_true(self.slit_b)
... control.add_clause([-self.slit_b, self.slit_a])
...
>>> ctl = Control(LIB, ["0"])
>>> ctl.register_propagator(AIFFB())
>>> ctl.parse_string("1 { a; b }.")
>>> ctl.ground()
>>> with ctl.solve(on_model=print) as hnd:
>>> print(hnd.get())
a b
SAT
Provides information about the current state of literals in the solver.
It provides methods to inspect and query the assignment, which is essential for implementing custom propagators.
Key concepts:
- Each literal is either true, false, or unassigned.
- Each assigned literal has a decision level.
- There is exactly one decision literal per level.
- All other literals on the same level are implied by the decision literal and literals from earlier levels.
- The current decision level is the highest level at which atoms are assigned.
- The root level is the lowest decision level that can be backtracked to.
Implements Sequence[int]
to access the solver literals in the assignment.
Returns the decision literal of the given level.
Each level has exactly one decision literal, which implies other literals on the same level.
Arguments:
- level: The decision level.
Returns:
The decision literal.
Check if the given literal is false.
Arguments:
- literal: The solver literal.
Returns:
Whether the literal is false.
Checks if the truth value of the literal is fixed.
Arguments:
- literal: The solver literal.
Returns:
Whether the literal is fixed.
Check if the given literal is free.
Arguments:
- literal: The solver literal.
Returns:
Whether the literal is free.
Check if the given literal is true.
Arguments:
- literal: The solver literal.
Returns:
Whether the literal is true.
Returns the decision level of the given literal.
The decision level indicates when the literal was assigned or implied during the solving process.
Arguments:
- literal: The solver literal.
Returns:
The decision level of the literal.
Returns the truth value of the literal, or None if unassigned.
Arguments:
- literal: The solver literal.
Returns:
The truth value of the literal.
Enumeration of check modes.
Call Propagator.check()
on propagation fixpoints and total assignments.
Call Propagator.check()
on propagation fixpoints.
Class for controlling propagation.
This class provides methods for adding clauses, literals, and nogoods, as well as managing watches and performing propagation.
Add a clause to the solver.
Tagged clauses are deleted after the current solve call finishes while locked clauses are exempt from the solvers clause deletion strategy.
See propagate()
for how to handle the case that the function returns false.
Arguments:
- literals: A sequence of solver literals representing the clause.
- tag: Whether to tag the clause.
- lock: Whether to lock the clause.
Returns:
Whether the clause could be integrated without conflict.
Add a literal to the solver.
This literal is only added to the associated solving thread and deleted after the solve call.
Returns:
A fresh solver literal.
A shortcut for add_clause([-literal for literal in literals], tag, lock)
.
Arguments:
- literals: A sequence of solver literals representing the nogood.
- tag: Whether to tag the nogood.
- lock: Whether to lock the nogood.
Returns:
Whether the nogood could be integrated without conflict.
Add a watch for the given solver literal.
Arguments:
- literal: The literal to watch.
Check if a watch exists for the given solver literal.
Arguments:
- literal: The literal to check.
Returns:
True if a watch exists for the literal, False otherwise.
Perform propagation in the solver.
If this function returns False, the propagator must add no further
clauses/literals and immediately return from the corresponding
Propagator.propagate()
or Propagator.check()
call.
Returns:
True if propagation was successful, False otherwise.
Class for initializing a propagator.
This class provides methods for setting up propagation, including adding clauses, literals, watches, and constraints.
Add a clause to the solver.
If the clause could not be added to the solver, there is a top-level conflict and the underlying problem is unsatisfiable.
Arguments:
- literals: A sequence of solver literals representing the clause.
Returns:
Whether the clause could be added without conflict.
Add a new literal to the solver.
See also freeze_literal()
.
Arguments:
- freeze: Whether to freeze the literal.
Returns:
The newly added solver literal.
Add a weighted literal to minimize to the solver.
Arguments:
- literal: The literal to minimize.
- weight: The weight of the literal.
- priority: The priority of the literal.
Add a watch for the given solver literal.
Arguments:
- literal: The literal to watch.
- thread_id: The id of the thread to add the watch to. If None, adds to all threads.
Add a weight constraint to the solver.
See add_clause
for how to interpret the return value.
Arguments:
- literal: The literal associated with the constraint.
- literals: A sequence of (literal, weight) tuples.
- bound: The bound of the weight constraint.
- type: The type of the weight constraint.
- compare_equal: Whether to use equality comparison.
Returns:
Whether the weight constraint could be added without conflict.
Freeze the given literal.
Frozen literals are exempt from simplification. This is important for literals whose truth values a propagator has to track.
Arguments:
- literal: The literal to freeze.
Perform initial propagation.
See the add_clause()
for how to intepret the return value.
Returns:
True if propagation was successful, False otherwise.
Remove the watch for the given literal.
Arguments:
- literal: The literal to remove the watch for.
- thread_id: The id of the thread to remove the watch from. If None, removes from all threads.
Interface for implementing propagators.
This class defines methods that can be implemented to create custom propagators for use with the solver. They can be left empty to use their default implementation.
Check if the current assignment is valid.
This method is called on propagation fixpoints or total assignments (see
PropagateInit.check_mode
). A propagator should add clauses to implement its
constraints here.
Arguments:
- control: The propagate control object for managing propagation.
Make a decision on the next literal to assign.
This method is called to decide on a literal to be assigned next.
Arguments:
- thread_id: The id of the current solver thread.
- assignment: The current assignment.
- fallback: The literal choosen by the solver's heuristic.
Returns:
The literal to assign or 0 if no decision was made.
Initialize the propagator.
This method is called once before each solving step. It is used to map relevant program literals to solver literals, add watches for solver literals, and initialize the propagator's internal state.
Arguments:
- init: The propagate init object for initializing the propagator.
Propagate given a set of changes.
This method is called during propagation with a non-empty list watched literals that have been assigned truth values. A propagator should add clauses to propagate literals and to implement its constraints.
Typical propagators add unit-resulting or conflicting constraints only.
Arguments:
- control: The propagate control object for managing propagation.
- changes: A list of literals that have changed.
Undo previous assignments.
This method is called to undo previous assignments.
See also PropagateInit.undo_mode
.
Arguments:
- thread_id: The id of the current solver thread.
- assignment: The current assignment.
- changes: The literals whose assignment is undone.
Provides access to literals in the solver's trail.
The trail represents the sequence of literals assigned during the solving process. It is structured by decision levels, where each level contains literals assigned due to implications from the decision literal at that level.
The literals within each level are ordered by implication, reflecting the logical dependencies between them as determined by the solver's propagation and learning mechanisms. The decision literal for each level is placed at the beginning of its respective sequence.
Implements Sequence[int]
to access the solver literals in the trail.
Get the index of the first literal on the given level.
This also corresponds to the decision literal for that level.
Arguments:
- level: A decision level.
Returns:
The index of the decision literal.
Get the index after the last literal on the given level.
Arguments:
- level: A decision level.
Returns:
The index after the last literal.
Get the literals assigned at the given decision level.
This sequence includes all literals assigned at this level in implication order, with the decision literal at the beginning of the sequence.
Arguments:
- level: A decision level.
Returns:
A sequence of literals.
Enumeration of undo modes.
Additionally call Propagator.undo()
when check has been called.
Call Propagator.undo()
for decision levels with non-emty changes.
Enumeration of weight constraint types.