-1

I have a recursive relation, that I want to update without using loops for speed.

For example

import numpy as np
x=np.array([1,0,0,0,0])
x[1:]=(1+x[0:len(x)-1])**2.

This returns [1,4,1,1,1] for x, but I want [1,4,25,676,458329]. I know this can be done with a loop, but I'm really trying to avoid loops.

For example,

for i in range(1,len(x)):
    x[i]=(1+x[i-1])**2.

will return [1,4,25,676,458329]

sempersax
  • 31
  • 4
  • 2
    Are you looking for `x[1:]=x[0]`? – pault Jun 28 '19 at 14:49
  • 1
    I think you need to describe your question in a more specific way. Hope then we can help you better. – Mobasshir Bhuiya Jun 28 '19 at 14:54
  • 1
    Please take the [tour] and read [ask], then explain your question in more detail with more examples of inputs and the desired outputs. – pault Jun 28 '19 at 14:57
  • 1
    I'm looking for x[1]=x[0], and then x[2]=x[1] using this updated value of x[1]. Maybe the example I've put here is too simple, I'm trying to do this for a Runge-Kutta type scheme – sempersax Jun 28 '19 at 14:58
  • it looks like you want to apply an operation across the array without an explicit loop –  Jun 28 '19 at 15:00
  • Yes, exactly. But from the way slicing appears to work, it uses the old version of the array, and doesn't use the new value as it's updated. – sempersax Jun 28 '19 at 15:04
  • Possible duplicate of [Is it possible to vectorize recursive calculation of a NumPy array where each element depends on the previous one?](https://stackoverflow.com/questions/4407984/is-it-possible-to-vectorize-recursive-calculation-of-a-numpy-array-where-each-el) – pault Jun 28 '19 at 15:24
  • It is, thank you, I hadn't been able to find that! – sempersax Jun 28 '19 at 15:33
  • In your example, the RHS is evaluated (as a whole), and then assigned to the LHS. The 'vectorization' is parallel, not serial. When you ask about alternatives to doing things with a loop it's good idea to provide a working example using the loop. It makes it a lot easier to verify our answers. – hpaulj Jun 28 '19 at 16:06
  • 1
    Possible duplicate of [Is it possible to vectorize recursive calculation of a NumPy array where each element depends on the previous one?](https://stackoverflow.com/questions/4407984/is-it-possible-to-vectorize-recursive-calculation-of-a-numpy-array-where-each-el) – Simply Ged Jun 29 '19 at 02:42

3 Answers3

1
>>> import numpy as np
>>> x=np.array([1,0,0,0,0])
>>> x[1:]=1
>>> x
array([1, 1, 1, 1, 1])
Mobasshir Bhuiya
  • 954
  • 6
  • 20
  • 3
    Perhaps I'm not clear. I have x[1] dependent on x[0], x[2] dependent on x[1], and so on and so forth. It's not that I want an array of ones, I want this dependency without a loop. – sempersax Jun 28 '19 at 14:51
  • Can you please use the different example set like a more diverse one? It doesn't seem perfect one. – Mobasshir Bhuiya Jun 28 '19 at 14:57
1

NumPy has a list of operations that work on arrays so you don't have to use an explicit for-loop to modify/update the array.

One of them is add which can add one array with another and you can use concatenate to operate on specific parts of the array:

import numpy as np
x = np.array([1, 0, 0, 0, 0])
head = x[:1] # => [1]
tail = x[1:] # => [0, 0, 0, 0]
tail_values = np.full_like(tail, 1) # => [1, 1, 1, 1]
tail_plus_one = np.add(tail, tail_values) # => [0, 0, 0, 0] + [1, 1, 1, 1]
np.concatenate(head, tail_plus_one) # => [1] + [1, 1, 1, 1]

NumPy has a section in their user guide on iterating and modifying arrays and how to make it an efficient operation.

  • 1
    I've updated my question to a more specific example, as it appears I was too vague before in what I was trying to do. Sorry – sempersax Jun 28 '19 at 15:17
0

Apparently this is what you are trying to do:

In [30]: x = np.array([1,0,0,0,0])                                                                              
In [31]: for i in range(1,len(x)): 
    ...:     x[i] = (1+x[i-1])**2 
    ...:                                                                                                        
In [32]: x                                                                                                      
Out[32]: array([     1,      4,     25,    676, 458329])

Many of the ufunc implement an accumulate method

In [33]: np.add.accumulate(np.arange(5))                                                                        
Out[33]: array([ 0,  1,  3,  6, 10])
In [34]: np.multiply.accumulate(np.arange(1,6))                                                                 
Out[34]: array([  1,   2,   6,  24, 120])

They iterate as above, but do so in compiled code. But, in general, you can't run your own Python function with the same speed.

hpaulj
  • 221,503
  • 14
  • 230
  • 353