I am programming a vehicle routing problem in Python with PuLP. I got all my code in it, but for some reason I get a negative value for one of my decision variables, even though I restricted all of them to be nonnegative.
My code is as follows (Traveltimes is a two dimensional np array, with travel times between each pair of customers (i,j), where c(i,j) = c(j,i) and c(i,i) = 0.):
My code:
numVehicles = 2
numCustomers = 2
prob = LpProblem("DSP", LpMinimize)
var = [[[0 for k in range(numVehicles)] for j in range(numCustomers+1)] for i in range(numCustomers+1)]
for i in range(numCustomers+1):
for j in range(numCustomers+1):
for k in range(numVehicles):
var[i][j][k] = LpVariable("x"+str(i)+","+str(j)+","+str(k), 0,1, cat='Binary')
# ADD OBJECTIVE
obj = ""
for i in range(numCustomers+1):
for j in range(numCustomers+1):
for k in range(numVehicles):
obj += traveltimes[i][j]*var[i][j][k]
prob += obj
# ADD CONSTRAINTS
# All customers visited
for j in range(numCustomers+1):
for k in range(numVehicles):
nr = ""
for i in range(numCustomers+1):
nr += var[i][j][k]
prob += nr == 1
# Enter each customer exactly once
for i in range(numCustomers+1):
nr = ""
for k in range(numVehicles):
for j in range(1, numCustomers+1):
nr += var[i][j][k]
prob += nr == 1
# Leave each customer exactly once
for j in range(numCustomers+1):
nr = ""
for k in range(numVehicles):
for i in range(1, numCustomers+1):
nr += var[i][j][k]
prob += nr == 1
# Per vehicle only one customer can be visited as first
nrFirst = ""
for k in range(numVehicles):
for j in range(numCustomers+1):
nrFirst += var[0][j][k]
prob += nrFirst <= 1
# Max num vehicles
nrOut = ""
for k in range(numVehicles):
for j in range(numCustomers+1):
nrOut += var[0][j][k]
prob += nrOut <= numVehicles
# Restrict x(0,j,k) to be nonpositive
for j in range(numCustomers+1):
for k in range(numVehicles):
prob += var[0][j][k] >= 0
print(prob)
# Solve LP
prob.solve()
for v in prob.variables():
print(v.name, "=", v.varValue)
print("objective=", value(prob.objective))
The first output is the formulation printed
MINIMIZE
1.731*x0,1,0 + 1.731*x0,1,1 + 2.983*x0,2,0 + 2.983*x0,2,1 + 1.731*x1,0,0 + 1.731*x1,0,1 + 9.375*x1,2,0 + 9.375*x1,2,1 + 2.983*x2,0,0 + 2.983*x2,0,1 + 9.375*x2,1,0 + 9.375*x2,1,1 + 0.0
SUBJECT TO
_C1: x0,0,0 + x1,0,0 + x2,0,0 = 1
_C2: x0,0,1 + x1,0,1 + x2,0,1 = 1
_C3: x0,1,0 + x1,1,0 + x2,1,0 = 1
_C4: x0,1,1 + x1,1,1 + x2,1,1 = 1
_C5: x0,2,0 + x1,2,0 + x2,2,0 = 1
_C6: x0,2,1 + x1,2,1 + x2,2,1 = 1
_C7: x0,1,0 + x0,1,1 + x0,2,0 + x0,2,1 <= 1
_C8: x1,1,0 + x1,1,1 + x1,2,0 + x1,2,1 <= 1
_C9: x2,1,0 + x2,1,1 + x2,2,0 + x2,2,1 <= 1
_C10: x0,0,0 + x0,1,0 + x0,2,0 <= 1
_C11: x0,0,0 + x0,0,1 + x0,1,0 + x0,1,1 + x0,2,0 + x0,2,1 <= 1
VARIABLES
0 <= x0,0,0 <= 1 Integer
0 <= x0,0,1 <= 1 Integer
0 <= x0,1,0 <= 1 Integer
0 <= x0,1,1 <= 1 Integer
0 <= x0,2,0 <= 1 Integer
0 <= x0,2,1 <= 1 Integer
0 <= x1,0,0 <= 1 Integer
0 <= x1,0,1 <= 1 Integer
0 <= x1,1,0 <= 1 Integer
0 <= x1,1,1 <= 1 Integer
0 <= x1,2,0 <= 1 Integer
0 <= x1,2,1 <= 1 Integer
0 <= x2,0,0 <= 1 Integer
0 <= x2,0,1 <= 1 Integer
0 <= x2,1,0 <= 1 Integer
0 <= x2,1,1 <= 1 Integer
0 <= x2,2,0 <= 1 Integer
0 <= x2,2,1 <= 1 Integer
It can clearly be observed that all variables are restricted to be an integer between 0 and 1 (thus binary). However, for some reason, I do get negative values for some variable(s), as can be seen below
x0,0,0 = 0.0
x0,0,1 = -1.0
x0,1,0 = 0.0
x0,1,1 = 1.0
x0,2,0 = 0.0
x0,2,1 = 1.0
x1,0,0 = 1.0
x1,0,1 = 1.0
x1,1,0 = 1.0
x1,1,1 = 0.0
x1,2,0 = 0.0
x1,2,1 = 0.0
x2,0,0 = 0.0
x2,0,1 = 1.0
x2,1,0 = 0.0
x2,1,1 = 0.0
x2,2,0 = 1.0
x2,2,1 = 0.0
objective= 11.159
Really looking forward to any suggestions on how to solve this problem, since I clearly do not want negative values!
As a few others have suggested you should write a Minimum Complete and Verifiable Example.
That said, if you are getting constraints violated, and you are sure you've implemented them correctly, I reckon you have an infeasible problem (i.e. if you looked at your constraints carefully you would find there is a combination which makes solving impossible).
To check this add:
print (("Status:"), LpStatus[prob.status])
Just after you do prob.solve(). I reckon you'll find it's infeasible.
prob += nr == 1
"+=" is for assignment
"==" is checking for equivalence, and belongs in an "if" statement or a "while".
For instance:
if prob + nr == 1: #execute what follows if prob + nr is equal to 1
I am trying to get this code to calculate 5 and print numbers by 5's with a while statement of 7, so I want it to loop through, generating a different number 7 times; however, when it gets to a number over 10, I want it to start back over at 0 and ignore the 10.
This is my code:
while z < 7:
firstpickplusfive = int(firstpickplusfive) + 1
counts = counts + 1
if counts == 1:
if firstpickplusfive > 9:
firstpickplusfive = 0
if counts == 5:
print firstpickplusfive
z = int(z) + 1
The code prints the first number, but freezes on printing any others. Why isn't this working?
Your code is not in the loop. Python's code blocks are created with indents:
while z < 7:
firstpickplusfive = int(firstpickplusfive) + 1
counts = counts + 1
if counts == 1:
if firstpickplusfive > 9:
firstpickplusfive = 0
if counts == 5:
print firstpickplusfive
z = int(z) + 1
Is this the result you were trying to achieve:
import random
x = random.randint(1,9)
for i in range(1,8):
print x
x += 5
if x >= 10:
x -= 9
This generates a random number, and adds 5 until it passes 10, then subtracts 9, and it does this seven times. If I understand your question correctly, this is what you were trying to do. Please correct me if I am wrong.
no this is not what I was trying to do here is what I am trying to do.
counts = 0
r = 0
firstpickplusfive = 7
p = firstpickplusfive + 5
while r < 3:
firstpickplusfive = p + counts
if firstpickplusfive > 6:
firstpickplusfive = firstpickplusfive + counts - 10
if p > 9:
p = firstpickplusfive + counts
print firstpickplusfive
counts = counts + 1
r = int(r) + 1
it works alone, but when I add it to the script I am trying to write it doesn't work...if there is a simpler way to do it I would appreciate knowing it.
ie.
number = number + 5 + 0
then
number = number + 5 + 1.....ect which
example 7 + 5 + 0 = 12,
7 + 5 + 1 = 13.........
if the number is equal to 10 then I want it to drop the tens place and keep the 1's place
example 7 + 5 + 0 = 2,
7 + 5 + 1 = 3
Here is an easier method:
for i in range(1,4):
num = 7
num += 5
num +=(i-1)
if num >=10:
num -= 10
print num
i+=1
Try this in your script, does it work?
I need to make a quick algorithm(I already made a slow one) which will find the number of all possible values from two ranges of integer numbers (ranges can intersect or not) which sum will be the given number
I can represent it like an equation: z = x + y
where z is a known number and equals x plus y
z can be any number between 0 and 10^18
x belongs to a range of integer numbers [a..b], where 0 <= a <= b <= 10^18 and
the difference between the consecutive numbers is 1
y belongs to a range of integer numbers [c..d], where 0 <= c <= d <= 10^18 and
the difference between the consecutive numbers is 1
so I need to find the number(not their exact values) of all the possible variations of x and y from two sets of numbers which sum will be z
Example:
z = 5
first set: a = 1, b = 5(it means the set consists of 1,2,3,4,5)
second set: c = 1, b = 5
then the answer is 4, because all possible combinations are:
x = 4, y = 1
x = 3, y = 2
x = 2, y = 3
x = 1, y = 4
because theirs sums are 5's
The compulsory condition for an algrorithm is to work faster than 1 second
The following code works fine but only with numbers lesser than 1000000. It starts to work much slower with big numbers
with open(r"input.txt") as f:
n = int(f.readline()) # the given number
a = int(f.readline()) # the start position of the first set
b = int(f.readline()) # the end position of the first set
c = int(f.readline()) # the start position of the second set
d = int(f.readline()) # the end position of the second set
# print "n:",n,"a:",a,"b:",b,"c:",c,"d:",d
t = b - a + 1 # all posible variants of the first set
k = d - c + 1 # all posible variants of the second set
number_of_vars = 0
if t >= k:
while b >= a:
if (n - b <= d) \
and (n - b>= c):
number_of_vars += 1
b -= 1
else:
b -= 1
if t < k:
while d >= c:
if (n-d <= b) and (n-d >= a):
number_of_vars += 1
d -= 1
else:
d -= 1
print number_of_vars
No algorithm required -- just algebra:
It suffices to count the number of x in [a,b] for which z - x is in [c,d]
You need both a <= x <= b and c <= z - x <= d. The second inequality is equivalent to z - d <= x <= z - c hence you need
max(a, z - d) <= x <= min(b,z - c)
The number of such x is 0 if min(b,z - c) < max(a, z - d) otherwise it is
min(b,z - c) - max(a, z - d) + 1
In either case the number of solutions is
max(0, min(b,z - c) - max(a, z - d) + 1)
In your example a = c = 1 and b = d = z = 5 and
min(b, z - c) - max(a, z - d) + 1 = min(5,4) - max(1,0) + 1 = 4 - 1 + 1 = 4
One thing that you can use to reduce the checks in your algorithm is,
If the range for the 2 sets are overlapping, then you can cancel out some checks. Like in your example,
range for 1st set is 1 to 5
range for 2nd set is 1 to 5
So, if
x = 4, y = 1
is working, then
x = 1, y = 4
will also work. So you have to go only till half the number (i.e till 3 only in this case)
If only a part of the range is overlapping, then you can use the above method for that part, and the remaining part can be checked using normal method.