Iterative Deepening A Star in Python

Gepostet: , Zuletzt aktualisiert:

def iterative_deepening_a_star(tree, heuristic, start, goal):
    """
    Performs the iterative deepening A Star (A*) algorithm to find the shortest path from a start to a target node.
    Can be modified to handle graphs by keeping track of already visited nodes.
    :param tree:      An adjacency-matrix-representation of the tree where (x,y) is the weight of the edge or 0 if there is no edge.
    :param heuristic: An estimation of distance from node x to y that is guaranteed to be lower than the actual distance. E.g. straight-line distance.
    :param start:      The node to start from.
    :param goal:      The node we're searching for.
    :return: number shortest distance to the goal node. Can be easily modified to return the path.
    """
    threshold = heuristic[start][goal]
    while True:
        print("Iteration with threshold: " + str(threshold))
        distance = iterative_deepening_a_star_rec(tree, heuristic, start, goal, 0, threshold)
        if distance == float("inf"):
            # Node not found and no more nodes to visit
            return -1
        elif distance < 0:
            # if we found the node, the function returns the negative distance
            print("Found the node we're looking for!")
            return -distance
        else:
            # if it hasn't found the node, it returns the (positive) next-bigger threshold
            threshold = distance


def iterative_deepening_a_star_rec(tree, heuristic, node, goal, distance, threshold):
    """
    Performs DFS up to a depth where a threshold is reached (as opposed to interative-deepening DFS which stops at a fixed depth).
    Can be modified to handle graphs by keeping track of already visited nodes.
    :param tree:      An adjacency-matrix-representation of the tree where (x,y) is the weight of the edge or 0 if there is no edge.
    :param heuristic: An estimation of distance from node x to y that is guaranteed to be lower than the actual distance. E.g. straight-line distance.
    :param node:      The node to continue from.
    :param goal:      The node we're searching for.
    :param distance:  Distance from start node to current node.
    :param threshold: Until which distance to search in this iteration.
    :return: number shortest distance to the goal node. Can be easily modified to return the path.
     """
    print("Visiting Node " + str(node))

    if node == goal:
        # We have found the goal node we we're searching for
        return -distance

    estimate = distance + heuristic[node][goal]
    if estimate > threshold:
        print("Breached threshold with heuristic: " + str(estimate))
        return estimate

    # ...then, for all neighboring nodes....
    min = float("inf")
    for i in range(len(tree[node])):
        if tree[node][i] != 0:
            t = iterative_deepening_a_star_rec(tree, heuristic, i, goal, distance + tree[node][i], threshold)
            if t < 0:
                # Node found
                return t
            elif t < min:
                min = t

    return min

Über den Algorithmus und die Programmiersprache in diesem Snippet:

Iterative Deepening A Star Algorithmus

Der A-Star Algorithmus mit iterativer Vertiefung (IDA & ast;) ist ein Algorithmus, der verwendet wird, um das Problem des kürzesten Pfades in einem Baum zu lösen, kann jedoch modifiziert werden, um Graphen (d. H. Zyklen) zu handhaben. Es baut auf der ID-DFS (Iterative Deepening Depth-First Search) auf, indem eine Heuristik hinzugefügt wird, um nur relevante Knoten zu untersuchen.

Beschreibung des Algorithmus

Während Iterative Deepening DFS eine einfache Tiefe verwendet, um zu entscheiden, wann die aktuelle Iteration abgebrochen und mit einer höheren Tiefe fortgesetzt werden soll, Iterative Vertiefung Ein Stern verwendet eine Heuristik, um zu bestimmen, welche Knoten erforscht und in welcher Tiefe gestoppt werden soll. Dies ähnelt der Art und Weise, wie Dijkstra den Knoten immer mit dem derzeit kürzesten Unterschied untersucht und A Star eine Heuristik hinzufügt, um nur Knoten zu untersuchen, die tatsächlich näher am Ziel liegen.

Im Einzelnen führt dies zu den folgenden Schritten:

  1. Für jedes Kind des aktuellen Knotens
  2. Wenn es sich um den Zielknoten handelt, kehren Sie zurück
  3. Wenn der Abstand plus die Heuristik den aktuellen Schwellenwert überschreitet, geben Sie diesen Schwellenwert zurück
  4. Setzen Sie den aktuellen Knoten auf diesen Knoten und kehren Sie zu 1 zurück.
  5. Nachdem Sie alle Kinder durchlaufen haben, gehen Sie zum nächsten Kind des Elternteils (dem nächsten Geschwister).
  6. Nachdem Sie alle untergeordneten Elemente des Startknotens durchlaufen haben, erhöhen Sie den Schwellenwert auf den kleinsten der überschrittenen Schwellenwerte.
  7. Wenn wir alle Blattknoten (unten) erreicht haben, existiert der Zielknoten nicht.

Beispiel des Algorithmus

Betrachten Sie das folgende Diagramm: Grafik für den Iterative Deepening A Star (IDA *) -Algorithmus für kürzeste Wege

Die Schritte, die der Algorithmus in diesem Diagramm ausführt, wenn Knoten 0 als Startpunkt und Knoten 6 als Ziel in der angegebenen Reihenfolge angegeben werden, sind:

  1. Iteration mit Schwelle: 6.32
  2. Besuche Knoten 0
  3. Besuche Knoten 1
  4. Schwelle mit Heuristik überschritten: 8.66
  5. Besuche Knoten 2
  6. Schwelle mit Heuristik überschritten: 7.00
  7. Iteration mit Schwelle: 7.00
  8. Besuche Knoten 0
  9. Besuche Knoten 1
  10. Schwelle mit Heuristik überschritten: 8.66
  11. Besuche Knoten 2
  12. Besuche Knoten 5
  13. Schwelle mit Heuristik überschritten: 8.83
  14. Iteration mit Schwelle: 8.66
  15. Besuche Knoten 0
  16. Besuche Knoten 1
  17. Besuche Knoten 3
  18. Schwelle mit Heuristik überschritten: 12.32
  19. Besuche Knoten 4
  20. Schwelle mit Heuristik überschritten: 8.83
  21. Besuche Knoten 2
  22. Besuche Knoten 5
  23. Schwelle mit Heuristik überschritten: 8.83
  24. Iteration mit Schwelle: 8,83
  25. Besuche Knoten 0
  26. Besuche Knoten 1
  27. Besuche Knoten 3
  28. Schwelle mit Heuristik überschritten: 12.32
  29. Besuche Knoten 4
  30. Besuche Knoten 2
  31. Besuche Knoten 5
  32. Besuche Knoten 6
  33. Den Knoten gefunden, den wir suchen!

Endgültig niedrigster Abstand von Knoten 0 zu Knoten 6: 9

Beachten Sie, dass der Algorithmus in der Iteration, in der er den Zielknoten gefunden hat, nicht weiter von Knoten 3 aus nach unten gesucht hat. Wenn Knoten 3 Kinder gehabt hätte, während Iterative Deepening DFS sie möglicherweise (und unnötig!) Erkundet hätte, hätte Iterative Deepening A Star dies nicht getan.

Laufzeit des Algorithmus

Die Laufzeitkomplexität von Iterative Deepening A Star entspricht im Prinzip der von Iterative Deepening DFS. In der Praxis können jedoch viele der Pfade eliminiert werden, bevor wir untersucht werden, wenn wir eine gute Heuristik wählen, was zu einer signifikanten Zeitverbesserung führt. Weitere Informationen darüber, wie die Heuristik die Komplexität beeinflusst, finden Sie im Wikipedia-Artikel.

Speicherkomplexität des Algorithmus

Die räumliche Komplexität von Iterative Deepening A Star ist die Speichermenge, die für den Baum oder das Diagramm benötigt wird. O(| N|), |N| = Anzahl der Knoten im Baum oder Diagramm, die für Bäume durch b^d ersetzt werden können, wobei b der Verzweigungsfaktor und d ist die Tiefe. Unabhängig davon, welchen Platz die Heuristik benötigt.

Python

Das Python-Logo

Python™ ist eine interpretierte Sprache, die für viele Zwecke verwendet wird, von der eingebetteten Programmierung bis zur Webentwicklung, wobei einer der größten Anwendungsfälle die Datenwissenschaft ist.

In Python zu “Hello World”

Das Wichtigste zuerst - so können Sie Ihre erste Codezeile in Python ausführen:

  1. Laden Sie die neueste Version von Python von python.org herunter und installieren Sie sie. Sie können auch eine frühere Version herunterladen, wenn Ihr Anwendungsfall dies erfordert. Viele Technologien erfordern dies aufgrund der mit Python 3 eingeführten Änderungen weiterhin.
  2. Öffnen Sie ein Terminal, stellen Sie sicher, dass der Befehl “python” oder “python3” funktioniert und dass der Befehl, den Sie verwenden, sich auf die Version bezieht, die Sie gerade installiert haben, indem Sie “python3 —version” oder “python —version” ausführen. Wenn der Fehler “Befehl nicht gefunden” (oder ähnliches) angezeigt wird, starten Sie die Befehlszeile, und, falls dies nicht hilft, Ihren Computer neu. Wenn das Problem weiterhin besteht, finden Sie hier einige hilfreiche Fragen zu StackOverflow für Windows, Mac und Linux.
  3. Sobald dies funktioniert, können Sie das folgende Snippet ausführen: print("Hello World"). Sie haben zwei Möglichkeiten, dies auszuführen: 3.1 Führen Sie “python” in der Befehlszeile aus, fügen Sie einfach das Code-Snippet ein und drücken Sie die Eingabetaste (Drücken Sie “STRG + D” oder schreiben Sie “exit ()” und drücken Sie die Eingabetaste, um das Programm zu beenden). 3.2 Speichern Sie das Snippet in einer Datei und nennen Sie es etwas, das mit “.py” endet, z.B. hello_world.py und führepython path / to / hello_world.py aus. Tipp: Verwenden Sie den Befehl ls (dir in Windows), um herauszufinden, welche Dateien sich in dem Ordner befinden, in dem sich Ihre Befehlszeile gerade befindet.

