Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-14 Thread Sebastian Walter
I've written a self-contained example that shows that numpy indeed
tries to call the __float__ method.
What is buggy is what happens if calling the __float__ method raises
an Exception.
Then numpy  assumes (in this case wrongly) that the object should be
casted to the neutral element.

I'd guess that  the __float__ method is called somewhere in a try:
statement and if an exception is raised it is casted to the neutral
element.
I've tried to locate the corresponding code in the numpy sources but I
got lost. Could someone be so kind and point me to it?


 start code --

import numpy

print 'numpy.__version__ = ',numpy.__version__

class ad1:

def __init__(self,x):
self.x = x

def __mul__(self,other):
if not isinstance(other, self.__class__):
return self.__class__(self.x * other)
return self.__class__(self.x * other.x)

def __rmul__(self,other):
return self * other

def __float__(self):
raise Exception('this is not possible')

def __str__(self):
return str(self.x)

print '\nThis example yields buggy behavior:'
x1 = numpy.array([ad1(1.), ad1(2.), ad1(3.)])
y1 = numpy.random.rand(3)
print 'y1= ',y1
print 'x1= ',x1
z1 = x1 * y1
y1 *= x1# this should call the __float__ method of ad1
which would raise an Exception
print 'z1=x1*y1',z1
print 'y1*=x1  ',y1

class ad2:

def __init__(self,x):
self.x = x

def __mul__(self,other):
if not isinstance(other, self.__class__):
return self.__class__(self.x * other)
return self.__class__(self.x * other.x)

def __rmul__(self,other):
return self * other

def __float__(self):
return float(self.x)

def __str__(self):
return str(self.x)

print '\nThis example works fine:'
x2 = numpy.array([ad2(1.), ad2(2.), ad2(3.)])
y2 = numpy.random.rand(3)
print 'y2= ',y2
print 'x2= ',x2
z2 = x2 * y2
y2 *= x2# this should call the __float__ method of ad1
which would raise an Exception
print 'z2=x2*y2',z2
print 'y2*=x2  ',y2


 end code --

 output -
wal...@wronski$ python
wrong_casting_object_to_float_of_augmented_assignment_statements.py
numpy.__version__ =  1.3.0

This example yields buggy behavior:
y1=  [ 0.15322371  0.47915903  0.81153995]
x1=  [1.0 2.0 3.0]
z1=x1*y1 [0.153223711127 0.958318053803 2.43461983729]
y1*=x1   [ 0.15322371  0.47915903  0.81153995]

This example works fine:
y2=  [ 0.49377037  0.60908423  0.79772095]
x2=  [1.0 2.0 3.0]
z2=x2*y2 [0.493770370747 1.21816846399 2.39316283707]
y2*=x2   [ 0.49377037  1.21816846  2.39316284]
 end  output -

On Tue, Jan 12, 2010 at 7:38 PM, Robert Kern  wrote:
> On Tue, Jan 12, 2010 at 12:31, Sebastian Walter
>  wrote:
>> On Tue, Jan 12, 2010 at 7:09 PM, Robert Kern  wrote:
>>> On Tue, Jan 12, 2010 at 12:05, Sebastian Walter
>>>  wrote:
 Hello,
 I have a question about the augmented assignment statements *=, +=, etc.
 Apparently, the casting of types is not working correctly. Is this
 known resp. intended behavior of numpy?
>>>
>>> Augmented assignment modifies numpy arrays in-place, so the usual
>>> casting rules for assignment into an array apply. Namely, the array
>>> being assigned into keeps its dtype.
>>
>> what are the usual casting rules?
>
> For assignment into an array, the array keeps its dtype and the data
> being assigned into it will be cast to that dtype.
>
>> How does numpy know how to cast an object to a float?
>
> For a general object, numpy will call its __float__ method.
>
>>> If you do not want in-place modification, do not use augmented assignment.
>>
>> Normally, I'd be perfectly fine with that.
>> However, this particular problem occurs when you try to automatically
>> differentiate an algorithm by using an Algorithmic Differentiation
>> (AD) tool.
>> E.g. given a function
>>
>> x = numpy.ones(2)
>> def f(x):
>>   a = numpy.ones(2)
>>   a *= x
>>   return numpy.sum(a)
>>
>> one would use an AD tool as follows:
>> x = numpy.array([adouble(1.), adouble(1.)])
>> y = f(x)
>>
>> but since the casting from object to float is not possible the
>> computed gradient \nabla_x f(x) will be wrong.
>
> Sorry, but that's just a limitation of the AD approach. There are all
> kinds of numpy constructions that AD can't handle.
>
> --
> Robert Kern
>
> "I have come to believe that the whole world is an enigma, a harmless
> enigma that is made terrible by our own mad attempt to interpret it as
> though it had an underlying truth."
>  -- Umberto Eco
> ___
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-12 Thread Christopher Barker
Sebastian Walter wrote:
>>> However, this particular problem occurs when you try to automatically
>>> differentiate an algorithm by using an Algorithmic Differentiation
>>> (AD) tool.
>>> E.g. given a function
>>>
>>> x = numpy.ones(2)
>>> def f(x):
>>>   a = numpy.ones(2)
>>>   a *= x
>>>   return numpy.sum(a)

