Ordering.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
19 #include <vector>
20 #include <limits>
21 
24 
25 #ifdef GTSAM_SUPPORT_NESTED_DISSECTION
26 #include <metis.h>
27 #endif
28 
29 using namespace std;
30 
31 namespace gtsam {
32 
33 /* ************************************************************************* */
34 FastMap<Key, size_t> Ordering::invert() const {
35  FastMap<Key, size_t> inverted;
36  for (size_t pos = 0; pos < this->size(); ++pos)
37  inverted.insert(make_pair((*this)[pos], pos));
38  return inverted;
39 }
40 
41 /* ************************************************************************* */
42 Ordering Ordering::Colamd(const VariableIndex& variableIndex) {
43  // Call constrained version with all groups set to zero
44  vector<int> dummy_groups(variableIndex.size(), 0);
45  return Ordering::ColamdConstrained(variableIndex, dummy_groups);
46 }
47 
48 /* ************************************************************************* */
49 Ordering Ordering::ColamdConstrained(const VariableIndex& variableIndex,
50  std::vector<int>& cmember) {
51  gttic(Ordering_COLAMDConstrained);
52 
53  gttic(Prepare);
54  const size_t nVars = variableIndex.size();
55  if (nVars == 0)
56  {
57  return Ordering();
58  }
59 
60  if (nVars == 1)
61  {
62  return Ordering(KeyVector(1, variableIndex.begin()->first));
63  }
64 
65  const size_t nEntries = variableIndex.nEntries(), nFactors =
66  variableIndex.nFactors();
67  // Convert to compressed column major format colamd wants it in (== MATLAB format!)
68  const size_t Alen = ccolamd_recommended((int) nEntries, (int) nFactors,
69  (int) nVars); /* colamd arg 3: size of the array A */
70  vector<int> A = vector<int>(Alen); /* colamd arg 4: row indices of A, of size Alen */
71  vector<int> p = vector<int>(nVars + 1); /* colamd arg 5: column pointers of A, of size n_col+1 */
72 
73  // Fill in input data for COLAMD
74  p[0] = 0;
75  int count = 0;
76  KeyVector keys(nVars); // Array to store the keys in the order we add them so we can retrieve them in permuted order
77  size_t index = 0;
78  for (auto key_factors: variableIndex) {
79  // Arrange factor indices into COLAMD format
80  const FactorIndices& column = key_factors.second;
81  for(size_t factorIndex: column) {
82  A[count++] = (int) factorIndex; // copy sparse column
83  }
84  p[index + 1] = count; // column j (base 1) goes from A[j-1] to A[j]-1
85  // Store key in array and increment index
86  keys[index] = key_factors.first;
87  ++index;
88  }
89 
90  assert((size_t)count == variableIndex.nEntries());
91 
92  //double* knobs = nullptr; /* colamd arg 6: parameters (uses defaults if nullptr) */
93  double knobs[CCOLAMD_KNOBS];
94  ccolamd_set_defaults(knobs);
95  knobs[CCOLAMD_DENSE_ROW] = -1;
96  knobs[CCOLAMD_DENSE_COL] = -1;
97 
98  int stats[CCOLAMD_STATS]; /* colamd arg 7: colamd output statistics and error codes */
99 
100  gttoc(Prepare);
101 
102  // call colamd, result will be in p
103  /* returns (1) if successful, (0) otherwise*/
104  if (nVars > 0) {
105  gttic(ccolamd);
106  int rv = ccolamd((int) nFactors, (int) nVars, (int) Alen, &A[0], &p[0],
107  knobs, stats, &cmember[0]);
108  if (rv != 1) {
109  throw runtime_error("ccolamd failed with return value " + to_string(rv));
110  }
111  }
112 
113  // ccolamd_report(stats);
114 
115  // Convert elimination ordering in p to an ordering
116  gttic(Fill_Ordering);
118  result.resize(nVars);
119  for (size_t j = 0; j < nVars; ++j)
120  result[j] = keys[p[j]];
121  gttoc(Fill_Ordering);
122 
123  return result;
124 }
125 
126 /* ************************************************************************* */
127 Ordering Ordering::ColamdConstrainedLast(const VariableIndex& variableIndex,
128  const KeyVector& constrainLast, bool forceOrder) {
129  gttic(Ordering_COLAMDConstrainedLast);
130 
131  size_t n = variableIndex.size();
132  std::vector<int> cmember(n, 0);
133 
134  // Build a mapping to look up sorted Key indices by Key
135  // TODO(frank): think of a way to not build this
136  FastMap<Key, size_t> keyIndices;
137  size_t j = 0;
138  for (auto key_factors: variableIndex)
139  keyIndices.insert(keyIndices.end(), make_pair(key_factors.first, j++));
140 
141  // If at least some variables are not constrained to be last, constrain the
142  // ones that should be constrained.
143  int group = (constrainLast.size() != n ? 1 : 0);
144  for (Key key: constrainLast) {
145  cmember[keyIndices.at(key)] = group;
146  if (forceOrder)
147  ++group;
148  }
149 
150  return Ordering::ColamdConstrained(variableIndex, cmember);
151 }
152 
153 /* ************************************************************************* */
154 Ordering Ordering::ColamdConstrainedFirst(const VariableIndex& variableIndex,
155  const KeyVector& constrainFirst, bool forceOrder) {
156  gttic(Ordering_COLAMDConstrainedFirst);
157 
158  const int none = -1;
159  size_t n = variableIndex.size();
160  std::vector<int> cmember(n, none);
161 
162  // Build a mapping to look up sorted Key indices by Key
163  FastMap<Key, size_t> keyIndices;
164  size_t j = 0;
165  for (auto key_factors: variableIndex)
166  keyIndices.insert(keyIndices.end(), make_pair(key_factors.first, j++));
167 
168  // If at least some variables are not constrained to be last, constrain the
169  // ones that should be constrained.
170  int group = 0;
171  for (Key key: constrainFirst) {
172  cmember[keyIndices.at(key)] = group;
173  if (forceOrder)
174  ++group;
175  }
176 
177  if (!forceOrder && !constrainFirst.empty())
178  ++group;
179  for(int& c: cmember)
180  if (c == none)
181  c = group;
182 
183  return Ordering::ColamdConstrained(variableIndex, cmember);
184 }
185 
186 /* ************************************************************************* */
187 Ordering Ordering::ColamdConstrained(const VariableIndex& variableIndex,
188  const FastMap<Key, int>& groups) {
189  gttic(Ordering_COLAMDConstrained);
190  size_t n = variableIndex.size();
191  std::vector<int> cmember(n, 0);
192 
193  // Build a mapping to look up sorted Key indices by Key
194  FastMap<Key, size_t> keyIndices;
195  size_t j = 0;
196  for (auto key_factors: variableIndex)
197  keyIndices.insert(keyIndices.end(), make_pair(key_factors.first, j++));
198 
199  // Assign groups
200  typedef FastMap<Key, int>::value_type key_group;
201  for(const key_group& p: groups) {
202  // FIXME: check that no groups are skipped
203  cmember[keyIndices.at(p.first)] = p.second;
204  }
205 
206  return Ordering::ColamdConstrained(variableIndex, cmember);
207 }
208 
209 /* ************************************************************************* */
210 Ordering Ordering::Metis(const MetisIndex& met) {
211 #ifdef GTSAM_SUPPORT_NESTED_DISSECTION
212  gttic(Ordering_METIS);
213 
214  idx_t size = met.nValues();
215  if (size == 0)
216  {
217  return Ordering();
218  }
219 
220  if (size == 1)
221  {
222  return Ordering(KeyVector(1, met.intToKey(0)));
223  }
224 
225  vector<idx_t> xadj = met.xadj();
226  vector<idx_t> adj = met.adj();
227  vector<idx_t> perm, iperm;
228 
229  for (idx_t i = 0; i < size; i++) {
230  perm.push_back(0);
231  iperm.push_back(0);
232  }
233 
234  int outputError;
235 
236  outputError = METIS_NodeND(&size, &xadj[0], &adj[0], nullptr, nullptr, &perm[0],
237  &iperm[0]);
239 
240  if (outputError != METIS_OK) {
241  std::cout << "METIS failed during Nested Dissection ordering!\n";
242  return result;
243  }
244 
245  result.resize(size);
246  for (size_t j = 0; j < (size_t) size; ++j) {
247  // We have to add the minKey value back to obtain the original key in the Values
248  result[j] = met.intToKey(perm[j]);
249  }
250  return result;
251 #else
252  throw runtime_error("GTSAM was built without support for Metis-based "
253  "nested dissection");
254 #endif
255 }
256 
257 /* ************************************************************************* */
258 void Ordering::print(const std::string& str,
259  const KeyFormatter& keyFormatter) const {
260  cout << str;
261  // Print ordering in index order
262  // Print the ordering with varsPerLine ordering entries printed on each line,
263  // for compactness.
264  static const size_t varsPerLine = 10;
265  bool endedOnNewline = false;
266  for (size_t i = 0; i < size(); ++i) {
267  if (i % varsPerLine == 0)
268  cout << "Position " << i << ": ";
269  if (i % varsPerLine != 0)
270  cout << ", ";
271  cout << keyFormatter(at(i));
272  if (i % varsPerLine == varsPerLine - 1) {
273  cout << "\n";
274  endedOnNewline = true;
275  } else {
276  endedOnNewline = false;
277  }
278  }
279  if (!endedOnNewline)
280  cout << "\n";
281  cout.flush();
282 }
283 
284 /* ************************************************************************* */
286  this->insert(this->end(), keys.begin(), keys.end());
287  return *this;
288 }
289 
290 /* ************************************************************************* */
291 bool Ordering::contains(const Key& key) const {
292  return std::find(this->begin(), this->end(), key) != this->end();
293 }
294 
295 /* ************************************************************************* */
296 bool Ordering::equals(const Ordering& other, double tol) const {
297  return (*this) == other;
298 }
299 
300 }
const gtsam::Symbol key('X', 0)
size_t ccolamd_recommended(int nnz, int n_row, int n_col)
A insert(1, 2)=0
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 & operator+=(bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:184
Key intToKey(int32_t value) const
Definition: MetisIndex.h:94
void ccolamd_set_defaults(double knobs [CCOLAMD_KNOBS])
size_t size() const
The number of variable entries. This is equal to the number of unique variable Keys.
Definition: VariableIndex.h:78
#define CCOLAMD_DENSE_ROW
Definition: ccolamd.h:63
idx_t idx_t * xadj
int n
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
size_t nEntries() const
The number of nonzero blocks, i.e. the number of variable-factor entries.
Definition: VariableIndex.h:84
Definition: BFloat16.h:88
const std::vector< int32_t > & adj() const
Definition: MetisIndex.h:88
EIGEN_STRONG_INLINE Packet4f print(const Packet4f &a)
size_t nFactors() const
The number of factors in the original factor graph.
Definition: VariableIndex.h:81
idx_t idx_t idx_t idx_t idx_t idx_t * iperm
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:48
Definition: pytypes.h:1614
bool stats
int METIS_NodeND(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, idx_t *options, idx_t *perm, idx_t *iperm)
Definition: ometis.c:43
const std::vector< int32_t > & xadj() const
Definition: MetisIndex.h:85
FastVector< FactorIndex > FactorIndices
Define collection types:
Definition: Factor.h:36
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
#define gttic(label)
Definition: timing.h:295
Values result
Definition: pytypes.h:1403
int32_t idx_t
idx_t idx_t idx_t idx_t idx_t * perm
std::function< std::string(Key)> KeyFormatter
Typedef for a function to format a key, i.e. to convert it to a string.
Definition: Key.h:35
#define CCOLAMD_DENSE_COL
Definition: ccolamd.h:66
const_iterator begin() const
Iterator to the first variable entry.
traits
Definition: chartTesting.h:28
size_t nValues() const
Definition: MetisIndex.h:91
#define gttoc(label)
Definition: timing.h:296
static EIGEN_DEPRECATED const end_t end
float * p
#define CCOLAMD_KNOBS
Definition: ccolamd.h:57
const G double tol
Definition: Group.h:86
const KeyVector keys
int ccolamd(int n_row, int n_col, int Alen, int A [], int p [], double knobs [CCOLAMD_KNOBS], int stats [CCOLAMD_STATS], int cmember [])
FastVector< Key > KeyVector
Define collection type once and for all - also used in wrappers.
Definition: Key.h:86
const MATRIX::ConstColXpr column(const MATRIX &A, size_t j)
Definition: base/Matrix.h:210
#define CCOLAMD_STATS
Definition: ccolamd.h:60
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:102
std::ptrdiff_t j


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:59