Drake
Drake C++ Documentation
linear_solve.h File Reference
#include <optional>
#include "drake/common/symbolic/expression.h"
#include "drake/math/autodiff.h"
#include "drake/math/autodiff_gradient.h"
Include dependency graph for linear_solve.h:
This graph shows which files directly or indirectly include this file:

## Classes

class  LinearSolver< LinearSolverType, DerivedA >
Solves a linear system of equations A*x=b. More...

drake

drake::math

## Functions

solve linear system of equations with a given solver.

Solve linear system of equations A * x = b. Where A is an Eigen matrix of double/AutoDiffScalar/symbolic::Expression, and b is an Eigen matrix of double/AutoDiffScalar/symbolic::Expression. Notice that if either A or b contains symbolic::Expression, then the other has to contain symbolic::Expression. This 3-argument version allows the user to re-use linear_solver when b changes or the gradient of A changes. When either A or b contains AutoDiffScalar, we use implicit function theorem to find the gradient in x as ∂x/∂zᵢ = A⁻¹(∂b/∂zᵢ - ∂A/∂zᵢ * x) where z is the variable we take gradient with.

Note
When both A and b are Eigen matrix of double, this function is almost as fast as calling linear_solver.solve(b) directly. When either A or b contains AutoDiffScalar, this function is a lot faster than first instantiating the linear solver of AutoDiffScalar, and then solving the equation with this autodiffable linear solver.
Template Parameters
 LinearSolver The type of linear solver, for example Eigen::LLT DerivedA An Eigen Matrix. DerivedB An Eigen Vector.
Parameters
 linear_solver The linear solver constructed with the double-version of A. A The matrix A. b The vector b.

Here is an example code.

Eigen::Matrix2d A_val;
A_val << 1, 2, 3, 4;
A0_gradient << 1, 2, 3, 4, 5, 6;
A1_gradient << 7, 8, 9, 10, 11, 12;
// Set the value and gradient of b to arbitrary value.
const Eigen::Vector2d b_val(2, 3);
b_gradient << 1, 3, 5, 7, 9, 11;
// Solve the linear system A_val * x_val = b_val.
Eigen::PartialPivLU<Eigen::Matrix2d> linear_solver(A_val);
const auto x_val = SolveLinearSystem(linear_solver, A_val, b_val);
// Solve the linear system A*x=b, together with the gradient.
// x_ad contains both the value of the solution A*x=b, together with its
template<typename LinearSolver , typename DerivedA , typename DerivedB >
std::enable_if< internal::is_double_or_symbolic_v< typename DerivedA::Scalar > &&internal::is_double_or_symbolic_v< typename DerivedB::Scalar > &&std::is_same_v< typename DerivedA::Scalar, typename DerivedB::Scalar >, Eigen::Matrix< typename DerivedA::Scalar, DerivedA::RowsAtCompileTime, DerivedB::ColsAtCompileTime > >::type SolveLinearSystem (const LinearSolver &linear_solver, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &b)
Specialized when A and b are both double or symbolic::Expression matrices. More...

template<typename LinearSolver , typename DerivedB >
std::enable_if< internal::is_double_or_symbolic_v< typename LinearSolver::MatrixType::Scalar > &&internal::is_double_or_symbolic_v< typename DerivedB::Scalar > &&std::is_same_v< typename LinearSolver::MatrixType::Scalar, typename DerivedB::Scalar >, Eigen::Matrix< typename LinearSolver::MatrixType::Scalar, DerivedB::RowsAtCompileTime, DerivedB::ColsAtCompileTime > >::type SolveLinearSystem (const LinearSolver &linear_solver, const Eigen::MatrixBase< DerivedB > &b)
Specialized when the matrix in linear_solver and b are both double or symbolic::Expression matrices. More...

template<typename LinearSolver , typename DerivedB >
std::enable_if< std::is_same_v< typename LinearSolver::MatrixType::Scalar, double > &&internal::is_autodiff_v< typename DerivedB::Scalar >, Eigen::Matrix< typename DerivedB::Scalar, DerivedB::RowsAtCompileTime, DerivedB::ColsAtCompileTime > >::type SolveLinearSystem (const LinearSolver &linear_solver, const Eigen::MatrixBase< DerivedB > &b)
Specialized the matrix in linear_solver is a double-valued matrix and b is an AutoDiffScalar-valued matrix. More...

template<typename LinearSolver , typename DerivedA , typename DerivedB >
std::enable_if< std::is_same_v< typename DerivedA::Scalar, double > &&internal::is_autodiff_v< typename DerivedB::Scalar >, Eigen::Matrix< typename DerivedB::Scalar, DerivedA::RowsAtCompileTime, DerivedB::ColsAtCompileTime > >::type SolveLinearSystem (const LinearSolver &linear_solver, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &b)
Specialized when A is a double-valued matrix and b is an AutoDiffScalar-valued matrix. More...

template<typename LinearSolver , typename DerivedA , typename DerivedB >
std::enable_if< internal::is_autodiff_v< typename DerivedA::Scalar >, Eigen::Matrix< typename DerivedA::Scalar, DerivedA::RowsAtCompileTime, DerivedB::ColsAtCompileTime > >::type SolveLinearSystem (const LinearSolver &linear_solver, const Eigen::MatrixBase< DerivedA > &A, const Eigen::MatrixBase< DerivedB > &b)
Specialized when A is an AutoDiffScalar-valued matrix, and b can contain either AutoDiffScalar or double. More...

Get linear solver

Create the linear solver for a given matrix A, which will be used to solve the linear system of equations A * x = b.

The following table indicate the scalar type of the matrix in the returned linear solver, depending on the scalar type in matrix A

solver double double Expr

where ADS stands for Eigen::AutoDiffScalar, and Expr stands for symbolic::Expression. Here is the example code

Eigen::Matrix2d A_val;
A_val << 1, 2, 2, 5;
Eigen::Vector2d b_val(3, 4);
const Eigen::Vector2d x_val =
SolveLinearSystem(GetLinearSolver<Eigen::LLT>(A_val), A_val, b_val);
A_ad(0, 0).derivatives() = Eigen::Vector3d(1, 2, 3);
A_ad(0, 1).derivatives() = Eigen::Vector3d(2, 3, 4);
A_ad(1, 0).derivatives() = Eigen::Vector3d(3, 4, 5);
A_ad(1, 1).derivatives() = Eigen::Vector3d(4, 5, 6);
// Solve A * x = b with A containing gradient.
const Eigen::Matrix<AutoDiffXd, 2, 1> x_ad1 =
// Solve A * x = b with b containing gradient.
const Eigen::Matrix<AutoDiffXd, 2, 1> x_ad2 =
// Solve A * x = b with both A and b containing gradient.
const Eigen::Matrix<AutoDiffXd, 2, 1> x_ad3 =

{cc}

template<template< typename, int... > typename LinearSolverType, typename DerivedA >
internal::EigenLinearSolver< LinearSolverType, DerivedA > GetLinearSolver (const Eigen::MatrixBase< DerivedA > &A)
Get the linear solver for a matrix A. More...

solve linear system of equations

Solve linear system of equations A * x = b. Where A is an Eigen matrix of double/AutoDiffScalar/symbolic::Expression, and b is an Eigen matrix of double/AutoDiffScalar/symbolic::Expression. Note that when either A or b contains symbolic::Expression, the other has to contain symbolic::Expression as well. When either A or b contains AutoDiffScalar, we use implicit function theorem to find the gradient in x as ∂x/∂zᵢ = A⁻¹(∂b/∂zᵢ - ∂A/∂zᵢ * x) where z is the variable we take gradient with.

The following table indicate the scalar type of x with A/b containing the specified scalar type. The entries with NA are not supported.

b ＼ A double ADS Expr
Expr NA NA Expr

where ADS stands for Eigen::AutoDiffScalar, and Expr stands for symbolic::Expression.

TODO(hongkai.dai): support one of A/b being a double matrix and the other being a symbolic::Expression matrix.

Note
When both A and b are Eigen matrix of double, this function is almost as fast as calling linear_solver.solve(b) directly; when either A or b contains AutoDiffScalar, this function is a lot faster than first instantiating the linear solver of AutoDiffScalar, and then solving the equation with this autodiffable linear solver.
Template Parameters
 LinearSolverType The type of linear solver, for example Eigen::LLT. Notice that this is just specifies the solver type (such as Eigen::LLT), not the matrix type (like Eigen::LLT). All Eigen solvers we care about are templated on the matrix type. Some are further templated on configuration ints. The int... will account for zero or more of these ints, providing a common interface for both types of solvers. DerivedA An Eigen Matrix. DerivedB An Eigen Vector.
Parameters
 A The matrix A. b The vector b.

Here is an example code.

Eigen::Matrix2d A_val;
A_val << 1, 2, 3, 4;
A0_gradient << 1, 2, 3, 4, 5, 6;
A1_gradient << 7, 8, 9, 10, 11, 12;
// Set the value and gradient of b to arbitrary value.
const Eigen::Vector2d b_val(2, 3);