Skip to content
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

Common errorTree method and its use in HybridGaussianFactorGraph #1837

Merged
merged 11 commits into from
Sep 22, 2024

Conversation

varunagrawal
Copy link
Collaborator

Add errorTree as a virtual method in HybridFactor, and implement it in child classes.
This allows us to make the HybridGaussianFactorGraph::errorTree method very clean.

Also added the HybridNonlinearFactorGraph::error(const HybridValues&) method and corresponding test.

@varunagrawal varunagrawal self-assigned this Sep 20, 2024
Copy link
Member

@dellaert dellaert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments. Not sure I am on board with location of these methods yet.

@@ -136,6 +136,10 @@ class GTSAM_EXPORT HybridFactor : public Factor {
/// Return only the continuous keys for this factor.
const KeyVector &continuousKeys() const { return continuousKeys_; }

/// Virtual class to compute tree of linear errors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linear?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This linear because it only accepts VectorValues right? This is also why its definition in HybridNonlinearFactor throws a runtime error.

gtsam/hybrid/HybridGaussianConditional.h Show resolved Hide resolved
gtsam/hybrid/HybridGaussianConditional.h Outdated Show resolved Hide resolved
gtsam/hybrid/HybridConditional.h Outdated Show resolved Hide resolved
@@ -129,6 +129,22 @@ double HybridConditional::error(const HybridValues &values) const {
"HybridConditional::error: conditional type not handled");
}

/* ************************************************************************ */
AlgebraicDecisionTree<Key> HybridConditional::errorTree(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not in HybridFactor?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HybridFactor doesn't have the asGaussian, asHybrid and asDiscrete methods.

gtsam/hybrid/HybridGaussianFactor.h Outdated Show resolved Hide resolved
@@ -74,6 +74,13 @@ class GTSAM_EXPORT HybridNonlinearFactor : public HybridFactor {
/// Decision tree of Gaussian factors indexed by discrete keys.
Factors factors_;

/// HybridFactor method implementation. Should not be used.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm. So then why does it exist in the base class. red flag. Should maybe only exist in Gaussian branch.

Copy link
Collaborator Author

@varunagrawal varunagrawal Sep 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is primarily because of HybridConditional.

The class hierarchy is

  • HybridFactor
    • HybridConditional
    • HybridGaussianFactor
      • HybridGaussianConditional

HybridConditional acts as a common container class for GaussianConditional, DiscreteConditional and HybridGaussianConditional. By defining errorTree in HybridFactor, I can just check for HybridFactor. Otherwise, I'll have to check for HybridConditional and HybridGaussianFactor separately which I felt defeated the purpose of this base class method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is a different hierarchy than the non-hybrid case then:

class GTSAM_EXPORT GaussianConditional :
    public JacobianFactor,
    public Conditional<JacobianFactor, GaussianConditional>

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry there was a rendering error in my previous comment.
It is the same hierarchy as GaussianConditional since HybridGaussianConditional inherits from HybridGaussianFactor, however HybridConditional complicates things (or at least makes it messier).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would break if you only have errorTree in HybridGaussianFactor? It would be available in HGC. All done?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is a check needed? We would never call errorTree on HybridConditional, as it only makes sense for Gaussian variants, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A HybridConditional can have a GaussianConditional or a HybridGaussianConditional as its underlying conditional.

Remember that HybridConditional is a container based on type erasure and not a base class for HybridGaussianConditional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. But then why would we need an errorTree function for HybridConditional. If it can be either, then a method providing VectorValues does not make sense to me. Where would that be used? Is it used???

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in an incremental sense, when we add the conditionals from a HybridBayesNet to the HybridGaussianFactorGraph, the factor graph now has HybridGaussianFactor (and potential HybridGaussianConditionals) and HybridConditionals as well.

The alternative could be to unwrap the conditionals from the HybridConditional before adding it to the graph.

I am open to suggestions about this since this was nontrivial for me. I think checking for HybridGaussianFactor and HybridConditional separately makes sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh and another case: if we go from a HybridBayesNet to a HybridGaussianFactorGraph, then all the factors are added as HybridConditionals which are represented as HybridFactors. This causes DiscreteFactors to be considered in the errorTree computations as well. :(

Copy link
Member

@dellaert dellaert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks for engaging in a discussion. It feels a bit weird still but this is a consequence from how we did the class hierarch and how defined the hybrid factor graphs.

@varunagrawal
Copy link
Collaborator Author

OK, thanks for engaging in a discussion. It feels a bit weird still but this is a consequence from how we did the class hierarch and how defined the hybrid factor graphs.

Yeah I think we can come up with a better class inheritance hierarchy, which is transparent to the user, later once the API is stable. I have ideas about this!

@varunagrawal varunagrawal merged commit e52973b into develop Sep 22, 2024
33 checks passed
@varunagrawal varunagrawal deleted the improved-api-2 branch September 22, 2024 23:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants