Creating Repeating Composite Functions

63 views
Skip to first unread message

Christopher Olah

unread,
Dec 19, 2009, 2:14:00 PM12/19/09
to sage-s...@googlegroups.com
Greetings!

I can't seem to figure out how (elegantly) to make a function that is
the repeated composite of another. eg. Suppose I have a function f,
how do I get f*f*f*f...

In math, I could just f^n, in normal lambda calculus, I'd just use n.f
(church numeral), but in sage the only way I could come up with was
using a loop to generate "f(f(...(x)))" and then printing it and copy
pasting it to the end of "g=lambda x: " and using that (and even then,
when I used ~100 iterations, sage crashed). There's got to be a more
elegant way...

Thanks,

Christopher

PS. If your wondering why I'm doing this, have a look at
http://christopherolah.wordpress.com/2009/12/19/formation-of-escape-time-fractals/
, I'm making some really neat pictures of the formation of escape time
fractals!

Robert Bradshaw

unread,
Dec 19, 2009, 2:53:48 PM12/19/09
to sage-s...@googlegroups.com
On Dec 19, 2009, at 11:14 AM, Christopher Olah wrote:

> Greetings!
>
> I can't seem to figure out how (elegantly) to make a function that is
> the repeated composite of another. eg. Suppose I have a function f,
> how do I get f*f*f*f...
>
> In math, I could just f^n,

One difficulty with supporting that would be that it's bit ambiguous
as powering is also often used for powering after application, not
only repeated application (e.g. sin^2(x) is usually interpreted as
(sin(x))^2) and it would make the gulf between functions and
expressions even bigger.

sage: f(x) = sin(x)
sage: f^2
x |--> sin(x)^2
sage: f = sin(x)
sage: f^2
sin(x)^2

> in normal lambda calculus, I'd just use n.f
> (church numeral), but in sage the only way I could come up with was
> using a loop to generate "f(f(...(x)))" and then printing it and copy
> pasting it to the end of "g=lambda x: " and using that (and even then,
> when I used ~100 iterations, sage crashed). There's got to be a more
> elegant way...

Though it's not perfect, you could do

sage: def compose(f, n, x): return x if n == 0 else compose(f, n-1,
f(x))
....:
sage: compose(sin, 3, x)
sin(sin(sin(x)))
sage: compose(sin, 100, x)
sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(sin(x))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
sage: foo = compose(sin, 500, x)
sage: foo(x=1.5)
0.0770617846688116


>
> Thanks,
>
> Christopher
>
> PS. If your wondering why I'm doing this, have a look at
> http://christopherolah.wordpress.com/2009/12/19/formation-of-escape-time-fractals/
> , I'm making some really neat pictures of the formation of escape time
> fractals!

Neat.

- Robert


William Stein

unread,
Dec 19, 2009, 3:16:42 PM12/19/09
to sage-support

The following is better. It is longer, but it will work even if n >=
1000, whereas the above will fail spectacularly due to Python's stack
limit. Also, the following is a bit faster than the above:

def compose(f, n, a):
"""
Return f(f(...f(a)...)), where the composition occurs n times.

INPUT:
- `f` -- anything that is callable
- `n` -- a nonnegative integer
- `a` -- any input for `f`

OUTPUT:
result of composing `f` with itself `n` times and applying to `a`.

EXAMPLES::

sage: def f(x): return x^2 + 1
sage: x = var('x')
sage: compose(f, 3, x)
((x^2 + 1)^2 + 1)^2 + 1
"""
n = Integer(n)
if n <= 0: return a
a = f(a)
for i in range(n-1): a = f(a)
return a


I independently called mine "compose" too, so that must be the right name!

I've made adding this to the library:
http://trac.sagemath.org/sage_trac/ticket/7742

I hope somebody will make a patch, etc. (since this would be good
practice for somebody, and I have other things to do).

William

Christopher Olah

unread,
Dec 19, 2009, 7:22:57 PM12/19/09
to sage-s...@googlegroups.com
> The following is better.   It is longer, but it will work even if n >=
> 1000, whereas the above will fail spectacularly due to Python's stack
> limit.  Also, the following is a bit faster than the above:
>
> def compose(f, n, a):
>    """
>    Return f(f(...f(a)...)), where the composition occurs n times.
>
>    INPUT:
>        - `f` -- anything that is callable
>        - `n` -- a nonnegative integer
>        - `a` -- any input for `f`
>
>    OUTPUT:
>        result of composing `f` with itself `n` times and applying to `a`.
>
>    EXAMPLES::
>
>        sage: def f(x): return x^2 + 1
>        sage: x = var('x')
>        sage: compose(f, 3, x)
>        ((x^2 + 1)^2 + 1)^2 + 1
>    """
>    n = Integer(n)
>    if n <= 0: return a
>    a = f(a)
>    for i in range(n-1): a = f(a)
>    return a

Two thoughts:

(1) For negative numbers, it should be the inverse function, if that
is feasible. Otherwise, an error.

(2) Secondly, could we get this to return a function, somehow? In the
present state, I imagine I could do something like:

sage: x=var('x')
sage: f = compose(sin, 10, x)
sage: f = lambda z : f(x=z)
#f= sin^10(x)

Message has been deleted

Carlos Córdoba

unread,
Dec 20, 2009, 10:30:53 AM12/20/09
to sage-s...@googlegroups.com
Hi,

There is a function in Mathematica that does exactly what you want and it's called Nest. I've reimplemented it in python as general effort to port some functional tools that I like to python. Please check this link if you are interested on it:


Hope this helps,
Carlos

2009/12/19 Minh Nguyen <nguye...@gmail.com>
Hi Christopher,

On Sun, Dec 20, 2009 at 6:14 AM, Christopher Olah
<christopherolah.co@gmail.com> wrote:

<SNIP>


> PS. If your wondering why I'm doing this, have a look at
> http://christopherolah.wordpress.com/2009/12/19/formation-of-escape-time-fractals/
> , I'm making some really neat pictures of the formation of escape time
> fractals!

Those are some pretty eye candies. The link to that blog post of yours
is now posted on the Sage Math Facebook page [1] and has been
twittered [2]. If you want, I could add your Wordpress blog to the
list of blogs on Planet Sage [3]. All you need to do is categorize
Sage specific blog posts as "Sage" and Planet Sage would pick up those
Sage specific posts.

[1] http://www.facebook.com/pages/Sage-Math/26593144945

[2] http://twitter.com/sagemath

[3] http://planet.sagemath.org

--
Regards
Minh Van Nguyen

--
To post to this group, send email to sage-s...@googlegroups.com
To unsubscribe from this group, send email to sage-support...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/sage-support
URL: http://www.sagemath.org

Reply all
Reply to author
Forward
0 new messages