-
Notifications
You must be signed in to change notification settings - Fork 2
/
CSP.py
134 lines (105 loc) · 4.76 KB
/
CSP.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import Heuristic
import Propagation
from Node import *
import copy
from GameRule import *
import sys
sys.setrecursionlimit(10 ** 9)
def print_board(board):
for i in board:
print(i)
print('*******************************************')
def create_domains_list(initial_board):
domains_list = copy.deepcopy(initial_board)
dimension = len(domains_list)
# convert puzzle board to my structure
# when still value is not assigned to cell,shows in array.
# when value is assigned to cell, shows with string "0" or "1"
for i in range(dimension):
for j in range(dimension):
if domains_list[i][j] == '1':
domains_list[i][j] = '1'
elif domains_list[i][j] == '0':
domains_list[i][j] = '0'
else:
domains_list[i][j] = ['0', '1']
# check domains with game rules
for i in range(dimension):
for j in range(dimension):
if domains_list[i][j] != "0" and domains_list[i][j] != "1": # when value is not assigned to variable
flag, new_domains_list = check_variables_domains_with_rule_game(domains_list, (i, j))
if flag:
domains_list = new_domains_list
else:
return False, []
return True, domains_list
# check puzzle when is backtracking to base_node, return False (puzzle is unsolvable)
def is_solvable(node):
if node.board == "":
print(" ====> This puzzle is unsolvable <====")
return False
return True
# it takes raw input and create basic structures for the program
def start_CSP(input_board, const_prop_mode):
# we start from base_node (base_node is parent of initial_node)
base_node = Node("", "", "", "", "")
is_puzzle_solved_with_game_rule, domains_list = create_domains_list(input_board)
if not is_puzzle_solved_with_game_rule:
print("This puzzle is breaking game rule")
return
initial_node = Node(input_board, base_node, domains_list, '', '') # initial node have parent => base_node
CSP_Backtracking(initial_node, const_prop_mode, 'start')
def CSP_Backtracking(node, const_prop_mode, csp_mode):
# check we arrive to node_base or not (when we arrive to node_base, puzzle is unsolvable)
if not is_solvable(node):
return
is_finished = check_all_rule_game(node)
if is_finished:
print('\n\n*************************** SOLVED PUZZLE *************************\n')
print_board(node.board)
return
print("**********************************************************")
print('***** Before MRV *****')
print_board(node.board)
not_empty = Heuristic.MRV(node, csp_mode)
if not not_empty:
# here we should go to parent node
print(" =====> BACKTRACKING <===== ")
CSP_Backtracking(node.parent, const_prop_mode, 'continue')
else:
print("***** After MRV *****")
new_variables_domain = copy.deepcopy(node.variables_domain)
x, y = node.assigned_variable
new_variables_domain[x][y] = node.assigned_value
new_board = copy.deepcopy(node.board)
new_board[x][y] = node.assigned_value
print("(MRV) => assigned variable {} = {}".format(node.assigned_variable, node.assigned_value))
print_board(new_board)
print("**********************************************************")
if const_prop_mode == 'forward-checking':
# print('var domains node ghable forward:\n')
# for i in new_variables_domain:
# print(i)
flag, variables_domain = Propagation.forward_checking(new_variables_domain)
# print("after FC flag is ", flag)
# print("var domains node after forward: \n")
# for i in variables_domain:
# print(i)
# print('after FC: ', node.variables_domain)
elif const_prop_mode == 'MAC':
flag, variables_domain = Propagation.MAC(new_variables_domain, node.assigned_variable)
if flag:
# continue solving the puzzle
print('***** Continue solving puzzle *****')
child_node = Node(new_board, node, variables_domain, '', '')
CSP_Backtracking(child_node, const_prop_mode, 'continue')
elif not flag and len(node.variables_domain[x][y]) == 0:
# backtracking
print('!!! Domain is empty ====> BACKTRACKING')
# print("node parent variables")
# print(node.parent.variables_domain)
CSP_Backtracking(node.parent, const_prop_mode, 'backtracking')
else:
# new values for assigned_variable should be considered
print(" ==> Change last assigned variable value <== ")
CSP_Backtracking(node, const_prop_mode, 'samevar')