Advanced Heuristics for MIP vehicle routing problem in PuLP - python

I am currently trying to speed up an MIP. An approach I was considering was to implement a cut callback heuristic with PuLP (one which rounds relaxed integer variables greater than .9 to 1). Unfortunately, I do not believe PuLP has such a function to call, and I have looked into the mip module as well as dippy, but I don't feel like jumping to those. So, as a side note, if anyone knows how this can be done natively with PuLP let me know...
This leads me to my main question. Since PuLP is a wrapper and can be used with other solvers, I did see that Gurobi has such a function, and was able to call the code to Gurobi from PuLP with the code below:
Lp_prob = plp.LpProblem('Problem', plp.LpMinimize)
sd = plp.solvers.GUROBI(mip=True)
sd.actualSolve(Lp_prob, callback=mycallback)
Here is the function I am trying to call:
def mycallback(model, where):
model._vars = model.getVars()
if where == GRB.Callback.MIPNODE:
for x in model._vars:
if model.cbGetNodeRel(x) > 0.9 and model.cbGetNodeRel(x) < 1.0:
model.cbSetSolution(x, 1.0)
else:
return
However, after running a couple of times, the heuristic doesn't quite speed things up, in fact it kind of slows it down. I was wondering if this was implemented correctly, or if I were missing something. Any help or suggestions would be greatly appreciated.

Related

CPLEX12.9: Strong branching is not available for mixed-integer problems?

