2

I have a recursive function that can produce a difficult-to-know number of expressions, each needing a new variable multiplied to it. These variables will later be removed out by calculations involving integration or residue.

How can I develop these unknown number of variables? Maybe indexed? All examples I've seen on the internet are working with an a priori known object of a definite size, e.g. "item" in How can you dynamically create variables via a while loop? or Accessing the index in Python 'for' loops

I think I can boil it down to this simple example to use in my real script:

import sympy as s
p0,p1,p2,p3,p4=s.symbols('p0 p1 p2 p3 p4')
l = [p0, p1, p2, p3, p4]

def f(n):
    if n == 0:
        return l[n]
    elif n == 1: 
        return l[n]
    else:
        return f(n-1)*l[n]+f(n-2)

f(3) # works
f(6) # doesnt' work - need to define ahead of time the 
     # dummy variables l[6], l[5], .... 
     # even if they are just symbols for (much) later numerical evaluation.

I need this above snippet to actually generate the needed unknowns ahead of time.

I saw some mentions of pandas, but couldn't find a good example for my need, nor even sure if that was the best route. Also saw things like, "...an unknown number of lines [file]...", or "...unknown number of arguments...", but those are, seemingly, not applicable.

nate
  • 269
  • 2
  • 11
  • while i am very new to python, I think both require knowing the size... I need something like the keyword gensym() in Maxima: http://maxima.sourceforge.net/docs/manual/maxima_33.html – nate Jan 21 '18 at 23:30
  • `list = [1, 2, 3], list.append(4)` - Is this what you are wanting to achieve? – Zachary Jan 21 '18 at 23:37
  • well, in the above snippet, if Ijust call `f(6)`, I would like the required `l[6]` to be implicitly available, by providing a dummy variable, so that the calculation can continue... – nate Jan 21 '18 at 23:39
  • Could you make a helper function to return a dummy value if f(6) doesn't exist? – Zachary Jan 21 '18 at 23:40
  • So if I call `f(6)`, it will require `l[6]` to exist. I could initiate a list to a 1000 indexed symbols (somehow I don't know), or maybe use a generator or dict I guess so the memory isn't taxed, but maybe I just don't know how to do that. Calling `f(6)` will require `l[6]` and then `f(5)` and `f(4)`, which will require `l[5]` and `l[4]`, etc. etc. So maybe your idea works but I can't tell yet. – nate Jan 21 '18 at 23:43
  • I think there may be some confusion -- appending would be if I created the variable and wanted to add it to a list (w/ index) for later calcs. I need the script itself to make the new variable – nate Jan 21 '18 at 23:46
  • If you need the previous values, a dictionary and use the index as a key. If the value does not exist, you can put it there with the dummy value without requiring the previous values to be within the data structure. Though if you need the previous values, adding in the required values with a helper function will be easy enough. – Zachary Jan 21 '18 at 23:48

1 Answers1

2

Indexed objects represent an abstract thing with an index taking any values, with no restriction on how large the index can be.

import sympy as s
p = s.IndexedBase("p")

def f(n):
    if n == 0 or n == 1:
        return p[n]
    else:
        return f(n-1)*p[n] + f(n-2)

print(f(7))

Output

(p[0] + p[1]*p[2])*p[3] + (((p[0] + p[1]*p[2])*p[3] + p[1])*p[4] + p[0] + p[1]*p[2])*p[5] + (((p[0] + p[1]*p[2])*p[3] + p[1])*p[4] + ((p[0] + p[1]*p[2])*p[3] + (((p[0] + p[1]*p[2])*p[3] + p[1])*p[4] + p[0] + p[1]*p[2])*p[5] + p[1])*p[6] + p[0] + p[1]*p[2])*p[7] + p[1]

As an aside, things like p0,p1,p2,p3,p4=s.symbols('p0 p1 p2 p3 p4') can be done more easily with syms = s.symbols('p0:5') or even

n = ...
syms = s.symbols('p0:{}'.format(n))

This creates individual symbols, not an indexed object, so the number n has to be known at the time of creation. But still easier than listing p0 p1 and so on.

  • 1
    perfect! Thanks! Still reading your link provided, but I do note that I can work with these objects, i.e. `f(7).subs(p[4],0)` – nate Jan 22 '18 at 00:32