2011-01-27 11 views
4

私はちょうどPythonでnqueenの問題を解決しました。このソリューションでは、n個のクイーンズをnXnチェス盤に配置するためのソリューションの合計数が出力されますが、n = 15で試してみると、答えを得るのに1時間以上かかります。誰でもコードを見て、このプログラムをスピードアップするためのヒントを教えてください......初心者のpythonプログラマー。n-queenパズルを解く

#!/usr/bin/env python2.7 

############################################################################## 
# a script to solve the n queen problem in which n queens are to be placed on 
# an nxn chess board in a way that none of the n queens is in check by any other 
#queen using backtracking''' 
############################################################################## 
import sys 
import time 
import array 

solution_count = 0 

def queen(current_row, num_row, solution_list): 
    if current_row == num_row: 
     global solution_count 
     solution_count = solution_count + 1 
    else: 
     current_row += 1 
     next_moves = gen_nextpos(current_row, solution_list, num_row + 1) 
     if next_moves: 
      for move in next_moves: 
       '''make a move on first legal move of next moves''' 
       solution_list[current_row] = move 
       queen(current_row, num_row, solution_list) 
       '''undo move made''' 
       solution_list[current_row] = 0 
     else: 
      return None 

def gen_nextpos(a_row, solution_list, arr_size): 
    '''function that takes a chess row number, a list of partially completed 
    placements and the number of rows of the chessboard. It returns a list of 
    columns in the row which are not under attack from any previously placed 
    queen. 
    ''' 
    cand_moves = [] 
    '''check for each column of a_row which is not in check from a previously 
    placed queen''' 
    for column in range(1, arr_size): 
     under_attack = False 
     for row in range(1, a_row): 
      ''' 
      solution_list holds the column index for each row of which a 
      queen has been placed and using the fact that the slope of 
      diagonals to which a previously placed queen can get to is 1 and 
      that the vertical positions to which a queen can get to have same 
      column index, a position is checked for any threating queen 
      ''' 
      if (abs(a_row - row) == abs(column - solution_list[row]) 
        or solution_list[row] == column): 
       under_attack = True 
       break 
     if not under_attack: 
      cand_moves.append(column) 
    return cand_moves 

def main(): 
    ''' 
    main is the application which sets up the program for running. It takes an 
    integer input,N, from the user representing the size of the chessboard and 
    passes as input,0, N representing the chess board size and a solution list to 
    hold solutions as they are created.It outputs the number of ways N queens 
    can be placed on a board of size NxN. 
    ''' 
    #board_size = [int(x) for x in sys.stdin.readline().split()] 
    board_size = [15] 
    board_size = board_size[0] 
    solution_list = array.array('i', [0]* (board_size + 1)) 
    #solution_list = [0]* (board_size + 1) 
    queen(0, board_size, solution_list) 
    print(solution_count) 


if __name__ == '__main__': 
    start_time = time.time() 
    main() 
    print(time.time() 
+1

あなたは正しい、あなたのアルゴリズムはO(N!)であることを認識していますか?あなたが一定の要因よりも何かを得ると信じる理由はありません。 – ephemient

+1

それをチェックしていないが、ウィキはn = 14に対して45kの解があると言っている。それはexpotentialの増加であるので、n = 15の方がさらに賭けることができる。最適なアルゴリズムでは、これは複雑な問題です。あなたのものは最適ではありません)。はるかに小さいn(例えば、8)を試してください。 – delnan

+0

http://www.durangobill.com/N_Queens.htmlには、N = 26までの解決策の数が含まれています。 – 9000

答えて

5

Nクイーンズ問題に対するバックトラッキングアルゴリズムは、最悪の場合、階乗アルゴリズムです。だからN = 8、8!解の数が最悪の場合にチェックされ、N = 9がそれを9にする!などのように、可能な解の数は非常に大きく、非常に高速に増加する。あなたが私を信じていない場合は、電卓に行き、1から始まる連続した数字の倍数を始めるだけです。

