Ask Your Question
1

apply functions iteratively (modified re-post)

asked 2017-01-04 02:14:39 +0100

Daniel L gravatar image

updated 2017-01-04 02:16:12 +0100

(This is a modified re-post of Apply Functions Iteratively since my original question wasn't answered)

I have a few functions R1,R2,R3,R4 which act on vectors. If X = matrix(3,1,(x0,y0,r)) then I have

def R1(X): return matrix(3,1,(X[0,0]/(X[0,0]^2+X[1,0]^2-X[2,0]^2),X[1,0]/(X[0,0]^2+X[1,0]^2-X[2,0]^2),X[2,0]/abs(X[0,0]^2+X[1,0]^2-X[2,0]^2)))

def R2(X): return matrix(3,1,(-X[0,0],X[1,0],X[2,0]))

def R3(X): return matrix(3,1,(-X[0,0]+2,X[1,0],X[2,0]))

def R4(X): return matrix(3,1,(X[0,0],-X[1,0]+2,X[2,0]))

For instance, if v = matrix(3,1,(1,1,1)), then applying R2 to v gives the matrix $(-1,1,1)$.

I'd like to apply about 10 "levels" of iteration of these functions and have the output as a list of vectors. So, the list should be $R1(v), R2(v),R3(v),R4(v),R1^2(v),R2(R1(v)),R3(R1(v)),R4(R1(v)),R1^3(v),...,R1^{10}(v)\,...,R4^{10}(v)$ (as vectors) where $R_j^n = R_j \circ \cdots \circ R_j$ $n$ times.

I know how to apply a single function iteratively, but I don't know how to combine/loop the four together. Thanks.

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2017-01-04 02:45:10 +0100

tmonteil gravatar image

updated 2017-01-05 05:04:29 +0100

Let me assume that you want all possible compositions of length say n=3.

First, let us put the four functions into a list L:

sage: L = [R1,R2,R3,R4] ; L
[<function R1 at 0x7fc150827320>,
 <function R2 at 0x7fc1508272a8>,
 <function R3 at 0x7fc150827a28>,
 <function R4 at 0x7fc150827aa0>]

Then, we want to look at the product of L with itself n times, and for each n-uple i, we want to appy each element of i (which is a function) iteratively starting from the vector v:

sage: n = 3
sage: from itertools import product
sage: for i in product(L, repeat=3):
....:     w = v
....:     print i        # to see which functions are applied (from left to right)
....:     for f in i:
....:         w = f(w)
....:     print w      # to see the composition applied to v

EDIT If you want to avoid redundency, you can put your results in a set. However, matrices are unhashable by default, so they can not be elements of sets. Hence you have to make them immutable first:

sage: S = set()
sage: for i in product(L, repeat=3):
....:     w = v
....:     for f in i:
....:         w = f(w)
....:         w.set_immutable()
....:     S.add(w)
sage: S
{[-3]
 [ 1]
 [ 1], [-1]
 [ 1]
 [ 1], [1/3]
 [1/9]
 [1/9], [1]
 [1]
 [1], [3]
 [1]
 [1]}

In case there are a lot of equalities in the partial compotitions we can an iterative approach (as @nbruin's answer) so that the simplification is done at each step:

sage: v.set_immutable()
sage: Sold = {v}
sage: for i in range(n):
....:     Snew = set()
....:     for f in L:
....:         for u in Sold:
....:             w = f(u)
....:             w.set_immutable()
....:             Snew.add(w)
....:     Sold = Snew
sage: Sold
{[-3]
 [ 1]
 [ 1], [-1]
 [ 1]
 [ 1], [1/3]
 [1/9]
 [1/9], [1]
 [1]
 [1], [3]
 [1]
 [1]}

In your example, you will save a lot of redundent computations, therefore you will be able to go way further.

edit flag offensive delete link more

Comments

This works well. Thank you!

Daniel L gravatar imageDaniel L ( 2017-01-05 04:47:04 +0100 )edit
0

answered 2017-01-04 04:30:10 +0100

nbruin gravatar image

updated 2017-01-04 09:50:08 +0100

If you want various levels in the list, you probably want the original as well. You could do

ops=[R1,R2,R3,R4]
T=[v]
L=[]
for i in range(10):
  L += T
  T = [f(v) for v in T for f in ops]
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2017-01-04 02:14:39 +0100

Seen: 642 times

Last updated: Jan 05 '17