Skip to content

Optimize Levenberg Marquardt elimination by caching JunctionTree.#2340

Merged
dellaert merged 3 commits intoborglab:developfrom
tzvist:feature/tzvi/JunctionIndexEliminationTree
Feb 22, 2026
Merged

Optimize Levenberg Marquardt elimination by caching JunctionTree.#2340
dellaert merged 3 commits intoborglab:developfrom
tzvist:feature/tzvi/JunctionIndexEliminationTree

Conversation

@tzvist
Copy link
Copy Markdown
Contributor

@tzvist tzvist commented Jan 6, 2026

Add JunctionIndexEliminationTree class that stores cluster roots using factor indices instead of full factor objects, enabling efficient reuse of elimination tree structure across multiple LevenbergMarquardt iterations.

Key changes:

  • Add JunctionIndexEliminationTree to cache cluster roots structure
  • Modify GaussianFactorGraph::optimize() to use cached elimination tree
  • Cache damped system elimination tree in LevenbergMarquardtOptimizer
  • Add comprehensive unit tests for JunctionIndexEliminationTree

Performance improvement: reduces runtime from ~120s to ~90s (~25% faster) in a specific test cases by avoiding repeated elimination tree construction.

@dellaert
Copy link
Copy Markdown
Member

dellaert commented Jan 8, 2026

woohoo, that's a big win! Will review Thursday.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an optimization to Levenberg-Marquardt iterations by caching the elimination tree structure across iterations. A new JunctionIndexEliminationTree class stores cluster roots using factor indices instead of full factor objects, avoiding repeated elimination tree construction.

Key changes:

  • New JunctionIndexEliminationTree class that caches elimination tree structure using factor indices
  • Modified GaussianFactorGraph::optimize() to use cached elimination tree when available
  • Added caching mechanism in LevenbergMarquardtOptimizer for the damped system elimination tree

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
gtsam/linear/JunctionIndexEliminationTree.h Header defining the new JunctionIndexEliminationTree class for cached elimination
gtsam/linear/JunctionIndexEliminationTree-inl.h Internal IndexedCluster data structure implementation
gtsam/linear/JunctionIndexEliminationTree.cpp Implementation of index-based elimination tree construction and elimination
gtsam/nonlinear/LevenbergMarquardtOptimizer.h Added cached elimination tree member variable
gtsam/nonlinear/LevenbergMarquardtOptimizer.cpp Cache creation and usage in tryLambda method
gtsam/linear/GaussianFactorGraph.h Added setCachedClusterRoots method and cache member
gtsam/linear/GaussianFactorGraph.cpp Modified optimize methods to use cached elimination tree
gtsam/linear/tests/testJunctionIndexEliminationTree.cpp Comprehensive unit tests for JunctionIndexEliminationTree

@dellaert
Copy link
Copy Markdown
Member

dellaert commented Jan 8, 2026

@tzvist I have not read the code in detail yet; it would help me to know the philosophy a little bit better. How do the new values of the damped system enter into the equation? Am I right to assume the system is still built as usual, but because you’re using indices, the new factors are accessed?

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Jan 8, 2026

@tzvist I have not read the code in detail yet; it would help me to know the philosophy a little bit better. How do the new values of the damped system enter into the equation? Am I right to assume the system is still built as usual, but because you’re using indices, the new factors are accessed?

Yes, the damped system is built exactly the same as before (the buildDampedSystem call at line 143) but instead of recomputing the elimination structure every time, we now cache a JunctionIndexEliminationTree that only stores the indices into the factor graph.
The key insight is that across different lambda iterations, the damped system's structure doesn't change - only the damping values change. So we compute the JunctionIndexEliminationTree once (lines 147-149) from the first damped system structure, and it stores the precalculated indices.
Then in each tryLambda call, we build the new damped system with the updated lambda value, pass it to the cached elimination tree via setCachedJunctionElimination (line 151), and the elimination process accesses the new factors according to the precalculated indices. This way we can reuse the expensive elimination structure computation across all lambda search iterations.

