VectorValues html

release/4.3a0
Frank Dellaert 2022-02-09 16:01:45 -05:00
parent c34456268a
commit f2780481c4
4 changed files with 94 additions and 37 deletions

View File

@ -33,7 +33,7 @@ namespace gtsam {
using boost::adaptors::map_values; using boost::adaptors::map_values;
using boost::accumulate; using boost::accumulate;
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues::VectorValues(const VectorValues& first, const VectorValues& second) VectorValues::VectorValues(const VectorValues& first, const VectorValues& second)
{ {
// Merge using predicate for comparing first of pair // Merge using predicate for comparing first of pair
@ -44,7 +44,7 @@ namespace gtsam {
throw invalid_argument("Requested to merge two VectorValues that have one or more variables in common."); throw invalid_argument("Requested to merge two VectorValues that have one or more variables in common.");
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues::VectorValues(const Vector& x, const Dims& dims) { VectorValues::VectorValues(const Vector& x, const Dims& dims) {
using Pair = pair<const Key, size_t>; using Pair = pair<const Key, size_t>;
size_t j = 0; size_t j = 0;
@ -61,7 +61,7 @@ namespace gtsam {
} }
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues::VectorValues(const Vector& x, const Scatter& scatter) { VectorValues::VectorValues(const Vector& x, const Scatter& scatter) {
size_t j = 0; size_t j = 0;
for (const SlotEntry& v : scatter) { for (const SlotEntry& v : scatter) {
@ -74,7 +74,7 @@ namespace gtsam {
} }
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues VectorValues::Zero(const VectorValues& other) VectorValues VectorValues::Zero(const VectorValues& other)
{ {
VectorValues result; VectorValues result;
@ -87,7 +87,7 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues::iterator VectorValues::insert(const std::pair<Key, Vector>& key_value) { VectorValues::iterator VectorValues::insert(const std::pair<Key, Vector>& key_value) {
std::pair<iterator, bool> result = values_.insert(key_value); std::pair<iterator, bool> result = values_.insert(key_value);
if(!result.second) if(!result.second)
@ -97,7 +97,7 @@ namespace gtsam {
return result.first; return result.first;
} }
/* ************************************************************************* */ /* ************************************************************************ */
void VectorValues::update(const VectorValues& values) void VectorValues::update(const VectorValues& values)
{ {
iterator hint = begin(); iterator hint = begin();
@ -115,7 +115,7 @@ namespace gtsam {
} }
} }
/* ************************************************************************* */ /* ************************************************************************ */
void VectorValues::insert(const VectorValues& values) void VectorValues::insert(const VectorValues& values)
{ {
size_t originalSize = size(); size_t originalSize = size();
@ -124,14 +124,14 @@ namespace gtsam {
throw invalid_argument("Requested to insert a VectorValues into another VectorValues that already contains one or more of its keys."); throw invalid_argument("Requested to insert a VectorValues into another VectorValues that already contains one or more of its keys.");
} }
/* ************************************************************************* */ /* ************************************************************************ */
void VectorValues::setZero() void VectorValues::setZero()
{ {
for(Vector& v: values_ | map_values) for(Vector& v: values_ | map_values)
v.setZero(); v.setZero();
} }
/* ************************************************************************* */ /* ************************************************************************ */
GTSAM_EXPORT ostream& operator<<(ostream& os, const VectorValues& v) { GTSAM_EXPORT ostream& operator<<(ostream& os, const VectorValues& v) {
// Change print depending on whether we are using TBB // Change print depending on whether we are using TBB
#ifdef GTSAM_USE_TBB #ifdef GTSAM_USE_TBB
@ -150,7 +150,7 @@ namespace gtsam {
return os; return os;
} }
/* ************************************************************************* */ /* ************************************************************************ */
void VectorValues::print(const string& str, void VectorValues::print(const string& str,
const KeyFormatter& formatter) const { const KeyFormatter& formatter) const {
cout << str << ": " << size() << " elements\n"; cout << str << ": " << size() << " elements\n";
@ -158,7 +158,7 @@ namespace gtsam {
cout.flush(); cout.flush();
} }
/* ************************************************************************* */ /* ************************************************************************ */
bool VectorValues::equals(const VectorValues& x, double tol) const { bool VectorValues::equals(const VectorValues& x, double tol) const {
if(this->size() != x.size()) if(this->size() != x.size())
return false; return false;
@ -170,7 +170,7 @@ namespace gtsam {
return true; return true;
} }
/* ************************************************************************* */ /* ************************************************************************ */
Vector VectorValues::vector() const { Vector VectorValues::vector() const {
// Count dimensions // Count dimensions
DenseIndex totalDim = 0; DenseIndex totalDim = 0;
@ -187,7 +187,7 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
Vector VectorValues::vector(const Dims& keys) const Vector VectorValues::vector(const Dims& keys) const
{ {
// Count dimensions // Count dimensions
@ -203,12 +203,12 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
void VectorValues::swap(VectorValues& other) { void VectorValues::swap(VectorValues& other) {
this->values_.swap(other.values_); this->values_.swap(other.values_);
} }
/* ************************************************************************* */ /* ************************************************************************ */
namespace internal namespace internal
{ {
bool structureCompareOp(const boost::tuple<VectorValues::value_type, bool structureCompareOp(const boost::tuple<VectorValues::value_type,
@ -219,14 +219,14 @@ namespace gtsam {
} }
} }
/* ************************************************************************* */ /* ************************************************************************ */
bool VectorValues::hasSameStructure(const VectorValues other) const bool VectorValues::hasSameStructure(const VectorValues other) const
{ {
return accumulate(combine(*this, other) return accumulate(combine(*this, other)
| transformed(internal::structureCompareOp), true, logical_and<bool>()); | transformed(internal::structureCompareOp), true, logical_and<bool>());
} }
/* ************************************************************************* */ /* ************************************************************************ */
double VectorValues::dot(const VectorValues& v) const double VectorValues::dot(const VectorValues& v) const
{ {
if(this->size() != v.size()) if(this->size() != v.size())
@ -244,12 +244,12 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
double VectorValues::norm() const { double VectorValues::norm() const {
return std::sqrt(this->squaredNorm()); return std::sqrt(this->squaredNorm());
} }
/* ************************************************************************* */ /* ************************************************************************ */
double VectorValues::squaredNorm() const { double VectorValues::squaredNorm() const {
double sumSquares = 0.0; double sumSquares = 0.0;
using boost::adaptors::map_values; using boost::adaptors::map_values;
@ -258,7 +258,7 @@ namespace gtsam {
return sumSquares; return sumSquares;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues VectorValues::operator+(const VectorValues& c) const VectorValues VectorValues::operator+(const VectorValues& c) const
{ {
if(this->size() != c.size()) if(this->size() != c.size())
@ -278,13 +278,13 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues VectorValues::add(const VectorValues& c) const VectorValues VectorValues::add(const VectorValues& c) const
{ {
return *this + c; return *this + c;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues& VectorValues::operator+=(const VectorValues& c) VectorValues& VectorValues::operator+=(const VectorValues& c)
{ {
if(this->size() != c.size()) if(this->size() != c.size())
@ -301,13 +301,13 @@ namespace gtsam {
return *this; return *this;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues& VectorValues::addInPlace(const VectorValues& c) VectorValues& VectorValues::addInPlace(const VectorValues& c)
{ {
return *this += c; return *this += c;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues& VectorValues::addInPlace_(const VectorValues& c) VectorValues& VectorValues::addInPlace_(const VectorValues& c)
{ {
for(const_iterator j2 = c.begin(); j2 != c.end(); ++j2) { for(const_iterator j2 = c.begin(); j2 != c.end(); ++j2) {
@ -320,7 +320,7 @@ namespace gtsam {
return *this; return *this;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues VectorValues::operator-(const VectorValues& c) const VectorValues VectorValues::operator-(const VectorValues& c) const
{ {
if(this->size() != c.size()) if(this->size() != c.size())
@ -340,13 +340,13 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues VectorValues::subtract(const VectorValues& c) const VectorValues VectorValues::subtract(const VectorValues& c) const
{ {
return *this - c; return *this - c;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues operator*(const double a, const VectorValues &v) VectorValues operator*(const double a, const VectorValues &v)
{ {
VectorValues result; VectorValues result;
@ -359,13 +359,13 @@ namespace gtsam {
return result; return result;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues VectorValues::scale(const double a) const VectorValues VectorValues::scale(const double a) const
{ {
return a * *this; return a * *this;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues& VectorValues::operator*=(double alpha) VectorValues& VectorValues::operator*=(double alpha)
{ {
for(Vector& v: *this | map_values) for(Vector& v: *this | map_values)
@ -373,12 +373,36 @@ namespace gtsam {
return *this; return *this;
} }
/* ************************************************************************* */ /* ************************************************************************ */
VectorValues& VectorValues::scaleInPlace(double alpha) VectorValues& VectorValues::scaleInPlace(double alpha)
{ {
return *this *= alpha; return *this *= alpha;
} }
/* ************************************************************************* */ /* ************************************************************************ */
string VectorValues::html(const KeyFormatter& keyFormatter) const {
stringstream ss;
// Print out preamble.
ss << "<div>\n<table class='VectorValues'>\n <thead>\n";
// Print out header row.
ss << " <tr><th>Variable</th><th>value</th></tr>\n";
// Finish header and start body.
ss << " </thead>\n <tbody>\n";
// Print out all rows.
for (const auto& kv : *this) {
ss << " <tr>";
ss << "<th>" << keyFormatter(kv.first) << "</th><td>"
<< kv.second.transpose() << "</td>";
ss << "</tr>\n";
}
ss << " </tbody>\n</table>\n</div>";
return ss.str();
}
/* ************************************************************************ */
} // \namespace gtsam } // \namespace gtsam

View File

@ -34,7 +34,7 @@
namespace gtsam { namespace gtsam {
/** /**
* This class represents a collection of vector-valued variables associated * VectorValues represents a collection of vector-valued variables associated
* each with a unique integer index. It is typically used to store the variables * each with a unique integer index. It is typically used to store the variables
* of a GaussianFactorGraph. Optimizing a GaussianFactorGraph or GaussianBayesNet * of a GaussianFactorGraph. Optimizing a GaussianFactorGraph or GaussianBayesNet
* returns this class. * returns this class.
@ -69,7 +69,7 @@ namespace gtsam {
* which is a view on the underlying data structure. * which is a view on the underlying data structure.
* *
* This class is additionally used in gradient descent and dog leg to store the gradient. * This class is additionally used in gradient descent and dog leg to store the gradient.
* \nosubgrouping * @addtogroup linear
*/ */
class GTSAM_EXPORT VectorValues { class GTSAM_EXPORT VectorValues {
protected: protected:
@ -344,11 +344,16 @@ namespace gtsam {
/// @} /// @}
/// @} /// @name Wrapper support
/// @name Matlab syntactic sugar for linear algebra operations
/// @{ /// @{
//inline VectorValues scale(const double a, const VectorValues& c) const { return a * (*this); } /**
* @brief Output as a html table.
*
* @param keyFormatter function that formats keys.
*/
std::string html(
const KeyFormatter& keyFormatter = DefaultKeyFormatter) const;
/// @} /// @}

View File

@ -255,6 +255,7 @@ class VectorValues {
// enabling serialization functionality // enabling serialization functionality
void serialize() const; void serialize() const;
void html() const;
}; };
#include <gtsam/linear/GaussianFactor.h> #include <gtsam/linear/GaussianFactor.h>

View File

@ -17,7 +17,7 @@
#include <gtsam/base/Testable.h> #include <gtsam/base/Testable.h>
#include <gtsam/linear/VectorValues.h> #include <gtsam/linear/VectorValues.h>
#include <gtsam/inference/LabeledSymbol.h> #include <gtsam/inference/Symbol.h>
#include <CppUnitLite/TestHarness.h> #include <CppUnitLite/TestHarness.h>
@ -248,6 +248,33 @@ TEST(VectorValues, print)
EXPECT(expected == actual.str()); EXPECT(expected == actual.str());
} }
/* ************************************************************************* */
// Check html representation.
TEST(VectorValues, html) {
VectorValues vv;
using symbol_shorthand::X;
vv.insert(X(1), Vector2(2, 3.1));
vv.insert(X(2), Vector2(4, 5.2));
vv.insert(X(5), Vector2(6, 7.3));
vv.insert(X(7), Vector2(8, 9.4));
string expected =
"<div>\n"
"<table class='VectorValues'>\n"
" <thead>\n"
" <tr><th>Variable</th><th>value</th></tr>\n"
" </thead>\n"
" <tbody>\n"
" <tr><th>x1</th><td> 2 3.1</td></tr>\n"
" <tr><th>x2</th><td> 4 5.2</td></tr>\n"
" <tr><th>x5</th><td> 6 7.3</td></tr>\n"
" <tr><th>x7</th><td> 8 9.4</td></tr>\n"
" </tbody>\n"
"</table>\n"
"</div>";
string actual = vv.html();
EXPECT(actual == expected);
}
/* ************************************************************************* */ /* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr); } int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
/* ************************************************************************* */ /* ************************************************************************* */