I want to get strong branching scores by cplex and python, and for the first step I just tried to use "cplex.advanced.strong_branching" to solve a very simple MILP problem (my code followed the example usage of this function exactly). However it told me that "CPLEX Error 1017: Not available for mixed-integer problems", which made me quite confused because SB should be a traditional branch-and-bound algorithm. But when I used it to solve a LP problem it worked well.
The error seemed to be raised from "CPXXstrongbranch", a base C/C++ API, which also made me question that how cplex could make SB decisions when I set the branching strategy parameter to SB. A similar question is that I know Python API doesn't have the important "CPXgetcallbacknodelp" function, so how could "cplex.advanced.strong_branching" work? Could it be the reason of this error?
I don't totally understand how "CPXstrongbranch" works in C, so the following information may be incorrect: I tried to use "CPXstrongbranch" in the user-set branch callback of the example "adlpex1.c", and the same error was raised; it stopped me to use "ctypes" to get the "CPXgetcallbacknodelp" function.
Could it be a version problem? Does Cplex block the access of SB? Because I have read a paper which relied on the SB scores in Cplex 12.6.1 and C API. Or I just made some mistakes.
My question is whether Cplex can do SB and deliver its results to users in the MILP problem.
cplex.advanced.strong_branching does not carry out any branching. The doc is a bit confusing here. What this function does is computing the strong branching scores for the variables you pass (or all variables if you don't pass a list).
This requires an LP because usually in a MIP search tree you call this function with the current LP relaxation.
If you want to use CPLEX with strong branching then set the variable selection parameter to "strong branching":
with cplex.Cplex() as cpx:
cpx.parameters.mip.strategy.variableselect.set(cpx.parameters.mip.strategy.variableselect.values.strong_branching)
cpx.solve()
The strong_branching function is only needed if you want to implement your own branching algorithm.

Gurobi specifies a problem as infeasible although it is not

I have tried to solve several similar optimization problems using Gurobi and Pyomo. The problems differ just by a few parameters. Each problem is run three times, each time with the same constraints but a different objective function.
There was one problem for which Gurobi could solve for only two of the objective functions I had specified. For the third objective function, it couldn't solve the problem, specifying the problem as 'infeasible'. But this didn't make sense to me as the feasible domain was exactly the same as when the other two objective functions were used to solve the problem.
I turned my computer off and on, and tried to solve the problem again on both PyCharm and Spyder. Gurobi was still telling me the problem was infeasible. However, I was sure the problem was perfectly feasible based on my observations of the other similar problems. So I tried to solve the exact same problem on another computer. This time it worked!...
I thus have partially solved my problem. I have the results I need but since I don't understand what's going on with Gurobi on my computer, I may be facing the same kind of problem in the future.
Does anyone have any idea about this "bug"?
You should verify that you Gurobi is reporting a status "infeasible" and not "infeasible or unbounded". You can check the return status or the log or turn off the presolve Dual Reductions. If you have large coefficients, you can see the previous question about integer programming and leaky abstractions. You can check one measure of the numerical difficulty of your problem with the attribute KappaExact. As #LarrySnyter610 suggested in the comments, Gurobi might also be running out of time.
If the objective is really the only thing that changes, you can likely resolve all these difficulties and get a performance boost by solving the problems consecutively. That way, Gurobi can use the solution from the previous objective as a warm start.
Suppose you have 2 objectives, obj1, obj2 for the same set of objectives. You can solve them consecutively by
m.setObjective(obj1)
m.optimize()
if m.SolCount > 0:
solution1 = m.getAttr('X', m.getVars())
m.setObjective(obj2)
if m.SolCount > 0:
solution2 = m.getAttr('X', m.getVars())

Python cvxopt glpk ilp return first feasible solution

I am using cvxopt.glpk.ilp to solve a very complicated Mixed Integer Program. I was wondering if there is a way to get the program to terminate after finding the first solution? It takes too long and a feasible solution would work fine for my purposes.
If I understand you correctly, you are only interested in a feasible solution?
Then it should be sufficient to set the objective function to zero.
Here is a Wikipedia example for an integer linear program and the following Python code returns a feasible solution:
import cvxopt
import cvxopt.glpk
# original program maximizing the second variable
# c=cvxopt.matrix([0,-1],tc='d')
# modified program returning only a feasible solution
c=cvxopt.matrix([0,0],tc='d')
G=cvxopt.matrix([[-1,1],[3,2],[2,3],[-1,0],[0,-1]],tc='d')
h=cvxopt.matrix([1,12,12,0,0],tc='d')
(status, x)=cvxopt.glpk.ilp(c,G.T,h,I=set([0,1]))
print('status',status)
print('variables',x[0],x[1])
print('objective',sum(c.T*x))
If you're using PuLP (another python library like cvxopt) to invoke glpk to solve MIP, there is one parameter called maxtime. If you set maxtime=1 then what will solver do is, terminate search (almost) right after finding the first solution. I bet cvxopt should have some similar parameter for glpk since either PuLP or cvxopt is just a wrapper of those solvers.
Copy paste the description of maxtime parameter in Xpress which is another solver, but I think glpk should have something similar which you may need to find it out.
The maximum time in seconds that the Optimizer will run before it terminates, including the problem setup time and solution time. For MIP problems, this is the total time taken to solve all the nodes.
0 = No time limit.
n > 0 = If an integer solution has been found, stop MIP search after n seconds, otherwise continue until an integer solution is finally found.
n < 0 = Stop in LP or MIP search after -n seconds.

Modular Exponentiation in Python

I was trying to solve the ZSUM problem at SPOJ using Python 2.7.9 as my coding language and designed a program to do so. As the code runs perfectly but gives a TLE at the judge, I guess it is not fast enough. Is there is possible to optimize the below code to meet the judge requirement or it is impossible to beat the challenge using Python.
Link to the problem: http://www.spoj.com/problems/ZSUM/
def zsum(n,k):
a=2*pow(n-1,k,10000007)
b=pow(n,k,10000007)
c=2*pow(n-1,n-1,10000007)
d=pow(n,n,10000007)
zsum=(a+b+c+d)%10000007
print zsum
def main():
while True:
n,k=map(int,raw_input().split())
if n==k==0:
break
else:
zsum(n,k)
main()
Since there are zero accepted python solutions in a total of 2335 successful submissions, i think, no matter how much you optimise your solution, it is unlikely to manage to get accepted with python. Although python is a very useful language, it is not preferred in programming contests, as it is extremely slow (compared to C/C++ for instance). If you know how to code in C++ you should definitely give it a shot, although you must write you own modular exponentiation procedure.
I don't know if this will help (if you read the problem's comments you will see someone saying that it is impossible to solve in Python - that can happen on online judges with slower languages) but you can optimize the code:
def zsum(n,k):
a=2*pow(n-1,k,10000007) # (1)
b=pow(n,k,10000007) # (2)
c=2*pow(n-1,n-1,10000007) # (1)
d=pow(n,n,10000007) # (2)
zsum=(a+b+c+d)%10000007
print zsum
Note that in (1), you are computing pow(n - 1, min(k, n - 1)) twice. You could compute it once and then use modular exponentiation only for what is left. Same for (2).

