线性代数学习笔记二

﹥>﹥吖頭↗ 提交于 2019-12-20 02:28:06
线性代数学习笔记二

线性代数学习笔记二

1 线性方程组

矩阵记号是为解方程组带来方便。 解方程组,消元法。

三种基本变换对应于增广矩阵的下列变换:

行初等变换

  1. (倍加变换 replacement) 把某一行换成它本身与另一行的倍数的和
  2. (对换变换 interchange) 把两行对换
  3. (倍乘变换 scaling) 把某一行的所有元素乘以同一个非零数

行变换可应用于任何矩阵.如果一个矩阵可以经过一系列行初等变换变成另一个矩阵,则称这两个矩阵是行等价的。

行变换是可逆的。

线性方程组的两个基本问题:

  1. 方程组是否相容,即它是否至少有一个解?
  2. 若它有解,是否只有一个解,即解是否唯一?

1.1 行化简与阶梯型矩阵

非零行或列指矩阵中至少包含一个非零元素的行或列,非零行的先导元素是指该行中最左边的非零元素。

一个矩阵称为阶梯型,则有以下三个性值: 1 每一非零行在每一零行之上 2 某一行的先导元素所在的列位于前一行先导元素的右面 3 某一先导元素所在列下方元素都是零。若一个阶梯型矩阵还满足以下性质,则称它为简化阶梯形: 4 每一非零行的先导元素是1 5 每一先导元素1是该元素所在列的唯一非零元素

一个矩阵可以行化简变为阶梯形矩阵,但不同的方法可以化为不同的阶梯形矩阵。一个矩阵只能化为唯一的简化阶梯形矩阵。

每个矩阵行等价于唯一的简化阶梯形矩阵。大部分矩阵程序用RREF作为简化阶梯形的缩写,有些用REF作为阶梯形的缩写。

1.1.1 主元位置

矩阵经过行变换化为阶梯形后,经进一步的行变换将矩阵化为简化阶梯形时,先导元素的位置并不改变。

矩阵中的主元位置是A中对应于它的阶梯形中先导元素的位置。主元列是A的含有主元位置的列。

用不同的行变换产生不同的主元。

行简化算法,向前步骤,向后步骤。

1.1.2 线性方程组的解

行简化算法应用于方程组的增广矩阵时,可以得出线性方程组解集的一种显式示法。

对应主元列的变量称为基本变量,其它变量称为自由变量。自由变量是指它可取任意值。

解集的参数表示

有自由变量的方程有无穷多个解

线性方程组相容的充要条件是增广矩阵的最右列不是主元列。就是说,增广矩阵的阶梯形没有 [0 … 0 b] b ≠ 0的行,如果线性方程组相容,它的解集可能有两种情形:

  • 当没有自由变量时,有唯一解。
  • 若至少有一个自由变量,有无穷多解。
#!/usr/bin/env plk

;;如果使用lein exec 需要添加alembic依赖,jvm clojure启动太慢了,
;;改用planck, clojurescript REPL,速度快

