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

boost::optional<const Ordering &> #156

Merged
merged 5 commits into from
Nov 13, 2019
Merged

boost::optional<const Ordering &> #156

merged 5 commits into from
Nov 13, 2019

Conversation

gchenfc
Copy link
Member

@gchenfc gchenfc commented Oct 20, 2019

Get rid of boost::optional, this PR is for Ordering and Scatter classes (should fix #148 ).
Replace all usages of boost::optional<*Ordering*> with function overloads.

compiles and passes tests, but some potentially code-breaking changes in:

  • Marginals.h - order of arguments had to change since factorization has a default value
  • EliminatableFactorGraph.h - marginalMultifrontalBayesNet and marginalMultifrontalBayesTree no longer accept boost::none as a placeholder to specify later arguments
  • NonlinearFactorGraph.h - same deal

Notes:

  • EliminateableFactorGraph.h - orderingType is no longer needed in function overloads that specify ordering, but I left it for the time being to avoid potential code breaking
  • NonlinearOptimizerParams.h and LevenbergMarquardParams.h still have a parameter that's a boost::optional<Ordering> but I left it in because it's not readily handle-able by a single function overload (not sure what other code depends on it being optional)

This change is Reviewable

Gerry Chen added 3 commits October 13, 2019 23:59
…s &>)` to overloaded

`func(...)` and
`func(..., const Class &)`
not all done
Also, although it currently passes all tests, I think some more tests may be needed...
compiles and passes tests, but some potentially code-breaking changes in:
Marginals.h - order of arguments had to change since `factorization` has a default value
EliminatableFactorGraph.h - marginalMultifrontalBayesNet and marginalMultifrontalBayesTree no longer accept `boost::none` as a placeholder to specify later arguments
Notes:
EliminateableFactorGraph.h - `orderingType` is no longer needed in function overloads that specify ordering, but I left it for the time being to avoid potential code breaking
Copy link
Member Author

@gchenfc gchenfc left a comment

Choose a reason for hiding this comment

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

some notes


// Cast or convert to Jacobians
FastVector<JacobianFactor::shared_ptr> jacobians = _convertOrCastToJacobians(
graph);

gttic(Order_slots);
Copy link
Member Author

Choose a reason for hiding this comment

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

4 new constructors (generated from combinations of 2 optional parameters) will use this same code so i moved it into a separate function, not sure why diff util didn't recognize it better

Comment on lines 60 to 68
Marginals(const NonlinearFactorGraph& graph, const Values& solution, Factorization factorization = CHOLESKY,
EliminateableFactorGraph<GaussianFactorGraph>::OptionalOrdering ordering = boost::none);
Marginals(const NonlinearFactorGraph& graph, const Values& solution, Factorization factorization = CHOLESKY);

/** Construct a marginals class from a nonlinear factor graph.
* @param graph The factor graph defining the full joint density on all variables.
* @param solution The linearization point about which to compute Gaussian marginals (usually the MLE as obtained from a NonlinearOptimizer).
* @param factorization The linear decomposition mode - either Marginals::CHOLESKY (faster and suitable for most problems) or Marginals::QR (slower but more numerically stable for poorly-conditioned problems).
* @param ordering The ordering for elimination.
*/
Marginals(const NonlinearFactorGraph& graph, const Values& solution, const Ordering& ordering, // argument order switch due to default value of factorization, potentially code breaking
Factorization factorization = CHOLESKY);
Copy link
Member Author

Choose a reason for hiding this comment

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

note ordering now comes before factorization because factorization has a default value

Comment on lines 380 to 382
KeyVector keys = values.keys();
Ordering defaultOrdering(keys);
return linearizeToHessianFactor(values, defaultOrdering, dampen);
Copy link
Member Author

Choose a reason for hiding this comment

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

is this tactic of creating a "default" ordering inefficient compared to creating a helper function? (as I did with the rest of the PR)

Comment on lines 272 to 276
boost::shared_ptr<BayesTreeType> marginalMultifrontalBayesTree(
boost::variant<const Ordering&, const KeyVector&> variables,
OptionalOrdering marginalizedVariableOrdering = boost::none,
const Ordering& marginalizedVariableOrdering, // this no longer takes boost::none - potentially code breaking
const Eliminate& function = EliminationTraitsType::DefaultEliminate,
OptionalVariableIndex variableIndex = boost::none) const;
Copy link
Member Author

Choose a reason for hiding this comment

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

potentially breaks code,
marginalMultifrontalBayesTree(variables, boost::none, EliminationQR, variableIndex); now becomes
marginalMultifrontalBayesTree(variables, EliminationQR, variableIndex);

Comment on lines 371 to 379
const Values& values, boost::optional<Ordering&> ordering, const Dampen& dampen) const {
const Values& values, const Dampen& dampen) const {
Copy link
Member Author

Choose a reason for hiding this comment

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

potentially breaks code,
linearizeToHessianFactor(values, boost::none, dampen) changes to
linearizeToHessianFactor(values, dampen)

Copy link
Member Author

Choose a reason for hiding this comment

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

added deprecated function to .h file

@dellaert
Copy link
Member

Unfortunately, API breaking/ changing is not allowed here. So we have to find another solution

@ProfFan
Copy link
Collaborator

ProfFan commented Oct 20, 2019

Can we have a flag that enables another overload for boost::optionals?

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.

I added a bunch of comments. Did not get to Marginals yet, but I assume some of earlier comments I made establish a pattern...

gtsam/base/TestableAssertions.h Outdated Show resolved Hide resolved
gtsam/discrete/DiscreteConditional.cpp Outdated Show resolved Hide resolved
gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
gtsam/inference/EliminateableFactorGraph.h Show resolved Hide resolved
gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
gtsam/linear/GaussianBayesNet.cpp Show resolved Hide resolved
@@ -250,10 +250,10 @@ HessianFactor::HessianFactor(const GaussianFactor& gf) :

/* ************************************************************************* */
HessianFactor::HessianFactor(const GaussianFactorGraph& factors,
boost::optional<const Scatter&> scatter) {
const Scatter& scatter) {
Copy link
Member

Choose a reason for hiding this comment

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

Are we doing scatter in this PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

I included Scatter to address issue #148

// Order variable slots - we maintain the vector of ordered slots, as well as keep a list
// 'unorderedSlots' of any variables discovered that are not in the ordering. Those will then
// be added after all of the ordered variables.
FastVector<VariableSlots::const_iterator> orderedSlotsHelper(
Copy link
Member

Choose a reason for hiding this comment

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

Did not read in detail but is this a delegated constructor pattern?

Copy link
Member Author

Choose a reason for hiding this comment

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

I instead put it in a member function rather than delegated constructor for a couple reasons:

  1. stuff needs to get done before the shared code, i.e.
    JacobianFactor() {
    // specific stuff creates some_variables
    // common stuff relies on some_variables
    }
  2. I didn't want to mess up the gttic() timings

In fact actually there are 2 helper functions (orderedSlotsHelper and JacobianFactorHelper), see constructor in line 409 for the quintessential example.

I also converted boost::optional<const VariableSlots &> while I was here because it was convenient, but I can revert that if you prefer to keep this PR tidy.

@dellaert
Copy link
Member

Can we have a flag that enables another overload for boost::optionals?

Let’s keep this PR focused...

also removed some edits that were tangential to the PR.
Copy link
Member Author

@gchenfc gchenfc left a comment

Choose a reason for hiding this comment

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

addressed comments for API breaking changes, unrelated changes, and others.

gtsam/base/TestableAssertions.h Outdated Show resolved Hide resolved
gtsam/discrete/DiscreteConditional.cpp Outdated Show resolved Hide resolved
@@ -250,10 +250,10 @@ HessianFactor::HessianFactor(const GaussianFactor& gf) :

/* ************************************************************************* */
HessianFactor::HessianFactor(const GaussianFactorGraph& factors,
boost::optional<const Scatter&> scatter) {
const Scatter& scatter) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I included Scatter to address issue #148

// Order variable slots - we maintain the vector of ordered slots, as well as keep a list
// 'unorderedSlots' of any variables discovered that are not in the ordering. Those will then
// be added after all of the ordered variables.
FastVector<VariableSlots::const_iterator> orderedSlotsHelper(
Copy link
Member Author

Choose a reason for hiding this comment

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

I instead put it in a member function rather than delegated constructor for a couple reasons:

  1. stuff needs to get done before the shared code, i.e.
    JacobianFactor() {
    // specific stuff creates some_variables
    // common stuff relies on some_variables
    }
  2. I didn't want to mess up the gttic() timings

In fact actually there are 2 helper functions (orderedSlotsHelper and JacobianFactorHelper), see constructor in line 409 for the quintessential example.

I also converted boost::optional<const VariableSlots &> while I was here because it was convenient, but I can revert that if you prefer to keep this PR tidy.

}

// Now, find dimensions of variables and/or extend
void Scatter::setDimensions(const GaussianFactorGraph& gfg, size_t sortStart) {
Copy link
Member Author

Choose a reason for hiding this comment

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

changed to delegated constructor

gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
* \endcode
* */
boost::shared_ptr<BayesTreeType> eliminateMultifrontal(
const Ordering& ordering,
Copy link
Member Author

Choose a reason for hiding this comment

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

done

gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
gtsam/inference/EliminateableFactorGraph.h Outdated Show resolved Hide resolved
Comment on lines 371 to 379
const Values& values, boost::optional<Ordering&> ordering, const Dampen& dampen) const {
const Values& values, const Dampen& dampen) const {
Copy link
Member Author

Choose a reason for hiding this comment

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

added deprecated function to .h file

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.

I have no time to do a second, detailed review. I propose @ProfFan goes through fine comb, and you wait to merge until he signs off. However, please resist expanding the scope of this PR, and please make absolutely sure it is backwards compatible. All API-breaking needs to be in deprecated blocks.

@ProfFan
Copy link
Collaborator

ProfFan commented Nov 1, 2019

@gchenfc We need to have API stability tests probably :(
Also, the previous boost::Optional&-based I/F should probably be retained with deprecated macros https://stackoverflow.com/questions/295120/c-mark-as-deprecated

@dellaert
Copy link
Member

dellaert commented Nov 1, 2019

No, I vote not to retain them. Let's merge this once API calls are verified (by a detailed review, not by additional tests). Again, don't expand scope...

@ProfFan
Copy link
Collaborator

ProfFan commented Nov 1, 2019

@dellaert I am all good with that 👍 The current testset should have already validated the API calls, but I will double check.

@dellaert
Copy link
Member

Status?

@ProfFan
Copy link
Collaborator

ProfFan commented Nov 13, 2019

Good to go.

@ProfFan ProfFan merged commit ed7f949 into develop Nov 13, 2019
@dellaert
Copy link
Member

And, @ProfFan , by "good to go" you mean : you verified it's 100% backward compatible, yes? :-)

@ProfFan
Copy link
Collaborator

ProfFan commented Nov 13, 2019

It is 99% backward compatible due to the fact that if someone used the pattern xxx(args, boost::none) instead of xxx(args)(using the default value) then there will be an error that boost::none cannot be converted to TypeOfArgument. Otherwise it would be just fine.

@ProfFan
Copy link
Collaborator

ProfFan commented Nov 13, 2019

BTW, this can be 100% if we retain the old boost::Optional<T&> interface.

@gchenfc
Copy link
Member Author

gchenfc commented Nov 18, 2019

Apologies for late reply, but I had already added deprecated overloads with boost::none_t to preserve this 1% of non-backwards compatibility.
For example, xxx(args, boost::optional<>) -> xxx(args, boost::none_t) For example, line 328 of EliminateableFactorGraph.h. I didn't think to do this until later though so I may have missed a couple. I can go back and check again if I missed any?

@ProfFan
Copy link
Collaborator

ProfFan commented Nov 19, 2019

@gchenfc Feel free to check and add :) Currently I have not found any issue in the current revision.

@ProfFan ProfFan mentioned this pull request Dec 20, 2019
@dellaert dellaert deleted the fix/boost-optional branch January 2, 2020 20:25
varunagrawal added a commit that referenced this pull request Oct 29, 2022
ba3dcab16 Merge pull request #156 from borglab/fix/matlab-properties
feb4ee1b9 update docs
e57fec56b add unit test for templated class property

git-subtree-dir: wrap
git-subtree-split: ba3dcab16a8316634b56e3c4c6061531c91eb36c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants