Created
November 23, 2015 02:51
-
-
Save rahulaga/ac291478d1d78c5f7d15 to your computer and use it in GitHub Desktop.
Scheme Gaussian Elimination
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;#################### | |
;Gaussian Elimination | |
;Rahul Agarwal | |
;################### | |
;################################################################# | |
;Test if value is a valid linear equation, helper is part | |
;of linear-equation? so not testing seperately | |
;################################################################# | |
(define (le-helper value) | |
(cond ((empty? value) #t) | |
((not (number? (car value))) #f);test if not a number, | |
also takes care of nested lists | |
(else (le-helper (cdr value))) | |
) | |
) | |
(define (linear-equation? value) | |
(cond ((not (list? value)) #f) | |
((empty? value) #f) | |
((< (length value) 2) #f);must have atleast 2 or more numbers | |
(else (le-helper value)) | |
) | |
) | |
#fShould be(linear-equation? '())Test... | |
#fShould be(linear-equation? 3)Test... | |
#fShould be(linear-equation? '(2))Test... | |
#tShould be(linear-equation? '(3 2.5 8 3.2))Test... | |
#tShould be(linear-equation? '(1 -1 +1 0))Test... | |
#fShould be(linear-equation? '(4 (3 2) 3))Test... | |
#fShould be(linear-equation? '(2 x 3 3))Test... | |
#fShould be(linear-equation? '(a b (s)))Test... | |
#fShould be(linear-equation? '(()))Test... | |
#tShould be(linear-equation? '(5 10))Test... | |
#tShould be(linear-equation? '(2/3 1/2 4/2))Test... | |
;################################################################# | |
;Test if value is a valid augmented matrix | |
;The length function gives the length, each row should be a linear | |
;equation and number atoms in each one more than number rows | |
;################################################################# | |
(define (am-helper value len);len is num rows | |
(cond | |
((empty? value) #t);reached end without false | |
((not (and (linear-equation? (car value)) (equal? (+ 1 len) | |
(length (car value))))) #f); linear eq && NxN+1 | |
(else (am-helper (cdr value) len)) | |
) | |
) | |
(define (augmented-matrix? value) | |
(cond | |
((not (list? value)) #f) | |
((empty? value) #f) | |
(else (am-helper value (length value))) | |
) | |
) | |
#tShould be(augmented-matrix? '((1 1 1 0)(1 -2 2 4)(1 +2 -1 2)))Test... | |
#fShould be(augmented-matrix? '((1 1 0)(1 -2 2 4)(1 +2 -1 2)))Test... | |
#fShould be(augmented-matrix? '((1 3 6 1 0)(1 -2 2 4)(1 +2 -1 2)))Test... | |
#fShould be(augmented-matrix? '((1 1 1 0)(1 -2 x 4)(1 +2 -1 2)))Test... | |
#fShould be(augmented-matrix? '((1 1 3 0)(1 +2 -1 2)))Test... | |
#fShould be(augmented-matrix? '((1 1 3 0)(12 1 33 0)(1 8 2 0)(1 +2 -1 2)))Test... | |
#fShould be(augmented-matrix? '())Test... | |
#fShould be(augmented-matrix? '((1 1 1 0)(1 -2 2 4)()))Test... | |
#fShould be(augmented-matrix? '((1 (1 1) 0)(1 (-2) 2 4)(1 +2 -1 (2))))Test... | |
#fShould be(augmented-matrix? 3)Test... | |
#fShould be(augmented-matrix? '((2 3 ())(3 2 1)))Test... | |
#tShould be(augmented-matrix? '((5 10)))Test... | |
#fShould be(augmented-matrix? '(5 10))Test... | |
#fShould be(augmented-matrix? '((3 2 1 3) 2 9 2 1 (2 4 2 2)))Test... | |
;################################################################# | |
;Find the upper triangualr matrix for the input. It is assumed | |
;that the value passed | |
;to this method is a valid augmented matrix so that is not tested and the | |
;test cases also | |
;do not target that. | |
;################################################################# | |
;Returns the xth value out of a list, returns empty if x is out of bounds | |
(define (get-x val x) | |
(cond ((empty? val) empty) | |
((> x (length val)) empty) | |
((< x 0) empty) | |
((= x 0) (car val)) | |
(else (get-x (cdr val) (- x 1))) | |
) | |
) | |
4Should be(get-x '(1 2 4) 2)Test... | |
emptyShould be(get-x '(1 2 4) -1)Test... | |
emptyShould be(get-x '(1 2 4) 3)Test... | |
;returns the colth value of the rowth row | |
(define (get-rc mat row col) | |
(get-x (get-x mat row) col) | |
) | |
2Should be(get-rc '((0 1 2 3)(4 5 6 7)) 0 2)Test... | |
emptyShould be(get-rc '((0 1 2 3)(4 5 6 7)) 2 2)Test... | |
emptyShould be(get-rc '((0 1 2 3)(4 5 6 7)) 0 -2)Test... | |
;returns the matrix till that row | |
(define (get-mat-till-row mat row) | |
(cond ((< row 0) empty) | |
((> row (length mat)) empty) | |
(else (cons (car mat) | |
(get-mat-till-row (cdr mat) (- row 1))) | |
) | |
) | |
) | |
'((2 3 2 3)(2 3 2 1))Should be(get-mat-till-row '((2 3 2 3)(2 3 2 1)(2 3 2 1)) 1)Test... | |
'((2 3 2 3))Should be(get-mat-till-row '((2 3 2 3)(2 3 2 1)(2 3 2 1)) 0)Test... | |
emptyShould be(get-mat-till-row '((2 3 2 3)(2 3 2 1)(2 3 2 1)) -5)Test... | |
emptyShould be(get-mat-till-row '((2 3 2 3)(2 3 2 1)(2 3 2 1)) 5)Test... | |
;scalar multi and substraction (sms) | |
;applies map using lambda function that cross multiples rows using the pivot col | |
;so that the value at col can then be zero in toList | |
(define (do-math-sms subList toList col) | |
(map (lambda | |
(x y) | |
(- (* x (get-x subList col)) | |
(* y (get-x toList col))) | |
) | |
toList | |
subList) | |
) | |
;NOTE: not tested for boundry cases cos this function can never be called with | |
;out of bounds values of col | |
'(0 7 -2)Should be(do-math-sms '(3 5 2) '(4 9 2) 0)Test... | |
'(-7 0 -8)Should be(do-math-sms '(3 5 2) '(4 9 2) 1)Test... | |
;makes all the values of the col to zero | |
;uses the do-math-sms on col in mat | |
(define (make-zero mat col) | |
(letrec( | |
(mz-helper (lambda (row newmat) | |
(cond ((>= row (length mat)) newmat);prevents make-zero if will | |
/violate upper triangular | |
(else | |
(mz-helper (+ 1 row) | |
(append newmat | |
(list (do-math-sms (get-x mat col) | |
(get-x mat row) | |
col))))) | |
) | |
) | |
);end lambda | |
) | |
(mz-helper (+ 1 col) (get-mat-till-row mat col));letrec body | |
) | |
) | |
;NOTE: not tested for boundry cases cos this function can never be called with | |
;out of bounds values of col | |
'((1 3 2)(0 -20 -14))Should be(make-zero '((1 3 2)(8 4 2)) 0)Test... | |
'((1 3 2 3)(8 2 4 2)(-6 0 -6 -4))Should be(make-zero '((1 3 2 3)(8 2 4 2)(5 2 1 0)) 1)Test... | |
;counts numbers of zeros before encountering a non-zero value | |
(define (count-zeros-at-front mat) | |
(cond ((empty? mat) 0) | |
((not (zero? (car mat))) 0) | |
(else (+ 1 (count-zeros-at-front (cdr mat)))) | |
) | |
) | |
0Should be(count-zeros-at-front '())Test... | |
0Should be(count-zeros-at-front '(1 0 0 0))Test... | |
4Should be(count-zeros-at-front '(0 0 0 0))Test... | |
2Should be(count-zeros-at-front '(0 0 3 0))Test... | |
;check top down - the 'row' passed should have 'row' number of zeros | |
(define (valid-ut-helper mat row totrows) | |
(cond ((empty? mat) #t) | |
((not (= row (count-zeros-at-front (car mat)))) #f) | |
((< row totrows) (valid-ut-helper (cdr mat) (+ 1 row) totrows)) | |
(else #t) | |
) | |
) | |
;checks whether a valid upper-triangular | |
;last row should hv atleast two non-zero at end, second last three and so on... | |
(define (valid-ut? mat) | |
(cond ((empty? mat) #f) | |
(else (valid-ut-helper mat 0 (length mat)));helper to enable | |
;looping via recursion | |
) | |
) | |
#fShould be(valid-ut? '())Test... | |
#tShould be(valid-ut? '((2.5 6.25)))Test... | |
#tShould be(valid-ut? '((1 1 1 0) (0 -3 1 4) (0 0 5 -10)))Test... | |
#fShould be(valid-ut? '((1 -1 4) (0 0 -12)))Test... | |
#fShould be(valid-ut? '((1 1 1 150) (0 1 2 -50) (0 0 0 -50)))Test... | |
#fShould be(valid-ut? '((0 0 0 0)(0 0 0 0)(0 0 0 0)))Test... | |
;process by sending each col to zero and creating new matrix | |
;each col is the pivot value in turn | |
(define (ut-helper mat col end) | |
(cond ((empty? (get-rc mat col col)) mat);base | |
((= col end) mat);base | |
(else | |
(ut-helper (make-zero mat col) (+ col 1) end)) | |
) | |
) | |
;creates the upper triangle for the given matrix | |
;actually helper does but writing cos this prototype required | |
(define (upper-triangular value) | |
(let ((ut-calculated (ut-helper value 0 (- (length value) 1))));var holding ut found | |
(cond ((valid-ut? ut-calculated) ut-calculated) | |
(else 'error) | |
) | |
);end let | |
) | |
'((5 10))Should be(upper-triangular '((5 10)))Test... | |
'((1 1 1 0) (0 -3 1 4) (0 0 5 -10))Should be(upper-triangular '((1 1 1 0) | |
(1 -2 2 4) (1 2 -1 2)))Test... | |
'((4 8 4 80) (0 -12 -24 -132) (0 0 -624 -1872))Should be(upper-triangular '((4 8 4 80) | |
(2 1 -4 7) (3 -1 2 22)))Test... | |
'((2.5 6.25))Should be(upper-triangular '((2.5 6.25)))Test... | |
'((3/2 5/2 1)(0 34/4 13/4))Should be(upper-triangular '((3/2 5/2 1)(-5/2 3/2 1/2)))Test... | |
'errorShould be(upper-triangular '((1 -1 4) (2 -2 -4)))Test... | |
'errorShould be(upper-triangular '((1 1 1 150) (1 2 3 100) (2 3 4 200)))Test... | |
'errorShould be(upper-triangular '((0 0 0 0)(0 0 0 0)(0 0 0 0)))Test... | |
;################################################################# | |
;Backsolver when given a upper-triangular. Again test cases assume | |
;that since this function is called only after | |
;upper-triangular is complete the value is a correct augmented matrix | |
;################################################################# | |
;my-sum takes the two lists and finds the special sum | |
;subsitutes values from one list and solves one unknown | |
(define (my-sum shortList longList ret) | |
(cond ((empty? shortList) ret) | |
(else (my-sum (rest shortList) | |
(rest longList) | |
(+ ret (* (first shortList) | |
(first longList))))) | |
) | |
) | |
;helper for backsolver | |
(define (bs-helper revmat ret col lastcol) | |
(cond ((empty? revmat) ret) | |
((zero? (get-x (first revmat) col)) 'error);prevent division by | |
;zero - catches inconsistent matrix | |
(else (bs-helper (rest revmat) | |
(cons (/ (- (get-x (first revmat) lastcol) | |
(my-sum (reverse ret) | |
(rest | |
(reverse (first revmat))) | |
0)) | |
(get-x (first revmat) col)) | |
ret) | |
(- col 1) | |
lastcol)) | |
) | |
) | |
;backsolves to get the values | |
;the reverse is used cos initial values are all zeros and easier | |
;this way to work at end of list instead of having to write functions to read last | |
(define (backsolve-upper-triangular value) | |
(cond ((not (valid-ut? value)) 'error);check if zeros in correct places else error | |
(else (bs-helper (reverse value) | |
empty | |
(- (length value) 1) | |
(length value))) | |
) | |
) | |
'(2)Should be(backsolve-upper-triangular '((5 10)))Test... | |
'(4 -2 -2)Should be(backsolve-upper-triangular '((1 1 1 0) (0 -3 1 4) (0 0 -5 10)))Test... | |
'(7 5 3)Should be(backsolve-upper-triangular '((4 8 4 80) (0 -6 -12 -66) (0 0 156 468)))Test... | |
'(2.5)Should be(backsolve-upper-triangular '((2.5 6.25)))Test... | |
'errorShould be(backsolve-upper-triangular '((1 -1 4) (0 0 -12)))Test... | |
'errorShould be(backsolve-upper-triangular '((1 1 1 150) (0 1 2 -50) (0 0 0 -50)))Test... | |
'errorShould be(backsolve-upper-triangular '((0 0 0 0)(0 0 0 0)(0 0 0 0)))Test... | |
'errorShould be(backsolve-upper-triangular '((0 1 2 5)(0 3 1 3)(0 0 6 4)))Test... | |
;############################################################# | |
;Combines all functions above, nothing special | |
;Test cases are same as upper-triangular and backsolve-upper-triangular | |
;hence very few test cases | |
;############################################################# | |
(define (solve value) | |
(if (augmented-matrix? value) | |
(let ((ut-calculated (upper-triangular value))) | |
(if (list? ut-calculated) (backsolve-upper-triangular ut-calculated) 'error) | |
) | |
'error | |
) | |
) | |
'(4 -2 -2)Should be(solve '((1 1 1 0) (0 -3 1 4) (0 0 -5 10)))Test... | |
'errorShould be(solve '((1 -1 4) (0 0 -12)))Test... | |
'errorShould be(solve '((1 -1 3 4) (0 0 -12)))Test... | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment