Minimax-Algorithmus

Der Minimax-Algorithmus ist ein Algorithmus zur Ermittlung der optimalen Spielstrategie für Spiele bei denen zwei gegnerische Spieler abwechselnd Züge ausführen (z.B. Schach, Go, Reversi, Dame, Mühle oder Vier gewinnt).

Im Gegensatz zu Würfelspielen sind die genannten Spiele nicht vom Zufall abhängig, im Gegensatz zu Karten- und Ratespielen sind sie offen, d.h. in jeder Spielsituation sind jedem der beiden Spieler alle Zugmöglichkeiten des jeweiligen Gegenspielers bekannt.

In solchen Fällen lässt sich die optimale Strategie für das jeweilige Spiel mit dem Minimax-Verfahren ermitteln. Die optimale Strategie ist dann gefunden, wenn sie zum (bestmöglichen) Ergebnis eines Spielers führt, wenn man von optimaler Spielweise des Gegners ausgeht.

Für einige Spiele, wie das so genannte Nim-Spiel, lässt sich eine optimale Strategie auch direkt ohne Minimax berechnen.

Inhaltsverzeichnis

Algorithmus

Der Algorithmus funktioniert folgendermaßen:

Bewertungsfunktion

Eine ideale Bewertungsfunktion ordnet einer Stellung den Wert +1 zu, wenn Spieler A gewinnt, und den Wert -1, wenn Spieler B gewinnt, und 0 bei Unentschieden. Kann man von sämtlichen Spielpositionen den Suchbaum bis zur maximalen Tiefe aufbauen (bis zur Endstellung, wo man sieht, wer gewinnt), so spielt der Algorithmus ein perfektes Spiel. Allerdings ist in der Praxis der vollständige Aufbau eines Suchbaums nur bei sehr einfachen Spielen wie Tic-Tac-Toe möglich.

Bei fast allen anderen Spielen ist dies zu rechenaufwändig. Deshalb begnügt man sich damit, den Suchbaum nur bis zu einer vorgegebenen Suchtiefe aufzubauen. Die Bewertungsfunktion wird modifiziert, sehr gute Spielpositionen für A erhalten sehr hohe Werte, sehr gute Spielpositionen für B erhalten sehr niedrige Werte. Zur Ermittlung der Werte bedient man sich Heuristiken zur Schätzung.

Die steigende Rechenleistung von Computern und bessere Programme haben mittlerweile dazu geführt, dass selbst bei so komplexen Spielen wie Schach heutzutage die meisten Menschen ohne Mühe vom Computer geschlagen werden können. Die dabei verwendete Strategie beruht im Wesentlichen auf dem Minmax-Algorithmus.

Suchbaum-Beispiel

Bild:040125_minmax.png

Das Bild oben zeigt einen einfachen Baum mit Suchtiefe 3.

Die Knoten der Ebenen 1 und 3 entsprechen Spielsituationen, in denen Spieler A am Zug ist, d.h. hier wird jeweils der Max-Wert der untergeordneten Knoten ermittelt.

Die Knoten der Ebene2 entsprechen Spielsituationen, in denen Spieler B am Zug ist, d.h. hier wird jeweils der Min-Wert der untergeordneten Knoten ermittelt.

Auf der Blätterebene werden die Knotenwerte jeweils über die Bewertungsfunktion ermittelt.

Im Bild sind Kanten (= Spielzüge), die zum Max-Wert führen, rot gekennzeichnet. Kanten, die zum Min-Wert führen, sind blau gekennzeichnet.

Anmerkungen

Der Minimax-Algorithmus benötigt einerseits mit steigender Suchtiefe exponentiell längere Zeit, andererseits steigt in der Regel bei höherer Suchtiefe auch die Qualität des Suchergebnisses.

Es existieren daher verschiedene optimierte Varianten, z.B.

Eine wesentliche Zeitersparnis ergibt sich durch Speicherung der bisher untersuchten Stellungen und deren Bewertungen. Wird eine Stellung durch verschiedene Zugfolgen von der Ausgangsstellung erreicht, braucht nicht jedes Mal wieder der gesamte darunter liegende Suchbaum durchsucht zu werden.

Iterative Tiefensuche

Speziell bei eingeschränkter Zeit für die Suche (z.B. im Turnierschach) wird iterative Tiefensuche (iterative deepening) verwendet. Dabei wird die Suche, ausgehend von der zu untersuchenden Stellung, wiederholt gestartet und dabei die gewünschte Suchtiefe schrittweise erhöht. Werden die bereits untersuchten Stellungen, wie oben beschrieben, gespeichert, müssen nur die gegenüber der vorhergehenden Suche neu erreichten Stellungen mit der Bewertungsfunktion bewertet werden. Dieses Verfahren wird so lange fortgesetzt, bis die verfügbare Suchzeit überschritten oder ein "hinreichend gutes" Ergebnis erzielt wurde.

Ohne iterative Tiefensuche wäre beim Überschreiten des Zeitlimits im schlimmsten Fall nur ein einziger Zug untersucht worden, dieser aber bis in sehr große Tiefe. Der nächste Zug, der vielleicht schon nach nur einem einzigen Gegenzug den Gewinn gesichert hätte, wäre gar nicht erst ausprobiert worden.

Pseudocode

Hauptprogramm (Auszug):
   var doNext : number
   dummy := maxWert ( gewünschte suchTiefe )
   Zug doNext ausführen
 function maxWert ( restTiefe ) returns number
 var ermittelt, zugWert : number
 begin
   ermittelt := - unendlich
   für alle möglichen Züge begin
     Zug simulieren
     if restTiefe <= 1 or keineFolgezügeMehrMöglich
     then zugWert := bewertungsFunktion
     else zugWert := minWert ( restTiefe - 1 )
     Zug-Simulation zurücksetzen
     if zugWert > ermittelt then begin
       ermittelt := zugWert
       doNext := nummer des Zuges  /* für das Hauptprogramm */
     end
   end
   return ermittelt
 end maxWert
 function minWert ( restTiefe ) returns number
 var ermittelt, zugWert : number
 begin
   ermittelt := + unendlich
   für alle möglichen Züge begin
     Zug simulieren
     if restTiefe <= 1 or keineFolgezügeMehrMöglich
     then zugWert := bewertungsFunktion
     else zugWert := maxWert ( restTiefe - 1 )
     Zug-Simulation zurücksetzen
     if zugWert < ermittelt then ermittelt := zugWert
   end
   return ermittelt
 end minWert
 

Variante: Der NegaMax-Algorithmus

Um den Code zu vereinfachen und jeden Knoten des Suchbaumes gleich behandeln zu können, definiert man, dass jeder Spieler versucht, ein für sich selbst maximales Ergebnis, das heißt maximalen Wert der Bewertungsfunktion, zu erzielen. Dazu muss die Bewertung der Folgestellungen mit -1 multipliziert werden (Negation, daher der Name). Damit muss nicht mehr unterschieden werden, ob A oder B am Zug ist und daher das Maximum oder das Minimum berechnet werden, sondern es wird in jeder Stellung immer nur das Maximum der negierten Bewertungen der Folgestellungen berechnet.

See also: Minimax-Algorithmus, Algorithmus, Alpha-Beta-Suche, Damespiel, Exponentiell, Go (Brettspiel), Heuristik, Iterative Tiefensuche, Mühlespiel, Nim-Spiel