@dellaert
Copy link
Copy Markdown
Member

dellaert commented Jan 9, 2026

I think you have the right idea here. I’ve actually used this idea as well recently in the new multifrontal solver. By the way, if you’re not aware of it, here is the link to the last PR that I just submitted: #2343

That new solver is on track to be integrated with the nonlinear optimizers, to get hopefully much more speed-up than 75% even. But I think that your idea can be used to speed up any eliminatable factor graph, including hybrid, so I’m interested in exploring this regardless. Also only linear systems without constraints can be sped up by the new multifrontal solver.

That being said, I prefer if we could discuss the API and make it a little bit more functional. Would you be available to meet some time next week?

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Jan 11, 2026

I think you have the right idea here. I’ve actually used this idea as well recently in the new multifrontal solver. By the way, if you’re not aware of it, here is the link to the last PR that I just submitted: #2343

That new solver is on track to be integrated with the nonlinear optimizers, to get hopefully much more speed-up than 75% even. But I think that your idea can be used to speed up any eliminatable factor graph, including hybrid, so I’m interested in exploring this regardless. Also only linear systems without constraints can be sped up by the new multifrontal solver.

That being said, I prefer if we could discuss the API and make it a little bit more functional. Would you be available to meet some time next week?

Sure, I’d be happy to discuss the API.
I’m in a different time zone, but I’m available this week (Monday–Thursday) between 9:00 and 11:00 Atlanta time.
Let me know if any of those times work for you.

@dellaert
Copy link
Copy Markdown
Member

Awesome. Here is a link that knows about time zones and my calendar :-) https://calendly.com/dellaert/teams-meeting

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Jan 15, 2026

Awesome. Here is a link that knows about time zones and my calendar :-) https://calendly.com/dellaert/teams-meeting

I have two more perforce oriented MR:
#2355
#2356

Maybe it will be best if you can try taking a look at them also and then we can meet next week and discuss them all.

@dellaert
Copy link
Copy Markdown
Member

Please take a look at the junction tree I built in the multi-frontal solver. I use a symbolic factor with some extra payload. I think it might be a good strategy to template the symbolic factor with an optional payload, so we can just use the strategy in both places.

In terms of using this junction tree (or elimination tree), which will now store the extra payload in its clique factors, I'd rather see that used in a functional interface rather than storing something in a mutable field in the Gaussian FG

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Jan 18, 2026

Please take a look at the junction tree I built in the multi-frontal solver. I use a symbolic factor with some extra payload. I think it might be a good strategy to template the symbolic factor with an optional payload, so we can just use the strategy in both places.

In terms of using this junction tree (or elimination tree), which will now store the extra payload in its clique factors, I'd rather see that used in a functional interface rather than storing something in a mutable field in the Gaussian FG

I have added Refactor MultifrontalSolver to use JunctionIndexEliminationTree i started doing the templating but this was an simpler approach, is this good in you opinion?
i still need to do the functional interface.

also do you think we should try to add the mergeSmallClusters also to existing LM?

@dellaert
Copy link
Copy Markdown
Member

I think we're a little tripping over ourselves here :-) I would prefer to hold up on this one. I'm hesitant about adding entire junction trees and cluster trees. Basically, by only adapting the symbolic factor a tiny little bit we get all the machinery without touching those larger classes. I have another refactor in the works that splits out the SymbolicAnalysis for the new solvers. For that, I might try my hand at the templated approach first - potentially accommodating your case as well. When done, you can check that out and see whether we can take your idea and make that work in a functional API.

@tzvist tzvist force-pushed the feature/tzvi/JunctionIndexEliminationTree branch 3 times, most recently from ea2455d to bbf7783 Compare January 24, 2026 23:57
@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Jan 31, 2026