I don't know anything about AD, but in general, when I write a function 
that requires a given numpy array type as input, I'll do something like:

def f(x):
   x = np.asarray(a, dtype=np.float)
   a = np.ones(2)
   a *= x
   return np.sum(a)


That makes the casting explicit, and forces it to happen at the top of 
the function, where the error will be more obvious. asarray will just 
pass through a conforming array, so little performance penalty when you 
do give it the right type.

-Chris


-- 
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-12 Thread Sebastian Walter
On Tue, Jan 12, 2010 at 7:38 PM, Robert Kern  wrote:
> On Tue, Jan 12, 2010 at 12:31, Sebastian Walter
>  wrote:
>> On Tue, Jan 12, 2010 at 7:09 PM, Robert Kern  wrote:
>>> On Tue, Jan 12, 2010 at 12:05, Sebastian Walter
>>>  wrote:
 Hello,
 I have a question about the augmented assignment statements *=, +=, etc.
 Apparently, the casting of types is not working correctly. Is this
 known resp. intended behavior of numpy?
>>>
>>> Augmented assignment modifies numpy arrays in-place, so the usual
>>> casting rules for assignment into an array apply. Namely, the array
>>> being assigned into keeps its dtype.
>>
>> what are the usual casting rules?
>
> For assignment into an array, the array keeps its dtype and the data
> being assigned into it will be cast to that dtype.
>
>> How does numpy know how to cast an object to a float?
>
> For a general object, numpy will call its __float__ method.

1)
the object does not have a __float__ method.

2)
I've now implemented the __float__ method (to raise an error).
However, it doesn't get called. All objects are casted to 1.




>
>>> If you do not want in-place modification, do not use augmented assignment.
>>
>> Normally, I'd be perfectly fine with that.
>> However, this particular problem occurs when you try to automatically
>> differentiate an algorithm by using an Algorithmic Differentiation
>> (AD) tool.
>> E.g. given a function
>>
>> x = numpy.ones(2)
>> def f(x):
>>   a = numpy.ones(2)
>>   a *= x
>>   return numpy.sum(a)
>>
>> one would use an AD tool as follows:
>> x = numpy.array([adouble(1.), adouble(1.)])
>> y = f(x)
>>
>> but since the casting from object to float is not possible the
>> computed gradient \nabla_x f(x) will be wrong.
>
> Sorry, but that's just a limitation of the AD approach. There are all
> kinds of numpy constructions that AD can't handle.
>
> --
> Robert Kern
>
> "I have come to believe that the whole world is an enigma, a harmless
> enigma that is made terrible by our own mad attempt to interpret it as
> though it had an underlying truth."
>  -- Umberto Eco
> ___
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-12 Thread Robert Kern
On Tue, Jan 12, 2010 at 12:31, Sebastian Walter
 wrote:
> On Tue, Jan 12, 2010 at 7:09 PM, Robert Kern  wrote:
>> On Tue, Jan 12, 2010 at 12:05, Sebastian Walter
>>  wrote:
>>> Hello,
>>> I have a question about the augmented assignment statements *=, +=, etc.
>>> Apparently, the casting of types is not working correctly. Is this
>>> known resp. intended behavior of numpy?
>>
>> Augmented assignment modifies numpy arrays in-place, so the usual
>> casting rules for assignment into an array apply. Namely, the array
>> being assigned into keeps its dtype.
>
> what are the usual casting rules?

For assignment into an array, the array keeps its dtype and the data
being assigned into it will be cast to that dtype.

> How does numpy know how to cast an object to a float?

For a general object, numpy will call its __float__ method.

>> If you do not want in-place modification, do not use augmented assignment.
>
> Normally, I'd be perfectly fine with that.
> However, this particular problem occurs when you try to automatically
> differentiate an algorithm by using an Algorithmic Differentiation
> (AD) tool.
> E.g. given a function
>
> x = numpy.ones(2)
> def f(x):
>   a = numpy.ones(2)
>   a *= x
>   return numpy.sum(a)
>
> one would use an AD tool as follows:
> x = numpy.array([adouble(1.), adouble(1.)])
> y = f(x)
>
> but since the casting from object to float is not possible the
> computed gradient \nabla_x f(x) will be wrong.

