List of all members | Public Types | Public Member Functions | Static Public Member Functions | Protected 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]
Collaboration diagram for casadi::Linsol:
Collaboration 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...
 
casadi_int checkout () const
 Checkout a memory object. More...
 
void release (int mem) const
 Release a memory object. More...
 
void serialize (SerializingStream &s) const
 Serialize an object. 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...
 
void print_ptr (std::ostream &stream=casadi::uout()) const
 
void own (SharedObjectInternal *node)
 
void assign (SharedObjectInternal *node)
 Assign the node to a node class pointer without reference counting. More...
 
SharedObjectInternal * get () const
 Get a const pointer to the node. More...
 
casadi_int getCount () const
 Get the reference count. More...
 
void swap (GenericShared &other)
 Swap content with another instance. 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...
 
GenericWeakRef< SharedObject, SharedObjectInternal > * weak ()
 Get a weak reference to the object. 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...
 
int sfact (const double *A, int mem=0) const
 
int nfact (const double *A, int mem=0) const
 
int solve (const double *A, double *x, casadi_int nrhs=1, bool tr=false, int mem=0) const
 
double det (const double *A, int mem=0) const
 
casadi_int neig (const double *A, int mem=0) const
 
casadi_int rank (const double *A, int mem=0) const
 

Static Public Member Functions

static std::string type_name ()
 Get type name. More...
 
static bool test_cast (const SharedObjectInternal *ptr)
 Check if a particular cast is allowed. More...
 
static Linsol create (LinsolInternal *node)
 Create from node. 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...
 
static Linsol deserialize (DeserializingStream &s)
 Deserialize with type disambiguation. More...
 

Protected Member Functions

void count_up ()
 
void count_down ()
 

Member Typedef Documentation

◆ base_type

Definition at line 103 of file shared_object.hpp.

◆ internal_base_type

Definition at line 102 of file shared_object.hpp.

Constructor & Destructor Documentation

◆ Linsol() [1/2]

casadi::Linsol::Linsol ( )

Definition at line 32 of file linsol.cpp.

32  {
33  }

◆ 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

Definition at line 35 of file linsol.cpp.

36  {
37  own(LinsolInternal::getPlugin(solver).creator(name, sp));
38  (*this)->construct(opts);
39  }
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.

References casadi::PluginInterface< LinsolInternal >::getPlugin(), and casadi::GenericShared< SharedObject, SharedObjectInternal >::own().

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.

148  {
149  return reinterpret_cast<casadi_int>(get());
150  }

◆ assign()

void casadi::GenericShared< SharedObject , SharedObjectInternal >::assign ( Internal *  node)
inherited

improper use will cause memory leaks!

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

Definition at line 96 of file generic_shared_impl.hpp.

86  {
87  node = node_;
88  }

◆ checkout()

casadi_int casadi::Linsol::checkout ( ) const

Definition at line 223 of file linsol.cpp.

223  {
224  return (*this)->checkout();
225  }

Referenced by casadi::SundialsInterface::init_mem(), and casadi::Ipqp::solve().

◆ class_name()

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

◆ count_down()

void casadi::GenericShared< SharedObject , SharedObjectInternal >::count_down
protectedinherited

Definition at line 133 of file generic_shared_impl.hpp.

46  {
47 #ifdef WITH_EXTRA_CHECKS
48  casadi_assert_dev(Function::call_depth_==0);
49 #endif // WITH_EXTRA_CHECKS
50  if (!node) return;
51 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
52  GenericWeakRef<Shared, Internal>* weak_ref =
53  node->weak_ref_.load(std::memory_order_acquire);
54 #else
55  GenericWeakRef<Shared, Internal>* weak_ref = node->weak_ref_;
56 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
57  if (weak_ref) {
58 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
59  // get_mutex() returns a shared_ptr copy, so the mutex outlives this lock
60  // even if delete node (below) destroys the WeakRefInternal holding it
61  auto mutex = weak_ref->get_mutex();
62  // Avoid triggering a delete while a weak_ref.shared_if_alive is being called
63  std::lock_guard<std::mutex> lock(*mutex);
64 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
65 
66  if (--static_cast<Internal*>(node)->count == 0) {
67  delete node;
68  node = nullptr;
69  }
70  } else {
71  if (--static_cast<Internal*>(node)->count == 0) {
72  delete node;
73  node = nullptr;
74  }
75  }
76  }

