1
1
"""CSP (Constraint Satisfaction Problems) problems and solvers. (Chapter 6)."""
2
2
3
- from utils import *
3
+ from utils import * # noqa
4
4
import search
5
5
6
6
from collections import defaultdict
7
7
from functools import reduce
8
8
9
+ import itertools
10
+ import re
11
+
9
12
10
13
class CSP (search .Problem ):
11
14
@@ -44,7 +47,8 @@ class CSP(search.Problem):
44
47
display(a) Print a human-readable representation
45
48
46
49
>>> search.depth_first_graph_search(australia)
47
- <Node (('WA', 'B'), ('Q', 'B'), ('T', 'B'), ('V', 'B'), ('SA', 'G'), ('NT', 'R'), ('NSW', 'R'))>
50
+ <Node (('WA', 'B'), ('Q', 'B'), ('T', 'B'), ('V', 'B'), ('SA', 'G'),
51
+ ('NT', 'R'), ('NSW', 'R'))>
48
52
"""
49
53
50
54
def __init__ (self , vars , domains , neighbors , constraints ):
@@ -70,8 +74,8 @@ def nconflicts(self, var, val, assignment):
70
74
"Return the number of conflicts var=val has with other variables."
71
75
# Subclasses may implement this more efficiently
72
76
def conflict (var2 ):
73
- return (var2 in assignment
74
- and not self .constraints (var , val , var2 , assignment [var2 ]))
77
+ return (var2 in assignment and
78
+ not self .constraints (var , val , var2 , assignment [var2 ]))
75
79
return count_if (conflict , self .neighbors [var ])
76
80
77
81
def display (self , assignment ):
@@ -149,7 +153,7 @@ def conflicted_vars(self, current):
149
153
return [var for var in self .vars
150
154
if self .nconflicts (var , current [var ], current ) > 0 ]
151
155
152
- #______________________________________________________________________________
156
+ # ______________________________________________________________________________
153
157
# Constraint Propagation with AC-3
154
158
155
159
@@ -180,7 +184,7 @@ def revise(csp, Xi, Xj, removals):
180
184
revised = True
181
185
return revised
182
186
183
- #______________________________________________________________________________
187
+ # ______________________________________________________________________________
184
188
# CSP Backtracking Search
185
189
186
190
# Variable ordering
@@ -251,17 +255,21 @@ def backtracking_search(csp,
251
255
"""[Fig. 6.5]
252
256
>>> backtracking_search(australia) is not None
253
257
True
254
- >>> backtracking_search(australia, select_unassigned_variable=mrv) is not None
258
+ >>> backtracking_search(australia,
259
+ >>> select_unassigned_variable=mrv) is not None
255
260
True
256
- >>> backtracking_search(australia, order_domain_values=lcv) is not None
261
+ >>> backtracking_search(australia,
262
+ >>> order_domain_values=lcv) is not None
257
263
True
258
- >>> backtracking_search(australia, select_unassigned_variable=mrv, order_domain_values=lcv) is not None
264
+ >>> backtracking_search(australia, select_unassigned_variable=mrv,
265
+ >>> order_domain_values=lcv) is not None
259
266
True
260
267
>>> backtracking_search(australia, inference=forward_checking) is not None
261
268
True
262
269
>>> backtracking_search(australia, inference=mac) is not None
263
270
True
264
- >>> backtracking_search(usa, select_unassigned_variable=mrv, order_domain_values=lcv, inference=mac) is not None
271
+ >>> backtracking_search(usa, select_unassigned_variable=mrv,
272
+ >>> order_domain_values=lcv, inference=mac) is not None
265
273
True
266
274
"""
267
275
@@ -285,7 +293,7 @@ def backtrack(assignment):
285
293
assert result is None or csp .goal_test (result )
286
294
return result
287
295
288
- #______________________________________________________________________________
296
+ # ______________________________________________________________________________
289
297
# Min-conflicts hillclimbing search for CSPs
290
298
291
299
@@ -313,12 +321,11 @@ def min_conflicts_value(csp, var, current):
313
321
return argmin_random_tie (csp .domains [var ],
314
322
lambda val : csp .nconflicts (var , val , current ))
315
323
316
- #______________________________________________________________________________
324
+ # ______________________________________________________________________________
317
325
318
326
319
327
def tree_csp_solver (csp ):
320
328
"[Fig. 6.11]"
321
- n = len (csp .vars )
322
329
assignment = {}
323
330
root = csp .vars [0 ]
324
331
X , parent = topological_sort (csp .vars , root )
@@ -339,7 +346,7 @@ def topological_sort(xs, x):
339
346
def make_arc_consistent (Xj , Xk , csp ):
340
347
unimplemented ()
341
348
342
- #______________________________________________________________________________
349
+ # ______________________________________________________________________________
343
350
# Map-Coloring Problems
344
351
345
352
@@ -417,7 +424,7 @@ def parse_neighbors(neighbors, vars=[]):
417
424
PI; PA: LR RA; PC: PL CE LI AQ; PI: NH NO CA IF; PL: BR NB CE PC; RA:
418
425
AU BO FC PA LR""" )
419
426
420
- #______________________________________________________________________________
427
+ # ______________________________________________________________________________
421
428
# n-Queens Problem
422
429
423
430
@@ -507,17 +514,14 @@ def display(self, assignment):
507
514
print (str (self .nconflicts (var , val , assignment ))+ ch , end = ' ' )
508
515
print ()
509
516
510
- #______________________________________________________________________________
517
+ # ______________________________________________________________________________
511
518
# Sudoku
512
519
513
- import itertools
514
- import re
515
-
516
520
517
521
def flatten (seqs ): return sum (seqs , [])
518
522
519
- easy1 = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..'
520
- harder1 = '4173698.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'
523
+ easy1 = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..' # noqa
524
+ harder1 = '4173698.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......' # noqa
521
525
522
526
_R3 = list (range (3 ))
523
527
_CELL = itertools .count ().__next__
@@ -531,6 +535,7 @@ def flatten(seqs): return sum(seqs, [])
531
535
for v in unit :
532
536
_NEIGHBORS [v ].update (unit - set ([v ]))
533
537
538
+
534
539
class Sudoku (CSP ):
535
540
536
541
"""A Sudoku problem.
@@ -564,7 +569,8 @@ class Sudoku(CSP):
564
569
8 1 4 | 2 5 3 | 7 6 9
565
570
6 9 5 | 4 1 7 | 3 8 2
566
571
>>> h = Sudoku(harder1)
567
- >>> None != backtracking_search(h, select_unassigned_variable=mrv, inference=forward_checking)
572
+ >>> None != backtracking_search(h, select_unassigned_variable=mrv,
573
+ >>> inference=forward_checking)
568
574
True
569
575
"""
570
576
R3 = _R3
@@ -596,8 +602,9 @@ def show_cell(cell): return str(assignment.get(cell, '.'))
596
602
def abut (lines1 , lines2 ): return list (
597
603
map (' | ' .join , list (zip (lines1 , lines2 ))))
598
604
print ('\n ------+-------+------\n ' .join (
599
- '\n ' .join (reduce (abut , list (map (show_box , brow )))) for brow in self .bgrid ))
600
- #______________________________________________________________________________
605
+ '\n ' .join (reduce (
606
+ abut , list (map (show_box , brow )))) for brow in self .bgrid ))
607
+ # ______________________________________________________________________________
601
608
# The Zebra Puzzle
602
609
603
610
0 commit comments