lu_decomposition.sf 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/LU_decomposition
  4. #
  5. func is_square(m) { m.all { .len == m.len } }
  6. func matrix_zero(n, m=n) { m.of { n.of(0) } }
  7. func matrix_ident(n) { n.of {|i| [i.of(0)..., 1, (n - i - 1).of(0)...] } }
  8. func pivotize(m) {
  9. var size = m.len
  10. var id = matrix_ident(size)
  11. for i in (^size) {
  12. var max = m[i][i]
  13. var row = i
  14. for j in (i ..^ size) {
  15. if (m[j][i] > max) {
  16. max = m[j][i]
  17. row = j
  18. }
  19. }
  20. if (row != i) {
  21. id.swap(row, i)
  22. }
  23. }
  24. return id
  25. }
  26. func mmult(a, b) {
  27. var p = []
  28. for r in ^a, c in ^b[0], i in ^b {
  29. p[r][c] := 0 += (a[r][i] * b[i][c])
  30. }
  31. return p
  32. }
  33. func lu(a) {
  34. is_square(a) || die "Defined only for square matrices!";
  35. var n = a.len
  36. var P = pivotize(a)
  37. var Aʼ = mmult(P, a)
  38. var L = matrix_ident(n)
  39. var U = matrix_zero(n)
  40. for i in ^n, j in ^n {
  41. if (j >= i) {
  42. U[i][j] = (Aʼ[i][j] - sum(^i, { U[_][j] * L[i][_] }))
  43. } else {
  44. L[i][j] = ((Aʼ[i][j] - sum(^j, { U[_][j] * L[i][_] })) / U[j][j])
  45. }
  46. }
  47. return [P, Aʼ, L, U]
  48. }
  49. func say_it(message, array) {
  50. say "\n#{message}"
  51. array.each { |row|
  52. say row.map{"%7s" % .as_rat}.join(' ')
  53. }
  54. }
  55. var t = [[
  56. %n(1 3 5),
  57. %n(2 4 7),
  58. %n(1 1 0),
  59. ],[
  60. %n(11 9 24 2),
  61. %n( 1 5 2 6),
  62. %n( 3 17 18 1),
  63. %n( 2 5 7 1),
  64. ]]
  65. t.each { |test|
  66. say_it('A Matrix', test)
  67. for a,b in (['P Matrix', 'Aʼ Matrix', 'L Matrix', 'U Matrix'] ~Z lu(test)) {
  68. say_it(a, b)
  69. }
  70. }