I think we're a little tripping over ourselves here :-) I would prefer to hold up on this one. I'm hesitant about adding entire junction trees and cluster trees. Basically, by only adapting the symbolic factor a tiny little bit we get all the machinery without touching those larger classes. I have another refactor in the works that splits out the SymbolicAnalysis for the new solvers. For that, I might try my hand at the templated approach first - potentially accommodating your case as well. When done, you can check that out and see whether we can take your idea and make that work in a functional API.

Could you review the last two commits? I think they’re close to what you had in mind.

Copy link
Copy Markdown
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.

Alright, I think we are starting to converge :-)

I still have structural comments and I'm hoping that you'll bear with me while we collaborate on making this a really cool addition to GTSAM :-)

@tzvist tzvist force-pushed the feature/tzvi/JunctionIndexEliminationTree branch 2 times, most recently from c9b2998 to 9ee0d42 Compare February 3, 2026 13:49
Copy link
Copy Markdown
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.

Okay, this is brilliant. Can you feel the stars align? :-)

@dellaert
Copy link
Copy Markdown
Member

dellaert commented Feb 3, 2026

Super happy with this right now. I propose we also wait for the benchmarking PR by @ProfFan so we can merge with confidence.

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Feb 3, 2026

Super happy with this right now. I propose we also wait for the benchmarking PR by @ProfFan so we can merge with confidence.

cool, maybe it will be interesting to compare the multifrontal solver with the LM after my changes.

@tzvist tzvist force-pushed the feature/tzvi/JunctionIndexEliminationTree branch 2 times, most recently from 3bc79fa to a3d41d8 Compare February 4, 2026 09:20
@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 4, 2026

/bench

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 4, 2026

timeSFMBAL benchmark

  • Head: 1cc5dec0e580a5a2b54ed9d7d4f3c97fe83dee07
  • Base: afff38a7374382b00ac831240ac49f047fa73861
Runner Metric Base (s) Head (s) Delta (s) Change
linux-arm64-tbbOFF timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalCholesky 9.853256 8.831666 -1.021590 -10.37%
linux-arm64-tbbOFF timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalSolver 12.569895 12.130573 -0.439322 -3.50%
linux-arm64-tbbON timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalCholesky 5.992584 4.953571 -1.039012 -17.34%
linux-arm64-tbbON timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalSolver 9.223792 9.162591 -0.061200 -0.66%
linux-x64-tbbOFF timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalCholesky 12.056695 11.114696 -0.941999 -7.81%
linux-x64-tbbOFF timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalSolver 17.833596 17.715216 -0.118379 -0.66%
linux-x64-tbbON timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalCholesky 8.044908 7.014190 -1.030718 -12.81%
linux-x64-tbbON timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalSolver 15.137964 14.734029 -0.403936 -2.67%
macos-arm64-tbbOFF timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalCholesky 59.356064 24.570510 -34.785553 -58.60%
macos-arm64-tbbOFF timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalSolver 20.711844 12.562268 -8.149576 -39.35%
macos-arm64-tbbON timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalCholesky 42.353868 27.878669 -14.475199 -34.18%
macos-arm64-tbbON timeSFMBAL/dubrovnik-135-90642-pre.txt/MultifrontalSolver 28.792136 16.689276 -12.102860 -42.04%

Worker runs

Role Runner SHA Conclusion
head linux-x64 1cc5dec0e580a5a2b54ed9d7d4f3c97fe83dee07 success
base linux-x64 afff38a7374382b00ac831240ac49f047fa73861 success
head linux-arm64 1cc5dec0e580a5a2b54ed9d7d4f3c97fe83dee07 success
base linux-arm64 afff38a7374382b00ac831240ac49f047fa73861 success
head macos-arm64 1cc5dec0e580a5a2b54ed9d7d4f3c97fe83dee07 success
base macos-arm64 afff38a7374382b00ac831240ac49f047fa73861 success

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 4, 2026

/bench

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 5, 2026

@dellaert Benchmark results look good :)

@dellaert
Copy link
Copy Markdown
Member

dellaert commented Feb 5, 2026