◆ count_up()

void casadi::GenericShared< SharedObject , SharedObjectInternal >::count_up
protectedinherited

Definition at line 132 of file generic_shared_impl.hpp.

36  {
37 #ifdef WITH_EXTRA_CHECKS
38  casadi_assert_dev(Function::call_depth_==0);
39 #endif // WITH_EXTRA_CHECKS
40 
41  if (node) static_cast<Internal*>(node)->count++;
42 
43  }

◆ create()

Linsol casadi::Linsol::create ( LinsolInternal *  node)
static

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

Definition at line 262 of file linsol.cpp.

262  {
263  Linsol ret;
264  ret.own(node);
265  return ret;
266  }
Linsol()
Default constructor (a null object)
Definition: linsol.cpp:32

References casadi::GenericShared< Shared, Internal >::own().

◆ debug_repr()

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

Definition at line 112 of file generic_shared_impl.hpp.

91  {
92  if (node) {
93  return node->debug_repr(node);
94  } else {
95  return "NULL";
96  }
97  }
std::string debug_repr(const Internal *) const

◆ deserialize()

Linsol casadi::Linsol::deserialize ( DeserializingStream &  s)
static

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

Definition at line 255 of file linsol.cpp.

255  {
256  Linsol linsol;
257  linsol.own(LinsolInternal::deserialize(s));
258  linsol->finalize();
259  return linsol;
260  }
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.

References casadi::LinsolInternal::deserialize(), casadi::ProtoFunction::finalize(), and casadi::GenericShared< Shared, Internal >::own().

◆ det() [1/3]

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

Definition at line 198 of file linsol.cpp.

198  {
199  if (A.sparsity()!=sparsity()) return det(project(A, sparsity()));
200  scoped_checkout<Linsol> mem(*this);
201  if (sfact(A.ptr(), mem)) casadi_error("Linsol::det: 'sfact' failed");
202  if (nfact(A.ptr(), mem)) casadi_error("Linsol::det: 'nfact' failed");
203  return det(A.ptr(), mem);
204  }
void nfact(const DM &A) const
Numeric factorization of the linear system.
Definition: linsol.cpp:133
double det(const DM &A) const
Matrix determinant.
Definition: linsol.cpp:198
const Sparsity & sparsity() const
Get the sparsity pattern of A fixed at construction.
Definition: linsol.cpp:69
void sfact(const DM &A) const
Symbolic factorization of the linear system, e.g. selecting pivots.
Definition: linsol.cpp:108

References nfact(), casadi::Matrix< Scalar >::ptr(), sfact(), sparsity(), and casadi::Matrix< Scalar >::sparsity().

Referenced by casadi::MX::det(), casadi::Determinant::eval(), and casadi::Determinant::eval_mx().

◆ det() [2/3]

double casadi::Linsol::det ( const double *  A,
int  mem = 0 
) const

Low-level API

Definition at line 174 of file linsol.cpp.

174  {
175  auto m = static_cast<LinsolMemory*>((*this)->memory(mem));
176  casadi_assert(m->is_nfact, "Linear system has not been factorized");
177  return (*this)->det(m, A);
178  }

◆ det() [3/3]

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

Definition at line 206 of file linsol.cpp.

206  {
207  return A->get_det(*this);
208  }

References casadi::MXNode::get_det().

◆ disp()

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

Definition at line 35 of file shared_object.cpp.

35  {
36  if (is_null()) {
37  stream << "NULL";
38  } else {
39  (*this)->disp(stream, more);
40  }
41  }

References casadi::GenericShared< SharedObject, SharedObjectInternal >::is_null().

Referenced by casadi::WeakRefInternal::disp(), casadi::Nlpsol::disp_more(), and casadi::CsparseInterface::nfact().

◆ doc()

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

Definition at line 61 of file linsol.cpp.

61  {
62  return LinsolInternal::getPlugin(name).doc;
63  }

References casadi::PluginInterface< LinsolInternal >::getPlugin().

Referenced by casadi::doc_linsol().

◆ get()

Definition at line 99 of file generic_shared_impl.hpp.

115  {
116  return node;
117  }

◆ get_str()

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

Definition at line 91 of file shared_object.hpp.

