VectorValues.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 
20 
21 #include <functional>
22 #include <utility>
23 
24 // assert_throw needs a semicolon in Release mode.
25 #pragma clang diagnostic push
26 #pragma clang diagnostic ignored "-Wextra-semi-stmt"
27 
28 namespace gtsam {
29 
30  /* ************************************************************************ */
32  {
33  // Merge using predicate for comparing first of pair
34  merge(first.begin(), first.end(), second.begin(), second.end(), inserter(values_, values_.end()),
35  std::bind(&std::less<Key>::operator(), std::less<Key>(), std::bind(&KeyValuePair::first, std::placeholders::_1),
36  std::bind(&KeyValuePair::first, std::placeholders::_2)));
37  if(size() != first.size() + second.size())
38  throw std::invalid_argument("Requested to merge two VectorValues that have one or more variables in common.");
39  }
40 
41  /* ************************************************************************ */
42  VectorValues::VectorValues(const Vector& x, const Dims& dims) {
43  size_t j = 0;
44  for (const auto& [key, n] : dims) {
45 #ifdef TBB_GREATER_EQUAL_2020
46  values_.emplace(key, x.segment(j, n));
47 #else
48  values_.insert({key, x.segment(j, n)});
49 #endif
50  j += n;
51  }
52  }
53 
54  /* ************************************************************************ */
55  VectorValues::VectorValues(const Vector& x, const Scatter& scatter) {
56  size_t j = 0;
57  for (const SlotEntry& v : scatter) {
58 #ifdef TBB_GREATER_EQUAL_2020
59  values_.emplace(v.key, x.segment(j, v.dimension));
60 #else
61  values_.insert({v.key, x.segment(j, v.dimension)});
62 #endif
63  j += v.dimension;
64  }
65  }
66 
67  /* ************************************************************************ */
69  {
71  for (const auto& [key, value] : other)
72 #ifdef TBB_GREATER_EQUAL_2020
73  result.values_.emplace(key, Vector::Zero(value.size()));
74 #else
75  result.values_.insert({key, Vector::Zero(value.size())});
76 #endif
77  return result;
78  }
79 
80  /* ************************************************************************ */
81  VectorValues::iterator VectorValues::insert(const std::pair<Key, Vector>& key_value) {
82  const std::pair<iterator, bool> result = values_.insert(key_value);
83  if(!result.second)
84  throw std::invalid_argument(
85  "Requested to insert variable '" + DefaultKeyFormatter(key_value.first)
86  + "' already in this VectorValues.");
87  return result.first;
88  }
89 
90  /* ************************************************************************ */
92  iterator hint = begin();
93  for (const auto& [key, value] : values) {
94  // Use this trick to find the value using a hint, since we are inserting
95  // from another sorted map
96  size_t oldSize = values_.size();
97  hint = values_.insert(hint, {key, value});
98  if (values_.size() > oldSize) {
99  values_.unsafe_erase(hint);
100  throw std::out_of_range(
101  "Requested to update a VectorValues with another VectorValues that "
102  "contains keys not present in the first.");
103  } else {
104  hint->second = value;
105  }
106  }
107  return *this;
108  }
109 
110  /* ************************************************************************ */
112  size_t originalSize = size();
113  values_.insert(values.begin(), values.end());
114  if (size() != originalSize + values.size())
115  throw std::invalid_argument(
116  "Requested to insert a VectorValues into another VectorValues that "
117  "already contains one or more of its keys.");
118  return *this;
119  }
120 
121  /* ************************************************************************ */
123  {
124  for(auto& [key, value] : *this) {
125  value.setZero();
126  }
127  }
128 
129  /* ************************************************************************ */
130  GTSAM_EXPORT std::ostream& operator<<(std::ostream& os, const VectorValues& v) {
131  // Change print depending on whether we are using TBB
132 #ifdef GTSAM_USE_TBB
133  std::map<Key, Vector> sorted;
134  for (const auto& [key, value] : v) {
135  sorted.emplace(key, value);
136  }
137  for (const auto& [key, value] : sorted)
138 #else
139  for (const auto& [key,value] : v)
140 #endif
141  {
142  os << " " << StreamedKey(key) << ": " << value.transpose() << "\n";
143  }
144  return os;
145  }
146 
147  /* ************************************************************************ */
148  void VectorValues::print(const std::string& str,
149  const KeyFormatter& formatter) const {
150  std::cout << str << ": " << size() << " elements\n";
151  std::cout << key_formatter(formatter) << *this;
152  std::cout.flush();
153 }
154 
155  /* ************************************************************************ */
156  bool VectorValues::equals(const VectorValues& x, double tol) const {
157  if(this->size() != x.size())
158  return false;
159  auto this_it = this->begin();
160  auto x_it = x.begin();
161  for(; this_it != this->end(); ++this_it, ++x_it) {
162  if(this_it->first != x_it->first ||
163  !equal_with_abs_tol(this_it->second, x_it->second, tol))
164  return false;
165  }
166  return true;
167  }
168 
169  /* ************************************************************************ */
171  // Count dimensions
172  DenseIndex totalDim = 0;
173  for (const auto& [key, value] : *this)
174  totalDim += value.size();
175 
176  // Copy vectors
177  Vector result(totalDim);
178  DenseIndex pos = 0;
179  for (const auto& [key, value] : *this) {
180  result.segment(pos, value.size()) = value;
181  pos += value.size();
182  }
183 
184  return result;
185  }
186 
187  /* ************************************************************************ */
189  {
190  // Count dimensions
191  DenseIndex totalDim = 0;
192  for (const auto& [key, dim] : keys)
193  totalDim += dim;
194  Vector result(totalDim);
195  size_t j = 0;
196  for(const Dims::value_type& it: keys) {
197  result.segment(j,it.second) = at(it.first);
198  j += it.second;
199  }
200  return result;
201  }
202 
203  /* ************************************************************************ */
205  this->values_.swap(other.values_);
206  }
207 
208  /* ************************************************************************ */
209  namespace internal
210  {
212  {
213  return a.first == b.first && a.second.size() == b.second.size();
214  }
215  }
216 
217  /* ************************************************************************ */
219  {
220  // compare the "other" container with this one, using the structureCompareOp
221  // and then return true if all elements are compared as equal
222  return std::equal(this->begin(), this->end(), other.begin(), other.end(),
224  }
225 
226  /* ************************************************************************ */
227  double VectorValues::dot(const VectorValues& v) const
228  {
229  if(this->size() != v.size())
230  throw std::invalid_argument("VectorValues::dot called with a VectorValues of different structure");
231  double result = 0.0;
232  auto this_it = this->begin();
233  auto v_it = v.begin();
234  for(; this_it != this->end(); ++this_it, ++v_it) {
235  assert_throw(this_it->first == v_it->first,
236  std::invalid_argument("VectorValues::dot called with a VectorValues of different structure"));
237  assert_throw(this_it->second.size() == v_it->second.size(),
238  std::invalid_argument("VectorValues::dot called with a VectorValues of different structure"));
239  result += this_it->second.dot(v_it->second);
240  }
241  return result;
242  }
243 
244  /* ************************************************************************ */
245  double VectorValues::norm() const {
246  return std::sqrt(this->squaredNorm());
247  }
248 
249  /* ************************************************************************ */
250  double VectorValues::squaredNorm() const {
251  double sumSquares = 0.0;
252  for(const auto& [key, value]: *this) {
253  sumSquares += value.squaredNorm();
254  }
255  return sumSquares;
256  }
257 
258  /* ************************************************************************ */
260  {
261  if(this->size() != c.size())
262  throw std::invalid_argument("VectorValues::operator+ called with different vector sizes");
264  std::invalid_argument("VectorValues::operator+ called with different vector sizes"));
265 
267  // The result.end() hint here should result in constant-time inserts
268  for(const_iterator j1 = begin(), j2 = c.begin(); j1 != end(); ++j1, ++j2)
269 #ifdef TBB_GREATER_EQUAL_2020
270  result.values_.emplace(j1->first, j1->second + j2->second);
271 #else
272  result.values_.insert({j1->first, j1->second + j2->second});
273 #endif
274 
275  return result;
276  }
277 
278  /* ************************************************************************ */
280  {
281  return *this + c;
282  }
283 
284  /* ************************************************************************ */
286  {
287  if(this->size() != c.size())
288  throw std::invalid_argument("VectorValues::operator+= called with different vector sizes");
290  std::invalid_argument("VectorValues::operator+= called with different vector sizes"));
291 
292  iterator j1 = begin();
293  const_iterator j2 = c.begin();
294  // The result.end() hint here should result in constant-time inserts
295  for(; j1 != end(); ++j1, ++j2)
296  j1->second += j2->second;
297 
298  return *this;
299  }
300 
301  /* ************************************************************************ */
303  {
304  return *this += c;
305  }
306 
307  /* ************************************************************************ */
309  {
310  for(const_iterator j2 = c.begin(); j2 != c.end(); ++j2) {
311  const auto& [it, success] = tryInsert(j2->first, Vector());
312  if(success)
313  it->second = j2->second;
314  else
315  it->second += j2->second;
316  }
317  return *this;
318  }
319 
320  /* ************************************************************************ */
322  {
323  if(this->size() != c.size())
324  throw std::invalid_argument("VectorValues::operator- called with different vector sizes");
326  std::invalid_argument("VectorValues::operator- called with different vector sizes"));
327 
329  // The result.end() hint here should result in constant-time inserts
330  for(const_iterator j1 = begin(), j2 = c.begin(); j1 != end(); ++j1, ++j2)
331 #ifdef TBB_GREATER_EQUAL_2020
332  result.values_.emplace(j1->first, j1->second - j2->second);
333 #else
334  result.values_.insert({j1->first, j1->second - j2->second});
335 #endif
336 
337  return result;
338  }
339 
340  /* ************************************************************************ */
342  {
343  return *this - c;
344  }
345 
346  /* ************************************************************************ */
347  VectorValues operator*(const double a, const VectorValues& c) {
349  for (const auto& [key, value] : c)
350 #ifdef TBB_GREATER_EQUAL_2020
351  result.values_.emplace(key, a * value);
352 #else
353  result.values_.insert({key, a * value});
354 #endif
355  return result;
356  }
357 
358  /* ************************************************************************ */
359  VectorValues VectorValues::scale(const double a) const
360  {
361  return a * *this;
362  }
363 
364  /* ************************************************************************ */
366  {
367  for (auto& [key, value]: *this) {
368  value *= alpha;
369  }
370  return *this;
371  }
372 
373  /* ************************************************************************ */
375  {
376  return *this *= alpha;
377  }
378 
379  /* ************************************************************************ */
380  std::string VectorValues::html(const KeyFormatter& keyFormatter) const {
381  std::stringstream ss;
382 
383  // Print out preamble.
384  ss << "<div>\n<table class='VectorValues'>\n <thead>\n";
385 
386  // Print out header row.
387  ss << " <tr><th>Variable</th><th>value</th></tr>\n";
388 
389  // Finish header and start body.
390  ss << " </thead>\n <tbody>\n";
391 
392  // Print out all rows.
393 #ifdef GTSAM_USE_TBB
394  // TBB uses un-ordered map, so inefficiently order them:
395  std::map<Key, Vector> ordered;
396  for (const auto& kv : *this) ordered.emplace(kv);
397  for (const auto& kv : ordered) {
398 #else
399  for (const auto& kv : *this) {
400 #endif
401  ss << " <tr>";
402  ss << "<th>" << keyFormatter(kv.first) << "</th><td>"
403  << kv.second.transpose() << "</td>";
404  ss << "</tr>\n";
405  }
406  ss << " </tbody>\n</table>\n</div>";
407  return ss.str();
408  }
409 
410  /* ************************************************************************ */
411 
412 } // \namespace gtsam
413 
414 #pragma clang diagnostic pop
415 
const gtsam::Symbol key('X', 0)
One SlotEntry stores the slot index for a variable, as well its dim.
Definition: Scatter.h:32
bool hasSameStructure(const VectorValues other) const
Values::iterator iterator
Iterator over vector values.
Definition: VectorValues.h:81
GTSAM_EXPORT friend std::ostream & operator<<(std::ostream &, const VectorValues &)
overload operator << to print to stringstream
VectorValues operator-(const VectorValues &c) const
void print(const std::string &str="VectorValues", const KeyFormatter &formatter=DefaultKeyFormatter) const
VectorValues & operator+=(const VectorValues &c)
int n
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
VectorValues & addInPlace(const VectorValues &c)
leaf::MyValues values
Values::value_type value_type
Typedef to pair<Key, Vector>
Definition: VectorValues.h:84
iterator insert(const std::pair< Key, Vector > &key_value)
iterator end()
Iterator over variables.
Definition: VectorValues.h:238
bool structureCompareOp(const VectorValues::value_type &a, const VectorValues::value_type &b)
VectorValues & addInPlace_(const VectorValues &c)
std::map< Key, size_t > Dims
Keyed vector dimensions.
Definition: VectorValues.h:86
EIGEN_CONSTEXPR Index first(const T &x) EIGEN_NOEXCEPT
Vector & at(Key j)
Definition: VectorValues.h:139
static const KeyFormatter DefaultKeyFormatter
Definition: Key.h:43
ptrdiff_t DenseIndex
The index type for Eigen objects.
Definition: types.h:108
const KeyFormatter & formatter
std::pair< iterator, bool > tryInsert(Key j, const Vector &value)
Definition: VectorValues.h:209
VectorValues scale(const double a) const
Factor Graph Values.
bool equals(const VectorValues &x, double tol=1e-9) const
Eigen::VectorXd Vector
Definition: Vector.h:38
Values result
VectorValues()
Default constructor creates an empty VectorValues.
Definition: VectorValues.h:92
VectorValues subtract(const VectorValues &c) const
Definition: pytypes.h:1403
static VectorValues Zero(const VectorValues &other)
Array< int, Dynamic, 1 > v
size_t dim(Key j) const
Definition: VectorValues.h:130
Values values_
Vectors making up this VectorValues.
Definition: VectorValues.h:78
To use the key_formatter on Keys, they must be wrapped in a StreamedKey.
Definition: Key.h:58
RealScalar alpha
VectorValues add(const VectorValues &c) const
VectorValues & scaleInPlace(double alpha)
Values::const_iterator const_iterator
Const iterator over vector values.
Definition: VectorValues.h:82
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
const G & b
Definition: Group.h:86
static std::stringstream ss
Definition: testBTree.cpp:31
bool equal_with_abs_tol(const Eigen::DenseBase< MATRIX > &A, const Eigen::DenseBase< MATRIX > &B, double tol=1e-9)
Definition: base/Matrix.h:80
traits
Definition: chartTesting.h:28
double squaredNorm() const
void swap(VectorValues &other)
void unsafe_erase(typename Base::iterator position)
Definition: ConcurrentMap.h:94
double dot(const VectorValues &v) const
ofstream os("timeSchurFactors.csv")
VectorValues & operator*=(double alpha)
VectorValues operator+(const VectorValues &c) const
double norm() const
std::string html(const KeyFormatter &keyFormatter=DefaultKeyFormatter) const
Output as a html table.
Vector vector() const
size_t size() const
Definition: VectorValues.h:127
friend GTSAM_EXPORT VectorValues operator*(const double a, const VectorValues &v)
VectorValues & update(const VectorValues &values)
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
const G double tol
Definition: Group.h:86
const KeyVector keys
#define assert_throw(CONDITION, EXCEPTION)
Definition: types.h:201
bool equal(const T &obj1, const T &obj2, double tol)
Definition: Testable.h:85
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
iterator begin()
Iterator over variables.
Definition: VectorValues.h:236
std::ptrdiff_t j


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:40:43