[Numpy-discussion] ufunc.accumulate question

Chris Withers chris@simplistix.co...
Fri Oct 8 04:10:10 CDT 2010


Thanks for this, very informative! :-)

Chris

On 06/10/2010 17:35, Friedrich Romstedt wrote:
> 2010/10/5 Chris Withers<chris@simplistix.co.uk>:
>> Hi All,
>>
>> I can't find any docs on this behavior.
>>
>> So, I have a python function. To keep it simple, lets just do addition:
>>
>> def add(x,y):
>>    print x,y
>>    retun x+y
>>
>> So, I can turn this into a ufunc as follows:
>>
>> uadd = np.frompyfunc(add,2,1)
>
> As a side remark, note that this will always return dtype=numpy.object
> arrays.  Maybe numpy.vectorize() is more appropriate for your
> use-case.
>
>> Now, I can apply it to an array:
>>
>>   >>>  uadd.accumulate(np.arange(3,10))
>> 3 4
>> 7 5
>> 12 6
>> 18 7
>> 25 8
>> 33 9
>> array([3, 7, 12, 18, 25, 33, 42], dtype=object)
>>
>> Okay, but where did the initial 3 come from?
>> http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.accumulate.html#numpy.ufunc.accumulate
>> suggests that:
>>
>> r = np.empty(len(A))
>> t = op.identity        # op = the ufunc being applied to A's  elements
>> for i in xrange(len(A)):
>>      t = op(t, A[i])
>>      r[i] = t
>> return r
>
> I see from the behaviour, that the implementation makes use of the
> following behaviour of the identity ``op.identity`` with respect to
> ``op``:
>
>>>> op(op.identity, X) == X
> True
>
> So the implementation acts in agnosticism of ``op.identity`` by
> assuming that the first call of ``t = op(t, A[i])`` in your example
> will just yield ``A[0]``, while i == 0.
>
> This is the work flow:
>
> [ t = op.identity ]  # in brackets because it cannot be executed, it's
> pseudo-code
>
> i = 0
> =====
> t = op(t, A[0]) = A[0]
> r[0] = t = A[0]
>
> i = 1
> =====
> t = op(t, A[1]) = op(A[0], A[1])
> r[1] = t
>
> i = 2
> =====
> t = op(t, A[2]) = op(op(A[0], A[1]), A[2])
> r[2] = t
>
> and so on ... clear now?
>
> Friedrich
>
>> ...but:
>>
>>   >>>  print uadd.identity
>> None
>
> It's simply not set, and will also not be used.
>
>> ...and:
>>
>>   >>>  add(None,3)
>> None 3
>> Traceback (most recent call last):
>>    File "<stdin>", line 1, in<module>
>>    File "<stdin>", line 3, in add
>> TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
>
> As said, the code in the docs is just pseudo-code, it's not the actual
> (C?) implementation, it just has the same semantics.
>
>> So, where is the reason that the 3 ends up in the output array documented?
>>
>> Also, what if I want to specify the identity of my newly created ufunc?
>> I have a case where I want to specify it as zero:
>>
>>   >>>  uadd.identity = 0
>> Traceback (most recent call last):
>>    File "<stdin>", line 1, in<module>
>> AttributeError: attribute 'identity' of 'numpy.ufunc' objects is not
>> writable
>
> I think you have to write an own class for this.  You cannot subclass
> numpy.ufunc ("it's not an acceptable base class" Python says).
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email
> ______________________________________________________________________

-- 
Simplistix - Content Management, Batch Processing & Python Consulting
             - http://www.simplistix.co.uk


More information about the NumPy-Discussion mailing list