1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

Branch-and-Bound Distanzmatrix C

  • Früchtemüsli
  • 11. Dezember 2013 um 19:15
  • Unerledigt
  • Früchtemüsli
    6
    Früchtemüsli
    Mitglied
    Reaktionen
    3
    Punkte
    398
    Beiträge
    63
    • 11. Dezember 2013 um 19:15
    • #1

    Hi

    In AlgoDat 2 wird gleich am Anfang eine "Distanzmatrix" erwähnt. Ich suche aktuell den besten Weg, wie man so eine Distanzmatrix anlegen kann.

    Warum ich das Thema nicht in AlgoDat 2 aufgemacht habe? Hatte ich. Aber dort bekam ich kein Feedback . Aber es gibt noch einen anderen Grund: es geht nämlich darum, wie man so etwas ganz grundsätzlich programmiert. Also darum, ob und wie man Informationen zurückgibt oder als Parameter übergibt. Ich hab damit leider ganz grundsätzlich noch Probleme. Ich weiß immer noch nicht, wo ich eine Zahl oder ein Objekt übergeben soll, wo ich etwas zurückgeben soll, oder nicht. Solange mir das Gespühr dafür fehlt, in welchem Stil man das programmiert, mache ich es vielleicht immer falsch.

    Ich hätte jetzt zu diesem konkreten Beispiel 3 unterschiedliche Varianten anzubieten. Hier mal die erste Variante.

    Ich hätte die Klassen BranchAndBoundNode und BranchAndBound. Also keine edge-Klasse.

    Für BranchAndBound:

    insert(key0, value0) // fügt einen Knoten hinzu
    insert(key1, value1)
    edgeDistances(key0, key1, distance01, distance10) // definiert die Distanzen zwischen 2 Knoten

    0 entspricht "von" (erster Knoten), 1 entspricht "nach" (zweiter Knoten).

    Bei jedem insert wird eine BranchAndBoundNode-Instanz angelegt.

    So schaut das bei mir aktuell in PHP aus:

    PHP
    <?php
       error_reporting(~0);
    
       class BranchAndBoundNode
       {
          private $iKey;
          private $value;
    
          function __construct($key, $value)
          {
             $this->setKey($key);
             $this->value = $value;
          }
          private function setKey($key)
          {
             if
             (
                !is_int($key) ||
                $key < 0
             )
                throw new Exception('key');
    
             $this->iKey = $key;
          }
       }
    
       class BranchAndBound
       {
          private $aNode = []; // Alle Knoten.
          private $aDistanceMatrix = []; // Für die Werte einer Distanz-Matrix.
    
          /**
           * Einen node hinzufügen.
           * @param mixed $key
           * @param mixed $value
           */
          function insert($key, $value)
          {
             if(array_key_exists($key, $this->aNode))
                throw new Exception('key');
    
             $this->aNode[$key] = new BranchAndBoundNode($key, $value);
          }
          /**
           * Definiert eine asymmetrische Distanz zwischen 2 Knoten.
           * @param int $key0 key von node 0
           * @param int $key1 key von node 1
           * @param number $distance01 Distanz von node 0 auf node 1
           * @param number $distance10 Distanz von node 1 auf node 0
           */
          function edgeDistances($key0, $key1, $distance01, $distance10)
          {
             if(!array_key_exists($key0, $this->aNode))
                throw new Exception('key0');
    
             if(!array_key_exists($key1, $this->aNode))
                throw new Exception('key1');
    
             if($key0 == $key1)
                throw new Exception('keys');
    
             self::checkDistance($distance01);
             self::checkDistance($distance10);
    
             $this->aDistanceMatrix[$key1]/* nach .. x */[$key0]/* von .. y */ = $distance01; /* von 0 nach 1 */
             $this->aDistanceMatrix[$key0][$key1] = $distance10;
          }
          /**
           * Distanz prüfen.
           * @param number $distance
           * @throws Exception
           *    not typ number
           */
          static private function checkDistance($distance)
          {
             if(!is_numeric($distance))
                throw new Exception('distance');
          }
          /**
           * Distanz-Matrix prüfen.
           * @throws Exception
           */
          private function checkDistanceMatrix()
          {
             $iCount = count($this->aNode);
             for($iTo = 0; $iTo < $iCount; ++$iTo)
             {
                for($iFrom = 0; $iFrom < $iCount; ++$iFrom)
                {
                   if($iFrom == $iTo)
                   {
                      $this->aDistanceMatrix[$iTo][$iFrom] = INF; // unendlich
                   }
                   elseif // Kontrolle, ob das Array-Element existiert:
                   (
                      !array_key_exists($iTo, $this->aDistanceMatrix) ||
                      !array_key_exists($iFrom, $this->aDistanceMatrix[$iTo])
                   )
                      throw new Exception('matrix value');
                }
                if(count($this->aDistanceMatrix[$iTo]) != $iCount)
                   throw new Exception('matrix count from');
             }
             if(count($this->aDistanceMatrix) != $iCount)
                throw new Exception('matrix count to');
          }
    
          // nur zum Testen:
          function getMatrix()
          {
             return $this->aDistanceMatrix;
          }
          function check()
          {
             $this->checkDistanceMatrix();
          }
       }
    
       $oBAB = new BranchAndBound();
    
       // nodes:
       $oBAB->insert(0, 0);
       $oBAB->insert(1, 1);
       $oBAB->insert(2, 2);
       $oBAB->insert(3, 3);
       $oBAB->insert(4, 4);
       $oBAB->insert(5, 5);
    
       // Distanzen:
       $oBAB->edgeDistances(1, 0, 6, 5);
       $oBAB->edgeDistances(2, 0, 1, 1);
       $oBAB->edgeDistances(3, 0, 4, 2);
       $oBAB->edgeDistances(4, 0, 1, 1);
       $oBAB->edgeDistances(5, 0, 6, 6);
       $oBAB->edgeDistances(2, 1, 4, 6);
       $oBAB->edgeDistances(3, 1, 3, 3);
       $oBAB->edgeDistances(4, 1, 5, 7);
       $oBAB->edgeDistances(5, 1, 2, 2);
       $oBAB->edgeDistances(3, 2, 3, 1);
       $oBAB->edgeDistances(4, 2, 1, 2);
       $oBAB->edgeDistances(5, 2, 6, 5);
       $oBAB->edgeDistances(4, 3, 2, 5);
       $oBAB->edgeDistances(5, 3, 4, 4);
       $oBAB->edgeDistances(5, 4, 5, 5);
    
       // nur zum Testen:
       var_dump($oBAB->getMatrix());
       $oBAB->check();
    ?>
    Alles anzeigen

    8 Mal editiert, zuletzt von Früchtemüsli (15. Dezember 2013 um 10:43)

  • Früchtemüsli
    6
    Früchtemüsli
    Mitglied
    Reaktionen
    3
    Punkte
    398
    Beiträge
    63
    • 12. Dezember 2013 um 19:08
    • #2

    Eine andere Möglichkeit wäre vielleicht, dass insert irgend etwas eindeutiges zurückgibt, das man dann edgeDistance als Parameter übergibt:

    id0 = insert(value0)
    id1 = insert(value1)
    edgeDistance(id0, id1, distance01, distance10)

    Diese ids könnten vielleicht Node-Objekte sein. Wie wäre diese Variante?

    Vielleicht auch möglich, außen Node-Objekte zu erzeugen, und die dann insert und edgeDistance übergeben:

    node0 = new Node(value0)
    node1 = new Node(value1)
    insert(node0)
    insert(node1)
    edgeDistance(node0, node1, distance01, distance10)

    4 Mal editiert, zuletzt von Früchtemüsli (15. Dezember 2013 um 10:40)

  • Früchtemüsli
    6
    Früchtemüsli
    Mitglied
    Reaktionen
    3
    Punkte
    398
    Beiträge
    63
    • 16. Dezember 2013 um 20:45
    • #3

    Also ich glaube, die Variante http://www.ccs.neu.edu/home/ada2358/D…phs/IGraph.html gefällt mir am besten.

    Sofern ich das richtig verstanden habe, erzeugt ich die Knoten außerhalb und übergebe sie addVertex bzw. danach addEdge.

    Das gefällt mir, weil mir das recht flexibel und schön erscheint. Dann sollte es auch möglich sein, eine eigene Vertexklasse zu programmieren, die von Vertex erbt. Die Vertexklassen können also bei jeder Anwendung ganz anders aussehen.

    PHP
    <?php
       error_reporting(~0);
    
       /**
        * Ganz allgemeine Vertex-Klasse.
        */
       class GraphVertex
       {
          private $name;
    
          function __construct($name)
          {
             $this->name = $name;
          }
          function getName()
          {
             return $this->name;
          }
       }
    
       /**
        * Wird dann einer CityGraphVertex zugewiesen.
        */    
       class City
       {
          private $sName;
          private $nArea;
          private $iPolulation;
    
          function __construct($name, $area, $population)
          { 
             // ...
          }
       }
    
       /**
        * Eine eigene Vertex-Klasse für Städte.
        */
       class CityGraphVertex extends GraphVertex
       {
          private $oCity;
    
          function __construct($name, City $oCity)
          {
             parent::__construct($name);
             $this->oCity = $oCity;
          }
          function getCity()
          {
             return $this->oCity;
          }
       }
    
       abstract class AEdge
       {
          protected $oU;
          protected $oV;
    
          function __construct(GraphVertex $oU, GraphVertex $oV)
          {
             $this->oU = $oU;
             $this->oV = $oV;
          }
       }
    
       /**
        * Gewichtete Kante.
        */
       class UniWeightEdge extends AEdge
       {
          private $nWeight;
          private $bDir;
    
          function __construct(GraphVertex $oU, GraphVertex $oV, $weight, $dir)
          {
             parent::__construct($oU, $oV);
             // ...
          }
       }
    
    
       /**
        * Bidirektional gewichtete Kante.
        */
       class BiWeightEdge extends AEdge
       {
          private $nWeightUV;
          private $nWeightVU;
          private $bDir;
    
          function __construct(GraphVertex $oU, GraphVertex $oV, $weightUV, $weightVU, $dir)
          {
             parent::__construct($oU, $oV);
             // ...
          }
       }
    
       /**
        * Ausgangsbasis für alle Arten von Graphen.
        */
       abstract class AGraph
       {
          protected $aVertex = [];
          protected $aEdge = [];
    
          function addVertex(GraphVertex $oVertex)
          {
             $this->aVertex[] = $oVertex;
          }
       }
    
       /**
        * Graph mit gewichteten Kanten.
        */
       class UniWeightGraph extends AGraph
       {
          function addEdge(GraphVertex $oU, GraphVertex $oV, $weight, $dir = false)
          {
             // ...
             $this->aEdge[] = new UniWeightEdge($oU, $oV, $weight, $dir);
          }
       }
    
       /**
        * Graph mit bidirektional gewichteten Kanten.
        */
       class BiWeightGraph extends AGraph
       {      
          function addEdge(GraphVertex $oU, GraphVertex $oV, $weightUV, $weightVU, $dir = false)
          {
             // ...
             $this->aEdge[] = new BiWeightEdge($oU, $oV, $weightUV, $weightVU, $dir);
          }
       }
    
       $oG = new BiWeightGraph();
    
       $oCGVParis = new CityGraphVertex('paris', new City('Paris', 17174.4, 12161542));
       $oCGVVienna = new CityGraphVertex('vienna', new City('Vienna', 414.87, 1763912));
    
       $oC->addVertex($oCGVParis);
       $oC->addVertex($oCGVVienna);
    
       $oC->addEdge($oCGVParis, $oCGVVienna, 1033, 1033.5);
    ?>
    Alles anzeigen

    Wie schaut das aus? OK so?

  • Maximilian Rupp 27. Dezember 2024 um 00:26

    Hat das Thema aus dem Forum Programmieren nach Entwicklung verschoben.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung