I am having some issues with my Linear Program Model in gurobi. I am quite new to programming, and don't really understand what the error is. It comes up as 'gurobipy.LinExpr' object is not iterable with my Objective Function. This is my code currently
from gurobipy import *
IDtoLVC = [
[40.4,61.2,69.3,60.9,86.8,13.1,70.5,69.7],
[59.5,5.6,45.8,85.6,62.6,46.9,77.8,29.7],
[27.2,62.7,26.9,30.1,30.3,62.6,11.7,45.0]
]
CCDPop = [2180,4887,2174,4244,2444,2156,2433,2096,4148,3636,4935,3160,4153,2058,4614,3862,4588,4264,2559,2770,3964,2333,3681,4786,3256]
CCDtoLVC = [
[48.8,0,0,0,0,19.2,0,0],
[46.3,0,0,0,0,8.3,0,0],
[0,37.2,0,0,0,17.7,0,0],
[0,14.0,0,0,0,0,0,36.1],
[0,18.4,0,0,0,0,0,42.2],
[35.5,0,0,0,0,20.1,0,0],
[33.3,0,0,0,0,6.8,0,0],
[24.9,0,0,0,0,18.7,0,0],
[0,17.4,0,0,0,30.8,0,0],
[0,12.4,0,0,0,0,0,20.1],
[23.5,0,0,31.6,0,0,0,0],
[6.9,0,0,28.3,0,0,0,0],
[17.9,0,27.7,0,0,0,0,0],
[0,24.4,20.3,0,0,0,0,16.4],
[0,28.9,26.1,0,0,0,0,11.5],
[28.3,0,0,12.0,0,0,0,0],
[13.0,0,0,14.4,0,0,24.9,0],
[13.1,0,26.7,31.0,0,0,24.0,0],
[0,0,6.5,0,17.1,0,0,25.4],
[0,0,20.3,0,16.4,0,0,23.3],
[0,0,0,15.1,0,0,35.3,0],
[27.2,0,0,14.1,0,0,7.8,0],
[0,0,25.6,0,25.0,0,14.7,0],
[0,0,26.7,0,12.0,0,0,0],
[0,0,30.2,0,15.5,0,0,0]
]
LVCCost = [194, 105, 184]
# Sets
I = range(3) # no. of IDs
J = range(8) # no. of LVCs
K = range(25) # no. of CCDs
T = range(6) # length of time
# Model
m = Model('Vaccine Distribution')
X = { (i,j,t): m.addVar() for i in I for j in J for t in T }
Y = { (j,k,t): m.addVar() for j in J for k in K for t in T }
m.setObjective((0.20 * quicksum(quicksum(quicksum(X[i,j,t] * IDtoLVC[i][j] for i in I for j in J for t in T)))) +
(quicksum(quicksum(quicksum(Y[j,k,t] * CCDtoLVC[k][j] for j in J for k in K for t in T)))) +
(quicksum(quicksum(quicksum(X[i,j,t] * LVCCost[i] for i in I for j in J for t in T)))),
GRB.MINIMIZE)
m.optimize()
You don't need three nested calls to quicksum in order to express a triple sum. Instead, you just call quicksum once:
sum1 = quicksum(X[i,j,t] * IDtoLVC[i][j] for i in I for j in J for t in T)
sum2 = quicksum(Y[j,k,t] * CCDtoLVC[k][j] for j in J for k in K for t in T)
sum3 = quicksum(X[i,j,t] * LVCCost[i] for i in I for j in J for t in T)
m.setObjective(0.20 * sum1 + sum2 + sum3, GRB.MINIMIZE)
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
Overall question: How do I know what I am getting from a Queue object when I call Queue.get()? How do I sort it, or identify it? Can you get specific items from the Queue and leave others?
Context:
I wanted to learn a little about multi-proccessing (threading?) to make solving a matrix equation more efficient.
To illustrate, below is my working code for solving the matrix equation Ax = b without taking advantage of multiple cores. The solution is [1,1,1].
def jacobi(A, b, x_k):
N = len(x_k)
x_kp1 = np.copy(x_k)
E_rel = 1
iteration = 0
if (N != A.shape[0] or N != A.shape[1]):
raise ValueError('Matrix/vector dimensions do not match.')
while E_rel > ((10**(-14)) * (N**(1/2))):
for i in range(N):
sum = 0
for j in range(N):
if j != i:
sum = sum + A[i,j] * x_k[j]
x_kp1[i] =(1 / A[i,i]) * (b[i] - sum)
E_rel = 0
for n in range(N):
E_rel = E_rel + abs(x_kp1[n] - x_k[n]) / ((abs(x_kp1[n]) + abs(x_k[n])) / 2)
iteration += 1
# print("relative error for this iteration:", E_rel)
if iteration < 11:
print("iteration ", iteration, ":", x_kp1)
x_k = np.copy(x_kp1)
return x_kp1
if __name__ == '__main__':
A = np.matrix([[12.,7,3],[1,5,1],[2,7,-11]])
b = np.array([22.,7,-2])
x = np.array([1.,2,1])
print("Jacobi Method:")
x_1 = jacobi(A, b, x)
Ok, so I wanted to convert this code following this nice example: https://p16.praetorian.com/blog/multi-core-and-distributed-programming-in-python
So I got some code that runs and converges to the correct solution in the same number of iterations! That's really great, but what is the guarantee that this happens? It seems like Queue.get() just grabs whatever result from whatever process finished first (or last?). I was actually very surprised when my code ran, as I expected
for i in range(N):
x_update[i] = q.get(True)
to jumble up the elements of the vector.
Here is my code updated using the multi-processing library:
import numpy as np
import multiprocessing as mu
np.set_printoptions(precision=15)
def Jacobi_step(index, initial_vector, q):
N = len(initial_vector)
sum = 0
for j in range(N):
if j != i:
sum = sum + A[i, j] * initial_vector[j]
# this result is the updated element at given index of our solution vector.
q.put((1 / A[index, index]) * (b[index] - sum))
if __name__ == '__main__':
A = np.matrix([[12.,7,3],[1,5,1],[2,7,-11]])
b = np.array([22.,7,-2])
x = np.array([1.,2,1])
q = mu.Queue()
N = len(x)
x_update = np.copy(x)
p = []
error = 1
iteration = 0
while error > ((10**(-14)) * (N**(1/2))):
# assign a process to each element in the vector x,
# update one element with a single Jacobi step
for i in range(N):
process = mu.Process(target=Jacobi_step(i, x, q))
p.append(process)
process.start()
# fill in the updated vector with each new element aquired by the last step
for i in range(N):
x_update[i] = q.get(True)
# check for convergence
error = 0
for n in range(N):
error = error + abs(x_update[n] - x[n]) / ((abs(x_update[n]) + abs(x[n])) / 2)
p[i].join()
x = np.copy(x_update)
iteration += 1
print("iteration ", iteration, ":", x)
del p[:]
A Queue is first-in-first-out which means the first element inserted is the first element retrieved, in order of insertion.
Since you have no way to control that, I suggest you insert tuples in the Queue, containing the value and some identifying object that can be used to sort/relate to the original computation.
result = (1 / A[index, index]) * (b[index] - sum)
q.put((index, result))
This example puts the index in the Queue together with the result, so that when you .get() later you get the index too and use it to know which computation this is for:
i, x_i = q.get(True)
x_update[i] = x_i
Or something like that.
I'm new to Python, and I'm trying to get familiar with it by solving problems on CodeChef. I'm attempting to solve the Easy problem Number Game. The issue is that the execution time is too long for my code.
I have translated the Python solution I wrote into C++, and the submission was accepted, so I know I have a correct answer, and it's just off by a constant multiple.
Is it possible to solve this problem in Python 3 in the allotted time? Can you help me speed up my code to accomplish this?
import time
def getStartValues(A, M):
startVals = [0]*M
b = [0]*len(A)
for i in range(len(A)-1):
b[i+1] = (10*b[i] + A[i]) % M
f = 0
power = 1
for i in range(len(A)-1,0,-1):
startVals[(b[i]*power + f) % M] += 1
f = (A[i]*power + f) % M
power = (power*10 % M)
startVals[f] += 1
return startVals, power
def checkValues(i, startVals, M, powNm1, checked, chklst):
if checked[i] == 1:
return startVals[i]
q = [i]
chk = [0]*M
chk[i] = 1
while len(q) > 0:
val = q.pop(0)
for j in chklst:
val2 = (powNm1*val + j) % M
if checked[val2] > 0:
checked[i] = 1
return startVals[i]
elif chk[val2] == 0:
q.append(val2)
chk[val2] = 1
return 0
def compute(A, M):
startVals, power = getStartValues(A, M)
checked = [0]*M
checked[0] = 1
chklst = [j for j in range(M) if startVals[j] > 0]
total = 0
for i in chklst:
c = checkValues(i, startVals, M, power, checked, chklst)
total += c
return total
start = time.time()
file = open('numbgame.in', 'r')
#T = int(input())
T = int(file.readline())
for i in range(T):
#A, M = input().split()
A, M = file.readline().split()
A = list(map(int,A))
M = int(M)
print(compute(A, M))
tDiff = time.time() - start
print('Total time: %s' % tDiff)
Note that I have modified the code to read from a file and to display execution time, as a convenience, and some small alterations are needed before it can be submitted.
getStartValues takes in the (big) list of digits of the input A and the (small) integer M and returns the values modulo M that can be generated from A by removing a single digit.
checkValues takes an index i, the list startValues, the integer M, the integer powNm1 (which is the value 10^(n-1) mod M, where n is the number of digits in A, a list checked that keeps track of whether a value has already been determined to be solvable, and the list chklst (which contains the indices i such that startValues[i] > 0).
The majority of the time is spent in the function getStartValues, since A could be up to 10^6 digits long. On my desktop, the getStartValues function call takes about 1.2s, while the rest of the compute function takes about 0.04s (for worst case inputs).