Sorry, but that's just a limitation of the AD approach. There are all
kinds of numpy constructions that AD can't handle.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless
enigma that is made terrible by our own mad attempt to interpret it as
though it had an underlying truth."
  -- Umberto Eco
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-12 Thread Sebastian Walter
On Tue, Jan 12, 2010 at 7:09 PM, Robert Kern  wrote:
> On Tue, Jan 12, 2010 at 12:05, Sebastian Walter
>  wrote:
>> Hello,
>> I have a question about the augmented assignment statements *=, +=, etc.
>> Apparently, the casting of types is not working correctly. Is this
>> known resp. intended behavior of numpy?
>
> Augmented assignment modifies numpy arrays in-place, so the usual
> casting rules for assignment into an array apply. Namely, the array
> being assigned into keeps its dtype.

what are the usual casting rules?
How does numpy know how to cast an object to a float?


>
> If you do not want in-place modification, do not use augmented assignment.

Normally, I'd be perfectly fine with that.
However, this particular problem occurs when you try to automatically
differentiate an algorithm by using an Algorithmic Differentiation
(AD) tool.
E.g. given a function

x = numpy.ones(2)
def f(x):
   a = numpy.ones(2)
   a *= x
   return numpy.sum(a)

one would use an AD tool as follows:
x = numpy.array([adouble(1.), adouble(1.)])
y = f(x)

but since the casting from object to float is not possible the
computed gradient \nabla_x f(x) will be wrong.


>
> --
> Robert Kern
>
> "I have come to believe that the whole world is an enigma, a harmless
> enigma that is made terrible by our own mad attempt to interpret it as
> though it had an underlying truth."
>  -- Umberto Eco
> ___
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-12 Thread josef . pktd
On Tue, Jan 12, 2010 at 1:05 PM, Sebastian Walter
 wrote:
> Hello,
> I have a question about the augmented assignment statements *=, +=, etc.
> Apparently, the casting of types is not working correctly. Is this
> known resp. intended behavior of numpy?
> (I'm using numpy.__version__ = '1.4.0.dev7039' on this machine but I
> remember a recent checkout of numpy yielded the same result).
>
> The problem is best explained at some examples:
>
> wrong casting from float to int::
>
>            In [1]: import numpy
>
>            In [2]: x = numpy.ones(2,dtype=int)
>
>            In [3]: y = 1.3 * numpy.ones(2,dtype=float)
>
>            In [4]: z = x * y
>
>            In [5]: z
>            Out[5]: array([ 1.3,  1.3])
>
>            In [6]: x *= y
>
>            In [7]: x
>            Out[7]: array([1, 1])
>
>            In [8]: x.dtype
>            Out[8]: dtype('int32')
>
>  wrong casting from float to object::
>
>            In [1]: import numpy
>
>            In [2]: import adolc
>
>            In [3]: x = adolc.adouble(numpy.array([1,2,3],dtype=float))
>
>            In [4]: y = numpy.array([4,5,6],dtype=float)
>
>            In [5]: x
>            Out[5]: array([1(a), 2(a), 3(a)], dtype=object)
>
>            In [6]: y
>            Out[6]: array([ 4.,  5.,  6.])
>
>            In [7]: x * y
>            Out[7]: array([4(a), 10(a), 18(a)], dtype=object)
>
>            In [8]: y *= x
>
>            In [9]: y
>
>            Out[9]: array([ 4.,  5.,  6.])
>
>
>        It is inconsistent to the Python behavior::
>
>            In [9]: a = 1
>
>            In [10]: b = 1.3
>
>            In [11]: c = a * b
>
>            In [12]: c
>            Out[12]: 1.3
>
>            In [13]: a *= b
>
>            In [14]: a
>            Out[14]: 1.3
>
>
> I would expect that numpy should at least raise an exception in the
> case of casting object to float.
> Any thoughts?

You are assigning to an existing array, which implies casting to the
dtype of that array. It's the behavior that I would expect. If you
want upcasting then don't use inplace *= , ...

Josef


>
> regards,
> Sebastian
> ___
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] wrong casting of augmented assignment statements

2010-01-12 Thread Robert Kern
On Tue, Jan 12, 2010 at 12:05, Sebastian Walter
 wrote:
> Hello,
> I have a question about the augmented assignment statements *=, +=, etc.
> Apparently, the casting of types is not working correctly. Is this
> known resp. intended behavior of numpy?

Augmented assignment modifies numpy arrays in-place, so the usual
casting rules for assignment into an array apply. Namely, the array
being assigned into keeps its dtype.

If you do not want in-place modification, do not use augmented assignment.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless
enigma that is made terrible by our own mad attempt to interpret it as
though it had an underlying truth."
  -- Umberto Eco
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion