[PPL-devel] [GIT] ppl/ppl(pip): Add new friend function add_mul_assign() for Linear_Expression.

Enea Zaffanella zaffanella at cs.unipr.it
Fri Feb 5 16:01:16 CET 2010


Module: ppl/ppl
Branch: pip
Commit: be3472f9d7b15cb7b31834a6f4e23a6fdd8bcf68
URL:    http://www.cs.unipr.it/git/gitweb.cgi?p=ppl/ppl.git;a=commit;h=be3472f9d7b15cb7b31834a6f4e23a6fdd8bcf68

Author: Enea Zaffanella <zaffanella at cs.unipr.it>
Date:   Fri Feb  5 15:59:56 2010 +0100

Add new friend function add_mul_assign() for Linear_Expression.
Used new function to optimize a couple of computations in PIP_Tree.cc.

---

 src/Linear_Expression.cc      |   19 ++++++++++++++++++
 src/Linear_Expression.defs.hh |   10 +++++++++
 src/PIP_Tree.cc               |   42 ++++++++++++++++++++++++++--------------
 3 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/src/Linear_Expression.cc b/src/Linear_Expression.cc
index 4ffc709..f7d50a3 100644
--- a/src/Linear_Expression.cc
+++ b/src/Linear_Expression.cc
@@ -354,6 +354,25 @@ PPL::operator*=(Linear_Expression& e, Coefficient_traits::const_reference n) {
   return e;
 }
 
+/*! \relates Parma_Polyhedra_Library::Linear_Expression */
+PPL::Linear_Expression&
+PPL::add_mul_assign(Linear_Expression& e,
+                    Coefficient_traits::const_reference n,
+                    const Variable v) {
+  const dimension_type v_space_dim = v.space_dimension();
+  if (v_space_dim > Linear_Expression::max_space_dimension())
+    throw std::length_error("Linear_Expression& "
+                            "PPL::add_mul_assign(e, n, v):\n"
+			    "v exceeds the maximum allowed space dimension.");
+  const dimension_type e_size = e.size();
+  if (e_size <= v_space_dim) {
+    Linear_Expression new_e(e, v_space_dim+1);
+    e.swap(new_e);
+  }
+  e[v_space_dim] += n;
+  return e;
+}
+
 bool
 PPL::Linear_Expression::OK() const {
   return Linear_Row::OK();
diff --git a/src/Linear_Expression.defs.hh b/src/Linear_Expression.defs.hh
index 2367c94..b4ce1e0 100644
--- a/src/Linear_Expression.defs.hh
+++ b/src/Linear_Expression.defs.hh
@@ -166,6 +166,12 @@ operator-=(Linear_Expression& e, Coefficient_traits::const_reference n);
 Linear_Expression&
 operator*=(Linear_Expression& e, Coefficient_traits::const_reference n);
 
+//! Returns the linear expression \p e + \p n * \p v and assigns it to \p e.
+/*! \relates Linear_Expression */
+Linear_Expression&
+add_mul_assign(Linear_Expression& e,
+               Coefficient_traits::const_reference n, Variable v);
+
 namespace IO_Operators {
 
 //! Output operator.
@@ -451,6 +457,10 @@ private:
   friend Linear_Expression&
   operator*=(Linear_Expression& e, Coefficient_traits::const_reference n);
 
+  friend Linear_Expression&
+  add_mul_assign(Linear_Expression& e,
+                 Coefficient_traits::const_reference n, Variable v);
+
   friend std::ostream&
   Parma_Polyhedra_Library::IO_Operators
   ::operator<<(std::ostream& s, const Linear_Expression& e);
diff --git a/src/PIP_Tree.cc b/src/PIP_Tree.cc
index c007c25..cb62db1 100644
--- a/src/PIP_Tree.cc
+++ b/src/PIP_Tree.cc
@@ -518,15 +518,21 @@ PIP_Tree_Node::OK() const {
 void
 PIP_Tree_Node
 ::add_constraint(const Row& row, const Variables_Set& parameters) {
-  const Variables_Set::const_iterator p_begin = parameters.begin();
-  const Variables_Set::const_iterator p_end = parameters.end();
-  PPL_ASSERT(static_cast<dimension_type>(std::distance(p_begin, p_end)) + 1
-             == row.size());
-  // FIXME: optimize the computation of expr.
+  const dimension_type num_params = parameters.size();
+  PPL_ASSERT(num_params + 1 == row.size());
+
+  // Compute the expression for the parameter constraint.
   Linear_Expression expr = Linear_Expression(row[0]);
-  dimension_type j = 1;
-  for (Variables_Set::const_iterator pj = p_begin; pj != p_end; ++pj, ++j)
-    expr += row[j] * Variable(*pj);
+  // NOTE: iterating downward on parameters to avoid reallocations.
+  Variables_Set::const_reverse_iterator p_j = parameters.rbegin();
+  // NOTE: index j spans [1..num_params] downwards.
+  for (dimension_type j = num_params; j > 0; --j) {
+    add_mul_assign(expr, row[j], Variable(*p_j));
+    // Move to previous parameter.
+    ++p_j;
+  }
+
+  // Add the parameter constraint.
   constraints_.insert(expr >= 0);
 }
 
@@ -1723,8 +1729,6 @@ PIP_Solution_Node::solve(const PIP_Problem& problem,
       }
 
       // Compute columns t[*][j] :
-      // t[i][j] -= t[i][pj] * t_pivot[j] / s_pivot_pj;
-      // ENEA: FIXME: according to code below, this comment should read:
       // t[i][j] -= s[i][pj] * t_pivot[j] / s_pivot_pj;
       for (dimension_type j = num_params; j-- > 0; ) {
         const Coefficient& t_pivot_j = t_pivot[j];
@@ -2094,6 +2098,7 @@ PIP_Solution_Node::generate_cut(const dimension_type index,
   const Coefficient& den = tableau.get_denominator();
 
   PPL_DIRTY_TEMP_COEFFICIENT(mod);
+  PPL_DIRTY_TEMP_COEFFICIENT(coeff);
 
 #ifdef NOISY_PIP
   std::cout << "Row " << index << " contains non-integer coefficients. "
@@ -2125,15 +2130,22 @@ PIP_Solution_Node::generate_cut(const dimension_type index,
     mod_assign(mod, row_t[0], den);
     Linear_Expression expr;
     if (mod != 0) {
+      // Optimizing computation: expr += (den - mod);
       expr += den;
       expr -= mod;
     }
-    Variables_Set::const_iterator p = parameters.begin();
-    for (dimension_type j = 1; j < num_params; ++j, ++p) {
+    // NOTE: iterating downwards on parameters to avoid reallocations.
+    Variables_Set::const_reverse_iterator p_j = parameters.rbegin();
+    // NOTE: index j spans [1..num_params-1] downwards.
+    for (dimension_type j = num_params; j-- > 1; ) {
       mod_assign(mod, row_t[j], den);
-      // FIXME: find a way to optimize the following.
-      if (mod != 0)
-        expr += (den - mod) * Variable(*p);
+      if (mod != 0) {
+        // Optimizing computation: expr += (den - mod) * Variable(*p_j);
+        coeff = den - mod;
+        add_mul_assign(expr, coeff, Variable(*p_j));
+      }
+      // Mode to previous parameter.
+      ++p_j;
     }
     // Generate new artificial parameter.
     Artificial_Parameter ap(expr, den);




More information about the PPL-devel mailing list