coin-or / Ipopt

COIN-OR Interior Point Optimizer IPOPT
https://coin-or.github.io/Ipopt
Other
1.41k stars 281 forks source link

Is it possible to modify variable bounds between iterations? #626

Closed EmJay276 closed 1 year ago

EmJay276 commented 1 year ago

I need to run nonlinear optimizations with ipopt iteratively in a loop. Between most of my ipopt calls only the variable boundary changes (I am moving points in 3D for a topology optimization but need to ensure these points don't overlap each other).

Due to the bound_push, the first ~10 iterations of a new run are needed to get back to the "end"/result of the previous run. I have read a lot about warm_start, but this led to even worst results/number of iterations needed.

Is it somehow possible to change the boundaries of the design variables between iterations without a complete restart of ipopt?

Thanks in advance!

svigerske commented 1 year ago

I don't think so. You could probably hack into various classes that store the bounds (e.g,. IpoptCalculatedQuantities, OrigIpoptNLP, TNLPAdapter) and change them there, but it could confuse the algorithm. Especially if bounds are tightened and the current iterate is suddenly outside bounds, I wouldn't know what will happen.

You can disable the bound-push when doing a warm start.

Also you could try whether you have more luck with saving and providing a complete "warm-start-iterate". I think you would get it from https://coin-or.github.io/Ipopt/classIpopt_1_1IpoptData.html#a7ea3aeb9b62b340f7671d61b88a9b056 and then provide it again by implementing https://coin-or.github.io/Ipopt/classIpopt_1_1TNLP.html#a273b8be28d2a0a805489cd8903aac1c6 This "warm-start-iterate" is closer to the internal NLP representation and should help to avoid loosing some dual values that exist for the internal problem only. I never tried that, but there is code in Bonmin that uses this.

EmJay276 commented 1 year ago

Thanks for your fast reply and nice suggestions!

I am using cyipopt, implementing get_warm_start_iterate() and accesing curr() from python is probably a bit more complicated.

You can disable the bound-push when doing a warm start.

How can I exactly do this? Setting warm_start_bound_push, warm_start_bound_frac, ... to 0? Or is there a option to completly disable the bound-push?

I don't think so. You could probably hack into various classes that store the bounds (e.g,. IpoptCalculatedQuantities, OrigIpoptNLP, TNLPAdapter) and change them there, but it could confuse the algorithm. Especially if bounds are tightened and the current iterate is suddenly outside bounds, I wouldn't know what will happen.

I see the problem in a general case, I my case the bounds would always relax around the current position.

svigerske commented 1 year ago

There is no extra option. Just set all 5 push/frac options in https://coin-or.github.io/Ipopt/OPTIONS.html#OPT_Warm_Start to some very tiny value. If that gives numerical problems, increase the value.