如何解决数独求解器具有约束满足的回溯迭代 DFS
我正在尝试使用具有回溯和约束满足的迭代 DFS 算法编写数独求解器。
def sudoku_solver(sudoku):
states = []
ste_Hsh = set()
visited = []
novisited = 0
states.append(sudoku)
ste_Hsh.add(str(sudoku))
visited.append(False)
r = findRemaining(sudoku)
while not all(visited):
if isSolved(sudoku):
return sudoku
if not visited[novisited]:
sudoku,r = pickValAndProp(findNewPos(sudoku,r),sudoku.copy(),r,ste_Hsh)
else:
try:
novisited = len(visited) - visited[::-1].index(False) -1
except:
break
sudoku = states[novisited]
if isinstance(sudoku,int):
visited[novisited] = True
try:
novisited = len(visited) - visited[::-1].index(False) -1
except:
break
sudoku = states[novisited]
r = findRemaining(sudoku)
continue
ste_Hsh.add(str(sudoku))
if len(ste_Hsh) > len(states):
if novisited == len(states)-1:
states.append(sudoku)
visited.append(False)
else:
states[novisited+1] = sudoku
visited[novisited+1] = False
novisited += 1
return np.full((9,9),-1,dtype=int)
这是我的求解器函数。
findRemaining()
返回每行 (r[2])、列 (r[1]) 和正方形 (3x3 网格) (r[0]) 的剩余可能值列表。
findNewPos()
返回要填充的下一个位置,它通过查找具有最小可能值的单元格(使用行、列和正方形的剩余值的总长度的复合度量进行评估)来完成单元格在)
pickValAndProp
是传播算法,见下文:
def pickValAndProp(new_pos,sudoku,ste_Hsh):
try:
val = 0
tried = set()
noOfStates = len(ste_Hsh)
i = 0
while noOfStates == len(ste_Hsh):
val = r[1][new_pos[1]][i]
if val in r[0][locateSquareOfPos(new_pos,sudoku)] and val in r[2][new_pos[0]]:
sudoku[new_pos[0]][new_pos[1]] = val
ste_Hsh.add(str(sudoku))
else:
tried.add(val)
if(len(tried) == len(r[1][new_pos[1]])):
return (-1,-1)
i+=1
print("no of States :",noOfStates)
#remove from square
r[0][locateSquareOfPos(new_pos,sudoku)].remove(val)
#remove from col
r[1][new_pos[1]].remove(val)
#remove from row
r[2][new_pos[0]].remove(val)
return (sudoku,r)
except:
return (-1,-1)
该算法在解决简单/中等问题时表现良好,但对于困难问题,它将永远持续下去。董事会的独特状态数量达到 100,000。
编辑:问题出在 findNewPos()
。我的启发式不正确。
这是更新的版本:
def findNewPos(sudoku,r):
new_pos = [-1,-1]
no_r = 10
deg_h = 100
for i in range(sudoku.shape[0]):
for j in range(sudoku.shape[1]):
if sudoku[i][j] == 0:
common = np.intersect1d(r[0][locateSquareOfPos([i,j],sudoku)]\,np.intersect1d(r[2][i],r[1][j]))
if len(common) == 0:
return [-1,-1]
if len(common) < no_r:
no_r = len(common)
deg_h = len(r[0][locateSquareOfPos(new_pos,sudoku)])\
+len(r[1][j]) + len(r[2][i])
new_pos = [i,j]
elif len(common) == no_r:
rmng = len(r[0][locateSquareOfPos(new_pos,sudoku)])\
+len(r[1][j]) + len(r[2][i])
if rmng < deg_h:
deg_h = rmng
new_pos = [i,j]
return new_pos
现在所有数独都在解决,尽管速度很慢。我需要改进我的 tiebreaker 启发式(当有多个变量的剩余值相同时),并且我想使用度数启发式。但是,我不确定这在数独的上下文中会如何工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。