Many constraints
of the same type
variables = {"x1": {1, 2, 3},
"x2": {1, 2, 3},
"x3": {1, 2, 3}}
c1 = LessThan("x1", "x2")
c2 = LessThan("x2", "x3")
We need to adapt the dfs(_,_)
function:
def dfs(variables, constraints):
# if constraint.filter(variables) is False:
if not fix_point(variables, constraints):
return 0 # at least one constraint is not satisfied
# ...
and ensure that a fix point is reached.
Fixpoint reasoning
Iteratively applying constraint propagation until no more improvements are possible or a failure is detected.
So, as long as a constraint filters values, all the other ones must be checked.
🚀 This could be refined.
step | x1 | x2 | x3 | To check | Consistent |
---|---|---|---|---|---|
0 | [1,3] | [1,3] | [1,3] | {c1,c2} | {} |
1 | [1,2] | [2,3] | - | {c1,c2} | {} |
{c2} | {c1} | ||||
2 | - | [2,2] | [3,3] | {c2} | {c1} |
{c1} | {c2} | ||||
3 | [1,1] | - | - | {c1} | {c2} |
{c2} | {c1} | ||||
4 | - | - | - | {c2} | {c1} |
{} | {c1, c2} |
We will create a method to iterate on the constraints:
def fix_point(variables, constraints):
"""Reach a fix point.
If a failure is raised, returns False,
otherwise guarantees that all events are propagated.
"""
>>🥛<<
def fix_point(variables, constraints):
while True:
fltrs = False
for c in constraints:
flt = c.filter(variables)
if flt is False: # in case of failure
return False
elif flt is True: # in case of filtering
fltrs |= True # keep on looping
if not fltrs : # to break the while-loop
return True
variables = {"x1": {1, 2, 3},
"x2": {1, 2, 3},
"x3": {1, 2, 3}}
c1 = LessThan("x1", "x2")
c2 = LessThan("x2", "x3")
fix_point(variables, {c1, c2})
print(variables)
outputs:
{'x1': [1], 'x2': [2], 'x3': [3]}
🚀 Propagation engine
- Event-based reasoning, advisors, watch literals
- Scheduling and propagating
- Variable-oriented or Constraint-oriented
- Iterating on constraints by considering their complexity