Als een leeuw op een kudde antilopen jaagt, welke regels bepalen dan het gedrag van de kudde? Een intrigerende mogelijkheid staat bekend als de zelfzuchtige kuddetheorie1 (selfish herd theory): in plaats van te handelen in het voordeel van de ganse groep, probeert elk dier zich te positioneren zodat er zich ten minste één ander dier tussen hemzelf en het roofdier bevindt. Dit vormt een patroon dat bekend staat als een Voronoi-betegeling2 — als elk zwart punt in onderstaand diagram een antilope is, dan is de omliggende gekleurde regio het gebied van alle punten die dichter bij die antilope liggen dan bij gelijk welke andere antilope. Als een leeuw jouw regio binnenkomt, dan ben jij de antilope die zal opgegeten worden.

Voronoi-betegeling (Euclidische afstand)
Voronoi-betegeling die aangeeft waar de 20 antilopes (zwarte punten) zullen opgegeten worden door een leeuw. Hierbij werden de regio's bepaald op basis van de Euclidische afstand.

Dit inzicht helpt om bepaalde vormen van kuddegedrag te verklaren. Elk dier wil immers zijn "gevarenregio" zo klein mogelijk maken en zich zo ver mogelijk van het roofdier bevinden. Dominante dieren hebben de neiging om de meest gunstige posities nabij het midden in te nemen, terwijl ondergeschikte dieren naar de randen geduwd worden. De hele formatie evolueert continu terwijl roofdier en prooi zich verplaatsen.

wenkkrab
Wenkende mannelijke wenkkrab (Uca perplexa) met een citroengele schaar.

Studies hebben aangetoond dat kolonies wenkkrabben3 de neiging hebben om zich bijzonder snel op te stellen volgens Voronoi-patronen wanneer een roofdier ten tonele verschijnt, en om dichter samen te hokken naarmate het gevaar toeneemt omdat elke krab probeert om zijn omliggende veelhoek kleiner te maken. Dit leidt er in feite toe dat sommige krabben zich dichter naar het roofdier verplaatsen in een poging om het centrum te bereiken en andere krabben tussen zichzelf en de jager te positioneren. Krabben die de bewegingsregels overtreden, hebben de neiging om er uitgepikt te worden, wat de evolutionaire kracht van de strategie verder versterkt.

aangevallen wenkkrabben
Voronoi-betegeling van een kolonie wenkkrabben (a) voor en (b) na een aanval door een klapperral (Rallus crepitans). De aanval komt van beneden.

Opgave

Beschouw een rechthoekig gebied waarin een kudde antilopen aan het grazen is. We delen het gebied op in cellen die een rechthoekig rooster vormen, zodat elke cel hoogstens één antilope bevat. De cellen van het rooster waarin er zich een antilope bevindt markeren we met een unieke hoofdletter. De overige cellen markeren we met een punt. Daardoor kunnen de posities van de antilopen in het gebied aangegeven worden op een kaart die de volgende vorm aanneemt:

......B..
.........
...A.....
.........
.......D.
.........
.C.......
.....E...
.........

De positie van een cel in het rooster wordt voorgesteld door een tuple $$(r, k)$$. Hierbij stelt $$r$$ (int) het rijnummer en $$k$$ (int) het kolomnummer voor van de cel in het rooster. De rijen en kolommen van het rooster worden respectievelijk van boven naar onder en van links naar rechts genummerd vanaf 0.

Je opdracht bestaat erin om aan de hand van een Voronoi-betegeling het gebied in te delen in regio's rond de verschillende antilopen. De regio rond een antilope bestaat uit de cel waarin de antilope zich bevindt, samen met alle andere cellen die zich dichter bij die antilope bevinden dan bij elke andere antilope. Hierbij gebruiken we verschillende definities voor het bepalen van de afstand tussen twee cellen op posities $$(x_1, y_1)$$ en $$(x_2, y_2)$$ in het rooster:

naam formule
Euclidische afstand $$d=\sqrt{(x_1-x_2)^2 + (y_1-y_2)^2}$$
Manhattan-afstand $$d=|x_1-x_2| + |y_1-y_2|$$
schaakbord-afstand $$d=\max(|x_1-x_2|,|y_1-y_2|)$$

Onderstaande diagrammen tonen aan dat de formule die gebruikt wordt om de afstand te bepalen wel degelijk een invloed heeft op de vorm van de regio's in de Voronoi-betegeling.

Voronoi-betegeling (Euclidische afstand)
Voronoi-betegeling die aangeeft waar de 20 antilopes (zwarte punten) zullen opgegeten worden door een leeuw. Hierbij werden de regio's bepaald op basis van de Euclidische afstand.
Voronoi-betegeling (Manhattan-afstand)
Voronoi-betegeling die aangeeft waar de 20 antilopes (zwarte punten) zullen opgegeten worden door een leeuw. Hierbij werden de regio's bepaald op basis van de Manhattan-afstand.

Een afstandsfunctie is een functie waaraan de posities van twee punten in het vlak moeten doorgegeven worden. De positie van een punt in het vlak is een tuple $$(x, y)$$ met $$x, y \in \mathbb{R}$$ (float). Een afstandsfunctie geeft altijd een reëel getal (float) terug dat de afstand uitdrukt tussen de twee gegeven punten volgens een bepaalde afstandsdefinitie. Gevraagd wordt:

Voor het bepalen van de afstand tussen twee cellen van een rooster moeten de functies dichtste_antilopen en regios gebruikmaken van een afstandsfunctie die kan doorgegeven worden aan een optionele parameter afstand. De Euclidische afstand moet gebruikt worden indien er niet expliciet een waarde wordt doorgegeven aan deze parameter.

Voorbeeld

In onderstaande voorbeeldsessie gaan we ervan uit dat het bestand kudde.txt4 zich in de huidige directory bevindt.

>>> euclidische_afstand((0, 0), (3, 4))
5.0
>>> manhattanafstand((0, 0), (3, 4))
7.0
>>> schaakbordafstand((0, 0), (3, 4))
4.0

>>> kudde('kudde.txt5')
(9, 9, {(2, 3): 'A', (0, 6): 'B', (6, 1): 'C', (4, 7): 'D', (7, 5): 'E'})

>>> posities = {(2, 3): 'A', (0, 6): 'B', (6, 1): 'C', (4, 7): 'D', (7, 5): 'E'}
>>> dichtste_antilopen((0, 0), posities)
{'A'}
>>> dichtste_antilopen((3, 5), posities, afstand=manhattanafstand)
{'A', 'D'}
>>> dichtste_antilopen((2, 5), posities, afstand=schaakbordafstand)
{'A', 'B', 'D'}

>>> print(regios('kudde.txt6'))
aaaabbBbb
aaaaabbbb
aaaAaabdd
aaaaaaddd
ccaaaddDd
cccceeddd
cCcceeedd
ccceeEeee
ccceeeeee
>>> print(regios('kudde.txt7', afstand=manhattanafstand))
aaaabbBbb
aaaaabbbb
aaaAaabdd
aaaaaaddd
ccaaaddDd
cccaeeddd
cCcceeedd
ccceeEeee
ccceeeeee
>>> print(regios('kudde.txt8', afstand=schaakbordafstand))
aaaaabBbb
aaaaabbbb
aaaAaabbb
aaaaaaddd
caaaaadDd
ccccedddd
cCcceeedd
cccceEeed
cccceeeee

Bronnen