Räuber Beute Simulation -- Overhead ?

earlgrey_tea

Aktives Mitglied
Liebe Java-Freunde,

es handelt sich bei meinem Posting um ein Crossposting aus einem anderen Java-Froum. Java-Uni Forum Leider hat dort niemand momentan Zeit und Muße sich meinem Problem zu widmen. Somit hoffe ich, dass ihr mir weiterhelfen könnt.

Als kleine Übung habe ich ein Programm geschrieben, das die Entwicklung von Räuber-Beute-Populationen simuliert. Das Programm soll nicht objektorientiert sein, sondern ich möchte das Ganze mit arrays verwirklichen (OO sol erst später kommen).

In dem Programm sollen Hasen 15 Jahre alt werden, Füchse 20 Jahre alt. Hasen sterben, wenn sie auf dem gleichen Feld sind wie ein Fuchs, Füchse sterben, wenn sie nach 4 Generationen nichts zu essen bekommen habe.


Mein erstes Programm hat zwei Probleme:

1. Wenn ich das Programm laufen lasse, komme ich nur bis Generation 4.; anschließend 'hängt' mein Rechner. Habe ich irgendeine missmutige Einstellung übersehen?

2. Wenn ich mir den Programmtext ansehe, dann beschleicht mich das ungute Gefühl zu viele Zeilen Code produziert zu haben. :) Hat jemand von euch vielleicht eine Idee, wie ich das Programm 'schlanker' gestalten kann (ohne Objektorientierung)?

Meine Lösung:

Java:
 1 import java.util.Random;
 2 
 3 public class räuberbeute2 {
 4     public static int hasenzahl;
 5     public static int fuchszahl;
 6     public static int weltgroesse = 20;
 7 public static void printtiere (int [][][] hase, int [][][] fuchs){
 8     hasenzahl = 0;
 9     fuchszahl = 0;
10     for (int i = 0; i < weltgroesse; i++){
11             for (int j = 0; j < weltgroesse; j++){
12                 if (hase[i][j][0] > 0){
13                     System.out.print("H ");
14                     hasenzahl++;
15                 }
16                 else if(fuchs[i][j][0] >= 1){
17                     System.out.print("F ");
18                     fuchszahl++;
19                 }
20                 else System.out.print(" ");
21             }
22             System.out.println();
23         }
24     }
25 public static void verteile (int [][][] tier, int nachkommen, int lebenszeit){
26 int i = 0;
27 int Zufall1, Zufall2;
28 int Kinder;
29 if (lebenszeit == 13){
30            Kinder = nachkommen * fuchszahl;
31 }
32 else        Kinder = nachkommen * hasenzahl;
33 Random generator = new Random ();
34 while (i <= Kinder){
35     Zufall1 = generator.nextInt(weltgroesse);
36     Zufall2 = generator.nextInt(weltgroesse);
37     switch (lebenszeit){
38         case 13:
39     if ((tier[Zufall1][Zufall2][0] <= 0 )){
40         tier[Zufall1][Zufall2][0] = lebenszeit;
41         tier[Zufall1][Zufall2][1] = 4;
42         i++;
43     }
44     else{
45         break;
46         }
47         case 9:
48     if (tier[Zufall1][Zufall2][0] <= 0  ){
49         tier[Zufall1][Zufall2][0] = lebenszeit;
50         i++;
51     }
52     else;
53     break;
54          }
55     }
56 }
57 public static void vergleichen (int [][][] hase, int [][][] fuchs ){
58     for (int i = 0; i< weltgroesse; i++){
59         for (int j = 0; j < weltgroesse; j++){
60             if ((hase[i][j][0] >= 1) && (fuchs[i][j][0] >= 1)){
61                 if (fuchs[i][j][1] >= 1){
62                 hase[i][j][0] = 0; 
63                 fuchs[i][j][0] -= 1;
64                 }
65                 else{
66                 fuchs[i][j][0] = 0;
67                 }
68             }
69             else if (fuchs[i][j][1] < 1){
70                 fuchs[i][j][0] = 0;
71             }
72             else {
73                 hase[i][j][0] -= 1;
74                 fuchs[i][j][1] -= 1;
75                 fuchs[i][j][0] -= 1;
76             }
77         }
78     }
79 }
80 public static void main(String[] args) {
81 
82             int [][][] hase = new int [weltgroesse][weltgroesse][2];
83             int [][][] fuchs = new int [weltgroesse][weltgroesse][2];
84             int v = 0;
85         for (int k = 0; k <= 20; k++){
86             System.out.println();
87             System.out.println("Generation"+k+":");
88             räuberbeute2.verteile(hase, 5, 9);
89             räuberbeute2.verteile(fuchs, 1, 13);
90             räuberbeute2.vergleichen(hase, fuchs);
91             räuberbeute2.printtiere(hase, fuchs);
92             System.out.print("Fuchszahl:"+fuchszahl+";");
93             System.out.println("Hasenzahl:"+hasenzahl);
94            
95            }
96      }
97 }
98 
99

