Forum Discussion

FICO's avatar
FICO
Community Manager
4 years ago

Final solution of a nonlinear non-convex problem solved with Knitro (via Xpress) looks worse than the initial solution

Dear all,

I have a couple of questions on the use of the procedure setinitval and more in general on the use of an initial solution for solving a nonlinear problem.

I am solving a series of nonlinear non-convex problems and I want to use the solution given by iteration n as the starting point for the iteration n+1.

Each iteration is a separate call of the model (written in mosel) because I apply some modifications to the input data. These modifications are not too disruptive, so the final solution of iteration n is always a good feasible starting point for the iteration n+1.

Nevertheless, sometimes I get a final solution at iteration n+1 that has a worse objective value than the initial solution I gave.

So, the first point is: how can I be sure that Knitro used my initial solution? Is there a parameter that I can set in order to know if the solution has been accepted or rejected?

The second point is this: the solution I give is actually a "partial solution" in the sense that I use the procedure setinitval in order to set the value of some fundamental variables. Given those, the value of all the other variables can be deduced by the constraints of the model, so I thought the solver would be able to reconstruct the complete solution itself.

Could this "partial" solution be the problem? Do I have to set a value for every single variable in order to make the solver use that initial point?

If the problem is this: how can I export the complete solution of iteration n and reload the solution before solving iteration n+1?

Thank you in advance for your help and time.

Caterina

7 Replies

  • FICO's avatar
    FICO
    Community Manager

    Hi Caterina,

    there exists the function XSLPsetcurrentiv (https://www.fico.com/fico-xpress-optimization/docs/latest/solver/nonlinear/HTML/XSLPsetcurrentiv.html) to store the current solution as an initial point for the next solve. Of course that would assume that you solve twice from the same problem, so if you want to solve from two separate Mosel models, you would have to store the solution after the first call and then forward this to the second to then insert as an initial point.

    For testing purposes, you can also try to set the LOG (https://www.fico.com/fico-xpress-optimization/docs/latest/solver/nonlinear/HTML/XSLP_LOG.html) control to 5, which will give you an additional output of the initial values that Xpress actually transferred to Knitro. Knitro itself will generally also print some information about what it did with the initial solution, like for example

    Knitro shifted start point further inside presolved bounds (2 variables).

    In addition to that, I would suggest to check the first line in the Knitro log (when going through Mosel, you might need to activate this explicitly via XNLP_VERBOSE (https://www.fico.com/fico-xpress-optimization/docs/latest/mosel/mosel_lang/dhtml/XNLP_VERBOSE.html)). If the previous solution was accepted, then this first line, in particular the objective value, should match the previous solution, if it doesn't, then the solution was not accepted for some reason (or completed in an unexpected way in case of a partial solution).

    Whether a partial solution is sufficient really depends on how obvious the remaining ones are. If presolve can remove the remaining variables, then initial values for them might not be needed, but if it doesn't, then the solver may not always be able to figure out the correct values for the remaining variables, so if you do have a full solution, then it would generally be advisable to set up all initial values rather than only a subset in the hope that the solver can fill in the rest.

    Best,

    Tristan

  • FICO's avatar
    FICO
    Community Manager

    Thank you Tristan! Your answer helped me a lot.

    I choose the option of saving the solution of one iteration and then forward it to the next iteration.

    This way we will be able to run a single iteration separately, if needed, and provide a better solution as an initial point.

    What are the functions/procedures I have to use for this purpose?

    I was able to generate the .slx file with the solution of one iteration but I don't know how to load this solution in the new iteration and set it as the initial value.

    Thanks again!

    Br, Caterina

  • FICO's avatar
    FICO
    Community Manager

    Hi Caterina,

    unfortunately there is currently no convenient way to load in an slx solution as initial values, although we might consider adding this in the future.

    At the moment you would need to store the solution values in an array and then set the initial values from there, for example:

    itersol: array(integer) of real

    (solve iteration i)

    forall (i in I) itersol(i) := getsol(x(i))

    (transfer itersol to the other model)

    forall (i in I) setinitval(x(i), itersol(i))

    Best,

    Tristan

  • FICO's avatar
    FICO
    Community Manager

    Hi Tristan,

    I followed your instructions but I have a new question related to the setinitval procedure.

    I load my initial solution by setting the value of each variable (not every but most of them).

    Then I set the parameter xslp_log = 5 in order to see the initial point passed to Knitro but the point is not what I expected.

    Beside some variables that completely changed their initial values, and I know this could be because of some preprocessing made by xpress, there are some other variables whose values look shifted from one position.

    Here is an example.

    What I load into the model and read in the .mps file of the problem is:

    flowOn((77_278_83_313)_ENERGY,0)= 111.446

    flowOn((77_278_83_313)_ENERGY,1)= 111.346

    flowOn((77_278_83_313)_ENERGY,2)= 111.246

    flowOn((77_278_83_313)_ENERGY,3)= 112.939

    What I read in the mosel log file is:

    flowOn((77_278_83_313)_ENERGY,0)= 111.346

    flowOn((77_278_83_313)_ENERGY,1)= 111.246

    flowOn((77_278_83_313)_ENERGY,2)= 112.939

    flowOn((77_278_83_313)_ENERGY,3)= 0

    I also tried to solve the .mps directly from the console and again I found this mismatch, please see the attached picture.

    Do you know what is happening? Could this be an error in the logging procedure? Or the initial point is actually shifted?

    This would explain why Knitro cannot complete the search and reaches the time limit even when the initial point I provide is a feasible one.

    Thank you!

    Br, Caterina

  • FICO's avatar
    FICO
    Community Manager

    Hi Caterina,

    this indeed looks strange. Can you share the instance and the code you used so that I can have a look? Either here or if you don't want to share it publicly to [email protected] ?

    Best,

    Tristan

  • FICO's avatar
    FICO
    Community Manager

    Hi Tristan!

    Thanks a lot for your quick answer. I send a private message in order to share several files.

    Best,

    Caterina

  • FICO's avatar
    FICO
    Community Manager

    Hi Caterina,

    this turned out to indeed be a bug in the logging, the initial values forwarded to Knitro should have been correct.

    Best,

    Tristan