-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoptimal_solver.py
More file actions
137 lines (109 loc) · 4.04 KB
/
Copy pathoptimal_solver.py
File metadata and controls
137 lines (109 loc) · 4.04 KB
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
135
136
137
"""
turn: 0: white, 1: black
piece: -1: black, 0: space, 1: white, 2: obstacle
"""
import math
import config
import numpy as np
from collections import defaultdict
def comb(n, k):
a = 1
for i in range(n - k + 1, n + 1):
a *= i
return a // math.factorial(k)
allowed_rows_cols = {x: defaultdict(dict) for x in config.supported_model}
side_combinations = {}
position_combinations = {}
obstacles_combinations = {}
piece_position_table = {}
inv_piece_position_table = {}
side_position_table = {}
inv_side_position_table = {}
def make_position_table(t, comb_num, limit):
k = list(range(t))
position_table = []
inv_position_table = {}
for i in range(comb_num):
position_table.append(k.copy())
inv_position_table.update({frozenset(k.copy()): i})
for j in range(t - 1, -1, -1):
if k[j] < limit - (t - j):
k[j] += 1
for h in range(j + 1, t):
k[h] = k[h - 1] + 1
break
else:
if j > 0 and k[j - 1] + 1 < k[j] - (t - j):
k[j - 1] = k[j - 1] + 1
for h in range(j, t):
k[h] = k[h - 1] + 1
break
# print(position_table, len(position_table))
return position_table, inv_position_table
# return 1d state with respect to state number
def num_to_state(n, rows, cols):
state = [0] * rows * cols
turn = n % 2
n //= 2
position_num = n % position_combinations[(rows, cols)]
n //= position_combinations[(rows, cols)]
side_num = n % side_combinations[(rows, cols)]
n //= side_combinations[(rows, cols)]
obstacles_num = n
positions = piece_position_table[(rows, cols)][position_num]
whites = side_position_table[(rows, cols)][side_num]
blacks = [i for i in range(4) if i not in whites]
state[positions[whites[0]]] = state[positions[whites[1]]] = 1
state[positions[blacks[0]]] = state[positions[blacks[1]]] = -1
for i in range(rows * cols):
if state[i] in [-1, 1]:
continue
is_obstacle = obstacles_num % 2
if is_obstacle == 1:
state[i] = 2
obstacles_num //= 2
return state, turn
def state_to_num(state, turn, rows, cols, state_dim=2):
if state_dim == 2:
state = [i for j in state for i in j] # flatten
num = turn
position = []
for i in range(rows * cols):
if state[i] in [-1, 1]:
position.append(i)
position_num = inv_piece_position_table[(rows, cols)][frozenset(position)]
num += position_num * 2
side = []
tmp = 0
for i in range(rows * cols):
if state[i] == 1: # from the perspective of white
side.append(tmp)
if state[i] in [-1, 1]:
tmp += 1
side_num = inv_side_position_table[(rows, cols)][frozenset(side)]
num += side_num * 2 * position_combinations[(rows, cols)]
obstacle_num = 0
tmp = 1
for i in range(rows * cols):
if state[i] == 2:
obstacle_num += tmp
if state[i] not in [-1, 1]:
tmp *= 2
num += obstacle_num * 2 * position_combinations[(rows, cols)] * side_combinations[(rows, cols)]
return num
def load_from_disk(rows, cols, file_name='NxNoptimal_bothsides_'):
distance_to_win = np.load(f"model/{file_name}dtw_r{rows}_c{cols}.npy").tolist()
parent = np.load(f"model/{file_name}par_r{rows}_c{cols}.npy").tolist()
return distance_to_win, parent
for r, c in allowed_rows_cols:
dtw, par = load_from_disk(r, c)
print(f'loaded model: {r}x{c} {par[:5]} {dtw[:5]}')
allowed_rows_cols[(r, c)]['dtw'] = dtw
allowed_rows_cols[(r, c)]['par'] = par
side_combinations[(r, c)] = comb(4, 2)
position_combinations[(r, c)] = comb(r * c, 4)
obstacles_combinations[(r, c)] = 2 ** (r * c - 4)
piece_position_table[(r, c)], inv_piece_position_table[(r, c)] = \
make_position_table(4, position_combinations[(r, c)], r * c)
side_position_table[(r, c)], inv_side_position_table[(r, c)] = \
make_position_table(2, side_combinations[(r, c)], 4)