按值传递列表列表不会在 Scheme 语言中更新

问题描述 投票:0回答:1

我正在尝试在 Scheme 中编写一个函数,它将使用高斯消除方法计算给定矩阵(以列表列表的形式)的等级。
我会在代码中解释我想做什么,如果有人能告诉我我做错了什么\如何纠正它,我将不胜感激。

iter-rows
函数中,我遍历行并对每一行进行高斯消元,使矩阵成为行梯形。
below-pivot
将基本上执行给定行中枢轴下方的消除步骤。
factor-rec
这里我计算了消元过程中乘以一行所需的因子
elimination
函数对枢轴下方的其余行执行消除本身。
至于
update-matrix
函数,它将从另一行中减去一行的倍数。
最后,计算所有非零行以找到排名。
由于列表是不可变的,我在每次调用时都传递它们的值。
参考代码如下:

#lang racket

(define (rank matrix)
  (define (iter-rows index rows-len matrix)
    (if (= index rows-len)
        matrix
          (let ((pivot (list-ref (list-ref matrix index) index)))
            (if (= pivot 0)
                (iter-rows (+ index 1) rows-len matrix)
                (begin
                  (below-pivot (+ index 1) rows-len matrix pivot index)
                  (iter-rows (+ index 1) rows-len matrix)
                  )
                )
            )
          )
    )
  (define (below-pivot from-index rows-len matrix pivot i)
    (if (= from-index rows-len)
        matrix
        (begin
          (factor-rec (+ from-index 1) rows-len matrix i pivot)
          (below-pivot (+ from-index 1) rows-len matrix pivot i)
          )
        )
    )
  (define (factor-rec j rows-len matrix i pivot)
    (if (= j rows-len)
        matrix
        (begin
          (let ([factor (/ (list-ref (list-ref matrix j) i) pivot)])
            (elimination i i rows-len matrix j factor)
            )
          )
        )
    )
  (define (elimination k i rows-len matrix j factor)
    (if (= k rows-len)
        matrix
        (begin
          (update-matrix matrix j k i factor)
          (elimination (+ k 1) i rows-len matrix j factor)
          )
        )
    )
  (define (update-matrix matrix j k i factor)
    (let ((new-cdr (- (list-ref (list-ref matrix j) k)
                      (* factor (list-ref (list-ref matrix i) k)))))
      (list (list-ref matrix i)
            (cons new-cdr (list-tail (list-ref matrix j) k)))
      )
    )
  (let ((rows-len (length matrix)))
    (iter-rows 0 rows-len matrix)
    )
  (define (count-nonzero-rows matrix)
  (let loop ((matrix matrix) (rank- 0))
    (cond ((null? matrix) rank-)
          ((not (all-zeroes? (car matrix))) (loop (cdr matrix) (+ rank- 1)))
          (else (loop (cdr matrix) rank-)))))
  (let* ((rank (count-nonzero-rows matrix)))
    rank)
  )

(define (all-zeroes? row)
  (for/and ([x row]) (= x 0)))

我是 Scheme 的新手,所以也很感激任何其他提示。
谢谢。

matrix scheme lisp racket linear-algebra
1个回答
0
投票

我想你想要这样的东西:

#lang racket

(define (extract matrix i j)
  (vector-ref (vector-ref matrix i) j))
  
(define (swap-rows! matrix i j)
  (let ((row-i (vector-ref matrix i))
        (row-j (vector-ref matrix j)))
    (vector-set! matrix i row-j)
    (vector-set! matrix j row-i)))

(define (scale-row! matrix i factor)
  (define (vector-scale vec factor)
    (vector-map (curry * factor) vec))
  (let* ((row (vector-ref matrix i))
         (scaled-row (vector-scale row factor)))
    (vector-set! matrix i scaled-row)))

(define (eliminate-rows! matrix i j pivot)
  (define (eliminate-row! matrix i j pivot)
    (when (< i (vector-length matrix))
      (let* ((element-i-j (extract matrix i j))
             (factor (/ element-i-j pivot)))
        (scale-row! matrix i factor)
        (eliminate-row! matrix (add1 i) j pivot))))
  (eliminate-row! matrix (add1 i) j pivot))

(define (gaussian-rank matrix (i 0) (j 0) (rank 0))
  (cond ((>= i (vector-length matrix)) rank)
        ((zero? (extract matrix i j)) (gaussian-rank matrix (add1 i) j rank))
        (else
          (swap-rows! matrix i rank)
          (let ((pivot (extract matrix rank j)))
            (when (not (zero? pivot))
              (scale-row! matrix rank (/ 1 pivot))
              (eliminate-rows! matrix rank j pivot))
            (gaussian-rank matrix (add1 i) (add1 j) (add1 rank))))))

(define mat (vector #(1 2 3) #(0 1 2) #(0 0 1)))
(gaussian-rank mat) ;;=> 1
© www.soinside.com 2019 - 2024. All rights reserved.