@dellaert Benchmark results look good :)

They look mixed right? seems like 25% slower on Mac no?

i’m wondering whether that BAL16 dataset is too small, as well. I’ve been using the 135 cameras.

@dellaert
Copy link
Copy Markdown
Member

dellaert commented Feb 5, 2026

Also, I’m now thinking we should do with and without TBB

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 7, 2026

I can add that

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 16, 2026

/bench

Refactor IndexedSymbolicFactor into shared IndexedJunctionTreeBuilder.h,
enabling efficient reuse of junction tree structure across multiple
nonlinear optimization iterations.

Key changes:
- Add IndexedJunctionTreeBuilder.h with buildIndexedJunctionTree() template
- Add GaussianFactorGraph::optimize() overload using cached junction tree
- Cache SymbolicJunctionTree in NonlinearOptimizer for multifrontal solve
- Refactor MultifrontalSolver and NonlinearMultifrontalSolver to use
  shared builder functions

Performance improvement: reduces runtime from ~120s to ~90s (~25% faster)
in specific test cases by avoiding repeated elimination tree construction.
@tzvist tzvist force-pushed the feature/tzvi/JunctionIndexEliminationTree branch from a3d41d8 to 8633b7b Compare February 17, 2026 09:22
@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Feb 17, 2026

/bench

rebased maybe this will help

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 17, 2026

/bench

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 17, 2026

btw bench results will be refreshed at the original comment

@dellaert
Copy link
Copy Markdown
Member

Oops - does not look good with TBB on… @tzvist any theories?

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Feb 18, 2026

Oops - does not look good with TBB on… @tzvist any theories?

Turns out I had accidentally removed the parallel eliminate implementation. Luckily this benchmark exposed it. pushed a fix commit.

@dellaert
Copy link
Copy Markdown
Member

/bench

@tzvist tzvist force-pushed the feature/tzvi/JunctionIndexEliminationTree branch from 6ce0fa6 to 1cc5dec Compare February 18, 2026 18:56
@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Feb 18, 2026

My example running with TBB 12 cores
Before this MR:

./build/simple_gtsam_deserialize
simple_gtsam_deserialize2.cpp
Reading values file took 0.0123 seconds
Reading graph file took 0.2029 seconds
Processing factor lines took 2.8737 seconds
Processing values lines took 0.1093 seconds
Setting up optimizer took 9.1637 seconds
Initial error: 83467.7055, values: 65796
iter      cost      cost_change    lambda  success iter_time
   0          inf         0.00       0.00      0       1.99
iter      cost      cost_change    lambda  success iter_time
   0     80421.88      3045.82       0.00      1       6.30
   1          inf         0.00       0.00      0       1.21
   1     80163.07       258.81       0.00      1       3.49
   2          inf         0.00       0.00      0       1.19
   2     80113.89        49.18       0.00      1       3.16
   3          inf         0.00       0.00      0       1.20
   3     80096.39        17.50       0.00      1       3.23
   4          inf         0.00       0.00      0       1.22
   4     80089.79         6.60       0.00      1       3.28
   5          inf         0.00       0.00      0       1.16
   5     80086.41         3.38       0.00      1       3.35
   6          inf         0.00       0.00      0       1.17
   6     80084.44         1.98       0.00      1       3.24
   7          inf         0.00       0.00      0       1.16
   7     80083.05         1.39       0.00      1       3.26
   8          inf         0.00       0.00      0       1.21
   8     80081.84         1.21       0.00      1       3.27
   9          inf         0.00       0.00      0       1.19
   9     80080.52         1.32       0.00      1       3.24
  10          inf         0.00       0.00      0       1.20
  10     80078.92         1.60       0.00      1       3.52
  11          inf         0.00       0.00      0       1.18
  11     80076.99         1.93       0.00      1       3.24
  12          inf         0.00       0.00      0       1.17
  12     80074.94         2.05       0.00      1       3.29
  13          inf         0.00       0.00      0       1.21
  13     80073.22         1.72       0.00      1       3.12
  14          inf         0.00       0.00      0       1.17
  14     80071.87         1.34       0.00      1       3.21
  15          inf         0.00       0.00      0       1.21
  15     80071.04         0.83       0.00      1       3.28
  16          inf         0.00       0.00      0       1.18
  16     80070.76         0.28       0.00      1       3.22
