diff options
| author | Marius Peter <dev@marius-peter.com> | 2025-12-13 22:38:24 +0100 |
|---|---|---|
| committer | Marius Peter <dev@marius-peter.com> | 2025-12-13 22:38:24 +0100 |
| commit | 7c9ea5c931f684c4d560ef3671691d89269a7141 (patch) | |
| tree | a3b3e4473727cbf0b9cedb1bd71ff0f7370ebbc8 | |
| parent | ae1a5e0eceefcb8af1600bca39a2209cabad7198 (diff) | |
Fix NNLS tests.
| -rw-r--r-- | services/nnls.rkt | 190 |
1 files changed, 95 insertions, 95 deletions
diff --git a/services/nnls.rkt b/services/nnls.rkt index b0902f9..4821b7d 100644 --- a/services/nnls.rkt +++ b/services/nnls.rkt @@ -189,131 +189,131 @@ "../db/conn.rkt" "../db/migrations.rkt") - (run-tests (test-suite "NNLS" - #:before (λ () - (connect! #:path 'memory) - (migrate-all!) - (create-nutrient! "Nitrogen" "Azote" "N") - (create-nutrient! "Phosphorus" "Phosphore" "P") - (create-nutrient! "Potassium" "Potassium" "K")) - #:after (λ () (disconnect!)) + (run-tests + (test-suite "NNLS" + #:before (λ () + (connect! #:path 'memory) + (migrate-all!) + (create-nutrient! "Nitrogen" "Azote" "N") + (create-nutrient! "Phosphorus" "Phosphore" "P") + (create-nutrient! "Potassium" "Potassium" "K")) + #:after (λ () (disconnect!)) - (test-case "Build fertilizer product matrix" - (define n (get-nutrient #:name "Nitrogen")) - (define p (get-nutrient #:name "Phosphorus")) + (test-case "Build fertilizer product matrix" + (define n (get-nutrient #:name "Nitrogen")) + (define p (get-nutrient #:name "Phosphorus")) - (define nutrients (list n p)) + (define nutrients (list n p)) - (define f1 (create-fertilizer-product! "F1" "F1" (hash n 10 p 20))) - (define f2 (create-fertilizer-product! "F2" "F2" (hash n 30 p 5))) - (define fertilizers (list f1 f2)) + (define f1 (create-fertilizer-product! "F1" "F1" (hash n 10 p 20))) + (define f2 (create-fertilizer-product! "F2" "F2" (hash n 30 p 5))) + (define fertilizers (list f1 f2)) - (define matrix (get-fertilizer-product-matrix nutrients fertilizers)) + (define matrix (get-fertilizer-product-matrix nutrients fertilizers)) - (check-= (matrix-ref matrix 0 0) 10 0 "N1 in F1") - (check-= (matrix-ref matrix 0 1) 30 0 "N1 in F2") - (check-= (matrix-ref matrix 1 0) 20 0 "N2 in F1") - (check-= (matrix-ref matrix 1 1) 5 0 "N2 in F2")) + (check-= (matrix-ref matrix 0 0) 10 0 "N1 in F1") + (check-= (matrix-ref matrix 0 1) 30 0 "N1 in F2") + (check-= (matrix-ref matrix 1 0) 20 0 "N2 in F1") + (check-= (matrix-ref matrix 1 1) 5 0 "N2 in F2")) - (test-case "Single nutrient, single fertilizer" - (define A (matrix [[2]])) - (define y (col-matrix [10])) - (define ε 1e-6) + (test-case "Single nutrient, single fertilizer" + (define A (matrix [[2]])) + (define y (col-matrix [10])) + (define ε 1e-6) - (define result (lawson-hanson-1974 A y ε)) + (define result (lawson-hanson-1974 A y ε)) - (check-= (matrix-ref result 0 0) 5.0 ε "Should give x = 5 since 2*5 = 10")) + (check-= (matrix-ref result 0 0) 5.0 ε "Should give x = 5 since 2*5 = 10")) - (test-case "Two variables, known solution" - (define A (matrix [[1 0] [0 1]])) - (define y (col-matrix [3 4])) - (define ε 1e-6) + (test-case "Two variables, known solution" + (define A (matrix [[1 0] [0 1]])) + (define y (col-matrix [3 4])) + (define ε 1e-6) - (define result (lawson-hanson-1974 A y ε)) + (define result (lawson-hanson-1974 A y ε)) - (check-= (matrix-ref result 0 0) 3.0 ε "x1 should be 3") - (check-= (matrix-ref result 1 0) 4.0 ε "x2 should be 4")) + (check-= (matrix-ref result 0 0) 3.0 ε "x1 should be 3") + (check-= (matrix-ref result 1 0) 4.0 ε "x2 should be 4")) - (test-case "Overdetermined system" - (define A (matrix [[1 1] [2 1] [1 2]])) - (define y (col-matrix [3 5 5])) - (define ε 1e-4) + (test-case "Overdetermined system" + (define A (matrix [[1 1] [2 1] [1 2]])) + (define y (col-matrix [3 5 5])) + (define ε 1e-4) - (define result (lawson-hanson-1974 A y ε)) + (define result (lawson-hanson-1974 A y ε)) - ;; Solution should be approximately [1.636, 1.636] (least squares fit) - (check-= (matrix-ref result 0 0) 1.636 0.01 "x1 approximately 1.636") - (check-= (matrix-ref result 1 0) 1.636 0.01 "x2 approximately 1.636")) + ;; Solution should be approximately [1.636, 1.636] (least squares fit) + (check-= (matrix-ref result 0 0) 1.636 0.01 "x1 approximately 1.636") + (check-= (matrix-ref result 1 0) 1.636 0.01 "x2 approximately 1.636")) - (test-case "Non-negativity enforcement" - (define A (matrix [[1 -1] [1 1]])) - (define y (col-matrix [1 3])) - (define ε 1e-6) + (test-case "Non-negativity enforcement" + (define A (matrix [[1 -1] [1 1]])) + (define y (col-matrix [1 3])) + (define ε 1e-6) - (define result (lawson-hanson-1974 A y ε)) + (define result (lawson-hanson-1974 A y ε)) - ;; All results should be non-negative - (check-true (>= (matrix-ref result 0 0) 0) "x1 should be non-negative") - (check-true (>= (matrix-ref result 1 0) 0) "x2 should be non-negative")) + ;; All results should be non-negative + (check-true (>= (matrix-ref result 0 0) 0) "x1 should be non-negative") + (check-true (>= (matrix-ref result 1 0) 0) "x2 should be non-negative")) - (test-case "Zero target" - (define A (matrix [[1 2] [3 4]])) - (define y (col-matrix [0 0])) - (define ε 1e-6) + (test-case "Zero target" + (define A (matrix [[1 2] [3 4]])) + (define y (col-matrix [0 0])) + (define ε 1e-6) - (define result (lawson-hanson-1974 A y ε)) + (define result (lawson-hanson-1974 A y ε)) - (check-= (matrix-ref result 0 0) 0.0 ε "x1 should be 0") - (check-= (matrix-ref result 1 0) 0.0 ε "x2 should be 0")) + (check-= (matrix-ref result 0 0) 0.0 ε "x1 should be 0") + (check-= (matrix-ref result 1 0) 0.0 ε "x2 should be 0")) - (test-case "Ferti recipe" - (define test-date "2025-01-01") - (define n (get-nutrient #:name "Nitrogen")) - (define p (get-nutrient #:name "Phosphorus")) - (define k (get-nutrient #:name "Potassium")) + (test-case "Ferti recipe" + (define test-date "2025-01-01") + (define n (get-nutrient #:name "Nitrogen")) + (define p (get-nutrient #:name "Phosphorus")) + (define k (get-nutrient #:name "Potassium")) - (create-nutrient-measurement! test-date (hash n 0 p 0)) - (define test-crop-requirement - (create-crop-requirement! "Test requirement" (hash n 100 p 50))) - (create-crop-rotation! test-date (hash test-crop-requirement 100)) + (create-nutrient-measurement! (nutrient-measurement #f test-date (hash n 0 p 0))) + (define test-crop-requirement (create-crop-requirement! "Test requirement" (hash n 100 p 50))) + (create-crop-rotation! test-date (hash test-crop-requirement 100)) - (create-fertilizer-product! "Nitrogen" "King Nitrogen" (hash n 100)) - (create-fertilizer-product! "Phosphorus" "Phosphorescent Baboon" (hash n 10 p 100)) - (create-fertilizer-product! "Diluted phosphorus" "John's Phosphorus" (hash n 3 p 30)) + (create-fertilizer-product! "Nitrogen" "King Nitrogen" (hash n 100)) + (create-fertilizer-product! "Phosphorus" "Phosphorescent Baboon" (hash n 10 p 100)) + (create-fertilizer-product! "Diluted phosphorus" "John's Phosphorus" (hash n 3 p 30)) - (define recipe (find-ferti-recipe test-date)) + (define recipe (find-ferti-recipe test-date)) - (check-equal? (hash-count recipe) 5 "Should have 5 fertilizer products") + (check-equal? (hash-count recipe) 5 "Should have 5 fertilizer products") - (for ([(fertilizer quantity) (in-hash recipe)]) - (check-true (>= quantity 0) "Fertilizer quantity should be non-negative"))) + (for ([(fertilizer quantity) (in-hash recipe)]) + (check-true (>= quantity 0) "Fertilizer quantity should be non-negative"))) - (test-case "Recipe calculation with real-world scenario" - (define test-date "2025-01-02") - (define n (get-nutrient #:name "Nitrogen")) - (define p (get-nutrient #:name "Phosphorus")) - (define k (get-nutrient #:name "Potassium")) + (test-case "Recipe calculation with real-world scenario" + (define test-date "2025-01-02") + (define n (get-nutrient #:name "Nitrogen")) + (define p (get-nutrient #:name "Phosphorus")) + (define k (get-nutrient #:name "Potassium")) - ;; Current levels - (create-nutrient-measurement! test-date (hash n 50 p 10 k 100)) + ;; Current levels + (create-nutrient-measurement! (nutrient-measurement #f test-date (hash n 50 p 10 k 100))) - ;; Target levels - (define test-crop-requirement - (create-crop-requirement! "Test requirement 2" (hash n 150 p 30 k 200))) - (create-crop-rotation! test-date (hash test-crop-requirement 100)) + ;; Target levels + (define test-crop-requirement + (create-crop-requirement! "Test requirement 2" (hash n 150 p 30 k 200))) + (create-crop-rotation! test-date (hash test-crop-requirement 100)) - ;; Available fertilizer products - (create-fertilizer-product! "" "Balanced" (hash n 100 p 100 k 100)) - (create-fertilizer-product! "Nitrogen blend" "High-N" (hash n 200 p 50 k 50)) - (create-fertilizer-product! "Phosphorus blend" "High-P" (hash n 50 p 200 k 50)) - (create-fertilizer-product! "Potassium blend" "High-K" (hash n 50 p 50 k 200)) + ;; Available fertilizer products + (create-fertilizer-product! "" "Balanced" (hash n 100 p 100 k 100)) + (create-fertilizer-product! "Nitrogen blend" "High-N" (hash n 200 p 50 k 50)) + (create-fertilizer-product! "Phosphorus blend" "High-P" (hash n 50 p 200 k 50)) + (create-fertilizer-product! "Potassium blend" "High-K" (hash n 50 p 50 k 200)) - (define recipe (find-ferti-recipe test-date)) + (define recipe (find-ferti-recipe test-date)) - (check-equal? (hash-count recipe) 9 "Recipe should have 9 fertilizers") + (check-equal? (hash-count recipe) 9 "Recipe should have 9 fertilizers") - ;; Verify solution is non-negative - (for ([(fertilizer quantity) (in-hash recipe)]) - (check-true (>= quantity 0) - (format "~a quantity must be non-negative" - (fertilizer-product-name fertilizer)))))))) + ;; Verify solution is non-negative + (for ([(fertilizer quantity) (in-hash recipe)]) + (check-true (>= quantity 0) + (format "~a quantity must be non-negative" + (fertilizer-product-name fertilizer)))))))) |