Das wars schon! Beachten Sie, dass das Drucken von etwas auf die Konsole in Python nur eine einzige Zeile ist - diese niedrige Eintrittsbarriere und das Fehlen von erforderlichem Boilerplate-Code machen einen großen Teil der Attraktivität von Python aus.

Grundlagen in Python

Um in Python implementierte Algorithmen und Technologien zu verstehen, muss man zunächst verstehen, wie grundlegende Programmierkonzepte in dieser bestimmten Sprache aussehen.

Variablen und Arithmetik

Variablen in Python sind wirklich einfach. Sie müssen weder einen Datentyp deklarieren noch deklarieren, dass Sie eine Variable definieren. Python weiß das implizit.

a = 1
b = {'c':2}

print(a + b['c']) # prints 3

Arrays

Das Arbeiten mit Arrays ist in Python ähnlich einfach:

arr = ["Hello", "World"]

print(arr[0]) # Hello
print(arr[1]) # World
# print(arr[2]) # IndexError

arr.append("!")

print(arr[2]) # !

Wie diejenigen von Ihnen, die mit anderen Programmiersprachen wie Java vertraut sind, möglicherweise bereits bemerkt haben, handelt es sich nicht um native Arrays, sondern um Listen, die wie Arrays gekleidet sind. Dies wird durch die Tatsache deutlich, dass keine Größe angegeben werden muss und Elemente nach Belieben angehängt werden können. Tatsächlich druckt print (type (arr)) <class ‘list’> `. Dies bedeutet, dass Arrays in Python erheblich langsamer sind als in Programmiersprachen niedrigerer Ebene. Es gibt jedoch Pakete wie numpy, die echte Arrays implementieren, die erheblich schneller sind.

Bedingungen

Wie die meisten Programmiersprachen kann Python “if-else”-Anweisungen ausführen:

value = 1
if value==1:
    print("Value is 1")
elif value==2:
    print("Value is 2")
else:
    print("Value is something else")

Python hat jedoch keine “case”-Anweisungen, die andere Sprachen wie Java haben. Meiner Meinung nach kann dies durch die Einfachheit der “if”-Anweisungen entschuldigt werden, die den “syntaktischen Zucker” von “case” -Anweisungen überflüssig machen.

Schleifen

Python unterstützt sowohl “for” - als auch “while” -Schleifen sowie “break” - und “continue” -Anweisungen. Es gibt zwar keine “do-while” -Schleifen, aber eine Reihe von integrierten Funktionen, die das Schleifen sehr bequem machen, wie “enumerate” oder “range”. Hier sind einige Beispiele:

value = 10
while value > 0:
    print(value)
    value -= 1

for index, character in enumerate("banana"):
    print("The %d-th letter is a %s" % (index + 1, character))

Beachten Sie, dass Python nicht die gemeinsame Iteratorvariablensyntax anderer Sprachen verwendet (z. B. for (int i = 0; i <arr.length; i ++) in Java) - hierfür kann die Funktion enumerate verwendet werden.

Funktionen

Funktionen in Python sind einfach zu definieren und erfordern zum Guten oder Schlechten keine Angabe von Rückgabe- oder Argumenttypen. Optional kann ein Standardwert für Argumente angegeben werden:

def print_something(something="Hello World"):
    print(something)
    return "Success"

print_something()
print(print_something("banana"))

 (Dies druckt “Hallo Welt”, “Banane” und dann “Erfolg”)

Syntax

Sie haben vielleicht bemerkt, dass Python keine geschweiften Klammern ({}) verwendet, um Codeblöcke in Bedingungen, Schleifen, Funktionen usw. zu umgeben. Dies liegt daran, dass Python als Teil seiner Syntax von Einrückungen (Leerzeichen) abhängt. Während Sie in Java beliebig viele Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche) hinzufügen und löschen können, ohne das Programm zu ändern, wird die Syntax in Python dadurch unterbrochen. Dies bedeutet auch, dass keine Semikolons erforderlich sind, was in anderen Sprachen ein häufiger Syntaxfehler ist.

Fortgeschrittene Kenntnisse in Python

Python wurde erstmals 1990 veröffentlicht und ist ein Multi-Paradigma. Das bedeutet, dass es in erster Linie zwingend und funktional ist, aber auch objektorientierte und reflektierende Elemente enthält. Es ist dynamisch typisiert, bietet jedoch seit Version 3.5 Syntax für die schrittweise Eingabe. Für weitere Informationen hat Python einen großartigen Artikel Wikipedia.