Multiple regression: Difference between revisions

Content deleted Content added
Robbie (talk | contribs)
Robbie (talk | contribs)
Line 515: Line 515:
#2A((0.9999999999999759d0) (2.000000000000005d0) (3.0d0))</lang>
#2A((0.9999999999999759d0) (2.000000000000005d0) (3.0d0))</lang>

=={{header|D}}==
{{trans|Java}}
<lang d>import std.algorithm;
import std.array;
import std.exception;
import std.range;
import std.stdio;

public class Matrix {
private double[][] data;
private size_t rowCount;
private size_t colCount;

public this(size_t size)
in(size > 0, "Must have at least one element")
{
this(size, size);
}

public this(size_t rows, size_t cols)
in(rows > 0, "Must have at least one row")
in(cols > 0, "Must have at least one column")
{
rowCount = rows;
colCount = cols;

data = uninitializedArray!(double[][])(rows, cols);
foreach (ref row; data) {
row[] = 0.0;
}
}

public this(const double[][] source) {
enforce(source.length > 0, "Must have at least one row");
rowCount = source.length;

enforce(source[0].length > 0, "Must have at least one column");
colCount = source[0].length;

data = uninitializedArray!(double[][])(rowCount, colCount);
foreach (i; 0 .. rowCount) {
enforce(source[i].length == colCount, "All rows must have equal columns");
data[i] = source[i].dup;
}
}

public auto opIndex(size_t r, size_t c) const {
return data[r][c];
}

public auto opIndex(size_t r) const {
return data[r];
}

public auto opBinary(string op)(const Matrix rhs) const {
static if (op == "*") {
auto rc1 = rowCount;
auto cc1 = colCount;
auto rc2 = rhs.rowCount;
auto cc2 = rhs.colCount;
enforce(cc1 == rc2, "Cannot multiply if the first columns does not equal the second rows");
auto result = new Matrix(rc1, cc2);
foreach (i; 0 .. rc1) {
foreach (j; 0 .. cc2) {
foreach (k; 0 .. rc2) {
result[i, j] += this[i, k] * rhs[k, j];
}
}
}
return result;
} else {
assert(false, "Not implemented");
}
}

public void opIndexAssign(double value, size_t r, size_t c) {
data[r][c] = value;
}

public void opIndexAssign(const double[] value, size_t r) {
enforce(colCount == value.length, "Slice size must match column size");
data[r] = value.dup;
}

public void opIndexOpAssign(string op)(double value, size_t r, size_t c) {
mixin("data[r][c] " ~ op ~ "= value;");
}

public auto transpose() const {
auto rc = rowCount;
auto cc = colCount;
auto t = new Matrix(cc, rc);
foreach (i; 0 .. cc) {
foreach (j; 0 .. rc) {
t[i, j] = this[j, i];
}
}
return t;
}

public void toReducedRowEchelonForm() {
auto lead = 0;
auto rc = rowCount;
auto cc = colCount;
foreach (r; 0 .. rc) {
if (cc <= lead) {
return;
}
auto i = r;

while (this[i, lead] == 0.0) {
i++;
if (rc == i) {
i = r;
lead++;
if (cc == lead) {
return;
}
}
}

auto temp = this[i];
this[i] = this[r];
this[r] = temp;

if (this[r, lead] != 0.0) {
auto div = this[r, lead];
foreach (j; 0 .. cc) {
this[r, j] = this[r, j] / div;
}
}

foreach (k; 0 .. rc) {
if (k != r) {
auto mult = this[k, lead];
foreach (j; 0 .. cc) {
this[k, j] -= this[r, j] * mult;
}
}
}

lead++;
}
}

public auto inverse() const {
enforce(rowCount == colCount, "Not a square matrix");
auto len = rowCount;
auto aug = new Matrix(len, 2 * len);
foreach (i; 0 .. len) {
foreach (j; 0 .. len) {
aug[i, j] = this[i, j];
}
// augment identity matrix to right
aug[i, i + len] = 1.0;
}
aug.toReducedRowEchelonForm;
auto inv = new Matrix(len);
// remove identify matrix to left
foreach (i; 0 .. len) {
foreach (j; len .. 2 * len) {
inv[i, j - len] = aug[i, j];
}
}
return inv;
}

void toString(scope void delegate(const(char)[]) sink) const {
import std.format;
auto fmt = FormatSpec!char("%s");

put(sink, "[");
foreach (i; 0 .. rowCount) {
if (i > 0) {
put(sink, " [");
} else {
put(sink, "[");
}

formatValue(sink, this[i, 0], fmt);
foreach (j; 1 .. colCount) {
put(sink, ", ");
formatValue(sink, this[i, j], fmt);
}

if (i + 1 < rowCount) {
put(sink, "]\n");
} else {
put(sink, "]");
}
}
put(sink, "]");
}
}

auto multipleRegression(double[] y, Matrix x) {
auto tm = new Matrix([y]);
auto cy = tm.transpose;
auto cx = x.transpose;
return ((x * cx).inverse * x * cy).transpose[0].dup;
}

void main() {
auto y = [1.0, 2.0, 3.0, 4.0, 5.0];
auto x = new Matrix([[2.0, 1.0, 3.0, 4.0, 5.0]]);
auto v = multipleRegression(y, x);
v.writeln;

y = [3.0, 4.0, 5.0];
x = new Matrix([
[1.0, 2.0, 1.0],
[1.0, 1.0, 2.0]
]);
v = multipleRegression(y, x);
v.writeln;

y = [52.21, 53.12, 54.48, 55.84, 57.20, 58.57, 59.93, 61.29, 63.11, 64.47, 66.28, 68.10, 69.92, 72.19, 74.46];
auto a = [1.47, 1.50, 1.52, 1.55, 1.57, 1.60, 1.63, 1.65, 1.68, 1.70, 1.73, 1.75, 1.78, 1.80, 1.83];
x = new Matrix([
repeat(1.0, a.length).array,
a,
a.map!"a * a".array
]);
v = multipleRegression(y, x);
v.writeln;
}</lang>
{{out}}
<pre>[0.981818]
[1, 2]
[128.813, -143.162, 61.9603]</pre>


=={{header|Emacs Lisp}}==
=={{header|Emacs Lisp}}==