Frösche und Schildkröten

… oder: Wie entsteht Segregation? Mitchel Resnick erzählt uns eine nette Geschichte: In einem Teich lebten Frösche und Schildkröten in trauter Eintracht zusammen. Jeder Frosch lebt auf einer Seerose und hat auf den acht benachbarten anliegenden Seerosen je vier Frösche und je vier Schildkröten als Nachbarn. (Man erkennt leicht, daß es sich um quadratische Seerosen mit einer Moore-Nachbarschaft handelt.) Doch eines Tages kommt ein böser Sturm auf und wirbelt alles durcheinander und auch etliche Frösche und Schildkröten kommen (zu gleichen Teilen) dabei um. Als sich der Sturm gelegt hat, versuchen die Tiere sich wieder zu organisieren und es sich auf den Seerosen gemütlich zu machen. Sie sind jedoch nur glücklich, wenn sie mindestens drei Nachbarn haben, die der gleichen Spezies angehören, ansonsten versuchen sie, eine andere, freie Seerose zu besiedeln. Und was passiert dabei? Es entstehen Kolonien, die nur von Schildkröten und andere Kolonien, die nur von Fröschen bevölkert werden. Eine vorbeifliegende Eule wundert sich und fragt einen Frosch, ob sie sich denn nicht mehr lieb haben würden. »Doch, wir haben uns lieb wie eh und je. Nur … es passiert einfach, daß wir zusammenziehen, unter der einzigen Voraussetzung, daß wir mindestens drei Nachbarn unserer Spezies haben wollen. Und den Schildkröten geht es genauso.«

Schauen wir uns daß doch einfach einmal an:

image

Bildschirmausgabe des Processing-Sketches: Links der Startzustand, rechts der Zustand nach etwa 100.000 Schritten. Die maximale Sprungdistanz beträgt 3.

Resnick hat das natürlich in StarLogo programmiert, ich habe ein leicht abgewandeltes Processing-Programm geschrieben, mit dem man das Verhalten untersuchen kann. Beim Start verteilen wir zufällig die Schildkröten und Frösche zu gleichen Teilen auf einem 50x50-Raster, wobei etwa 30 Prozent leer bleiben, damit sich die Viecher auch bewegen können. In jedem Durchlauf wird zufällig ein Bewohner ausgewählt und er wird gefragt, ob er glücklich sei. Glücklich ist er nur, wenn er wenigstens drei Nachbarn hat, die der gleichen Spezies angehören. Ist er glücklich, bleibt er da sitzen wo er ist. Ist er unglücklich, sucht er zufällig in der Nachbarschaft in seiner Sprungdistanz (ja, in meiner Geschichte können auch Schildkröten springen) eine Seerose aus. Ist diese Seerose frei, springt er dahin, hoffend, dort glücklich zu werden. Ist das Feld nicht frei, bleibt er hocken und hofft auf eine neue Chance, wieder ausgewürfelt zu werden.

Läßt man diese Simulation nun laufen, stellt man fest, daß sich tatsächlich Cluster gleicher Spezies bilden. Die kleinste stabile Einheit ist ein Quadrat mit der Kantenlänge zwei – hier hat jeder mindestens drei Nachbarn. Außerdem ist eine Flucht von den Rändern weg zu beobachten. Hier habe ich einfach angenommen, daß das Wasser so flach ist, daß dort keine Seerosen gedeihen – die Ränder werden also nicht periodisch fortgesetzt. Und so hat man an den Rändern natürlich weniger Nachbarn und die Chance, glücklich zu sein, ist geringer.

Außerdem kann es vorkommen, daß einzelne Tiere regelrecht von der benachbarten Spezies eingekesselt werden und sie nicht mehr fliehen können. Die Armen sind zu einem ewigen Unglücklichsein verdammt. Hier hilft nur, die maximale Sprungdistanz zu erhöhen.

Überhaupt: Obige Screenshots stammen von einem Sketch mit einer Sprungdistanz von drei. Erhöht man diesen Wert (zum Beispiel auf fünf), dann geht nicht nur die Clusterbildung schneller vonstatten, sondern auch die Zahl der eingekesselten Tiere geht massiv zurück.

Was uns dieses einfache Programm über die tatsächliche Segregation erzählt, überlasse ich aber der Phantasie meiner Leserinnen und Leser.

Quellcode

int EMPTY  = 0;
int FROG   = 1;
int TURTLE = 2;

int rows = 50;
int cols = 50;
int maxdist = 3;
int counter = 0;

int neighboorhood [][] = new int[rows][cols];
int neighboorX;
int neighboorY;

int w = 6;
int h = 6;

void setup() {
  size(rows*w, cols*h);
  smooth();
  noStroke();
  background(0);
  for (int i = maxdist; i < (rows - maxdist); i++) {
    for (int j = maxdist; j < (cols - maxdist); j++) {
      switch(round(random(2))) {
      case 0:
        neighboorhood[i][j] = EMPTY;
        break;
      case 1:
        neighboorhood[i][j] = FROG;
        fill(174, 221, 60);
        ellipse(i*w + w/2, j*h + h/2, w, h);
        break;
      case 2:
        neighboorhood[i][j] = TURTLE;
        fill(129, 130, 87);
        ellipse(i*w + w/2, j*h + h/2, w, h);
        break;
      }
    }
  }
}

void draw() {
  smooth();
  noStroke();
  background(0);
  boolean happy = false;
  int actorX = int(random(rows));
  int actorY = int(random(cols));
  if (neighboorhood[actorX][actorY] > 0) {
    happy = happyness(neighboorhood[actorX][actorY], actorX, actorY);
    if (!happy) {
      int newX = round(random(-maxdist, maxdist));
      int newY = round(random(-maxdist, maxdist));
      newX += actorX;
      newY += actorY;
      if ((newX >= maxdist) && (newX < rows - maxdist) && (newY >= maxdist) && (newY < cols - maxdist)) {
        if (neighboorhood[newX][newY] == EMPTY) {
          neighboorhood[newX][newY] = neighboorhood[actorX][actorY];
          neighboorhood[actorX][actorY] = EMPTY;
        }
      }
    }
  }
  counter++;
  if ((counter % 100) == 0) {
    print(counter + " -- ");
  }
  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      int lilypond = neighboorhood[i][j];
      switch(lilypond) {
      case 0:
        break;
      case 1:
        fill(174, 221, 60);
        ellipse(i*w + w/2, j*h + h/2, w, h);
        break;
      case 2:
        fill(129, 130, 87);
        ellipse(i*w + w/2, j*h + h/2, w, h);
        break;     
      }
    }
  }
}

boolean happyness(int _animal, int _x, int _y) {
  int x = _x;
  int y = _y;
  int animal = _animal;
  int happy = 0;
  if (neighboorhood[x][y-1]   == animal) {
    happy += 1;
  }
  if (neighboorhood[x+1][y-1] == animal) {
    happy += 1;
  }
  if (neighboorhood[x+1][y]   == animal) {
    happy += 1;
  }
  if (neighboorhood[x+1][y+1] == animal) {
    happy += 1;
  }
  if (neighboorhood[x][y+1]   == animal) {
    happy += 1;
  }
  if (neighboorhood[x-1][y+1] == animal) {
    happy += 1;
  }
  if (neighboorhood[x][y+1]   == animal) {
    happy += 1;
  }
  if (neighboorhood[x-1][y]   == animal) {
    happy += 1;
  }
  if (happy >= 3) {
    return true;
  }
  else {
    return false;
  }
}

Quelle(n)




Sie sind hier: StartProgrammierungCreative CodingProcessing → froescheundschildkroeten.txt


Suche

Werkzeuge