14
14
class CSP (search .Problem ):
15
15
"""This class describes finite-domain Constraint Satisfaction Problems.
16
16
A CSP is specified by the following inputs:
17
- variables A list of variables; each is atomic (e.g. int or string).
17
+ variables A list of variables; each is atomic (e.g. int or string).
18
18
domains A dict of {var:[possible_value, ...]} entries.
19
19
neighbors A dict of {var:[var,...]} that for each variable lists
20
20
the other variables that participate in constraints.
21
21
constraints A function f(A, a, B, b) that returns true if neighbors
22
22
A, B satisfy the constraint when they have values A=a, B=b
23
+
23
24
In the textbook and in most mathematical definitions, the
24
25
constraints are specified as explicit pairs of allowable values,
25
26
but the formulation here is easier to express and more compact for
@@ -29,7 +30,7 @@ class CSP(search.Problem):
29
30
problem, that's all there is.
30
31
31
32
However, the class also supports data structures and methods that help you
32
- solve CSPs by calling a search function on the CSP. Methods and slots are
33
+ solve CSPs by calling a search function on the CSP. Methods and slots are
33
34
as follows, where the argument 'a' represents an assignment, which is a
34
35
dict of {var:val} entries:
35
36
assign(var, val, a) Assign a[var] = val; do other bookkeeping
@@ -307,8 +308,9 @@ def tree_csp_solver(csp):
307
308
"""[Figure 6.11]"""
308
309
assignment = {}
309
310
root = csp .variables [0 ]
310
- X , parent = topological_sort (csp .variables , root )
311
- for Xj in reversed (X ):
311
+ root = 'NT'
312
+ X , parent = topological_sort (csp , root )
313
+ for Xj in reversed (X [1 :]):
312
314
if not make_arc_consistent (parent [Xj ], Xj , csp ):
313
315
return None
314
316
for Xi in X :
@@ -318,8 +320,43 @@ def tree_csp_solver(csp):
318
320
return assignment
319
321
320
322
321
- def topological_sort (xs , x ):
322
- raise NotImplementedError
323
+ def topological_sort (X , root ):
324
+ """Returns the topological sort of X starting from the root.
325
+
326
+ Input:
327
+ X is a list with the nodes of the graph
328
+ N is the dictionary with the neighbors of each node
329
+ root denotes the root of the graph.
330
+
331
+ Output:
332
+ stack is a list with the nodes topologically sorted
333
+ parents is a dictionary pointing to each node's parent
334
+
335
+ Other:
336
+ visited shows the state (visited - not visited) of nodes
337
+
338
+ """
339
+ nodes = X .variables
340
+ neighbors = X .neighbors
341
+
342
+ visited = defaultdict (lambda : False )
343
+
344
+ stack = []
345
+ parents = {}
346
+
347
+ build_topological (root , None , neighbors , visited , stack , parents )
348
+ return stack , parents
349
+
350
+ def build_topological (node , parent , neighbors , visited , stack , parents ):
351
+ """Builds the topological sort and the parents of each node in the graph"""
352
+ visited [node ] = True
353
+
354
+ for n in neighbors [node ]:
355
+ if (not visited [n ]):
356
+ build_topological (n , node , neighbors , visited , stack , parents )
357
+
358
+ parents [node ] = parent
359
+ stack .insert (0 ,node )
323
360
324
361
325
362
def make_arc_consistent (Xj , Xk , csp ):
0 commit comments