Генерация треугольника Серпинского итеративно в Mathematica?

Я написал код, который рисует фрактал Серпинского. Это очень медленно, так как использует рекурсию. Кто-нибудь из вас знает, как я могу написать тот же код без рекурсии, чтобы он работал быстрее? Вот мой код:

 midpoint[p1_, p2_] := Mean[{p1, p2}]
 trianglesurface[A_, B_, C_] :=  Graphics[Polygon[{A, B, C}]]
 sierpinski[A_, B_, C_, 0] := trianglesurface[A, B, C]
 sierpinski[A_, B_, C_, n_Integer] :=
 Show[
 sierpinski[A, midpoint[A, B], midpoint[C, A], n - 1],
 sierpinski[B, midpoint[A, B], midpoint[B, C], n - 1],
 sierpinski[C, midpoint[C, A], midpoint[C, B], n - 1]
 ]

редактировать:

Я написал это с подходом Chaos Game, если кому-то интересно. Спасибо за ваши отличные ответы! Вот код:

 random[A_, B_, C_] := Module[{a, result},
 a = RandomInteger[2];
 Which[a == 0, result = A,
 a == 1, result = B,
 a == 2, result = C]]

 Chaos[A_List, B_List, C_List, S_List, n_Integer] :=
 Module[{list},
 list = NestList[Mean[{random[A, B, C], #}] &, 
 Mean[{random[A, B, C], S}], n];
 ListPlot[list, Axes -> False, PlotStyle -> PointSize[0.001]]]

person John    schedule 30.01.2012    source источник
comment
Взгляните на stackoverflow.com /вопросы/159590/   -  person Dr. belisarius    schedule 30.01.2012
comment
Когда я рисовал такие вещи, я обнаружил, что рендеринг графики может занять гораздо больше времени, чем вычисление местоположения треугольников. Я также использовал рекурсивный подход (хотя и немного другой).   -  person Szabolcs    schedule 31.01.2012


Ответы (5)


Это использует Scale и Translate в сочетании с Nest для создания списка треугольников.

Manipulate[
  Graphics[{Nest[
    Translate[Scale[#, 1/2, {0, 0}], pts/2] &, {Polygon[pts]}, depth]}, 
   PlotRange -> {{0, 1}, {0, 1}}, PlotRangePadding -> .2],
  {{pts, {{0, 0}, {1, 0}, {1/2, 1}}}, Locator},
  {{depth, 4}, Range[7]}]

Графика Mathematica

person Heike    schedule 30.01.2012

Если вам нужна качественная аппроксимация треугольника Серпинского, вы можете использовать подход, называемый игра хаоса. Идея заключается в следующем: выберите три точки, которые вы хотите определить как вершины треугольника Серпинского, и выберите одну из этих точек случайным образом. Затем повторите следующую процедуру столько раз, сколько хотите:

  1. Выберите случайную вершину треугольника.
  2. Переместитесь из текущей точки в точку на полпути между ее текущим местоположением и этой вершиной треугольника.
  3. Постройте пиксель в этой точке.

Как вы можете видеть на этой анимации, эта процедура вариант разрешения треугольника. Если вы хотите, вы можете использовать многопоточность, чтобы несколько процессов отображали пиксели одновременно, что в конечном итоге приведет к более быстрому рисованию треугольника.

В качестве альтернативы, если вы просто хотите преобразовать свой рекурсивный код в итеративный код, одним из вариантов может быть использование подхода с рабочим списком. Поддерживайте стек (или очередь), содержащий набор записей, каждая из которых содержит вершины треугольника и число n. Изначально занесите в этот рабочий список вершины основного треугольника и фрактальную глубину. Затем:

  • While the worklist is not empty:
    • Remove the first element from the worklist.
    • If its n value is not zero:
      • Draw the triangle connecting the midpoints of the triangle.
      • Для каждого подтреугольника добавьте этот треугольник со значением n n - 1 в рабочий список.

По сути, это итеративно моделирует рекурсию.

Надеюсь это поможет!

person templatetypedef    schedule 30.01.2012
comment
Сначала я просто хотел перевести код, но подход к игре хаоса кажется действительно интересным! Буду дома пробовать! Большое спасибо, это было очень полезно! - person John; 31.01.2012
comment
Еще раз спасибо, я написал это с подходом Chaos Game! Я добавил его в свой пост на случай, если вам интересно посмотреть, как к нему подошли. - person John; 31.01.2012

Вы можете попробовать

l = {{{{0, 1}, {1, 0}, {0, 0}}, 8}};
g = {};
While [l != {},
 k = l[[1, 1]];
 n = l[[1, 2]];
 l = Rest[l];
 If[n != 0,
  AppendTo[g, k];
  (AppendTo[l, {{#1, Mean[{#1, #2}], Mean[{#1, #3}]}, n - 1}] & @@ #) & /@
                                                 NestList[RotateLeft, k, 2]
  ]]
Show@Graphics[{EdgeForm[Thin], Pink,Polygon@g}]

Затем замените AppendTo чем-то более эффективным. См., например, https://mathematica.stackexchange.com/questions/845/internalbag-inside-compile

введите здесь описание изображения

Изменить

Быстрее:

f[1] = {{{0, 1}, {1, 0}, {0, 0}}, 8};
i = 1;
g = {};
While[i != 0,
 k = f[i][[1]];
 n = f[i][[2]];
 i--;
 If[n != 0,
  g = Join[g, k];
  {f[i + 1], f[i + 2], f[i + 3]} =
    ({{#1, Mean[{#1, #2}], Mean[{#1, #3}]}, n - 1} & @@ #) & /@ 
                                                 NestList[RotateLeft, k, 2];
  i = i + 3
  ]]
Show@Graphics[{EdgeForm[Thin], Pink, Polygon@g}]
person Dr. belisarius    schedule 30.01.2012

Поскольку функции, основанные на треугольниках, уже были хорошо изучены, вот подход, основанный на растре.
Он итеративно строит треугольник Паскаля, затем берет по модулю 2 и отображает результат.

NestList[{0, ##} + {##, 0} & @@ # &, {1}, 511] ~Mod~ 2 // ArrayPlot

Графика Mathematica

person Mr.Wizard    schedule 01.02.2012

Clear["`*"];
sierpinski[{a_, b_, c_}] := 
  With[{ab = (a + b)/2, bc = (b + c)/2,  ca = (a + c)/2}, 
   {{a, ab, ca}, {ab, b, bc}, {ca, bc, c}}];

pts = {{0, 0}, {1, 0}, {1/2, Sqrt[3]/2}} // N;
n = 5;
d = Nest[Join @@ sierpinski /@ # &, {pts}, n]; // AbsoluteTiming
Graphics[{EdgeForm@Black, Polygon@d}]

(*sierpinski=Map[Mean, Tuples[#,2]~Partition~3 ,{2}]&;*)

Вот 3D-версия, https://mathematica.stackexchange.com/questions/22256/how-can-i-compile-this-function

введите здесь описание изображения

ListPlot@NestList[(# + RandomChoice[{{0, 0}, {2, 0}, {1, 2}}])/2 &,
 N@{0, 0}, 10^4]

With[{data = 
   NestList[(# + RandomChoice@{{0, 0}, {1, 0}, {.5, .8}})/2 &, 
    N@{0, 0}, 10^4]}, 
 Graphics[Point[data, 
   VertexColors -> ({1, #[[1]], #[[2]]} & /@ Rescale@data)]]
 ]

With[{v = {{0, 0, 0.6}, {-0.3, -0.5, -0.2}, {-0.3, 0.5, -0.2}, {0.6, 
     0, -0.2}}}, 
 ListPointPlot3D[
  NestList[(# + RandomChoice[v])/2 &, N@{0, 0, 0}, 10^4], 
  BoxRatios -> 1, ColorFunction -> "Pastel"]
 ]

введите здесь описание изображениявведите здесь описание изображения

person chyanog    schedule 15.09.2013