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->push_back(key);
287  return *this;
288 }
289 
290 /* ************************************************************************* */
292  this->push_back(key);
293  return *this;
294 }
295 
296 /* ************************************************************************* */
298  this->insert(this->end(), keys.begin(), keys.end());
299  return *this;
300 }
301 
302 /* ************************************************************************* */
303 bool Ordering::contains(const Key& key) const {
304  return std::find(this->begin(), this->end(), key) != this->end();
305 }
306 
307 /* ************************************************************************* */
308 bool Ordering::equals(const Ordering& other, double tol) const {
309  return (*this) == other;
310 }
311 
312 }
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:163
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 Sat Nov 16 2024 04:03:13