Running gtsam optimizer took 87.3073 seconds

After

./build/simple_gtsam_deserialize
simple_gtsam_deserialize2.cpp
Reading values file took 0.0112 seconds
Reading graph file took 0.1967 seconds
Processing factor lines took 2.8551 seconds
Processing values lines took 0.1035 seconds
Setting up optimizer took 8.8668 seconds
Initial error: 83467.7055, values: 65796
iter      cost      cost_change    lambda  success iter_time
   0          inf         0.00       0.00      0       2.42
iter      cost      cost_change    lambda  success iter_time
   0     80421.88      3045.82       0.00      1       6.37
   1          inf         0.00       0.00      0       0.36
   1     80163.07       258.81       0.00      1       2.31
   2          inf         0.00       0.00      0       0.34
   2     80113.89        49.18       0.00      1       2.64
   3          inf         0.00       0.00      0       0.34
   3     80096.39        17.50       0.00      1       2.75
   4          inf         0.00       0.00      0       0.35
   4     80089.79         6.60       0.00      1       2.53
   5          inf         0.00       0.00      0       0.27
   5     80086.41         3.38       0.00      1       2.63
   6          inf         0.00       0.00      0       0.34
   6     80084.44         1.98       0.00      1       2.42
   7          inf         0.00       0.00      0       0.33
   7     80083.05         1.39       0.00      1       2.71
   8          inf         0.00       0.00      0       0.33
   8     80081.84         1.21       0.00      1       2.43
   9          inf         0.00       0.00      0       0.43
   9     80080.52         1.32       0.00      1       2.55
  10          inf         0.00       0.00      0       0.40
  10     80078.92         1.60       0.00      1       2.74
  11          inf         0.00       0.00      0       0.32
  11     80076.99         1.93       0.00      1       2.33
  12          inf         0.00       0.00      0       0.32
  12     80074.94         2.05       0.00      1       2.68
  13          inf         0.00       0.00      0       0.32
  13     80073.22         1.72       0.00      1       2.50
  14          inf         0.00       0.00      0       0.34
  14     80071.87         1.34       0.00      1       2.43
  15          inf         0.00       0.00      0       0.40
  15     80071.04         0.83       0.00      1       2.89
  16          inf         0.00       0.00      0       0.31
  16     80070.76         0.28       0.00      1       2.56
Running gtsam optimizer took 63.1366 seconds

@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Feb 18, 2026

/bench

please rerun again

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 18, 2026

/bench

@dellaert
Copy link
Copy Markdown
Member

@ProfFan I cannot find the new benchmark results.

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 19, 2026

