mdl = Model('CVRP')
x = mdl.binary_var_dict(A, name='x')
u = mdl.continuous_var_dict(N, name='u')
mdl.minimize(mdl.sum(distanceList[i][j]*x[i, j] for i, j in A))
mdl.add_constraints(mdl.sum(x[i, j] for j in V if j != i) == 1 for i in N)
mdl.add_constraints(mdl.sum(x[i, j] for i in V if i != j) == 1 for j in N)
mdl.add_constraints(mdl.add(u[i] - u[j] + n*(x[i,j]) <= n - 1 for i in N for j in N if i!=j))
When I ran this code, I got this warning:
Warning: constraint has already been posted: 25x_25_24-u_24+u_25 <= 24, index is: 649
I think my model duplicates same constraints many times, but I cannot figure that why this is happening. It is related to the last constraint that provides subtour elimination.
I really appreciate that somebody helps me to get rid of duplication or a new subtour elimination constraint. Thanks.
Model.add(..) builds a constraint , add it to the model and returns it.
Thus when you call Model.add_constraints on the results of the various Model.add calls, you end adding constraints *which have already been added.
Removing the call to Model.add should do the trick:
mdl.add_constraints((u[i] - u[j] + n*(x[i,j]) <= n - 1) for i in N for j in N if i!=j)
Related
A is a mn matrix
B is a nn matrix
I want to return matrix C of size m*n such that:
In python it could be like below
for i in range(m):
for j in range(n):
C[i][j] = 0
for k in range(n):
C[i][j] += max(0, A[i][j] - B[j][k])
this runs on O(m*n^2)
if A[i][j] - B[j][k] is always > 0 it could easily be improved as
C[i][j] = n*A[i][j] - sum(B[j])
but it is possible to improve as well when there are cases of A[i][j] - B[j][k]< 0 ? I think some divide and conquer algorithms might help here but I am not familiar with them.
For each j, You can sort each column B[j][:] and compute cumulative sums.
Then for a given A[i][j] you can find the sum of B[j][k] that are larger than A[i][j] in O(log n) time using binary search. If there's x elements of B[j][:] that are greater than A[i][j] and their sum is S, then C[i][j] = A[i][j] * x - S.
This gives you an overall O((m+n)n log n) time algorithm.
I would look on much simpler construct and go from there..
lets say the max between 0 and the addition wasn't there.
so the answer would be : a(i,j)n - sum(b(j,)
on this you could just go linearly by sum each vector and erase it from a(i,j)n
and because you need sum each vector in b only once per j it can be done in max(mn,nn)
now think about simple solution for the max problem...
if you would find which elements in b(j,) is bigger than a(i,j) you could just ignore their sum and substract their count from the multipication of a(i,j)
All of that can be done by ordering the vector b(j,) by size and make a summing array to each vector from the biggest to lowest (it can be done in nnlog(n) because you order each b(j,) vector once)
then you only need to binary search where is the a(i,j) in the ordered vector and take the sum you already found and subtract it from a(i,j) * the position you found in the binary search.
Eventually you'll get O( max( mnlog(n),nnlog(n) ) )
I got for you also the implementation:
import numpy as np
M = 4
N = 7
array = np.random.randint(100, size=(M,N))
array2 = np.random.randint(100, size=(N,N))
def matrixMacossoOperation(a,b, N, M):
cSlow = np.empty((M,N))
for i in range(M):
for j in range(N):
cSlow[i][j] = 0
for k in range(N):
cSlow[i][j] += max(0, a[i][j] - b[j][k])
for i in range(N):
b[i].sort()
sumArr = np.copy(b)
for j in range(N):
for i in range(N - 1):
sumArr[j][i + 1] += sumArr[j][i]
c = np.empty((M,N))
for i in range(M):
for j in range(N):
sumIndex = np.searchsorted(b[j],a[i][j])
if sumIndex == 0:
c[i][j] = 0;
else:
c[i][j] = ((sumIndex) * a[i][j]) - sumArr[j][sumIndex - 1]
print(c)
assert(np.array_equal(cSlow,c))
matrixMacossoOperation(array,array2,N,M)
I have a variable made of 961 elements. And I have a constraint like this: only 8 elements of the variable are nonzero, and the others are 0. I don't know how to express this constraint in cvxpy. I tried this:
import cvxpy as cp
K = cp.Variable(961, integer=Ture)
s = 0
constraint = [cp.sum([s+1 for t in K if t!=0])==8]
But I got the following error:
Exception: Cannot evaluate the truth value of a constraint or chain constraints, e.g., 1 >= x >= 0.
Let's look at this mathematically.
Problem: You have integer variables x[i] ∈ {0,1,2,...,N} and you want to allow only K of them to be nonzero.
We can do this by introducing a parallel binary variable b[i] ∈ {0,1} that indicates whether x[i] is pinned to zero. I use the convention:
b[i] = 0 => x[i] = 0
b[i] = 1 => x[i] ∈ {0,1,2,...,N}
This can be written simply as a set of constraints:
x[i] <= N*b[i]
sum(i,b[i]) = K
If you want to use the slightly different definition:
b[i] = 0 => x[i] = 0
b[i] = 1 => x[i] ∈ {1,2,...,N}
then we need:
x[i] <= N*b[i]
x[i] >= b[i]
sum(i,b[i]) = K
If the integer variables are: x[i] ∈ {-N,...,-2,-1,0,1,2,...,N} then we can do:
x[i] <= N*b[i]
x[i] >= -N*b[i]
sum(i,b[i]) = K
I assume that CVXPY generates the same thing when you say:
abs(x) <= N*b
sum(b) == K
(The condition abs(x[i]) >= b[i] is a little bit more messy to linearize in this case).
This should not be too difficult to transcribe into a CVXPY model. Note that we need this explicit upper bound N on x[i]. Make it not too large.
from gurobipy import *
import pandas as p
import numpy as np
d={
(1,1):2,(1,2):3,(1,3):3,(1,4):5,
(2,1):2,(2,2):3,(2,3):3,(2,4):5,
(3,1):2,(3,2):3,(3,3):3,(3,4):5,
(4,1):2,(4,2):3,(4,3):3,(4,4):5,
(5,1):2,(5,2):3,(5,3):3,(5,4):5,
}
P,p=multidict({1:1,2:1,3:2,4:2,5:2})
W,w=multidict({1:2,2:2,3:2,4:2})
D=100
total_p=sum([i for i in p.values()])
total_w=sum([j for j in w.values()])
if total_w/total_p<1:
R= total_w/total_p
else :
R=1
print(R)
model=Model("keibi optimizer")
x={}
for i in P:
for j in W:
x[i,j]=model.addVar(vtype="C",name="x(%s,%s)"%(i,j))
model.update()
for j in W:
model.addConstr(quicksum(x[i,j] for i in P) == w[j],name='Demand(%s)' %j)
for i in P:
model.addConstr(quicksum(x[i,j] for j in W) <= p[i],name='Capacity(%s)' %i)
for i in P:
for j in W:
model.addConstr(d[i,j]*x[i,j],"<=",D*x[i,j])
model.setObjective(quicksum(D-(sum((d[i,j]*x[i,j]/x[i,j]) for j in W if x!=0))for i in P),GRB.MAXIMIZE)
model.optimize()
print("Optimal value:", model.ObjVal/(total_p*D))
for(i,j) in x:
print("sending quantity %10s from factory %3s to customer %3s" %(x[i,j], j, i))
I made the above program using python gurobi9.12. But I cannot run the program.
error message
Divisor must be a constant
I guess model.setObjective(quicksum(D-(sum((d[i,j]*x[i,j]/x[i,j]) for j in W if x!=0))for i in P),GRB.MAXIMIZE) is complicated.
I want to make a program using the formula in the photo below as the objective function.
What should I do? Please help me.
So let's focus on: Σ_j∈W d[i,j]*x[i,j]/Σj∈W x[i,j]. First, the math is confusing. I never, ever have a sum over j inside a sum over j. We don't know what j is inside the inner sum.
I'll use the notation:
sum(j, d[i,j]*x[i,j]/y[i])
y[i] = sum(j, x[i,j])
for our problem. Now we can do:
sum(j, d[i,j]*z[i,j])
y[i]*z[i,j] = x[i,j] for all i,j
y[i] = sum(j, x[i,j]) for all i
y[i],z[i,j] free variables
As you can see, there is no division anymore. Note that we introduced a non-convex quadratic constraint here. That is a bit expensive but better than division which cannot be handled by Gurobi at all. Further note that we allow y[i]=0 here (multiplication by zero is allowed, but dividing by zero is not).
In general, if you see z=x/y, you need to consider using x=z*y.
I am trying to write the constraint related to multiple variables. However, it shows error "Indicator constraints can only be triggered by a single binary variable at a given value". Can you help me fix this error? Thank you very much!
The code is following:
mdl.addConstrs((x[i,j,k] - t[i,j,k] == 1) >> (d2[j,k] == d2[i,k] - d[i,j]) for i, j, k in arcos2 if i != 0 and j != 0)
Where:
x[i,j,k], t[i,j,k] are binary variables
d2[j,k], d2[i,k] are continuous variables
d[i,j] is a parameter
I think the error message is pretty clear. Define binary helper variables q[i,j,k] to represent x[i,j,k] - t[i,j,k]. Then:
for i, j, k in arcos2:
if i != 0 and j != 0:
mdl.addConstr(q[i,j,k] == x[i,j,k] - t[i,j,k])
mdl.addConstr((q[i,j,k] == 1) >> (d2[j,k] == d2[i,k] - d[i,j]))
I am quite new in python cplex. I tried to model VRP and needed to eliminate subtours for feasible solution, but I cannot do that with the following code:
from docplex.mp.model import Model
import numpy as np
n = 10
Q = 20
N = [i for i in range(1, n+1)]
V = [0] + N
rnd = np.random
rnd.seed(0)
q = {i: rnd.randint(1, 10) for i in N}
loc_x = rnd.rand(len(V))*200
loc_y = rnd.rand(len(V))*100
A = [(i, j) for i in V for j in V if i != j]
c = {(i, j): np.hypot(loc_x[i]-loc_x[j], loc_y[i]-loc_y[j]) for i, j in A}
mdl = Model('CVRP')
x = mdl.binary_var_dict(A, name='x')
u = mdl.continuous_var_dict(N, lb=0, name='u')
mdl.minimize(mdl.sum(c[i, j]*x[i, j] for i, j in A))
mdl.add_constraints(mdl.sum(x[i, j] for j in V if j != i) == 1 for i in N)
mdl.add_constraints(mdl.sum(x[i, j] for i in V if i != j) == 1 for j in N)
mdl.add_constraints(mdl.add(u[i] - u[j] + n*(x[i,j]) <= n - 1 for i,j in N if i!=j))
mdl.parameters.timelimit = 15
solution = mdl.solve()
print(solution)
When I run it, I get the following error:
File "C:\Users\user.spyder-py3\TSP\cplexExp.py", line 25, in
mdl.add_constraints(mdl.add(u[i] - u[j] + n*(x[i,j]) <= n - 1 for i,j in N if i!=j))
TypeError: cannot unpack non-iterable int object
I really appreciate for any help. thanks!!
Thanks guys, the problem is that N is one dimensional array, but I considered it as two dimensional by using i,j in N. I figured that out. By the way, do you know any good resource to learn CPLEX Python? I am new and do not know where to start. Thanks!!
Have a look at the Docplex examples here:
https://github.com/IBMDecisionOptimization/docplex-examples