91  {
92  std::stringstream ss;
93  disp(ss, more);
94  return ss.str();
95  }
void disp(std::ostream &stream, bool more=false) const
Print a description of the object.

◆ getCount()

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

Definition at line 102 of file generic_shared_impl.hpp.

138  {
139  return (*this)->getCount();
140  }

◆ has_plugin()

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

Definition at line 53 of file linsol.cpp.

53  {
54  return LinsolInternal::has_plugin(name);
55  }
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.

References casadi::PluginInterface< LinsolInternal >::has_plugin().

Referenced by casadi::has_linsol().

◆ is_null()

Definition at line 116 of file generic_shared_impl.hpp.

120  {
121  return node==nullptr;
122  }

◆ load_plugin()

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

Definition at line 57 of file linsol.cpp.

57  {
59  }
static Plugin load_plugin(const std::string &pname, bool register_plugin=true, bool needs_lock=true)
Load a plugin dynamically.

References casadi::PluginInterface< LinsolInternal >::load_plugin().

Referenced by casadi::load_linsol().

◆ neig() [1/2]

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

Definition at line 180 of file linsol.cpp.

180  {
181  if (A.sparsity()!=sparsity()) return neig(project(A, sparsity()));
182  casadi_int n = neig(A.ptr());
183  casadi_assert(n>=0, "'neig' failed");
184  return n;
185  }
casadi_int neig(const DM &A) const
Number of negative eigenvalues.
Definition: linsol.cpp:180

References casadi::Matrix< Scalar >::ptr(), sparsity(), and casadi::Matrix< Scalar >::sparsity().

Referenced by casadi::QpoasesInterface::qpoases_nfact().

◆ neig() [2/2]

casadi_int casadi::Linsol::neig ( const double *  A,
int  mem = 0 
) const

Low-level API

Definition at line 187 of file linsol.cpp.

187  {
188  return (*this)->neig((*this)->memory(mem), A);
189  }

◆ nfact() [1/2]

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

Definition at line 133 of file linsol.cpp.

133  {
134  if (A.sparsity()!=sparsity()) {
135  nfact(project(A, sparsity()));
136  return;
137  }
138  if (nfact(A.ptr())) casadi_error("'nfact' failed");
139  }

References casadi::Matrix< Scalar >::ptr(), sparsity(), and casadi::Matrix< Scalar >::sparsity().

Referenced by det(), casadi::Determinant::eval(), casadi::SlicotDple::eval(), casadi::KinsolInterface::psetup(), casadi::QpoasesInterface::qpoases_nfact(), solve(), casadi::Ipqp::solve(), and casadi::Newton::solve().

◆ nfact() [2/2]

int casadi::Linsol::nfact ( const double *  A,
int  mem = 0 
) const

Low-level API

Definition at line 141 of file linsol.cpp.

141  {
142  if (A==nullptr) return 1;
143  auto *m = static_cast<LinsolMemory*>((*this)->memory(mem));
144 
145  // Perform pivoting, if required
146  if (!m->is_sfact) {
147  if (sfact(A, mem)) return 1;
148  }
149 
150  m->is_nfact = false;
151  if (m->t_total) m->fstats.at("nfact").tic();
152  int flag = (*this)->nfact(m, A);
153  if (m->t_total) m->fstats.at("nfact").toc();
154  if (flag && (*this)->regularity_check_) {
155  // Collect nonzeros
156  std::vector<std::string> nonzeros(sparsity().nnz());
157  for (size_t nz = 0; nz < nonzeros.size(); ++nz)
158  nonzeros[nz] = std::to_string(A[nz]);
159  // Create .m file
160  std::string fname = (*this)->class_name() + "_" + (*this)->name_ + "_debug.m";
161  auto mfile_ptr = Filesystem::ofstream_ptr(fname);
162  std::ostream& mfile = *mfile_ptr;
163  Dict opts;
164  opts["name"] = "A";
165  opts["nonzeros"] = nonzeros;
166  sparsity().export_code("matlab", mfile, opts);
167  casadi_error("Numerical factorization failed for " + (*this)->name_
168  + "[" + (*this)->class_name() + "]. Linear system saved to '" + fname + "'");
169  }
170  m->is_nfact = true;
171  return flag;
172  }
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
Definition: filesystem.cpp:115
void export_code(const std::string &lang, std::ostream &stream=casadi::uout(), const Dict &options=Dict()) const
Write code that reconstructs the pattern in another language.
Definition: sparsity.cpp:802
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.

