Chaos game to get specific fractal

399 Views Asked by At

In the Wikipedia page for Chaos Game, you can see this fractal, which is the result of the rule:

A point inside a square repeatedly jumps half of the distance towards a randomly chosen vertex, but the currently chosen vertex cannot be 1 or 3 places, respectively away from the two previously chosen vertices.

However, that is unlikely since the rule implies that all the point will do is to get closer to vertex 1 or 3 (or 2 or 4), so that the image after some iterations would be a line joining both vertices.

Can you give a rule that produces the desired fractal?

1

There are 1 best solutions below

2
On

Partial answer. I wrote the following MATLAB function to produce those pretty pictures:

function chaosGame(forbidden, mode, side, points)
  % CHAOSGAME play a chaos game
  %
  % https://en.wikipedia.org/wiki/Chaos_game
  %
  % A point inside a square repeatedly jumps half the distance
  % towards a randomly chosen vertex, but the currently chosen
  % vertex must obey the constraint specified by forbidden and
  % mode.
  %
  % - forbidden is a row vector with values from {0,1,2,3,NaN}.
  % - mode is either 'all' or 'any'
  %
  % If forbidden(k) is m, then the current vertex should not be
  % m places away (counterclockwise) from the one chosen k
  % turns before.  If forbidden(k) is NaN, the vertex chosen
  % k turns before imposes no constraint.
  %
  % If mode is 'all' all constraints specified by forbidden must
  % be satisfied.  If mode is 'any' at least one constraint must
  % be satisfied.  Using NaN with 'any' gives an unconstrained
  % choice.

  if nargin < 1 || isempty(forbidden)
    forbidden = [1 3];
  end
  if nargin < 2 || isempty(mode)
    mode = 'all';
  end
  if nargin < 3 || isempty(side)
    side = 1000;
  end
  if nargin < 4 || isempty(points)
    points = fix(side.^2);
  end

  switch mode
    case {'all'}
      compareall = true;
    case {'any'}
      compareall = false;
    otherwise
      error('mode should be either all or any')
  end

  % Start with a white canvas.
  canvas = ones(side);
  % List vertices from top left counterclockwise.
  vertices = [1 1; 1 side; side side; side 1];
  % Past vertex indices (which are in {0,1,2,3}) are initially
  % invalid (-1) so that the first vertex choice is free.
  past = -ones(size(forbidden));
  % Pick random starting point inside the canvas.
  p = side * rand(1,2);
  canvas(fix(p(1)), fix(p(2))) = 0;

  for n = 1:points
    while 1
      pick = randi([0 3]);
      d = mod(pick + forbidden, 4);
      if compareall
        validchoice = all(d ~= past);
      else
        validchoice = any(d ~= past);
      end
      if validchoice
        past = [pick past(1:end-1)];
        break
      end
    end
    vert = vertices(pick+1,:);
    p = (vert + p) / 2;
    canvas(fix(p(1)), fix(p(2))) = 0;
  end
  imshow(canvas,'InitialMagnification','fit')
end

This is what I got for forbidden set to $0$, $1$, $2$, and $[1,3]$ (from top to bottom, and from left to right):

enter image description here

I'm not sure the $[1,3]$ picture is what you describe, but it's definitely not the one on the Wikipedia page. The 'any' mode also produces some nice graphs:

enter image description here

As one would expect, there are more black points, but we are still far from the desired result.

(Note: the function also works with Octave (except for an inessential warning) but is much slower.)