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