Я решил изучить смоделированный отжиг как новый метод для атаки this problem. Он по существу спрашивает, как заполнить сетку -1, 0 или 1, чтобы каждая сумма строк и столбцов была уникальной. В качестве тестового примера я использовал 6x6 сетку, для которых, безусловно, является оптимальным решение дается Neil:Имитированный отжиг не возвращает оптимального решения
1 1 1 1 1 1 6
1 1 1 1 1 -1 4
1 1 1 1 -1 -1 2
1 1 0 -1 -1 -1 -1
1 0 -1 -1 -1 -1 -3
0 -1 -1 -1 -1 -1 -5
5 3 1 0 -2 -4
Моего код обычно не доходит до оптимального случая большинства трасс и даже возвращает неправильную сетку стоимость (old_cost
должна соответствовать count_conflict(grid)
). Неправильно ли установлены мои параметры, неправильно ли я реализован или, возможно, имитирован отжиг, а не жизнеспособный метод?
import random
from math import exp
G_SIZE = 6
grid = [[1]*G_SIZE for i in range(G_SIZE)]
def count_conflict(grid):
cnt = [0]*(2*G_SIZE+1)
conflicts = 0
for row in grid:
cnt[sum(row)] += 1
for col in zip(*grid):
cnt[sum(col)] += 1
#print(cnt)
for c in cnt:
if c == 0: conflicts += 1
if c > 1: conflicts += c-1
return conflicts
def neighbor(grid):
new_grid = grid[:]
i = random.choice(range(G_SIZE))
j = random.choice(range(G_SIZE))
new_cells = [-1, 0, 1]
new_cells.remove(new_grid[i][j])
new_grid[i][j] = random.choice(new_cells)
return new_grid
def acceptance_probability(old_cost, new_cost, T):
if new_cost < old_cost: return 1.0
return exp(-(new_cost - old_cost)/T)
# Initial guess
for i in range(1, G_SIZE):
for j in range(0, i):
grid[i][j] = -1
#print(grid)
old_cost = count_conflict(grid)
T = 10.0
T_min = 0.1
alpha = 0.99
while T > T_min:
for i in range(1000):
new_sol = neighbor(grid)
new_cost = count_conflict(new_sol)
ap = acceptance_probability(old_cost, new_cost, T)
print(old_cost, new_cost, ap, T)
if ap > random.random():
grid = new_sol
old_cost = new_cost
T *= alpha
for row in grid:
print(row)
print(count_conflict(grid))
Как бы то ни было, я думаю, что базовая проблема должна быть опубликована на математическом вопроснике, так как кажется, что вы можете перевести эту проблему в группу связанных уравнений с несколькими переменными, которая переносится в вычисление матриц. – DainDwarf
Я уверен, что SA не предоставляет никаких гарантий поиска глобального минимума. Чем больше раз вы бросаете кости, тем больше вероятность того, что вы обнаружите ее при некоторых обстоятельствах. Играйте со своим охлаждающим профилем. Это то, что вам нужно сделать полу-вручную, по крайней мере, вначале. Можете ли вы сравнить свою рутину с чем-то известным - почему бы не работать параллельно с 'scipy.optimize.anneal' и сравнивать поведение. – uhoh
@uhoh Я поиграл с параметрами, но программа обычно останавливается как можно меньше намеченной цели. Поскольку имитированный отжиг работает с проблемой N queens, я надеялся, что это сработает здесь. – qwr