2017-02-14 6 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()에 추가하지 않고 그것을 실행, 후속/두 번째는 어떤 이유로 문제입니다. 나는 [True, False, True]의 배열과 함께 알 수없는 진리 값 측면이 있음을 이해한다 그에서 하나의 True 또는 False을 결정하는 것은 불가능하다고,하지만 왜 heapq은 그렇게 할 필요합니까? 특히 두 번째 경우에만?

+1

. 힙 요소는 튜플이며 튜플의 첫 번째 항목은 동일하므로 두 번째 요소를 비교합니다. 두 번째 요소를 비교해도 부울로 해석 될 수있는 것은 아닙니다. – user2357112

+0

'heapq.heappush (heap, (x, y))'는 "우선 순위가'x' 인"y "를 푸시하라는 의미가 아닙니다. 그것은 "push thing'(x, y)'"를 의미합니다. 별도의 우선 순위와 요소가 없습니다. 요소가 있습니다. – user2357112

답변

2

TL; DR : 그들은 더 이상의 요소를 포함하는 경우 NumPy와 배열은 부울에 캐스트 할 수 없기 때문에. 힙에 대한


일부 정보 :

힙을 "위하여"그 내용 (그래서 항목 <를 구현해야하지만이 구현 세부입니다).

그러나 항목에 대해 tuple을 생성하여 heap에 항목을 삽입합니다. 첫 번째 요소는 값이고 두 번째 요소는 배열입니다.

튜플을 비교하면 첫 번째 항목이 동등한 지 먼저 확인하고 둘째 항목이 같지 않을 때까지 두 번째 항목이 같은지 확인한 다음 더 작 으면 확인합니다 (작업이 < 일 때). 보다 큼 (>). 그러나 터플은 C로 구현되었고, ==은 Python에서와 약간 차이가있다. PyObject_RichCompareBool을 사용합니다. 특히 "메모"o1o2이 같은 객체

경우 여기서 중요한, PyObject_RichCompareBool() 항상 Py_NE에 대한 Py_EQ 0 1을 반환합니다. 이제

의이 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 -module는 PyObject_RichCompareBool()을 사용하므로 두 배열이 동일한 경우는 확인할 수 있지만 !그것은 여러 번에 전달 된 동일한 어레이와 함께 작동하는 이유

는 그이다 그러나 당신이 그것을 복사 할 때 그것은 실패

힙 요소를 비교할 필요가 heapq
>>> arr is arr 
True 
>>> arr is arr.copy() 
False 
+0

"힙은 안정적이며 그 내용을"주문 "합니다. 즉, 평등을 비교하는 항목은 원래와 동일한 순서로 나타납니다."- 당신은 무엇을 말하고 있습니까? heapq는 그것을 전혀 보장하지 않으며 여러분이 설명하는 value-position tuple을 수행하지 않습니다. 당신이 그 행동을 원하면, 당신 스스로해야합니다. – user2357112

+0

@ user2357112 의견을 보내 주셔서 감사 드리며 답변을 수정했습니다. – MSeifert