Deterministic solves for repeated calls to generated code

I am doing repeated OSQP solves using the generated C code, updating the problem matrices for each solve. Sometimes a solve is related to the prior solve, in which case I take advantage of warm starting and don’t worry much about the value of any persistent states in the code.

However, at other times I must perform a solve that is completely unrelated to a prior solve (apart from having the same sparsity pattern). For these cases I’m wondering if there is something I should do to “reset” any persistent states in the OSQP code to default settings. For one example, is the adaptive rho a persistent state? If so, then for determinism I should probably reset it to a default value whenever I wish to solve a new and unrelated problem.

I may have missed it, but I didn’t see anything in the documentation that covered this, and would appreciate any guidance. Thanks,

Matt

There are two aspects to the question I think:

  1. The initialisation of iterates: This is the easiest part to answer. If you solve an unrelated problem then the solver will still warm start from the previous iterate unless you take some action. You can just manually warm start in this case by setting the x and y values back to vectors of zeros. There is also a cold start function that you can call via the API (I think), which will do the same thing.

  2. The parameter rho: This value is persistent even if you cold start. If you update the P and A matrices, it seems from the code that this causes the KKT matrix to update, and then the solver immediately forces a refactorisation. It seems that the rho vector is not updated when his happens. There is also a function to update the rho values, but this also immediately forces a refactorisation. I don’t see an obvious way of updating all of P/A/rho while ending up with only a single refactorisation.

I think the central problem is that we did not write the warm starting features with your case in mind, i.e. the situation in which a user would have structurally identical problems but with totally different values. Our expectation was that warm starting, particularly when updating P and A, would be done by a user as part of some kind of sequential procedure (i.e. as part of a larger SQP solver).

If your problems are hugely different, it might be better to just create a new solver object unless the overhead from reallocating memory is too burdensome for your use case.

NB: I have edited this reply since my initial response also said that updated P/A data might be internally rescaled using suboptimal scaling matrices. That was wrong : OSQP will recalculate the scaling matrices based on the updated P/A.

Hi Paul,

Thank you very much for the detailed reply.

You mentioned OSQP computes the scaling matrices when you “first create a problem instance.” Does this mean the scaling matrices are fixed at codegen time? Or equivalently, that the data used to derive the scaling is fixed at codegen time?

Some use cases for changing the problem significantly would be:

  • MPC with changes to model parameters

  • Repeatedly solve different SQP problem instances

It would be great to see an API to comprehensively reset OSQP in some future version.

Thanks for making OSQP available!

Best,

Matt

See my modified reply. We had a closer look at the code, and it seems that the data is rescaled when you update the A and P matrices. The scaling matrices are not fixed and will update correctly if you update P and A in your problem.

Thank you very much for the clarification.
Best,

Matt