Wolfram zelluläre Automaten

Halli

Mitglied
Hallo,

ich bräuchte dringend Hilfe.
Ich soll für ein Modul in meiner Uni Wolframs zelluläre Automaten in java programmieren. Leider kenne ich mich in java nicht so gut aus und bekomme das nicht hin.
Das Programm soll drei Parameter akzeptieren Regelnummer (z.B. 130),Zahl der Generationen (z.B. 300), Maximale Breite (z.B. 150).

Ich hoffe ihr könnt mir helfen

Danke schon mal :)
 

minzee

Bekanntes Mitglied
Grundsätzlich kenn ich mich mit solchen Automaten aus. Nur sagt mir dieser Wolfram-Automat nichts. Ich bräuchte etwas zu lesen dazu.

Gibt es einen Video-Stream zu euren Vorlesungen im Internet? Würde mich wirklich sehr interessieren!!!!! :)
 
Zuletzt bearbeitet:

JavaMeister

Gesperrter Benutzer
Nur sagt mir dieser Wolfram-Automat nichts.

hihi ^^ => Wolfram Automaten nennt man auch: Zellulärer Automat. Noch vor kurzem hast du dich damit beschäftigt.

Und die exakte Lösung, die man von Python nach Java übersetzen muss, schafft es alle Regeln mit 256 zu berechnen und auszugeben: Wikipedia nach wenigen klicken.

Zellul

Wenn wir dabei helfen sollen, sag bescheid, wo die Probleme sind ;D
 

minzee

Bekanntes Mitglied
Achso, das ist das Gleiche. Vielleicht habe ich das schon irgendwo gelesen, aber wieder vergessen :oops:

Soll der Automat 1-dimensional sein? Ohne spezielle Randbehandlung? Und der Ablaufmodus synchron? Und wie soll der Anfangszustand aussehen? Und mit wie vielen Nachbarn (Radius)?

Ich glaube, die Frage nach dem Radius war unnötig, kann nur 1 sein, richtig? Ist der Anfangszustand eine 1 in der Mitte? Und bei der Randbehandlung außen eine 0 annehmen?
 
Zuletzt bearbeitet:

Halli

Mitglied
Ja er soll 1-dimensional sein. Keine spezielle Randbehandlung. Der Anfangszustand ist eine 1.
Unser Dozent hat sonst dazu nichts weiter gesagt.
 

JavaMeister

Gesperrter Benutzer
Unser Dozent hat sonst dazu nichts weiter gesagt.

Zur Kentniss genommen.

Heißt das aber auch, dass wir hier keine weitere Eigeninitiative von Dir erwarten müssen? - Oder was möchtest Du nun mit diesem Thread erreichen?

Es besteht die Gefahr, dass minzee hier eine Lösung postet, die du dann abgibst.
 

minzee

Bekanntes Mitglied
Dann vermute ich einfach mal, dass die 1 in der Mitte sein soll. Ich versuche, das heute Nacht zu programmieren und poste es dann rein.

EDIT:
Es besteht die Gefahr, dass minzee hier eine Lösung postet, die du dann abgibst.
Jo :)
 
Zuletzt bearbeitet:

minzee

Bekanntes Mitglied
Java:
class Main
{
   /**
    * @param int rule 0 bis 255
    * @param int count >= 0 Anzahl der Durchläufe
    * @param int width Gitter-Breite
    * @return int[]
    */
   private static int[] module(int rule, int count, int width)
   {
      // Gitter definieren:
      int[][] states = new int[2][width];
      
      // Startzustand:
      int target = 0;
      states[target][width / 2] = 1;
      
      // rule in Array ablegen:
      int[] ruleStates = new int[8];
      for(int j = 0; j < 8; ++j)
      {
         ruleStates[j] = rule % 2;
         rule = rule >> 1;
      }

      // Zellen durchlaufen:
      for
      (
         int source = 0, i = 0; 
         i < count; 
         source = (source + 1) % 2, ++i
      )      
      {
         target = (source + 1) % 2;
         for(int j = 1; j < width - 1; ++j)
         {
            states[target][j] = ruleStates
            [
               4 * states[source][j - 1] + 
               2 * states[source][j] + 
               states[source][j + 1]
            ];
         }
      }
      
      return states[target];
   }
   public static void main(String[] args)
   {
      int states[] = module(30, 15, 31);
      for(int i = 0; i < states.length; ++i)
      {
         System.out.print(states[i]);
      }
   }
}
Würde mich freuen, wenn ich von dir dafür einen Link zu einem Vorlesungsstream bekäme.
 

JavaMeister

Gesperrter Benutzer
Also neben den vielen (sinnlosen) Kommentaren und schlecht formatierten Code, ist mir ein kleiner Fehler aufgefallen. Den möchte ich aber heute Abend zunächst testen.

So auf dem Handy ist das doof.
 

