From 3b998c060b31103df7e4e580c341b7bfb73c525f Mon Sep 17 00:00:00 2001 From: mehbark Date: Sun, 15 Jan 2023 20:21:25 -0500 Subject: [PATCH] automation basically done --- src/matrix/auto.clj | 38 +++++++++++++++++++++++++++++++++++--- src/matrix/base.clj | 10 +++++++++- src/matrix/core.clj | 24 ++++++++++++++---------- test/matrix/core_test.clj | 14 +++++++++++++- 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/matrix/auto.clj b/src/matrix/auto.clj index 208b2c8..8aa96ac 100644 --- a/src/matrix/auto.clj +++ b/src/matrix/auto.clj @@ -35,18 +35,50 @@ (for [y (range (inc col) (matrix-height m))] {:add-row col :times (- (at m col y)) :to-row y})))) +; TODO: make-gaussian-eliminable, which swaps rows so that they can actually be gaussian-elim'd + (defn gaussian-elim - "Takes a matrix and returns the steps to put in the form + "Takes a matrix and returns the steps to put it in the form [[1 a ... | sum1] [0 1 ... | sum2] ...] Assumes a lot of things lol" - ([m] - (gaussian-elim m 0)) + ([m] (gaussian-elim m 0)) ([m col] (if (= col (matrix-height m)) [] (let [steps (gaussian-column m col) new (apply-all-at-once m steps)] (concat steps (gaussian-elim new (inc col))))))) + +(defn back-sub-column + [m col] + (for [y (range 0 col)] + {:add-row col + :times (- (at m col y)) + :to-row y})) + +; idea: clear backwards +(defn back-sub + "Takes a gaussian-eliminated matrix and returns the steps to make the id matrix on the left side" + ([m] (back-sub m (dec (matrix-height m)))) + ([m col] + (if (zero? col) + [] + (let [steps (back-sub-column m col) + new (apply-all-at-once m steps)] + (println new) + (concat steps (back-sub new (dec col))))))) + +(defn auto-steps-and-final + [m] + (let [g-elim-steps (gaussian-elim m) + after-g-elim (apply-all-at-once m g-elim-steps) + bsub-steps (back-sub after-g-elim) + after-bsub (apply-all-at-once after-g-elim bsub-steps)] + [(concat g-elim-steps bsub-steps) + after-bsub])) + +(def auto-steps (comp first auto-steps-and-final)) +(def auto-final (comp last auto-steps-and-final)) diff --git a/src/matrix/base.clj b/src/matrix/base.clj index ff3c7dc..b8aad46 100644 --- a/src/matrix/base.clj +++ b/src/matrix/base.clj @@ -3,7 +3,7 @@ (defn to-vec [v] - (apply vector v)) + (into [] v)) (defn swap-rows "Swap rows n and m of the given matrix, 0-indexed" @@ -105,3 +105,11 @@ "Returns the number at x y in a matrix" [m x y] (get (get m y) x)) + +(defn map-matrix + ([f] #(map-matrix f %)) + ([f m] + (->> m + (map #(map f %)) + (map to-vec) + to-vec))) diff --git a/src/matrix/core.clj b/src/matrix/core.clj index c7daa86..8bcb5ef 100644 --- a/src/matrix/core.clj +++ b/src/matrix/core.clj @@ -1,24 +1,28 @@ (ns matrix.core - (:require [matrix.base :refer :all]) + (:require [clojure.string :as str] + [matrix.base :refer :all]) (:require [matrix.interactive :refer :all]) (:require [matrix.auto :refer :all]) + (:require [matrix.render :refer :all]) (:gen-class)) (defn -main "I don't do a whole lot ... yet." [& args] - (let [got (read)] - (-> (if (number? got) - (id-matrix got) - got) - matrix-repl - last))) + (let [[steps final] (auto-steps-and-final (read))] + (println "Steps:") + ;; (for [step steps] + ;; (println (pretty-row-op step))) + (println (str/join "\n" (map pretty-row-op steps))) + (println "Final:") + (pprint-matrix final))) ; TODO: actual parsing of row operations ; TODO: parse equations (easy, but requires context (e.g. x = 1 could be any number of variables)) ; TODO: undoing ; will have to have a higher level thing for storing state ; use a set for options on the higher-level thing #{:show-equations? :show-bar? :color?} -; TODO: solving id-matrix -; TODO: solving gaussian-eliminated matrix -; TODO: automation +; DONE: solving id-matrix +; DONE: solving gaussian-eliminated matrix +; DONE: automation +; TODO: remove redundant row ops diff --git a/test/matrix/core_test.clj b/test/matrix/core_test.clj index bab7d97..7a468da 100644 --- a/test/matrix/core_test.clj +++ b/test/matrix/core_test.clj @@ -1,6 +1,7 @@ (ns matrix.core-test (:require [clojure.test :refer :all] - [matrix.base :refer :all])) + [matrix.base :refer :all] + [matrix.auto :refer :all])) ; TODO: more tests @@ -15,3 +16,14 @@ (testing "Multiplying by two 1x1 ident matrix" (let [mat (id-matrix 1)] (is (= [[2]] (mul-row mat 2 0)))))) + +(deftest test-auto + (testing "1 variable equation" + (is (= [[1 10]] (auto-final [[2 20]])))) + (testing "2 variable equation" + (is (= [[1 0 3] + [0 1 3]] + (map-matrix int + (auto-final + [[2 3 15] + [1 -1 0]]))))))