How to resolve the algorithm QR decomposition step by step in the jq programming language
How to resolve the algorithm QR decomposition step by step in the jq programming language
Table of Contents
Problem Statement
Any rectangular
m × n
{\displaystyle m\times n}
matrix
A
{\displaystyle {\mathit {A}}}
can be decomposed to a product of an orthogonal matrix
Q
{\displaystyle {\mathit {Q}}}
and an upper (right) triangular matrix
R
{\displaystyle {\mathit {R}}}
, as described in QR decomposition. Task Demonstrate the QR decomposition on the example matrix from the Wikipedia article: and the usage for linear least squares problems on the example from Polynomial regression. The method of Householder reflections should be used: Method Multiplying a given vector
a
{\displaystyle {\mathit {a}}}
, for example the first column of matrix
A
{\displaystyle {\mathit {A}}}
, with the Householder matrix
H
{\displaystyle {\mathit {H}}}
, which is given as reflects
a
{\displaystyle {\mathit {a}}}
about a plane given by its normal vector
u
{\displaystyle {\mathit {u}}}
. When the normal vector of the plane
u
{\displaystyle {\mathit {u}}}
is given as then the transformation reflects
a
{\displaystyle {\mathit {a}}}
onto the first standard basis vector which means that all entries but the first become zero. To avoid numerical cancellation errors, we should take the opposite sign of
a
1
{\displaystyle a_{1}}
: and normalize with respect to the first element: The equation for
H
{\displaystyle H}
thus becomes: or, in another form with Applying
H
{\displaystyle {\mathit {H}}}
on
a
{\displaystyle {\mathit {a}}}
then gives and applying
H
{\displaystyle {\mathit {H}}}
on the matrix
A
{\displaystyle {\mathit {A}}}
zeroes all subdiagonal elements of the first column: In the second step, the second column of
A
{\displaystyle {\mathit {A}}}
, we want to zero all elements but the first two, which means that we have to calculate
H
{\displaystyle {\mathit {H}}}
with the first column of the submatrix (denoted *), not on the whole second column of
A
{\displaystyle {\mathit {A}}}
. To get
H
2
{\displaystyle H_{2}}
, we then embed the new
H
{\displaystyle {\mathit {H}}}
into an
m × n
{\displaystyle m\times n}
identity: This is how we can, column by column, remove all subdiagonal elements of
A
{\displaystyle {\mathit {A}}}
and thus transform it into
R
{\displaystyle {\mathit {R}}}
. The product of all the Householder matrices
H
{\displaystyle {\mathit {H}}}
, for every column, in reverse order, will then yield the orthogonal matrix
Q
{\displaystyle {\mathit {Q}}}
. The QR decomposition should then be used to solve linear least squares (Multiple regression) problems
A
x
b
{\displaystyle {\mathit {A}}x=b}
by solving When
R
{\displaystyle {\mathit {R}}}
is not square, i.e.
m
n
{\displaystyle m>n}
we have to cut off the
m
− n
{\displaystyle {\mathit {m}}-n}
zero padded bottom rows. and the same for the RHS: Finally, solve the square upper triangular system by back substitution:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm QR decomposition step by step in the jq programming language
Source code in the jq programming language
def sum(s): reduce s as $_ (0; . + $_);
# Sum of squares
def ss(s): sum(s|.*.);
# Create an m x n matrix
def matrix(m; n; init):
if m == 0 then []
elif m == 1 then [range(0;n) | init]
elif m > 0 then
matrix(1;n;init) as $row
| [range(0;m) | $row ]
else error("matrix\(m);_;_) invalid")
end;
def dot_product(a; b):
reduce range(0;a|length) as $i (0; . + (a[$i] * b[$i]) );
# A and B should both be numeric matrices, A being m by n, and B being n by p.
def multiply($A; $B):
($B[0]|length) as $p
| ($B|transpose) as $BT
| reduce range(0; $A|length) as $i
([];
reduce range(0; $p) as $j
(.;
.[$i][$j] = dot_product( $A[$i]; $BT[$j] ) ));
# $ndec decimal places
def round($ndec):
def rpad: tostring | ($ndec - length) as $l | . + ("0" * $l);
def abs: if . < 0 then -. else . end;
pow(10; $ndec) as $p
| round as $round
| if $p * ((. - $round)|abs) < 0.1
then ($round|tostring) + "." + ($ndec * "0")
else . * $p | round / $p
| tostring
| capture("(?<left>[^.]*)[.](?<right>.*)")
| .left + "." + (.right|rpad)
end;
# pretty-print a 2-d matrix
def pp($ndec; $width):
def pad(n): tostring | (n - length) * " " + .;
def row: map(round($ndec) | pad($width)) | join(" ");
reduce .[] as $row (""; . + "\n\($row|row)");
def minor($x; $d):
($x|length) as $nr
| ($x[0]|length) as $nc
| reduce range(0; $d) as $i (matrix($nr;$nc;0); .[$i][$i] = 1)
| reduce range($d; $nr) as $i (.;
reduce range($d;$nc) as $j (.; .[$i][$j] = $x[$i][$j] ) );
def vmadd($a; $b; $s):
reduce range (0; $a|length) as $i ([];
.[$i] = $a[$i] + $s * $b[$i] );
def vmul($v):
($v|length) as $n
| reduce range(0;$n) as $i (null;
reduce range(0;$n) as $j (.; .[$i][$j] = -2 * $v[$i] * $v[$j] ))
| reduce range(0;$n) as $i (.; .[$i][$i] += 1 );
def vnorm($x):
sum($x[] | .*.) | sqrt;
def vdiv($x; $d):
[range (0;$x|length) | $x[.] / $d];
def mcol($m; $c):
[range (0;$m|length) | $m[.][$c]];
def householder($m):
($m|length) as $nr
| ($m[0]|length) as $nc
| { q: [], # $nr
z: $m,
k: 0 }
| until( .k >= $nc or .k >= $nr-1;
.z = minor(.z; .k)
| .x = mcol(.z; .k)
| .a = vnorm(.x)
| if ($m[.k][.k] > 0) then .a = -.a else . end
| .e = [range (0; $nr) as $i | if ($i == .k) then 1 else 0 end]
| .e = vmadd(.x; .e; .a)
| .e = vdiv(.e; vnorm(.e))
| .q[.k] = vmul(.e)
| .z = multiply(.q[.k]; .z)
| .k += 1 )
| .Q = .q[0]
| .R = multiply(.q[0]; $m)
| .i = 1
| until (.i >= $nc or .i >= $nr-1;
.Q = multiply(.q[.i]; .Q)
| .i += 1 )
| .R = multiply(.Q; $m)
| .Q |= transpose
| [.Q, .R] ;
def x: [
[12, -51, 4],
[ 6, 167, -68],
[-4, 24, -41],
[-1, 1, 0],
[ 2, 0, 3]
];
def task:
def pp: pp(3;8);
# Assume $a and $b are conformal
def ssd($a; $b):
[$a[][]] as $a
| [$b[][]] as $b
| ss( range(0;$a|length) | $a[.] - $b[.] );
householder(x) as [$Q, $R]
| multiply($Q; $R) as $m
| "Q:", ($Q|pp),
"\nR:", ($R|pp),
"\nQ * R:", ($m|pp),
"\nSum of squared discrepancies: \(ssd(x; $m))"
;
task
You may also check:How to resolve the algorithm Sum of a series step by step in the Unicon programming language
You may also check:How to resolve the algorithm MD5 step by step in the Slate programming language
You may also check:How to resolve the algorithm Stack step by step in the Action! programming language
You may also check:How to resolve the algorithm Check that file exists step by step in the Elena programming language
You may also check:How to resolve the algorithm Execute a system command step by step in the FreeBASIC programming language