I'd like to be able to write a cplex solution file and read it back into CPLEX at a later time for further analysis. In Python, the documentation (and perhaps interface implementation) is a bit sketchy. The writing of the files seems to work fine, but when I go to read them and then attempt to access the c.solution object, it returns an error that no solution available.

c = cplex.Cplex() ... construct the model ... c.solve() # OK c.write('myfile.sol') # OK later... c.load('myfile.sol') # OK c.solution # returns 0 : None c.solution.get_objective_value() #Fails with CPLEX Error 1217: No solution exists.

I've also tried to load the .sav and .lp before loading the solution and this doesn't appear to help.

Am I doing something wrong?

asked 19 Sep '14, 15:27

johnclarke's gravatar image

johnclarke
2417
accept rate: 0%


Cplex.write()/.read() write/read problems to/from file, not: solutions (starts, resp.).

For the latter, you want to look in SolutionInterface/SolnPoolInterface (Cplex.solution.*, Cplex.solution.pool.*), InitialInterface/MIPStartsInterface (Cplex.start.*, Cplex.MIP_starts.*):

c = cplex.Cplex()

... construct the model ...

c.solve()
c.solution.write("my_sol.sol")
# or: c.solution.pool.write("my_sol.sol")

... later ...

c.start.read_start("my_sol.sol")
# or: c.MIP_starts.read("my_sol.sol")        
c.solve()
link

answered 20 Sep '14, 07:25

fbahr's gravatar image

fbahr ♦
4.6k716
accept rate: 13%

edited 20 Sep '14, 09:24

@fbahr, thank you -- this looks closer to what I need. I tried it, but it doesn't seem to take any less time. To clarify, after solving the problem an initial time, I launch a new instance using a different Python script, so I assume that the problem must be first loaded with c.read('myproblem.lp') and then c.read_start('my_sol.sol')and then c.solve().

(22 Sep '14, 12:21) johnclarke
1

@johnclarke Sorry for the long delay, but I've been hoping that @Paul Rubin would get back to this... we're touching a somewhat "delicate matter" here (that I'd rather have liked to delegate a "higher authority" ;-).

But ...let's try:

A: The .sol file created from c.solution.write("my_sol.sol") might not provide a feasible (not even speaking of optimal) solution to the model loaded from myproblem.lp – for reasons discussed, e. g., here: http://orinanobworld.blogspot.com/2010/09/internal-model-v-lp-file-v-sav-file.html

B: The .sol file – to your best knowledge – provides a feasible (or even "optimal" [w.r.t MIP gap & other parameters]) solution, but... CPLEX won't just trust your "opinion": c.feasopt( ... ) could provide a work-around (depending on your needs and goals).

C: The .sol file provides an "optimal" solution, ... and you want to convince CPLEX of your opinion: sth. like c.MIP_starts.change(0, c.MIP_starts.get_starts(0)[0], <1,...,4>) could alleviate your "pains" when processing c.solve().

D, most sophisticated approach: Don't provide my_sol.sol as a solution to myproblem.<LP|SAV|...> – but to a modified model that incorporates cuts added by CPLEX during a MIP optimization [IINM, the same can be achieved using the Python API].

(24 Sep '14, 15:34) fbahr ♦

@Florian: Your authority is high enough. :-) I don't know the Python API, but everything else you mentioned is correct.

(24 Sep '14, 16:59) Paul Rubin ♦♦

@fbahr Thank you very much for this detailed response!

What I understand is that there is no way to store the (entire) state of the cplex instance in a way as to re-instantiate it in a way that it 'trusts' itself. That's fine and I see the benefit of the different approaches you mention above.

My problem is that if I have a bug or a exception in the post-processing code, there is no way (I can see) to fix the code and come back to that point. I will probably end up simply serializing the parts of the state that are important to me.

Again thank you for your help -- I appreciate it!

(24 Sep '14, 21:35) johnclarke

I'm not a Pythonista, but I'm pretty sure the problem is that you haven't called solve. Loading a solution into CPLEX primes it to start from that solution (or something close to it, if the solution needs repair) when you invoke the solve method. CPLEX still needs to verify that the solution is both feasible and optimal (particularly since you could be feeding it a Alton from a somewhat different version of the problem, or a suboptimal solution from an earlier run, or even one you snatched out of a place we shall not discuss).

link

answered 19 Sep '14, 16:21

Paul%20Rubin's gravatar image

Paul Rubin ♦♦
14.6k412
accept rate: 19%

@Paul Rubin -- good idea! Unfortunately, c.solve() just resolves the problem (and thus defeats the purpose of saving the solution/state). This could be an artifact of the Python interface -- in other words, perhaps the .sol file (and I tried with .lp and .sav) is not getting saved or loaded correctly. I wonder if this is possible with C# or C++.

(19 Sep '14, 16:30) johnclarke

Does the second solve need the same amount of time? If you're solving a MIP, sine branching will be necessary to verify optimality. If it's an LP, you should be restoring an optimal basis, requiring little no pivoting.

(19 Sep '14, 16:38) Paul Rubin ♦♦

It is an MIP. I'll have to re-check but a first glance it takes longer to solve after having loaded the sol file.

(19 Sep '14, 19:55) johnclarke
Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×191
×16
×5

Asked: 19 Sep '14, 15:27

Seen: 2,133 times

Last updated: 24 Sep '14, 21:35

OR-Exchange! Your site for questions, answers, and announcements about operations research.