Skip to content

Commit d3992f4

Browse files
authored
Merge pull request #2394 from borglab/feature/format_docs_spelling
Constrained docs
2 parents b0522e6 + 4578f01 commit d3992f4

23 files changed

+1330
-187
lines changed

gtsam/constrained/Constrained.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Constrained
2+
3+
The `constrained` module in GTSAM provides constrained nonlinear optimization on top of factor graphs.
4+
It includes classes for representing constraints, building constrained problems, and solving them with penalty and augmented Lagrangian methods.
5+
6+
## Core Problem Model
7+
8+
- [`ConstrainedOptProblem`](doc/ConstrainedOptProblem.ipynb): Holds objective costs, equality constraints, and inequality constraints.
9+
- [`ConstrainedOptProblem::AuxiliaryKeyGenerator`](doc/ConstrainedOptProblem.ipynb): Generates keys for auxiliary variables used when transforming inequality constraints.
10+
- [`NonlinearConstraint`](doc/NonlinearConstraint.ipynb): Base class for nonlinear constraints represented as constrained `NoiseModelFactor` objects.
11+
12+
## Equality Constraints
13+
14+
- [`NonlinearEqualityConstraint`](doc/NonlinearEqualityConstraint.ipynb): Base class for constraints of the form `h(x) = 0`.
15+
- [`ExpressionEqualityConstraint<T>`](doc/NonlinearEqualityConstraint.ipynb): Equality constraint from an expression and right-hand side.
16+
- [`ZeroCostConstraint`](doc/NonlinearEqualityConstraint.ipynb): Equality constraint that enforces zero residual on a cost factor.
17+
- [`NonlinearEqualityConstraints`](doc/NonlinearEqualityConstraint.ipynb): Container graph for equality constraints.
18+
19+
## Inequality Constraints
20+
21+
- [`NonlinearInequalityConstraint`](doc/NonlinearInequalityConstraint.ipynb): Base class for constraints of the form `g(x) <= 0`.
22+
- [`ScalarExpressionInequalityConstraint`](doc/NonlinearInequalityConstraint.ipynb): Scalar expression-based inequality constraint.
23+
- [`NonlinearInequalityConstraints`](doc/NonlinearInequalityConstraint.ipynb): Container graph for inequality constraints.
24+
- [`InequalityPenaltyFunction`](doc/InequalityPenaltyFunction.ipynb): Interface for ramp-like penalty mappings used with inequality constraints.
25+
Derived classes:
26+
- [`RampFunction`](doc/InequalityPenaltyFunction.ipynb)
27+
- [`SmoothRampPoly2`](doc/InequalityPenaltyFunction.ipynb)
28+
- [`SmoothRampPoly3`](doc/InequalityPenaltyFunction.ipynb)
29+
- [`SoftPlusFunction`](doc/InequalityPenaltyFunction.ipynb)
30+
31+
## Optimizers
32+
33+
- [`ConstrainedOptimizerParams`](doc/ConstrainedOptimizer.ipynb), [`ConstrainedOptimizerState`](doc/ConstrainedOptimizer.ipynb), [`ConstrainedOptimizer`](doc/ConstrainedOptimizer.ipynb): Shared base interfaces and iteration state for constrained solvers.
34+
- [`PenaltyOptimizerParams`](doc/PenaltyOptimizer.ipynb), [`PenaltyOptimizerState`](doc/PenaltyOptimizer.ipynb), [`PenaltyOptimizer`](doc/PenaltyOptimizer.ipynb): Penalty method solver and its parameters/state.
35+
- [`AugmentedLagrangianParams`](doc/AugmentedLagrangianOptimizer.ipynb), [`AugmentedLagrangianState`](doc/AugmentedLagrangianOptimizer.ipynb), [`AugmentedLagrangianOptimizer`](doc/AugmentedLagrangianOptimizer.ipynb): Augmented Lagrangian solver and its parameters/state.
36+
37+
## How the Pieces Fit Together
38+
39+
For a new user, it helps to think in two phases:
40+
41+
1. Build a constrained problem.
42+
2. Run a constrained solver on that problem.
43+
44+
Inequality constraints can use different smooth penalty shapes via
45+
`InequalityPenaltyFunction` (ramp, smooth polynomial ramps, or softplus),
46+
which controls behavior near the active constraint boundary.
47+
48+
### 1) Build the Problem
49+
50+
This stage is about modeling: you separate what you want to minimize
51+
(objective terms) from what must hold (constraints), then combine them into a
52+
single `ConstrainedOptProblem` object that the solvers can consume.
53+
54+
```mermaid
55+
flowchart TB
56+
User["User-defined model"]
57+
Costs["Objective terms<br/>NonlinearFactorGraph"]
58+
Eq["Equality constraints<br/>NonlinearEqualityConstraint(s)<br/>h(x)=0"]
59+
Ineq["Inequality constraints<br/>NonlinearInequalityConstraint(s)<br/>g(x)<=0"]
60+
Problem["ConstrainedOptProblem"]
61+
62+
User --> Costs
63+
User --> Eq
64+
User --> Ineq
65+
Costs --> Problem
66+
Eq --> Problem
67+
Ineq --> Problem
68+
```
69+
70+
### 2) Solve the Problem
71+
72+
This stage is algorithmic: pick a constrained solver, form iterative
73+
unconstrained subproblems internally, and solve those subproblems with a
74+
standard nonlinear optimizer until constraint violation and cost are reduced.
75+
76+
```mermaid
77+
flowchart TB
78+
Problem["ConstrainedOptProblem"]
79+
Choose{"Choose constrained solver"}
80+
Penalty["PenaltyOptimizer"]
81+
AL["AugmentedLagrangianOptimizer"]
82+
PenFunc["InequalityPenaltyFunction<br/>(ramp / smooth ramp / softplus)"]
83+
Sub["Iterative unconstrained subproblems"]
84+
LM["Nonlinear optimizer<br/>(Levenberg-Marquardt by default)"]
85+
Result["Optimized Values<br/>+ cost and violation metrics"]
86+
87+
Problem --> Choose
88+
Choose --> Penalty
89+
Choose --> AL
90+
PenFunc --> Penalty
91+
PenFunc --> AL
92+
Penalty --> Sub
93+
AL --> Sub
94+
Sub --> LM
95+
LM --> Result
96+
```

