add a solid, literate spec, and stuff to use it

This commit is contained in:
mehbark 2023-01-14 23:16:23 -05:00
parent 80c7eff160
commit a09cfe7b19
5 changed files with 79 additions and 12 deletions

View file

@ -26,3 +26,8 @@
;; (defn apply-operations-with-steps ;; (defn apply-operations-with-steps
;; "Takes a matrix and a list of operations and returns a seq of matrices" ;; "Takes a matrix and a list of operations and returns a seq of matrices"
;; ) ;; )
;; (defn gaussian-top-op
;; [m]
;; "Takes a matrix and returns the op required to gaussian-eliminate the top"
;; {:n})

View file

@ -1,4 +1,5 @@
(ns matrix.base) (ns matrix.base
(:require [matrix.spec :as opspec]))
(defn to-vec (defn to-vec
[v] [v]
@ -66,3 +67,25 @@
(def matrix-height (def matrix-height
"Get the height of a matrix" "Get the height of a matrix"
count) count)
(defn apply-row-op
"Apply a spec-compliant row-op to a matrix, curriable"
([op]
(fn [m]
(apply-row-op op m)))
([op m]
(if-let [[type inner] (opspec/conform op)]
(case type
:swap (swap-rows
m
(:swap inner)
(:with inner))
:add (add-rows-with-mul
m
(:times inner)
(:add-row inner)
(:to inner))
:mul (mul-row
m
(:by inner)
(:mul-row inner))))))

View file

@ -2,7 +2,8 @@
(ns matrix.render (ns matrix.render
(:require [clojure.string :as str]) (:require [clojure.string :as str])
(:require [matrix.base :refer :all])) (:require [matrix.base :refer :all])
(:require [matrix.spec :refer :all]))
(def default-render-options (def default-render-options
{:bar? false {:bar? false
@ -152,26 +153,27 @@
(str/join (map shrink-digit (str n)))) (str/join (map shrink-digit (str n))))
(defn pretty-swap [op] (defn pretty-swap [op]
(str "R" (shrink-number (:a op)) (str "R" (shrink-number (:swap op))
" ↔ " " ↔ "
"R" (shrink-number (:b op)))) "R" (shrink-number (:with op))))
(defn pretty-mul [op] (defn pretty-mul [op]
(str (:n op) "R" (shrink-number (:row op)))) (str (:by op) "R" (shrink-number (:mul-row op))))
(defn pretty-add [op] (defn pretty-add [op]
(let [n (if (= 1 (:n op)) (let [n (if (= 1 (:times op))
"" ""
(str (:n op)))] (str (:times op)))]
(str n (str n
"R" (shrink-number (:from op)) "R" (shrink-number (:add-row op))
" + " " + "
"R" (shrink-number (:to op))))) "R" (shrink-number (:to op)))))
(defn pretty-row-op (defn pretty-row-op
"Returns a pretty string of a row operation" "Returns a pretty string of a row operation"
[op] [op]
(cond (if-let [[op-type inner] (conform op)]
(:swap op) (pretty-swap op) (case op-type
(:mul op) (pretty-mul op) :swap (pretty-swap inner)
(:add op) (pretty-add op))) :mul (pretty-mul inner)
:add (pretty-add inner))))

35
src/matrix/spec.clj Normal file
View file

@ -0,0 +1,35 @@
(ns matrix.spec
(:require [clojure.spec.alpha :as spec]))
;; (spec/def ::n number?)
;; (spec/def ::a number?)
;; (spec/def ::b number?)
;; (spec/def ::row number?)
;; (spec/def ::from number?)
;; (spec/def ::to number?)
(spec/def ::swap
(spec/map-of #{:swap :with} number?))
(spec/def ::add
(spec/map-of #{:add-row :times :to} number?))
(spec/def ::mul
(spec/map-of #{:mul-row :by} number?))
(spec/def ::row-op
(spec/or :swap ::swap
:add ::add
:mul ::mul))
;; (def bla (spec/conform ::row-op {:mul-by 1 :row 2}))
(defn conform
[op]
(let [conformed (spec/conform ::row-op op)]
(if (spec/invalid? conformed)
nil
conformed)))
(defn explain
[op]
(spec/explain ::row-op op))

View file

@ -2,6 +2,8 @@
(:require [clojure.test :refer :all] (:require [clojure.test :refer :all]
[matrix.base :refer :all])) [matrix.base :refer :all]))
; TODO: more tests
(deftest test-mul-row (deftest test-mul-row
(testing "Multiplying by one remains the same" (testing "Multiplying by one remains the same"
(let [mat (id-matrix 10)] (let [mat (id-matrix 10)]