Исходный код:
from copy import deepcopy
import time
class Node:
def __init__(self):
self.state = \
[['8', '7', '3'],
['1', '5', '6'],
['4', '2', ' ']]
self.x = 2
self.y = 2
self.iter = 1
self.unique = 1
self.action = None
states.update({self.get_string(): self.iter})
# self.states = {}
# self.states.update({self.get_string(): self.iter})
def perform_action(self, action: str):
if action == 'right':
self.state[self.x][self.y] = self.state[self.x][self.y - 1]
self.state[self.x][self.y - 1] = ' '
self.y -= 1
elif action == 'left':
self.state[self.x][self.y] = self.state[self.x][self.y + 1]
self.state[self.x][self.y + 1] = ' '
self.y += 1
elif action == 'up':
self.state[self.x][self.y] = self.state[self.x + 1][self.y]
self.state[self.x + 1][self.y] = ' '
self.x += 1
elif action == 'down':
self.state[self.x][self.y] = self.state[self.x - 1][self.y]
self.state[self.x - 1][self.y] = ' '
self.x -= 1
self.iter += 1
self.action = action
if self.get_string() not in states.keys():
states.update({self.get_string(): self.iter})
else:
self.unique = 0
def out_node(self):
for i in range(len(self.state)):
print(*self.state[i])
def get_state(self):
return self.state
def get_string(self) -> str:
s = ''
for i in range(len(self.state)):
s += ''.join(self.state[i])
return s
def available_actions(self) -> list:
actions = []
if 0 <= self.x <= 1:
actions += ['up']
if 1 <= self.x <= 2:
actions += ['down']
if 1 <= self.y <= 2:
actions += ['right']
if 0 <= self.y <= 1:
actions += ['left']
return actions
states = {}
looked_string = '12345678 '
def get_indexes(string):
node = [[0, 0] for i in range(9)]
for i in range(9):
if looked_string[i] == ' ':
value = '9'
else:
value = looked_string[i]
value = int(value)-1
node[i][0] = value // 3
node[i][1] = value % 3
return node
looked_node = get_indexes(looked_string)
class TreeNode:
def __init__(self, data: Node, parent):
self.data = data
self.children = []
self.parent = parent
self.h = {1: self.count_h1(), 2: self.count_h2()}
def add_child(self, child_node):
self.children.append(child_node)
def get_node(self):
return self.data
def count_h1(self):
h1 = 0
curr_string = self.data.get_string()
for i in range(len(looked_string)):
h1 += curr_string[i] != looked_string[i]
return h1
def count_h2(self):
h2 = 0
for x in range(3):
for y in range(3):
value = self.data.get_state()[x][y]
if value == ' ': value = '9'
value = int(value) - 1
ind_x, ind_y = looked_node[value]
h2 += abs(x - ind_x) + abs(y - ind_y)
return h2
def A_star(h_type: int, debug_value):
root = TreeNode(Node(), None)
states.clear()
open_set = [root]
found = False
it = 0
while not found:
current_node = min(open_set, key=lambda x: x.h[h_type] + x.get_node().iter)
if debug_value == 1:
print(f"\n---- Step {it} ----")
current_node.get_node().out_node()
print(f"Tree depth: {current_node.get_node().iter}")
print(f"Heuristic value for this field: {current_node.h[h_type] + current_node.get_node().iter}")
open_set.remove(current_node)
if current_node.get_node().get_string() == looked_string:
print("Final state achieved!")
print(f"Iterations amount: {it}")
print(f"Tree depth: {current_node.get_node().iter}")
print(f"Unique states amount: {len(states)}")
return current_node
it += 1
actions = current_node.get_node().available_actions()
if debug_value == 1:
print("\nFound nodes on this step:")
for action in actions:
new_node = deepcopy(current_node.get_node())
new_node.perform_action(action)
if debug_value == 1:
print(f"Action = {new_node.action}")
new_node.out_node()
temp_tree_node = TreeNode(new_node, None)
print(f"Heuristics for this node: {temp_tree_node.h[h_type] + new_node.iter}")
if new_node.unique:
new_tree_node = TreeNode(new_node, current_node)
current_node.add_child(new_tree_node)
open_set.append(new_tree_node)
if debug_value == 1:
print("This state is unique, added to the tree")
elif debug_value == 1:
print("This state is not unique, it will not be checked")
if debug_value == 1:
print("Press enter to continue or type in 0 to skip to the final step")
a = input()
if a == "0":
debug_value = 0
mode = -1
while mode != 0:
mode = input('''1 - A* with h1
2 - A* with h2
Your choice: ''')
if mode == "1" or mode == "2":
steps = input("Type in 1 to see steps, type in anything else to hide steps: ")
start_time = time.time()
result = A_star(int(mode), int(steps))
print("--- %s seconds ---" % (time.time() - start_time))
else:
break