Integrate stiff ODEs with Python

I'm looking for a good library that will integrate stiff ODEs in Python. The issue is, scipy's odeint gives me good solutions sometimes, but the slightest change in the initial conditions causes it to fall down and give up. The same problem is solved quite happily by MATLAB's stiff solvers (ode15s and ode23s), but I can't use it (even from Python, because none of the Python bindings for the MATLAB C API implement callbacks, and I need to pass a function to the ODE solver). I'm trying PyGSL, but it's horrendously complex. Any suggestions would be greatly appreciated.
EDIT: The specific problem I'm having with PyGSL is choosing the right step function. There are several of them, but no direct analogues to ode15s or ode23s (bdf formula and modified Rosenbrock if that makes sense). So what is a good step function to choose for a stiff system? I have to solve this system for a really long time to ensure that it reaches steady-state, and the GSL solvers either choose a miniscule time-step or one that's too large.
If you can solve your problem with Matlab's ode15s, you should be able to solve it with the vode solver of scipy. To simulate ode15s, I use the following settings:
ode15s = scipy.integrate.ode(f)
ode15s.set_integrator('vode', method='bdf', order=15, nsteps=3000)
ode15s.set_initial_value(u0, t0)
and then you can happily solve your problem with ode15s.integrate(t_final). It should work pretty well on a stiff problem.
(See also Link)
Python can call C. The industry standard is LSODE in ODEPACK. It is public-domain. You can download the C version. These solvers are extremely tricky, so it's best to use some well-tested code.
Added: Be sure you really have a stiff system, i.e. if the rates (eigenvalues) differ by more than 2 or 3 orders of magnitude. Also, if the system is stiff, but you are only looking for a steady-state solution, these solvers give you the option of solving some of the equations algebraically. Otherwise, a good Runge-Kutta solver like DVERK will be a good, and much simpler, solution.
Added here because it would not fit in a comment: This is from the DLSODE header doc:
C T :INOUT Value of the independent variable. On return it
C will be the current value of t (normally TOUT).
C
C TOUT :IN Next point where output is desired (.NE. T).
Also, yes Michaelis-Menten kinetics is nonlinear. The Aitken acceleration works with it, though. (If you want a short explanation, first consider the simple case of Y being a scalar. You run the system to get 3 Y(T) points. Fit an exponential curve through them (simple algebra). Then set Y to the asymptote and repeat. Now just generalize to Y being a vector. Assume the 3 points are in a plane - it's OK if they're not.) Besides, unless you have a forcing function (like a constant IV drip), the MM elimination will decay away and the system will approach linearity. Hope that helps.
PyDSTool wraps the Radau solver, which is an excellent implicit stiff integrator. This has more setup than odeint, but a lot less than PyGSL. The greatest benefit is that your RHS function is specified as a string (typically, although you can build a system using symbolic manipulations) and is converted into C, so there are no slow python callbacks and the whole thing will be very fast.
I am currently studying a bit of ODE and its solvers, so your question is very interesting to me...
From what I have heard and read, for stiff problems the right way to go is to choose an implicit method as a step function (correct me if I am wrong, I am still learning the misteries of ODE solvers). I cannot cite you where I read this, because I don't remember, but here is a thread from gsl-help where a similar question was asked.
So, in short, seems like the bsimp method is worth taking a shot, although it requires a jacobian function. If you cannot calculate the Jacobian, I will try with rk2imp, rk4imp, or any of the gear methods.

Categories