1

node in children is always false but in the debugger:

(pdb) children.keys()
...
turn: 1, last: (5, 2), hash: 5837165650205296398,
...
(pdb) node
turn: 1, last: (5, 2), hash: 5837165650205296398
(pdb) node in children
False
(pdb) node.__eq__(node)
True

heres the function.

def _select(node):
    path = []
    global new, terminals, found
    while True:
        path.append(node)
        if node not in children: new += 1;return path
        if not children[node]: terminals += 1;return path;
        unexplored = children[node] - children.keys()
        if unexplored:
            found += 1
            n = unexplored.pop() # ignore best path?
            path.append(n)
            return path
        # node = _uct_select(node)
        else: node = choice(tuple(children[unexplored]))

and here's the hash() and eq() functions

    def __hash__(self):
        "Nodes must be hashable"
        return hash(tuple(self.board.flatten() ))

    def __eq__(node1, node2):
        "Nodes must be comparable"
        return node1.board is node2.board

board is just a [6,7] array

Saxt
  • 27
  • 5
  • It seems unlikely your nodes are equal, as I don't think `node1.board is node2.board` would be true - however, it is impossible to tell without knowing more about how nodes are constructed. – Amadan Aug 19 '19 at 08:51
  • Did you really mean `node1.board is node2.board` rather than `node1.board == node2.board`? – Thomas Aug 19 '19 at 08:51
  • @Amadan it does produce true though. I've added that to the question – Saxt Aug 19 '19 at 08:53
  • @Thomas using "==" produces a boolean array, whereas "is" produces a single boolean – Saxt Aug 19 '19 at 08:54
  • Of course `node.__eq__(node)`. Construct two _different but equal_ nodes and try it. e.g. `foo = object(); foo is foo` has a very different semantics than `object() is object()`. – Amadan Aug 19 '19 at 08:54
  • @Amadan but ``__eq__()`` only checks the board, and ``__hash()__`` only uses the board, so it's not possible for ``__eq__()`` to be false if they have the same board. I assume that ``in dict`` uses ``__eq__()``? – Saxt Aug 19 '19 at 08:57
  • @Thomas it doesn't return a boolean array, since I used ``board is board`` instead of ``board == board``. the latter creates an array – Saxt Aug 19 '19 at 09:00
  • 1
    You are using `is` check. That means `__eq__` will be true only if the two have the _same_ board, not if they have the _different but identical_ board. To reiterate my example from before, `[1, 2] is [1, 2]` returns false. – Amadan Aug 19 '19 at 09:00
  • https://stackoverflow.com/help/minimal-reproducible-example – bruno desthuilliers Aug 19 '19 at 09:07

2 Answers2

1

The issue is your eq function. unless they are the exact same list ie. their object ids are equal is will return false. is is not the same as ==

board_b  = [6,7]
board_a  = [6,7]

print(board_a is board_b)
print(board_a == board_b)

prints

False
True

see Is there a difference between "==" and "is"? for lots more info on subject

Nath
  • 748
  • 4
  • 16
  • how would I get a single boolean, instead of a boolean array? and does that mean I couldn't use ``is None`` if they are different objects either? – Saxt Aug 19 '19 at 09:04
  • I'm not sure what you mean by that question. when are you getting an array of bools? – Nath Aug 19 '19 at 09:08
  • I'm using ``some_object is None`` to see if an object is ``NoneType`` elsewhere in my code. would this always produce ``False`` if the ``NoneType`` object and ``None`` are different objects? – Saxt Aug 19 '19 at 09:15
  • `is None` is fine and is normal to use. None is keyword and functions like a singleton . `None is None` will always be true – Nath Aug 19 '19 at 09:18
1

I am guessing from your question and comments that node.board is a numpy array; it would have helped if you had mentioned that explicitly. The == operator (i.e. __eq__()) on numpy arrays indeed has some surprising behaviour: it returns a numpy array of booleans, rather than a single boolean.

>>> import numpy as np
>>> a = np.array([1, 2])
>>> b = np.array([1, 2])
>>> a == b
array([ True,  True])

But the is operator can't be used as an alternative, because these two arrays are not the same object:

>>> a is b
False

So in this case, you need to use numpy.array_equal(node1.board, node2.board):

>>> np.array_equal(a, b)
True
Thomas
  • 174,939
  • 50
  • 355
  • 478