List of all members | Public Types | Public Member Functions | Static Public Member Functions
casadi::Linsol Class Reference

Linear solver. More...

#include <linsol.hpp>

Detailed Description

Solves the square linear system A*X = B or A'*X = B for X with a sparse direct solver plugin. A Linsol is created for a fixed sparsity pattern of A; the numerical values are given at every call. A matrix with another sparsity pattern is projected onto the fixed one (entries outside it are dropped). The solve is split in a symbolic factorization (sfact, pivot selection from the pattern), a numeric factorization (nfact) and the triangular solves (solve); solve(A, B) performs all three. A numerically singular matrix makes nfact (or solve) raise an error for most plugins; for a symbolic (MX) A, solve returns an expression node that is differentiable with respect to A and B.

Available plugins include "qr" and "ldl" (sparse direct QR and LDL, codegen support), "symbolicqr" (QR as a symbolic expression), "csparse", "csparsecholesky", "lapacklu", "lapackqr", "ma27", "mumps". neig and rank are only implemented by "ldl", det by "qr" and "csparse". The constructor raises an error for a non-square pattern only when the plugin checks it; otherwise the solve fails.

>>> A = DM([[3, 1], [1, 2]]); b = DM([4, 3])
>>> L = Linsol("L", "qr", A.sparsity())
>>> L.plugin_name(), L.sparsity()
('qr', Sparsity(2x2))
>>> L.solve(A, b), L.solve(DM([[1, 2], [0, 1]]), DM([1, 1]), True)
(DM([1, 1]), DM([1, -1]))
>>> L.solve(A, DM([[4, 1], [3, 0]]))
DM(
[[1, 0.4],
 [1, -0.2]])
>>> L.det(A)
5.0
>>> try:
...     L.solve(DM([[1, 1], [1, 1]]), b)
... except RuntimeError as e:
...     print("'nfact' failed" in str(e))
True
>>> Am = MX.sym("A", A.sparsity()); bm = MX.sym("b", 2)
>>> f = Function("f", [Am, bm], [L.solve(Am, bm), L.det(Am)])
>>> f(A, b)
(DM([1, 1]), DM(5))

>> A = DM([3 1; 1 2]); b = DM([4; 3]);
>> L = Linsol('L', 'qr', A.sparsity());
>> L.plugin_name(), L.sparsity()
qr
2x2
>> L.solve(A, b), L.solve(DM([1 2; 0 1]), DM([1; 1]), true)
[1, 1]
[1, -1]
>> L.solve(A, DM([4 1; 3 0]))
[[1, 0.4],
 [1, -0.2]]
