Reduced row echelon form: Difference between revisions
Content added Content deleted
(→{{header|Wren}}: Added a sentance) |
|||
Line 2,553: | Line 2,553: | ||
rref(a); |
rref(a); |
||
matrix([1,0,0,0,1/2],[0,1,0,0,-1],[0,0,1,0,-1/2],[0,0,0,1,1],[0,0,0,0,0])</lang> |
matrix([1,0,0,0,1/2],[0,1,0,0,-1],[0,0,1,0,-1/2],[0,0,0,1,1],[0,0,0,0,0])</lang> |
||
=={{header|Nim}}== |
|||
===Using rationals=== |
|||
To avoid rounding issues, we can use rationals and convert to floats only at the end. |
|||
<lang Nim>import rationals, strutils |
|||
type Fraction = Rational[int] |
|||
const Zero: Fraction = 0 // 1 |
|||
type Matrix[M, N: static Positive] = array[M, array[N, Fraction]] |
|||
func toMatrix[M, N: static Positive](a: array[M, array[N, int]]): Matrix[M, N] = |
|||
## Convert a matrix of integers to a matrix of integer fractions. |
|||
for i in 0..a.high: |
|||
for j in 0..a[0].high: |
|||
result[i][j] = a[i][j] // 1 |
|||
func transformToRref(mat: var Matrix) = |
|||
## Transform the given matrix to reduced row echelon form. |
|||
var lead = 0 |
|||
for r in 0..<mat.M: |
|||
if lead >= mat.N: return |
|||
var i = r |
|||
while mat[i][lead] == Zero: |
|||
inc i |
|||
if i == mat.M: |
|||
i = r |
|||
inc lead |
|||
if lead == mat.N: return |
|||
swap mat[i], mat[r] |
|||
if (let d = mat[r][lead]; d) != Zero: |
|||
for item in mat[r].mitems: |
|||
item /= d |
|||
for i in 0..<mat.M: |
|||
if i != r: |
|||
let m = mat[i][lead] |
|||
for c in 0..<mat.N: |
|||
mat[i][c] -= mat[r][c] * m |
|||
inc lead |
|||
proc `$`(mat: Matrix): string = |
|||
## Display a matrix. |
|||
for row in mat: |
|||
var line = "" |
|||
for val in row: |
|||
line.addSep(" ", 0) |
|||
line.add val.toFloat.formatFloat(ffDecimal, 2).align(7) |
|||
echo line |
|||
#——————————————————————————————————————————————————————————————————————————————————————————————————— |
|||
template runTest(mat: Matrix) = |
|||
## Run a test using matrix "mat". |
|||
echo "Original matrix:" |
|||
echo mat |
|||
echo "Reduced row echelon form:" |
|||
mat.transformToRref() |
|||
echo mat |
|||
echo "" |
|||
var m1 = [[ 1, 2, -1, -4], |
|||
[ 2, 3, -1, -11], |
|||
[-2, 0, -3, 22]].toMatrix() |
|||
var m2 = [[2, 0, -1, 0, 0], |
|||
[1, 0, 0, -1, 0], |
|||
[3, 0, 0, -2, -1], |
|||
[0, 1, 0, 0, -2], |
|||
[0, 1, -1, 0, 0]].toMatrix() |
|||
var m3 = [[1, 2, 3, 4, 3, 1], |
|||
[2, 4, 6, 2, 6, 2], |
|||
[3, 6, 18, 9, 9, -6], |
|||
[4, 8, 12, 10, 12, 4], |
|||
[5, 10, 24, 11, 15, -4]].toMatrix() |
|||
var m4 = [[0, 1], |
|||
[1, 2], |
|||
[0, 5]].toMatrix() |
|||
runTest(m1) |
|||
runTest(m2) |
|||
runTest(m3) |
|||
runTest(m4)</lang> |
|||
{{out}} |
|||
<pre>Original matrix: |
|||
1.00 2.00 -1.00 -4.00 |
|||
2.00 3.00 -1.00 -11.00 |
|||
-2.00 0.00 -3.00 22.00 |
|||
Reduced row echelon form: |
|||
1.00 0.00 0.00 -8.00 |
|||
0.00 1.00 0.00 1.00 |
|||
0.00 0.00 1.00 -2.00 |
|||
Original matrix: |
|||
2.00 0.00 -1.00 0.00 0.00 |
|||
1.00 0.00 0.00 -1.00 0.00 |
|||
3.00 0.00 0.00 -2.00 -1.00 |
|||
0.00 1.00 0.00 0.00 -2.00 |
|||
0.00 1.00 -1.00 0.00 0.00 |
|||
Reduced row echelon form: |
|||
1.00 0.00 0.00 0.00 -1.00 |
|||
0.00 1.00 0.00 0.00 -2.00 |
|||
0.00 0.00 1.00 0.00 -2.00 |
|||
0.00 0.00 0.00 1.00 -1.00 |
|||
0.00 0.00 0.00 0.00 0.00 |
|||
Original matrix: |
|||
1.00 2.00 3.00 4.00 3.00 1.00 |
|||
2.00 4.00 6.00 2.00 6.00 2.00 |
|||
3.00 6.00 18.00 9.00 9.00 -6.00 |
|||
4.00 8.00 12.00 10.00 12.00 4.00 |
|||
5.00 10.00 24.00 11.00 15.00 -4.00 |
|||
Reduced row echelon form: |
|||
1.00 2.00 0.00 0.00 3.00 4.00 |
|||
0.00 0.00 1.00 0.00 0.00 -1.00 |
|||
0.00 0.00 0.00 1.00 0.00 0.00 |
|||
0.00 0.00 0.00 0.00 0.00 0.00 |
|||
0.00 0.00 0.00 0.00 0.00 0.00 |
|||
Original matrix: |
|||
0.00 1.00 |
|||
1.00 2.00 |
|||
0.00 5.00 |
|||
Reduced row echelon form: |
|||
1.00 0.00 |
|||
0.00 1.00 |
|||
0.00 0.00</pre> |
|||
===Using floats=== |
|||
When using floats, we have to be careful when doing comparisons. The previous program adapted to use floats instead of rationals may give wrong results. This would be the case with the second matrix. To get the right result, we have to do a comparison to an epsilon rather than zero. Here is the program modified to work with floats: |
|||
<lang Nim>import strutils |
|||
const Eps = 1e-10 |
|||
type Matrix[M, N: static Positive] = array[M, array[N, float]] |
|||
func toMatrix[M, N: static Positive](a: array[M, array[N, int]]): Matrix[M, N] = |
|||
## Convert a matrix of integers to a matrix of floats. |
|||
for i in 0..a.high: |
|||
for j in 0..a[0].high: |
|||
result[i][j] = a[i][j].toFloat |
|||
func transformToRref(mat: var Matrix) = |
|||
## Transform the given matrix to reduced row echelon form. |
|||
var lead = 0 |
|||
for r in 0..<mat.M: |
|||
if lead >= mat.N: return |
|||
var i = r |
|||
while mat[i][lead] == 0: |
|||
inc i |
|||
if i == mat.M: |
|||
i = r |
|||
inc lead |
|||
if lead == mat.N: return |
|||
swap mat[i], mat[r] |
|||
let d = mat[r][lead] |
|||
if abs(d) > Eps: # Checking "d != 0" will give wrong results in some cases. |
|||
for item in mat[r].mitems: |
|||
item /= d |
|||
for i in 0..<mat.M: |
|||
if i != r: |
|||
let m = mat[i][lead] |
|||
for c in 0..<mat.N: |
|||
mat[i][c] -= mat[r][c] * m |
|||
inc lead |
|||
proc `$`(mat: Matrix): string = |
|||
## Display a matrix. |
|||
for row in mat: |
|||
var line = "" |
|||
for val in row: |
|||
line.addSep(" ", 0) |
|||
line.add val.formatFloat(ffDecimal, 2).align(7) |
|||
echo line |
|||
#——————————————————————————————————————————————————————————————————————————————————————————————————— |
|||
template runTest(mat: Matrix) = |
|||
## Run a test using matrix "mat". |
|||
echo "Original matrix:" |
|||
echo mat |
|||
echo "Reduced row echelon form:" |
|||
mat.transformToRref() |
|||
echo mat |
|||
echo "" |
|||
var m1 = [[ 1, 2, -1, -4], |
|||
[ 2, 3, -1, -11], |
|||
[-2, 0, -3, 22]].toMatrix() |
|||
var m2 = [[2, 0, -1, 0, 0], |
|||
[1, 0, 0, -1, 0], |
|||
[3, 0, 0, -2, -1], |
|||
[0, 1, 0, 0, -2], |
|||
[0, 1, -1, 0, 0]].toMatrix() |
|||
var m3 = [[1, 2, 3, 4, 3, 1], |
|||
[2, 4, 6, 2, 6, 2], |
|||
[3, 6, 18, 9, 9, -6], |
|||
[4, 8, 12, 10, 12, 4], |
|||
[5, 10, 24, 11, 15, -4]].toMatrix() |
|||
var m4 = [[0, 1], |
|||
[1, 2], |
|||
[0, 5]].toMatrix() |
|||
runTest(m1) |
|||
runTest(m2) |
|||
runTest(m3) |
|||
runTest(m4)</lang> |
|||
{{Out}} |
|||
Same result as that of the program working with rationals (at least for the matrices used here). |
|||
=={{header|Objeck}}== |
=={{header|Objeck}}== |