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


gtsam
Author(s):
autogenerated on Sun Dec 22 2024 04:12:24