VDX is a Matlab wrapper for the creation of generic CasADi NLPs which provides automatic, transparent, index tracking facilities for named variable classes. It also provides a direct interface to CasADi nlpsol and allows for automatic results extraction for the mentioned variable classes.
This section provides a quick overview for general users of how to use this tool. First we create a problem via:
prob = vdx.Problem();
which creates a problem of the form
minimize f(w,p), subject to
lbw <= w <= ubw
lbg <= g(w,p) <= ubg
The decision variable w
, parameters p
, and the constraint function g
, are subdivided into individual index tracked "variable classes".
These are useful to track the semantic meanings of variables or contstraints.
The following example produces the x
and y
variables of hanging masses in a hanging chain problems:
prob = vdx.Problem();
lbx = 0; ubx = 10;
lby = -10; uby = 10;
for ii=1:n_masses
x = SX.sym(['x_' num2str(ii)], 1);
y = SX.sym(['y_' num2str(ii)], 1);
init_x = ii*10/n_masses;
init_y = -10 + ii*20/n_masses;
prob.w.x(ii) = {x, lbx, ubx, init_x};
prob.w.y(ii) = {y, lby, uby, init_y};
end
It is important to note that the variable classes do not need to be pre-defined as the first time a variable class is indexed into it is automatically created. The syntax for adding a variable is as follows:
<variable>.<class>(<index>) = {<symbolic>[,<lower bound>, <upper bound>, <initial value>]}
<variable>.<class>(<index>) = {{<var_name>, <var_length>}[,<lower bound>, <upper bound>, <initial value>]}
the first of which takes a CasADi symbolic vector as its first member and the second generates the CasADi symbolic from a name and a vector size.
If <index>
is not scalar one can initalize multiple indices at once.
This is useful to compactly populate the variable in multiple dimensions.
You can modify the bounds and initial values of a variable by assigning to the lb
, ub
, and init
fields of a variable class:
prob.w.x(1).lb = 5;
prob.w.y(1).ub = 0;
prob.w.x(1).init = 7;
VDX provides the facility to group variables and index into this group.
var_group = vdx.VariableGroup({<members>}[, {<indexing rules>}])
where the first argument is a list of vdx.Variable
and the optional second parameter allows for a custom indexing function with the signature: (index,vdx.Variable) -> index
.
Simple indexing rules are implemented in vdx.indexing
and include rules that map indicies to the (lexicographically) previous or next index.
If variables of different dimension are used in the same variable group then the lower dimensioned variables are indexed by a truncation of the index.
For example the group with u
10 by 1, and x
10 by 4, indexed at (4,4)
would yield the vector: [u(4), x(4,4)]
.
The syntax for adding a constraint is identical to the syntax for adding vectors, however the second syntax is not useful because it creates a new variable.
Constraints for multiple indices can be created via the special syntax:
<variable>.<class>(<index>) = {{<function:casadi.Function>, {<arguments>}[, {<indexing rules>}]}[,<lower bound>, <upper bound>, <initial value>]}
with the arguments and indexing rules forming the variable group which makes up the arguments to the function. This is then applied for all the indices.
Currently you can generate a CasADi nlpsol
by calling Problem.create_solver(casadi_options)
where the argument is a struct containing the CasADi nlpsol options.
Here is an example:
prob = vdx.Problem();
...
% define problem
...
casadi_options = struct;
...
% define casadi options
...
prob.create_solver(casadi_options);
stats = prob.solve();
Once the solver is created and solve is called the mult
and res
fields of w
, g
, and p
are populated with the multipliers and results of the last solver call.
These values can be accessed as in the following example:
full_result = prob.w.res;
x_result = prob.w.x.res;
y_i_result = prob.w.y(ii).res;
lambda_x = prob.w.x.mult;
lambda_y_ii = prob.w.y(ii).mult;
We also provide a package of specialized problem formulations. Currently the only supported formulation is for Mathematical Programs with Complementarity Constraints (MPCC):
minimize f(w,p), subject to
lbw <= w <= ubw
lbg <= g(w,p) <= ubg
0 <= G(w,p) perp H(w,p) >= 0
There are some details that are important to note:
- Indexing into variable class is zero indexed.
- Assigning to
init
,lb
, andub
, can only be done for scalar indexes. Updating VDX to allow for assigning to non-scalar indices is a soon to be implemented. - We assume that the length of each index of a variable class is uniformly a single value or empty.
- When accessing a variable class numeric value (
lb
,ub
,init
,res
,mult
), the values are horizontally concatenated and in column major order, i.e. in "lexicographical" order. - This project is similar in its goals to the existing (but as far as I know deprecated)
structures
concept in thecasadi.tools
python package. As of now we do not plan to guarantee any sort of common interface however.