6 const Real TOL=1e-2; // roughly 1/10 mm
9 Active_constraints::status() const
11 String s("Active|Inactive [");
12 for (int i=0; i< active.sz(); i++) {
13 s += String(active[i]) + " ";
17 for (int i=0; i< inactive.sz(); i++) {
18 s += String(inactive[i]) + " ";
26 Active_constraints::OK() {
29 assert(active.sz() +inactive.sz() == opt->cons.sz());
30 assert(H.dim() == opt->dim());
31 assert(active.sz() == A.rows());
34 for (int i=0; i < opt->cons.sz(); i++)
36 for (int i=0; i < active.sz(); i++) {
40 for (int i=0; i < inactive.sz(); i++) {
44 for (int i=0; i < allcons.sz(); i++)
45 assert(allcons[i] == 1);
49 Active_constraints::get_lagrange(Vector gradient)
57 Active_constraints::add(int k)
63 inactive.swap(k,inactive.sz()-1);
66 Vector a( opt->cons[cidx] );
70 Vector addrow(Ha.dim());
73 a != 0, so if Ha = O(EPS), then
74 Ha * aH / aHa = O(EPS^2/EPS)
76 if H*a == 0, the constraints are dependent.
78 H -= Matrix(Ha/aHa , Ha);
82 sorry, don't know how to justify this. ..
86 A -= Matrix(A*a, addrow);
87 A.insert_row(addrow,A.rows());
89 WARN << "degenerate constraints";
93 Active_constraints::drop(int k)
98 inactive.add(active[k]);
104 if (a.norm() > EPS) {
108 Real q = a*opt->quad*a;
110 A -= A*opt->quad*Matrix(a,a/q);
112 WARN << "degenerate constraints";
114 Vector rem_row(A.row(q));
115 assert(rem_row.norm() < EPS);
122 Active_constraints::Active_constraints(Ineq_constrained_qp const *op)
127 for (int i=0; i < op->cons.sz(); i++)
129 Choleski_decomposition chol(op->quad);
133 /* Find the optimum which is in the planes generated by the active
137 Active_constraints::find_active_optimum(Vector g)
142 /****************************************************************/
145 min_elt_index(Vector v)
147 Real m=INFTY; int idx=-1;
148 for (int i = 0; i < v.dim(); i++){
153 assert(v(i) <= INFTY);
158 ///the numerical solving
160 Ineq_constrained_qp::solve(Vector start) const
162 Active_constraints act(this);
169 Vector gradient=quad*x+lin;
172 Vector last_gradient(gradient);
175 while (iterations++ < MAXITER) {
176 Vector direction= - act.find_active_optimum(gradient);
178 mtor << "gradient "<< gradient<< "\ndirection " << direction<<"\n";
180 if (direction.norm() > EPS) {
181 mtor << act.status() << '\n';
185 Inactive_iter minidx(act);
189 we know the optimum on this "hyperplane". Check if we
190 bump into the edges of the simplex
193 for (Inactive_iter ia(act); ia.ok(); ia++) {
195 if (ia.vec() * direction >= 0)
197 Real alfa= - (ia.vec()*x - ia.rhs())/
198 (ia.vec()*direction);
205 Real unbounded_alfa = 1.0;
206 Real optimal_step = MIN(minalf, unbounded_alfa);
208 Vector deltax=direction * optimal_step;
210 gradient += optimal_step * (quad * deltax);
212 mtor << "step = " << optimal_step<< " (|dx| = " <<
213 deltax.norm() << ")\n";
215 if (minalf < unbounded_alfa) {
216 /* bumped into an edge. try again, in smaller space. */
217 act.add(minidx.idx());
218 mtor << "adding cons "<< minidx.idx()<<'\n';
221 /*ASSERT: we are at optimal solution for this "plane"*/
226 Vector lagrange_mult=act.get_lagrange(gradient);
227 int m= min_elt_index(lagrange_mult);
229 if (m>=0 && lagrange_mult(m) > 0) {
230 break; // optimal sol.
232 assert(gradient.norm() < EPS) ;
237 mtor << "dropping cons " << m<<'\n';
240 if (iterations >= MAXITER)
241 WARN<<"didn't converge!\n";
243 mtor << ": found " << x<<" in " << iterations <<" iterations\n";
248 /** Mordecai Avriel, Nonlinear Programming: analysis and methods (1976)
253 This is a "projected gradient" algorithm. Starting from a point x
254 the next point is found in a direction determined by projecting
255 the gradient onto the active constraints. (well, not really the
256 gradient. The optimal solution obeying the active constraints is
257 tried. This is why H = Q^-1 in initialisation) )