Formen in 2D-Array suchen und dann optimieren

11

Ich habe gerade ein Bild bekommen ... Das Bild unten aus meinem Spiel zeigt einige abgedunkelte Blöcke, die als Teil einer "T" -Form erkannt wurden. Wie zu sehen ist, hat der Code die Blöcke mit den roten Punkten abgedunkelt und die "T" -Formen mit den grünen Umrissen nicht gesehen.

Gewünschte Muster gefunden, aber noch nicht optimiert

Mein Code durchläuft x / y, markiert Blöcke als verwendet, dreht die Form, wiederholt, ändert die Farbe, wiederholt.

Ich habe versucht, diese Überprüfung mit großer Besorgnis zu beheben. Die aktuelle Idee ist:

  • Durchlaufen Sie das Raster, notieren Sie sich alle Mustervorkommen (markieren Sie die Blöcke NICHT als verwendet) und fügen Sie diese einem Array hinzu
  • Durchlaufen Sie das Raster erneut und notieren Sie diesmal, welche Blöcke von welchen Mustern und daher welche von mehreren Mustern belegt sind.
  • Sie durchlaufen erneut das Raster und stellen diesmal fest, welche Muster welche Muster behindern

So viel fühlt sich richtig an ... Was mache ich jetzt?

Ich denke ich müsste

  • Probieren Sie verschiedene Kombinationen widersprüchlicher Formen aus, beginnend mit denen, die zuerst die meisten anderen Muster behindern. Wie gehe ich mit diesem um?
  • Verwenden Sie das Rationale, das besagt, dass ich 3 widersprüchliche Formen habe, die 8 Blöcke belegen, und die Formen sind jeweils 4 Blöcke, daher kann ich nur maximal zwei Formen haben.

(Ich beabsichtige auch, andere Formen einzubeziehen, und es wird wahrscheinlich eine Punktgewichtung geben, die berücksichtigt werden muss, wenn die widersprüchlichen Formen durchlaufen werden, aber das kann ein anderer Tag sein.)

Ich glaube nicht, dass es ein Problem beim Verpacken von Behältern ist, aber ich bin mir nicht sicher, wonach ich suchen soll. Hoffe das macht Sinn, danke für deine Hilfe

BEARBEITEN Trotz der Klarheit der Frage scheint jeder verstanden zu haben, ja,

Ich möchte die maximalen "T" -Formen in jeder Farbe finden

(denn wenn ich dir Punkte für zwei geben würde und du drei gemacht hättest, wärst du ein bisschen verärgert)

Assembler
quelle
Ein gieriger Algorithmus könnte darin bestehen, das Board in Sammlungen verbundener Blöcke aufzuteilen. Dann können Sie für jede Sammlung versuchen, mit Formen zu füllen und der Füllung eine Punktzahl zu geben, die von der Anzahl der verbleibenden Blöcke abhängt, die nicht abgedunkelt werden. Irgendwie denke ich an das Problem en.wikipedia.org/wiki/Knapsack_ .
Jonathan Connell
2
Ich denke, in der Frage fehlt etwas. Möchten Sie einen Algorithmus erstellen, der so viele T-förmige Gruppen wie möglich findet?
Markus von Broady
Wenn ich dich verstehe, bist du auf dem richtigen Weg. Sie sind nicht besonders klar und ich würde es lieben, wenn Sie näher darauf eingehen könnten.
AturSams

Antworten:

3

Lassen Sie mich sehen, ob ich es richtig verstanden habe, die rot markierten Blöcke waren blau und der Algorithmus hat eine T-Form gefunden und sie rot markiert. Ist das richtig? Ihr Ziel ist es, so viele T-Formen wie möglich mit gleichfarbigen Blöcken zu finden, wie ich hoffe, bis jetzt richtig. Derzeit markieren Sie sie, sobald Sie sie gefunden haben, und dies verringert die Nützlichkeit des Algorithmus (da Ihnen möglicherweise die optimale Lösung fehlt). Sie planen, nach allen Formen zu suchen und dann auszuwählen, welche verwendet werden sollen und welche nicht. Bin ich soweit richtig? Denn Sie möchten die Anzahl der Blöcke maximieren, die in den T-Formen enthalten sind, wenn der Algorithmus fertig ist.

Wenn ich richtig liege, ist das Folgende meiner Meinung nach die optimale Lösung für Ihre Situation.

Wir werden Integer Linear Programming verwenden.

Ich glaube, ich habe diesen in der Vergangenheit benutzt:

