Skip to content

Commit 60d0dc5

Browse files
author
Teseo Schneider
committed
added test
1 parent ea649d1 commit 60d0dc5

File tree

8 files changed

+130
-12
lines changed

8 files changed

+130
-12
lines changed

non-linear-solver-spec.json

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@
190190
"pointer": "/solver/*",
191191
"type": "object",
192192
"type_name": "Newton",
193+
"required": [
194+
"type"
195+
],
193196
"optional": [
194197
"residual_tolerance"
195198
],
@@ -199,6 +202,9 @@
199202
"pointer": "/solver/*",
200203
"type": "object",
201204
"type_name": "ProjectedNewton",
205+
"required": [
206+
"type"
207+
],
202208
"optional": [
203209
"residual_tolerance"
204210
],
@@ -208,6 +214,9 @@
208214
"pointer": "/solver/*",
209215
"type": "object",
210216
"type_name": "RegularizedNewton",
217+
"required": [
218+
"type"
219+
],
211220
"optional": [
212221
"residual_tolerance",
213222
"reg_weight_min",
@@ -220,6 +229,9 @@
220229
"pointer": "/solver/*",
221230
"type": "object",
222231
"type_name": "DenseNewton",
232+
"required": [
233+
"type"
234+
],
223235
"optional": [
224236
"residual_tolerance"
225237
],
@@ -229,6 +241,9 @@
229241
"pointer": "/solver/*",
230242
"type": "object",
231243
"type_name": "DenseProjectedNewton",
244+
"required": [
245+
"type"
246+
],
232247
"optional": [
233248
"residual_tolerance"
234249
],
@@ -238,6 +253,9 @@
238253
"pointer": "/solver/*",
239254
"type": "object",
240255
"type_name": "DenseRegularizedNewton",
256+
"required": [
257+
"type"
258+
],
241259
"optional": [
242260
"residual_tolerance",
243261
"reg_weight_min",
@@ -250,12 +268,18 @@
250268
"pointer": "/solver/*",
251269
"type": "object",
252270
"type_name": "GradientDescent",
271+
"required": [
272+
"type"
273+
],
253274
"doc": "Options for Gradient Descent."
254275
},
255276
{
256277
"pointer": "/solver/*",
257278
"type": "object",
258279
"type_name": "StochasticGradientDescent",
280+
"required": [
281+
"type"
282+
],
259283
"optional": [
260284
"erase_component_probability"
261285
],
@@ -265,8 +289,10 @@
265289
"pointer": "/solver/*",
266290
"type": "object",
267291
"type_name": "L-BFGS",
292+
"required": [
293+
"type"
294+
],
268295
"optional": [
269-
"erase_component_probability",
270296
"history_size"
271297
],
272298
"doc": "Options for L-BFGS."
@@ -275,11 +301,28 @@
275301
"pointer": "/solver/*",
276302
"type": "object",
277303
"type_name": "BFGS",
278-
"optional": [
279-
"erase_component_probability"
304+
"required": [
305+
"type"
280306
],
281307
"doc": "Options for BFGS."
282308
},
309+
{
310+
"pointer": "/solver/*/type",
311+
"type": "string",
312+
"options": [
313+
"Newton",
314+
"DenseNewton",
315+
"ProjectedNewton",
316+
"DenseProjectedNewton",
317+
"RegularizedNewton",
318+
"DenseRegularizedNewton",
319+
"GradientDescent",
320+
"StochasticGradientDescent",
321+
"L-BFGS",
322+
"BFGS"
323+
],
324+
"doc": "Nonlinear solver type"
325+
},
283326
{
284327
"pointer": "/solver/*/residual_tolerance",
285328
"default": 1e-5,

src/polysolve/Utils.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,12 @@ namespace polysolve
7171
return I;
7272
}
7373

74+
double extract_param(const std::string &key, const std::string &name, const json &json)
75+
{
76+
if (json.find(key) != json.end())
77+
return json[key][name];
78+
79+
return json[name];
80+
}
81+
7482
} // namespace polysolve

src/polysolve/Utils.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ namespace polysolve
6060

6161
Eigen::SparseMatrix<double> sparse_identity(int rows, int cols);
6262

63+
double extract_param(const std::string &key, const std::string &name, const json &json);
64+
6365
} // namespace polysolve

src/polysolve/nonlinear/Solver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ namespace polysolve::nonlinear
124124
{
125125
for (const auto &j : solver_params["solver"])
126126
{
127-
const std::string solver_name = solver_params["type"];
127+
const std::string solver_name = j["type"];
128128
solver->add_strategy(crate_solver(solver_name, j, linear_solver_params, characteristic_length, logger));
129129
}
130130
}

src/polysolve/nonlinear/descent_strategies/GradientDescent.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "GradientDescent.hpp"
22

3+
#include <polysolve/Utils.hpp>
4+
35
namespace polysolve::nonlinear
46
{
57

@@ -10,7 +12,7 @@ namespace polysolve::nonlinear
1012
: Superclass(solver_params_, characteristic_length, logger), is_stochastic_(is_stochastic)
1113
{
1214
if (is_stochastic_)
13-
erase_component_probability_ = solver_params_["StochasticGradientDescent"]["erase_component_probability"];
15+
erase_component_probability_ = extract_param("StochasticGradientDescent", "erase_component_probability", solver_params_);
1416
}
1517

1618
bool GradientDescent::compute_update_direction(

src/polysolve/nonlinear/descent_strategies/LBFGS.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include "LBFGS.hpp"
44

5+
#include <polysolve/Utils.hpp>
6+
57
namespace polysolve::nonlinear
68
{
79
LBFGS::LBFGS(const json &solver_params,
@@ -11,7 +13,7 @@ namespace polysolve::nonlinear
1113
characteristic_length,
1214
logger)
1315
{
14-
m_history_size = solver_params["L-BFGS"]["history_size"];
16+
m_history_size = extract_param("L-BFGS", "history_size", solver_params);
1517
if (m_history_size <= 0)
1618
log_and_throw_error(logger, "L-BFGS history_size must be >=1, instead got {}", m_history_size);
1719
}

src/polysolve/nonlinear/descent_strategies/Newton.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "Newton.hpp"
22

3+
#include <polysolve/Utils.hpp>
4+
35
namespace polysolve::nonlinear
46
{
57

@@ -71,7 +73,7 @@ namespace polysolve::nonlinear
7173
const json &linear_solver_params,
7274
const double characteristic_length,
7375
spdlog::logger &logger)
74-
: Newton(sparse, solver_params["Newton"]["residual_tolerance"], solver_params, linear_solver_params, characteristic_length, logger)
76+
: Newton(sparse, extract_param("Newton", "residual_tolerance", solver_params), solver_params, linear_solver_params, characteristic_length, logger)
7577
{
7678
}
7779

@@ -81,7 +83,7 @@ namespace polysolve::nonlinear
8183
const json &linear_solver_params,
8284
const double characteristic_length,
8385
spdlog::logger &logger)
84-
: Superclass(sparse, solver_params["ProjectedNewton"]["residual_tolerance"], solver_params, linear_solver_params, characteristic_length, logger)
86+
: Superclass(sparse, extract_param("ProjectedNewton", "residual_tolerance", solver_params), solver_params, linear_solver_params, characteristic_length, logger)
8587
{
8688
}
8789

@@ -91,11 +93,11 @@ namespace polysolve::nonlinear
9193
const json &linear_solver_params,
9294
const double characteristic_length,
9395
spdlog::logger &logger)
94-
: Superclass(sparse, solver_params["RegularizedNewton"]["residual_tolerance"], solver_params, linear_solver_params, characteristic_length, logger)
96+
: Superclass(sparse, extract_param("RegularizedNewton", "residual_tolerance", solver_params), solver_params, linear_solver_params, characteristic_length, logger)
9597
{
96-
reg_weight_min = solver_params["RegularizedNewton"]["reg_weight_min"];
97-
reg_weight_max = solver_params["RegularizedNewton"]["reg_weight_max"];
98-
reg_weight_inc = solver_params["RegularizedNewton"]["reg_weight_inc"];
98+
reg_weight_min = extract_param("RegularizedNewton", "reg_weight_min", solver_params);
99+
reg_weight_max = extract_param("RegularizedNewton", "reg_weight_max", solver_params);
100+
reg_weight_inc = extract_param("RegularizedNewton", "reg_weight_inc", solver_params);
99101

100102
reg_weight = reg_weight_min;
101103

tests/test_nonlinear_solver.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,65 @@ TEST_CASE("non-linear", "[solver]")
424424
// test_solvers({"L-BFGS"}, 1000, false);
425425
}
426426

427+
TEST_CASE("non-linear-fallbacks", "[solver]")
428+
{
429+
json solver_params = R"({"solver": [
430+
{
431+
"type": "Newton"
432+
},
433+
{
434+
"type": "RegularizedNewton"
435+
},
436+
{
437+
"type": "L-BFGS",
438+
"history_size": 10
439+
},
440+
{
441+
"type": "StochasticGradientDescent",
442+
"erase_component_probability": 0.5
443+
}
444+
]
445+
})"_json;
446+
json linear_solver_params;
447+
linear_solver_params["solver"] = "Eigen::SimplicialLDLT";
448+
449+
const double characteristic_length = 1;
450+
451+
static std::shared_ptr<spdlog::logger> logger = spdlog::stdout_color_mt("test_logger");
452+
logger->set_level(spdlog::level::info);
453+
TestProblem::TVector g;
454+
auto prob = std::make_unique<QuadraticProblem>();
455+
456+
TestProblem::TVector x(prob->size());
457+
x.setZero();
458+
459+
std::cout << solver_params << std::endl;
460+
461+
for (int i = 0; i < N_RANDOM; ++i)
462+
{
463+
auto solver = Solver::create(solver_params,
464+
linear_solver_params,
465+
characteristic_length,
466+
*logger);
467+
468+
solver->minimize(*prob, x);
469+
470+
double err = std::numeric_limits<double>::max();
471+
for (auto sol : prob->solutions())
472+
err = std::min(err, (x - sol).norm());
473+
if (err >= 1e-7)
474+
{
475+
prob->gradient(x, g);
476+
err = g.norm();
477+
}
478+
CHECK(err < 1e-7);
479+
if (err >= 1e-7)
480+
break;
481+
482+
x.setRandom();
483+
}
484+
}
485+
427486
TEST_CASE("non-linear-gradient-fd", "[solver]")
428487
{
429488
test_solvers_gradient_fd(false);

0 commit comments

Comments
 (0)