Seite 1 von 1

Nebenbedingung funktioniert nicht

Verfasst: Donnerstag 1. August 2019, 09:38
von kristingr13
Hallo ihr Lieben,

mit Hilfe von Python/ Gurobi versuche ich das folgende Modell zu lösen. Das Problem ist, dass das Modell lösbar ist, außer ich nehme Nebenbedingung 2b hinzu. Die funktioniert nur, wenn es >= 1 heißt, es muss aber == 1 sein. Woran kann das liegen? Ich finde den Fehler einfach nicht. Vielen Dank schonmal im Voraus!

Code: Alles auswählen

from gurobi import *

model = Model("intermodality")

model.modelSense = GRB.MINIMIZE

#noch mit Beispielinstanzen

v = 5 #Beispiel
Standorte = range(v)                                                          #Standorte Kreis Heinsberg

m = 3
Mobilitaetsmodi = range(m)                                                    #Mobilitätsmodi: OEPNV, Carsharing, Bikesharing

b = 3 #Beispiel
Opportunities = range(b)                                                     #Opportunities (Welche Art?) Beispiel: Hausarzt, HNO, Zahnarzt


#Standorte_opportunities = [[0,1,0,1,1],[1,1,1,0,0],[1,1,1,1,1]]          #Standorte, welche Opportunity o anbieten
#Beispiel           
Standorte_opportunities = [[1,3,4],[0,1,2],[0,1,2,3,4]]


dictOpportunities = {}
for o in Opportunities:
        dictOpportunities[o] = Standorte_opportunities[o]

print (dictOpportunities)

times = [[[0,0,0],[46,17,57],[55,16,44],[26,14,40],[41,14,28]], #Beispielwerte travel times t[i,j,m]
         [[50,17,52],[0,0,0],[50,21,91],[15,21,71],[4,13,27]],
         [[58,16,41],[49,21,89],[0,0,0],[19,13,30],[44,18,60]],
         [[26,14,35],[16,21,71],[20,13,31],[0,0,0],[12,17,44]],
         [[46,14,28],[4,12,31],[46,18,66],[9,18,47],[0,0,0]]]


dictTimes = {}
for i in Standorte:
    for j in Standorte:
        for m in Mobilitaetsmodi:
            dictTimes[i,j,m] = times[i][j][m]  


PossibleItineraries = {}                  #Dictionary possible itineraries
Requirements = {}                       #Dictionary mobility hub requirements
itineraryTimes = {}                     #Dictionary Fahrtzeit der verschiedenen Routen
numberRequirements = {}                  #Dictionary Anzahl requirements

itineraryID = 0
for i in Standorte:
    for j in Standorte:
        if i != j:
            PossibleItineraries[i,j] = []
            #0-transfers
            for m in Mobilitaetsmodi:
                PossibleItineraries[i,j].append(itineraryID)
                Requirements[itineraryID] = [[i,m],[j,m]]                          #set of mobility hub requirements
                numberRequirements[itineraryID] = len(Requirements[itineraryID])
                itineraryTimes[itineraryID] = dictTimes[i,j,m]
                itineraryID += 1
            #1-transfer
            for k in Standorte:
                for m in Mobilitaetsmodi:
                    for n in Mobilitaetsmodi:
                        if m!=n:
                            if k!=i:
                                if k!=j:
                                    if times[i][k][m]+times[k][j][n]<=times[i][j][0]:       
                                    #die Fahrzeit mit einem Umstieg muss besser/gleich der direkten Fahrzeit mit OEPNV sein
                                        if times[i][k][m]+times[k][j][n]<=2 * times[i][j][1]:
                                        #direkte Autoverbindungen müssen zweimal schneller sein, um gewählt zu werden
                                           PossibleItineraries[i,j].append(itineraryID)
                                           Requirements[itineraryID] = [[i,m],[k,m],[k,n],[j,n]]
                                           numberRequirements[itineraryID] = len(Requirements[itineraryID])
                                           itineraryTimes[itineraryID] = dictTimes[i,k,m]+dictTimes[k,j,n]+10       #+10 Minuten Umstiegszeit
                                           itineraryID += 1                                           
            #2-transfer
            for k in Standorte:
                for l in Standorte:
                   for m in Mobilitaetsmodi:
                        for n in Mobilitaetsmodi:
                            for q in Mobilitaetsmodi:
                                if m!=n:
                                    if n!=q:
                                        if k!=i:
                                            if k!=j:
                                                if k!=l:
                                                    if l!=i:
                                                        if l!=j:
                                                            if times[i][k][m]+times[k][l][n]+times[l][j][q]<=times[i][j][0]:
                                                            #die Fahrzeit mit zwei Umstieg muss besser/gleich der direkten Fahrzeit mit OEPNV sein
                                                                if times[i][k][m]+times[k][l][n]+times[l][j][q]<=2 * times[i][j][1]:
                                                                #direkte Autoverbindungen müssen zweimal schneller sein, um gewählt zu werden
                                                                    PossibleItineraries[i,j].append(itineraryID)
                                                                    Requirements[itineraryID] = [[i,m],[k,m],[k,n],[l,n],[l,q],[j,q]]
                                                                    numberRequirements[itineraryID] = len(Requirements[itineraryID])
                                                                    itineraryTimes[itineraryID] = dictTimes[i,k,m]+dictTimes[k,l,n]+dictTimes[l,j,q]+20
                                                                    #+20 Minuten Umstiegszeit
                                                                    itineraryID += 1


travelvolume = [[0, 1000, 200, 400, 666],                      #travelvolume
             [200, 0, 350, 50, 2000],
             [1000, 400, 0, 750, 230],
             [190, 607, 610, 0, 550],
             [222, 88, 234, 512, 0]]
#Beispiel 


dictVolume = {}
for i in Standorte:
    for j in Standorte:
        dictVolume[i,j] = travelvolume[i][j]
        

Capacity={}
Capacity[1]=3
Capacity[2]=3


#ENTSCHEIDUNGSVARIABLEN

x = {}
y = {}

f = {}
g = {}

for i in Standorte:
    for m in Mobilitaetsmodi:
        y[i,m] = model.addVar(vtype=GRB.BINARY, name="y_%s%s" % (i,m))
        #y[i,m]=1 -> am Standort i wird Mobilitymode m angeboten
        
for i in Standorte:
    for j in Standorte:
        if i!=j:
            for p in PossibleItineraries[i,j]:
                x[i,j,p] = model.addVar(vtype=GRB.BINARY, name = "x_%s%s%s" % (i,j,p))
            #x[i,j,p]=1 -> die Route von p ist die schnellste von i nach j und wird ausgewählt
            
for i in Standorte:
    for j in Standorte:
        if i!=j:
            f[i,j] = model.addVar(vtype=GRB.INTEGER, name="f_%s%s" % (i,j))
            #traveltime der schnellsten Route von i nach j
        
for i in Standorte:
    for o in Opportunities:
        g[i,o] = model.addVar(vtype=GRB.INTEGER, name="g_%s%s" % (i,o))
        #traveltime schnellste Route von i zur Opportunity o
        
       
        
        
        
#ZIELFUNKTIONEN       
ZF=1
if ZF==1:
    model.setObjective(quicksum(dictVolume[i,j] * f[i,j] for i in Standorte for j in Standorte if i!=j))    #Zielfunktion 1a
else:
    model.setObjective(quicksum(g[i,o] for i in Standorte for o in Opportunities)) 
if ZF==1:
    valObjH=quicksum(g[i,o] for i in Standorte for o in Opportunities)                                       #Zielfunktion 1b
else:
    valObjH=quicksum(dictVolume[i,j] * f[i,j] for i in Standorte for j in Standorte if i!=j)

            
model.update()


#NEBENBEDINGUNGEN

for i in Standorte:
    for j in Standorte:
        if i!=j:
            model.addConstr(quicksum(x[i,j,p] for p in PossibleItineraries[i,j])==1)                                     #NB 2a
           

for i in Standorte:
    for o in Opportunities:
        model.addConstr(quicksum(x[i,j,p] for j in dictOpportunities[o] if i!=j for p in PossibleItineraries[i,j])==1)   #NB 2b
        

for i in Standorte:    
    for j in Standorte:
        if i!=j:
            for p in PossibleItineraries[i,j]:
                model.addConstr(numberRequirements[p] * x[i,j,p] <= quicksum(y[k,m] for (k,m) in Requirements[p]))        #NB 3

for i in Standorte:
    for j in Standorte:
        if i!=j:
            for p in PossibleItineraries[i,j]:
                    model.addConstr(itineraryTimes[p] * x[i,j,p] <= f[i,j])                                             #NB 4a
                  
for i in Standorte:
    for o in Opportunities:
        for j in dictOpportunities[o]:
            if i!=j:
                for p in PossibleItineraries[i,j]:
                    model.addConstr(itineraryTimes[p] * x[i,j,p] <= g[i,o])                                             #NB 4b             

for m in [1,2]:
    model.addConstr(quicksum(y[i,m] for i in Standorte)<=Capacity[m])                                                   #NB 5

model.optimize()





Re: Nebenbedingung funktioniert nicht

Verfasst: Freitag 2. August 2019, 10:50
von Sirius3
Die vielen verschachtelten for- mit if-Blöcke kann man durch itertools.combinations deutlich eleganter und performanter ausdrücken.

`itineraryTimes` wäre wohl besser eine Liste als ein Wörterbuch.
Und `dictTimes` scheint auch überflüssig zu sein, weil man auch direkt `times` verwenden könnte.

Wie kommst Du darauf, dass das Problem mit den Nebenbedingungen lösbar sein sollte?

Re: Nebenbedingung funktioniert nicht

Verfasst: Freitag 2. August 2019, 19:01
von kristingr13
Sirius3 hat geschrieben: Freitag 2. August 2019, 10:50 Die vielen verschachtelten for- mit if-Blöcke kann man durch itertools.combinations deutlich eleganter und performanter ausdrücken.

`itineraryTimes` wäre wohl besser eine Liste als ein Wörterbuch.
Und `dictTimes` scheint auch überflüssig zu sein, weil man auch direkt `times` verwenden könnte.

Wie kommst Du darauf, dass das Problem mit den Nebenbedingungen lösbar sein sollte?
Erstmal vielen Dank für die Antwort! Deine Tipps werde ich auf jeden Fall beherzigen.
Ich habe es jetzt erstmal so probiert, dass ich eine neue Variable erstellt habe: s[i,j,p], die genauso aufgebaut ist wie x[i,j,p].
Da war wohl das Problem, bin mir aber noch nicht sicher.