python, numpy boolean array: negation in where statement
Question: with:

    
    
    import numpy as np
    array = get_array()
    

I need to do the following thing:

    
    
    for i in range(len(array)):
        if random.uniform(0, 1) < prob:
            array[i] = not array[i]
    

with array being a numpy.array.

I wish I could do something similar to:

    
    
    array = np.where(np.random.rand(len(array)) < prob, not array, array)
    

but I obtain the following result (referring to 'not array'):

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

Why can I take the value of array but not its negation?

Currently I solved with:

    
    
    array = np.where(np.random.rand(len(array)) < prob, - array + 1, array)
    

but it looks really clumsy to me.

Thank you for your help

p.s.: I don't care if the statement modifies array or not. I just need the
result of the operation.

just another question: I want to do this change for 2 reasons: readability and
efficiency. Is there a real performance improvement with it? Thank you again


Answer: I suggest using

    
    
    array ^= numpy.random.rand(len(array)) < prob
    

This is probably the most efficient way of getting the desired result. It will
modify the array in place, using "xor" to invert the entries which the random
condition evaluates to `True` for.

> Why can I take the value of array but not its negation?

You can't take the truth value of the array either:

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

The `not` operator implicitly tries to convert its operand to `bool`, and then
returns the opposite truth value. It is not possible to overload `not` to
perform any other behaviour. To negate a NumPy array of `bool`s, you can use

    
    
    ~array
    

or

    
    
    numpy.logical_not(array)
    

or

    
    
    numpy.invert(array)
    

though.

