17#include <casadi/casadi.hpp>
31 if (!(scale > 0.0) || !std::isfinite(scale)) {
37inline double max_finite_abs(std::optional<double> lower_bound, std::optional<double> upper_bound) {
38 double bound_mag = 0.0;
39 if (lower_bound.has_value() && std::isfinite(lower_bound.value())) {
40 bound_mag = std::max(bound_mag, std::abs(lower_bound.value()));
42 if (upper_bound.has_value() && std::isfinite(upper_bound.value())) {
43 bound_mag = std::max(bound_mag, std::abs(upper_bound.value()));
49 std::optional<double> upper_bound) {
50 return std::max({std::abs(init_guess),
max_finite_abs(lower_bound, upper_bound), 1.0});
54 std::optional<double> lower_bound,
55 std::optional<double> upper_bound) {
56 double init_mag = init_guess.size() > 0 ? init_guess.cwiseAbs().maxCoeff() : 0.0;
57 return std::max({init_mag,
max_finite_abs(lower_bound, upper_bound), 1.0});
61 return static_cast<std::vector<double>
>(value);
66 return elements.empty() ? 0.0 : elements.front();
70 std::vector<casadi::MX> assignments = opti.initial();
71 std::vector<casadi::MX> params = opti.value_parameters();
72 assignments.insert(assignments.end(), params.begin(), params.end());
81 double tol = 1e-12 * std::max({1.0, std::abs(a), std::abs(b)});
82 return std::abs(a - b) <= tol;
86 double upper_bound,
bool has_upper_bound) {
87 if (has_lower_bound && value < lower_bound) {
88 return lower_bound - value;
90 if (has_upper_bound && value > upper_bound) {
91 return value - upper_bound;
97 double upper_bound,
bool has_upper_bound) {
98 double magnitude = std::abs(value);
99 if (has_lower_bound) {
100 magnitude = std::max(magnitude, std::abs(lower_bound));
102 if (has_upper_bound) {
103 magnitude = std::max(magnitude, std::abs(upper_bound));
105 return std::max(magnitude, 1.0);
172 Opti() : opti_(), categories_to_freeze_(), categories_() {}
182 explicit Opti(
const std::vector<std::string> &categories_to_freeze)
183 : opti_(), categories_to_freeze_(categories_to_freeze), categories_() {}
201 std::optional<double> lower_bound = std::nullopt,
202 std::optional<double> upper_bound = std::nullopt) {
217 std::optional<double> scale = std::nullopt,
218 std::optional<double> lower_bound = std::nullopt,
219 std::optional<double> upper_bound = std::nullopt) {
224 double s = scale.has_value()
233 opti_.set_value(param, init_guess);
238 scaled_var = s * raw_var;
241 opti_.set_initial(raw_var, init_guess / s);
244 if (lower_bound.has_value()) {
245 opti_.subject_to(scaled_var >= lower_bound.value());
247 if (upper_bound.has_value()) {
248 opti_.subject_to(scaled_var <= upper_bound.value());
252 init_vector(0) = init_guess;
253 register_variable_block(init_vector, opts.
category, s, scale.has_value(), lower_bound,
258 categories_[opts.
category].push_back(scaled_var);
274 std::optional<double> scale = std::nullopt,
275 std::optional<double> lower_bound = std::nullopt,
276 std::optional<double> upper_bound = std::nullopt) {
278 double s = scale.has_value()
287 opti_.set_initial(raw_var, init_guess / s);
290 if (lower_bound.has_value()) {
291 opti_.subject_to(scaled_var >= lower_bound.value());
293 if (upper_bound.has_value()) {
294 opti_.subject_to(scaled_var <= upper_bound.value());
297 register_variable_block(NumericVector::Constant(n_vars, init_guess),
"Uncategorized", s,
298 scale.has_value(), lower_bound, upper_bound);
313 std::optional<double> scale = std::nullopt,
314 std::optional<double> lower_bound = std::nullopt,
315 std::optional<double> upper_bound = std::nullopt) {
316 int n_vars =
static_cast<int>(init_guess.size());
319 double s = scale.has_value()
328 std::vector<double> init_vec(init_guess.data(), init_guess.data() + init_guess.size());
329 for (
auto &v : init_vec) {
332 opti_.set_initial(raw_var, init_vec);
335 if (lower_bound.has_value()) {
336 opti_.subject_to(scaled_var >= lower_bound.value());
338 if (upper_bound.has_value()) {
339 opti_.subject_to(scaled_var <= upper_bound.value());
342 register_variable_block(init_guess,
"Uncategorized", s, scale.has_value(), lower_bound,
362 opti_.set_value(param, value);
373 int n =
static_cast<int>(value.size());
375 std::vector<double> vals(value.data(), value.data() + value.size());
376 opti_.set_value(param, vals);
409 linear_scale,
"Opti::subject_to")));
417 void subject_to(
const std::vector<SymbolicScalar> &constraints) {
418 for (
const auto &c : constraints) {
428 void subject_to(
const std::vector<SymbolicScalar> &constraints,
double linear_scale) {
430 for (
const auto &c : constraints) {
431 opti_.subject_to(c, casadi::DM(s));
447 void subject_to(std::initializer_list<SymbolicScalar> constraints) {
448 for (
const auto &c : constraints) {
458 void subject_to(std::initializer_list<SymbolicScalar> constraints,
double linear_scale) {
460 for (
const auto &c : constraints) {
461 opti_.subject_to(c, casadi::DM(s));
473 opti_.subject_to(scalar >= lower_bound);
482 opti_.subject_to(scalar <= upper_bound);
511 for (Eigen::Index i = 0; i < vec.size(); ++i) {
512 opti_.subject_to(vec(i) >= lower_bound);
523 for (Eigen::Index i = 0; i < vec.size(); ++i) {
524 opti_.subject_to(vec(i) <= upper_bound);
607 "' is not available in this CasADi build");
610 casadi::Dict solver_opts;
613 switch (options.solver) {
615 configure_snopt_opts(solver_opts, options);
618 configure_qpoases_opts(solver_opts, options);
622 configure_ipopt_opts(solver_opts, options);
628 solver_opts[
"jit"] =
true;
629 solver_opts[
"jit_options"] = casadi::Dict{{
"flags", std::vector<std::string>{
"-O3"}}};
633 opti_.solver(
solver_name(options.solver), solver_opts);
634 return OptiSol(opti_.solve());
667 "' is not available in this CasADi build");
671 result.param_values = values;
672 result.all_converged =
true;
675 casadi::Dict solver_opts;
677 switch (options.solver) {
679 configure_snopt_opts(solver_opts, options);
682 configure_qpoases_opts(solver_opts, options);
686 configure_ipopt_opts(solver_opts, options);
688 solver_opts[
"ipopt.warm_start_init_point"] =
"yes";
692 opti_.solver(
solver_name(options.solver), solver_opts);
694 for (
size_t idx = 0; idx < values.size(); ++idx) {
695 double val = values[idx];
696 opti_.set_value(param, val);
699 auto sol = opti_.solve();
700 result.iterations.push_back(sol.stats().count(
"iter_count")
701 ?
static_cast<int>(sol.stats().at(
"iter_count"))
703 result.solutions.emplace_back(sol);
704 result.converged.push_back(
true);
705 result.errors.emplace_back();
706 }
catch (
const std::exception &e) {
707 result.all_converged =
false;
708 result.solutions.emplace_back(std::nullopt);
709 result.converged.push_back(
false);
710 result.errors.push_back(e.what());
711 result.iterations.push_back(-1);
743 double derivative_init_guess,
744 const std::string &method =
"trapezoidal") {
745 int n =
static_cast<int>(var.size());
746 if (n !=
static_cast<int>(with_respect_to.size())) {
748 "derivative_of: variable and with_respect_to must have same size");
752 auto deriv =
variable(n, derivative_init_guess);
772 const std::string &method =
"trapezoidal") {
781 int n =
static_cast<int>(var.size());
790 for (
int i = 0; i < n - 1; ++i) {
792 SymbolicScalar rhs = 0.5 * (derivative(i) + derivative(i + 1)) * dt(i);
793 opti_.subject_to(lhs == rhs);
799 for (
int i = 0; i < n - 1; ++i) {
802 opti_.subject_to(lhs == rhs);
808 for (
int i = 0; i < n - 1; ++i) {
811 opti_.subject_to(lhs == rhs);
832 if (!variable_records_.empty()) {
837 for (
size_t i = 0; i < variable_records_.size(); ++i) {
838 const auto &record = variable_records_[i];
839 VariableScalingInfo info;
840 info.block_index =
static_cast<int>(i);
841 info.size = record.size;
842 info.category = record.category;
844 info.user_supplied_scale = record.user_supplied_scale;
845 info.scale = record.scale;
846 info.init_abs_mean = record.init_abs_mean;
847 info.init_abs_max = record.init_abs_max;
848 info.normalized_init_abs_mean = record.init_abs_mean / record.scale;
849 info.normalized_init_abs_max = record.init_abs_max / record.scale;
850 info.lower_bound = record.lower_bound;
851 info.upper_bound = record.upper_bound;
852 info.suggested_scale = record.suggested_scale;
860 if (record.init_abs_max > 0.0 &&
861 info.normalized_init_abs_max < opts.normalized_low_warn) {
864 "variable[" + std::to_string(i) +
"]",
865 "initial guess is much smaller than the applied variable scale",
866 record.init_abs_max, record.scale, info.normalized_init_abs_max,
867 record.suggested_scale});
868 }
else if (info.normalized_init_abs_max > opts.normalized_high_warn) {
872 "variable[" + std::to_string(i) +
"]",
873 "initial guess is much larger than the applied variable scale",
874 record.init_abs_max, record.scale, info.normalized_init_abs_max,
875 record.suggested_scale});
879 if (!variable_records_.empty()) {
885 "decision-variable scales span many orders of magnitude",
893 if (objective_expr_.has_value()) {
909 "objective magnitude is large relative to the applied objective scale",
915 if (opti_.ng() > 0) {
916 std::vector<double> g_values =
918 std::vector<double> lbg_values =
920 std::vector<double> ubg_values =
924 for (
int i = 0; i < static_cast<int>(g_values.size()); ++i) {
925 ConstraintScalingInfo info;
927 info.value_at_initial = g_values.at(i);
928 info.scale = i < static_cast<int>(g_scales.size()) ? g_scales.at(i) : 1.0;
929 info.lower_bound = i < static_cast<int>(lbg_values.size()) ? lbg_values.at(i) : 0.0;
930 info.upper_bound = i < static_cast<int>(ubg_values.size()) ? ubg_values.at(i) : 0.0;
931 info.has_lower_bound =
932 i < static_cast<int>(lbg_values.size()) && std::isfinite(info.lower_bound);
933 info.has_upper_bound =
934 i < static_cast<int>(ubg_values.size()) && std::isfinite(info.upper_bound);
935 info.equality = info.has_lower_bound && info.has_upper_bound &&
937 info.normalized_magnitude =
939 info.has_lower_bound, info.upper_bound,
940 info.has_upper_bound) /
942 info.normalized_violation =
944 info.has_lower_bound, info.upper_bound,
945 info.has_upper_bound) /
948 info.value_at_initial, info.lower_bound, info.has_lower_bound, info.upper_bound,
949 info.has_upper_bound);
952 if (info.normalized_magnitude > opts.normalized_high_warn) {
956 "constraint magnitude or bound magnitude is large relative to its scale",
957 info.suggested_scale, info.scale, info.normalized_magnitude,
958 info.suggested_scale});
963 if (opti_.nx() > 0 && opti_.ng() > 0) {
964 casadi::Sparsity jac_sp = casadi::MX::jacobian_sparsity(opti_.g(), opti_.x());
967 static_cast<double>(jac_sp.nnz()) /
968 static_cast<double>(std::max<casadi_int>(1, opti_.nx() * opti_.ng()));
992 void set_initial(
const casadi::MX &x,
const casadi::DM &v) { opti_.set_initial(x, v); }
1004 std::vector<SymbolicScalar>
get_category(
const std::string &category)
const {
1005 auto it = categories_.find(category);
1006 if (it != categories_.end()) {
1017 std::vector<std::string> names;
1018 names.reserve(categories_.size());
1019 for (
const auto &[name, _] : categories_) {
1020 names.push_back(name);
1031 return std::find(categories_to_freeze_.begin(), categories_to_freeze_.end(), category) !=
1032 categories_to_freeze_.end();
1036 struct VariableRecord {
1038 std::string category =
"Uncategorized";
1039 bool user_supplied_scale =
false;
1041 double init_abs_mean = 0.0;
1042 double init_abs_max = 0.0;
1043 std::optional<double> lower_bound;
1044 std::optional<double> upper_bound;
1045 double suggested_scale = 1.0;
1049 std::vector<std::string> categories_to_freeze_;
1050 std::map<std::string, std::vector<SymbolicScalar>> categories_;
1051 std::vector<VariableRecord> variable_records_;
1052 std::optional<SymbolicScalar> objective_expr_;
1053 double objective_scale_ = 1.0;
1054 bool objective_scale_user_supplied_ =
false;
1055 bool objective_is_maximize_ =
false;
1061 void configure_ipopt_opts(casadi::Dict &solver_opts,
const OptiOptions &options) {
1062 solver_opts[
"ipopt.max_iter"] = options.max_iter;
1063 solver_opts[
"ipopt.max_cpu_time"] = options.max_cpu_time;
1064 solver_opts[
"ipopt.tol"] = options.tol;
1065 solver_opts[
"ipopt.mu_strategy"] = options.mu_strategy;
1066 solver_opts[
"ipopt.sb"] =
"yes";
1068 if (options.verbose) {
1069 solver_opts[
"ipopt.print_level"] = 5;
1071 solver_opts[
"print_time"] =
false;
1072 solver_opts[
"ipopt.print_level"] = 0;
1075 if (options.detect_simple_bounds) {
1076 solver_opts[
"detect_simple_bounds"] =
true;
1080 void configure_snopt_opts(casadi::Dict &solver_opts,
const OptiOptions &options) {
1081 const auto &snopt = options.snopt_opts;
1084 solver_opts[
"snopt.Major_iterations_limit"] = snopt.major_iterations_limit;
1085 solver_opts[
"snopt.Minor_iterations_limit"] = snopt.minor_iterations_limit;
1086 solver_opts[
"snopt.Major_optimality_tolerance"] = snopt.major_optimality_tolerance;
1087 solver_opts[
"snopt.Major_feasibility_tolerance"] = snopt.major_feasibility_tolerance;
1089 if (options.verbose) {
1090 solver_opts[
"snopt.Major_print_level"] = 1;
1091 solver_opts[
"snopt.Minor_print_level"] = 1;
1093 solver_opts[
"print_time"] =
false;
1094 solver_opts[
"snopt.Major_print_level"] = snopt.print_level;
1095 solver_opts[
"snopt.Minor_print_level"] = 0;
1099 void configure_qpoases_opts(casadi::Dict &solver_opts,
const OptiOptions &options) {
1100 solver_opts[
"qpoases.nWSR"] = options.max_iter;
1101 solver_opts[
"qpoases.CPUtime"] = options.max_cpu_time;
1103 if (!options.verbose) {
1104 solver_opts[
"print_time"] =
false;
1105 solver_opts[
"qpoases.printLevel"] =
"none";
1109 void register_variable_block(
const NumericVector &init_guess,
const std::string &category,
1110 double scale,
bool user_supplied_scale,
1111 std::optional<double> lower_bound,
1112 std::optional<double> upper_bound) {
1113 VariableRecord record;
1114 record.size =
static_cast<int>(init_guess.size());
1115 record.category = category;
1116 record.user_supplied_scale = user_supplied_scale;
1118 record.init_abs_mean = init_guess.size() > 0 ? init_guess.cwiseAbs().mean() : 0.0;
1119 record.init_abs_max = init_guess.size() > 0 ? init_guess.cwiseAbs().maxCoeff() : 0.0;
1120 record.lower_bound = lower_bound;
1121 record.upper_bound = upper_bound;
1122 record.suggested_scale =
1123 init_guess.size() == 1
1126 variable_records_.push_back(record);
1129 void set_objective(
const SymbolicScalar &objective,
double scale,
bool user_supplied_scale,
1131 objective_expr_ = objective;
1133 objective_scale_user_supplied_ = user_supplied_scale;
1135 opti_.minimize((
maximize ? -objective : objective) / objective_scale_);
Numerical differentiation and integration (gradient, trapz, cumtrapz, diff).
Finite difference weights, derivative approximations, and integration defects.
Custom exception hierarchy for Janus framework.
Core type aliases for numeric and symbolic Eigen/CasADi interop.
Solver selection and configuration for Opti.
Solution wrapper for extracting optimized values.
Parametric sweep results for optimization problems.
Scaling diagnostics and metadata for optimization problems.
Input validation failed (e.g., mismatched sizes, invalid parameters).
Definition JanusError.hpp:31
Solution wrapper for optimization results.
Definition OptiSol.hpp:32
void constrain_derivative(const SymbolicVector &derivative, const SymbolicVector &var, const NumericVector &with_respect_to, IntegrationMethod method)
Constrain an existing variable to be a derivative (enum version).
Definition Opti.hpp:779
SymbolicVector parameter(const NumericVector &value)
Create a vector parameter.
Definition Opti.hpp:372
SymbolicScalar variable(double init_guess, const VariableOptions &opts, std::optional< double > scale=std::nullopt, std::optional< double > lower_bound=std::nullopt, std::optional< double > upper_bound=std::nullopt)
Create a scalar decision variable with options.
Definition Opti.hpp:216
void subject_to(const std::vector< SymbolicScalar > &constraints)
Add multiple constraints.
Definition Opti.hpp:417
Opti(const std::vector< std::string > &categories_to_freeze)
Construct with frozen categories.
Definition Opti.hpp:182
void subject_to(const std::vector< SymbolicScalar > &constraints, double linear_scale)
Add multiple constraints with one shared linear scale.
Definition Opti.hpp:428
void minimize(const SymbolicScalar &objective, double objective_scale)
Set objective to minimize with explicit objective scaling.
Definition Opti.hpp:565
void subject_to_upper(const SymbolicVector &vec, double upper_bound)
Apply upper bound to all elements of a vector.
Definition Opti.hpp:522
SymbolicVector variable(int n_vars, double init_guess=0.0, std::optional< double > scale=std::nullopt, std::optional< double > lower_bound=std::nullopt, std::optional< double > upper_bound=std::nullopt)
Create a vector of decision variables with scalar init guess.
Definition Opti.hpp:273
std::vector< SymbolicScalar > get_category(const std::string &category) const
Get all variables in a category.
Definition Opti.hpp:1004
void minimize(const SymbolicScalar &objective)
Set objective to minimize.
Definition Opti.hpp:555
void maximize(const SymbolicScalar &objective, double objective_scale)
Set objective to maximize with explicit objective scaling.
Definition Opti.hpp:585
void subject_to_bounds(const SymbolicScalar &scalar, double lower_bound, double upper_bound)
Apply both lower and upper bounds to a scalar variable.
Definition Opti.hpp:491
OptiSol solve(const OptiOptions &options={})
Solve the optimization problem.
Definition Opti.hpp:603
Opti()
Construct a new optimization environment.
Definition Opti.hpp:172
const casadi::Opti & casadi_opti() const
Access the underlying CasADi Opti object.
Definition Opti.hpp:981
void subject_to_upper(const SymbolicScalar &scalar, double upper_bound)
Apply upper bound to a scalar variable.
Definition Opti.hpp:481
std::vector< std::string > get_category_names() const
Get all registered category names.
Definition Opti.hpp:1016
void subject_to_bounds(const SymbolicVector &vec, double lower_bound, double upper_bound)
Apply both lower and upper bounds to all elements.
Definition Opti.hpp:541
void maximize(const SymbolicScalar &objective)
Set objective to maximize.
Definition Opti.hpp:575
void subject_to(std::initializer_list< SymbolicScalar > constraints, double linear_scale)
Add an initializer-list of constraints with one shared linear scale.
Definition Opti.hpp:458
SymbolicScalar variable(double init_guess=0.0, std::optional< double > scale=std::nullopt, std::optional< double > lower_bound=std::nullopt, std::optional< double > upper_bound=std::nullopt)
Create a scalar decision variable.
Definition Opti.hpp:200
void subject_to(const SymbolicScalar &constraint, double linear_scale)
Add a scaled scalar constraint.
Definition Opti.hpp:407
void subject_to(std::initializer_list< SymbolicScalar > constraints)
Add constraints from initializer list.
Definition Opti.hpp:447
SymbolicVector derivative_of(const SymbolicVector &var, const NumericVector &with_respect_to, double derivative_init_guess, const std::string &method="trapezoidal")
Create a derivative variable constrained by integration.
Definition Opti.hpp:742
void constrain_derivative(const SymbolicVector &derivative, const SymbolicVector &var, const NumericVector &with_respect_to, const std::string &method="trapezoidal")
Constrain an existing variable to be a derivative.
Definition Opti.hpp:770
void subject_to_lower(const SymbolicVector &vec, double lower_bound)
Apply lower bound to all elements of a vector.
Definition Opti.hpp:510
bool is_category_frozen(const std::string &category) const
Check if a category is marked for freezing.
Definition Opti.hpp:1030
void set_initial(const casadi::MX &x, const casadi::DM &v)
Set initial guess for a symbolic expression.
Definition Opti.hpp:992
void subject_to_lower(const SymbolicScalar &scalar, double lower_bound)
Apply lower bound to a scalar variable.
Definition Opti.hpp:472
SymbolicVector variable(const NumericVector &init_guess, std::optional< double > scale=std::nullopt, std::optional< double > lower_bound=std::nullopt, std::optional< double > upper_bound=std::nullopt)
Create a vector of decision variables with per-element init guess.
Definition Opti.hpp:312
void subject_to(const SymbolicScalar &constraint)
Add a scalar constraint.
Definition Opti.hpp:396
SweepResult solve_sweep(const SymbolicScalar ¶m, const std::vector< double > &values, const OptiOptions &options={})
Perform parametric sweep over a parameter.
Definition Opti.hpp:662
SymbolicScalar parameter(double value)
Create a scalar parameter.
Definition Opti.hpp:360
ScalingReport analyze_scaling(const ScalingAnalysisOptions &opts={}) const
Diagnose variable, objective, and constraint scaling at the current initial point.
Definition Opti.hpp:827
Operation failed at runtime (e.g., CasADi eval with free variables).
Definition JanusError.hpp:41
Smooth approximation of ReLU function: softplus(x) = (1/beta) * log(1 + exp(beta * x)).
Definition Diagnostics.hpp:131
double validate_positive_scale(double scale, const std::string &context)
Definition Opti.hpp:30
bool nearly_equal(double a, double b)
Definition Opti.hpp:80
std::vector< casadi::MX > current_assignments(const casadi::Opti &opti)
Definition Opti.hpp:69
double dm_to_scalar(const casadi::DM &value)
Definition Opti.hpp:64
double max_finite_abs(std::optional< double > lower_bound, std::optional< double > upper_bound)
Definition Opti.hpp:37
ScalingIssueLevel issue_level(double normalized, const ScalingAnalysisOptions &opts)
Definition Opti.hpp:108
double constraint_magnitude(double value, double lower_bound, bool has_lower_bound, double upper_bound, bool has_upper_bound)
Definition Opti.hpp:96
double normalized_magnitude(double magnitude, double scale)
Definition Opti.hpp:76
double suggest_vector_scale(const NumericVector &init_guess, std::optional< double > lower_bound, std::optional< double > upper_bound)
Definition Opti.hpp:53
double constraint_violation(double value, double lower_bound, bool has_lower_bound, double upper_bound, bool has_upper_bound)
Definition Opti.hpp:85
std::vector< double > dm_to_std_vector(const casadi::DM &value)
Definition Opti.hpp:60
double suggest_scalar_scale(double init_guess, std::optional< double > lower_bound, std::optional< double > upper_bound)
Definition Opti.hpp:48
Definition Diagnostics.hpp:19
JanusVector< SymbolicScalar > SymbolicVector
Eigen vector of MX elements.
Definition JanusTypes.hpp:72
@ Ipopt
Interior Point OPTimizer (default, always available).
Definition OptiOptions.hpp:22
@ Snopt
Sparse Nonlinear OPTimizer (requires license).
Definition OptiOptions.hpp:23
@ QpOases
QP solver for QP subproblems.
Definition OptiOptions.hpp:24
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
bool solver_available(Solver solver)
Check if a solver is available in the current CasADi build.
Definition OptiOptions.hpp:58
IntegrationMethod
Integration/differentiation method for trajectory optimization.
Definition FiniteDifference.hpp:24
@ BackwardEuler
First-order backward difference: x[i+1] - x[i] = xdot[i+1] * dt.
Definition FiniteDifference.hpp:26
@ ForwardEuler
First-order forward difference: x[i+1] - x[i] = xdot[i] * dt.
Definition FiniteDifference.hpp:25
@ Midpoint
Alias for Trapezoidal (same formula).
Definition FiniteDifference.hpp:28
@ Trapezoidal
Second-order trapezoidal: x[i+1] - x[i] = 0.5 * (xdot[i] + xdot[i+1]) * dt.
Definition FiniteDifference.hpp:27
auto diff(const Eigen::MatrixBase< Derived > &v)
Computes adjacent differences of a vector Returns a vector of size N-1 where out[i] = v[i+1] - v[i].
Definition Calculus.hpp:27
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
const char * solver_name(Solver solver)
Get the CasADi solver name string.
Definition OptiOptions.hpp:38
ScalingIssueLevel
Severity used by Opti scaling diagnostics.
Definition Scaling.hpp:20
@ Warning
Potential scaling concern.
Definition Scaling.hpp:21
@ Critical
Severe scaling issue likely to cause solver failure.
Definition Scaling.hpp:22
IntegrationMethod parse_integration_method(const std::string &method)
Parse integration method from string.
Definition FiniteDifference.hpp:47
@ Summary
Aggregate issue across the problem.
Definition Scaling.hpp:32
@ Objective
Issue with objective scaling.
Definition Scaling.hpp:31
@ Variable
Issue with variable scaling.
Definition Scaling.hpp:29
@ Constraint
Issue with constraint scaling.
Definition Scaling.hpp:30
casadi::MX SymbolicScalar
CasADi MX symbolic scalar.
Definition JanusTypes.hpp:70
double scale
Definition Scaling.hpp:106
double normalized_value
Definition Scaling.hpp:107
double suggested_scale
Definition Scaling.hpp:108
bool maximize
Definition Scaling.hpp:103
double value_at_initial
Definition Scaling.hpp:105
bool configured
Definition Scaling.hpp:102
bool user_supplied_scale
Definition Scaling.hpp:104
Options for solving optimization problems.
Definition OptiOptions.hpp:126
Thresholds controlling Opti scaling diagnostics.
Definition Scaling.hpp:38
double normalized_high_critical
Escalate to critical beyond this.
Definition Scaling.hpp:41
Aggregate result returned by Opti::analyze_scaling().
Definition Scaling.hpp:129
ScalingSummary summary
Top-level numeric summary.
Definition Scaling.hpp:130
std::vector< VariableScalingInfo > variables
Per-variable-block metadata.
Definition Scaling.hpp:132
ObjectiveScalingInfo objective
Objective scaling metadata.
Definition Scaling.hpp:131
std::vector< ConstraintScalingInfo > constraints
Per-constraint-row metadata.
Definition Scaling.hpp:133
std::vector< ScalingIssue > issues
Detected scaling issues.
Definition Scaling.hpp:134
int variable_blocks
Definition Scaling.hpp:115
double max_variable_scale
Definition Scaling.hpp:120
int scalar_constraints
Definition Scaling.hpp:116
int jacobian_nnz
Definition Scaling.hpp:117
double min_variable_scale
Definition Scaling.hpp:119
double jacobian_density
Definition Scaling.hpp:118
double variable_scale_ratio
Definition Scaling.hpp:121
Result of a parametric sweep.
Definition OptiSweep.hpp:32
Options for variable creation.
Definition Opti.hpp:126
bool freeze
If true, variable is fixed at init_guess.
Definition Opti.hpp:128
std::string category
Category for grouping variables.
Definition Opti.hpp:127