http://sourceforge.net/projects/lpsolve/

http://lpsolve.sourceforge.net/5.5/Java/README.html

(Sie können es mit vielen Sprachen zum Laufen bringen, ich habe es mit PHP, Java und C verwendet)

Wir registrieren jede mögliche T-Form auf der Platine und verwenden dann ILP, um die Anzahl der abgedeckten Blöcke zu maximieren. ILP ist exponentiell komplex. Angesichts der Größe Ihres Boards ist dies kein Problem. Ich habe mit ILP viel kompliziertere Min / Max-Fragen zu Diagrammen gestellt und es dauerte nur einen Bruchteil einer Sekunde, bis sie abgeschlossen waren, und bis zu 30-90 Sekunden mit Hunderten von Eckpunkten (in Ihrem Fall fällt sie in den Bruchteil einer Sekunde).

Was ich empfehlen würde:

  1. Finde alle möglichen Linienformen
  2. Suchen Sie alle Schnittpunkte zwischen Linienformen derselben Farbe
  3. Finde alle möglichen T-Formen und suche alle Schnittpunkte.
  4. Definieren Sie eine boolesche Variable im linearen Problem für jede T-Form ( 0 <= Bi <= 1) Da die Werte Ganzzahlen sind, bleibt 0 oder 1 übrig.
  5. Legen Sie die Bedingungen für jedes Paar von T-Formen fest, die sich schneiden ( Bi + Bj <= 1)
  6. Die Zielfunktion ist (Summe der Blöcke in "T" -Form (i) * Bi)
  7. Führen Sie den Solver aus und verdunkeln Sie die T-Formen dort, wo die entsprechenden Booleschen Werte des Solvers 1 in der optimalen Lösung sind.

Das ist wertvolles Wissen, ich habe oft lineare Löser für Arbeitsprojekte verwendet.

ILP ist im Grunde eine Möglichkeit, Auswahlprobleme zu lösen, bei denen Sie für eine lineare Funktion ein Maximum oder ein Minimum erreichen möchten.

Weitere Informationen finden Sie hier. Die Verwendung der linearen Ganzzahlprogrammierung und der linearen Programmierung ist für den Programmierer gleich, nur dass die Ganzzahl für den Computer weitaus komplexer ist, was zu langen Laufzeiten führen kann. Nicht in Ihrem Fall, es ist sehr einfach und sollte im schlimmsten Fall nur weniger als Millisekunden dauern.

Ich denke, Sie könnten hier mehr lesen:

http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns

Das erklärt es gut:

http://fisher.osu.edu/~croxton_4/tutorial/

Es ist im Grunde ein Entscheidungsproblemlöser, wie man Entscheidungen trifft, die das gewünschte Ergebnis maximieren. Dies setzt voraus, dass die Funktion, die das Ergebnis beurteilt, linear ist, wie es in Ihrem speziellen aktuellen Fall der Fall ist. Die Funktion, die in diesem Fall das Ergebnis beurteilt, fasst die Blöcke für alle T-Formen zusammen, die Sie abdunkeln möchten.

Mathematisch, wie man die Variablen setzt: In unserem aktuellen Fall Boolesche Werte (Habe ich die T-Form mit dem Index i abgedunkelt oder nicht) auf die optimalen Werte, um das gewünschte Ergebnis zu maximieren: Verdunkeln Sie so viele Blöcke wie möglich, ohne sich überschneidende T-Formen abzudunkeln. Solange das gewünschte Ergebnis mit einer linearen Funktion berechnet werden kann, wenn Sie alle Variablen festgelegt haben, wird es gelöst. In unserem Fall prüfen wir, welche T-Formen wir abgedunkelt haben, und addieren die Blöcke, die sie abdecken.

Geben Sie hier die Bildbeschreibung ein

Ich weiß, dass dies nicht trivial ist. Wenn Sie sich also für den Sprung entscheiden, können Sie dies gerne kommentieren, und ich werde darauf näher eingehen.