minzee

Bekanntes Mitglied
Dann warten wir jetzt nur noch auf den Meister, auf die Verbesserungsvorschläge und den Hinweis auf den Fehler.
 
Zuletzt bearbeitet:

minzee

Bekanntes Mitglied
Ich habe das jetzt auch mit Threads programmiert:
Java:
class T extends Thread
{
   private int[][] states;
   private int[] ruleStates;
   private int source;
   private int target;
   private int start;
   private int end;
   
   public T(int[][] states, int[] ruleStates, int source, int target, int start, int end)
   {
      this.states = states;
      this.ruleStates = ruleStates;
      this.source = source;
      this.target = target;
      this.start = start;
      this.end = end;
      
      // Thread starten:
      start();
   }
   public void run()
   {
      for(int i = start; i < end; ++i)
      {
         states[target][i] = ruleStates
         [
            4 * states[source][i - 1] + 
            2 * states[source][i] + 
            states[source][i + 1]
         ];
      }
   }
}
class Main
{
   /**
    * Deterministischer Synchroner, 1-dimensionaler Automat ohne Randbehandlung.
    * @param int rule 0 bis 255
    * @param int count >= 0 Anzahl der Durchläufe
    * @param int width > 0 Gitter-Breite
    * @return int[]
    */
   private static int[] module(int rule, int count, int width) throws InterruptedException
   {
      // Gitter definieren:
      int[][] states = new int[2][width];
      
      // Startzustand:
      int target = 0;
      states[target][width / 2] = 1; // alles 0, außer in der Mitte eine 1
      
      // rule in Array ablegen:
      int[] ruleStates = new int[8];
      for(int i = 0; i < 8; ++i)
      {
         ruleStates[i] = rule % 2;
         rule = rule >> 1;
      }
      
      // Anzahl Threads:
      int p = Runtime.getRuntime().availableProcessors();
      int n = Math.min(width - 2, p);
       
      // Anzahl Stati pro Thread:
      double threadWidth = ((double)width - 2.0) / (double)n; 
      
      // Durchläufe:
      for(int i = 0; i < count; ++i)      
      {
         // Bufferzuordnung:
         int source = target;
         target = (target + 1) % 2;
         
         // zu jedem Prozessor 1 Thread;
         int start = 1;
         for(int j = 0; j < n; )
         {
            int end = 1 + (int)Math.round((++j) * threadWidth);
            new T(states, ruleStates, source, target, start, end).join();
            start = end;
         }
      }
      
      return states[target];
   }
   public static void main(String[] args)
   {
      try
      {
         int states[] = module(30, 14, 31);
         for(int i = 0; i < states.length; ++i)
         {
            System.out.print(states[i]);
         }
      }
      catch(InterruptedException e)
      {
         System.out.println("error");
      }
   }
}
Aber mir gefällt das irgendwie nicht. Bei jedem Durchlauf muss ich die Threads neu anlegen. Außerdem muss ich immer so viele Parameter den Threads übergeben. Geht das noch irgendwie schöner?
 
Zuletzt bearbeitet:

minzee

Bekanntes Mitglied
Da ist mir ein Fehler passiert. Der join darf nicht gleich beim Instanzieren passieren. Muss nach der j-Schleife in einer eigenen Schleife passieren.

Habe auch die Zeit gestoppt. Die Thread-Variante ist viel langsamer als die Variante ohne Threads. Liegt an den vielen Thread-Instanzierungen, oder?
 

arilou

Bekanntes Mitglied
Im Allgemeinen rechnet man pro Thread-Erzeugung/-Start irgendwas zwischen 100.000 und 1 Mio. Assemblerbefehle bzw. Prozessortakte. Deine Threads rechnen
4 Additionen
2 Multiplikationen
3 Array-Indexbestimmungen
sagen wir, alles zusammen etwa 20 Operationen bzw. Takte pro Schleifeniteration. Bei 2 Threads sollte (end-start) also möglichst über (5.000 oder 50.000) liegen, damit das was bringt. Und davon ausgehend, dass die ganzen Rechendaten in den CPU-Cache passen, damit die (maximale) Ram-Übertragungsrate nicht beschränkt.
 
Zuletzt bearbeitet:

minzee

Bekanntes Mitglied
Das ist eine wirklich sehr interessante Information. Vielen Dank! :)

Abhaken möchte ich dieses Thema damit aber dennoch nicht. Zellularautomaten können auch 2 und mehrdimensional sein. So ein Zellularautomat könnte z. B. aus 1000 x 1000 Zellen bestehen. Rein gefühlsmäßig würde ich glauben, dass sich Threads dann schon positiv bemerkbar machen könnten, sofern ich es irgendwie schaffe, die Threads nicht bei jedem Durchlauf neu anlegen zu müssen.

Wie siehst du das?
 
Zuletzt bearbeitet:
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben