[解決済み】再帰:反復中にPythonのset changed setを回避する方法 RuntimeError
質問
背景と問題の説明
私はグラフの色付け問題(広義には無向グラフに「色」を割り当て、エッジで結ばれた2つの頂点が同じ色にならないようにする問題)を解くコードをいくつか持っています。標準的な再帰的バックトラックアルゴリズムの効率を向上させるために、制約伝搬を用いた解法を実装しようとしているのですが、次のようなエラーに遭遇しています。
File "C:\Users\danisg\Desktop\coloring\Solver.py",
line 99, in solve
for color in self.domains[var]:
RuntimeError: Set changed size during iteration
ここでは、各頂点に対して
set
を、その特定の頂点に可能な特定の値で表現します。
self.domains = { var: set(self.colors) for var in self.vars }
割り当てた後、この制約を隣接するドメインに伝搬させ、探索空間を限定するのです。
for key in node.neighbors: # list of keys corresponding to adjacent vertices
if color in self.domains[key]: # remove now to prune possible choices
self.domains[key].remove(color)
これは、実際にエラーが投げられた場所ではない(私のコードでは、問題が発生した場所を
try-except
ブロック)ですが、問題の原因である可能性があります。
私の質問です。
私は正しい考えを持っているのだろうか、ここで、正しい実装ではないにしても?もっと言えば、どうすればこれを修正できるのでしょうか?また、別の
domains
の辞書を参照してください。それとも
{コード
をグラフの各ノードのプロパティにすることはできますか?
私のコード
以下は
domain
関数で、このコードが呼び出されます。
solve
私の実装では
def solve(self):
uncolored = [var for var in self.vars if self.map[var].color == None]
if len(uncolored) == 0:
return True
var = min(uncolored, key = lambda x: len(self.domains[var]))
node = self.map[var]
old = { var: set(self.domains[var]) for var in self.vars }
for color in self.domains[var]:
if not self._valid(var, color):
continue
self.map[var].color = color
for key in node.neighbors:
if color in self.domains[key]:
self.domains[key].remove(color)
try:
if self.solve():
return True
except:
print('happening now')
self.map[var].color = None
self.domains = old
return False
オブジェクトを作成します。
Node
その他に使っている/役にたっている機能を2つ紹介します。
プレclass Solver:
class Node:
def __init__(self, var, neighbors, color = None, domain = set()):
self.var = var
self.neighbors = neighbors
self.color = color
self.domain = domain
def __str__(self):
return str((self.var, self.color))
def __init__(self, graph, K):
self.vars = sorted( graph.keys(), key = lambda x: len(graph[x]), reverse = True ) # sort by number of links; start with most constrained
self.colors = range(K)
self.map = { var: self.Node(var, graph[var]) for var in self.vars }
self.domains = { var: set(self.colors) for var in self.vars }
コードが失敗しているデータと例
私が使っているグラフの例は、以下の通りです。 こちら .
データを読み込むための関数です。
def validate(self):
for var in self.vars:
node = self.map[var]
for key in node.neighbors:
if node.color == self.map[key].color:
return False
return True
def _valid(self, var, color):
node = self.map[var]
for key in node.neighbors:
if self.map[key].color == None:
continue
if self.map[key].color == color:
return False
return True
次のように呼び出す必要があります。
def read_and_make_graph(input_data):
lines = input_data.split('\n')
first_line = lines[0].split()
node_count = int(first_line[0])
edge_count = int(first_line[1])
graph = {}
for i in range(1, edge_count + 1):
line = lines[i]
parts = line.split()
node, edge = int(parts[0]), int(parts[1])
if node in graph:
graph[node].add(edge)
if edge in graph:
graph[edge].add(node)
if node not in graph:
graph[node] = {edge}
if edge not in graph:
graph[edge] = {node}
return graph
解決するには?
問題はここだと思うのですが。
file_location = 'C:\\Users\\danisg\\Desktop\\coloring\\data\\gc_50_3'
input_data_file = open(file_location, 'r')
input_data = ''.join(input_data_file.readlines())
input_data_file.close()
graph = read_and_make_graph(input_data)
solver = Solver(graph, 6) # a 6 coloring IS possible
print(solver.solve()) # True if we solved; False if we didn't
もし
for color in self.domains[var]:
if not self._valid(var, color):
continue
self.map[var].color = color
for key in node.neighbors:
if color in self.domains[key]:
self.domains[key].remove(color) # This is potentially bad.
いつ
key == var
が呼ばれると、現在反復しているセットのサイズを変更することになります。これを避けるには
self.domains[key].remove(color)
copy() を使用すると、元のセットから項目を削除しながら、そのコピーに対して反復処理を行うことができます。
関連
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】Python: OverflowError: 数学の範囲エラー
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] Pythonでファイルやフォルダを削除する方法は?
-
[解決済み] Pythonで文字列の部分文字列を取得するにはどうすればよいですか?
-
[解決済み] pipでPythonの全パッケージをアップグレードする方法
-
[解決済み] Pythonで文字列を小文字にするには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonの非常に便利な2つのデコレーターを解説
-
Python カメの描画コマンドとその例
-
Python jiabaライブラリの使用方法について説明
-
[解決済み】ImportError: sklearn.cross_validation という名前のモジュールがない。
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】pygame.error: ビデオシステムが初期化されていない
-
[解決済み】「SyntaxError.Syntax」は何ですか?Missing parentheses in call to 'print'」はPythonでどういう意味ですか?
-
[解決済み】IndexError: invalid index to scalar variableを修正する方法
-
[解決済み】ValueError: pickleプロトコルがサポートされていません。3、python2 pickleはpython3 pickleでダンプしたファイルを読み込むことができない?
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。