I am using OR-Tools to solve a MIP with SCIP. OR-Tools returns optimal values for continuous and integer (binary) variables of my problem.
When I then fix the binary variables of this MIP to the optimal values returned by OR-Tools (for the MIP) and I solve the corresponding LP with GLOP, OR-Tools returns new values for the optimal values of the continuous variables.
My understanding is that the initial problem does not have a unique solution (in terms of optimal values of variables).
So my question is: How can I make OR-tools return every optimal solution, and not just one?
Please find the code bellow:
from ortools.linear_solver import pywraplp
#Fixed parameters
K = 4
L = 3
J = {}
J[0,0] = 3
J[0,1] = 2
J[0,2] = 1
J[1,0] = 3
J[1,1] = 1
J[1,2] = 2
J[2,0] = 2
J[2,1] = 2
J[2,2] = 2
J[3,0] = 1
J[3,1] = 1
J[3,2] = 1
S_up = {}
S_lw = {}
U = {}
S_up[0,0,0] = 20
S_up[0,1,0] = 40
S_up[0,2,0] = 60
S_up[0,0,1] = 15
S_up[0,1,1] = 40
S_up[0,0,2] = 50
S_lw[0,0,0] = 0
S_lw[0,1,0] = 21
S_lw[0,2,0] = 41
S_lw[0,0,1] = 5
S_lw[0,1,1] = 16
S_lw[0,0,2] = 10
U[0,0,0] = 5
U[0,1,0] = 7
U[0,2,0] = 8
U[0,0,1] = 2
U[0,1,1] = 5
U[0,0,2] = 6
S_up[1,0,0] = 25
S_up[1,1,0] = 35
S_up[1,2,0] = 50
S_up[1,0,1] = 30
S_up[1,0,2] = 30
S_up[1,1,2] = 30
S_lw[1,0,0] = 5
S_lw[1,1,0] = 26
S_lw[1,2,0] = 36
S_lw[1,0,1] = 10
S_lw[1,0,2] = 5
S_lw[1,1,2] = 31
U[1,0,0] = 6
U[1,1,0] = 8
U[1,2,0] = 9
U[1,0,1] = 3
U[1,0,2] = 5
U[1,1,2] = 7
S_up[2,0,0] = 40
S_up[2,1,0] = 60
S_up[2,0,1] = 60
S_up[2,1,1] = 80
S_up[2,0,2] = 40
S_up[2,1,2] = 60
S_lw[2,0,0] = 5
S_lw[2,1,0] = 41
S_lw[2,0,1] = 5
S_lw[2,1,1] = 61
S_lw[2,0,2] = 5
S_lw[2,1,2] = 41
U[2,0,0] = 5
U[2,1,0] = 6
U[2,0,1] = 4
U[2,1,1] = 5
U[2,0,2] = 5
U[2,1,2] = 6
S_up[3,0,0] = 100
S_up[3,0,1] = 90
S_up[3,0,2] = 90
S_lw[3,0,0] = 0
S_lw[3,0,1] = 0
S_lw[3,0,2] = 0
U[3,0,0] = 5
U[3,0,1] = 4
U[3,0,2] = 5
D = [100,100,90]
P = [50,30,20]
Q_up = [0,1,1,1]
Q_lw = [0,0,0.1,0]
#Declare MIP solver
solver_mip = pywraplp.Solver.CreateSolver('SCIP')
#Define variables
infinity = solver_mip.infinity()
y = {}
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
y[k, j, l] = solver_mip.NumVar(0, infinity, '')
x = {}
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
x[k, j, l] = solver_mip.IntVar(0, 1, '')
print('Number of variables =', solver_mip.NumVariables())
#Define constraints
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
solver_mip.Add(y[k, j, l] <= x[k, j, l]*S_up[k, j, l])
solver_mip.Add(x[k, j, l]*S_lw[k, j, l] <= y[k, j, l])
for k in range(K):
for l in range(L):
solver_mip.Add(sum([x[k, j, l] for j in range(J[k,l])]) <= 1)
for l in range(L):
solver_mip.Add(sum([sum([y[k, j, l] for j in range(J[k,l])]) for k in range(K)]) == D[l])
for k in range(K):
solver_mip.Add(sum([sum([y[k, j, l]*P[l] for j in range(J[k,l])]) for l in range(L)]) <= Q_up[k]*sum([D[l]*P[l] for l in range(L)]))
solver_mip.Add(Q_lw[k]*sum([D[l]*P[l] for l in range(L)]) <= sum([sum([y[k, j, l]*P[l] for j in range(J[k,l])]) for l in range(L)]))
print('Number of constraints =', solver_mip.NumConstraints())
#Define objective
solver_mip.Minimize(sum([sum([sum([y[k,j,l]*U[k,j,l] for j in range(J[k,l])]) for k in range(K)]) for l in range(L)]))
#Call MIP solver
status = solver_mip.Solve()
#Display solution
if status == pywraplp.Solver.OPTIMAL:
print('Solution of MIP:')
print('Objective value =', solver_mip.Objective().Value())
x_opt = {} #store optimal values of binary variable
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
x_opt[k,j,l] = x[k,j,l].solution_value()
if x[k,j,l].solution_value() == 1:
print('y[',k,',',j,',',l,']=',y[k,j,l].solution_value())
else:
print('The problem does not have an optimal solution.')
print('\nAdvanced usage:')
print('Problem solved in %f milliseconds' % solver_mip.wall_time())
print('Problem solved in %d iterations' % solver_mip.iterations())
print('Problem solved in %d branch-and-bound nodes' % solver_mip.nodes())
#Primal problem with fixed binary variables to optimal value becomes a LP
#Declare LP solver
solver_lp = pywraplp.Solver.CreateSolver('GLOP')
##Quantity variable
y_fixed_binary = {}
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
y_fixed_binary[k, j, l] = solver_lp.NumVar(0, infinity, '')
#Define constraints
##Quantity should be in bounds defined by reinsurer
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
solver_lp.Add(y_fixed_binary[k, j, l] <= x_opt[k, j, l]*S_up[k, j, l])
solver_lp.Add(x_opt[k, j, l]*S_lw[k, j, l] <= y_fixed_binary[k, j, l])
for l in range(L):
solver_lp.Add(sum([sum([y_fixed_binary[k, j, l] for j in range(J[k,l])]) for k in range(K)]) == D[l])
for k in range(K):
solver_lp.Add(sum([sum([y_fixed_binary[k, j, l]*P[l] for j in range(J[k,l])]) for l in range(L)]) <= Q_up[k]*sum([D[l]*P[l] for l in range(L)]))
solver_lp.Add(Q_lw[k]*sum([D[l]*P[l] for l in range(L)]) <= sum([sum([y_fixed_binary[k ,j ,l]*P[l] for j in range(J[k,l])]) for l in range(L)]))
#Define objective
solver_lp.Minimize(sum([sum([sum([y_fixed_binary[k,j,l]*U[k,j,l] for j in range(J[k,l])]) for k in range(K)]) for l in range(L)]))
status = solver_lp.Solve()
if status == pywraplp.Solver.OPTIMAL:
print('Solution of LP:')
print('Objective value =', solver_mip.Objective().Value())
for k in range(K):
for l in range(L):
for j in range(J[k,l]):
if x_opt[k,j,l] == 1:
print('y[',k,',',j,',',l,']=',y_fixed_binary[k,j,l].solution_value())
else:
print('The LP does not have an optimal solution.')
print('Advanced usage:')
print('Problem solved in %f milliseconds' % solver_lp.wall_time())
And the output is
Solution of MIP:
Objective value = 1280.0
y[ 1 , 0 , 1 ]= 30.0
y[ 2 , 0 , 0 ]= 13.999999999999998
y[ 2 , 0 , 1 ]= 5.0
y[ 2 , 0 , 2 ]= 5.0
y[ 3 , 0 , 0 ]= 86.0
y[ 3 , 0 , 1 ]= 55.0
y[ 3 , 0 , 2 ]= 85.0
Solution of LP:
Objective value = 1280.0
y[ 1 , 0 , 1 ]= 30.0
y[ 2 , 0 , 0 ]= 40.0
y[ 2 , 0 , 1 ]= 60.0
y[ 2 , 0 , 2 ]= 40.0
y[ 3 , 0 , 0 ]= 60.0
y[ 3 , 0 , 1 ]= 0.0
y[ 3 , 0 , 2 ]= 50.0
You can get all optimal solutions by calling NextSolution() after the first Solve()
I have in java:
public static void main(String[] args) {
int x = 10;
for(int i = 0; i <= x; i++ ){
System.out.println("i = " + i + "******");
for(int j = 0; j <= i; j++){
System.out.print("j = " + j + " ");
}
}
with output:
run:
i = 0******
j = 0 i = 1******
j = 0 j = 1 i = 2******
j = 0 j = 1 j = 2 i = 3******
j = 0 j = 1 j = 2 j = 3 i = 4******
j = 0 j = 1 j = 2 j = 3 j = 4 i = 5******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 i = 6******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 i = 7******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 i = 8******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 i = 9******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 j = 9 i = 10******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 j = 9 j = 10
I'd like to achieve exactly effect in python for loop:
x = 10
for i in range(0, x, 1):
print("i = ", i, "*******")
for j in range(0, i, 1):
print("j = ", j, end="")
Output:
i = 0 *******
i = 1 *******
j = 0i = 2 *******
j = 0j = 1i = 3 *******
j = 0j = 1j = 2i = 4 *******
j = 0j = 1j = 2j = 3i = 5 *******
j = 0j = 1j = 2j = 3j = 4i = 6 *******
j = 0j = 1j = 2j = 3j = 4j = 5i = 7 *******
j = 0j = 1j = 2j = 3j = 4j = 5j = 6i = 8 *******
j = 0j = 1j = 2j = 3j = 4j = 5j = 6j = 7i = 9 *******
j = 0j = 1j = 2j = 3j = 4j = 5j = 6j = 7j = 8
I started learning python, I know java at intermediate level and cant start thinking in those pyhon loops. Python 3.6
The upper bound of range(..) is exclusive, so you simply need to add one to the upper bound:
x = 10
for i in range(0, x+1):
print("i = ",i,"*******",sep='')
for j in range(0, i+1):
print("j = ",j, sep='', end=' ')
If the step is 1, you do not have to mention this. By default Python uses 1 as step.
Furthermore by default Python will separate two arguments with a space, you can use the sep parameter to split it with no space (or another character sequence).
This prints:
i = 0*******
j = 0 i = 1*******
j = 0 j = 1 i = 2*******
j = 0 j = 1 j = 2 i = 3*******
j = 0 j = 1 j = 2 j = 3 i = 4*******
j = 0 j = 1 j = 2 j = 3 j = 4 i = 5*******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 i = 6*******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 i = 7*******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 i = 8*******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 i = 9*******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 j = 9 i = 10*******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 j = 9 j = 10
You want to use end=" " rather than end="" to have a space between a value of j and the string j = from next iteration.
Besides, the result of range does not include the upper limit, you have to add 1 to compensate for it.
And finally, instead of:
print("i = ", i, "*******")
use
print("i = {}*******".format(i))
to exactly reproduce your Java output.
Simple solution of your problem.
x=10
for i in range(0,x+1):
print "i = "+str(i)+"******"
for j in range(0,i+1):
print "j = "+str(j)+" ",
output:-
i = 0******
j = 0 i = 1******
j = 0 j = 1 i = 2******
j = 0 j = 1 j = 2 i = 3******
j = 0 j = 1 j = 2 j = 3 i = 4******
j = 0 j = 1 j = 2 j = 3 j = 4 i = 5******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 i = 6******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 i = 7******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 i = 8******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 i = 9******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 j = 9 i = 10******
j = 0 j = 1 j = 2 j = 3 j = 4 j = 5 j = 6 j = 7 j = 8 j = 9 j = 10