CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
color_general.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_COLOR_GENERAL_HPP
2 # define CPPAD_LOCAL_COLOR_GENERAL_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 
15 # include <cppad/configure.hpp>
17 
18 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
19 /*!
20 \file color_general.hpp
21 Coloring algorithm for a general sparse matrix.
22 */
23 // --------------------------------------------------------------------------
24 /*!
25 Determine which rows of a general sparse matrix can be computed together;
26 i.e., do not have non-zero entries with the same column index.
27 
28 \tparam VectorSize
29 is a simple vector class with elements of type size_t.
30 
31 \tparam VectorSet
32 is vector_of_sets class.
33 
34 \param pattern [in]
35 Is a representation of the sparsity pattern for the matrix.
36 
37 \param row [in]
38 is a vector specifying which row indices to compute.
39 
40 \param col [in]
41 is a vector, with the same size as row,
42 that specifies which column indices to compute.
43 For each valid index k, the index pair
44 <code>(row[k], col[k])</code> must be present in the sparsity pattern.
45 It may be that some entries in the sparsity pattern do not need to be computed;
46 i.e, do not appear in the set of
47 <code>(row[k], col[k])</code> entries.
48 
49 \param color [out]
50 is a vector with size m.
51 The input value of its elements does not matter.
52 Upon return, it is a coloring for the rows of the sparse matrix.
53 \n
54 \n
55 If for some i, <code>color[i] == m</code>, then
56 the i-th row does not appear in the vector row.
57 Otherwise, <code>color[i] < m</code>.
58 \n
59 \n
60 Suppose two differen rows, <code>i != r</code> have the same color and
61 column index j is such that both of the pairs
62 <code>(i, j)</code> and <code>(r, j)</code> appear in the sparsity pattern.
63 It follows that neither of these pairs appear in the set of
64 <code>(row[k], col[k])</code> entries.
65 \n
66 \n
67 This routine tries to minimize, with respect to the choice of colors,
68 the maximum, with respct to k, of <code>color[ row[k] ]</code>
69 (not counting the indices k for which row[k] == m).
70 */
71 template <class VectorSet, class VectorSize>
73  const VectorSet& pattern ,
74  const VectorSize& row ,
75  const VectorSize& col ,
76  CppAD::vector<size_t>& color )
77 {
78  size_t K = row.size();
79  size_t m = pattern.n_set();
80  size_t n = pattern.end();
81 
82  CPPAD_ASSERT_UNKNOWN( size_t( col.size() ) == K );
83  CPPAD_ASSERT_UNKNOWN( size_t( color.size() ) == m );
84 
85  // We define the set of rows, columns, and pairs that appear
86  // by the set ( row[k], col[k] ) for k = 0, ... , K-1.
87 
88  // initialize rows that appear
89  CppAD::vector<bool> row_appear(m);
90  for(size_t i = 0; i < m; i++)
91  row_appear[i] = false;
92 
93  // rows and columns that appear
94  VectorSet c2r_appear, r2c_appear;
95  c2r_appear.resize(n, m);
96  r2c_appear.resize(m, n);
97  for(size_t k = 0; k < K; k++)
98  { CPPAD_ASSERT_UNKNOWN( pattern.is_element(row[k], col[k]) );
99  row_appear[ row[k] ] = true;
100  c2r_appear.post_element(col[k], row[k]);
101  r2c_appear.post_element(row[k], col[k]);
102  }
103  // process posts
104  for(size_t j = 0; j < n; ++j)
105  c2r_appear.process_post(j);
106  for(size_t i = 0; i < m; ++i)
107  r2c_appear.process_post(i);
108 
109  // for each column, which rows are non-zero and do not appear
110  VectorSet not_appear;
111  not_appear.resize(n, m);
112  for(size_t i = 0; i < m; i++)
113  { typename VectorSet::const_iterator pattern_itr(pattern, i);
114  size_t j = *pattern_itr;
115  while( j != pattern.end() )
116  { if( ! c2r_appear.is_element(j , i) )
117  not_appear.post_element(j, i);
118  j = *(++pattern_itr);
119  }
120  }
121  // process posts
122  for(size_t j = 0; j < n; ++j)
123  not_appear.process_post(j);
124 
125  // initial coloring
126  color.resize(m);
127  size_t ell = 0;
128  for(size_t i = 0; i < m; i++)
129  { if( row_appear[i] )
130  color[i] = ell++;
131  else color[i] = m;
132  }
133  /*
134  See GreedyPartialD2Coloring Algorithm Section 3.6.2 of
135  Graph Coloring in Optimization Revisited by
136  Assefaw Gebremedhin, Fredrik Maane, Alex Pothen
137 
138  The algorithm above was modified (by Brad Bell) to take advantage of the
139  fact that only the entries (subset of the sparsity pattern) specified by
140  row and col need to be computed.
141  */
142  CppAD::vector<bool> forbidden(m);
143  for(size_t i = 1; i < m; i++) // for each row that appears
144  if( color[i] < m )
145  {
146  // initial all colors as ok for this row
147  // (value of forbidden for ell > initial color[i] does not matter)
148  for(ell = 0; ell <= color[i]; ell++)
149  forbidden[ell] = false;
150 
151  // -----------------------------------------------------
152  // Forbid colors for which this row would destroy results:
153  //
154  // for each column that is non-zero for this row
155  typename VectorSet::const_iterator pattern_itr(pattern, i);
156  size_t j = *pattern_itr;
157  while( j != pattern.end() )
158  { // for each row that appears with this column
159  typename VectorSet::const_iterator c2r_itr(c2r_appear, j);
160  size_t r = *c2r_itr;
161  while( r != c2r_appear.end() )
162  { // if this is not the same row, forbid its color
163  if( (r < i) & (color[r] < m) )
164  forbidden[ color[r] ] = true;
165  r = *(++c2r_itr);
166  }
167  j = *(++pattern_itr);
168  }
169 
170 
171  // -----------------------------------------------------
172  // Forbid colors that destroy results needed for this row.
173  //
174  // for each column that appears with this row
175  typename VectorSet::const_iterator r2c_itr(r2c_appear, i);
176  j = *r2c_itr;
177  while( j != r2c_appear.end() )
178  { // For each row that is non-zero for this column
179  // (the appear rows have already been checked above).
180  typename VectorSet::const_iterator not_itr(not_appear, j);
181  size_t r = *not_itr;
182  while( r != not_appear.end() )
183  { // if this is not the same row, forbid its color
184  if( (r < i) & (color[r] < m) )
185  forbidden[ color[r] ] = true;
186  r = *(++not_itr);
187  }
188  j = *(++r2c_itr);
189  }
190 
191  // pick the color with smallest index
192  ell = 0;
193  while( forbidden[ell] )
194  { ell++;
195  CPPAD_ASSERT_UNKNOWN( ell <= color[i] );
196  }
197  color[i] = ell;
198  }
199  return;
200 }
201 
202 # if CPPAD_HAS_COLPACK
203 /*!
204 Colpack version of determining which rows of a sparse matrix
205 can be computed together.
206 
207 \copydetails color_general
208 */
209 template <class VectorSet, class VectorSize>
210 void color_general_colpack(
211  const VectorSet& pattern ,
212  const VectorSize& row ,
213  const VectorSize& col ,
214  CppAD::vector<size_t>& color )
215 {
216  size_t m = pattern.n_set();
217  size_t n = pattern.end();
218 
219  // Determine number of non-zero entries in each row
220  CppAD::vector<size_t> n_nonzero(m);
221  size_t n_nonzero_total = 0;
222  for(size_t i = 0; i < m; i++)
223  { n_nonzero[i] = 0;
224  typename VectorSet::const_iterator pattern_itr(pattern, i);
225  size_t j = *pattern_itr;
226  while( j != pattern.end() )
227  { n_nonzero[i]++;
228  j = *(++pattern_itr);
229  }
230  n_nonzero_total += n_nonzero[i];
231  }
232 
233  // Allocate memory and fill in Adolc sparsity pattern
234  CppAD::vector<unsigned int*> adolc_pattern(m);
235  CppAD::vector<unsigned int> adolc_memory(m + n_nonzero_total);
236  size_t i_memory = 0;
237  for(size_t i = 0; i < m; i++)
238  { adolc_pattern[i] = adolc_memory.data() + i_memory;
240  std::numeric_limits<unsigned int>::max() >= n_nonzero[i],
241  "Matrix is too large for colpack"
242  );
243  adolc_pattern[i][0] = static_cast<unsigned int>( n_nonzero[i] );
244  typename VectorSet::const_iterator pattern_itr(pattern, i);
245  size_t j = *pattern_itr;
246  size_t k = 1;
247  while(j != pattern.end() )
248  {
250  std::numeric_limits<unsigned int>::max() >= j,
251  "Matrix is too large for colpack"
252  );
253  adolc_pattern[i][k++] = static_cast<unsigned int>( j );
254  j = *(++pattern_itr);
255  }
256  CPPAD_ASSERT_UNKNOWN( k == 1 + n_nonzero[i] );
257  i_memory += k;
258  }
259  CPPAD_ASSERT_UNKNOWN( i_memory == m + n_nonzero_total );
260 
261  // Must use an external routine for this part of the calculation because
262  // ColPack/ColPackHeaders.h has as 'using namespace std' at global level.
263  cppad_colpack_general(color, m, n, adolc_pattern);
264 
265  return;
266 }
267 # endif // CPPAD_HAS_COLPACK
268 
269 } } // END_CPPAD_LOCAL_NAMESPACE
270 # endif
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
void color_general_cppad(const VectorSet &pattern, const VectorSize &row, const VectorSize &col, CppAD::vector< size_t > &color)
Determine which rows of a general sparse matrix can be computed together; i.e., do not have non-zero ...
void resize(size_t n)
change the number of elements in this vector.
Definition: vector.hpp:399
size_t size(void) const
number of elements currently in this vector.
Definition: vector.hpp:387
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.