0

i'm a newbie to julia and struggling how to handle quadratic equality constraints when using gurobi as the main solver. Can u may take a quick look at the following listing? I alread know that such structures are impossible to solve by using gurobi, but how do I can bypass this difficulty and thus enforce the condition to my model?

[listing][1]

Relevant and defined Variables causing problems:

  • x: binary decision variable
  • s: s>=0

I would be glad about any help!

Andre

eukl_distance = [0 6 5 7 9 8; 6 0 6 3 14 9; 5 6 0 5 9 4; 7 3 5 0 13 8; 
9 14 9 13 0 7; 8 9 4 8 7 0]

# Nachfrage an Knoten i
d = [0,2,1,1,3,1]

no_nodes = 6

# Zeitfenster 
time_windows = [Vector{Float64}(2) for i=1:no_nodes]
time_windows[1] = [0,10]
time_windows[2] = [1,4]
time_windows[3] = [2,5]
time_windows[4] = [4,7]
time_windows[5] = [3,6]
time_windows[6] = [5,8]

# Fahrtzeit von i nach j und Servicezeit an Knoten i
t = [Array{Float64}(no_nodes) for i=1:no_nodes]
t[1] = [0,2,1.5,2.5,4,3.5]
t[2] = [2,0,2,1,6,4]
t[3] = [1.5,2,0,1.5,4,1.25]
t[4] = [2.5,1,1.5,0,5.75,3.5]
t[5] = [4,6,4,5.75,0,2.5]
t[6] = [3.5,4,1.25,3.5,2.5,0]

# Anzahl Fahrzeuge
k = 2

# Kapazität Fahrzeuge
C = 5

# Strafkostenfaktor
z = 2

M = 100000000000000000

using JuMP, Gurobi, LightGraphs, Distances

m = Model(solver = GurobiSolver())

@variable(m, x[i=1:no_nodes,j=1:no_nodes,kk=1:k], Bin)
@variable(m, y[i=1:no_nodes, kk=1:k], Bin)
@variable(m, 0<=s[i=1:no_nodes,kk=1:k]<=M)
@variable(m, w1[i=1:no_nodes, kk=1:k]>=0)
@variable(m, w2[i=1:no_nodes, kk=1:k]>=0)

# Hilfsvariablen
@variable(m, h1[i=1:no_nodes, j=1:no_nodes, kk=1:k]>=0)
@variable(m, h2[i=1:no_nodes, j=1:no_nodes, kk=1:k]>=0)

# Beachte: Division von z durch no_nodes notwendig,
# da ansonsten w1 und w2 für jedes i über jedes j
# addiert werden. Beispiel: Sei i = 2 und j=1:6
# x[2,1,1]*dist+w1[2,1]*2+w2[2,1]*2+x[2,1,2]*dist+w1[2,2]*2+w2[2,2]*2 +
# x[2,2,1]*dist+w1[2,1]*2+w2[2,1]*2+x[2,2,2]*dist+w1[2,2]*2+w2[2,2]*2 + 
# ... x[2,6,1]*dist+w1[2,1]*2+w2[2,1]*2+x[2,6,2]*dist+w1[2,2]*2+w2[2,2]*2
@objective(m, Min, sum(x[i=ii,j=jj,n=kk]*eukl_distance[ii,jj]+w1[i=ii,n=kk]*z/no_nodes+w2[i=ii,n=kk]*z/no_nodes for ii=1:no_nodes, jj=1:no_nodes, kk=1:k))

# erlaube verfrühte sowie verspätete Ankunft
# Abfahrt am Depot zum Zeitpunkt 0
@constraint(m, earlyArrival[ii=1:no_nodes,kk=1:k], time_windows[i=ii][1]-s[i=ii,n=kk]-w1[i=ii,n=kk]<=0)
@constraint(m, lateArrival[ii=1:no_nodes,kk=1:k], time_windows[i=ii][2]-s[i=ii,n=kk]+w2[i=ii,n=kk]>=0)

# Eliminiere Kanten von i zu i
# [i,i]=0
@constraint(m, noSelfConnection[ii=1:no_nodes,kk=1:k], x[i=ii,j=ii,n=kk]==0)

# Jeder Kunde wird von einem Fahrzeug besucht
@constraint(m, oneCustomerVisitation[ii=2:no_nodes], sum(y[i=ii,kk=1:k])==1)

# Genau K Fahrzeuge erreichen das Depot
@constraint(m, sum(y[i=1,kk=1:k])==k)

# Wenn ein Fahrzeug einen Kunden i anfährt,
# muss die Summe aller genutzten ausgehenden und eingehenden Kanten,
# basienrend auf Knoten i, genau 1 entsprechen
@constraint(m, completeRoute1[ii=1:no_nodes, kk=1:k], sum(x[i=ii,j=1:no_nodes,n=kk])-y[i=ii,n=kk]==0)
@constraint(m, completeRoute2[ii=1:no_nodes, kk=1:k], sum(x[j=1:no_nodes,i=ii,n=kk])-y[i=ii,n=kk]==0)

# Kapazitätsbeschränkung
@constraint(m, capacityConstr[kk=1:k], sum(d[i]*y[i,kk] for i in 1:no_nodes)<=C)

# Ankunft am Knoten i entspricht der 
# Summe aus Ankunftszeit am Knoten j und Lieferzeit 
# von Knoten i zu j
for i=1:no_nodes, j=1:no_nodes, kk=1:k
    @constraint(m, h1[i,j,kk]<=M*x[i,j,kk])
    @constraint(m, h1[i,j,kk]<=x[i,j,kk]*s[i,kk])
    @constraint(m, h1[i,j,kk]>=s[i,kk]-M*(1-x[i,j,kk]))

    @constraint(m, h2[i,j,kk]<=M*x[i,j,kk])
    @constraint(m, h2[i,j,kk]<=x[i,j,kk]*s[j,kk])
    @constraint(m, h2[i,j,kk]>=s[j,kk]-M*(1-x[i,j,kk]))
    if i==1
        @constraint(m, x[i,j,kk]*t[i][j]-h2[i,j,kk]==0)
    else
        @constraint(m, h1[i,j,kk]+x[i,j,kk]*t[i][j]-h2[i,j,kk]==0)
    end
end

# ------------ Lazy Constraint -------------

function buildGraph(n)
g = DiGraph(n)
for i in 1:n, j in 1:n, kk in 1:k
    if round.(Int,getvalue(x)[i,j,kk])==1
        add_edge!(g,(i,j))
    end
end
return simplecycles_hadwick_james(g)
end

function subtour(cb)
subtours = buildGraph(no_nodes)
for n in 1:length(subtours), kk in 1:k
    if subtours[n][1]!=1 
        @lazyconstraint(cb, sum(x[i=subtours[n],j=subtours[n],kk])<=length(subtours[n])-1)
    end
end
end

addlazycallback(m, subtour)

solve(m)
getobjectivevalue(m)

for i in 1:no_nodes, j in 1:no_nodes, kk in 1:k
    if round.(Int,getvalue(x)[i,j,kk])==1
        println("($i,$j,$kk) = 1")
    end
end
PTueller
  • 31
  • 2
  • 7
  • Hi, can you post your code and the error thrown, because JuMP with Gurobi should be able to handle quadratic constraints. It would be best if you included the code in the question using code quoting feature of GitHub. – Bogumił Kamiński Aug 26 '18 at 07:27
  • Hey, thanks a lot for ur fast answer! I already update my post, hope so it's a bit more accessibe. Thanks again! All the best, Andre – PTueller Aug 26 '18 at 16:28
  • Check out this answer https://stackoverflow.com/questions/42598827/quadratically-constrained-miqp-with-julia-and-gurobi that explains the limitations of Gurobi solver and what can be done. I did not notice earlier that you have *equality* constraint in quadratic term. – Bogumił Kamiński Aug 26 '18 at 18:33
  • Hey, do you may have some hints how to rephrase the condition to make it compatible? Thanks in advance, Andre – PTueller Aug 26 '18 at 18:54
  • I would try to redefine variables to reduce it to PSD type of constraint `x^TQx + q^Tx <= b` (probably two for each condition) by merging `x`, `t` and `s` variables into one new `x` variable (which will be continuous) and then externally adding additional variable `S` that is binary with condition `s=S`. But I do not guarantee that it will work - your problem is too big to analyze in head. Hope it helps. – Bogumił Kamiński Aug 26 '18 at 19:16
  • Hi Bogumil, i tried to rephrase the condition but now it is said the Q-Matrix is not psd. I really do not know how to continue - the constraint is not a equality condition, rather an inequality condition. I've edit the post again with some example code, hope you can help! All the best, Andre – PTueller Aug 27 '18 at 15:43
  • Now you must be able to copy and paste the example code, thus you can have a look at the specific output. – PTueller Aug 27 '18 at 15:51
  • I could not find any satisfactory solution. Maybe your problem is not directly solvable using these methods (CPLEX show the same error). I am not sure what to do. – Bogumił Kamiński Aug 27 '18 at 22:53

0 Answers0