Janus 2.0.0
High-performance C++20 dual-mode numerical framework
Loading...
Searching...
No Matches
AutoDiff.hpp
Go to the documentation of this file.
1#pragma once
7
12#include <string>
13#include <vector>
14
15namespace janus {
16
25
34
46
54 int output_count = 0;
57 bool stiff = false;
58
60
62
64
68
76 casadi::Dict integrator_options() const {
77 casadi::Dict opts;
78 if (uses_forward_mode()) {
79 opts["nfwd"] = parameter_count;
80 opts["fsens_err_con"] = true;
81 } else {
82 opts["nadj"] = output_count;
83 if (uses_checkpointing()) {
84 opts["steps_per_checkpoint"] = steps_per_checkpoint;
86 opts["interpolation_type"] = std::string("polynomial");
88 opts["interpolation_type"] = std::string("hermite");
89 }
90 }
91 }
92 return opts;
93 }
94};
95
96// --- Jacobian (Symbolic Automatic Differentiation) ---
108template <typename Expr, typename... Vars>
109auto jacobian(const Expr &expression, const Vars &...variables) {
110 if constexpr (std::is_same_v<Expr, SymbolicScalar>) {
111 // Collect pack into a vector of MX
112 std::vector<SymbolicScalar> vars;
113 (vars.push_back(variables), ...);
114
115 SymbolicScalar v_cat = SymbolicScalar::vertcat(vars);
116 return SymbolicScalar::jacobian(expression, v_cat);
117 } else {
118 // Fallback or static_assert for non-symbolic types
119 // Ideally we would support numeric autodiff here later
120 static_assert(std::is_same_v<Expr, casadi::MX>,
121 "Automatic Jacobian only supported for Symbolic types currently.");
122 return Expr(0);
123 }
124}
125
126// Reuse shared helpers from Sparsity.hpp detail namespace
127namespace detail {
128
129inline int input_numel(const Function &fn, int input_idx) {
130 const auto &cas_fn = fn.casadi_function();
131 return cas_fn.size1_in(input_idx) * cas_fn.size2_in(input_idx);
132}
133
134inline int output_numel(const Function &fn, int output_idx) {
135 const auto &cas_fn = fn.casadi_function();
136 return cas_fn.size1_out(output_idx) * cas_fn.size2_out(output_idx);
137}
138
139inline void validate_scalar_output(const Function &fn, int output_idx, const std::string &context) {
140 if (output_numel(fn, output_idx) != 1) {
141 throw InvalidArgument(context + ": selected function output must be scalar");
142 }
143}
144
145inline void validate_same_shape(const casadi::MX &lhs, const casadi::MX &rhs,
146 const std::string &context, const std::string &rhs_name) {
147 if (lhs.size1() != rhs.size1() || lhs.size2() != rhs.size2()) {
148 throw InvalidArgument(context + ": " + rhs_name +
149 " must have the same shape as the differentiation variables");
150 }
151}
152
153inline std::vector<casadi::MX> symbolic_inputs_like(const Function &fn) {
154 return fn.casadi_function().mx_in();
155}
156
157inline casadi::MX make_zero_seed(int rows, int cols, int directions) {
158 return casadi::MX::zeros(rows, cols * directions);
159}
160
161inline casadi::MX make_basis_seed(int rows, int cols) {
162 const int directions = rows * cols;
163 std::vector<casadi::MX> blocks;
164 blocks.reserve(static_cast<std::size_t>(directions));
165
166 for (int direction = 0; direction < directions; ++direction) {
167 casadi::DM e = casadi::DM::zeros(directions, 1);
168 e(direction) = 1.0;
169 blocks.push_back(casadi::MX::reshape(casadi::MX(e), rows, cols));
170 }
171
172 return casadi::MX::horzcat(blocks);
173}
174
175inline casadi::MX stacked_blocks_to_columns(const casadi::MX &stacked, int block_rows,
176 int block_cols, int n_blocks) {
177 std::vector<casadi::MX> cols;
178 cols.reserve(static_cast<std::size_t>(n_blocks));
179
180 for (int block = 0; block < n_blocks; ++block) {
181 casadi::MX block_mx =
182 stacked(casadi::Slice(), casadi::Slice(block * block_cols, (block + 1) * block_cols));
183 cols.push_back(casadi::MX::reshape(block_mx, block_rows * block_cols, 1));
184 }
185
186 return casadi::MX::horzcat(cols);
187}
188
189inline std::string sensitivity_function_name(const Function &fn, const std::string &suffix,
190 int output_idx, int input_idx) {
191 return fn.casadi_function().name() + "_" + suffix + "_o" + std::to_string(output_idx) + "_i" +
192 std::to_string(input_idx);
193}
194
195inline std::string lagrangian_function_name(const Function &fn, const std::string &suffix,
196 int objective_output_idx, int constraint_output_idx,
197 int input_idx) {
198 return fn.casadi_function().name() + "_" + suffix + "_obj" +
199 std::to_string(objective_output_idx) + "_con" + std::to_string(constraint_output_idx) +
200 "_i" + std::to_string(input_idx);
201}
202
203inline void validate_scalar_expression(const casadi::MX &expr, const std::string &context,
204 const std::string &name) {
205 if (expr.numel() != 1) {
206 throw InvalidArgument(context + ": " + name + " must be scalar");
207 }
208}
209
210inline casadi::MX lagrangian_scalar(const SymbolicArg &objective, const SymbolicArg &constraints,
211 const SymbolicArg &multipliers, const std::string &context) {
212 const casadi::MX objective_mx = objective.get();
213 const casadi::MX constraints_mx = constraints.get();
214 const casadi::MX multipliers_mx = multipliers.get();
215
216 validate_scalar_expression(objective_mx, context, "objective");
217 if (constraints_mx.numel() != multipliers_mx.numel()) {
218 throw InvalidArgument(context + ": multipliers must have the same number of entries as "
219 "the constraint output");
220 }
221
222 const casadi::MX constraints_vec =
223 casadi::MX::reshape(constraints_mx, constraints_mx.numel(), 1);
224 const casadi::MX multipliers_vec =
225 casadi::MX::reshape(multipliers_mx, multipliers_mx.numel(), 1);
226 return objective_mx + casadi::MX::dot(multipliers_vec, constraints_vec);
227}
228
229inline casadi::MX forward_block_jacobian(const Function &fn, int output_idx, int input_idx) {
230 const auto &cas_fn = fn.casadi_function();
231 const int nfwd = input_numel(fn, input_idx);
232 const int out_rows = cas_fn.size1_out(output_idx);
233 const int out_cols = cas_fn.size2_out(output_idx);
234
235 std::vector<casadi::MX> inputs = symbolic_inputs_like(fn);
236 std::vector<casadi::MX> outputs = cas_fn(inputs);
237
238 casadi::Function fwd = cas_fn.forward(nfwd);
239
240 std::vector<casadi::MX> args;
241 args.reserve(static_cast<std::size_t>(cas_fn.n_in() * 2 + cas_fn.n_out()));
242 args.insert(args.end(), inputs.begin(), inputs.end());
243 args.insert(args.end(), outputs.begin(), outputs.end());
244
245 for (int i = 0; i < cas_fn.n_in(); ++i) {
246 if (i == input_idx) {
247 args.push_back(make_basis_seed(cas_fn.size1_in(i), cas_fn.size2_in(i)));
248 } else {
249 args.push_back(make_zero_seed(cas_fn.size1_in(i), cas_fn.size2_in(i), nfwd));
250 }
251 }
252
253 std::vector<casadi::MX> sensitivities = fwd(args);
254 return stacked_blocks_to_columns(sensitivities.at(output_idx), out_rows, out_cols, nfwd);
255}
256
257inline casadi::MX reverse_block_jacobian(const Function &fn, int output_idx, int input_idx) {
258 const auto &cas_fn = fn.casadi_function();
259 const int nadj = output_numel(fn, output_idx);
260 const int in_rows = cas_fn.size1_in(input_idx);
261 const int in_cols = cas_fn.size2_in(input_idx);
262
263 std::vector<casadi::MX> inputs = symbolic_inputs_like(fn);
264 std::vector<casadi::MX> outputs = cas_fn(inputs);
265
266 casadi::Function adj = cas_fn.reverse(nadj);
267
268 std::vector<casadi::MX> args;
269 args.reserve(static_cast<std::size_t>(cas_fn.n_in() + cas_fn.n_out() * 2));
270 args.insert(args.end(), inputs.begin(), inputs.end());
271 args.insert(args.end(), outputs.begin(), outputs.end());
272
273 for (int i = 0; i < cas_fn.n_out(); ++i) {
274 if (i == output_idx) {
275 args.push_back(make_basis_seed(cas_fn.size1_out(i), cas_fn.size2_out(i)));
276 } else {
277 args.push_back(make_zero_seed(cas_fn.size1_out(i), cas_fn.size2_out(i), nadj));
278 }
279 }
280
281 std::vector<casadi::MX> sensitivities = adj(args);
282 casadi::MX jac_t =
283 stacked_blocks_to_columns(sensitivities.at(input_idx), in_rows, in_cols, nadj);
284 return jac_t.T();
285}
286
287} // namespace detail
288
292inline SensitivityRecommendation
293select_sensitivity_regime(int parameter_count, int output_count, int horizon_length = 1,
294 bool stiff = false,
296 if (parameter_count <= 0) {
297 throw InvalidArgument("select_sensitivity_regime: parameter_count must be positive");
298 }
299 if (output_count <= 0) {
300 throw InvalidArgument("select_sensitivity_regime: output_count must be positive");
301 }
302 if (horizon_length <= 0) {
303 throw InvalidArgument("select_sensitivity_regime: horizon_length must be positive");
304 }
305 if (opts.forward_parameter_threshold <= 0 || opts.adjoint_parameter_threshold <= 0 ||
306 opts.checkpoint_horizon_threshold <= 0 || opts.very_long_horizon_threshold <= 0 ||
307 opts.checkpoint_steps <= 0 || opts.checkpoint_steps_very_long <= 0) {
308 throw InvalidArgument("select_sensitivity_regime: thresholds must be positive");
309 }
310 if (opts.forward_parameter_threshold > opts.adjoint_parameter_threshold) {
311 throw InvalidArgument(
312 "select_sensitivity_regime: forward_parameter_threshold must not exceed "
313 "adjoint_parameter_threshold");
314 }
315 if (opts.checkpoint_horizon_threshold > opts.very_long_horizon_threshold) {
316 throw InvalidArgument(
317 "select_sensitivity_regime: checkpoint_horizon_threshold must not exceed "
318 "very_long_horizon_threshold");
319 }
320
321 SensitivityRecommendation recommendation;
322 recommendation.parameter_count = parameter_count;
323 recommendation.output_count = output_count;
324 recommendation.horizon_length = horizon_length;
325 recommendation.stiff = stiff;
326
327 const bool forward_friendly =
328 parameter_count <= opts.forward_parameter_threshold && output_count >= parameter_count;
329 const bool long_horizon = horizon_length >= opts.checkpoint_horizon_threshold;
330 const bool output_limited = parameter_count > output_count;
331 const bool parameter_heavy = parameter_count >= opts.adjoint_parameter_threshold;
332
333 if (forward_friendly) {
334 recommendation.regime = SensitivityRegime::Forward;
335 return recommendation;
336 }
337
338 if (long_horizon && output_limited) {
340 recommendation.checkpoint_interpolation =
342 recommendation.steps_per_checkpoint = horizon_length >= opts.very_long_horizon_threshold
343 ? opts.checkpoint_steps_very_long
344 : opts.checkpoint_steps;
345 return recommendation;
346 }
347
348 recommendation.regime = (parameter_heavy || output_limited) ? SensitivityRegime::Adjoint
350 return recommendation;
351}
352
356inline SensitivityRecommendation
357select_sensitivity_regime(const Function &fn, int output_idx = 0, int input_idx = 0,
358 int horizon_length = 1, bool stiff = false,
360 detail::validate_function_indices(fn, output_idx, input_idx, "select_sensitivity_regime");
362 detail::output_numel(fn, output_idx), horizon_length, stiff,
363 opts);
364}
365
372inline Function
373sensitivity_jacobian(const Function &fn, int output_idx = 0, int input_idx = 0,
374 int horizon_length = 1, bool stiff = false,
376 detail::validate_function_indices(fn, output_idx, input_idx, "sensitivity_jacobian");
377
378 const SensitivityRecommendation recommendation =
379 select_sensitivity_regime(fn, output_idx, input_idx, horizon_length, stiff, opts);
380
381 casadi::MX jacobian_expr = recommendation.uses_forward_mode()
382 ? detail::forward_block_jacobian(fn, output_idx, input_idx)
383 : detail::reverse_block_jacobian(fn, output_idx, input_idx);
384
385 return Function(
387 fn, recommendation.uses_forward_mode() ? "fwd_jac" : "adj_jac", output_idx, input_idx),
389 std::vector<SymbolicArg>{SymbolicArg(jacobian_expr)});
390}
391
399inline auto jacobian(const std::vector<SymbolicArg> &expressions,
400 const std::vector<SymbolicArg> &variables) {
401 SymbolicScalar expr_cat = SymbolicScalar::vertcat(detail::to_mx_vector(expressions));
402 SymbolicScalar var_cat = SymbolicScalar::vertcat(detail::to_mx_vector(variables));
403 return SymbolicScalar::jacobian(expr_cat, var_cat);
404}
405
416inline SymbolicVector sym_gradient(const SymbolicArg &expr, const SymbolicArg &vars) {
417 // CasADi gradient returns a dense vector (column or row depending on version, usually 1xN or
418 // Nx1) We force it to be a column vector
419 SymbolicScalar g = SymbolicScalar::gradient(expr.get(), vars.get());
420
421 // Convert to SymbolicVector (Janus type)
422 if (g.size2() > 1 && g.size1() == 1) {
423 return to_eigen(g.T());
424 }
425 return to_eigen(g);
426}
427
437inline SymbolicMatrix hessian(const SymbolicArg &expr, const SymbolicArg &vars) {
438 // casadi::MX::hessian returns {H, g}
439 // We only want H
440 // Note: older CasADi versions return H directly, but modern one returns vector
441 // Let's use the property that hessian(f, x) = jacobian(gradient(f, x), x) for safety/clarity
442 // or use the optimized CasADi call:
443 SymbolicScalar H = SymbolicScalar::hessian(expr.get(), vars.get());
444 return to_eigen(H);
445}
446
460 const SymbolicArg &constraints, const SymbolicArg &vars,
461 const SymbolicArg &multipliers) {
462 return janus::hessian(
463 detail::lagrangian_scalar(objective, constraints, multipliers, "hessian_lagrangian"), vars);
464}
465
478 const SymbolicArg &direction) {
479 const casadi::MX expr_mx = expr.get();
480 const casadi::MX vars_mx = vars.get();
481 const casadi::MX direction_mx = direction.get();
482
483 detail::validate_scalar_expression(expr_mx, "hessian_vector_product", "expression");
484 detail::validate_same_shape(vars_mx, direction_mx, "hessian_vector_product", "direction");
485
486 const casadi::MX gradient_mx = casadi::MX::gradient(expr_mx, vars_mx);
487 const casadi::MX hvp_mx = casadi::MX::jtimes(gradient_mx, vars_mx, direction_mx, false);
488 return to_eigen(casadi::MX::reshape(hvp_mx, vars_mx.size1(), vars_mx.size2()));
489}
490
504 const SymbolicArg &constraints,
505 const SymbolicArg &vars,
506 const SymbolicArg &multipliers,
507 const SymbolicArg &direction) {
508 return hessian_vector_product(detail::lagrangian_scalar(objective, constraints, multipliers,
509 "lagrangian_hessian_vector_product"),
510 vars, direction);
511}
512
520inline Function hessian_vector_product(const Function &fn, int output_idx = 0, int input_idx = 0) {
521 detail::validate_function_indices(fn, output_idx, input_idx, "hessian_vector_product");
522 detail::validate_scalar_output(fn, output_idx, "hessian_vector_product");
523
524 const auto &cas_fn = fn.casadi_function();
525 std::vector<casadi::MX> inputs = detail::symbolic_inputs_like(fn);
526 std::vector<casadi::MX> outputs = cas_fn(inputs);
527 casadi::MX direction =
528 casadi::MX::sym("hvp_direction", cas_fn.size1_in(input_idx), cas_fn.size2_in(input_idx));
529
530 casadi::MX hvp_expr = as_mx(
531 janus::hessian_vector_product(outputs.at(output_idx), inputs.at(input_idx), direction));
532
533 std::vector<SymbolicArg> args = detail::to_symbolic_args(inputs);
534 args.emplace_back(direction);
535
536 return Function(detail::sensitivity_function_name(fn, "hvp", output_idx, input_idx), args,
537 std::vector<SymbolicArg>{SymbolicArg(hvp_expr)});
538}
539
547inline Function lagrangian_hessian_vector_product(const Function &fn, int objective_output_idx,
548 int constraint_output_idx, int input_idx = 0) {
549 detail::validate_function_indices(fn, objective_output_idx, input_idx,
550 "lagrangian_hessian_vector_product");
551 detail::validate_function_indices(fn, constraint_output_idx, input_idx,
552 "lagrangian_hessian_vector_product");
553 detail::validate_scalar_output(fn, objective_output_idx, "lagrangian_hessian_vector_product");
554
555 const auto &cas_fn = fn.casadi_function();
556 std::vector<casadi::MX> inputs = detail::symbolic_inputs_like(fn);
557 std::vector<casadi::MX> outputs = cas_fn(inputs);
558 casadi::MX multipliers =
559 casadi::MX::sym("lagrange_multipliers", cas_fn.size1_out(constraint_output_idx),
560 cas_fn.size2_out(constraint_output_idx));
561 casadi::MX direction = casadi::MX::sym("lagrangian_hvp_direction", cas_fn.size1_in(input_idx),
562 cas_fn.size2_in(input_idx));
563
565 outputs.at(objective_output_idx), outputs.at(constraint_output_idx), inputs.at(input_idx),
566 multipliers, direction));
567
568 std::vector<SymbolicArg> args = detail::to_symbolic_args(inputs);
569 args.emplace_back(multipliers);
570 args.emplace_back(direction);
571
572 return Function(detail::lagrangian_function_name(fn, "lag_hvp", objective_output_idx,
573 constraint_output_idx, input_idx),
574 args, std::vector<SymbolicArg>{SymbolicArg(hvp_expr)});
575}
576
577// --- Overloads for vector inputs (convenience) ---
578
582inline SymbolicVector sym_gradient(const SymbolicArg &expr, const std::vector<SymbolicArg> &vars) {
583 SymbolicScalar v_cat = SymbolicScalar::vertcat(detail::to_mx_vector(vars));
584 return sym_gradient(expr, v_cat);
585}
586
590inline SymbolicMatrix hessian(const SymbolicArg &expr, const std::vector<SymbolicArg> &vars) {
591 SymbolicScalar v_cat = SymbolicScalar::vertcat(detail::to_mx_vector(vars));
592 return janus::hessian(expr, v_cat);
593}
594
599 const SymbolicArg &constraints,
600 const std::vector<SymbolicArg> &vars,
601 const SymbolicArg &multipliers) {
602 SymbolicScalar v_cat = SymbolicScalar::vertcat(detail::to_mx_vector(vars));
603 return hessian_lagrangian(objective, constraints, v_cat, multipliers);
604}
605
610 const std::vector<SymbolicArg> &vars,
611 const SymbolicArg &direction) {
612 SymbolicScalar v_cat = SymbolicScalar::vertcat(detail::to_mx_vector(vars));
613 return hessian_vector_product(expr, v_cat, direction);
614}
615
620 const SymbolicArg &constraints,
621 const std::vector<SymbolicArg> &vars,
622 const SymbolicArg &multipliers,
623 const SymbolicArg &direction) {
624 SymbolicScalar v_cat = SymbolicScalar::vertcat(detail::to_mx_vector(vars));
625 return lagrangian_hessian_vector_product(objective, constraints, v_cat, multipliers, direction);
626}
627
628} // namespace janus
Symbolic function wrapper around CasADi with Eigen-native IO.
C++20 concepts constraining valid Janus scalar types.
Core type aliases for numeric and symbolic Eigen/CasADi interop.
Sparsity pattern analysis, graph coloring, and sparse derivative evaluators.
Wrapper around casadi::Function providing Eigen-native IO.
Definition Function.hpp:46
const casadi::Function & casadi_function() const
Access the underlying CasADi function.
Definition Function.hpp:186
Input validation failed (e.g., mismatched sizes, invalid parameters).
Definition JanusError.hpp:31
Universal symbolic argument wrapper for Function inputs/outputs.
Definition JanusTypes.hpp:250
SymbolicScalar get() const
Get underlying CasADi MX object.
Definition JanusTypes.hpp:286
void validate_scalar_expression(const casadi::MX &expr, const std::string &context, const std::string &name)
Definition AutoDiff.hpp:203
std::vector< SymbolicScalar > to_mx_vector(const std::vector< SymbolicArg > &args)
Definition Sparsity.hpp:592
int output_numel(const Function &fn, int output_idx)
Definition AutoDiff.hpp:134
std::string lagrangian_function_name(const Function &fn, const std::string &suffix, int objective_output_idx, int constraint_output_idx, int input_idx)
Definition AutoDiff.hpp:195
casadi::MX lagrangian_scalar(const SymbolicArg &objective, const SymbolicArg &constraints, const SymbolicArg &multipliers, const std::string &context)
Definition AutoDiff.hpp:210
std::string sensitivity_function_name(const Function &fn, const std::string &suffix, int output_idx, int input_idx)
Definition AutoDiff.hpp:189
casadi::MX reverse_block_jacobian(const Function &fn, int output_idx, int input_idx)
Definition AutoDiff.hpp:257
casadi::MX forward_block_jacobian(const Function &fn, int output_idx, int input_idx)
Definition AutoDiff.hpp:229
void validate_same_shape(const casadi::MX &lhs, const casadi::MX &rhs, const std::string &context, const std::string &rhs_name)
Definition AutoDiff.hpp:145
void validate_scalar_output(const Function &fn, int output_idx, const std::string &context)
Definition AutoDiff.hpp:139
casadi::MX make_basis_seed(int rows, int cols)
Definition AutoDiff.hpp:161
casadi::MX stacked_blocks_to_columns(const casadi::MX &stacked, int block_rows, int block_cols, int n_blocks)
Definition AutoDiff.hpp:175
std::vector< SymbolicScalar > symbolic_inputs_like(const Function &fn, const std::string &prefix)
Definition Sparsity.hpp:629
std::vector< SymbolicArg > to_symbolic_args(const std::vector< SymbolicScalar > &args)
Definition Sparsity.hpp:601
casadi::MX make_zero_seed(int rows, int cols, int directions)
Definition AutoDiff.hpp:157
int input_numel(const Function &fn, int input_idx)
Definition AutoDiff.hpp:129
void validate_function_indices(const Function &fn, int output_idx, int input_idx, const char *where)
Definition Sparsity.hpp:618
Definition Diagnostics.hpp:19
JanusVector< SymbolicScalar > SymbolicVector
Eigen vector of MX elements.
Definition JanusTypes.hpp:72
@ Forward
Forward-mode (column compression).
Definition Sparsity.hpp:586
SensitivityRecommendation select_sensitivity_regime(int parameter_count, int output_count, int horizon_length=1, bool stiff=false, const SensitivitySwitchOptions &opts=SensitivitySwitchOptions())
Recommend a sensitivity regime from parameter/output counts.
Definition AutoDiff.hpp:293
Function sensitivity_jacobian(const Function &fn, int output_idx=0, int input_idx=0, int horizon_length=1, bool stiff=false, const SensitivitySwitchOptions &opts=SensitivitySwitchOptions())
Build a Jacobian function for one output/input block using the recommended regime.
Definition AutoDiff.hpp:373
SymbolicMatrix lagrangian_hessian_vector_product(const SymbolicArg &objective, const SymbolicArg &constraints, const SymbolicArg &vars, const SymbolicArg &multipliers, const SymbolicArg &direction)
Hessian-vector product of a Lagrangian, i.e. a second-order adjoint action.
Definition AutoDiff.hpp:503
SymbolicMatrix hessian_lagrangian(const SymbolicArg &objective, const SymbolicArg &constraints, const SymbolicArg &vars, const SymbolicArg &multipliers)
Hessian of Lagrangian for constrained optimization.
Definition AutoDiff.hpp:459
JanusMatrix< SymbolicScalar > SymbolicMatrix
Eigen matrix of MX elements.
Definition JanusTypes.hpp:71
CheckpointInterpolation
Checkpoint interpolation recommendation for long-horizon adjoints.
Definition AutoDiff.hpp:29
@ Polynomial
Definition AutoDiff.hpp:32
@ None
Definition AutoDiff.hpp:30
@ Hermite
Definition AutoDiff.hpp:31
SensitivityRegime
Sensitivity regime selected for a Jacobian-like derivative workload.
Definition AutoDiff.hpp:20
@ Adjoint
Few outputs, many parameters.
Definition AutoDiff.hpp:22
@ Forward
Many outputs, relatively few parameters.
Definition AutoDiff.hpp:21
@ CheckpointedAdjoint
Adjoint with checkpoint recommendations for long horizons.
Definition AutoDiff.hpp:23
Eigen::Matrix< casadi::MX, Eigen::Dynamic, Eigen::Dynamic > to_eigen(const casadi::MX &m)
Convert CasADi MX to Eigen matrix of MX.
Definition JanusTypes.hpp:213
auto jacobian(const Expr &expression, const Vars &...variables)
Computes Jacobian of an expression with respect to variables.
Definition AutoDiff.hpp:109
SymbolicVector sym_gradient(const SymbolicArg &expr, const SymbolicArg &vars)
Symbolic gradient (for scalar-output functions).
Definition AutoDiff.hpp:416
SymbolicMatrix hessian_vector_product(const SymbolicArg &expr, const SymbolicArg &vars, const SymbolicArg &direction)
Hessian-vector product for a scalar expression without forming the dense Hessian.
Definition AutoDiff.hpp:477
casadi::MX SymbolicScalar
CasADi MX symbolic scalar.
Definition JanusTypes.hpp:70
SymbolicScalar as_mx(const SymbolicVector &v)
Get the underlying MX representation of a SymbolicVector.
Definition JanusTypes.hpp:173
SymbolicMatrix hessian(const SymbolicArg &expr, const SymbolicArg &vars)
Hessian matrix (second-order derivatives).
Definition AutoDiff.hpp:437
Result of Janus sensitivity regime selection.
Definition AutoDiff.hpp:50
int parameter_count
Definition AutoDiff.hpp:53
bool uses_checkpointing() const
Definition AutoDiff.hpp:63
bool uses_forward_mode() const
Definition AutoDiff.hpp:59
int horizon_length
Definition AutoDiff.hpp:55
SensitivityRegime regime
Definition AutoDiff.hpp:51
int steps_per_checkpoint
Definition AutoDiff.hpp:56
int output_count
Definition AutoDiff.hpp:54
casadi::Dict integrator_options() const
Convert the recommendation into SUNDIALS/CasADi integrator options.
Definition AutoDiff.hpp:76
CheckpointInterpolation checkpoint_interpolation
Definition AutoDiff.hpp:52
bool stiff
Definition AutoDiff.hpp:57
int casadi_direction_count() const
Definition AutoDiff.hpp:65
bool uses_reverse_mode() const
Definition AutoDiff.hpp:61
Heuristics controlling automatic forward-vs-adjoint selection.
Definition AutoDiff.hpp:38
int forward_parameter_threshold
Definition AutoDiff.hpp:39
int adjoint_parameter_threshold
Definition AutoDiff.hpp:40
int very_long_horizon_threshold
Definition AutoDiff.hpp:42
int checkpoint_steps
Definition AutoDiff.hpp:43
int checkpoint_steps_very_long
Definition AutoDiff.hpp:44
int checkpoint_horizon_threshold
Definition AutoDiff.hpp:41