PuLP programming output - python

I am working with a collaborator on a certain optimization project involving linear programming. We both use Coin-OR branch-and-cut solver to solve the problem. I construct the .LP file using Python-based PuLP package. I am not entirely sure how the collaborator creates their .LP file (definitely not using Python), but essentially, we have two different systems generating .LP files for the exact same problem - i.e. the objective function, variables, constraints are exactly the same.
I typically solve my problem within Python (myProblm.solve()), but I have also been generating a .LP file and calling a CBC solver from the command line to solve this file (problem). Next, I compare the output I get from my system (either Python or command-line), to that my collaborator obtains. [Please note that the output of the problem on my side is exactly the same whether solved in PuLP or on command-line.]
The values of the objective function match well between us, but the other details do not exactly match. For example, if we were to solve this Whiskas blending problem, the total cost of ingredients would be exactly same, but the ratios of ingredients differ. Any idea why that would be?
I manually compared our .LP files and noticed a few differences. For starters, the sequence of constraints and variables is different. In other words, if there are 5 constraints, my file lists them as C1,C2,C5,C4,C3, whereas the same constraints will be listed as C1,C2,C3,C4,C5. Also, my Python code rounds all numbers to 10's place, while his system rounds them to 1's place. Hence, the coefficients of some of the variables have slightly different values.
Do these differences play a role in the exact output of the solver?
Also, the next question by extension is: What should we do to get the exact same output when solving a linear programming optimization problem? Which factors influence the solution of LP problems? Do factors like the structure of an .LP file play a role? Will I get the exact same output if I run the same LP file with exact same conditions on different computers?

Because there are multiple solutions to an LP problem with the same optimal objective function, different solvers cant guarantee that they will return the same solution. This issue becomes even more complicated when MIP problems use branch and bound. Using Multi threading or multiprocessing makes it almost impossible.
In summary to get the same solution either generate the exact same LP files and solve with the same solvers. Or change you objective function so that there is only one optimal solution (perhaps prefer some ordering of ingredients, with a small change of the costs for the ingredients).

Related

Can I include continuous variable when optimising with CPMpy?

