26 #include "nlp_tools.hpp"
28 #include "casadi_misc.hpp"
34 const T& g,
const T& lbg,
const T& ubg,
35 std::vector<casadi_int>& gi,
41 casadi_int ng = g.size1();
42 casadi_int nx = x.size1();
44 casadi_assert(lbg.size1()==ng,
"Dimension mismatch");
45 casadi_assert(ubg.size1()==ng,
"Dimension mismatch");
46 casadi_assert(g.is_column(),
"Dimension mismatch");
47 casadi_assert(lbg.is_column(),
"Dimension mismatch");
48 casadi_assert(ubg.is_column(),
"Dimension mismatch");
49 casadi_assert(x.is_column(),
"Dimension mismatch");
52 Function temp(
"temp_detect_simple_bounds_gen", {x, p}, {g});
53 Sparsity sp = temp.jac_sparsity().at(0);
57 std::vector<bool> is_simple(ng,
true);
60 std::vector<bool> is_nonlin = which_depends(g, x, 2,
true);
62 const casadi_int* row = spT.
colind();
63 for (casadi_int i=0;i<ng;++i) {
65 bool single_dependency = row[i+1]-row[i]==1;
66 is_simple[i] = single_dependency && !is_nonlin[i];
73 std::vector<casadi_int> sgi_to_sgsi =
lookupvector(sgi, ng);
77 std::vector<T>{g_bounds, jtimes(g_bounds, x, T::ones(nx, 1))});
80 gf.
call(std::vector<T>{0, p}, res,
true,
false);
86 T lb_pre = (lbg(sgi)-f1)*f2_inv;
87 T ub_pre = (ubg(sgi)-f1)*f2_inv;
92 T lb = lb_pre*pos_f2+ub_pre*neg_f2;
93 T ub = ub_pre*pos_f2+lb_pre*neg_f2;
101 const casadi_int* xi = spT.
row();
109 std::vector< std::vector<casadi_int> > sgsi_groups, sgi_groups, sxi_groups;
110 casadi_int n_groups = 0;
113 std::vector<casadi_int> group_count(nx);
116 for (casadi_int i=0;i<ng;++i) {
118 if (!is_simple[i])
continue;
120 casadi_int j = xi[row[i]];
121 casadi_int& k = group_count[j];
124 sgsi_groups.emplace_back();
125 sgi_groups.emplace_back();
126 sxi_groups.emplace_back();
129 sxi_groups[k].push_back(j);
130 sgi_groups[k].push_back(i);
131 sgsi_groups[k].push_back(sgi_to_sgsi[i]);
135 casadi_assert(n_groups>=1,
"mismatch");
137 for (casadi_int i=0;i<n_groups;++i) {
138 lbx(sxi_groups[i]) = fmax(lbx(sxi_groups[i]), lb(sgsi_groups[i]));
139 ubx(sxi_groups[i]) = fmin(ubx(sxi_groups[i]), ub(sgsi_groups[i]));
144 const std::vector<casadi_int>& sxi_ref = sxi_groups[0];
146 std::vector< std::vector<casadi_int> > xsub(n_groups);
148 xsub[0] =
range(sxi_ref.size());
151 std::vector<casadi_int> lookup =
lookupvector(sxi_ref, nx);
152 for (casadi_int i=1;i<n_groups;++i) {
153 const std::vector<casadi_int>& sxi = sxi_groups[i];
154 for (casadi_int j=0;j<sxi.size();++j) {
155 xsub[i].push_back(lookup[sxi[j]]);
162 T lam_g_forward = T::sym(
"lam_g", ng);
163 T lam_sg_backward = T::sym(
"lam_g", gi.size());
164 T lam_x_backward = T::sym(
"lam_x", nx);
167 T lam_sg_forward = lam_g_forward(sgi);
168 T lam_x_forward = T::zeros(nx, 1);
169 T lam_g_backward = T::zeros(ng, 1);
170 lam_g_backward(gi) = lam_sg_backward;
173 std::vector<T> lcomp, ucomp;
174 for (casadi_int i=0;i<n_groups;++i) {
175 lcomp.push_back(lbx(sxi_groups[i])==lb(sgsi_groups[i]));
176 ucomp.push_back(ubx(sxi_groups[i])==ub(sgsi_groups[i]));
180 T count_lb = T::zeros(nx);
181 T count_ub = T::zeros(nx);
182 for (casadi_int i=0;i<n_groups;++i) {
183 count_lb(sxi_groups[i]) += lcomp[i];
184 count_ub(sxi_groups[i]) += ucomp[i];
188 for (casadi_int i=0;i<n_groups;++i) {
189 T l = lam_sg_forward(sgsi_groups[i]);
192 lam_x_forward(sxi_groups[i]) += l*(lt*lcomp[i]+gt*ucomp[i]);
196 T l = lam_x_backward(sxi_ref);
199 T lam_xl = l*lt/count_lb(sxi_ref);
200 T lam_xu = l*gt/count_ub(sxi_ref);
202 for (casadi_int i=0;i<n_groups;++i) {
203 lam_g_backward(sgi_groups[i]) = lam_xl(xsub[i])*lcomp[i]+lam_xu(xsub[i])*ucomp[i];
207 lam_forward =
Function(
"lam_forward",
208 {lam_g_forward, p}, {lam_g_forward(gi), lam_x_forward},
209 {
"lam_g",
"p"}, {
"lam_sg",
"lam_x"});
210 casadi_assert_dev(!lam_forward.
has_free());
211 lam_backward =
Function(
"lam_backward",
212 {lam_sg_backward, lam_x_backward, p}, {lam_g_backward},
213 {
"lam_sg",
"lam_x",
"p"}, {
"lam_g"});
214 casadi_assert_dev(!lam_backward.
has_free());
218 const SX& g,
const SX& lbg,
const SX& ubg,
219 std::vector<casadi_int>& gi,
224 gi, lbx, ubx, lam_forward, lam_backward);
228 const MX& g,
const MX& lbg,
const MX& ubg,
229 std::vector<casadi_int>& gi,
234 gi, lbx, ubx, lam_forward, lam_backward);
bool has_free() const
Does the function have free variables.
void call(const std::vector< DM > &arg, std::vector< DM > &res, bool always_inline=false, bool never_inline=false) const
Evaluate the function symbolically or numerically.
Sparse matrix class. SX and DM are specializations.
Sparsity T() const
Transpose the matrix.
const casadi_int * row() const
Get a reference to row-vector,.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
std::vector< casadi_int > lookupvector(const std::vector< casadi_int > &v, casadi_int size)
Returns a vector for quickly looking up entries of supplied list.
std::vector< bool > boolvec_not(const std::vector< bool > &v)
Invert all entries.
void detect_simple_bounds(const SX &x, const SX &p, const SX &g, const SX &lbg, const SX &ubg, std::vector< casadi_int > &gi, SX &lbx, SX &ubx, Function &lam_forward, Function &lam_backward)
Detect simple bounds from general constraints.
void detect_simple_bounds_gen(const T &x, const T &p, const T &g, const T &lbg, const T &ubg, std::vector< casadi_int > &gi, T &lbx, T &ubx, Function &lam_forward, Function &lam_backward)
std::vector< casadi_int > boolvec_to_index(const std::vector< bool > &v)