Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
a local clone.
kaleidic.lubeck
Lubeck - Linear Algebra
Authors:
Ilya Yaroshenko, Lars Tandle Kyllingstad (SciD author)
- template
BlasType(Iterators...) - Gets the type that can be used with Blas routines that all types can be implicitly converted to.
- Slice!(BlasType!(IteratorA, IteratorB)*, 2)
mtimes(IteratorA, SliceKind kindA, IteratorB, SliceKind kindB)(Slice!(IteratorA, 2, kindA)a, Slice!(IteratorB, 2, kindB)b); - General matrix-matrix multiplication. Allocates result to an uninitialized slice using GC.Parameters:
Slice!(IteratorA, 2, kindA) am(rows) x k(cols) matrix Slice!(IteratorB, 2, kindB) bk(rows) x n(cols) matrix Result m(rows) x n(cols)
Examples:import mir.ndslice; auto a = [-5, 1, 7, 7, -4, -1, -5, 6, 3, -3, -5, -2, -3, 6, 0].sliced(3, 5); auto b = slice!double(5, 4); b[] = [[-5, -3, 3, 1], [ 4, 3, 6, 4], [-4, -2, -2, 2], [-1, 9, 4, 8], [ 9, 8, 3, -2]]; assert(mtimes(a, b) == [[-42, 35, -7, 77], [-69, -21, -42, 21], [ 23, 69, 3, 29]] );
Examples:ger specialized case in mtimesimport mir.ndslice; // from https://github.com/kaleidicassociates/lubeck/issues/8 { auto a = [1.0f, 2.0f].sliced(2, 1); auto b = [1.0f, 2.0f].sliced(2, 1); assert(mtimes(a, b.transposed) == [[1, 2], [2, 4]]); } { auto a = [1.0, 2.0].sliced(1, 2); auto b = [1.0, 2.0].sliced(1, 2); assert(mtimes(a.transposed, b) == [[1, 2], [2, 4]]); }
Examples:import mir.ndslice; // from https://github.com/kaleidicassociates/lubeck/issues/3 Slice!(float*, 2) a = slice!float(1, 1); Slice!(float*, 2, Universal) b1 = slice!float(16, 1).transposed; Slice!(float*, 2) b2 = slice!float(1, 16); a[] = 3; b1[] = 4; b2[] = 4; // Confirm that this message does not appear // Outputs: ** On entry to SGEMM parameter number 8 had an illegal value assert(a.mtimes(b1) == a.mtimes(b2));
- Slice!(BlasType!(IteratorA, IteratorB)*)
mtimes(IteratorA, SliceKind kindA, IteratorB, SliceKind kindB)(Slice!(IteratorA, 2, kindA)a, Slice!(IteratorB, 1, kindB)b); - General matrix-matrix multiplication. Allocates result to an uninitialized slice using GC.Parameters:
Slice!(IteratorA, 2, kindA) am(rows) x k(cols) matrix Slice!(IteratorB, 1, kindB) bk(rows) x 1(cols) vector Result m(rows) x 1(cols)
- Slice!(BlasType!(IteratorA, IteratorB)*)
mtimes(IteratorA, SliceKind kindA, IteratorB, SliceKind kindB)(Slice!(IteratorB, 1, kindB)a, Slice!(IteratorA, 2, kindA)b); - General matrix-matrix multiplication.Parameters:
Slice!(IteratorB, 1, kindB) a1(rows) x k(cols) vector Slice!(IteratorA, 2, kindA) bk(rows) x n(cols) matrix Result 1(rows) x n(cols)
Examples:import mir.ndslice; auto a = [-5, 1, 7, 7, -4, -1, -5, 6, 3, -3, -5, -2, -3, 6, 0] .sliced(3, 5) .universal .transposed; auto b = slice!double(5); b[] = [-5, 4,-4,-1, 9]; assert(mtimes(b, a) == [-42, -69, 23]);
- CommonType!(BlasType!IteratorA, BlasType!IteratorB)
mtimes(IteratorA, SliceKind kindA, IteratorB, SliceKind kindB)(Slice!(IteratorB, 1, kindB)a, Slice!(IteratorA, 1, kindA)b); - Vector-vector multiplication (dot product).Parameters:
Slice!(IteratorB, 1, kindB) a1(rows) x k(cols) vector Slice!(IteratorA, 1, kindA) bk(rows) x 1(cols) matrix Result scalar
Examples:import mir.ndslice; auto a = [1, 2, 4].sliced; auto b = [3, 4, 2].sliced; assert(a.mtimes(b) == 19);
- auto
inv(Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)a); - Calculates the inverse of a matrix.Examples:
import mir.complex; import mir.ndslice; auto a = [ 1, 0, 2, 2, 2, 0, 0, 1, 1] .sliced(3, 3); enum : double { _13 = 1.0/3.0, _16 = 1.0/6.0, _23 = 2.0/3.0 } auto ans = [ _13, _13, -_23, -_13,_16, _23, _13, -_16, _13] .sliced(a.shape); import mir.algorithm.iteration: equal; import mir.math.common: approxEqual; assert(equal!((a, b) => a.approxEqual(b, 1e-10L, 1e-10L))(a.inv, ans)); assert(equal!((a, b) => a.approxEqual(b, 1e-10L, 1e-10L))(a.map!(a => Complex!double(a, 0)).inv.member!"re", ans));
Examples:import mir.ndslice.topology: iota; try { auto m = [3, 3].iota.inv; assert (false, "Matrix should be detected as singular"); } catch (Exception e) { assert (true); }
- struct
SvdResult(T); -
- Slice!(T*, 2)
u; - Slice!(T*)
sigma; - Slice!(T*, 2)
vt;
- auto
svd(Flag!"allowDestroy" allowDestroy = No.allowDestroy, string algorithm = "gesvd", SliceKind kind, Iterator)(Slice!(Iterator, 2, kind)matrix, Flag!"slim"slim= No.slim)
if (algorithm == "gesvd" || algorithm == "gesdd"); - Computes the singular value decomposition.Parameters:
Slice!(Iterator, 2, kind) matrixinput M x N matrix Flag!" slim"slimIf true the first min(M,N) columns of u and the first min(M,N) rows of vt are returned in the ndslices u and vt. Returns:SvdResult. Results are allocated by the GC.Examples:import mir.ndslice; auto a = [ 7.52, -1.10, -7.95, 1.08, -0.76, 0.62, 9.34, -7.10, 5.13, 6.62, -5.66, 0.87, -4.75, 8.52, 5.75, 5.30, 1.33, 4.91, -5.49, -3.52, -2.40, -6.77, 2.34, 3.95] .sliced(6, 4); auto r = a.svd; auto sigma = slice!double(a.shape, 0); sigma.diagonal[] = r.sigma; auto m = r.u.mtimes(sigma).mtimes(r.vt); import mir.algorithm.iteration: equal; import mir.math.common: approxEqual; assert(equal!((a, b) => a.approxEqual(b, 1e-8, 1e-8))(a, m));
Examples:import std.typecons: Yes; import mir.ndslice; auto a = [ 7.52, -1.10, -7.95, 1.08, -0.76, 0.62, 9.34, -7.10, 5.13, 6.62, -5.66, 0.87, -4.75, 8.52, 5.75, 5.30, 1.33, 4.91, -5.49, -3.52, -2.40, -6.77, 2.34, 3.95] .sliced(6, 4); auto r = a.svd(Yes.slim); assert(r.u.shape == [6, 4]); assert(r.vt.shape == [4, 4]);
- Slice!(BlasType!(IteratorA, IteratorB)*, 2)
mldivide(IteratorA, SliceKind kindA, IteratorB, SliceKind kindB)(Slice!(IteratorA, 2, kindA)a, Slice!(IteratorB, 2, kindB)b);
Slice!(BlasType!(IteratorA, IteratorB)*)mldivide(IteratorA, SliceKind kindA, IteratorB, SliceKind kindB)(Slice!(IteratorA, 2, kindA)a, Slice!(IteratorB, 1, kindB)b); - Solve systems of linear equations AX = B for X. Computes minimum-norm solution to a linear least squares problem if A is not a square matrix.Examples:AX=B
import mir.complex; import std.meta: AliasSeq; import mir.ndslice; foreach(C; AliasSeq!(double, Complex!double)) { static if(is(C == Complex!double)) alias transform = a => C(a, 0); else enum transform = "a"; auto a = [ 1, -1, 1, 2, 2, -4, -1, 5, 0].sliced(3, 3).map!transform; auto b = [ 2.0, 0, -6 , -6, 9 , 1].sliced(3, 2).map!transform; auto t = [ 1.0, -1, 2 , 0, 3 , 1].sliced(3, 2).map!transform; auto x = mldivide(a, b); assert(x == t); }
Examples:Ax=Bimport mir.complex; import std.meta: AliasSeq; import mir.ndslice; foreach(C; AliasSeq!(double, Complex!double)) { static if(is(C == Complex!double)) alias transform = a => C(a, 0); else enum transform = "a"; auto a = [ 1, -1, 1, 2, 2, -4, -1, 5, 0].sliced(3, 3).map!transform; auto b = [ 2.0, -6 , 9 ].sliced(3).map!transform; auto t = [ 1.0, 2 , 3 ].sliced(3).map!transform; auto x = mldivide(a, b); assert(x == t); }
Examples:Least-Squares Solution of Underdetermined Systemimport mir.complex; import std.meta: AliasSeq; import mir.ndslice; foreach(C; AliasSeq!(double, )) //Complex!double fails for DMD>=2085 { static if(is(C == Complex!double)) alias transform = a => C(a, 0); else enum transform = "a"; auto a = [ -0.57, -1.28, -0.39, 0.25, -1.93, 1.08, -0.31, -2.14, 2.30, 0.24, 0.40, -0.35, -1.93, 0.64, -0.66, 0.08, 0.15, 0.30, 0.15, -2.13, -0.02, 1.03, -1.43, 0.50, ].sliced(6, 4).map!transform; auto b = [ -2.67, -0.55, 3.34, -0.77, 0.48, 4.10, ].sliced.map!transform; auto x = [ 1.5339, 1.8707, -1.5241, 0.0392].sliced.map!transform; import mir.math.common: approxEqual; import mir.algorithm.iteration: all; alias appr = all!((a, b) => approxEqual(a, b, 1e-3, 1e-3)); assert(appr(a.mldivide(b), x)); }
- struct
PcaResult(T); - Principal component analises result.
- Slice!(T*, 2)
coeff; - Principal component coefficients, also known as loadings.
- Slice!(T*, 2)
score; - Principal component scores.
- Slice!(T*)
latent; - Principal component variances.
- auto
pca(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)matrix, in Flag!"centerColumns"cc= Yes.centerColumns); - Principal component analysis of raw data.Parameters:
Slice!(Iterator, 2, kind) matrixinput M x N matrix, where 'M (rows)>= N(cols)' Flag!"centerColumns" ccFlag to centern columns. True by default. Returns:Examples:import mir.ndslice; import mir.math.common: approxEqual; import mir.algorithm.iteration: equal; auto ingedients = [ 7, 26, 6, 60, 1, 29, 15, 52, 11, 56, 8, 20, 11, 31, 8, 47, 7, 52, 6, 33, 11, 55, 9, 22, 3, 71, 17, 6, 1, 31, 22, 44, 2, 54, 18, 22, 21, 47, 4, 26, 1, 40, 23, 34, 11, 66, 9, 12, 10, 68, 8, 12].sliced(13, 4); auto res = ingedients.pca; auto coeff = [ -0.067799985695474, -0.646018286568728, 0.567314540990512, 0.506179559977705, -0.678516235418647, -0.019993340484099, -0.543969276583817, 0.493268092159297, 0.029020832106229, 0.755309622491133, 0.403553469172668, 0.515567418476836, 0.730873909451461, -0.108480477171676, -0.468397518388289, 0.484416225289198, ].sliced(4, 4); auto score = [ 36.821825999449700, -6.870878154227367, -4.590944457629745, 0.396652582713912, 29.607273420710964, 4.610881963526308, -2.247578163663940, -0.395843536696492, -12.981775719737618, -4.204913183175938, 0.902243082694698, -1.126100587210615, 23.714725720918022, -6.634052554708721, 1.854742000806314, -0.378564808384691, -0.553191676624597, -4.461732123178686, -6.087412652325177, 0.142384896047281, -10.812490833309816, -3.646571174544059, 0.912970791674604, -0.134968810314680, -32.588166608817929, 8.979846284936063, -1.606265913996588, 0.081763927599947, 22.606395499005586, 10.725906457369449, 3.236537714483416, 0.324334774646368, -9.262587237675838, 8.985373347478788, -0.016909578102172, -0.543746175981799, -3.283969329640680, -14.157277337500918, 7.046512994833761, 0.340509860960606, 9.220031117829379, 12.386080787220454, 3.428342878284624, 0.435152769664895, -25.584908517429557, -2.781693148152386, -0.386716066864491, 0.446817950545605, -26.903161834677597, -2.930971165042989, -2.445522630195304, 0.411607156409658, ].sliced(13, 4); auto latent = [5.177968780739053, 0.674964360487231, 0.124054300480810, 0.002371532651878].sliced; latent[] *= 100; assert(equal!approxEqual(res.coeff, coeff)); assert(equal!approxEqual(res.score, score)); assert(equal!approxEqual(res.latent, latent));
- Slice!(BlasType!Iterator*, 2)
pinv(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)matrix, doubletolerance= (double).nan); - Computes Moore-Penrose pseudoinverse of matrix.Parameters:
Slice!(Iterator, 2, kind) matrixInput M x N matrix. double toleranceThe computation is based on SVD and any singular values less than tolerance are treated as zero. Returns:Moore-Penrose pseudoinverse matrixExamples:import mir.ndslice; auto a = [ 64, 2, 3, 61, 60, 6, 9, 55, 54, 12, 13, 51, 17, 47, 46, 20, 21, 43, 40, 26, 27, 37, 36, 30, 32, 34, 35, 29, 28, 38, 41, 23, 22, 44, 45, 19, 49, 15, 14, 52, 53, 11, 8, 58, 59, 5, 4, 62].sliced(8, 6); auto b = a.pinv; auto result = [ 0.0177, -0.0165, -0.0164, 0.0174, 0.0173, -0.0161, -0.0160, 0.0170, -0.0121, 0.0132, 0.0130, -0.0114, -0.0112, 0.0124, 0.0122, -0.0106, -0.0055, 0.0064, 0.0060, -0.0043, -0.0040, 0.0049, 0.0045, -0.0028, -0.0020, 0.0039, 0.0046, -0.0038, -0.0044, 0.0064, 0.0070, -0.0063, -0.0086, 0.0108, 0.0115, -0.0109, -0.0117, 0.0139, 0.0147, -0.0141, 0.0142, -0.0140, -0.0149, 0.0169, 0.0178, -0.0176, -0.0185, 0.0205].sliced(6, 8); import mir.math.common: approxEqual; import mir.algorithm.iteration: all; assert(b.all!((a, b) => approxEqual(a, b, 1e-2, 1e-2))(result));
- Slice!(BlasType!Iterator*, 2)
cov(Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)matrix); - Covariance matrix.Parameters:
Slice!(Iterator, 2, kind) matrixmatrix whose rows represent observations and whose columns represent random variables. Returns:Normalized by N-1 covariance matrix.Examples:import mir.ndslice; import std.stdio; import mir.ndslice; auto c = 8.magic[0..$-1].cov; auto result = [ 350.0000, -340.6667, -331.3333, 322.0000, 312.6667, -303.3333, -294.0000, 284.6667, -340.6667, 332.4762, 324.2857, -316.0952, -307.9048, 299.7143, 291.5238, -283.3333, -331.3333, 324.2857, 317.2381, -310.1905, -303.1429, 296.0952, 289.0476, -282.0000, 322.0000, -316.0952, -310.1905, 304.2857, 298.3810, -292.4762, -286.5714, 280.6667, 312.6667, -307.9048, -303.1429, 298.3810, 293.6190, -288.8571, -284.0952, 279.3333, -303.3333, 299.7143, 296.0952, -292.4762, -288.8571, 285.2381, 281.6190, -278.0000, -294.0000, 291.5238, 289.0476, -286.5714, -284.0952, 281.6190, 279.1429, -276.6667, 284.6667, -283.3333, -282.0000, 280.6667, 279.3333, -278.0000, -276.6667, 275.3333].sliced(8, 8); import mir.math.common: approxEqual; import mir.algorithm.iteration: all; assert(c.all!((a, b) => approxEqual(a, b, 1e-5, 1e-5))(result));
- auto
detSymmetric(Iterator, SliceKind kind)(charstore, Slice!(Iterator, 2, kind)a);
autodet(Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)a); - Matrix determinant.Examples:
import mir.ndslice; import mir.math; // Check for zero-determinant shortcut. auto ssing = [4, 2, 2, 1].sliced(2, 2); auto ssingd = det(ssing); assert (det(ssing) == 0); assert (detSymmetric('L', ssing) == 0); // check determinant of empty matrix assert(slice!double(0, 0).det == 1); // check determinant of zero matrix assert(repeat(0, 9).sliced(3, 3).det == 0); // General dense matrix. int dn = 101; auto d = uninitSlice!double(dn, dn); foreach (k; 0 .. dn) foreach (l; 0 .. dn) d[k,l] = 0.5 * (k == l ? (k + 1) * (k + 1) + 1 : 2 * (k + 1) * (l + 1)); auto dd = det(d); import mir.math.common: approxEqual; assert (approxEqual(dd, 3.539152633479803e289, double.epsilon.sqrt)); // Symmetric packed matrix auto spa = [ 1.0, -2, 3, 4, 5, -6, -7, -8, -9, 10].sliced.stairs!"+"(4); auto sp = [spa.length, spa.length].uninitSlice!double; import mir.algorithm.iteration: each; sp.stairs!"+".each!"a[] = b"(spa); assert (detSymmetric('L', sp).approxEqual(5874.0, double.epsilon.sqrt)); assert (detSymmetric('U', sp.universal.transposed).approxEqual(5874.0, double.epsilon.sqrt));
- struct
EigSymmetricResult(T); - Eigenvalues and eigenvectors POD.See Also:
- Slice!(T*)
values; - Eigenvalues
- Slice!(T*, 2)
vectors; - Eigenvectors stored in rows
- auto
eigSymmetric(Flag!"computeVectors" cv = Yes.computeVectors, Iterator, SliceKind kind)(charstore, Slice!(Iterator, 2, kind)a); - Eigenvalues and eigenvectors of symmetric matrix.Returns:Examples:
import mir.ndslice; import mir.ndslice.slice: sliced; import mir.ndslice.topology: universal, map; import mir.ndslice.dynamic: transposed; import mir.math.common: approxEqual; import mir.algorithm.iteration: all; auto a = [ 1.0000, 0.5000, 0.3333, 0.2500, 0.5000, 1.0000, 0.6667, 0.5000, 0.3333, 0.6667, 1.0000, 0.7500, 0.2500, 0.5000, 0.7500, 1.0000].sliced(4, 4); auto eigr = eigSymmetric('L', a); alias appr = all!((a, b) => approxEqual(a, b, 1e-3, 1e-3)); assert(appr(eigr.values, [0.2078,0.4078,0.8482,2.5362])); auto test = [ 0.0693, -0.4422, -0.8105, 0.3778, -0.3618, 0.7420, -0.1877, 0.5322, 0.7694, 0.0486, 0.3010, 0.5614, -0.5219, -0.5014, 0.4662, 0.5088].sliced(4, 4).transposed; foreach (i; 0 .. 4) assert(appr(eigr.vectors[i], test[i]) || appr(eigr.vectors[i].map!"-a", test[i]));
- struct
LUResult(T); - LUResult consist lu factorization.
- Slice!(T*, 2, Canonical)
lut; - Matrix in witch lower triangular is L part of factorization (diagonal elements of L are not stored), upper triangular is U part of factorization.
- Slice!(lapackint*)
ipiv; - The pivot indices, for 1 <= i <= min(M,N), row i of the matrix was interchanged with row ipiv(i).
- @property auto
l(); - L part of the factorization.
- @property auto
u(); - U part of the factorization.
- auto
solve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, size_t N, SliceKind kind)(chartrans, Slice!(Iterator, N, kind)b);
- auto
luDecomp(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)a); - Computes LU factorization of a general 'M x N' matrix 'A' using partial pivoting with row interchanges. The factorization has the form: \A = P * L * U Where P is a permutation matrix, L is lower triangular with unit diagonal elements (lower trapezoidal if m > n), and U is upper triangular (upper trapezoidal if m < n).Parameters:
allowDestroy flag to delete the source matrix. Slice!(Iterator, 2, kind) ainput 'M x N' matrix for factorization. Returns: - auto
luSolve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, SliceKind kindB, size_t N, IteratorB, IteratorLU)(chartrans, Slice!(IteratorLU, 2, Canonical)lut, Slice!(lapackint*)ipiv, Slice!(IteratorB, N, kindB)b); - Solves a system of linear equations \A * X = B, or \A**T * X = B with a general 'N x N' matrix 'A' using the LU factorization computed by luDecomp.Parameters:
allowDestroy flag to delete the source matrix. Slice!(IteratorLU, 2, Canonical) lutfactorization of matrix 'A', A = P * L * U. Slice!(lapackint*) ipivthe pivot indices from luDecomp. Slice!(IteratorB, N, kindB) bthe right hand side matrix B. char transspecifies the form of the system of equations: 'N': A * X = B (No transpose) 'T': AT * X = B (Transpose) 'C': AT * X = B (Conjugate transpose = Transpose) Returns:Return solve of the system linear equations.Examples:import mir.math; import mir.ndslice; auto A = [ 1, 4, -3, 5, 6, -2, 8, 5, 7, 8, 3, 4, 7, 9, 1, 2, 4, 6, 3, 2, 6, 8, 3, 5, 2 ] .sliced(5, 5) .as!double.slice .canonical; import mir.random.variable; import mir.random.algorithm; auto B = randomSlice(uniformVar(-100, 100), 5, 100); auto LU = A.luDecomp(); auto X = LU.solve('N', B); import mir.algorithm.iteration: equal; assert(equal!((a, b) => fabs(a - b) < 1e-12)(mtimes(A, X), B));
- struct
LDLResult(T); - Consist LDL factorization;
- char
uplo; - uplo = 'U': Upper triangle is stored; 'L': lower triangle is stored.
- Slice!(T*, 2, Canonical)
matrix; - Matrix in witch lower triangular matrix is 'L' part of factorization, diagonal is 'D' part.
- Slice!(lapackint*)
ipiv; - The pivot indices. If ipiv(k) > 0, then rows and columns k and ipiv(k) were interchanged and D(k, k) is a '1 x 1' diagonal block. If ipiv(k) = ipiv(k + 1) < 0, then rows and columns k+1 and -ipiv(k) were interchanged and D(k:k+1, k:k+1) is a '2 x 2' diagonal block.
- auto
solve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, SliceKind kindB, size_t N, IteratorB)(Slice!(IteratorB, N, kindB)b); - Return solves a system of linear equations \A * X = B, using LDL factorization.
- auto
ldlDecomp(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, SliceKind kind)(charuplo, Slice!(Iterator, 2, kind)a); - Computes the factorization of a real symmetric matrix A using the Bunch-Kaufman diagonal pivoting method. The for of the factorization is: \A = LDL**T Where L is product if permutation and unit lower triangular matrices, and D is symmetric and block diagonal with '1 x 1' and '2 x 2' diagonal blocks.Parameters:
allowDestroy flag to delete the source matrix. Slice!(Iterator, 2, kind) ainput symmetric 'n x n' matrix for factorization. char uplo'U': Upper triangle is stored; 'L': lower triangle is stored. Returns:LDLResult - auto
ldlSolve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, SliceKind kindB, size_t N, IteratorB, IteratorA)(charuplo, Slice!(IteratorA, 2, Canonical)a, Slice!(lapackint*)ipiv, Slice!(IteratorB, N, kindB)b); - Solves a system of linear equations \A * X = B with symmetric matrix 'A' using the factorization \A = U * D * UT, or \A = L * D * LT computed by ldlDecomp.Parameters:
allowDestroy flag to delete the source matrix. Slice!(IteratorA, 2, Canonical) a'LD' or 'UD' matrix computed by ldlDecomp. Slice!(lapackint*) ipivdetails of the interchanges and the block structure of D as determined by ldlDecomp. Slice!(IteratorB, N, kindB) bthe right hand side matrix. char uplospecifies whether the details of the factorization are stored as an upper or lower triangular matrix: 'U': Upper triangular, form is \A = U * D * UT; 'L': Lower triangular, form is \A = L * D * LT. Returns:The solution matrix.Examples:import mir.ndslice; auto A = [ 2.07, 3.87, 4.20, -1.15, 3.87, -0.21, 1.87, 0.63, 4.20, 1.87, 1.15, 2.06, -1.15, 0.63, 2.06, -1.81 ] .sliced(4, 4) .as!double.slice .canonical; import mir.random.variable; import mir.random.algorithm; auto B = randomSlice(uniformVar(-100, 100), 4, 100); auto LDL = ldlDecomp('L', A); auto X = LDL.solve(B); import mir.math.common: approxEqual; import mir.algorithm.iteration: equal; alias appr = equal!((a, b) => approxEqual(a, b, 1e-5, 1e-5)); assert(appr(mtimes(A, X), B));
- auto
choleskyDecomp(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, SliceKind kind)(charuplo, Slice!(Iterator, 2, kind)a); - Computs Cholesky decomposition of symmetric positive definite matrix 'A'. The factorization has the form: \A = UT * U, if UPLO = 'U', or \A = L * LT, if UPLO = 'L' Where U is an upper triangular matrix and L is lower triangular.Parameters:
allowDestroy flag to delete the source matrix. Slice!(Iterator, 2, kind) asymmetric 'N x N' matrix. char uploif uplo is Upper, then upper triangle of A is stored, else lower. Returns:Examples:import mir.algorithm.iteration: equal, eachUploPair; import mir.ndslice; import mir.random.algorithm; import mir.random.variable; import mir.math.common: approxEqual; auto A = [ 25, double.nan, double.nan, 15, 18, double.nan, -5, 0, 11 ] .sliced(3, 3); auto B = randomSlice(uniformVar(-100, 100), 3, 100); auto C = choleskyDecomp('L', A); auto X = C.solve(B); A.eachUploPair!"a = b"; assert(equal!approxEqual(mtimes(A, X), B));
- auto
choleskySolve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, SliceKind kindB, size_t N, IteratorB, IteratorC)(charuplo, Slice!(IteratorC, 2, Canonical)c, Slice!(IteratorB, N, kindB)b); - Solves a system of linear equations A * X = B with a symmetric matrix A using the Cholesky factorization: \A = UT * U or \A = L * LT computed by choleskyDecomp.Parameters:
allowDestroy flag to delete the source matrix. Slice!(IteratorC, 2, Canonical) cthe triangular factor 'U' or 'L' from the Cholesky factorization \A = UT * U or \A = L * LT, as computed by choleskyDecomp. Slice!(IteratorB, N, kindB) bthe right hand side matrix. char uplo'U': Upper triangle of A is stored; 'L': Lower triangle of A is stored. Returns:The solution matrix X.Examples:import mir.ndslice.slice: sliced; import mir.ndslice.topology: as; import std.typecons: Flag, Yes; auto A = [ 1.0, 1, 3, 1 , 5, 5, 3 , 5, 19 ].sliced(3, 3); auto B = [ 10.0, 157, 80 ].sliced; auto C_ = B.dup.sliced(3, 1); auto C = choleskyDecomp('U', A); auto X = choleskySolve!(Yes.allowDestroy)(C.uplo, C.matrix, B); import mir.math.common: approxEqual; import mir.algorithm.iteration: equal; alias appr = equal!((a, b) => approxEqual(a, b, 1e-5, 1e-5)); assert(appr(mtimes(A, X), C_));
- struct
QRResult(T); - Examples:
import mir.ndslice; auto A = [ 1, 1, 0, 1, 0, 1, 0, 1, 1 ] .sliced(3, 3) .as!double.slice; auto Q_test = [ -0.7071068, 0.4082483, -0.5773503, -0.7071068, -0.4082483, 0.5773503, 0, 0.8164966, 0.5773503] .sliced(3, 3) .as!double.slice; auto R_test = [ -1.414214, -0.7071068, -0.7071068, 0, 1.2247449, 0.4082483, 0, 0, 1.1547005] .sliced(3, 3) .as!double.slice; auto val = qrDecomp(A); //saving these values to doublecheck they don't change later auto val_matrix = val.matrix.slice; auto val_tau = val.tau.slice; import mir.math.common: approxEqual; import mir.ndslice : equal; auto r = val.R; assert(equal!approxEqual(val.R, R_test)); auto q = val.Q; assert(equal!approxEqual(val.Q, Q_test)); //double-checking values do not change assert(equal!approxEqual(val_matrix, val.matrix)); assert(equal!approxEqual(val_tau, val.tau)); auto a = val.reconstruct; assert(equal!approxEqual(A, a));
- Slice!(T*, 2, Canonical)
matrix; - Matrix in witch the elements on and above the diagonal of the array contain the min(M, N) x N upper trapezoidal matrix 'R' (R is upper triangular if m >= n). The elements below the diagonal, with the array tau, represent the orthogonal matrix 'Q' as product of min(m, n).
- Slice!(T*)
tau; - The scalar factors of the elementary reflectors
- auto
solve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, size_t N, SliceKind kind)(Slice!(Iterator, N, kind)b); - Solve the least squares problem: \min ||A * X - B|| Using the QR factorization: \A = Q * R computed by qrDecomp.
- auto
Q(Flag!"allowDestroy"allowDestroy= No.allowDestroy); - Extract the Q matrix
- auto
R(); - Extract the R matrix
- auto
reconstruct(); - Reconstruct the original matrix given a QR decomposition
- auto
reconstruct(T, U)(Tq, Ur)
if (isMatrix!T && isMatrix!U); - Reconstruct the original matrix given a QR decomposition
- auto
qrDecomp(Flag!"allowDestroy" allowDestroy = No.allowDestroy, Iterator, SliceKind kind)(Slice!(Iterator, 2, kind)a); - Computes a QR factorization of matrix 'a'.Parameters:
allowDestroy flag to delete the source matrix. Slice!(Iterator, 2, kind) ainitial matrix Returns: - auto
qrSolve(Flag!"allowDestroy" allowDestroy = No.allowDestroy, SliceKind kindB, size_t N, IteratorB, IteratorA, IteratorT)(Slice!(IteratorA, 2, Canonical)a, Slice!IteratorTtau, Slice!(IteratorB, N, kindB)b); - Solve the least squares problem: \min ||A * X - B|| Using the QR factorization: \A = Q * R computed by qrDecomp.Parameters:
allowDestroy flag to delete the source matrix. Slice!(IteratorA, 2, Canonical) adetalis of the QR factorization of the original matrix as returned by qrDecomp. Slice!IteratorT taudetails of the orhtogonal matrix Q. Slice!(IteratorB, N, kindB) bright hand side matrix. Returns:solution matrix.Examples:import mir.ndslice; auto A = [ 3, 1, -1, 2, -5, 1, 3, -4, 2, 0, 1, -1, 1, -5, 3, -3 ] .sliced(4, 4) .as!double.slice; import mir.random.variable; import mir.random.algorithm; auto B = randomSlice(uniformVar(-100, 100), 4, 100); auto C = qrDecomp(A); auto X = C.solve(B); import mir.math.common: approxEqual; import mir.algorithm.iteration: equal; alias appr = equal!((a, b) => approxEqual(a, b, 1e-5, 1e-5)); assert(appr(mtimes(A, X), B));
Copyright © 2016-2021 by Ilya Yaroshenko | Page generated by
Ddoc on Fri Aug 20 14:35:49 2021