使用多处理的数独解决方案

Posted

技术标签:

【中文标题】使用多处理的数独解决方案【英文标题】:Sudoku Solution Using Multiprocessing 【发布时间】:2020-12-13 09:09:58 【问题描述】:

我尝试了使用回溯的数独解决方案,但要花费 12 秒左右的时间才能给出输出。我试图实现一种多处理技术,但它比回溯花费更多的时间。我从来没有完全运行过它太慢了。请建议我错过了什么?如果有人也能告诉我如何通过我的 GPU 运行它,那就更好了。 (使用 CUDA)。

import concurrent.futures
import copy

A = [[0]*9 for _ in range(9)]
A[0][6] = 2
A[1][1] = 8
A[1][5] = 7
A[1][7] = 9
A[2][0] = 6
A[2][2] = 2
A[2][6] = 5
A[3][1] = 7
A[3][4] = 6
A[4][3] = 9
A[4][5] = 1
A[5][4] = 2
A[5][7] = 4
A[6][2] = 5
A[6][6] = 6
A[6][8] = 3
A[7][1] = 9
A[7][3] = 4
A[7][7] = 7
A[8][2] = 6

Boards = [A]

L = []
for i in range(9):
    for j in range(9):
        if A[i][j] == 0:
            L.append([i,j])
            
def RC_Check(A,Value,N):
    global L
    i,j = L[N]
    
    for x in range(9):
        if A[x][j] == Value:
            return False
        if A[i][x] == Value:
            return False
    return True

def Square_Check(A,Value,N):
    global L
    i,j = L[N]
    
    X, Y = int(i/3)*3,int(j/3)*3
    for x in range(X,X+3):
        for y in range(Y,Y+3):
            if A[x][y] == Value:
                return False
    return True

def New_Boards(Board,N):
    global L
    i,j = L[N]

    Boards = []
    with concurrent.futures.ProcessPoolExecutor() as executor:
        RC_Process = executor.map(RC_Check,[Board]*10,list(range(1,10)),[N]*10)
        Square_Process = executor.map(Square_Check,[Board]*10,list(range(1,10)),[N]*10)

        for Value, (RC_Process, Square_Process) in enumerate(zip(RC_Process,Square_Process)):
            if RC_Process and Square_Process:
                Board[i][j] = Value+1
                Boards.append(copy.deepcopy(Board))

    return Boards

def Solve_Boards(Boards,N):
    Results = []
    with concurrent.futures.ProcessPoolExecutor() as executor:
        Process = executor.map(New_Boards,Boards,[N]*len(Boards))

        for new_boards in Process:
            if len(new_boards):
                Results.extend(new_boards)

    return Results

if __name__ == "__main__":
    N = 0
    while N < len(L):
        Boards = Solve_Boards(Boards,N)
        N+=1
        print(len(Boards),N)
print(Boards)

【问题讨论】:

【参考方案1】:

多重处理不是灵丹妙药。在大多数情况下,回溯比并行穷举搜索更有效。我尝试在我的电脑上运行这段代码,它有 32 核 64 线程,但是需要很长时间。

你想用GPGPU来解决这个问题,但我不适合,因为板子的状态取决于之前的状态,所以不能有效地拆分计算。

【讨论】:

非常感谢您的澄清,但由于大部分时间都在计算下一个可用板。我们可以每次使用 GPU 并行计算那些下一个可用的板,直到找到解决方案。那会不会有效?我认为 GPU 要快得多,因此在 GPU 上运行它应该能够节省大量时间。或者即使我们这样做,它会比回溯花费更长的时间? 我不是这个领域的专家,但我认为数独输入模式的数量远远超过 GPU 单元的数量。即使QUADRO RTX 8000 也只有 4,608 个内核。另一方面,Sudoku solutions are 6\.67×10^21 如果彻底搜索。能做到的,肯定只有量子计算机了。

以上是关于使用多处理的数独解决方案的主要内容,如果未能解决你的问题,请参考以下文章

操作系统作业数独解决方案验证器(利用多线程解决)

具有回溯的数独求解器不能总是检测到多个解决方案

LeetCode 36 有效的数独

LeetCode 36 有效的数独

算法初涉-解决比9*9数独更复杂的结构

如何将对象的唯一副本存储在列表中,在这种情况下是一个半解决的数独单元格的锯齿状数组