>> L.det(A)
5
>> try, L.solve(DM([1 1; 1 1]), b); catch e, msg = e.message; end
>> contains(msg, '''nfact'' failed')
1
>> Am = MX.sym('A', A.sparsity()); bm = MX.sym('b', 2);
>> f = Function('f', {Am, bm}, {L.solve(Am, bm), L.det(Am)});
>> [xs, d] = f(A, b); disp(xs), disp(d)
[1, 1]
5

julia> A = ca.DM([3 1; 1 2]); b = ca.DM([4, 3]);
julia> L = ca.Linsol("L", "qr", ca.sparsity(A));
julia> ca.plugin_name(L), ca.sparsity(L)
("qr", 2x2)
julia> ca.solve(L, A, b)
DM([1, 1])
julia> ca.solve(L, ca.DM([1 2; 0 1]), ca.DM([1, 1]), true)
DM([1, -1])
julia> ca.solve(L, A, ca.DM([4 1; 3 0]))
DM(
[[1, 0.4],
 [1, -0.2]])
julia> L.det(A)
5.0
julia> try
           ca.solve(L, ca.DM([1 1; 1 1]), b, false)
       catch e
           println(occursin("'nfact' failed", sprint(showerror, e)))
       end
true
julia> Am = ca.MX.sym("A", ca.sparsity(A)); bm = ca.MX.sym("b", 2);
julia> f = ca.Function("f", [Am, bm], [ca.solve(L, Am, bm), L.det(Am)]);
julia> f(A, b)
([1, 1], 5)

General information

List of plugins

- csparsecholesky

- csparse

- ma27

- lapacklu

- lapackqr

- mumps

- ldl

- qr

- tridiag

- symbolicqr

Note: some of the plugins in this list might not be available on your system. Also, there might be extra plugins available to you that are not listed here. You can obtain their documentation with Linsol.doc("myextraplugin")


csparsecholesky

Linsol with CSparseCholesky Interface

Extra doc: https://github.com/casadi/casadi/wiki/L_21u


csparse

Linsol with CSparse Interface

Extra doc: https://github.com/casadi/casadi/wiki/L_21t


ma27

Interface to the sparse direct linear solver MA27 Works for symmetric indefinite systems Partly adopted from qpOASES 3.2

Author
Joel Andersson
Date
2016

Extra doc: https://github.com/casadi/casadi/wiki/L_229


lapacklu

This class solves the linear system A.x=b by making an LU factorization of A:
A = L.U, with L lower and U upper triangular

Extra doc: https://github.com/casadi/casadi/wiki/L_22h


List of available options
IdTypeDescription
allow_equilibration_failureOT_BOOLNon-fatal error when equilibration fails
equilibrationOT_BOOLEquilibrate the matrix

lapackqr

This class solves the linear system A.x=b by making an QR factorization of A:
A = Q.R, with Q orthogonal and R upper triangular

Extra doc: https://github.com/casadi/casadi/wiki/L_22g


List of available options
IdTypeDescription
max_nrhsOT_INTMaximum number of right-hand-sides that get processed in a single pass [default:10].

mumps

Interface to the sparse direct linear solver MUMPS Works for symmetric indefinite systems

Author
Joel Andersson
Date
2019

Extra doc: https://github.com/casadi/casadi/wiki/L_22t


List of available options
IdTypeDescription
posdefOT_BOOLPositive definite
symmetricOT_BOOLSymmetric matrix

ldl

Linear solver using sparse direct LDL factorization

Extra doc: https://github.com/casadi/casadi/wiki/L_233


List of available options
IdTypeDescription
incompleteOT_BOOLIncomplete factorization, without any fill-in
preorderingOT_BOOLApproximate minimal degree (AMD) preordering

qr

Linear solver using sparse direct QR factorization

Extra doc: https://github.com/casadi/casadi/wiki/L_22z


List of available options
IdTypeDescription
cacheOT_DOUBLEAmount of factorisations to remember (thread-local) [0]
epsOT_DOUBLEMinimum R entry before singularity is declared [1e-12]

tridiag

Linear solver for tridiagonal matrices

Extra doc: https://github.com/casadi/casadi/wiki/L_22v


symbolicqr

Linear solver for sparse least-squares problems Inspired from https://github.com/scipy/scipy/blob/v0.14.0/scipy/sparse/linalg/isolve/lsqr.py#L96

Extra doc: https://github.com/casadi/casadi/wiki/L_230

Linsol based on QR factorization with sparsity pattern based reordering without partial pivoting

Extra doc: https://github.com/casadi/casadi/wiki/L_231


List of available options
IdTypeDescription
foptsOT_DICTOptions to be passed to generated function objects
Author
Joel Andersson
Date
2011-2016

Extra doc: https://github.com/casadi/casadi/wiki/L_1kh

Definition at line 142 of file linsol.hpp.

Inheritance diagram for casadi::Linsol:
Inheritance graph
[legend]

Public Types

using internal_base_type = SharedObjectInternal
 
using base_type = SharedObject
 

Public Member Functions

 Linsol ()
 Default constructor (a null object) More...
 
 Linsol (const std::string &name, const std::string &solver, const Sparsity &sp, const Dict &opts=Dict())
 Create a linear solver. More...
 
LinsolInternal * operator-> ()
 Access functions of the node. More...
 
const LinsolInternal * operator-> () const
 
std::string plugin_name () const
 Query plugin name. More...
 
const Sparsity & sparsity () const
 Get the sparsity pattern of A fixed at construction. More...
 
void sfact (const DM &A) const
 Symbolic factorization of the linear system, e.g. selecting pivots. More...
 
void nfact (const DM &A) const
 Numeric factorization of the linear system. More...
 
casadi_int neig (const DM &A) const
 Number of negative eigenvalues. More...
 
casadi_int rank (const DM &A) const
 Matrix rank. More...
 
double det (const DM &A) const
 Matrix determinant. More...
 
MX det (const MX &A) const
 Matrix determinant as an MX graph node. More...
 
Dict stats (int mem=1) const
 Get all statistics obtained at the end of the last evaluate call. More...
 
std::string class_name () const
 Get class name. More...
 
void disp (std::ostream &stream, bool more=false) const
 Print a description of the object. More...
 
std::string get_str (bool more=false) const
 Get string representation. More...
 
std::string debug_repr () const
 
bool is_null () const
 Is a null pointer? More...
 
casadi_int __hash__ () const
 Returns a number that is unique for a given Node. More...
 
DM solve (const DM &A, const DM &B, bool tr=false) const
 Solve the linear system A*X = B (or A'*X = B with tr true) More...
 
MX solve (const MX &A, const MX &B, bool tr=false) const
 Solve the linear system A*X = B (or A'*X = B with tr true) More...
 

Static Public Member Functions

static std::string type_name ()
 Get type name. More...
 
static bool has_plugin (const std::string &name)
 Check if a plugin is available. More...
 
static void load_plugin (const std::string &name)
 Explicitly load a plugin dynamically. More...
 
static std::string doc (const std::string &name)
 Get solver specific documentation. More...
 

Member Typedef Documentation

◆ base_type

Definition at line 103 of file shared_object.hpp.

◆ internal_base_type

using casadi::SharedObject::internal_base_type = SharedObjectInternal
inherited

Definition at line 102 of file shared_object.hpp.

Constructor & Destructor Documentation

◆ Linsol() [1/2]

casadi::Linsol::Linsol ( )

◆ Linsol() [2/2]

casadi::Linsol::Linsol ( const std::string &  name,
const std::string &  solver,
const Sparsity &  sp,
const Dict &  opts = Dict() 
)
explicit
Parameters
nameName of the solver object
solverPlugin name, e.g. "qr", "ldl", "csparse"; see has_linsol
spSparsity pattern of A (square); the numerical values are given at every call
optsOptions; an unknown option raises an error

>>> L = Linsol("L", "ldl", Sparsity.dense(2, 2))
>>> L
Linsol(Linear solver LinsolLdl)
>>> try:
...     Linsol("L", "qr", Sparsity.dense(2, 2), {"no_such_option": 1})
... except RuntimeError as e:
...     print("Unknown option" in str(e))
True

>> L = Linsol('L', 'ldl', Sparsity.dense(2, 2)); disp(L)
Linear solver LinsolLdl
>> opts = struct('no_such_option', 1);
>> try, Linsol('L', 'qr', Sparsity.dense(2, 2), opts); catch e, msg = e.message; end
>> contains(msg, 'Unknown option')
1

julia> L = ca.Linsol("L", "ldl", ca.Sparsity.dense(2, 2));
julia> ca.str(L)
"Linear solver LinsolLdl"
julia> try
           ca.Linsol("L", "qr", ca.Sparsity.dense(2, 2), Dict("no_such_option" => 1))
       catch e
           println(occursin("Unknown option", sprint(showerror, e)))
       end
true

Extra doc: https://github.com/casadi/casadi/wiki/L_2pe

Member Function Documentation

◆ __hash__()

casadi_int casadi::GenericShared< SharedObject , SharedObjectInternal >::__hash__
inherited

If the Object does not point to any node, "0" is returned.

Extra doc: https://github.com/casadi/casadi/wiki/L_av

Definition at line 123 of file generic_shared_impl.hpp.

◆ class_name()

std::string casadi::SharedObject::class_name ( ) const
inherited

◆ debug_repr()

std::string casadi::GenericShared< SharedObject , SharedObjectInternal >::debug_repr
inherited

Definition at line 112 of file generic_shared_impl.hpp.

◆ det() [1/2]

double casadi::Linsol::det ( const DM &  A) const

Not available for all solvers ("qr" and "csparse"); factorizes A first.

>>> A = DM([[3, 1], [1, 2]])
>>> Linsol("L", "qr", A.sparsity()).det(A)
5.0
>>> try:
...     Linsol("L", "ldl", A.sparsity()).det(A)
... except RuntimeError as e:
...     print("'det' not defined" in str(e))
True

>> A = DM([3 1; 1 2]); L = Linsol('L', 'qr', A.sparsity()); disp(L.det(A))
5
>> L = Linsol('L', 'ldl', A.sparsity());
>> try, L.det(A); catch e, disp(contains(e.message, '''det'' not defined')); end
1

julia> A = ca.DM([3 1; 1 2]);
julia> ca.Linsol("L", "qr", ca.sparsity(A)).det(A)
5.0
julia> try
           ca.Linsol("L", "ldl", ca.sparsity(A)).det(A)
       catch e
           println(occursin("'det' not defined", sprint(showerror, e)))
       end
true

Extra doc: https://github.com/casadi/casadi/wiki/L_2hw

◆ det() [2/2]

MX casadi::Linsol::det ( const MX &  A) const

◆ disp()

void casadi::SharedObject::disp ( std::ostream &  stream,
bool  more = false 
) const
inherited

◆ doc()

static std::string casadi::Linsol::doc ( const std::string &  name)
static

Same as doc_linsol.

>>> "LDL" in Linsol.doc("ldl")
True

>> contains(Linsol.doc('ldl'), 'LDL')
1

julia> occursin("LDL", ca.Linsol.doc("ldl"))
true

Extra doc: https://github.com/casadi/casadi/wiki/L_2ph

◆ get_str()

std::string casadi::SharedObject::get_str ( bool  more = false) const
inlineinherited

Definition at line 91 of file shared_object.hpp.

◆ has_plugin()

static bool casadi::Linsol::has_plugin ( const std::string &  name)
static

Same as has_linsol.

>>> Linsol.has_plugin("qr"), Linsol.has_plugin("no_such_plugin")
(True, False)

>> Linsol.has_plugin('qr'), Linsol.has_plugin('no_such_plugin')
1
0

julia> ca.Linsol.has_plugin("qr"), ca.Linsol.has_plugin("no_such_plugin")
(true, false)

Extra doc: https://github.com/casadi/casadi/wiki/L_2pf

◆ is_null()

bool casadi::GenericShared< SharedObject , SharedObjectInternal >::is_null
inherited

Definition at line 116 of file generic_shared_impl.hpp.

◆ load_plugin()

static void casadi::Linsol::load_plugin ( const std::string &  name)
static

Same as load_linsol; raises an error when the plugin cannot be found.

>>> try:
...     Linsol.load_plugin("no_such_plugin")
... except RuntimeError as e:
...     print("no_such_plugin" in str(e))
True

>> try, Linsol.load_plugin('no_such_plugin'); catch e, msg = e.message; end
>> contains(msg, 'no_such_plugin')
1

julia> try
           ca.Linsol.load_plugin("no_such_plugin")
       catch e
           println(occursin("no_such_plugin", sprint(showerror, e)))
       end
true

Extra doc: https://github.com/casadi/casadi/wiki/L_2pg

◆ neig()

casadi_int casadi::Linsol::neig ( const DM &  A) const

Not available for all solvers (only "ldl"); uses the factorization of the most recent nfact call, which must have been made with the same matrix.

>>> A = DM([[-2, 0], [0, 1]])
>>> L = Linsol("L", "ldl", A.sparsity())
>>> L.nfact(A)
>>> L.neig(A)
1
>>> try:
...     Linsol("L", "qr", A.sparsity()).neig(A)
... except RuntimeError as e:
...     print("'neig' not defined" in str(e))
True

>> A = DM([-2 0; 0 1]); L = Linsol('L', 'ldl', A.sparsity());
>> L.nfact(A); disp(L.neig(A))
1
>> L = Linsol('L', 'qr', A.sparsity());
>> try, L.neig(A); catch e, disp(contains(e.message, '''neig'' not defined')); end
1

julia> A = ca.DM([-2 0; 0 1]);
julia> L = ca.Linsol("L", "ldl", ca.sparsity(A));
julia> ca.nfact(L, A)
julia> ca.neig(L, A)
1
julia> try
           ca.neig(ca.Linsol("L", "qr", ca.sparsity(A)), A)
       catch e
           println(occursin("'neig' not defined", sprint(showerror, e)))
       end
true

Extra doc: https://github.com/casadi/casadi/wiki/L_1kk

◆ nfact()

void casadi::Linsol::nfact ( const DM &  A) const

Factorizes the values of A (after sfact if not done yet), so that neig, rank and the low-level solve can use the factorization. Raises an error when the factorization fails with option "regularity_check" set; otherwise a failure is only reported by solve.

>>> A = DM([[3, 1], [1, 2]])
>>> L = Linsol("L", "ldl", A.sparsity())
>>> L.nfact(A)
>>> L.neig(A), L.rank(A)
(0, 2)
>>> L.nfact(DM([[-1, 0], [0, 1]]))
>>> L.neig(DM([[-1, 0], [0, 1]]))
1

>> A = DM([3 1; 1 2]); L = Linsol('L', 'ldl', A.sparsity());
>> L.nfact(A); fprintf('%d %d\n', L.neig(A), L.rank(A))
0 2
>> B = DM([-1 0; 0 1]); L.nfact(B); disp(L.neig(B))
1

julia> A = ca.DM([3 1; 1 2]);
julia> L = ca.Linsol("L", "ldl", ca.sparsity(A));
julia> ca.nfact(L, A)
julia> ca.neig(L, A), ca.rank(L, A)
(0, 2)
julia> ca.nfact(L, ca.DM([-1 0; 0 1]))
julia> ca.neig(L, ca.DM([-1 0; 0 1]))
1

Extra doc: https://github.com/casadi/casadi/wiki/L_2pj

◆ operator->() [1/2]

LinsolInternal* casadi::Linsol::operator-> ( )

◆ operator->() [2/2]

const LinsolInternal* casadi::Linsol::operator-> ( ) const

◆ plugin_name()

std::string casadi::Linsol::plugin_name ( ) const

◆ rank()

casadi_int casadi::Linsol::rank ( const DM &  A) const

Not available for all solvers (only "ldl"); uses the factorization of the most recent nfact call, which must have been made with the same matrix.

A rank-deficient matrix also triggers a warning in nfact.

>>> A = DM([[2, 1], [1, 3]])
>>> L = Linsol("L", "ldl", A.sparsity())
>>> L.nfact(A)
>>> L.rank(A)
2

>> A = DM([2 1; 1 3]); L = Linsol('L', 'ldl', A.sparsity());
>> L.nfact(A); disp(L.rank(A))
2

julia> A = ca.DM([2 1; 1 3]);
julia> L = ca.Linsol("L", "ldl", ca.sparsity(A));
julia> ca.nfact(L, A)
julia> ca.rank(L, A)
2

Extra doc: https://github.com/casadi/casadi/wiki/L_1kl

◆ sfact()

void casadi::Linsol::sfact ( const DM &  A) const

Only uses the sparsity pattern of A. Called automatically by nfact and solve when needed; raises an error when the plugin fails.

Extra doc: https://github.com/casadi/casadi/wiki/L_2pi

◆ solve() [1/2]

DM casadi::Linsol::solve ( const DM &  A,
const DM &  B,
bool  tr = false 
) const

For DM arguments, factorizes A and solves for all columns of B at once; the result is dense. For MX arguments, returns an expression node that is differentiable. The row count of A and B must match.

Parameters
ASquare matrix with the sparsity pattern given at construction (projected onto it otherwise)
BRight-hand side, one column per system to solve
trSolve with the transpose of A instead
Returns
X with the shape of B

>>> L = Linsol("L", "qr", Sparsity.dense(2, 2))
>>> L.solve(DM([[3, 1], [1, 2]]), DM([4, 3]))
DM([1, 1])
>>> try:
...     L.solve(DM([[3, 1], [1, 2]]), DM([1, 2, 3]))
... except RuntimeError as e:
...     print("matching row count" in str(e))
True

>> L = Linsol('L', 'qr', Sparsity.dense(2, 2));
>> L.solve(DM([3 1; 1 2]), DM([4; 3]))
[1, 1]
>> try, L.solve(DM([3 1; 1 2]), DM([1; 2; 3])); catch e, msg = e.message; end
>> contains(msg, 'matching row count')
1

julia> L = ca.Linsol("L", "qr", ca.Sparsity.dense(2, 2));
julia> ca.solve(L, ca.DM([3 1; 1 2]), ca.DM([4, 3]))
DM([1, 1])
julia> try
           ca.solve(L, ca.DM([3 1; 1 2]), ca.DM([1, 2, 3]))
       catch e
           println(occursin("matching row count", sprint(showerror, e)))
       end
true

Extra doc: https://github.com/casadi/casadi/wiki/L_2pk

◆ solve() [2/2]

MX casadi::Linsol::solve ( const MX &  A,
const MX &  B,
bool  tr = false 
) const

For DM arguments, factorizes A and solves for all columns of B at once; the result is dense. For MX arguments, returns an expression node that is differentiable. The row count of A and B must match.

Parameters
ASquare matrix with the sparsity pattern given at construction (projected onto it otherwise)
BRight-hand side, one column per system to solve
trSolve with the transpose of A instead
Returns
X with the shape of B

>>> L = Linsol("L", "qr", Sparsity.dense(2, 2))
>>> L.solve(DM([[3, 1], [1, 2]]), DM([4, 3]))
DM([1, 1])
>>> try:
...     L.solve(DM([[3, 1], [1, 2]]), DM([1, 2, 3]))
... except RuntimeError as e:
...     print("matching row count" in str(e))
True

>> L = Linsol('L', 'qr', Sparsity.dense(2, 2));
>> L.solve(DM([3 1; 1 2]), DM([4; 3]))
[1, 1]
>> try, L.solve(DM([3 1; 1 2]), DM([1; 2; 3])); catch e, msg = e.message; end
>> contains(msg, 'matching row count')
1

julia> L = ca.Linsol("L", "qr", ca.Sparsity.dense(2, 2));
julia> ca.solve(L, ca.DM([3 1; 1 2]), ca.DM([4, 3]))
DM([1, 1])
julia> try
           ca.solve(L, ca.DM([3 1; 1 2]), ca.DM([1, 2, 3]))
       catch e
           println(occursin("matching row count", sprint(showerror, e)))
       end
true

Extra doc: https://github.com/casadi/casadi/wiki/L_2pk

◆ sparsity()

const Sparsity& casadi::Linsol::sparsity ( ) const

◆ stats()

Dict casadi::Linsol::stats ( int  mem = 1) const

Plugin-specific; empty for most plugins. Raises an error before the first solve. With the option "record_time" set, it holds call counts and timings (n_call_*, t_proc_*, t_wall_*) of sfact, nfact and solve.

>>> L = Linsol("L", "qr", Sparsity.dense(1, 1))
>>> try:
...     L.stats()
... except RuntimeError as e:
...     print("did not solve a problem yet" in str(e))
True
>>> L.solve(DM(2), DM(4)), L.stats()
(DM(2), {})
>>> L = Linsol("L", "qr", Sparsity.dense(1, 1), {"record_time": True})
>>> L.solve(DM(2), DM(4)); L.stats()["n_call_solve"]
DM(2)
1

>> L = Linsol('L', 'qr', Sparsity.dense(1, 1));
>> try, L.stats(); catch e, disp(contains(e.message, 'did not solve a problem yet')); end
1
>> L.solve(DM(2), DM(4)), isempty(fieldnames(L.stats()))
2
1

julia> L = ca.Linsol("L", "qr", ca.Sparsity.dense(1, 1));
julia> try
           ca.stats(L)
       catch e
           println(occursin("did not solve a problem yet", sprint(showerror, e)))
       end
true
julia> ca.solve(L, ca.DM(2), ca.DM(4)), ca.stats(L)
(2, Dict{String, Any}())
julia> L = ca.Linsol("L", "qr", ca.Sparsity.dense(1, 1), Dict("record_time" => true));
julia> ca.solve(L, ca.DM(2), ca.DM(4)); ca.stats(L)["n_call_solve"]
1

Extra doc: https://github.com/casadi/casadi/wiki/L_2pl

◆ type_name()

static std::string casadi::Linsol::type_name ( )
inlinestatic

Extra doc: https://github.com/casadi/casadi/wiki/L_1ki

Definition at line 149 of file linsol.hpp.


The documentation for this class was generated from the following file: