Skip to content

Commit fa9b4e7

Browse files
committed
Adjust structure for DLLS Params
1 parent b1027bb commit fa9b4e7

File tree

6 files changed

+89
-93
lines changed

6 files changed

+89
-93
lines changed

gtsam/nonlinear/DoglegOptimizerImpl.h

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,22 @@ typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate(
258258
* trust region is not correlated between algorithm iterations.
259259
*/
260260
struct GTSAM_EXPORT DoglegLineSearchImpl {
261+
struct Params {
262+
double minDelta; ///< Minimum allowed small delta
263+
double maxDelta; ///< Maximum allowed delta
264+
double stepSize; ///< Increase of trust region for outward steps
265+
double sufficientDecreaseCoeff; ///< Coefficient for suff. decrease check
266+
bool verbose; ///< Whether to print debug information
267+
};
268+
261269
/**
262270
* Compute the update point for one iteration of the Dogleg Line Search
263-
* algorithm, starting with a trust region of |N| * min_delta the algorithm
264-
* searches trust regions from |N| * min_delta to max_delta where |N| is the
271+
* algorithm, starting with a trust region of |N| * minDelta the algorithm
272+
* searches trust regions from |N| * minDelta to maxDelta where |N| is the
265273
* number of variables in the system. The algorithm returns the search point
266274
* with minimum cost that meets the Wolfe Conditions. Evaluation points for
267275
* the line search are computed according to a geometric series step_{k+1} =
268-
* step_size * step_k.
276+
* stepSize * step_k.
269277
*
270278
*
271279
* @tparam M The type of the Bayes' net or tree, currently
@@ -274,12 +282,7 @@ struct GTSAM_EXPORT DoglegLineSearchImpl {
274282
* @tparam F For normal usage this will be NonlinearFactorGraph<VALUES>.
275283
* @tparam VALUES The Values or TupleValues to pass to F::error() to evaluate
276284
* the error function.
277-
* @param min_delta The minimum trust region size (scaled by size of system)
278-
* @param max_delta The maximum trust region size (scaled by size of system)
279-
* @param step_size The multiplicative factor for the geometric series that
280-
* defines the evaluation points for the line search
281-
* @param sufficient_decrease_coeff The coefficient for sufficient decrease to
282-
* ensure that the linesearch meets the Wolfe conditions
285+
* @param params The parameters for dogleg line search
283286
* @param Rd The Bayes' net or tree as described above.
284287
* @param f The original nonlinear factor graph with which to evaluate the
285288
* accuracy of \f$ M(\delta x) \f$ to adjust \f$ \delta \f$.
@@ -289,83 +292,81 @@ struct GTSAM_EXPORT DoglegLineSearchImpl {
289292
* update \c dx_d, and the resulting nonlinear error \c f_error.
290293
*/
291294
template <class M, class F, class VALUES>
292-
static DoglegOptimizerImpl::IterationResult Iterate(
293-
const double min_delta, const double max_delta, const double step_size,
294-
const double sufficient_decrease_coeff, const VectorValues& dx_u,
295-
const VectorValues& dx_n, const M& Rd, const F& f, const VALUES& x0,
296-
const bool verbose = false);
295+
static DoglegOptimizerImpl::IterationResult Iterate(const Params& params,
296+
const VectorValues& dx_u,
297+
const VectorValues& dx_n,
298+
const M& Rd, const F& f,
299+
const VALUES& x0);
297300
};
298301

299302
/* ************************************************************************* */
300303
template <class M, class F, class VALUES>
301304
typename DoglegOptimizerImpl::IterationResult DoglegLineSearchImpl::Iterate(
302-
const double min_delta, const double max_delta, const double step_size,
303-
const double sufficient_decrease_coeff, const VectorValues& dx_u,
304-
const VectorValues& dx_n, const M& Rd, const F& f, const VALUES& x0,
305-
const bool verbose) {
306-
if (verbose)
307-
std::cout << "DoglegLineSearch | minDelta: " << min_delta
308-
<< " maxDelta: " << max_delta << " stepSize: " << step_size
309-
<< std::endl;
310-
const double F_init_error = f.error(x0);
311-
const double gn_step = dx_n.norm();
312-
const size_t num_vars = dx_n.size();
313-
314-
double max_step, step;
305+
const Params& params, const VectorValues& dx_u, const VectorValues& dx_n,
306+
const M& Rd, const F& f, const VALUES& x0) {
307+
if (params.verbose)
308+
std::cout << "DoglegLineSearch | minDelta: " << params.minDelta
309+
<< " maxDelta: " << params.maxDelta
310+
<< " stepSize: " << params.stepSize << std::endl;
311+
const double fInitError = f.error(x0);
312+
const double gnStep = dx_n.norm();
313+
const size_t numVars = dx_n.size();
314+
315+
double maxStep, step;
315316
/// The search bounds are scaled by the number of variables in the system
316-
max_step = std::min(max_delta * num_vars, gn_step);
317-
step = std::min(min_delta * num_vars, gn_step);
318-
step = std::min(step, max_step); // Edge case min_step > max_step
317+
maxStep = std::min(params.maxDelta * numVars, gnStep);
318+
step = std::min(params.minDelta * numVars, gnStep);
319+
step = std::min(step, maxStep); // Edge case min_step > maxStep
319320

320-
if (verbose)
321-
std::cout << "Search Region: [ " << step << " -> " << max_step << "]"
321+
if (params.verbose)
322+
std::cout << "Search Region: [ " << step << " -> " << maxStep << "]"
322323
<< std::endl;
323324

324325
DoglegOptimizerImpl::IterationResult result;
325326
result.dx_d =
326-
DoglegOptimizerImpl::ComputeDoglegPoint(step, dx_u, dx_n, verbose);
327+
DoglegOptimizerImpl::ComputeDoglegPoint(step, dx_u, dx_n, params.verbose);
327328
result.f_error = f.error(x0.retract(result.dx_d));
328329
result.delta = step;
329-
if (verbose)
330+
if (params.verbose)
330331
std::cout << "Initial Step Error: " << result.f_error << std::endl;
331332

332333
// Validate Step size will terminate search
333-
if (step < 1e-12 || step_size < 1.0)
334+
if (step < 1e-12 || params.stepSize < 1.0)
334335
throw std::runtime_error(
335336
"Invalid DoglegLineSearch configuration. Would cause infinite search.");
336337

337338
// Search Increase delta
338339
double eps = std::numeric_limits<double>::epsilon();
339-
while (step < max_step - eps) {
340+
while (step < maxStep - eps) {
340341
// Compute the trust region for the evaluation point according to the
341342
// Geometric Series
342-
step = std::min(max_step, step * step_size);
343+
step = std::min(maxStep, step * params.stepSize);
343344

344345
// Compute the Evaluation Point and evaluate the error
345-
VectorValues dx_d =
346-
DoglegOptimizerImpl::ComputeDoglegPoint(step, dx_u, dx_n, verbose);
346+
VectorValues dx_d = DoglegOptimizerImpl::ComputeDoglegPoint(
347+
step, dx_u, dx_n, params.verbose);
347348
VALUES x_d(x0.retract(dx_d));
348-
double new_F_error = f.error(x_d);
349+
double fNewError = f.error(x_d);
349350

350-
if (verbose)
351-
std::cout << "Step: " << step << " | Error: " << new_F_error << std::endl;
351+
if (params.verbose)
352+
std::cout << "Step: " << step << " | Error: " << fNewError << std::endl;
352353

353354
// Check step acceptance conditions
354-
bool update_decreased_error = new_F_error < result.f_error;
355-
bool update_has_sufficient_decrease =
356-
new_F_error < (F_init_error - sufficient_decrease_coeff * step);
355+
bool updateDecreasedError = fNewError < result.f_error;
356+
bool updateHasSufficientDecrease =
357+
fNewError < (fInitError - params.sufficientDecreaseCoeff * step);
357358

358-
if (verbose)
359-
std::cout << "Decrease Error: " << update_decreased_error
360-
<< " | Suff. Dec.: " << update_has_sufficient_decrease
359+
if (params.verbose)
360+
std::cout << "Decrease Error: " << updateDecreasedError
361+
<< " | Suff. Dec.: " << updateHasSufficientDecrease
361362
<< std::endl;
362363

363-
if (update_decreased_error && update_has_sufficient_decrease) {
364-
result.f_error = new_F_error;
364+
if (updateDecreasedError && updateHasSufficientDecrease) {
365+
result.f_error = fNewError;
365366
result.dx_d = dx_d;
366367
result.delta = step;
367368

368-
if (verbose) std::cout << "Step Accepted" << std::endl;
369+
if (params.verbose) std::cout << "Step Accepted" << std::endl;
369370
}
370371
}
371372

gtsam/nonlinear/ISAM2.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -779,10 +779,10 @@ void ISAM2::updateDelta(bool forceFullSolve) const {
779779
gttoc(Copy_dx_d);
780780
} else if (std::holds_alternative<ISAM2DoglegLineSearchParams>(
781781
params_.optimizationParams)) {
782-
const ISAM2DoglegLineSearchParams& dlls_params =
782+
const ISAM2DoglegLineSearchParams& isamDllsParams =
783783
std::get<ISAM2DoglegLineSearchParams>(params_.optimizationParams);
784784
const double effectiveWildfireThreshold =
785-
forceFullSolve ? 0.0 : dlls_params.getWildfireThreshold();
785+
forceFullSolve ? 0.0 : isamDllsParams.getWildfireThreshold();
786786

787787
// Timer start
788788
gttic(DoglegLineSearch_Iterate);
@@ -803,11 +803,9 @@ void ISAM2::updateDelta(bool forceFullSolve) const {
803803

804804
// Do the DogLeg Line Search
805805
DoglegOptimizerImpl::IterationResult doglegResult(
806-
DoglegLineSearchImpl::Iterate(
807-
dlls_params.getMinDelta(), dlls_params.getMaxDelta(),
808-
dlls_params.getStepSize(), dlls_params.getSufficientDecreaseCoeff(),
809-
dx_u, deltaNewton_, *this, nonlinearFactors_, theta_,
810-
dlls_params.isVerbose()));
806+
DoglegLineSearchImpl::Iterate(isamDllsParams.dllsParams, dx_u,
807+
deltaNewton_, *this, nonlinearFactors_,
808+
theta_));
811809

812810
// Update Delta and linear step
813811
delta_ = doglegResult.dx_d;

gtsam/nonlinear/ISAM2Params.h

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -134,25 +134,18 @@ struct GTSAM_EXPORT ISAM2DoglegParams {
134134
* ISAM2(const ISAM2Params&).
135135
*/
136136
struct GTSAM_EXPORT ISAM2DoglegLineSearchParams {
137-
double minDelta; ///< Minimum allowed small delta
138-
double maxDelta; ///< Maximum allowed delta
139-
double stepSize; ///< Increase of trust region for outward steps
140-
double sufficientDecreaseCoeff; ///< Coefficient for suff. decrease check
137+
DoglegLineSearchImpl::Params dllsParams; ///< Params for DoglegLineSearch
141138
double wildfireThreshold; ///< Update delta when changes are above thresh
142-
bool verbose; ///< Whether to print debug information
143139

144140
/** Specify parameters as constructor arguments */
145141
ISAM2DoglegLineSearchParams(double minDelta = 0.02, double maxDelta = 0.5,
146142
double stepSize = 1.5,
147143
double sufficientDecreaseCoeff = 1e-3,
148-
double wildfireThreshold = 1e-4,
149-
bool verbose = false)
150-
: minDelta(minDelta),
151-
maxDelta(maxDelta),
152-
stepSize(stepSize),
153-
sufficientDecreaseCoeff(sufficientDecreaseCoeff),
154-
wildfireThreshold(wildfireThreshold),
155-
verbose(verbose) {
144+
bool verbose = false,
145+
double wildfireThreshold = 1e-4)
146+
: dllsParams{minDelta, maxDelta, stepSize, sufficientDecreaseCoeff,
147+
verbose},
148+
wildfireThreshold(wildfireThreshold) {
156149
if (minDelta < 1e-12 || maxDelta < 1e-12 || stepSize < 1.0) {
157150
throw std::invalid_argument(
158151
"ISAM2DoglegLineSearchParams constructed with invalid configuration. "
@@ -163,33 +156,37 @@ struct GTSAM_EXPORT ISAM2DoglegLineSearchParams {
163156
void print(const std::string str = "") const {
164157
using std::cout;
165158
cout << str << "type: ISAM2DoglegLineSearchParams\n";
166-
cout << str << "minDelta: " << minDelta << "\n";
167-
cout << str << "maxDelta: " << maxDelta << "\n";
168-
cout << str << "stepSize: " << stepSize << "\n";
169-
cout << str << "sufficientDecreaseCoeff: " << sufficientDecreaseCoeff
159+
cout << str << "minDelta: " << dllsParams.minDelta << "\n";
160+
cout << str << "maxDelta: " << dllsParams.maxDelta << "\n";
161+
cout << str << "stepSize: " << dllsParams.stepSize << "\n";
162+
cout << str
163+
<< "sufficientDecreaseCoeff: " << dllsParams.sufficientDecreaseCoeff
170164
<< "\n";
165+
cout << str << "verbose: " << dllsParams.verbose << "\n";
171166
cout << str << "wildfireThreshold: " << wildfireThreshold << "\n";
172167
cout.flush();
173168
}
174169
/** Getters **/
175-
double getMinDelta() const { return minDelta; }
176-
double getMaxDelta() const { return maxDelta; }
177-
double getStepSize() const { return stepSize; }
178-
double getSufficientDecreaseCoeff() const { return sufficientDecreaseCoeff; }
170+
double getMinDelta() const { return dllsParams.minDelta; }
171+
double getMaxDelta() const { return dllsParams.maxDelta; }
172+
double getStepSize() const { return dllsParams.stepSize; }
173+
double getSufficientDecreaseCoeff() const {
174+
return dllsParams.sufficientDecreaseCoeff;
175+
}
176+
bool isVerbose() const { return dllsParams.verbose; }
179177
double getWildfireThreshold() const { return wildfireThreshold; }
180-
bool isVerbose() const { return verbose; }
181178

182179
/** Setters */
183-
void setMinDelta(double minDelta) { this->minDelta = minDelta; }
184-
void setMaxDelta(double maxDelta) { this->maxDelta = maxDelta; }
185-
void setStepSize(double stepSize) { this->stepSize = stepSize; }
180+
void setMinDelta(double minDelta) { this->dllsParams.minDelta = minDelta; }
181+
void setMaxDelta(double maxDelta) { this->dllsParams.maxDelta = maxDelta; }
182+
void setStepSize(double stepSize) { this->dllsParams.stepSize = stepSize; }
186183
void setSufficientDecreaseCoeff(double sufficientDecreaseCoeff) {
187-
this->sufficientDecreaseCoeff = sufficientDecreaseCoeff;
184+
this->dllsParams.sufficientDecreaseCoeff = sufficientDecreaseCoeff;
188185
}
186+
void setVerbose(bool verbose) { this->dllsParams.verbose = verbose; }
189187
void setWildfireThreshold(double wildfireThreshold) {
190188
this->wildfireThreshold = wildfireThreshold;
191189
}
192-
void setVerbose(bool verbose) { this->verbose = verbose; }
193190
};
194191

195192
/**

gtsam/nonlinear/nonlinear.i

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,14 +437,14 @@ class ISAM2DoglegLineSearchParams {
437437
double getMaxDelta() const;
438438
double getStepSize() const;
439439
double getSufficientDecreaseCoeff() const;
440-
double getWildfireThreshold() const;
441440
bool isVerbose() const;
441+
double getWildfireThreshold() const;
442442
void setMinDelta(double min_delta);
443443
void setMaxDelta(double max_delta);
444444
void setStepSize(double step_size);
445445
void setSufficientDecreaseCoeff(double sufficient_decrease_coeff);
446-
void setWildfireThreshold(double wildfire_threshold);
447446
void setVerbose(bool verbose);
447+
void setWildfireThreshold(double wildfire_threshold);
448448
};
449449

450450
class ISAM2ThresholdMapValue {

tests/testDoglegOptimizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ TEST(DoglegOptimizer, IterateLineSearch) {
186186
VectorValues dx_u = gbn->optimizeGradientSearch();
187187
VectorValues dx_n = gbn->optimize();
188188
DoglegOptimizerImpl::IterationResult result = DoglegLineSearchImpl::Iterate(
189-
0.02, 0.5, 1.5, 1e-3, dx_u, dx_n, *gbn, fg, config);
189+
{0.02, 0.5, 1.5, 1e-3, false}, dx_u, dx_n, *gbn, fg, config);
190190
EXPECT(result.f_error < fg.error(config)); // Check that error decreases
191191

192192
Values newConfig(config.retract(result.dx_d));

tests/testGaussianISAM2.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,13 @@ TEST(ISAM2, slamlike_solution_dogleg)
318318
}
319319

320320
/* ************************************************************************* */
321-
TEST(ISAM2, slamlikeSolutionDoglegLineSearch) {
321+
TEST(ISAM2, SlamlikeSolutionDoglegLineSearch) {
322322
// These variables will be reused and accumulate factors and values
323323
Values fullinit;
324324
NonlinearFactorGraph fullgraph;
325325
ISAM2 isam = createSlamlikeISAM2(
326326
&fullinit, &fullgraph,
327-
ISAM2Params(ISAM2DoglegLineSearchParams(0.1, 1.0, 3, 1e-4, 1e-3, false),
327+
ISAM2Params(ISAM2DoglegLineSearchParams(0.1, 1.0, 3, 1e-4, false, 1e-3),
328328
0.0, 0, false));
329329

330330
// Compare solutions
@@ -356,13 +356,13 @@ TEST(ISAM2, slamlike_solution_dogleg_qr)
356356
}
357357

358358
/* ************************************************************************* */
359-
TEST(ISAM2, slamlikeSolutionDoglegLineSearchQr) {
359+
TEST(ISAM2, SlamlikeSolutionDoglegLineSearchQr) {
360360
// These variables will be reused and accumulate factors and values
361361
Values fullinit;
362362
NonlinearFactorGraph fullgraph;
363363
ISAM2 isam = createSlamlikeISAM2(
364364
&fullinit, &fullgraph,
365-
ISAM2Params(ISAM2DoglegLineSearchParams(0.1, 10.0, 3, 1e-4, 1e-3, false),
365+
ISAM2Params(ISAM2DoglegLineSearchParams(0.1, 10.0, 3, 1e-4, false, 1e-3),
366366
0.0, 0, false, false, ISAM2Params::QR));
367367

368368
// Compare solutions
@@ -1023,7 +1023,7 @@ TEST(ISAM2, calculate_nnz)
10231023
}
10241024

10251025
/* ************************************************************************* */
1026-
TEST(ISAM2, predictUpdateInfo) {
1026+
TEST(ISAM2, PredictUpdateInfo) {
10271027
// Setup iSAM2
10281028
ISAM2Params params;
10291029
params.findUnusedFactorSlots = true;

0 commit comments

Comments
 (0)