-
Notifications
You must be signed in to change notification settings - Fork 0
/
lendec.py
87 lines (74 loc) · 3.04 KB
/
lendec.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from constants import *
class LENDEC():
'''Implements length decrement boundary consistency.
Consecutive nodes must decrease in length, at least 1 centimeters. The following relations must
hold between L2 through L7:
L2 => L3 + 10mm
L3 => L4 + 10mm
L4 => L5 + 10mm
L5 => L6 + 10mm
L6 => L7 + 10mm
For each relation, a binary constraint is defined. This class establishes
binary consistency for them all.'''
def establish(self, csp, curvar, value, participants, spec):
'''Establishes consistency after curvar: value assignment.
The assumption is that curvar is in the assigned variables.'''
Li, Lj = sorted(participants, key=lambda p: int(p[1:]))
A = csp.get_assignment()
D = csp.get_domains()
return self.__revise(csp, Li, Lj, A, D)
def propagate(self, csp, reduced_vars, participants, spec):
'''Establishes consistency after reduction of some variables.'''
Li, Lj = sorted(participants, key=lambda p: int(p[1:]))
A = csp.get_assignment()
D = csp.get_domains()
return self.__revise(csp, Li, Lj, A, D)
def __revise(self, csp, Li, Lj, A, D):
'''Canculates new consistent bounds for Li and Lj where Lj < Li.'''
reduced_vars = set([])
if Li in A: # make Lj[max] consistent
newDj = {
"min": D[Lj]["min"],
"max": min(A[Li]-10, D[Lj]["max"])
}
if newDj["min"] > newDj["max"]:
return (CONTRADICTION, {Lj})
if newDj != D[Lj]:
csp.update_domain(Lj, newDj)
reduced_vars.add(Lj)
elif Lj in A: # make Li[min] consistent
newDi = {
"min": max(A[Lj]+10, D[Li]["min"]),
"max": D[Li]["max"]
}
if newDi["min"] > newDi["max"]:
return (CONTRADICTION, {Li})
if newDi != D[Li]:
csp.update_domain(Li, newDi)
reduced_vars.add(Li)
else: # try making Li[min] and Lj[max] consistent
newDi = {
"min": max(D[Lj]["min"]+10, D[Li]["min"]),
"max": D[Li]["max"],
}
if newDi["min"] > newDi["max"]:
return (CONTRADICTION, {Li, Lj})
newDj = {
"min": D[Lj]["min"],
"max": min(D[Li]["max"]-10, D[Lj]["max"]),
}
if newDj["min"] > newDj["max"]:
return (CONTRADICTION, {Li, Lj})
if newDj != D[Lj]:
csp.update_domain(Lj, newDj)
reduced_vars.add(Lj)
if newDi != D[Li]:
csp.update_domain(Li, newDi)
reduced_vars.add(Li)
if len(reduced_vars) == 0:
return ALREADY_CONSISTENT
return MADE_CONSISTENT, reduced_vars
def __failed_set(self, csp, participants):
'''Returns the failed set.'''
unassigned = csp.get_unassigned_vars()
return participants.intersection(unassigned)