;(require 'alembic.still)
;(alembic.still/distill '[org.clojure/math.numeric-tower "0.0.4"])
;(require '[clojure.math.numeric-tower :as math])

;;; matrix
(defn make-matrix
  "构造一个矩阵,
  array为元素内容
  len为每行有几个元素"
  [array len]
  (partition len array))

(defn cols-of-matrix
  "矩阵的列数"
  [m]
  (count (first m)))

(defn rows-of-matrix
  "矩阵的行数"
  [m]
  (count m))

(defn drop-ncol-matrix
  "丢弃矩阵m的前n列"
  [m n]
  (map #(drop n %) m))

(defn print-matrix
  "打印一个矩阵"
  [m]
  (println "--rows:" (rows-of-matrix m) ",cols:" (cols-of-matrix m) "--" )
  (doseq [row m]
    (print "|")
    (doseq [v row]
      (print v "\t" ))
    (println "|")))

(defn transpose-matrix
  "矩阵转置,就是行变为列,列变为行"
  [m]
  (apply mapv vector m))

(defn add-matrix
  "加两个矩阵"
  [m1 m2]
  (assert (and
           (= (cols-of-matrix m1) (cols-of-matrix m2))
           (= (rows-of-matrix m1) (rows-of-matrix m2)))
          "matrix length not match")
  (map #(map + %1 %2) m1 m2))

(defn scal-matrix
  "放大矩阵m"
  [scal-n matrix]
  (map (fn [row]
         (map #(* scal-n %1) row)) matrix))

(defn dot-product
  "两个向量的点积"
  [v1 v2]
  (reduce + (map * v1 v2)))

(defn mul-matrix
  "乘2个矩阵"
  [m1 m2]
  (assert (= (cols-of-matrix m1) (rows-of-matrix m2))
          "matrix not match, can't mul")
  (let [tm2 (transpose-matrix m2)]
    (map (fn [row-m1]
           (map (fn [col-m2]
                  (dot-product row-m1 col-m2))
                tm2))
         m1)))

(defn col-of-matrix
  "返回一个矩阵m的第c列"
  [m c]
  (map #(nth % c) m))

(defn row-of-matrix
  "返回一个矩阵m的第r行"
  [m r]
  (nth m r))

(defn val-of-matrix
  "返回矩阵m位置(row,col)的值"
  [m row col]
  (nth (nth m row) col))

(defn pivot-of-vec
  "返回一个向量中主元的索引及主元值"
  [v]
  (let [[idx _](apply max-key second (map-indexed #(vector %1 (Math/abs %2)) v))]
    [idx (nth v idx)]))

(defn replacement-row
  "倍加变换"
  [m r1 r2 n]
  (println "add " n " times row " r2 " to row " r1 )
  (let [row2 (row-of-matrix m r2)
        scal-row2 (map #(* n %1) row2)]
    (map-indexed (fn [idx row]
                   (if (== idx r1)
                     (map + row scal-row2)
                     row))
                 m)))

(defn interchange-row
  "交换矩阵m的行r1和r2"
  [m r1 r2]
  (let [row1 (row-of-matrix m r1)
        row2 (row-of-matrix m r2)]
    (println "interchange row " r1 " and " r2)
    (map-indexed (fn [idx r]
                   (cond
                     (= idx r1) row2
                     (= idx r2) row1
                     :else r)) m)))

(defn scaling-row
  "放大矩阵m第r行n倍,倍乘r行"
  [m r n]
  (println "scaling row " r " with " n)
  (map-indexed (fn [idx row]
                 (if (== idx r)
                   (map #(* n %1) row)
                   row)) m))

(defn echelon-form
  "对矩阵m行化简为阶梯形矩阵"
  [m]
  (let [cols (cols-of-matrix m)
        rows (rows-of-matrix m)]
    (loop [row-idx 0
           col-idx 0
           result m]
      (println "loop forward phase row" row-idx " col-idx" col-idx "matrix:")
      (print-matrix result)
      (if (= row-idx (- rows 1))
        result
        (let [rest (take-last (- rows row-idx) result)
              [pivot-idx pivot col-idx]
                                        ;找到主元列
              (loop [idx col-idx]
                (let [[pivot-idx pivot] (pivot-of-vec (col-of-matrix rest idx))]
                  (if (== 0 pivot)
                    (recur (inc idx))
                                        ;这里的pivot-idx加上row-idx是因为此矩阵是截取过的
                    [(+ row-idx pivot-idx) pivot idx])))
;              a (println "pivot of col" col-idx " pivot-row" pivot-idx " pivot " pivot )
                                        ;是否交换行

              result (if-not (= row-idx pivot-idx)
                       (interchange-row result row-idx pivot-idx)
                       result)
                                        ;倍加消元
              result (reduce (fn [r idx]
                               (let [rv (val-of-matrix r idx col-idx)]
                                 (if (== 0 rv)
                                   r
                                   (replacement-row r idx row-idx (/ (- rv) pivot))))
                               ) result (range (inc row-idx) rows))]
          (recur (inc row-idx)
                 (inc col-idx)
                 result))))))

(defn pivot-of-row
  "获得矩阵某行的主元,返回[c n]
  c为主元所在列
  n为主元值
  "
  [m r]
  (->> (row-of-matrix m r)
       (map-indexed vector)
       (filter (fn [[idx v]] (not (== v 0))))
       first))

(defn reduced-echelon-form
  "简化阶梯形矩阵"
  [m]
  (loop [row-idx (- (rows-of-matrix m) 1)
         result (echelon-form m)]
    (println "loop backward phase,row " row-idx )
    (print-matrix result)
    (if (< row-idx 0)
      result
      (let [[pivot-col pivot] (pivot-of-row result row-idx)
            _ (println "pivot at (" row-idx "," pivot-col ") = " pivot)
            result (if (nil? pivot)
                     result
                     (loop [result (if-not (== 1 pivot)
                                     (scaling-row result row-idx (/ 1 pivot))
                                     result)
                            r2-idx (dec row-idx)]
                                        ;倍加消元
                       (if (< r2-idx 0)
                         result
                         (let [v (val-of-matrix result r2-idx pivot-col)]
                           (if (== 0 v)
                             (recur result (dec r2-idx))
                             (recur (replacement-row result r2-idx row-idx (- v))
                                    (dec r2-idx)))))))]
        (recur (dec row-idx) result)))))

(def a (make-matrix [3 -1 2 0] 2))
(def b (make-matrix [-7 2 3 5] 2))
(def c (make-matrix [-7 2 3 5 6 8 9 2 3 4] 5))
(print-matrix a)
(print-matrix b)
(print-matrix c)
(echelon-form c)
(reduced-echelon-form c)
(print-matrix (add-matrix a b))
(print-matrix (add-matrix a (scal-matrix -1 b)))
(print-matrix (add-matrix
               (make-matrix [1 2 3 4 5 6 7 8 9] 3)
               (make-matrix [-10 -100 -1000 1 0 0 1 0 1] 3)))
(print-matrix (mul-matrix
               (make-matrix [2 -3 7 5] 2)
               (make-matrix [10 -8 12 -2] 2)))
(reduced-echelon-form (make-matrix [1 -2 1 0
                                    0 2 -8 8
                                    5 0 -5 10] 4))
;;; AB <> BA
(print-matrix (mul-matrix
               (make-matrix [1 2 3 4] 2)
               (make-matrix [5 6 7 8] 2)))
(print-matrix (mul-matrix
               (make-matrix [5 6 7 8] 2)
               (make-matrix [1 2 3 4] 2)))

(print-matrix (mul-matrix
               (make-matrix [3 1 2 -2 0 5] 3)
               (make-matrix [-1 3 0 5 1 5] 2)))

(def a (make-matrix [1 -2 1 0 0 2 -8 8 5 0 -5 10] 4))
(print-matrix a)
(print-matrix (replacement-row a 2 0 (/ -5 1)))
(print-matrix (scaling-row a 2 (/ 1 5)))
(print-matrix (interchange-row a 0 2))

(def a (make-matrix [0 3 -6 6 4 -5
                     3 -7 8 -5 8 9
                     3 -9 12 -9 6 15] 6))
(print-matrix a)
(print-matrix (echelon-form a))
(reduced-echelon-form a)
(reduced-echelon-form (make-matrix [1 0 -5 1
                                    0 1 1 4
                                    0 0 0 0 ] 4))
(def b (make-matrix [1 6 2 -5 -2 -4
                     0 0 2 -8 -1 3
                     0 0 0 0 1 7] 6))
(reduced-echelon-form b)

(reduced-echelon-form (make-matrix [3 -9 12 -9 6 15
                                    0 2 -4 4 2 -6
                                    0 0 0 0 1 4] 6))
(reduced-echelon-form (make-matrix [1 -3 -5 0
                                    0 1 1 3] 4))
(defn vec-i
  "返回一个向量,
  长度为n,默认值为0,
  第i个元素值为m,"
  [m i n]
  (-> (repeat n 0)
      (vec)
      (assoc-in [i] m)))

;;单位矩阵I  IA=A AI=A 方阵
(defn identity-matrix
  "返回nxn的单位矩阵"
  [n]
  (vec (map-indexed #(vec-i %2 %1 n) (repeat n 1))))

(defn augment-matrix
  "增广矩阵"
  [m1 m2]
  (assert (= (rows-of-matrix m1)
             (rows-of-matrix m2))
          "augment matrix rows mismatch")
  (map concat m1 m2))

(augment-matrix (make-matrix [1 2 3 4 5 6] 3)
                (make-matrix [7 8 9 10 11 12] 3)
                )

(defn invert-matrix
  "获得矩阵的逆矩阵"
  [m]
  (let [rn (rows-of-matrix m) ]
    (assert (= rn (cols-of-matrix m))
            "invert not a square matrix")
    (-> (reduced-echelon-form (augment-matrix m (identity-matrix rn)))
        (drop-ncol-matrix rn))))

(print-matrix (identity-matrix 4))

;; A'A = I ; A'是A的逆
(print-matrix (invert-matrix (make-matrix [2 5 -3 -7] 2)))
(print-matrix (invert-matrix (make-matrix [0 1 2
                                           1 0 3
                                           4 -3 8] 3)))

(defn add-vec
  "加两个向量"
  [v1 v2]
  (map + v1 v2))

(defn scal-vec
  "标量乘法"
  [n v]
  (map  #(* n  %1) v))

(add-vec [4 -8] [-6 15])
(scal-vec 4 [4 -8])
(add-vec (scal-vec 4 [1 -2]) (scal-vec -3 [2 -5]))
(reduced-echelon-form (make-matrix [1 2 7 -2 5 4 -5 6 -3] 3))
(reduced-echelon-form (make-matrix [-5 6 -3 1 2 7 -2 5 4 ] 3))
(add-vec (scal-vec 100 [0.45 0.25 0.15])
         (scal-vec 20 [0.4 0.3 0.15]))
(def v1 [20 550])
(def v2 [30 500])
(reduced-echelon-form (make-matrix [20 30 150
                                    550 500 2825] 3))
(reduced-echelon-form (make-matrix [27.6 30.2 162
                                    3100 6400 23610
                                    250 360 1623] 3))
(mul-matrix (make-matrix [1 2 -1 0 -5 3] 3)
            (make-matrix [4 3 7] 1))

1.2 向量方程

仅含一列的矩阵称为列向量,或简称向量。

所有两个元素的向量的集记为R2, R表示向量中的元素是实数,指数2表示每个向量包含2个元素。

给定Rn 中向量v1, v2, …, vp 和标量 c1, c2, …, cp ,向量 \[ y = c_1v_1+...+c_pv_p \] 称为向量v1, v2, …, vp 以c1, c2, …, cp 为权的线性组合。

向量方程 \[ x_1a_1+x_2a_2+...+x_na_n=b\] 和增广矩阵为

\begin{equation} \label{eq:m1} [a_1 \quad a_2 \quad ... \quad a_n \quad b] \end{equation}

的线性方程组有相同的解集。特别地, b 可以表示为 a1, a2, …, an 的线性组合,当且仅当对应于 \eqref{eq:m1} 式的方程组有解.

1.3 矩阵方程

若A是mxn矩阵,它的各列为a1, …, an. 若x是Rn 中向量,则A与x的积,记为Ax,就是A的各列以x中对应元素为权的线性组合,即 \[ Ax=\begin{bmatrix} a_1 & a_2 & \dots & a_n \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} = x_1a_1 + x_2a_2 + \dots + x_n a_n \]

称Ax=b这样的方程为矩阵方程

至此,线性方程组有三种不同但彼此等价的观点:作为矩阵方程、作为向量方程或作为线性方程组。 都用行化简算法来化简增广矩阵来解。

主对角线上元素为1,其他位置元素为0,这个矩阵称为单位矩阵。记为I

1.4 线性方程组的解集

如果线性方程组可以写成Ax=0的形式,则称为齐次的,A是mxn矩阵,0是Rn 中的零向量。这样的方程组至少有一个解,即x=0,这个解称为它的平凡解。

齐次方程Ax=0有非平凡解,当且仅当方程至少有一个自由变量。

测试

Created: 2018-12-11 Tue 20:16

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!