I need to run a model, where I optimise a diet within a set of constraints and call all integer solutions in the end. I have found a diet example matching almost what I need here: hakank.org. However, in my case, my variables take continuous values, so in the examples this would be all the nutritional values and the cost, while only x take integer. However, it seems like I can only define either 'intvar' or 'boolvar' when defining by variables with this model. Is there a way to overcome this? Other would there be other more suitable models with examples that I can read online?
I'm new to constraint programming, so any help would be appreaciated!
Thanks.
Most Constraint Programming tools and solvers only work with integers. That is where their strength is. If you have a mixture of continuous and discrete variables, it is a good idea to have a look at Mixed Integer Programming. MIP tools and solvers are widely available.
The diet model is a classic example of an LP (Linear Programming) Model. When adding integer restrictions, you end up with a MIP model.
To answer your question: CPMpy does not support float variables (and I'm not sure that it's in the pipeline for future extensions).
Another take - than using MIP solvers as Erwin suggest - would be to write a MiniZinc (https://www.minizinc.org/) model of the problem and use some of its solvers. See my MiniZinc version of the diet problem: http://hakank.org/minizinc/diet1.mzn. And see the MiniZinc version of Stigler's Diet problem though it's float vars only: http://hakank.org/minizinc/stigler.mzn.
There are some MiniZinc CP solvers that also supports float variables, e.g. Gecode, JaCoP, and OptimathSAT. However, depending on the exact constraints - such as the relation with the float vars and the integer vars - they might struggle to find solutions fast. In contrast to some MIP solvers, generating all solutions is one of the general features of CP solvers.
Perhaps all these diverse suggestions more confuse than help you. Sorry about that. It might help if you give some more details about your problem.

Getting top 10 sub-optimal solutions computed by GLPK solver for LP in python

I am trying to use GLPK for solving an LP problem. My problem is the routing problem in a computer network. Given network topology and each link capacity and the traffic demand matrix for each source-destination pair in the network, I want to minimize maximum link utilization in the network. This is an LP problem and I know how to use GLPK to get the optimum solution.
My problem is that I want to get the sub-optimal solutions also. Is there any way that I can get say top 10 suboptimal solutions by GLPK?
Best
For a pure LP (with only continuous variables), the concept of finding "next best" solutions is very difficult (just move an epsilon away, and you have another solution). We can define this differently: find "next best" corner points (a.k.a. bases). This is not so easy to do, but there is a somewhat complex way by encoding bases using binary variables (link).
If the problem is actually a MIP (with binary variables) it is easier to find "next best" solutions. Some advanced solvers have built-in facilities for this (called: solution pool). Note: glpk does not have this option. Alternatively, we can also do this by adding a cut that forbids the best-found solution and then resolve (link). In this case we exploited some structure. A general cut for 0-1 variables is derived here. This can also be done for general integer variables, but then things get a bit messy.

Basic variables in a linear program

I have a small size linear program with restrictions Ax<=b and x>=0. To solve it I've been using the Python library scipy.optimize.linprog.
From my n variables, I need to know which ones form the basis.
I searched a lot and couldn't find a way for this. I also tried the Pulp library without success.
I'm interested in degenerate instances, so looking for positive variables is not enough; it is likely that some zero variable is basic.
Do you know a way to get this information? I can use any library, but it has to be on Python.
Thanks!
There is almost no LP solver that does not return arrays/vectors containing the basis status of each variable and each row (or slack). Unfortunately scipy.optimize.linprog is the exception. I am sure if you look at the source you can locate basis status arrays. Pulp is not a solver but a modeling tool. I am not sure what solution info Pulp provides. But you can always generate an MPS file with PULP and feed that in any LP solver.
If the solution is non-degenerate you can do something like
x(j)>0 => basic
x(j)=0 => non-basic
s(i)>0 => slack is basic
s(i)=0 => slack is non-basic
However if the solution is degenerate we have some basic variables/slacks with value zero.

Solving integer programs in Python with PuLP

I am working on a Python package for computing several NP-Hard graph invariants. The current version of the package uses brute force for nearly all of the algorithms, but I am very interested in using integer programming to help speed up the computations for larger graphs.
For example, a simple integer program for solving the independence number of an n-vertex graph is to maximize given the constraints , where .
How do I solve this using PuLP? Is PuLP my best option, or would it be beneficial to use solvers in another language, like Julia, and interface may package with those?
I don't propose to write your full implementation for you, but to address the final question about PuLP versus other languages.
PuLP provides a Python wrapper over a range of existing LP Solvers.
Once you have specified your problem with a Python syntax, it converts it to another language internally (e.g. you can save .lp files, and inspect them) and passes that to any one of a number of third-party solvers, that generally aren't written in Python.
So there is no need to learn another language to get a better solver.

solving ODEs on networks with PyDSTool

After using scipy.integrate for a while I am at the point where I need more functions like bifurcation analysis or parameter estimation. This is why im interested in using the PyDSTool, but from the documentation I can't figure out how to work with ModelSpec and if this is actually what will lead me to the solution.
Here is a toy example of what I am trying to do: I have a network with two nodes, both having the same (SIR) dynamic, described by two ODEs, but different initial conditions. The equations are coupled between nodes via the Epsilon (see formula below).
formulas as a picture for better read, the 'n' and 'm' are indices, not exponents ~>
http://image.noelshack.com/fichiers/2014/28/1404918182-odes.png
(could not use the upload on stack, sadly)
In the two node case my code (using PyDSTool) looks like this:
#multiple SIR metapopulations
#parameter and initial condition definition; a dict is a must
import PyDSTool as pdt
params={'alpha': 0.7, 'beta':0.1, 'epsilon1':0.5,'epsilon2':0.5}
ini={'s1':0.99,'s2':1,'i1':0.01,'i2':0.00}
DSargs=pdt.args(name='SIRtest_multi',
ics=ini,
pars=params,
tdata=[0,20],
#the for-macro generates formulas for s1,s2 and i1,i2;
#sum works similar but sums over the expressions in it
varspecs={'s[o]':'for(o,1,2,-alpha*s[o]*sum(k,1,2,epsilon[k]*i[k]))',
'i[l]':'for(l,1,2,alpha*s[l]*sum(m,1,2,epsilon[m]*i[m]))'})
#generator
DS = pdt.Generator.Vode_ODEsystem(DSargs)
#computation, a trajectory object is generated
trj=DS.compute('test')
#extraction of the points for plotting
pts=trj.sample()
#plotting; pylab is imported along with PyDSTool as plt
pdt.plt.plot(pts['t'],pts['s1'],label='s1')
pdt.plt.plot(pts['t'],pts['i1'],label='i1')
pdt.plt.plot(pts['t'],pts['s2'],label='s2')
pdt.plt.plot(pts['t'],pts['i2'],label='i2')
pdt.plt.legend()
pdt.plt.xlabel('t')
pdt.plt.show()
But in my original problem, there are more than 1000 nodes and 5 ODEs for each, every node is coupled to a different number of other nodes and the epsilon values are not equal for all the nodes. So tinkering with this syntax did not led me anywhere near the solution yet.
What I am actually thinking of is a way to construct separate sub-models/solver(?) for every node, having its own parameters (epsilons, since they are different for every node). Then link them to each other. And this is the point where I do not know wether it is possible in PyDSTool and if it is the way to handle this kind of problems.
I looked through the examples and the Docs of PyDSTool but could not figure out how to do it, so help is very appreciated! If the way I'm trying to do things is unorthodox or plain stupid, you are welcome to make suggestions how to do it more efficiently. (Which is actually more efficient/fast/better way to solve problems like this: subdivide it into many small (still not decoupled) models/solvers or one containing all the ODEs at once?)
(Im neither a mathematician nor a programmer, but willing to learn, so please be patient!)
The solution is definitely not to build separate simulation models. That won't work because so many variables will be continuously coupled between the sub-models. You absolutely must have all the ODEs in one place together.
It sounds like the solution you need is to use the ModelSpec object constructs. These let you hierarchically build the sub-model definitions out of symbolic pieces. They can have their own "epsilon" parameters, etc. You declare all the pieces when you're finished and let PyDSTool make the final strings containing the ODE definitions for you. I suggest you look at the tutorial example at:
http://www.ni.gsu.edu/~rclewley/PyDSTool/Tutorial/Tutorial_compneuro.html
and the provided examples: ModelSpec_test.py, MultiCompartments.py. But, remember that you still have to have a source for the parameters and coupling data (i.e., a big matrix or dictionary loaded from a file) to be able to automate the process of building the model, otherwise you'd still be writing it all out by hand.
You have to build some classes for the components that you want to have. You might also create a factory function (compare 'makeSoma' in the neuralcomp.py toolbox) that will take all your sub-components and create an ODE based on summing something up from each of the declared components. At the end, you can refer to the parameters by their position in the hierarchy. One might be 's1.epsilon' while another might be 'i4.epsilon'.
Unfortunately, to build models like this efficiently you will have to learn to do some more complex programming! So start by understanding all the steps in the tutorial. You can email me directly through the SourceForge support discussions or email once you've got started and have specific questions.

Categories

Resources