nach einigem Tüfteln hab ich versucht das Programm etwas kleiner zu halten. Trotzdem hab ich noch immer das Problem, dass sich der Rechner nach eingen "Generationen" aufhängt.

Neues Programm (nach der Volterra-Formel) >> Hier <<:
Java:
import java.util.Random;
public class räuberbeute3 {
    // für mehr Flexibilität können hier Instanzvariablen definiert werden.
    public static int welt = 100;
 
public static void printMatrix (int [][] Wiese, int k){
int räuber, beute;
räuber = 0;
beute = 0;
System.out.println();
System.out.println(k+". Generation");
    for (int i = 0; i < welt; i++){
        for (int j = 0; j < welt; j++){
            if (Wiese[i][j] == 2){
                System.out.print("F ");
                räuber++;
            }
            else if (Wiese[i][j] == 1){
                System.out.print("§ ");
                beute++;
            }
            else System.out.print("- ");
        }
        System.out.println();
    }
System.out.print("Hasen:"+beute+" ;  ");
System.out.println("Füchse:"+räuber+" ;  ");
}
 
public static void matrixTier(int [][] Wiese, double räuber, double beute){
    Random generator = new Random ();
    int Zufall1, Zufall2;
    int i;
    i = 0;
    while (i <= räuber) {
    Zufall1 = generator.nextInt(welt);
    Zufall2 = generator.nextInt(welt);
        if (Wiese[Zufall1][Zufall2] == 0){
            Wiese[Zufall1][Zufall2] = 2;
            i++;
            }
        else;
    }
    i = 0;
    while (i <= beute){
    Zufall1 = generator.nextInt(welt);
    Zufall2 = generator.nextInt(welt);
        if (Wiese[Zufall1][Zufall2] == 0){
            Wiese[Zufall1][Zufall2] = 1; // markiert für die print einen Hasen
            i++;
            }
        else;
    }
 
}
public static double räuberZahl (double y, double c, double d, double x){
    double räuber;
    räuber = y * (1-c+d*x);
    return räuber;
}
public static double hasenZahl (double x, double a, double b, double y){
    double hasen;
    hasen = x * (1+a-b*y);
    return hasen;
}
 
    public static void main(String[] args) {
        int [][] Wiese = new int [welt][welt];
        double raub, baut;
        raub = räuberZahl(20.0, 0.3, 0.005, 100.0 );
        baut = hasenZahl(100.0, 0.4, 0.01, 20.0);
        System.out.println("Räuber:"+raub);
        System.out.println("Beute:"+baut);
        räuberbeute3.matrixTier(Wiese, raub, baut);
        räuberbeute3.printMatrix(Wiese, 1);
        double räuber = raub;
        double beute = baut;
    for (int k = 2; k < welt; k++){
        raub = räuberbeute3.räuberZahl(räuber, 0.3, 0.005, beute);
        baut = räuberbeute3.hasenZahl(beute, 0.4, 0.01, räuber);
        System.out.println("Räuber:"+raub);
        System.out.println("Beute:"+baut);
        räuberbeute3.matrixTier(Wiese, raub, baut);
        räuber = raub;
        beute = baut;
        räuberbeute3.printMatrix(Wiese, k);
        }
    }
 
}

Vielleicht könnt ihr mir weiterhelfen? Was habe ich übersehen?
Es wäre super, wenn ihr mir mit beiden Programmen behilflich sein könntet.

Viele Grüße
earlgrey_tea
 
S

SlaterB

Gast
eine while-Schleife mit Random und if drin kann immer endlos laufen,
was ist wenn die Wiese komplett voll ist?

zur Sicherheit kann man technisch immer eine Lauf-Variable für solche Schleifen hochzählen und nach 100.000 Versuchen mit Fehlermeldung abbrechen
 

earlgrey_tea

