[PYTHON] Über das Problem der reisenden Verkäufer

Vor kurzem hatte ich aufgrund meiner Arbeit die Möglichkeit, mit "mathematischer Optimierung" in Kontakt zu treten. Es ist eine gute Idee, deshalb möchte ich die Ergebnisse einer kleinen privaten Berührung veröffentlichen.

Was ich getan habe, war ein Beispiel für mathematische Optimierung, das "Circular Salesman Problem". Da dies mit dem Pulp der freien Umgebung implementiert werden kann, habe ich versucht, es während der Vorbereitung der Umgebung zu implementieren.

Die Probleme, die ich versuchen möchte, sind wie folgt.

◆ 2.12 Problem mit dem Patrol-Verkäufer https://www.msi.co.jp/nuopt/docs/v19/examples/html/02-12-00.html

Ich habe unten ein einfaches Bild gezeichnet. A, B, C, D sind die Punkte auf der Karte.

map.png

Welche Route hat die geringste Gesamtentfernung, wenn Sie A verlassen und mit einem einzigen Schlag zurückkehren? Es scheint, dass das Optimierungsproblem als "Patrouillenverkäuferproblem" bezeichnet wird. Es heißt NP-Schwierigkeit, und es scheint ziemlich schwierig zu sein.

Der Ansatz mit dem Modellierer namens Pulp, der in der Python-Umgebung berührt wird, ist jedoch kostenlos !!! Es ist einfach, daher werde ich auf den folgenden Artikel verweisen.

◆ Mathematische Optimierung ausgehend vom Problem des Handlungsreisenden https://qiita.com/panchovie/items/6509fb54e3d53f4766aa

Das Tolle ist, dass wir alles haben, von der Installation von Zellstoff bis zum Beispielcode. Lassen Sie uns die erste Einstellung sofort in den Beispielcode einfügen. Was ist mit dem folgenden Code, der vorerst kompiliert zu werden scheint?

import pulp as pp

#Definition des Optimierungsmodells
mip_model = pp.LpProblem("tsp_mip", pp.LpMinimize)

N = 4
BigM = 10000

c_ = [
      [0,6,5,5], # pointA > [pointA,pointB,pointC,pointD]
      [6,0,7,4], # pointB > [pointA,pointB,pointC,pointD]
      [5,7,0,3], # pointC > [pointA,pointB,pointC,pointD]
      [5,4,3,0], # pointD > [pointA,pointB,pointC,pointD]
      ]

#Variablendefinition
x = [[pp.LpVariable("x(%s,%s)"%(i, j), cat="Binary") for i in range(N)] for j in range(N)]
u = [pp.LpVariable("u(%s)"%(i), cat="Continuous", lowBound=1.0, upBound=(N)) for i in range(N)]

#Definition und Registrierung des Bewertungsindex (Gleichung (1))
objective = pp.lpSum(c_[i][j] * x[i][j] for i in range(N) for j in range(N) if i != j)
mip_model += objective

#Bedingter Ausdruck(2)Registrierung von
for i in range(N):
    mip_model += pp.lpSum(x[i][j] for j in range(N) if i != j) == 1

#Bedingter Ausdruck(3)Registrierung von
for i in range(N):
    mip_model += pp.lpSum(x[j][i] for j in range(N) if i != j) == 1

for i in range(N):
    mip_model += x[i][i] == 0
    
#Bedingter Ausdruck(4) (MTZ-Einschränkung)
for i in range(N):
    for j in range(N):
        if i != j:
            mip_model += u[i] + 1.0 - BigM * (1.0 - x[i][j]) <= u[j]


#Führen Sie eine Optimierung durch
status = mip_model.solve()

#Die Ergebnisse verstehen
print("Status: {}".format(pp.LpStatus[status]))
print("Optimal Value [a.u.]: {}".format(objective.value()))

for i in range(N):
    for j in range(N):
        if i != j:
            print("x[%d][%d]:%f" % (i,j,x[i][j].value()))

for i in range(len(u)):
    print("u[%d] %f" % (i,u[i].value()))