AturSams
quelle
Danke Arthur für deine Hilfe. Die Verdauung kann einige Lesevorgänge dauern. Und ja, Sie haben das Problem richtig verstanden. Es würde mich sehr interessieren, wenn Sie näher darauf eingehen würden (nein, nein, es ist nicht trivial), aber dies sollte mir helfen, dorthin zu gelangen, wohin ich gehe!
Assembler
Welche Sprache verwenden Sie für die Implementierung?
AturSams
Actionscript 3! jedermanns Favorit!
Assembler
hier gilt das gleiche. Ich werde eine Implementierung in as3 schreiben und sie zum Herunterladen mit Kommentaren in einen Github hochladen. Ich arbeite Schritt für Schritt - ich kann sie später heute
erledigen
Haben Sie bestimmte Bereiche 1 bis 7, in denen ich weitere Kommentare hinzufügen oder näher erläutern soll? Übrigens, eine gute Nachricht für uns AS3-Liebhaber: Adobe hat FlasCC veröffentlicht, das C ++ unterstützt, damit wir vorhandene lineare Löser problemlos verwenden können. :)
AturSams
4

Sobald Sie eine Liste aller (möglicherweise überlappenden) T-Formen in Ihrem Raster haben, bleibt Ihnen ein maximales Problem beim Packen .

Im Allgemeinen ist dies ein NP-vollständiges Problem. Ihr Raster ist jedoch klein genug (und zerfällt normalerweise in noch kleinere unabhängige Teilprobleme), sodass es durchaus möglich sein kann, genaue Lösungen zu erhalten.


Nachtrag: Hier ist ein grundlegender Backtracking-Suchalgorithmus, der den Trick machen könnte:

function max_packing_recursive ( set A, set S, set M ):
    if |M| < |S| then let M = S;
    for each shape X in A do:
        remove X from A;
        let B = A;
        remove all shapes that intersect with X from B;
        if |M| < |B| + |S| + 1 then:        // upper bound
            let M = max_packing_recursive( B, S + {X}, M );
        end if
        if |M| >= |A| + |S| then return M;  // shortcut
    end for
    return M;
end function

function max_packing( set A ):
    return max_packing_recursive( A, {}, {} );
end function

Hier {X, Y, Z}bezeichnet die Menge, die die Elemente enthält X, Yund Z( {}wobei die leere Menge ist) und |Q|bezeichnet die Größe der Menge Q.

In der rekursiven Funktion Aenthält die Menge die Formen, die für die verbleibende Lösung verfügbar sind, Senthält die Formen im aktuellen Lösungskandidaten und Mist die bisherige maximale Lösung (die Sie möglicherweise als globale Variable speichern möchten, anstatt sie zurückzusenden Anrufkette). Die wichtige Optimierung befindet sich in der mit gekennzeichneten Zeile // upper bound, die Zweige des Suchbaums beschneidet, die möglicherweise keine bessere Lösung als zurückgeben können M.

(Da wir wissen, dass jede T-Form genau vier Stellen enthält, könnte eine viel bessere Obergrenze erhalten werden, indem |B|durch die Anzahl der verschiedenen Stellen ersetzt wird, die von den Formen in abgedeckt B, durch vier geteilt und abgerundet werden (und ähnlich für |A|die Linie markiert mit // shortcut). Der oben angegebene Algorithmus funktioniert jedoch für beliebige Formensammlungen.)

Eine mögliche zusätzliche Optimierung, die ich oben nicht implementiert habe, besteht darin, zu Beginn der rekursiven Funktion zu überprüfen, ob sie Asich in mehrere unabhängige Teilmengen aufteilt, in dem Sinne, dass sich keine Formen in verschiedenen Teilmengen überlappen, und wenn ja, die anzuwenden Algorithmus für jede der Teilmengen separat. (In jedem Fall sollten Sie dies auf jeden Fall mindestens einmal auf der obersten Ebene tun, bevor Sie den rekursiven Algorithmus aufrufen.) Das Ageeignete Sortieren der Formen vor dem Schleifen, z. B. in aufsteigender Reihenfolge nach Anzahl der überlappenden Formen, kann ebenfalls hilfreich sein .

Ilmari Karonen
quelle
Ja, ich denke, er könnte ein ILP verwenden, um es aufgrund der Größe des Problems relativ schmerzlos zu lösen. 2 ^ 20 ~ = 1.000.000. Da es also nur so viele T-Formen geben kann, sollte er dafür einen linearen Löser verwenden können . Es ist eindeutig exponentiell komplex (zumindest bis es jemandem gelingt, zu beweisen, dass p = np ist). Die Größe ermöglicht es, Heuristiken in diesem relativ einfachen Fall zu vermeiden.
AturSams
Ilmari, vielen Dank. Auch diese Antwort wird ein paar Mal dauern, um zu verstehen. Das Bit für beliebige Formen kann in zukünftigen Iterationen nützlich sein.
Assembler