blob: 074f2f3434834c70da1dfb29596a2d7bb695e38d [file] [log] [blame]
Austin Schuh29441032023-05-31 19:32:24 -07001#ifndef FRC971_SOLVERS_SPARSE_CONVEX_H_
2#define FRC971_SOLVERS_SPARSE_CONVEX_H_
3
4#include <sys/types.h>
5#include <unistd.h>
6
Austin Schuh29441032023-05-31 19:32:24 -07007#include <iomanip>
8
9#include "glog/logging.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070010#include <Eigen/Sparse>
Austin Schuh29441032023-05-31 19:32:24 -070011
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080012namespace frc971::solvers {
Austin Schuh29441032023-05-31 19:32:24 -070013
14// TODO(austin): Steal JET from Ceres to generate the derivatives easily and
15// quickly?
16//
17// States is the number of inputs to the optimization problem.
18// M is the number of inequality constraints.
19// N is the number of equality constraints.
20class SparseConvexProblem {
21 public:
22 size_t states() const { return states_; }
23 size_t inequality_constraints() const { return inequality_constraints_; }
24 size_t equality_constraints() const { return equality_constraints_; }
25
26 // Returns the function to minimize and it's derivatives.
27 virtual double f0(Eigen::Ref<const Eigen::VectorXd> X) const = 0;
28 // TODO(austin): Should the jacobian be sparse?
29 virtual Eigen::SparseMatrix<double> df0(
30 Eigen::Ref<const Eigen::VectorXd> X) const = 0;
31 virtual Eigen::SparseMatrix<double> ddf0(
32 Eigen::Ref<const Eigen::VectorXd> X) const = 0;
33
34 // Returns the constraints f(X) < 0, and their derivative.
35 virtual Eigen::VectorXd f(Eigen::Ref<const Eigen::VectorXd> X) const = 0;
36 virtual Eigen::SparseMatrix<double> df(
37 Eigen::Ref<const Eigen::VectorXd> X) const = 0;
38
39 // Returns the equality constraints of the form A x = b
40 virtual Eigen::SparseMatrix<double> A() const = 0;
41 virtual Eigen::VectorXd b() const = 0;
42
43 protected:
44 SparseConvexProblem(size_t states, size_t inequality_constraints,
45 size_t equality_constraints)
46 : states_(states),
47 inequality_constraints_(inequality_constraints),
48 equality_constraints_(equality_constraints) {}
49
50 private:
51 size_t states_;
52 size_t inequality_constraints_;
53 size_t equality_constraints_;
54};
55
56// Implements a Primal-Dual Interior point method convex solver.
57// See 11.7 of https://web.stanford.edu/~boyd/cvxbook/bv_cvxbook.pdf
58//
59// States is the number of inputs to the optimization problem.
60// M is the number of inequality constraints.
61// N is the number of equality constraints.
62class SparseSolver {
63 public:
64 // Ratio to require the cost to decrease when line searching.
65 static constexpr double kAlpha = 0.05;
66 // Line search step parameter.
67 static constexpr double kBeta = 0.5;
68 static constexpr double kMu = 2.0;
69 // Terminal condition for the primal problem (equality constraints) and dual
70 // (gradient + inequality constraints).
71 static constexpr double kEpsilonF = 1e-6;
72 // Terminal condition for nu, the surrogate duality gap.
73 static constexpr double kEpsilon = 1e-6;
74
75 // Solves the problem given a feasible initial solution.
76 Eigen::VectorXd Solve(const SparseConvexProblem &problem,
77 Eigen::Ref<const Eigen::VectorXd> X_initial);
78
79 private:
80 // Class to hold all the derivataves and function evaluations.
81 struct Derivatives {
82 size_t states() const { return hessian.rows(); }
83 size_t inequality_constraints() const { return f.rows(); }
84 size_t equality_constraints() const { return Axmb.rows(); }
85
86 Eigen::SparseMatrix<double> gradient;
87 Eigen::SparseMatrix<double> hessian;
88
89 // Inequality function f
90 Eigen::VectorXd f;
91 // df
92 Eigen::SparseMatrix<double> df;
93
94 // ddf is assumed to be 0 because for the linear constraint distance
95 // function we are using, it is actually 0, and by assuming it is zero
96 // rather than passing it through as 0 to the solver, we can save enough CPU
97 // to make it worth it.
98
99 // A
100 Eigen::SparseMatrix<double> A;
101 // Ax - b
102 Eigen::VectorXd Axmb;
103 };
104
105 // Computes all the values for the given problem at the given state.
Philipp Schrader790cb542023-07-05 21:06:52 -0700106 Derivatives ComputeDerivative(const SparseConvexProblem &problem,
107 const Eigen::Ref<const Eigen::VectorXd> y);
Austin Schuh29441032023-05-31 19:32:24 -0700108
109 // Computes Rt at the given state and with the given t_inverse. See 11.53 of
110 // cvxbook.pdf.
Philipp Schrader790cb542023-07-05 21:06:52 -0700111 Eigen::VectorXd Rt(const Derivatives &derivatives, Eigen::VectorXd y,
112 double t_inverse);
Austin Schuh29441032023-05-31 19:32:24 -0700113
114 // Prints out all the derivatives with VLOG at the provided verbosity.
Philipp Schrader790cb542023-07-05 21:06:52 -0700115 void PrintDerivatives(const Derivatives &derivatives,
116 const Eigen::Ref<const Eigen::VectorXd> y,
117 std::string_view prefix, int verbosity);
Austin Schuh29441032023-05-31 19:32:24 -0700118};
119
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800120} // namespace frc971::solvers
Austin Schuh29441032023-05-31 19:32:24 -0700121
122#endif // FRC971_SOLVERS_SPARSE_CONVEX_H_