References casadi::Sparsity::export_code(), casadi::LinsolMemory::is_nfact, casadi::Filesystem::ofstream_ptr(), sfact(), and sparsity().

◆ operator->() [1/2]

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

Definition at line 41 of file linsol.cpp.

41  {
42  return static_cast<LinsolInternal*>(SharedObject::operator->());
43  }
SharedObjectInternal * operator->() const
Access a member function or object.

References casadi::GenericShared< SharedObject, SharedObjectInternal >::operator->().

◆ operator->() [2/2]

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

Definition at line 45 of file linsol.cpp.

45  {
46  return static_cast<const LinsolInternal*>(SharedObject::operator->());
47  }

References casadi::GenericShared< SharedObject, SharedObjectInternal >::operator->().

◆ own()

void casadi::GenericShared< SharedObject , SharedObjectInternal >::own ( Internal *  node)
inherited

Assign the node to a node class pointer (or null)

Definition at line 89 of file generic_shared_impl.hpp.

◆ plugin_name()

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

Definition at line 65 of file linsol.cpp.

65  {
66  return (*this)->plugin_name();
67  }

◆ print_ptr()

void casadi::SharedObject::print_ptr ( std::ostream &  stream = casadi::uout()) const
inherited

Print the pointer to the internal class

Definition at line 43 of file shared_object.cpp.

43  {
44  stream << get();
45  }
SharedObjectInternal * get() const
Get a const pointer to the node.

References casadi::GenericShared< SharedObject, SharedObjectInternal >::get().

◆ rank() [1/2]

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

Definition at line 191 of file linsol.cpp.

191  {
192  if (A.sparsity()!=sparsity()) return rank(project(A, sparsity()));
193  casadi_int n = rank(A.ptr());
194  casadi_assert(n>=0, "'rank' failed");
195  return n;
196  }
casadi_int rank(const DM &A) const
Matrix rank.
Definition: linsol.cpp:191

References casadi::Matrix< Scalar >::ptr(), sparsity(), and casadi::Matrix< Scalar >::sparsity().

Referenced by casadi::QpoasesInterface::qpoases_nfact().

◆ rank() [2/2]

casadi_int casadi::Linsol::rank ( const double *  A,
int  mem = 0 
) const

Low-level API

Definition at line 210 of file linsol.cpp.

210  {
211  return (*this)->rank((*this)->memory(mem), A);
212  }

◆ release()

void casadi::Linsol::release ( int  mem) const

Definition at line 227 of file linsol.cpp.

227  {
228  (*this)->release(mem);
229  }

Referenced by casadi::Ipqp::solve().

◆ serialize()

void casadi::Linsol::serialize ( SerializingStream &  s) const

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

Definition at line 250 of file linsol.cpp.

250  {
251  // TODO(jgillis): I don't get why LinsolInternal:: this is necessary
252  (*this)->LinsolInternal::serialize(s);
253  }

◆ sfact() [1/2]

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

Definition at line 108 of file linsol.cpp.

108  {
109  if (A.sparsity()!=sparsity()) {
110  sfact(project(A, sparsity()));
111  return;
112  }
113  if (sfact(A.ptr())) casadi_error("'sfact' failed");
114  }

References casadi::Matrix< Scalar >::ptr(), sparsity(), and casadi::Matrix< Scalar >::sparsity().

Referenced by det(), casadi::Determinant::eval(), casadi::SlicotDple::eval(), nfact(), casadi::QpoasesInterface::qpoases_sfact(), and solve().

◆ sfact() [2/2]

int casadi::Linsol::sfact ( const double *  A,
int  mem = 0 
) const

Low-level API

Definition at line 116 of file linsol.cpp.

116  {
117  if (A==nullptr) return 1;
118  auto *m = static_cast<LinsolMemory*>((*this)->memory(mem));
119 
120  // Factorization will be needed after this step
121  m->is_sfact = m->is_nfact = false;
122 
123  if (m->t_total) m->fstats.at("sfact").tic();
124  // Perform pivoting
125  if ((*this)->sfact(m, A)) return 1;
126  if (m->t_total) m->fstats.at("sfact").toc();
127 
128  // Mark as (successfully) pivoted
129  m->is_sfact = true;
130  return 0;
131  }

References casadi::LinsolMemory::is_sfact.

◆ solve() [1/3]

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

Definition at line 73 of file linsol.cpp.

73  {
74  casadi_assert(A.size1()==B.size1(),
75  "Linsol::solve: Dimension mismatch. A and b must have matching row count. "
76  "Got " + A.dim() + " and " + B.dim() + ".");
77 
78  // Quick return if possible
79  if (A.size1()==0) return densify(B);
80 
81  scoped_checkout<Linsol> mem(*this);
82  auto *m = static_cast<LinsolMemory*>((*this)->memory(mem));
83 
84  // Reset statistics
85  for (auto&& s : m->fstats) s.second.reset();
86  if (m->t_total) m->t_total->tic();
87  // Symbolic factorization
88  if (sfact(A.ptr(), mem)) casadi_error("Linsol::solve: 'sfact' failed");
89 
90  // Numeric factorization
91  if (nfact(A.ptr(), mem)) casadi_error("Linsol::solve: 'nfact' failed");
92 
93  // Solve
94  DM x = densify(B);
95  if (solve(A.ptr(), x.ptr(), x.size2(), tr, mem))
96  casadi_error("Linsol::solve: 'solve' failed");
97  // Show statistics
98  if (m->t_total) m->t_total->toc();
99 
100  (*this)->print_time(m->fstats);
101  return x;
102  }
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)
Definition: linsol.cpp:73
Matrix< double > DM
Definition: dm_fwd.hpp:33

References casadi::GenericMatrix< MatType >::dim(), nfact(), casadi::Matrix< Scalar >::ptr(), sfact(), casadi::GenericMatrix< MatType >::size1(), casadi::GenericMatrix< MatType >::size2(), casadi::ProtoFunctionMemory::t_total, and casadi::FStats::tic().

Referenced by casadi::SlicotDple::eval(), casadi::KinsolInterface::psolve(), casadi::QpoasesInterface::qpoases_solve(), casadi::Ipqp::solve(), casadi::LinsolCall< Tr >::solve(), casadi::MX::solve(), casadi::Newton::solve(), and casadi::IdasInterface::solve_transposed().

◆ solve() [2/3]

int casadi::Linsol::solve ( const double *  A,
double *  x,
casadi_int  nrhs = 1,
bool  tr = false,
int  mem = 0 
) const

Low-level API

Definition at line 214 of file linsol.cpp.

214  {
215  auto *m = static_cast<LinsolMemory*>((*this)->memory(mem));
216  casadi_assert(m->is_nfact, "Linear system has not been factorized");
217  if (m->t_total) m->fstats.at("solve").tic();
218  int ret = (*this)->solve(m, A, x, nrhs, tr);
219  if (m->t_total) m->fstats.at("solve").toc();
220  return ret;
221  }

◆ solve() [3/3]

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

Definition at line 104 of file linsol.cpp.

104  {
105  return A->get_solve(B, tr, *this);
106  }

References casadi::MXNode::get_solve().

◆ sparsity()

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

Definition at line 69 of file linsol.cpp.

69  {
70  return (*this)->sp_;
71  }

Referenced by det(), casadi::SundialsInterface::init(), neig(), nfact(), rank(), casadi::SundialsInterface::set_work(), and sfact().

◆ 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

Definition at line 244 of file linsol.cpp.

244  {
245  casadi_assert((*this)->has_memory(mem),
246  "No stats available since Linsol did not solve a problem yet.");
247  return (*this)->get_stats((*this)->memory(mem));
248  }

◆ swap()

Definition at line 105 of file generic_shared_impl.hpp.

131  {
132  GenericShared<Shared, Internal> temp = *this;
133  *this = other;
134  other = temp;
135  }

◆ test_cast()

bool casadi::Linsol::test_cast ( const SharedObjectInternal *  ptr)
static

Definition at line 49 of file linsol.cpp.

49  {
50  return dynamic_cast<const LinsolInternal*>(ptr)!=nullptr;
51  }

◆ 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.

149 {return "Linsol";}

◆ weak()

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

Definition at line 130 of file generic_shared_impl.hpp.

143  {
144  return (*this)->weak();
145  }

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