Aktives Mitglied
Mensch super, genau das Problem mit der "vollen Wiese" tritt bei mir auf.
Werd mich heute Abend mal drum kümmern, oder hast du spontan einen Vorschlag wie man das schöner lösen kann?
Vielen Dank für die schnelle Antwort
Grüße earlgrey_tea
 
S

SlaterB

Gast
du könntest das Feld einmal durchlaufen und die Zahl der freien Felder zählen oder diese gar separat in einer Variable aktuell halten,
dann bei 0 entsprechend reagieren, was immer dein Programm bei einer volle Wiese machen soll,
ansonsten eine Zufallszahl x von 0 bis n bestimmten
und in einem zweiten Durchlauf genau die x.-Stelle finden

bei leeren Feldern etwas aufwendig, hmm
 

earlgrey_tea

Aktives Mitglied
@SlaterB:

Dein Tipp funktioniert soweit, leider ist er nicht besonders schön ;) (is nicht bös gemeint;. mir ist gar nichts eingefallen :D).

Hab folgende Änderungen vorgenommen:

Zeile 5: [JAVA=5]public static int freifeld; [/code]
Zeile 23 [JAVA=23]freifeld++;[/code]
Zeile 84 [JAVA=84]if (freifeld < 260){
räuber = 1;
beute = 2 ;
}
else{
räuber = raub;
beute = baut;}[/code]

260 war ein Erfahrungswert für eine Welt der Größe 20 * 20.

Haltet mich für "besessen" , aber ist nicht eigentlich der Witz an so einer Räuber-Beute Simulation, dass das Ganze ewig läuft, aufgrund der Anpassung der beiden Populationen aneinander? Bei mir schießen die Werte in eigenartige Höhen und nehmen nicht wie zu erwarten ab. Ich glaube ja, dass sich noch ein 'mittelschwerer' Fehler in dem Programm versteckt, leider kann ich ihn partout nicht entdecken.

Liebe Grüße
earlgrey_tea
 
Zuletzt bearbeitet:
S

SlaterB

Gast
nur weil man irgendwas programmiert wird es nicht automatisch richtig,
du musst doch gewisse Simulationsregeln aufbauen, dir irgendwas dabei gedacht haben,

soweit ich das bisher sehe ist die Matrix ganz egal, es geht nur um die Berechnung der Anzahl Tiere
aus 100 Hasen werden in einem Schritt 140, um diese 40 Wachstum auszugleichen bräuchte es nach deiner Formal 4000 Füchse,
etwas unrealistisch, sollte es nicht schon bei Gleichstand von Fuchs und Hase mit den Hasen abwärts gehen?

andererseits ist das Wchstum der Fuchse sehr begrenzt, vom Startwert 20 aus verlieren sie nach Formel 6 pro Runde,
um das auszugleichen, müssten bereits 1000 Hasen vorhanden sein,
erst dann vermehren sich die Füchse langsam im einstelligen Bereich, während bei den Hasen gleich 400 dazukommen

na du kannst ja die Formel weiter durchlaufen lassen, ohne die nervige Matrix nebenher,
mit anderen Parametern wirds anders aussehen, auch an quadratische Formeln denken,
y*y verstärkt den Faktor der anderen Rasse ungemein
 

earlgrey_tea

Aktives Mitglied
SlaterB hat gesagt.:
nur weil man irgendwas programmiert wird es nicht automatisch richtig,
du musst doch gewisse Simulationsregeln aufbauen, dir irgendwas dabei gedacht haben,
so vermessen bin ich zum Glück nicht. :)
Ich gestehe ehrlich, dass ich die Formel zunächst enfach so übernommen habe, ohne sie nachzuprüfen. Ich hab sie jetzt auch mal ohne die Matrix laufen lassen und exorbitant hohe Werte bekommen. Lief aber ohne Probleme. Ich denke, dass es wahrscheinlich das Besete ist, wenn ich mich nochmal umschaue, ob es nicht eine 'bessere' Version der Formel gibt; oder:
SlaterB hat gesagt.:
na du kannst ja die Formel weiter durchlaufen lassen, ohne die nervige Matrix nebenher,
mit anderen Parametern wirds anders aussehen, auch an quadratische Formeln denken,
y*y verstärkt den Faktor der anderen Rasse ungemei
Auf jeden Fall werd ich mir mit deinen Tipps auch nochmal das erste Programm vorknöpfen, das zweite ist ja eher aus der Wut heraus entstanden.
 

Neue Themen


Oben