gtsam/constrained/ConstrainedOptProblem.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,19 @@ namespace gtsam {
2828
* s.t. h(X) = 0
2929
* g(X) <= 0
3030
* where X represents the variables, 0.5||f(X)||^2 represents the quadratic cost
31-
* functions, h(X)=0 represents the nonlinear equality constraints, g(x)<=0 represents the
32-
* inequality constraints.
31+
* functions, h(X)=0 represents the nonlinear equality constraints, g(x)<=0
32+
* represents the inequality constraints.
3333
*/
3434
class GTSAM_EXPORT ConstrainedOptProblem {
3535
public:
3636
typedef ConstrainedOptProblem This;
3737
typedef std::shared_ptr<This> shared_ptr;
3838

3939
protected:
40-
NonlinearFactorGraph costs_; // cost function, ||f(X)||^2
41-
NonlinearEqualityConstraints eqConstraints_; // equality constraints, h(X)=0
42-
NonlinearInequalityConstraints ineqConstraints_; // inequality constraints, g(X)<=0
40+
NonlinearFactorGraph costs_; // cost function, ||f(X)||^2
41+
NonlinearEqualityConstraints eqConstraints_; // equality constraints, h(X)=0
42+
NonlinearInequalityConstraints
43+
ineqConstraints_; // inequality constraints, g(X)<=0
4344

4445
public:
4546
/** Default constructor. */
@@ -57,16 +58,22 @@ class GTSAM_EXPORT ConstrainedOptProblem {
5758
static ConstrainedOptProblem EqConstrainedOptProblem(
5859
const NonlinearFactorGraph& costs,
5960
const NonlinearEqualityConstraints& eqConstraints) {
60-
return ConstrainedOptProblem(costs, eqConstraints, NonlinearInequalityConstraints());
61+
return ConstrainedOptProblem(costs, eqConstraints,
62+
NonlinearInequalityConstraints());
6163
}
6264

6365
/** Member variable access functions. */
6466
const NonlinearFactorGraph& costs() const { return costs_; }
65-
const NonlinearEqualityConstraints& eConstraints() const { return eqConstraints_; }
66-
const NonlinearInequalityConstraints& iConstraints() const { return ineqConstraints_; }
67+
const NonlinearEqualityConstraints& eConstraints() const {
68+
return eqConstraints_;
69+
}
70+
const NonlinearInequalityConstraints& iConstraints() const {
71+
return ineqConstraints_;
72+
}
6773

6874
/** Evaluate cost and constraint violations.
69-
* Return a tuple representing (cost, e-constraint violation, i-constraint violation).
75+
* Return a tuple representing (cost, e-constraint violation, i-constraint
76+
* violation).
7077
*/
7178
std::tuple<double, double, double> evaluate(const Values& values) const;
7279

gtsam/constrained/NonlinearConstraint.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
#pragma once
2020

21-
#include <gtsam/inference/FactorGraph.h>
2221
#include <gtsam/inference/FactorGraph-inst.h>
22+
#include <gtsam/inference/FactorGraph.h>
2323
#include <gtsam/nonlinear/NonlinearFactor.h>
2424
#if GTSAM_ENABLE_BOOST_SERIALIZATION
2525
#include <boost/serialization/base_object.hpp>
@@ -29,8 +29,8 @@ namespace gtsam {
2929

3030
/**
3131
* Base class for nonlinear constraint.
32-
* The constraint is represented as a NoiseModelFactor with Constrained noise model.
33-
* whitenedError() returns The constraint violation vector.
32+
* The constraint is represented as a NoiseModelFactor with Constrained noise
33+
* model. whitenedError() returns The constraint violation vector.
3434
* unwhitenedError() returns the sigma-scaled constraint violation vector.
3535
*/
3636
class GTSAM_EXPORT NonlinearConstraint : public NoiseModelFactor {
@@ -45,8 +45,10 @@ class GTSAM_EXPORT NonlinearConstraint : public NoiseModelFactor {
4545
/** Destructor. */
4646
virtual ~NonlinearConstraint() {}
4747

48-
/** Create a cost factor representing the L2 penalty function with scaling coefficient mu. */
49-
virtual NoiseModelFactor::shared_ptr penaltyFactor(const double mu = 1.0) const {
48+
/** Create a cost factor representing the L2 penalty function with scaling
49+
* coefficient mu. */
50+
virtual NoiseModelFactor::shared_ptr penaltyFactor(
51+
const double mu = 1.0) const {
5052
return cloneWithNewNoiseModel(penaltyNoise(mu));
5153
}
5254

@@ -71,7 +73,7 @@ class GTSAM_EXPORT NonlinearConstraint : public NoiseModelFactor {
7173
return noiseModel::Diagonal::Sigmas(noiseModel()->sigmas() / sqrt(mu));
7274
}
7375

74-
/** Default constrained noisemodel used for construction of constraint. */
76+
/** Default constrained noise model used for construction of constraint. */
7577
static SharedNoiseModel constrainedNoise(const Vector& sigmas) {
7678
return noiseModel::Constrained::MixedSigmas(1.0, sigmas);
7779
}
@@ -82,8 +84,8 @@ class GTSAM_EXPORT NonlinearConstraint : public NoiseModelFactor {
8284
friend class boost::serialization::access;
8385
template <class ARCHIVE>
8486
void serialize(ARCHIVE& ar, const unsigned int /*version*/) {
85-
ar& boost::serialization::make_nvp("NonlinearConstraint",
86-
boost::serialization::base_object<Base>(*this));
87+
ar& boost::serialization::make_nvp(
88+
"NonlinearConstraint", boost::serialization::base_object<Base>(*this));
8789
}
8890
#endif
8991
};

gtsam/constrained/NonlinearEqualityConstraint-inl.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,19 @@
2121

2222
namespace gtsam {
2323

24-
/* ********************************************************************************************* */
24+
/* ************************************************************************* */
2525
template <typename T>
26-
ExpressionEqualityConstraint<T>::ExpressionEqualityConstraint(const Expression<T>& expression,
27-
const T& rhs,
28-
const Vector& sigmas)
26+
ExpressionEqualityConstraint<T>::ExpressionEqualityConstraint(
27+
const Expression<T>& expression, const T& rhs, const Vector& sigmas)
2928
: Base(constrainedNoise(sigmas), expression.keysAndDims().first),
3029
expression_(expression),
3130
rhs_(rhs),
3231
dims_(expression.keysAndDims().second) {}
3332

34-
/* ********************************************************************************************* */
33+
/* ************************************************************************* */
3534
template <typename T>
36-
Vector ExpressionEqualityConstraint<T>::unwhitenedError(const Values& x,
37-
OptionalMatrixVecType H) const {
35+
Vector ExpressionEqualityConstraint<T>::unwhitenedError(
36+
const Values& x, OptionalMatrixVecType H) const {
3837
// Copy-paste from ExpressionFactor.
3938
if (H) {
4039
const T value = expression_.valueAndDerivatives(x, keys_, dims_, *H);
@@ -45,10 +44,12 @@ Vector ExpressionEqualityConstraint<T>::unwhitenedError(const Values& x,
4544
}
4645
}
4746

48-
/* ********************************************************************************************* */
47+
/* ************************************************************************* */
4948
template <typename T>
50-
NoiseModelFactor::shared_ptr ExpressionEqualityConstraint<T>::penaltyFactor(const double mu) const {
51-
return std::make_shared<ExpressionFactor<T>>(penaltyNoise(mu), rhs_, expression_);
49+
NoiseModelFactor::shared_ptr ExpressionEqualityConstraint<T>::penaltyFactor(
50+
const double mu) const {
51+
return std::make_shared<ExpressionFactor<T>>(penaltyNoise(mu), rhs_,
52+
expression_);
5253
}
5354

5455
} // namespace gtsam

gtsam/constrained/NonlinearEqualityConstraint.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,25 @@
2020

2121
namespace gtsam {
2222

23-
/* ********************************************************************************************* */
24-
ZeroCostConstraint::ZeroCostConstraint(const NoiseModelFactor::shared_ptr& factor)
25-
: Base(constrainedNoise(factor->noiseModel()->sigmas()), factor->keys()), factor_(factor) {}
23+
/* ************************************************************************* */
24+
ZeroCostConstraint::ZeroCostConstraint(
25+
const NoiseModelFactor::shared_ptr& factor)
26+
: Base(constrainedNoise(factor->noiseModel()->sigmas()), factor->keys()),
27+
factor_(factor) {}
2628

27-
/* ********************************************************************************************* */
28-
Vector ZeroCostConstraint::unwhitenedError(const Values& x, OptionalMatrixVecType H) const {
29+
/* ************************************************************************* */
30+
Vector ZeroCostConstraint::unwhitenedError(const Values& x,
31+
OptionalMatrixVecType H) const {
2932
return factor_->unwhitenedError(x, H);
3033
}
3134

32-
/* ********************************************************************************************* */
33-
NoiseModelFactor::shared_ptr ZeroCostConstraint::penaltyFactor(const double mu) const {
35+
/* ************************************************************************* */
36+
NoiseModelFactor::shared_ptr ZeroCostConstraint::penaltyFactor(
37+
const double mu) const {
3438
return factor_->cloneWithNewNoiseModel(penaltyNoise(mu));
3539
}
3640

37-
/* ********************************************************************************************* */
41+
/* ************************************************************************* */
3842
NonlinearEqualityConstraints NonlinearEqualityConstraints::FromCostGraph(
3943
const NonlinearFactorGraph& graph) {
4044
NonlinearEqualityConstraints constraints;
@@ -45,7 +49,7 @@ NonlinearEqualityConstraints NonlinearEqualityConstraints::FromCostGraph(
4549
return constraints;
4650
}
4751

48-
/* ********************************************************************************************* */
52+
/* ************************************************************************* */
4953
size_t NonlinearEqualityConstraints::dim() const {
5054
size_t dimension = 0;
5155
for (const auto& constraint : *this) {
@@ -54,26 +58,29 @@ size_t NonlinearEqualityConstraints::dim() const {
5458
return dimension;
5559
}
5660

57-
/* ********************************************************************************************* */
58-
Vector NonlinearEqualityConstraints::violationVector(const Values& values, bool whiten) const {
61+
/* ************************************************************************* */
62+
Vector NonlinearEqualityConstraints::violationVector(const Values& values,
63+
bool whiten) const {
5964
Vector violation(dim());
6065
size_t start_idx = 0;
6166
for (const auto& constraint : *this) {
6267
size_t dim = constraint->dim();
6368
violation.segment(start_idx, dim) =
64-
whiten ? constraint->whitenedError(values) : constraint->unwhitenedError(values);
69+
whiten ? constraint->whitenedError(values)
70+
: constraint->unwhitenedError(values);
6571
start_idx += dim;
6672
}
6773
return violation;
6874
}
6975

70-
/* ********************************************************************************************* */
76+
/* ************************************************************************* */
7177
double NonlinearEqualityConstraints::violationNorm(const Values& values) const {
7278
return violationVector(values, true).norm();
7379
}
7480

75-
/* ********************************************************************************************* */
76-
NonlinearFactorGraph NonlinearEqualityConstraints::penaltyGraph(const double mu) const {
81+
/* ************************************************************************* */
82+
NonlinearFactorGraph NonlinearEqualityConstraints::penaltyGraph(
83+
const double mu) const {
7784
NonlinearFactorGraph graph;
7885
for (const auto& constraint : *this) {
7986
graph.add(constraint->penaltyFactor(mu));

0 commit comments

Comments
 (0)