28 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION 29 #include <boost/archive/text_iarchive.hpp> 30 #include <boost/archive/text_oarchive.hpp> 31 #include <boost/serialization/vector.hpp> 57 edges_.reserve(indices.size());
58 for (
const size_t &index : indices) {
59 const Edge e{index, 1.0};
69 eid.push_back(edge.index);
74 #ifdef GTSAM_ENABLE_BOOST_SERIALIZATION 77 std::ofstream
os(fn.c_str());
78 boost::archive::text_oarchive oa(
os);
84 Subgraph Subgraph::load(
const std::string &fn) {
85 std::ifstream is(fn.c_str());
86 boost::archive::text_iarchive ia(is);
97 os << edge.
index <<
"(" << std::setprecision(2) << edge.
weight <<
")";
105 os <<
"Subgraph" << endl;
106 for (
const auto &
e : subgraph.
edges()) {
117 os <<
"SubgraphBuilderParameters" << endl
118 <<
"skeleton: " << skeletonTranslator(skeletonType) << endl
119 <<
"skeleton weight: " << skeletonWeightTranslator(skeletonWeight)
121 <<
"augmentation weight: " 122 << augmentationWeightTranslator(augmentationWeight) << endl;
137 if (s ==
"NATURALCHAIN")
141 else if (s ==
"KRUSKAL")
143 throw std::invalid_argument(
144 "SubgraphBuilderParameters::skeletonTranslator undefined string " + s);
150 if (s == NATURALCHAIN)
151 return "NATURALCHAIN";
154 else if (s == KRUSKAL)
172 else if (s ==
"RANDOM")
174 throw std::invalid_argument(
175 "SubgraphBuilderParameters::skeletonWeightTranslator undefined string " +
185 else if (w == RHS_2NORM)
187 else if (w == LHS_FNORM)
189 else if (w == RANDOM)
198 const std::string &src) {
202 if (s ==
"SKELETON")
return SKELETON;
205 throw std::invalid_argument(
206 "SubgraphBuilder::Parameters::augmentationWeightTranslator undefined " 215 if (w == SKELETON)
return "SKELETON";
224 const vector<double> &weights)
const {
228 return natural_chain(gfg);
237 std::cerr <<
"SubgraphBuilder::buildTree undefined skeleton type" << endl;
240 return vector<size_t>();
245 vector<size_t> unaryFactorIndices;
247 for (
const auto &factor : gfg) {
248 if (factor->size() == 1) {
249 unaryFactorIndices.push_back(index);
253 return unaryFactorIndices;
259 vector<size_t> chainFactorIndices;
262 if (gf->size() == 2) {
263 const Key k0 = gf->keys()[0], k1 = gf->keys()[1];
264 if ((k1 - k0) == 1 || (k0 - k1) == 1) chainFactorIndices.push_back(index);
268 return chainFactorIndices;
277 const size_t n = variableIndex.
size();
280 vector<size_t> bfsFactorIndices;
281 bfsFactorIndices.reserve(n - 1);
284 std::queue<size_t>
q;
287 std::set<size_t> flags;
292 const size_t head = q.front();
294 for (
const size_t index : variableIndex[head]) {
296 for (
const size_t key : gf.
keys()) {
297 if (flags.count(
key) == 0) {
305 return bfsFactorIndices;
310 const vector<double> &weights)
const {
316 const size_t t)
const {
317 std::mt19937
rng(42);
324 const auto &
p = parameters_;
327 const size_t n = inverse_ordering.size(),
m = gfg.
size();
332 size_t numExtraEdges = n *
p.augmentationFactor;
333 const size_t numRemaining =
m - (n - 1);
334 numExtraEdges =
std::min(numExtraEdges, numRemaining / 2);
337 vector<double> weights = this->weights(gfg);
340 const vector<size_t>
tree = buildTree(gfg, weights);
341 if (tree.size() != n - 1) {
342 throw std::runtime_error(
343 "SubgraphBuilder::operator() failure: tree.size() != n-1, might be caused by disconnected graph");
347 for (
const size_t index : tree) {
348 weights[index] = 0.0;
352 vector<size_t> offTree = sample(weights, numExtraEdges);
354 vector<size_t> subgraph =
unary(gfg);
355 subgraph.insert(subgraph.end(), tree.begin(), tree.end());
356 subgraph.insert(subgraph.end(), offTree.begin(), offTree.end());
365 const size_t m = gfg.
size();
370 switch (parameters_.skeletonWeight) {
372 weight.push_back(1.0);
376 std::dynamic_pointer_cast<JacobianFactor>(gf)) {
377 weight.push_back(jf->getb().norm());
379 std::dynamic_pointer_cast<HessianFactor>(gf)) {
380 weight.push_back(hf->linearTerm().norm());
385 std::dynamic_pointer_cast<JacobianFactor>(gf)) {
386 weight.push_back(
std::sqrt(jf->getA().squaredNorm()));
388 std::dynamic_pointer_cast<HessianFactor>(gf)) {
389 weight.push_back(
std::sqrt(hf->information().squaredNorm()));
394 weight.push_back(std::rand() % 100 + 1.0);
398 throw std::invalid_argument(
399 "SubgraphBuilder::weights: undefined weight scheme ");
412 for (
const auto &
e : subgraph) {
413 const auto factor = gfg[
e.index];
414 subgraphFactors.
push_back(clone ? factor->clone() : factor);
416 return subgraphFactors;
428 for (
const auto &
e : subgraph) {
432 return {subgraphFactors, remaining};
void print(const Matrix &A, const string &s, ostream &stream)
const gtsam::Symbol key('X', 0)
enum gtsam::SubgraphBuilderParameters::Skeleton skeletonType
const Edges & edges() const
std::vector< size_t > sample(const std::vector< double > &weights, const size_t t) const
size_t size() const
The number of variable entries. This is equal to the number of unique variable Keys.
std::shared_ptr< This > shared_ptr
A shared_ptr to this class.
std::vector< size_t > buildTree(const GaussianFactorGraph &gfg, const std::vector< double > &weights) const
std::vector< size_t > kruskal(const GaussianFactorGraph &gfg, const std::vector< double > &weights) const
IsDerived< DERIVEDFACTOR > push_back(std::shared_ptr< DERIVEDFACTOR > factor)
Add a factor directly using a shared_ptr.
Fast sampling without replacement.
std::vector< size_t > kruskal(const FactorGraph< FACTOR > &fg, const std::vector< double > &weights)
A faster implementation for DSF, which uses vector rather than btree.
std::vector< double > Weights
std::vector< size_t > unary(const GaussianFactorGraph &gfg) const
std::vector< size_t > natural_chain(const GaussianFactorGraph &gfg) const
Array< double, 1, 3 > e(1./3., 0.5, 2.)
EIGEN_DEVICE_FUNC const Scalar & q
Linear Factor Graph where all factors are Gaussians.
EIGEN_DONT_INLINE void transform(const Transformation &t, Data &data)
std::shared_ptr< This > shared_ptr
shared_ptr to this class
GaussianFactorGraph buildFactorSubgraph(const GaussianFactorGraph &gfg, const Subgraph &subgraph, const bool clone)
std::shared_ptr< This > shared_ptr
shared_ptr to this class
virtual Subgraph operator()(const GaussianFactorGraph &jfg) const
A thin wrapper around std::map that uses boost's fast_pool_allocator.
EdgeIndices edgeIndices() const
ofstream os("timeSchurFactors.csv")
Weights weights(const GaussianFactorGraph &gfg) const
std::vector< size_t > sampleWithoutReplacement(size_t numSamples, const std::vector< double > &weights)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE FixedSegmentReturnType< internal::get_fixed_value< NType >::value >::Type head(NType n)
static AugmentationWeight augmentationWeightTranslator(const std::string &s)
const KeyVector & keys() const
Access the factor's involved variable keys.
void reserve(size_t size)
std::pair< GaussianFactorGraph, GaussianFactorGraph > splitFactorGraph(const GaussianFactorGraph &factorGraph, const Subgraph &subgraph)
Jet< T, N > sqrt(const Jet< T, N > &f)
static Skeleton skeletonTranslator(const std::string &s)
friend std::ostream & operator<<(std::ostream &os, const Subgraph &subgraph)
static Ordering Natural(const FACTOR_GRAPH &fg)
Return a natural Ordering. Typically used by iterative solvers.
std::uint64_t Key
Integer nonlinear key type.
std::vector< size_t > bfs(const GaussianFactorGraph &gfg) const
static SkeletonWeight skeletonWeightTranslator(const std::string &s)