[PYTHON] Kombinationsoptimierungstechniken in Rätseln

Nachtrag: Referenzlink

Einführung

Mit der Kombinationsoptimierung (bfbf4c185ed7004b5721) (sogenannte Mixed Integer-Optimierung) können Sie einfach verschiedene Regeln schreiben. Hier werden wir einige Techniken am Beispiel von Rätseln kurz vorstellen. Einige dieser Techniken sind auch Teil von Python. Python eignet sich gut zur Modellierung der mathematischen Optimierung.

Umgebung

pip install pulp ortoolpy unionfind more_itertools

Vorbereitung

Als Modellierer wird PuLP verwendet. (Über PuLP) Im folgenden Codebeispiel wird Folgendes weggelassen.

python


%matplotlib inline
import numpy as np, matplotlib.pyplot as plt
from itertools import groupby
from pulp import *
from unionfind import unionfind
from ortoolpy import addvar, addvars, addbinvar, addbinvars
m = LpProblem()
Methode Beschreibung
gruppieren nach Gruppieren Sie Dinge mit demselben Schlüssel
unionfind [Datenstruktur des Elementarsatzes](https://ja.wikipedia.org/wiki/%E7%B4%A0%E9%9B%86%E5%90%88%E3%83%87%E3%83% Klasse für BC% E3% 82% BF% E6% A7% 8B% E9% 80% A0)
addvar Eine Variable erstellen
addvars Erstellt eine Liste von Variablen
addbinvar 0-1 Erstellen Sie eine Variable
addbinvars 0-1 Erstellt eine Liste von Variablen
LpProblem PuLP Mathematical Optimization Model

Zielpuzzle

Vorbereitet in SaitoTsutomu / OptForPuzzle.

Technik

Erstellen Sie Variablen mit np.array

Dienstprogramm: Beschleunigen Sie die Berechnung, verschiedene Zugriffe Zielrätsel: "Plötzlich" usw. Beispiel:

python


v = np.array(addbinvars(9, 9, 9)) # (1)
m += lpSum(v[i,:,k]) == 1 # (2)
m += lpSum(v[i:i+3,j:j+3,k]) == 1 # (3)
w = addvars(9, 9) # (4)
m += lpDot(range(9), v[i,j])+1 == r[i][j] # (4)

-In (1) wird eine 0-1-Variable eines mehrdimensionalen 9x9x9-Arrays erstellt. Jede Dimension repräsentiert eine Zeile, eine Spalte und eine Zahl. -In (2) bedeutet dies, dass es nur eine Zahl $ k + 1 $ in der Zeile $ i $ gibt. -In (3) ist oben links der Bereich von 3x3, in dem $ (i, j) $, was bedeutet, dass es nur eine Zahl $ k + 1 $ gibt.

Holen Sie sich das Ergebnis mit np.vectorize

Dienstprogramm: Beschleunigen Sie die Berechnung, verschiedene Zugriffe Zielrätsel: "Plötzlich" usw. (Visualisierung ist "Kurodoko" usw.) Beispiel:

python


r = np.vectorize(value)(v).astype(int) # (1)
plt.imshow(1-r, cmap='gray', interpolation='none') # (2)

Es ist zweckmäßig, das Ergebnis $ r $ wie in (1) oben gezeigt zu erhalten, um eine Variable mit np.array zu erstellen und die Optimierung zu lösen. Auf diese Weise erhalten Sie schnell und einfach Ergebnisse und können die Verarbeitung mit den verschiedenen Funktionen von numpy fortsetzen. Wenn Sie das Ergebnis von 2D-Schwarzweiß als Abbildung überprüfen möchten, können Sie es mithilfe von matplotlib wie in (2) gezeigt einfach visualisieren.

Wenn die Variablen von der Pandas DataFrame-Serie verwaltet werden, können Sie dies auch mit apply tun.

Alles das selbe

Dienstprogramm: Effiziente Modellierung Zielpuzzle: "Malbereich" etc. Beispiel:

python


for vi, vj in zip(v, v[1:]):
    m += vi == vj

Wenn alle Elemente des eindimensionalen Variablenarrays $ v $ denselben Wert haben müssen, können Sie wie oben schreiben. (Es gibt auch eine Möglichkeit, die Variable selbst zu ersetzen.)

Nummer herum

Dienstprogramm: Effiziente Modellierung Zielrätsel: "Creek", "Shakashaka", "Mehrere Walzen", "Nori-Kleber", "Malbereich", "Bomber-Puzzle"

Wenn Sie die Summe der oberen, unteren, linken und rechten Variablen der Massenvariablen $ v [i, j] $ verwenden möchten, können Sie $ w $ wie unten gezeigt verwenden. Beispiel:

python


u = np.zeros((nh+2, nw+2), dtype=object)
v = u[1:-1,1:-1] = np.array(addbinvars(nh, nw))
w = u[:-2,1:-1]+u[2:,1:-1]+u[1:-1,:-2]+u[1:-1,2:]

Dies ist ein Beispiel für die gute Verwendung von Slices, indem ein Array $ u $ vorbereitet wird, das eine Runde weiter um v liegt.

IF-Einschränkung

Dienstprogramm: Drückt den Fall aus, der abhängig von den Bedingungen gilt Zielrätsel: "Kanaore" usw. Wenn es Variablen $ x, y $ gibt und Sie "$ y \ le a " machen möchten, wenn " x == 1 $", verwenden Sie eine ausreichend große Zahl $ M $, wie unten gezeigt. Ich kann schreiben. Beispiel:

python


m += y <= a + M(1-x)

Wenn Sie "$ y = a " setzen möchten, wenn " x == 1 $", können Sie wie folgt schreiben. Beispiel:

python


m += y <= a + M(1-x)
m += y >= a - M(1-x)

Verkettungsbeschränkungen

Dienstprogramm: Einfache Modellierung Zielpuzzle: "Kurodoko" etc.

Es gibt eine Einschränkung, dass "alle weißen Quadrate miteinander verbunden sind" wie "schwarzer Ort". Der Versuch, eine solche Einschränkung mit einer mathematischen Formel auszudrücken, kann ziemlich schwierig sein. Daher gibt es eine Möglichkeit, es einmal zu ignorieren. Wenn es nicht verbunden ist, verbieten Sie die Lösung und lösen Sie sie erneut.

Beispiel: Überprüfen der Konnektivität

python


from unionfind import unionfind
r = np.array(
    [[0,0,0],
     [1,1,1],
     [0,0,0]])
print(unionfind.isconnected(1-r))
r[1][1] = 0
print(unionfind.isconnected(1-r))
>>>
False
True

Angenommen, das resultierende $ r $ steht für 0: Weiß und 1: Schwarz. Sie können überprüfen, ob Weiß mit unionfind.isconnected (1-r) verbunden ist. In diesem Sinne können Sie das Modell ändern, bis es wie unten gezeigt verbunden ist.

python


while True:
    m.solve()
    r = np.vectorize(value)(v).astype(int)
    if unionfind.isconnected(1-r):
        break
    m += lpSum(v[r==1]) <= r.sum() - 1

Der obige Code ist einfach, kann jedoch bei einigen Rätseln lange dauern. In diesem Fall ist es möglich, anstatt "alle schwarzen Zellen im Ergebnis zu verbieten", effizient zu lösen, indem "die schwarzen Zellen, die das Weiß umgeben", für jeden durch die schwarzen Zellen geteilten weißen Bereich "verboten" werden. Ich kann es schaffen

Verarbeitung nach Gebiet (Raum oder Land)

Vorteile: Einfache Eingabe und Programmierung Zielrätsel: "Factor Room", "Country Road", "Satogaeri", "Star Battle", "Tile Paint", "Chocona", "Nori Nori", "Hey" Beispiel:

python


data = """\
AABBB
AABCC
ADDDC
DDECC
EEEEC""".split()
v = np.array(addbinvars(nn, nn))
for _, d in groupby(sorted(zip(''.join(data), v.flat)), lambda x:x[0]):
    m += lpSum(c[1] for c in d) == 1

Die Tabelle der zweidimensionalen Zellen ist wie in den obigen Daten gezeigt in Räume unterteilt. Zu diesem Zeitpunkt kann die Bedingung, dass "in jedem Raum ein schwarzes Quadrat vorhanden ist", einfach wie oben beschrieben werden, indem group by verwendet wird.

Wählen Sie aus Kandidaten

Dienstprogramm: Einfache Modellierung Zielrätsel: "Kanaore" "Satogaeri" "In Quadrate schneiden" "Nurikabe" "Noguram" "Filmat" "Blockpuzzle" "Firefly Beam]

Wenn Sie zwei 0-1-Variablen $ x, y $ haben und höchstens eine davon (= 1) enthalten soll, können Sie Folgendes tun:

Beispiel:

python


m += x + y <= 1

Wenn es schwierig ist, die Regeln eines Puzzles mit einer Formel auszudrücken, kann es einfach sein, die Kombinationen, die den Regeln entsprechen, aufzulisten und sie aus ihnen auswählen zu lassen. Eine solche Formulierung entspricht dem Set Division Problem des Typical Problem.

Werfen wir einen Blick auf die Funktion zur Erstellung von Kandidaten für "Kanaore". Beispiel:

python


def makecand(lst, y, x, d, l, p, u):
    yy, xx = y+[0, -1, 0, 1][d], x+[-1, 0, 1, 0][d] # (1)
    if 0 <= yy < nh and 0 <= xx < nw and (yy,xx) not in u:
        if p == l - 1:
            lst.append(u + [(yy, xx)])
            return
        for k in range(4):
            makecand(lst, yy, xx, k, l, p + 1, u + [(yy,xx)])

Das Argument d ist die Richtung. Fügen Sie 1 Quadrat in (1) hinzu, und wenn p die Länge erreicht, fügen Sie es zu lst hinzu und beenden Sie. Wenn nicht, wiederholen Sie die Suche in vier Richtungen. Es wäre schwierig, "Kanaore" anders als auf diese Weise zu modellieren. Modellierungssprachen wie AMPL ermöglichen kein flexibles Schreiben. Die Verwendung von Python für die Modellierung auf diese Weise kann sehr nützlich sein.

das ist alles

Recommended Posts

Kombinationsoptimierungstechniken in Rätseln
Lösen von "Würfeln in Würfeln" mit Kombinationsoptimierung
Python in der Optimierung
Verwenden Sie die Kombinationsoptimierung
Gruppierung nach Kombinationsoptimierung
Leistungsoptimierung in Django 3.xx.
Sternumfrage mit Kombinationsoptimierung
Gruppieren von Spielen mit Kombinationsoptimierung
Techniken zum Sortieren in Python
Kombinationsoptimierung mit Quantenglühen
Lösen Sie Optimierungsprobleme mit Python