Wenn Sie es in diesem Zustand ausführen ...

Status: Infeasible
Optimal Value [a.u.]: 18.0
x[0][1]:0.000000
x[0][2]:1.000000
x[0][3]:0.000000
x[1][0]:0.999800
x[1][2]:0.000000
x[1][3]:0.000200
x[2][0]:0.000200
x[2][1]:0.000000
x[2][3]:0.999800
x[3][0]:0.000000
x[3][1]:1.000000
x[3][2]:0.000000

Es scheint, dass es nicht gut berechnet wurde. Es scheint, dass die Einschränkungsbedingungen nicht gut erfüllt sind, so dass es nach verschiedenen Untersuchungen so aussieht, als ob die MTZ-Einschränkungsformel so seltsam ist, wie sie ist. Wenn Sie alle vier Formeln für x bis u im Endzustand schreiben, ist dies wie folgt.

u[0] < u[2]\\
u[1] < u[0]\\
u[2] < u[3]\\
u[3] < u[1]

Wenn es darum geht, all dies zu befriedigen,

u[0] < u[2] < u[3] < u[1] < u[0] < ...

Es wird unendlich zunehmen, aber da der effektive Bereich von u zwischen 1 und 4 liegt, scheint es einen Widerspruch zu geben. Lassen Sie uns daher die Formel wie folgt rekonstruieren, indem Sie die Einschränkung für die Variable entfernen, die am Ende zu Punkt A zurückkehrt.

u[0] < u[2]\\
u[2] < u[3]\\
u[3] < u[1]

Dies ändert die Implementierung und die MTZ-Bedingungsformel in:

#Bedingter Ausdruck(4) (MTZ-Einschränkung)
for i in range(N):
    for j in range(1,N):
        if i != j:
            mip_model += u[i] + 1.0 - BigM * (1.0 - x[i][j]) <= u[j]

Der Quellcode ist unten zusammengefasst.

sample_route.py


import pulp as pp

#Definition des Optimierungsmodells
mip_model = pp.LpProblem("tsp_mip", pp.LpMinimize)

N = 4
BigM = 10000

c_ = [
      [0,6,5,5], # pointA > [pointA,pointB,pointC,pointD]
      [6,0,7,4], # pointB > [pointA,pointB,pointC,pointD]
      [5,7,0,3], # pointC > [pointA,pointB,pointC,pointD]
      [5,4,3,0], # pointD > [pointA,pointB,pointC,pointD]
      ]

#Variablendefinition
x = [[pp.LpVariable("x(%s,%s)"%(i, j), cat="Binary") for i in range(N)] for j in range(N)]
u = [pp.LpVariable("u(%s)"%(i), cat="Continuous", lowBound=1.0, upBound=(N)) for i in range(N)]

#Definition und Registrierung des Bewertungsindex (Gleichung (1))
objective = pp.lpSum(c_[i][j] * x[i][j] for i in range(N) for j in range(N) if i != j)
mip_model += objective

#Bedingter Ausdruck(2)Registrierung von
for i in range(N):
    mip_model += pp.lpSum(x[i][j] for j in range(N) if i != j) == 1

#Bedingter Ausdruck(3)Registrierung von
for i in range(N):
    mip_model += pp.lpSum(x[j][i] for j in range(N) if i != j) == 1

for i in range(N):
    mip_model += x[i][i] == 0
    
#Bedingter Ausdruck(4) (MTZ-Einschränkung)
for i in range(N):
    for j in range(1,N):
        if i != j:
            mip_model += u[i] + 1.0 - BigM * (1.0 - x[i][j]) <= u[j]


#Führen Sie eine Optimierung durch
status = mip_model.solve()

#Die Ergebnisse verstehen
print("Status: {}".format(pp.LpStatus[status]))
print("Optimal Value [a.u.]: {}".format(objective.value()))

for i in range(N):
    for j in range(N):
        if i != j:
            print("x[%d][%d]:%f" % (i,j,x[i][j].value()))