FAILED: [code=1] gtsam/CMakeFiles/gtsam.dir/symbolic/SymbolicFactorGraph.cpp.o 
/usr/bin/c++ -DNDEBUG -Dgtsam_EXPORTS -I/Users/runner/work/gtsam/gtsam -I/Users/runner/work/gtsam/gtsam/build -I/Users/runner/work/gtsam/gtsam/CppUnitLite -I/Users/runner/work/gtsam/gtsam/gtsam/3rdparty/metis/include -I/Users/runner/work/gtsam/gtsam/gtsam/3rdparty/metis/libmetis -I/Users/runner/work/gtsam/gtsam/gtsam/3rdparty/metis/GKlib -I/Users/runner/work/gtsam/gtsam/gtsam/3rdparty/cephes -isystem /Users/runner/work/gtsam/gtsam/gtsam/3rdparty/SuiteSparse_config -isystem /Users/runner/work/gtsam/gtsam/gtsam/3rdparty/Spectra -isystem /Users/runner/work/gtsam/gtsam/gtsam/3rdparty/CCOLAMD/Include -isystem /opt/homebrew/include -isystem /Users/runner/work/gtsam/gtsam/gtsam/3rdparty/Eigen -w -O3 -DNDEBUG -std=c++17 -arch arm64 -fPIC -Werror -Wall -Wpedantic -Wextra -Wno-unused-parameter -Wreturn-type -Wformat -Werror=format-security -Wsuggest-override -O3 -MD -MT gtsam/CMakeFiles/gtsam.dir/symbolic/SymbolicFactorGraph.cpp.o -MF gtsam/CMakeFiles/gtsam.dir/symbolic/SymbolicFactorGraph.cpp.o.d -o gtsam/CMakeFiles/gtsam.dir/symbolic/SymbolicFactorGraph.cpp.o -c /Users/runner/work/gtsam/gtsam/gtsam/symbolic/SymbolicFactorGraph.cpp
In file included from /Users/runner/work/gtsam/gtsam/gtsam/symbolic/SymbolicFactorGraph.cpp:20:
/Users/runner/work/gtsam/gtsam/gtsam/inference/EliminateableFactorGraph-inst.h:169:22: error: no matching constructor for initialization of 'JunctionTreeType' (aka 'gtsam::SymbolicJunctionTree')
  169 |     JunctionTreeType junctionTree(asDerived(), indexedJunctionTree);
      |                      ^            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/runner/work/gtsam/gtsam/gtsam/symbolic/SymbolicFactorGraph.cpp:31:18: note: in instantiation of member function 'gtsam::EliminateableFactorGraph<gtsam::SymbolicFactorGraph>::eliminateMultifrontal' requested here
   31 |   template class EliminateableFactorGraph<SymbolicFactorGraph>;
      |                  ^
/Users/runner/work/gtsam/gtsam/gtsam/symbolic/SymbolicJunctionTree.h:65:5: note: candidate constructor not viable: requires single argument 'eliminationTree', but 2 arguments were provided
   65 |     SymbolicJunctionTree(const SymbolicEliminationTree& eliminationTree);
      |     ^                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/runner/work/gtsam/gtsam/gtsam/symbolic/SymbolicJunctionTree.h:50:22: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
   50 |   class GTSAM_EXPORT SymbolicJunctionTree :
      |                      ^~~~~~~~~~~~~~~~~~~~
/Users/runner/work/gtsam/gtsam/gtsam/symbolic/SymbolicJunctionTree.h:50:22: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
   50 |   class GTSAM_EXPORT SymbolicJunctionTree :
      |                      ^~~~~~~~~~~~~~~~~~~~
1 error generated.
[147/275] Building CXX object gtsam/CMakeFiles/gtsam.dir/symbolic/SymbolicISAM.cpp.o
ninja: build stopped: subcommand failed.
Error: Process completed with exit code 1.

They failed

@dellaert
Copy link
Copy Markdown
Member

Oops. How can that be?

@dellaert
Copy link
Copy Markdown
Member

CI fails as well. - @tzvist please check if you can compile (and build wrapper) locally?

@tzvist tzvist force-pushed the feature/tzvi/JunctionIndexEliminationTree branch from 1f50b08 to 1cc5dec Compare February 19, 2026 12:00
@tzvist
Copy link
Copy Markdown
Contributor Author

tzvist commented Feb 19, 2026

removed problematic commit

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 19, 2026

/bench

@ProfFan
Copy link
Copy Markdown
Collaborator

ProfFan commented Feb 19, 2026

@dellaert bench results is up

@dellaert
Copy link
Copy Markdown
Member

Incredible guys, this is a fantastic PR and, @ProfFan, your benchmark action is a fantastic addition. It just shows how good this contribution is. Thank you so much, @tzvist !! Will merge now.

@dellaert dellaert merged commit 1965238 into borglab:develop Feb 22, 2026
64 checks passed
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.

4 participants