Open alexe15 opened 4 years ago
Broadly speaking, the goal is to untangle Casadi from Aladin so that we can use Aladin without having to use Casadi. This is necessary for large problems, where Casadi just takes too long to set up the problem.
Let me add some details:
Currently, there is no possibility to not use Casadi. In other words, when you use the toolbox, you need to use casadi. The advantages of Casadi, but so are its disadvantages:
It is especially the last point that is painful. For instance, large (optimal) power flow problems simply take too long to set up. Playing with them is no fun 😢
Untangle Aladin and Casadi. Essentially, make two repositories: the Aladin core and a Casadi preprocessor. Then, using the Casadi preprocessor together with Aladin core is like using the toolbox now. However, if someone is brave enough to not use Casadi, then use just Aladin core. The goal of this issue is to write Aladin core
The plain Aladin algorithm that does not rely on external packages. It takes a problem formulation as input and returns the solution. The critial point is how to formulate and solve the local NLPs; how to call a solver depends on the solver itself: fmincon is different from ipopt, and so on.
Question: Should the formulation of the NLP be part of Aladin core or not? If it is, we restrict ourselves to the solvers that we support.
Once we have reached consensus on this issue, we should create a file to define the interface.
I agree, just for you to know we have a similar feature implemented in ALADIN-M. If you have a look at the ALADIN MPC example (https://alexe15.github.io/ALADIN.m/robotEx/, you can also find this problem in the /examples
folder), then you can see that Ruchuan implemented a reuse
option. This means that the problem formulation can be reused after one ALADIN run for MPC problems, where only the initial condition for the ODE changes. This reuse is automatically detected within ALADIN-M. This is done here https://github.com/alexe15/ALADIN.m/blob/43dbc9d993d5c7ccb040cf0c2f27c677f8ab02f3/src/core/run_ALADINnew.m#L30
so if NLP solvers, sensitivities etc. are defined in the sProb
struct ALADIN-M will use them. So I think to some extent, this is where we could start. If we pass solvers here, which use the same interface as the CasADi solvers as here
https://github.com/alexe15/ALADIN.m/blob/43dbc9d993d5c7ccb040cf0c2f27c677f8ab02f3/src/core/parallelStepCentral.m#L27
then I guess we should be able to define the problems more or less completely externally also with non-CasADi solvers. Btw @Ruchuan is working on a similar issue for a machine learning problem in #102 (Yuning suggested to include this as an additional example showing that we can gain some benefits with bi-level ALADIN for machine learning problems)
You agree with what? 🤣
I can ask my question again in ALADIN-M-lingo: should Aladin core be simply iterateAL()
? Yes or no?
(that's really a design question i don't know the answer to)
However, I do think that we should not rely on the interface from Casadi, because it's highly customized to Casadi. Instead, can we move to function handles? Check out this prototypical example:
Taking the standard example
import casadi.*
x = SX.sym('x');
y = SX.sym('y');
z = SX.sym('z');
nlp = struct('x',[x;y;z], 'f',x^2+100*z^2, 'g',z+(1-x)^2-y);
S = nlpsol('S', 'ipopt', nlp);
the Casadi way to solve this is
x0 = [2.5,3.0,0.75]
S('x0', x0', 'lbg', 0, 'ubg', 0)
What if, instead, we make this a function handle?
solve_problem = @(x)S('x0', x, 'lbg', 0, 'ubg', 0)
solve_problem(x0)
Thinking about this a little more: this does fix a lot of Casadi dependency. As you said: as long as I provide a valid sProb
together with a (function handle solve_problem
) way to solve the NLPs, I am fine.. or not?!?!
@Till: this is a valid suggestion, which has been on the table for discussion for some time. At this point, it should not get priority.
Running examples/examples_main.m
with use_fmincon = false
yields the usual solution:
Setting now use_mincon = true
uses fmincon only to solve the local NLP. The computation of the sensitivities is untouched. The result is
While overall convergence agrees, the final values differ.
Anyhow, first step taken. Yay 🎉 🎉 🎉
However, we do need to agree on a common interface for calling the NLP solvers. I do think that abstractifying everything will improve readability of the code tremendously. Check out how
is defined:
Having talked to @alexe15, the suggestion for the common interface for solving the local NLPs is:
solve_NLP(x0, z, rho, lambda, Sigma, pars)
where pars is a struct
containing arbitrary parameters.
I rectified the interface https://github.com/alexe15/ALADIN.m/blob/ff08ccaa927a8f7aa4f60e4ad3ed506803c1fdde/src/core/parallelStepCentral.m#L35-L36
I only tested against runtests('OptProbsTest')
with Ipopt. ^^
The next step is to let the user specify the sensititivies.
Big fail from my side: the numerical sensitivies were not used correctly in all previous versions (and the gradient of the cost function was incorrect..). With 075888a it should be correct. Also, for the distributed power flow problem I compared the numerical sensitivities against casadi: they agree.
I wrote a few lines to describe what I did the last couple of days. My preliminary conclusion is that to abstractify aladin is, luckily, less involved than I feared. I got it to work with fmincon and user-supplied sensitivities for a distributed power flow problem, and it can solve cases for which casadi+ipopt simpy takes too long to set up (e.g. coupling three 118-bus systems).
I will stop working on this for now, but @bennerh will take over beginning in May.
@alexe15, please take a look at the document I wrote. This should be the basis for future discussions.
I cleaned up the parallel step tremendously, shifting all the heavy burden to local functions. Readability of the code is increased. I think this more modular approach helps also for the file doing the decentralized step.
Having spoken to @alexe15, the goal of the abstractify
branch can be summarized as follows:
When calling iterateAL( sProb, opts, timers )
, no information about casadi need to be passed.
In its simplest form, the following check needs to evaluate to true: does iterateAL()
run after having deleted all fields in sProb
that have cas
in their name?
In a more elegant form, sProb
should not contain any casadi information to begin with.. ;)
Proposal for next step: Construct an example file that should run with the abstractified-ALADIN branch version. To do so, I would rebuild the example provided by @timueh for the abstractify branch.
In case there are no objections from your side, I would start doing that now..
Furthermore I would like to test a solver different from fmincon and ipopt, because it's a good task for me and a good test in the end. Any suggestions there?
I would not try to replicate my example; there is simply no need. The best tests are and remain the test that you have written already.
AFAICT either all of them work or all of them fail... ;)
Implementing different solvers is on the agenda, see #106, #107, but I would not do that now. Let's do one thing at a time.
ALADIN implementation independent of CasADi.