幸いにも、すべての可能な解決策をチェックする必要はありません。残念なことに、正しい解の数は、依然としてほぼ階乗的な成長パターンに従います。したがって、アルゴリズムの実行時間は、階乗ペースで増加する。

すべての解決策を見つける必要があるため、プログラムのスピードアップについてはあまり効果がありません。あなたはすでに検索ツリーから不可能な枝を切り取るのに良い仕事をしています。私は大きな効果があるとは思わない。それは単に遅いアルゴリズムです。

2

ドナルドクヌスの無作為推定法を用いて解の数を推定することができます。

クイーンズが配置されていない状態から開始して、次の行の許容位置の数はnです。 ランダムに1つの位置を選択し、次の行の許容位置数(p)を計算し、これをnで倍数し、それを合計解数(合計= n * p)として格納し、次に許容されるポジション。

この行では、次の行の許容位置数(p)を計算し、これにより合計解数を合計します(合計* = p)。ボードを解くことができないか、解の数がゼロになるか、ボードが解けるまで、これを繰り返します。

これを何度も繰り返し、解の平均数(ゼロを含む)を計算します。これにより、近似を使って解の数を素早く正確に近似することができます。私は、これは理にかなって願っています

、私はあなたをお勧めし

2

)はN-クイーンズ問題の代替実装のためのPythonソースからtest_generators.py覗きます。

Python 2.6.5 (release26-maint, Sep 12 2010, 21:32:47) 
[GCC 4.4.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from test import test_generators as tg 
>>> n= tg.Queens(15) 
>>> s= n.solve() 
>>> next(s) 
[0, 2, 4, 1, 9, 11, 13, 3, 12, 8, 5, 14, 6, 10, 7] 
>>> next(s) 
[0, 2, 4, 6, 8, 13, 11, 1, 14, 7, 5, 3, 9, 12, 10] 
0

以下は私のPYTHONの実装です。より高速にPYPYを使用することもできます。

O(1)タイムメソッドを使用して、次のクイーンがすでにボードに置かれている人に攻撃されているかどうかを確認することによって、そのスピードが助けられます。

プログラムが "nqueen.py"であるとすると、それを実行する例は "python nqueen.py 6"です(6は6x6ボードのサイズです)。

#!/bin/python 
# 
# TH @stackoverflow, 2016-01-20, "N Queens" with an O(1) time method to check whether the next queen is attacked 
# 
import sys 


board_size = int(sys.argv[1]) 
Attacked_H = { i:0 for i in range(0, board_size) } 
Attacked_DU = { i:0 for i in range(0, board_size*2) } 
Attacked_DD = { i:0 for i in range(-board_size, board_size) } 


def nqueen(B, N, row, col): 
    if(row >= N): 
     return 1 
    if(col >= N): 
     print "board:\n" + str.join("\n", ["_|"*q + "Q|" + "_|"*(board_size - q - 1) for q in B]) 
     return 0 
    B[col] = row 
    if(0==(Attacked_H[row] + Attacked_DU[row+col] + Attacked_DD[row-col])): 
     [Attacked_H[row], Attacked_DU[row+col], Attacked_DD[row-col]] = [ 1,1,1 ] 
     nqueen(B, N, 0, col + 1) 
     [Attacked_H[row], Attacked_DU[row+col], Attacked_DD[row-col]] = [ 0,0,0 ] 
    nqueen(B, N, row + 1, col) 


nqueen(list(range(0, board_size)), board_size, 0, 0) 
0

遺伝的アルゴリズムでもn-queensを解くことができます。これは、edXコースColumbiaXの講義の1つであるhttps://youtu.be/l6qll5OldHQに記述されています.CSMM.101x人工知能(AI)。

目的関数は、攻撃していないクイーン対の数を最適化しようとします。 以下のアニメーションは、n = 20のRのソリューションの例を示しています。遺伝的アルゴリズムを用いてn-queensを解く方法の詳細については、https://sandipanweb.wordpress.com/2017/03/09/solving-the-n-queen-puzzle-with-genetic-algorithm-in-r/?frame-nonce=76cf9b156aを参照してください。

enter image description here

関連する問題