Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing variable bounds during reoptimization #95

Open
cdanielmachado opened this issue Jul 5, 2024 · 9 comments
Open

Changing variable bounds during reoptimization #95

cdanielmachado opened this issue Jul 5, 2024 · 9 comments

Comments

@cdanielmachado
Copy link

I am trying to solve an LP problem multiple times, where both the objective coefficients and the bounds of the variables may get modified between iterations. Something of the form:

for iteration i in {1,2,3... }:

solve:
    max c(i) * x
    where
        A * x = b
        lb(i) < x < ub(i)

I start with enableReoptimization() before populating the model with variables and constraints. After solving the problem in each iteration, I free the problem with freeReoptSolve(), and then modify the objective coefficients and the variable bounds.

Changing the objective coefficients is successful, however something strange happens with the variable bounds. I am able to change them (if I retrieve the bounds from the variables, i see they have been updated), but the model is still solved with the original values (and if I write the problem to a file, I see that the old values are still there).

  1. Is this an issue or is it expected behavior?

  2. How can I (properly) modify variable bounds using re-optimization?

@cdanielmachado
Copy link
Author

Small correction to what i said above: changing the bounds after freeReoptSolve() (stage moves to PRESOLVED) updates the "global" bounds but not "local" or "original".

This is likely a result of this:

    switch( scip->set->stage )
    {
    case SCIP_STAGE_PROBLEM:
       assert(!SCIPvarIsTransformed(var));
       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
       SCIP_CALL( SCIPvarChgLbLocal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
             scip->branchcand, scip->eventqueue, newbound) );
       SCIP_CALL( SCIPvarChgLbOriginal(var, scip->set, newbound) );
       break;
 
    case SCIP_STAGE_TRANSFORMING:
    case SCIP_STAGE_PRESOLVED:
       SCIP_CALL( SCIPvarChgLbGlobal(var, scip->mem->probmem, scip->set, scip->stat, scip->lp,
             scip->branchcand, scip->eventqueue, scip->cliquetable, newbound) );
       break;

And somehow changing only the global bounds does not affect the next optimization, since they are somehow ignored.

According to the documentation https://www.scipopt.org/doc-8.0.3/html/REOPT.php it should be possible to change variable bounds between P(i) and P(i+1)...

@svigerske
Copy link
Member

It is not related directly to the issue raised here, but I doubt that the reoptimization feature of SCIP is useful to solve a sequence of similar LPs. For LPs, you would want that at least the basis solution of one solve is somehow used as a starting point for the next solve. However, that won't happen here. SCIP's reoptimization is for solving a sequence of MIPs (with changing objective or shrinking feasible region) and focuses on reusing some information from the branch-and-bound tree of one solve for the next one. When solving LPs with SCIP, there is no branch-and-bound.

You may want to look into using LP solvers directly instead, e.g., SoPlex.

@cdanielmachado
Copy link
Author

cdanielmachado commented Jul 6, 2024 via email

@svigerske
Copy link
Member

It should not throw an error when solved again from PROBLEM stage. Can you include more information on this error?

@cdanielmachado
Copy link
Author

Sure, here is what happens if I try to solve a second time (by the way, I'm using PySCIPOpt API, but i don't think it is a problem with the python API):

Screen Shot 2024-07-08 at 15 02 02

@svigerske
Copy link
Member

This seems like a bug, but I have problems to reproduce.
I tried this:

   SCIP* scip;
   SCIPcreate(&scip);
   SCIPincludeDefaultPlugins(scip);
   SCIPprintVersion(scip, NULL);
   SCIPreadProb(scip, "/path/to/some/lp.mps", NULL);
   SCIPsolve(scip);
   SCIPfreeTransform(scip);
   SCIPsolve(scip);

There was no error.

Since you pointed to the SCIP 8 docu before, can you check that you use the latest SCIP version (9.1.0). If so, can you provide some full example code to reproduce this?

@cdanielmachado
Copy link
Author

I am using the latest PySCIPOpt, which according to the documentation, comes pre-packaged with SCIP 9.1.

You can reproduce the error with:

#!/usr/bin/python

from pyscipopt import Model
problem = Model()
problem.enableReoptimization()
X = problem.addVar("X", lb=0, ub=1)
problem.chgReoptObjective(X, sense='minimize')
problem.optimize()
problem.freeTransform()
problem.optimize()

But actually, I just realized that the problem disappears if i don't enable re-optimization.

In fact, it seems I can re-use the problem instance and re-optimize multiple times as long as I don't enable reoptimization... Even the problem I reported initially (variable bounds not changing) seems to disappear if I don't enable reoptimization...

@svigerske
Copy link
Member

Ah ok, I didn't realize you still tried reoptimization. Then I can reproduce the issue also with the following C code:

int main() {
   SCIP* scip;
   SCIPcreate(&scip);
   SCIPincludeDefaultPlugins(scip);
   SCIPenableReoptimization(scip, TRUE);
   SCIPreadProb(scip, "/path/to/some/lp.mps", NULL);
   SCIPsolve(scip);
   SCIPfreeTransform(scip);
   SCIPsolve(scip);
   
   return 0;
}

The docu suggests to use SCIPfreeReoptSolve() instead of SCIPfreeTransform(). If I do that, it runs through without an issue.

I suppose a better error message could be nice.

@sbolusani You were looking into reoptimization recently. :) Could you take a look into this?

@cdanielmachado
Copy link
Author

Unfortunately with freeReOptSolve() we get back to the original issue that changing variable bounds has no effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants