Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -2,30 +2,33 @@ import std.stdio, std.math, std.algorithm, std.traits,
|
|||
std.typecons, std.numeric, std.range, std.conv;
|
||||
|
||||
template elementwiseMat(string op) {
|
||||
T[][] elementwiseMat(T, U)(in T[][] A, in U B)
|
||||
pure nothrow if (is(U == T) || is(U == T[][])) {
|
||||
static if (is(U == T[][]))
|
||||
assert(A.length == B.length);
|
||||
T[][] elementwiseMat(T)(in T[][] A, in T B) pure nothrow {
|
||||
if (A.empty)
|
||||
return null;
|
||||
auto R = new typeof(return)(A.length, A[0].length);
|
||||
|
||||
foreach (immutable r, const row; A)
|
||||
static if (is(U == T)) {
|
||||
R[r][] = mixin("row[] " ~ op ~ "B");
|
||||
} else {
|
||||
assert(row.length == B[r].length);
|
||||
R[r][] = mixin("row[] " ~ op ~ "B[r][]");
|
||||
}
|
||||
R[r][] = mixin("row[] " ~ op ~ "B");
|
||||
return R;
|
||||
}
|
||||
|
||||
T[][] elementwiseMat(T, U)(in T[][] A, in U[][] B)
|
||||
pure nothrow if (is(Unqual!T == Unqual!U)) {
|
||||
assert(A.length == B.length);
|
||||
if (A.empty)
|
||||
return null;
|
||||
auto R = new typeof(return)(A.length, A[0].length);
|
||||
foreach (immutable r, const row; A) {
|
||||
assert(row.length == B[r].length);
|
||||
R[r][] = mixin("row[] " ~ op ~ "B[r][]");
|
||||
}
|
||||
return R;
|
||||
}
|
||||
}
|
||||
|
||||
alias msum = elementwiseMat!q{ + },
|
||||
msub = elementwiseMat!q{ - },
|
||||
pmul = elementwiseMat!q{ * },
|
||||
pdiv = elementwiseMat!q{ / };
|
||||
alias mSum = elementwiseMat!q{ + },
|
||||
mSub = elementwiseMat!q{ - },
|
||||
pMul = elementwiseMat!q{ * },
|
||||
pDiv = elementwiseMat!q{ / };
|
||||
|
||||
bool isRectangular(T)(in T[][] mat) pure nothrow {
|
||||
return mat.all!(r => r.length == mat[0].length);
|
||||
|
|
@ -49,7 +52,7 @@ in {
|
|||
|
||||
Unqual!T[][] transpose(T)(in T[][] m) pure nothrow {
|
||||
auto r = new Unqual!T[][](m[0].length, m.length);
|
||||
foreach (immutable nr, const row; m)
|
||||
foreach (immutable nr, row; m)
|
||||
foreach (immutable nc, immutable c; row)
|
||||
r[nc][nr] = c;
|
||||
return r;
|
||||
|
|
@ -59,8 +62,8 @@ T norm(T)(in T[][] m) pure nothrow {
|
|||
return transversal(m, 0).map!q{ a ^^ 2 }.sum.sqrt;
|
||||
}
|
||||
|
||||
T[][] makeUnitVector(T)(in size_t dim) pure nothrow {
|
||||
auto result = new T[][](dim, 1);
|
||||
Unqual!T[][] makeUnitVector(T)(in size_t dim) pure nothrow {
|
||||
auto result = new Unqual!T[][](dim, 1);
|
||||
foreach (row; result)
|
||||
row[] = 0;
|
||||
result[0][0] = 1;
|
||||
|
|
@ -68,8 +71,8 @@ T[][] makeUnitVector(T)(in size_t dim) pure nothrow {
|
|||
}
|
||||
|
||||
/// Return a nxn identity matrix.
|
||||
T[][] matId(T)(in size_t n) pure nothrow {
|
||||
auto Id = new T[][](n, n);
|
||||
Unqual!T[][] matId(T)(in size_t n) pure nothrow {
|
||||
auto Id = new Unqual!T[][](n, n);
|
||||
foreach (immutable r, row; Id) {
|
||||
row[] = 0;
|
||||
row[r] = 1;
|
||||
|
|
@ -77,10 +80,10 @@ T[][] matId(T)(in size_t n) pure nothrow {
|
|||
return Id;
|
||||
}
|
||||
|
||||
Unqual!T[][] slice2D(T)(in T[][] A,
|
||||
in size_t ma, in size_t mb,
|
||||
in size_t na, in size_t nb) pure nothrow {
|
||||
auto B = new Unqual!T[][](mb - ma + 1, nb - na + 1);
|
||||
T[][] slice2D(T)(in T[][] A,
|
||||
in size_t ma, in size_t mb,
|
||||
in size_t na, in size_t nb) pure nothrow {
|
||||
auto B = new T[][](mb - ma + 1, nb - na + 1);
|
||||
foreach (immutable i, brow; B)
|
||||
brow[] = A[ma + i][na .. na + brow.length];
|
||||
return B;
|
||||
|
|
@ -93,7 +96,7 @@ size_t cols(T)(in T[][] A) pure nothrow {
|
|||
}
|
||||
|
||||
T[][] mcol(T)(in T[][] A, in size_t n) pure nothrow {
|
||||
return slice2D(A, 0, rows(A)-1, n, n);
|
||||
return slice2D(A, 0, A.rows - 1, n, n);
|
||||
}
|
||||
|
||||
T[][] matEmbed(T)(in T[][] A, in T[][] B,
|
||||
|
|
@ -109,13 +112,13 @@ T[][] matEmbed(T)(in T[][] A, in T[][] B,
|
|||
// Main routines ---------------
|
||||
|
||||
T[][] makeHouseholder(T)(in T[][] a) {
|
||||
immutable size_t m = rows(a);
|
||||
immutable T s = sgn(a[0][0]);
|
||||
immutable m = a.rows;
|
||||
immutable T s = a[0][0].sgn;
|
||||
immutable e = makeUnitVector!T(m);
|
||||
immutable u = msum(a, pmul(e, norm(a) * s));
|
||||
immutable v = pdiv(u, u[0][0]);
|
||||
immutable beta = 2.0 / matMul(transpose(v), v)[0][0];
|
||||
return msub(matId!T(m), pmul(matMul(v, transpose(v)), beta));
|
||||
immutable u = mSum(a, pMul(e, a.norm * s));
|
||||
immutable v = pDiv(u, u[0][0]);
|
||||
immutable beta = 2.0 / v.transpose.matMul(v)[0][0];
|
||||
return mSub(matId!T(m), pMul(v.matMul(v.transpose), beta));
|
||||
}
|
||||
|
||||
Tuple!(T[][],"Q", T[][],"R") QRdecomposition(T)(T[][] A) {
|
||||
|
|
@ -124,25 +127,25 @@ Tuple!(T[][],"Q", T[][],"R") QRdecomposition(T)(T[][] A) {
|
|||
auto Q = matId!T(m);
|
||||
|
||||
// Work on n columns of A.
|
||||
foreach (immutable i; 0 .. (m == n ? n-1 : n)) {
|
||||
foreach (immutable i; 0 .. (m == n ? n - 1 : n)) {
|
||||
// Select the i-th submatrix. For i=0 this means the original
|
||||
// matrix A.
|
||||
immutable B = slice2D(A, i, m-1, i, n-1);
|
||||
immutable B = slice2D(A, i, m - 1, i, n - 1);
|
||||
|
||||
// Take the first column of the current submatrix B.
|
||||
immutable x = mcol(B, 0);
|
||||
|
||||
// Create the Householder matrix for the column and embed it
|
||||
// into an mxm identity.
|
||||
immutable H = matEmbed(matId!T(m), makeHouseholder(x), i, i);
|
||||
immutable H = matEmbed(matId!T(m), x.makeHouseholder, i, i);
|
||||
|
||||
// The product of all H matrices from the right hand side is
|
||||
// the orthogonal matrix Q.
|
||||
Q = matMul(Q, H);
|
||||
Q = Q.matMul(H);
|
||||
|
||||
// The product of all H matrices with A from the LHS is the
|
||||
// upper triangular matrix R.
|
||||
A = matMul(H, A);
|
||||
A = H.matMul(A);
|
||||
}
|
||||
|
||||
// Return Q and R.
|
||||
|
|
@ -153,7 +156,7 @@ Tuple!(T[][],"Q", T[][],"R") QRdecomposition(T)(T[][] A) {
|
|||
|
||||
/// Solve an upper triangular system by back substitution.
|
||||
T[][] solveUpperTriangular(T)(in T[][] R, in T[][] b) pure nothrow {
|
||||
immutable size_t n = cols(R);
|
||||
immutable n = R.cols;
|
||||
auto x = new T[][](n, 1);
|
||||
|
||||
foreach_reverse (immutable k; 0 .. n) {
|
||||
|
|
@ -168,33 +171,32 @@ T[][] solveUpperTriangular(T)(in T[][] R, in T[][] b) pure nothrow {
|
|||
|
||||
/// Solve a linear least squares problem by QR decomposition.
|
||||
T[][] lsqr(T)(T[][] A, in T[][] b) pure nothrow {
|
||||
const qr = QRdecomposition(A);
|
||||
immutable size_t n = cols(qr.R);
|
||||
const qr = A.QRdecomposition;
|
||||
immutable n = qr.R.cols;
|
||||
return solveUpperTriangular(
|
||||
slice2D(qr.R, 0, n-1, 0, n-1),
|
||||
slice2D(matMul(transpose(qr.Q), b), 0, n-1, 0, 0));
|
||||
slice2D(qr.R, 0, n - 1, 0, n - 1),
|
||||
slice2D(qr.Q.transpose.matMul(b), 0, n - 1, 0, 0));
|
||||
}
|
||||
|
||||
Unqual!T[][] polyFit(T)(in T[][] x, in T[][] y, in size_t n)
|
||||
pure nothrow {
|
||||
immutable size_t m = cols(x);
|
||||
auto A = new Unqual!T[][](m, n + 1);
|
||||
T[][] polyFit(T)(in T[][] x, in T[][] y, in size_t n) pure nothrow {
|
||||
immutable size_t m = x.cols;
|
||||
auto A = new T[][](m, n + 1);
|
||||
foreach (immutable i, row; A)
|
||||
foreach (immutable j, ref item; row)
|
||||
item = x[0][i] ^^ j;
|
||||
return lsqr(A, transpose(y));
|
||||
return lsqr(A, y.transpose);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// const (Q, R) = QRdecomposition(
|
||||
const qr = QRdecomposition([[12.0, -51, 4],
|
||||
[ 6.0, 167, -68],
|
||||
[-4.0, 24, -41]]);
|
||||
immutable string form = "[%([%(%2.3f, %)]%|,\n %)]\n";
|
||||
// immutable (Q, R) = QRdecomposition([[12.0, -51, 4],
|
||||
immutable qr = QRdecomposition([[12.0, -51, 4],
|
||||
[ 6.0, 167, -68],
|
||||
[-4.0, 24, -41]]);
|
||||
immutable form = "[%([%(%2.3f, %)]%|,\n %)]\n";
|
||||
writefln(form, qr.Q);
|
||||
writefln(form, qr.R);
|
||||
|
||||
immutable x = [[0.0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]];
|
||||
immutable y = [[1.0, 6, 17, 34, 57, 86, 121, 162, 209, 262, 321]];
|
||||
writeln(polyFit(x, y, 2));
|
||||
polyFit(x, y, 2).writeln;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue