]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/ineq-constrained-qp.cc
release: 0.1.61
[lilypond.git] / lily / ineq-constrained-qp.cc
index 4455a195b4590b23ee1128352e8e7bb8d41b8313..70856b56dc14cb3f1a869e3adff845f7b7f1a6c1 100644 (file)
@@ -3,19 +3,21 @@
 
   source file of the GNU LilyPond music typesetter
 
-  (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+  (c) 1996, 1997--1998 Han-Wen Nienhuys <hanwen@stack.nl>
 */
 #include "ineq-constrained-qp.hh"
 #include "qlpsolve.hh"
 #include "debug.hh"
 #include "choleski.hh"
+#include "main.hh"
 
 /*
-  MAy be this also should go into a library
+  May be this also should go into a library
  */
 
 const int MAXITER=100;         // qlpsolve.hh
 
+
 /*
   assume x (idx) == value, and adjust constraints, lin and quad accordingly
 
@@ -24,35 +26,35 @@ const int MAXITER=100;              // qlpsolve.hh
 void
 Ineq_constrained_qp::eliminate_var (int idx, Real value)
 {
-  Vector row (quad.row (idx));
+  Vector row (quad_.row (idx));
   row*= value;
 
-  quad.delete_row (idx);
+  quad_.delete_row (idx);
 
-  quad.delete_column (idx);
+  quad_.delete_column (idx);
 
-  lin.del (idx);
+  lin_.del (idx);
   row.del (idx);
-  lin +=row ;
+  lin_ +=row ;
 
-  for (int i=0; i < cons.size(); i++) 
+  for (int i=0; i < cons_.size(); i++)
     {
-      consrhs[i] -= cons[i](idx) *value;
-      cons[i].del (idx);
+      consrhs_[i] -= cons_[i](idx) *value;
+      cons_[i].del (idx);
     }
 }
 
 void
 Ineq_constrained_qp::add_inequality_cons (Vector c, double r)
 {
-  cons.push (c);
-  consrhs.push (r);
+  cons_.push (c);
+  consrhs_.push (r);
 }
 
 Ineq_constrained_qp::Ineq_constrained_qp (int novars):
-  quad (novars),
-  lin (novars),
-  const_term (0.0)
+  quad_ (novars),
+  lin_ (novars),
+  const_term_ (0.0)
 {
 }
 
@@ -60,28 +62,28 @@ void
 Ineq_constrained_qp::OK() const
 {
 #if !defined (NDEBUG) && defined (PARANOID)
-  assert (cons.size() == consrhs.size ());
-  Matrix Qdif= quad - quad.transposed();
-  assert (Qdif.norm()/quad.norm () < EPS);
-#endif    
+  assert (cons_.size() == consrhs_.size ());
+  Matrix Qdif= quad_ - quad_.transposed();
+  assert (Qdif.norm()/quad_.norm () < EPS);
+#endif
 }
-   
+
 
 Real
 Ineq_constrained_qp::eval (Vector v)
 {
-  return v * quad * v + lin * v + const_term;
+  return v * quad_ * v + lin_ * v + const_term_;
 }
 
 
 int
 min_elt_index (Vector v)
 {
-  Real m=infinity_f; 
+  Real m=infinity_f;
   int idx=-1;
   for (int i = 0; i < v.dim(); i++)
     {
-      if (v (i) < m) 
+      if (v (i) < m)
        {
          idx = i;
          m = v (i);
@@ -106,38 +108,40 @@ min_elt_index (Vector v)
 
   */
 Vector
-Ineq_constrained_qp::constraint_solve (Vector start) const 
-{    
+Ineq_constrained_qp::constraint_solve (Vector start) const
+{
   if (!dim())
     return Vector (0);
-  
-  // experimental
-  if (quad.dim() > 10)
-    quad.try_set_band();
-  
+
   Active_constraints act (this);
-  act.OK();    
+  act.OK();
+
 
-  
   Vector x (start);
-  Vector gradient=quad*x+lin;
-  //    Real fvalue = x*quad*x/2 + lin*x + const_term;
+  Vector gradient=quad_*x+lin_;
+  //    Real fvalue = x*quad_*x/2 + lin*x + const_term;
   // it's no use.
 
   Vector last_gradient (gradient);
   int iterations=0;
-  
-  while (iterations++ < MAXITER) 
+
+  while (iterations++ < MAXITER)
     {
+      //#ifdef PARANOID
+      if (experimental_features_global_b)
+       assert_solution (x);
+      //#endif
+      
       Vector direction= - act.find_active_optimum (gradient);
-       
+
       DOUT << "gradient "<< gradient<< "\ndirection " << direction<<"\n";
-       
-      if (direction.norm() > EPS) 
+
+      if (direction.norm() > EPS)
        {
          DOUT << act.status() << '\n';
-           
-         Real minalf = infinity_f;
+
+         Real unbounded_alfa = 1.0;
+         Real minalf = unbounded_alfa;
 
          Inactive_iter minidx (act);
 
@@ -146,32 +150,44 @@ Ineq_constrained_qp::constraint_solve (Vector start) const
            we know the optimum on this "hyperplane". Check if we
            bump into the edges of the simplex
            */
-  
-         for (Inactive_iter ia (act); ia.ok(); ia++) 
-           {
 
-             if (ia.vec() * direction >= 0)
+         for (Inactive_iter ia (act); ia.ok(); ia++)
+           {
+             Real dot = ia.vec() * direction;
+             if (dot >= 0)
                continue;
-             Real alfa= - (ia.vec()*x - ia.rhs ())/
-               (ia.vec()*direction);
-               
-             if (minalf > alfa) 
+
+             
+             Real numerator = ia.rhs () - ia.vec()*x;
+             if (numerator >= 0)
+               {
+                 if (numerator > EPS)
+                   warning (String ("Ineq_constrained_qp::solve (): Constraint off by ") + numerator);
+                 minalf = -numerator;
+                 minidx = ia;
+                 break;
+               }
+
+             Real alfa = numerator / dot;
+
+
+             if (minalf > alfa)
                {
                  minidx = ia;
                  minalf = alfa;
                }
            }
-         Real unbounded_alfa = 1.0;
-         Real optimal_step = min (minalf, unbounded_alfa);
+
+         Real optimal_step = minalf;
 
          Vector deltax=direction * optimal_step;
-         x += deltax;      
-         gradient += optimal_step * (quad * deltax);
-           
+         x += deltax;
+         gradient += optimal_step * (quad_ * deltax);
+
          DOUT << "step = " << optimal_step<< " (|dx| = " <<
-           deltax.norm() << ")\n";         
-          
-         if (minalf < unbounded_alfa) 
+           deltax.norm() << ")\n";
+
+         if (minalf < unbounded_alfa)
            {
              /* bumped into an edge. try again, in smaller space. */
              act.add (minidx.idx());
@@ -179,47 +195,54 @@ Ineq_constrained_qp::constraint_solve (Vector start) const
              continue;
            }
          /*ASSERT: we are at optimal solution for this "plane"*/
-  
-  
+
+
        }
-       
-      Vector lagrange_mult=act.get_lagrange (gradient);        
+
+      Vector lagrange_mult=act.get_lagrange (gradient);
       int m= min_elt_index (lagrange_mult);
-       
-      if (m>=0 && lagrange_mult (m) > 0) 
+
+      if (m>=0 && lagrange_mult (m) > 0)
        {
          break;                // optimal sol.
        }
-      else if (m<0) 
+      else if (m<0)
        {
          assert (gradient.norm() < EPS) ;
-           
+
          break;
        }
-       
+
       DOUT << "dropping cons " << m<<'\n';
       act.drop (m);
     }
   if (iterations >= MAXITER)
-    WARN<<"didn't converge!\n";
-  
+    WARN<<_("didn't converge!\n");
+
   DOUT <<  ": found " << x<<" in " << iterations <<" iterations\n";
   assert_solution (x);
   return x;
-} 
+}
+
 
-  
 Vector
 Ineq_constrained_qp::solve (Vector start) const
-{ 
+{
   /* no hassle if no constraints*/
-  if (! cons.size()) 
+  if (! cons_.size())
     {
-      Choleski_decomposition chol (quad);
-      return - chol.solve (lin);
+      Choleski_decomposition chol (quad_);
+      return - chol.solve (lin_);
     }
-  else 
+  else
     {
       return constraint_solve (start);
     }
 }
+
+int
+Ineq_constrained_qp::dim () const
+{
+  return lin_.dim();
+}
+