Java - Distanzmatrix Algorithmus, Wie ansetzen?

2 Antworten

Mir ist nicht ganz klar, wo Dein Problem steckt. Soweit ich erkennen kann, gilt:

  • Aⁿ enthält die Zahl der n-Pfade von i nach j. Interessant ist nur, ob da eine 0 steht oder nicht.
  • Dⁿ enthält die minimale Pfadlänge von i nach j, oder ∞, wenn es keinen Pfad der Länge ≤n gibt.

Um Dⁿ aus Dⁿ⁻¹ und Aⁿ zu berechnen, schaust Du Dir einfach jeden noch unbekannten Wert Dⁿ⁻¹(i,j)=∞ an und überschreibst ihn mit Dⁿ(i,j):=n, falls ein n-Pfad von i nach j existiert, also Aⁿ(i,j)>0 ist:

boolean update ( int[][] D, int[][] An, int n )
{
    boolean changed = false;
    for ( int i=0; i<D.length; ++i )
        for ( int j=0; j<D.length; ++j )
            if ( D[i][j]>n && An[i][j]>0 )
            {
                D[i][j] = n;
                changed = true;
            }
    return changed;
}

Wenn es keine Änderungen mehr gibt, kann man abbrechen. Das klappt auch, wenn der Graph nicht zusammenhängend ist und einige Distanzen noch ∞ sind.

Man schaut sich jetzt alle Nuller (außer die Hauptdiagonale von der Eingangsmatrix an (siehe Bild 1)) und markiert sich nur die Zahlen (rot), die sich von der Potenzierung der Eingangsmatrix verändert haben.

Ich sehe keinen Grund, die Werte in Aⁿ irgendwie zu markieren. Du prüfst einen Eintrag Aⁿ(i,j) doch eh nur, wenn bisher noch kein Pfad von i nach j gefunden wurde.

Übrigens würde ich mit D⁰ statt D¹ anfangen: D⁰(i,j):=∞, D⁰(i,i):=0. Dein D¹ berechnet sich beim ersten update(D⁰, A¹, 1).


HabboHacker09 
Beitragsersteller
 16.06.2021, 20:34

Danke für den Kommentar, es hat mir auf jeden Fall weiter geholfen!

Aber es geht leider immer noch nicht bzw warhscheinlich habe ich etwas übersehen..

Mein Code für die Berechnung der Distanzmatrix schaut jetzt so aus:

   public void Distanzmatrix() throws PersonalException

   {

      int[][] distanzMatrix = new int[dimension][dimension];

      int[][] neuePotenz = new int[20][20];

      @SuppressWarnings("unused")

      int hauptdiagonale;

      int unendlich = -9;

         // Hauptdiagonale der Matrix wird erfasst und gespeichert. Alle restlichen Nuller werden als "unendlich" bezeichnet und gespeichert //

      for (int i = 0; i < Matrix.length; i++)

      {

          for (int j = 0; j < Matrix[i].length; j++)

          {

             if(i == j)

             {

                hauptdiagonale = this.Matrix[i][j];

             }

             else if (Matrix[i][j] == 0)

             {

                this.Matrix[i][j] = unendlich;

             }   

             // System.out.print(Matrix[i][j] + "     ");

          }

          System.out.println();

      }

      System.out.println();

         // Speichert die jetzige Matrix in "distanzMatrix" //

         for (int i = 0; i < Matrix.length; i++)

          {

              for (int j = 0; j < Matrix[i].length; j++)

              {

                 distanzMatrix[i][j] = Matrix[i][j];

                  System.out.print(distanzMatrix[i][j] + " ");    

              }

              System.out.println();

          }

//Ab hier beginnt der Teil den du mir erklärt hast

         for(int k = 1; k < Matrix.length; k++)

         {

         update(distanzMatrix, neuePotenz, k);

            for(int i = 0; i < Matrix.length; i++)

            {

               for (int j = 0; j < Matrix.length; j++)

               {

                  if (neuePotenz[i][j] > 0 && distanzMatrix[i][j] == unendlich)

                  {

                     distanzMatrix[i][j] = k;

                  }

                  System.out.println(distanzMatrix[i][j]);

               }

            }

         }

      }

   public boolean update (int[][] D, int[][] An, int n)

   {

      boolean changed = false;

      for (int i = 0; i < D.length; i++ )

          for (int j = 0; j < D.length; j++ )

              if (D[i][j] > n && An[i][j] > 0 )

              {

                  D[i][j] = n;

                  changed = true;

              }

      System.out.println(changed);

      return changed;

   }

Danke!!!

1
HabboHacker09 
Beitragsersteller
 16.06.2021, 20:40

Meine Ausgabe auf der Konsole habe ich unten als eigenen Kommentar gepostet

0
ralphdieter  16.06.2021, 23:34
@HabboHacker09

Der Code ist etwas aus dem Zusammenhang gerissen. Ich nehme an, dass Matrix und this.Matrix dasselbe sind und die Adjazenzmatrix darstellen.

Problem 1:

Du initialisiert die distanzMatrix falsch. Du darfst Matrix dabei nicht ändern, weil Du sie noch mehrfach brauchst. So sollte es aussehen:

     int[][] distanzMatrix = new int[dimension][dimension];
     int unendlich = -9;
     for (int i = 0; i < Matrix.length; i++)
     {
         for (int j = 0; j < Matrix[i].length; j++)
         {
            if(i == j)
            {
               // (i,i) hat die Distanz 0:
               distanzMatrix[i][j] = 0;
            }
            else if (Matrix[i][j] == 0)
            {
               // (i,j) ohne Kante haben eine unbekannte Distanz:
               distanzMatrix[i][j] = unendlich;
            }
            else
            {
               // (i,j) mit Kante haben die Distanz 1:
               distanzMatrix[i][j] = 1;
            }
            // System.out.print(distanzMatrix[i][j] + "    ");
         }
         System.out.println();
     }

Problem 2:

//Ab hier beginnt der Teil den du mir erklärt hast
        for(int k = 1; k < Matrix.length; k++)

Du hast oben bereits alle Pfade der Länge 0 und 1 gesetzt. Jetzt suchst Du nach weiteren Pfaden ab Länge k=2.

Problem 3:

           update(distanzMatrix, neuePotenz, k);
           for(int i = 0; i < Matrix.length; i++)
           {
              //...

Meine update-Funktion macht praktisch dasselbe wie Dein nachfolgender Schleifenrumpf. (Nur habe ich angenommen, dass ∞ sehr groß ist. Mein Test D[i][j]>n funktioniert für -9 nicht, und deshalb tut meine Funktion effektiv nichts. Aber so oder so: Die doppelte Suche nach Pfaden der Länge k ist zwar nicht falsch, aber völlig überflüssig. Lass den update()-Aufruf einfach wieder weg.

Problem 4:

Du verwendest zwar neuePotenz für Matrix^k, berechnest sie aber nie. Das muss in jedem Schleifendurchlauf passieren:

        int[][] neuePotenz = Matrix; // "Matrix hoch 1"
        for(int k = 2; k < Matrix.length; k++)
        {
           // Matrix hoch k-1 --> Matrix hoch k:
           neuePotenz = malMatrix(neuePotenz);
           for(int i = 0; i < Matrix.length; i++)
           {
              //...

Beachte, dass malMatrix() das übergebene Argument nicht ändern darf, sondern eine neue Matrix erzeugen und zurückgeben muss:

  public int[][] malMatrix(int[][] faktor)
  {
     int[][] produkt = new int[Matrix.length][Matrix.length];

     for (int i = 0; i < Matrix.length; i++)
     {
        // produkt[i][j] berechnen
     }
     return produkt;
  }
1
HabboHacker09 
Beitragsersteller
 17.06.2021, 01:18
@ralphdieter

VIELEN VIELEN VIELEN DANK!!! Ich habe es endlich geschafft !!! Nur dank dir!!

Tausend Dank !!!!

Danke!
Hoffe du hast noch einen angenehmen Tag

0