2017-02-14 14 views
1

次のコードでValueErrorが発生する理由を説明できますか?numpy配列をヒープキューに追加する

import heapq 
import numpy as np 

a = np.ones((2, 2), dtype=int) 

states = [] 
heapq.heappush(states, (0, a)) 
heapq.heappush(states, (0, a.copy())) 

エラーメッセージは次のとおりです。

Traceback (most recent call last): 
    File "x.py", line 8, in <module> 
    heapq.heappush(states, (0, a.copy())) 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

は、ヒープが正常に動作しますa.copy()に追加することなく、それを実行すると、それに続く/秒1は、いくつかの理由で問題のためです。 [True, False, True]の配列を持つ未知の真理値面があり、それでTrueまたはFalseという単一のものを特定することはできませんが、なぜheapqでそれを行う必要があるのですか?特に後者の場合のみ?

+1

ヒープ要素を比較する必要があるheapq。ヒープ要素はタプルであり、タプルの最初のエントリは等しいので、2番目の要素を比較します。 2番目の要素を比較しても、ブール値として解釈できるものはありません。 – user2357112

+0

'heapq.heappush(heap、(x、y))'は、 '' x''を優先してプッシュ 'y'を意味するわけではありません。それは "プッシュ事'(x、y) '"を意味します。別の優先事項と要素はありません。要素があります。 – user2357112

答えて

2

TL; DR:複数の要素が含まれている場合、numpy配列をブール値にキャストできないためです。


ヒープに関するいくつかの情報:

ヒープ「注文」その内容(その項目が<を実装する必要がありますが、それは実装の詳細です)。

ただし、最初の要素は値で、2番目の要素は配列で、項目にはtupleを作成してheapに項目を挿入します。

タプルを比較すると、最初のアイテムが等しいかどうかが最初にチェックされ、2番目のアイテムが等しくないかどうかがチェックされ、等しくなければ小さい場合(操作が<だった場合)より大きい(>の場合)。しかし、タプルはC言語で実装されており、==のチェックには、Pythonのものと少し違います。それはPyObject_RichCompareBoolを使用します。特にo1o2が同じオブジェクトである場合は、「ノート」は、ここで

重要であり、PyObject_RichCompareBool()は常にPy_NEためPy_EQのための1と0を返します。今

のはnumpyの配列に行ってみましょう:ifチェックが暗黙的に条件を変換し

>>> arr = np.array([1,2,3]) 
>>> bool(arr) 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

:それは複数の項目が含まれている場合は、boolnumpy.arrayを変換することはできません

ブール値:

>>> if arr: pass 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

numpy-arra YS彼らはまだnumpyの配列です:だからこれらは==で評価することはできません

>>> arr > arr 
array([False, False], dtype=bool) 
>>> arr == arr 
array([ True, True], dtype=bool) 

>>> if arr == arr: pass 
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

だからあなたはブール値に複数の要素でnumpyの-配列を変換することはできません!しかし、今興味深い部分があります:heapq - モジュールPyObject_RichCompareBool()を使用するので、2つの配列が等しいかどうかを確認できますが、の場合はが同じ場合に限り一致します。それが何回かに渡された同じ配列で動作しますが、あなたはそれをコピーするとき、それが失敗した理由です

>>> arr is arr 
True 
>>> arr is arr.copy() 
False 
+0

"ヒープは安定しており、その内容を"注文 "しています...等しいと比較するアイテムは、元々の順序と同じです。" - あなたは何を話していますか? heapqはそのことをまったく保証しておらず、あなたが記述する値位置タプルをしません。あなたがその行動を望むなら、あなたはそれを自分で行う必要があります。 – user2357112

+0

@ user2357112コメントをいただきありがとうございます、私は答えを修正しました。 – MSeifert

関連する問題