Оптимизация игры жизни - PullRequest
2 голосов
/ 22 марта 2011

Я пишу программу «Игра в жизнь» на языке mathematica, однако есть оговорка: мне нужно иметь возможность применять правила воспроизведения к некоторому проценту клеток, я хочу попробовать новый метод с использованием MapAt, но liveNeighbors не не работает поэлементно, и я не могу придумать способ исправить это, не выполнив точно то, что я делал раньше (много грязной индексации), у кого-нибудь есть какие-либо предложения? (Я предполагаю, что это будет более эффективным, чем старый метод, который приведен ниже, если нет, пожалуйста, дайте мне знать, я только начинающий!).

Что я пытаюсь сделать:

 Map[ArrayPlot,FixedPointList[MapAt[update[#,liveNeighbors[#]]&,#,coords]&,Board, 1]]

Что я уже сделал:

LifeGame[ n_Integer?Positive, steps_] := Module [{Board, liveNeighbors, update},
  Board = Table [Random [Integer], {n}, {n}];
  liveNeighbors[ mat_] := 
   Apply[Plus,Map[RotateRight[mat,#]&,{{-1,-1},{-1, 0},{-1,1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}]];
  update[1, 2] := 1;
  update[_, 3] := 1;
  update[ _, _] := 0;
  SetAttributes[update, Listable];
 Seed = RandomVariate[ProbabilityDistribution[0.7 UnitStep[x] + 0.3 UnitStep[x - 1], {x, 0, 1, 1}], {n, n}];
 FixedPointList[Table[If[Seed[[i, j]] == 1,update[#[[i, j]], liveNeighbors[#][[i, j]]],#[[i, j]]], {i, n}, {j, n}]&, Board, steps]]]

Спасибо!

Ответы [ 3 ]

5 голосов
/ 23 марта 2011
In[156]:= 
LifeGame2[n_Integer?Positive, steps_] := 
 Module[{Board, liveNeighbors, update},
  Board = RandomInteger[1, {n, n}];
  liveNeighbors[mat_] := 
   ListConvolve[{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, 
    ArrayPad[mat, 1, "Periodic"]];
  SetAttributes[update, Listable];
  Seed = RandomVariate[BernoulliDistribution[0.3], {n, n}];
  update[0, el_, nei_] := el;
  update[1, 1, 2] := 1;
  update[1, _, 3] := 1;
  update[1, _, _] := 0;
  FixedPointList[MapThread[update, {Seed, #, liveNeighbors[#]}, 2] &, 
   Board, steps]
  ]

Эта реализация делает то же самое, что и ваша, за исключением того, что она намного быстрее:

In[162]:= AbsoluteTiming[
 res1 = BlockRandom[SeedRandom[11]; LifeGame[20, 100]];]

Out[162]= {6.3476347, Null}

In[163]:= Timing[BlockRandom[Seed[11]; LifeGame2[20, 100]] == res1]

Out[163]= {0.047, True}
4 голосов
/ 23 марта 2011

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

Прямо из документации,правило 2D CA:

GameOfLife = {224, {2, {{2, 2, 2}, {2, 1, 2}, {2, 2, 2}}}, {1, 1}};

И итерация по сетке 100x100 для 100 шагов:

ArrayPlot[CellularAutomaton[GameOfLife, RandomInteger[1, {100, 100}], {{{100}}}]]

output of CellularAutomaton

Это, по крайней мере, даст вам базовую линиюдля сравнения скорости.

Вместо MapAt вы можете использовать Part с синтаксисом Span для замены всего подмассива сразу:

a = ConstantArray[0, {5, 5}];
a[[2 ;; 4, 2 ;; 4]] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}

a in MatrixForm

HTH!

0 голосов
/ 23 марта 2011
...