for i in range(len(u)):
    print("u[%d] %f" % (i,u[i].value()))

Das Ergebnis ist wie folgt.

Status: Optimal
Optimal Value [a.u.]: 18.0
x[0][1]:0.000000
x[0][2]:1.000000
x[0][3]:0.000000
x[1][0]:1.000000
x[1][2]:0.000000
x[1][3]:0.000000
x[2][0]:0.000000
x[2][1]:0.000000
x[2][3]:1.000000
x[3][0]:0.000000
x[3][1]:1.000000
x[3][2]:0.000000
u[0] 1.000000
u[1] 4.000000
u[2] 2.000000
u[3] 3.000000

Es konvergierte sicher. Die Ergebnisse sind nicht grafisch,

Punkt A → Punkt C → Punkt D → Punkt B → Punkt A.

Scheint die kürzeste zu sein und die Entfernung beträgt 18. Wo das Problem aufgeführt war

Punkt A → Punkt B → Punkt D → Punkt C → Punkt A.

Immerhin ist die Entfernung 18 und es scheint die kürzeste zu sein, also gibt es einige Antworten.

Die mathematische Optimierung ist nur in Bereichen sehr aktuell, die wir zuvor noch nicht angesprochen haben. Es gibt eine Umgebung, in der Sie es gerne ausprobieren können, also werde ich diese Gelegenheit nutzen, um verschiedene Dinge zu studieren.

Recommended Posts

Über das Problem der reisenden Verkäufer
Über das bestellte Patrouillenverkäuferproblem
Python: Ich habe das Problem des Handlungsreisenden ausprobiert
Lösen Sie das Problem des Handlungsreisenden mit OR-Tools
Ich habe versucht, das Problem des Handlungsreisenden umzusetzen
Denken Sie an das Problem der minimalen Änderung
Brennmethode und Problem mit reisenden Verkäufern
Über den Test
Über die Warteschlange
Versuchen Sie, das Problem des Handlungsreisenden mit einem genetischen Algorithmus zu lösen (Theorie)
Versuchen Sie, das Problem des Handlungsreisenden mit einem genetischen Algorithmus zu lösen (Ausführungsergebnis)
Informationen zur Entfaltungsfunktion
Über den Servicebefehl
Lösung des Problems des Handlungsreisenden mit dem genetischen Algorithmus (GA) und seiner Bibliothek (vcopt)
Lösen Sie das asymmetrische Python-Problem für reisende Verkäufer mit der Branch-and-Bound-Methode
Über die Verwirrungsmatrix
Über das Besuchermuster
Untersuchen Sie das doppelte Problem
Lösen Sie das Monty Hall-Problem
Über das Python-Modul venv
Über die Aufzählungsfunktion (Python)
Eine Geschichte über den Umgang mit dem CORS-Problem
Über das Verständnis des 3-Punkt-Lesers [...]
Über die Komponenten von Luigi
Über die Funktionen von Python
Kombinationsoptimierung - typisches Problem - Rundschreiben Verkäufer Problem
Ich habe versucht, "einen genetischen Algorithmus (GA) in Python zu implementieren, um das Problem des Handlungsreisenden (TSP) zu lösen".
Eine Geschichte, in der der Algorithmus zu einem lächerlichen Ergebnis kam, als er versuchte, das Problem der reisenden Verkäufer richtig zu lösen
[Python] Was ist @? (Über Dekorateure)
Über den Rückgabewert von pthread_mutex_init ()
Über den Rückgabewert des Histogramms.
Über den Grundtyp von Go
Über die Obergrenze von Threads-max
Über die durchschnittliche Option von sklearn.metrics.f1_score
Über das Verhalten von Yield_per von SqlAlchemy
Illustration der Ergebnisse des Rucksackproblems
Über die Größe der Punkte in Matplotlib
Informationen zur Grundlagenliste der Python-Grundlagen
Denken Sie grob über die Verlustfunktion nach
Mein Freund scheint Python zu machen, also denke über das Problem nach ~ fizzbuzz ~