1-dimensionaler Wald: {0, 1,...}
In[1]:= n:=12
Out[1]=
In[2]:= forestList=Table[Random[Integer],{n}]
Out[2]= {1,0,1,1,1,0,1,1,1,0,0,1}
In[3]:= treeGrowIgnite[0]:=Floor[1+p-Random[]]
Out[3]=
In[4]:= treeGrowIgnite[1]:=Floor[2+f-Random[]]
Out[4]=
In[5]:= f:=0.3; p:=0.75
Out[5]=
In[6]:= forestList=treeGrowIgnite /@ forestList
Out[6]= {1,0,2,1,1,0,1,2,1,0,0,2}
Wald mit jungen Bäumen, der ,,ein bißchen`` brennt.
Steppe | = | {0,0,0,0,0,0,0,0,0,0,0,0} |
Wald mit jungen Bäumen | = | {1,0,1,1,1,0,1,1,1,0,0,1} |
Anzünden | ![]() |
{1,0,2,1,1,0,1,2,1,0,0,2} |
Brennen | ![]() |
{2,0,2,2,1,0,2,2,2,0,0,2} |
Brennen | ![]() |
{2,0,2,2,2,0,2,2,2,0,0,2} |
Absterben | ![]() |
{0,0,0,0,0,0,0,0,0,0,0,0} |
Idee:
{...2,1...} {...2,2...}
{...1,2...} {...2,2...}
In[7]:= forestBurn[{a___,2,1,b___}]:=forestBurn[{a,2,2,b}]
Out[7]=
In[8]:= forestBurn[{a___,1,2,b___}]:=forestBurn[{a,2,2,b}]
Out[8]=
In[9]:= forestBurn[{1,a___,2}]:=forestBurn[{2,a,2}]
Out[9]=
In[10]:= forestBurn[{2,a___,1}]:=forestBurn[{2,a,2}]
Out[10]=
Eine alternative Formulierung mit Transformation Rules:
forestList /. {a___,2,1,b___} -> {a,2,2,b}
Mit /. würde jedoch nur eine Ersetzung vorgenommen.
Daher muß man ReplaceRepeated = //. verwenden:
forestList //. {a___,2,1,b___} -> {a,2,2,b}
{2,0,2,2,2,0,2,2,2,0,0,2} {0,0,0,0,0,0,0,0,0,0,0,0}
In[11]:= forestBurn[forestList]
Out[11]= forestBurn[{2, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 2}]
In[12]:= %[[1]] /. 2->0
Out[12]= {0,0,0,0,0,0,0,0,0,0,0,0}
Bäume wachsen von neuem und entzünden sich:
In[13]:= treeGrowIgnite /@ %
Out[13]= {1,0,1,0,1,1,1,1,1,1,0,1}
Um einen kontinuierlichen Kreislauf zu erzeugen, muß ein Anfangszustand erzeugt werden, der Wald wachsen und sich entzünden, das Feuer sich ausbreiten und die brennenden Bäume schließlich absterben. Dann kann der Wald neuerlich wachsen und sich entzünden, ...
Nest bietet sich an, um eine geeignete Funktion, die das Wachsen, Entzünden, Ausbreiten des Feuers und Absterben der Bäume herbeiführt, immer wieder auf den Wald anzuwenden (zu iterieren).
Die zu iterierende Funktion:
In[14]:= doForestCycle[l_List]:=
forestBurn[treeGrowIgnite /@ l][[1]] /. 2->0
Out[14]=
Der Kreislauf schließt sich:
In[15]:= woodlife[n_Integer, m_Integer]:=
Nest[doForestCycle, Table[Random[Integer],{n}],m]
Out[15]=
forestBurn verbleibt als Kopf nach dem Anzünden der Nachbarbäume.
Durch eine zusätzliche Regel läßt sich das verhindern.
In[16]:= forestBurn[l_List]:=l /. 2->0
Out[16]=
Die Reihenfolge der Regeln von forestBurn ist hier jedoch entscheidend!
Diese kann einfach kontrolliert werden:
In[17]:= ?forestBurn
Out[17]= Global`forestBurn
forestBurn[ {a___, 2, 1, b___} ] := forestBurn[{a, 2, 2, b}]
forestBurn[ {a___, 1, 2, b___} ] := forestBurn[{a, 2, 2, b}]
forestBurn[{1, a___, 2}] := forestBurn[{2, a, 2}]
forestBurn[{2, a___, 1}] := forestBurn[{2, a, 2}]
forestBurn[l_List] := l /. 2 -> 0
doForestCycle läßt sich jetzt vereinfachen:
In[18]:= doForestCycle[l_List]:=
forestBurn[treeGrowIgnite /@ l]
Out[18]=
Eliminieren des Maps /@ in doForestCycle:
In[19]:= SetAttributes[treeGrowIgnite, Listable]
Out[19]=
In[21]:= SetAttributes[x, Listable]
Out[21]=
In[22]:= x[{a,b,c}]
Out[22]= {x[a],x[b],x[c]}
langsamer als Map:
x /@ {a,b,c}
aber:
In[23]:= x[{a,{b,c}}]
Out[23]= {x[a],{x[b],x[c]}}
Ergebnis:
In[24]:= doForestCycle[l_List]:=forestBurn[treeGrowIgnite[l]]
Out[24]=
:> kennzeichnet eine ,,Delayed Rule``, die nicht bei der Definition, sondern erst bei der Auswertung des Ausdrucks angewendet wird.