-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fan/prototype hybrid tr #42
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t understand: is this a completely new framework? How does it relate to what we already have?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me explain what is happening here.
In a historical perspective, when we merged in DCSAM code we started by making HybridFactorGraph
there a FactorGraph<T>
in GTSAM. However, that class is not designed in that way. If you look at that you can see that it is not a children of FactorGraph
.
The native way in GTSAM how we make Factor graphs is by inheriting FactorGraph<DERIVED>
. By doing this you automatically gets a container of DERIVED
factors that comes with all the goodies. However, since the DCSAM version of HybridFactorGraph
is not using this underlying storage, we have to work around the existing methods in FactorGraph, which is very tedious and error-prone.
A proper implementation, as I propose here, is to just use the underlying storage of FactorGraph
and build logic only in the EliminateHybrid
method. This allows us to have a minimal change in GTSAM to enable the same algorithms in DCSAM.
Actually, everything in this PR except the elimination functions are merely boilerplate: they 100% resembles their counterparts in linear
and discrete
.
gtsam/hybrid/CGMixtureFactor.h
Outdated
|
||
namespace gtsam { | ||
|
||
class CGMixtureFactor : HybridFactor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be analogous to the current DCMixtureFactor
|
||
namespace gtsam { | ||
|
||
// Instantiate base class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to look at this
* - DiscreteConditional | ||
* - GaussianMixture | ||
* - GaussianConditional | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HybridConditional is a type-erased wrapper for all:
- DiscreteConditional
- GaussianMixture
- GaussianConditional
Gist is that by unifying all these types the only work need in HybridBayesTree is boilerplate (same to linear and discrete), the hard work (type-based dispatch) is offloaded to this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This eliminates the necessity of AbstractConditional
, which is good because now we don't need to touch other modules, especially inference
, at all.
gtsam/hybrid/HybridFactor.h
Outdated
/** | ||
* Base class for hybrid probabilistic factors | ||
*/ | ||
class GTSAM_EXPORT HybridFactor: public Factor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just the base for all hybrid factors
gtsam/hybrid/HybridFactorGraph.cpp
Outdated
|
||
/* ************************************************************************ */ | ||
std::pair<HybridConditional::shared_ptr, HybridFactor::shared_ptr> // | ||
EliminateHybrid(const HybridFactorGraph& factors, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we are in the Conditional Gaussian regime there are only
few cases:
- continuous variable, we make a GM if there are hybrid factors;
- continuous variable, we make a GF if there are no hybrid factors;
- discrete variable, no continuous factor is allowed (escapes CG regime), so we panic
- if discrete only we do the discrete elimination.
We can know which variable is discrete by querying the factors.
GTSAM_PRINT(*result.first); | ||
} | ||
|
||
TEST(HybridFactorGraph, eliminateMultifrontal) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By employing this scheme we don't need any special code for handling the templated JunctionTree
and BayesTree
s, so eliminateMultifrontal
just work. In contrast, I spent tens of hours to make the old code to compile with JunctionTree
and failed.
OK, these explanations shed a lot of light, so thank you! I will do an in-depth look tomorrow, and then we can talk. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took 40 minutes to review. Please address every comment by either implementing suggestion and resolving OR providing a rationale and not resolving.
typedef boost::shared_ptr<HybridFactor> shared_ptr; ///< shared_ptr to this class | ||
typedef Factor Base; ///< Our base class | ||
|
||
bool isDiscrete_ = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would each derived class not know this automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to avoid the need to dynamic casts each time we need to know what is the type of one factor.
@dellaert I now believe I have full multifrontal elimination working. The code still needs some cleaning up though. BTW, I am now thinking a bit more about the decision to use DecisionTree as the base structure. Maybe a hash table keyed on the discrete assignment will be better both in performance and in difficulty of programming, if we have pruning? |
@dellaert @varunagrawal Feel free to play with the code while I add new unit tests :) |
Also, I guess it would be a good idea to add a massive comment on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comments
@@ -0,0 +1,273 @@ | |||
/* ---------------------------------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many tests should be in testHybridFactorGraph
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
X(0), Z_3x1, I_3x3, X(1), I_3x3), | ||
boost::make_shared<GaussianConditional>( | ||
X(0), Vector3::Ones(), I_3x3, X(1), I_3x3))); | ||
GTSAM_PRINT(clgc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convert print to real tests.
X(0), Z_3x1, I_3x3, X(1), I_3x3), | ||
boost::make_shared<GaussianConditional>( | ||
X(0), Vector3::Ones(), I_3x3, X(1), I_3x3))); | ||
GTSAM_PRINT(clgc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use curly braces for discrete keys
|
||
DiscreteKey c1(C(1), 2); | ||
|
||
hfg.add(JacobianFactor(X(0), I_3x3, Z_3x1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't copy paste
|
||
HybridFactorGraph hfg; | ||
|
||
hfg.add(JacobianFactor(X(0), I_3x3, X(1), -I_3x3, Z_3x1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comments to show example.
boost::shared_ptr<CliqueType> clique; | ||
|
||
BayesTreeOrphanWrapper(const boost::shared_ptr<CliqueType>& clique) | ||
: clique(clique) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make it a constructor for Base
|
||
#pragma once | ||
|
||
#include <gtsam/discrete/DiscreteConditional.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean them up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check other headers
|
||
/* ************************************************************************ */ | ||
std::pair<HybridConditional::shared_ptr, HybridFactor::shared_ptr> // | ||
EliminateHybrid(const HybridFactorGraph &factors, const Ordering &frontalKeys) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should really consider breaking this method up into smaller chunks. There is already a logical demarcation.
@@ -0,0 +1,273 @@ | |||
/* ---------------------------------------------------------------------------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
gtsam/hybrid/tests/Switching.h
Outdated
return {new_order, levels}; | ||
} | ||
|
||
} // namespace gtsam |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a newline.
@ProfFan after you address these relatively minor comments (please do so ASAP) please close this PR and create a PR from this branch directly to GTSAM develop (after merging in that develop). |
453be44
to
e36583e
Compare
Prototyping a GTSAM-native hybrid graph that uses the CLG formulation described in Murphy02 and Salmeron18.
Multifrontal just works,
though no actual functionality is added yeteverything works.I believe this is a better way to do hybrid, since everything now lies in accordance with other modules (
discrete
,linear
, etc).Also this is also how
LinearContainerFactor
is designed...