# Ikeda map (fractal)

## Generating an Ikeda Map

Today in my ongoing quest to generate fractals in Rstats using every available avenue: generating an Ikeda map.

Methods for generating fractals so far:

## Ikeda map

An Ikeda map is a model of light going acound a nonlinear optical resonator. To be honest, the wiki page and the original paper by Ikeda are impenetrable to me!

However, creating the map is relatively straightforward.

1. Start at a random point
2. Update the position of the point
3. Continue updating the point’s position for N steps
4. Draw the path joining all the positions of this point
5. Repeat steps 1-4
``````library(tidyverse)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#' Computing a single path from the given starting point
#'
#' @param u ikeda parameter
#' @param x,y starting point
#' @param N is the number of iterations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compute_ikeda_trajectory <- function(u=0.918, x1, y1, N) {
x    <- y <- double(N)
x[1] <- x1
y[1] <- y1

for (i in 2:N) {
t    <- 0.4 - 6/(1 + x[i-1]*x[i-1] + y[i-1]*y[i-1])
x[i] <- 1 + u * (x[i-1] * cos(t) - y[i-1] * sin(t))
y[i] <-     u * (x[i-1] * sin(t) + y[i-1] * cos(t))
}

data_frame(x=x, y=y)
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate P random starting points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
P <- 2000  # Number of starting  points
N <- 1000  # Number of iterations of each point
set.seed(1)
x <- rnorm(P) * 10
y <- rnorm(P) * 10

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Generate the P paths from the random starting points
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
res <- seq(P) %>%
map(~compute_ikeda_trajectory(u=0.928, x[.x], y[.x], N))``````
``````Warning: `data_frame()` is deprecated, use `tibble()`.
This warning is displayed once per session.``````
``````#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Plot all the paths
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
par(pty='s',bg='black')
plot(0, type='n', as=1, xlim=c(-10, 10), ylim=c(-10, 10))
res %>% walk(~lines(.x, col='#ffffff08'))``````

## Tweetable Ikeda map

This one was a hell of a squeeze to get it into a tweet:

• Use `1e3` instead of `1000` to save a single character.
• Drop leading `0` from `0.9`
• Use `rep(0,N)` instead of `double(N)` to save a single character
• use `lst` instead of `tibble` or `data.frame` to save at least 3 chars
• Dropping from `10` to `9` as a multiplier to trip a single digit each time.
• Came out at exactly 280 characters!
• Update Thanks to Jonathan Carroll for pointing out a shorter way to call `map2` it’s down to 272 characters which means I can include the #rstats hashtag! (which then brings it back up to 280 characters)
``````#rstats
library(tidyverse)
N=1e3
x=y=rep(0,N)
F=function(X,Y){x[1]=X
y[1]=Y
for(i in 2:N){X=x[i-1];Y=y[i-1]
t=.4-6/(1+X^2+Y^2)
S=sin(t);C=cos(t)
x[i]=1+.9*(X*C-Y*S)
y[i]=.9*(X*S+Y*C)}
lst(x,y)}
r=rnorm
plot(0,as=1,yli=c(-9,9))
walk(map2(r(N)*9,r(N)*9,F),~lines(.x,co='#00000010'))``````