Gauche で グレブナ基底計算
D加群セミナーの関係で、
グレブナ基底と代数多様体入門〈上〉イデアル・多様体・アルゴリズム
を読んだ副産物です。
ブッフベルガーのアルゴリズムで一番簡単なやつを実装しただけなので、おもちゃの域をでるものではありません。90式はブリキ缶だぜ!
(use srfi-1) (use srfi-43) (use util.combinations) (define (poly . l) (apply hash-table (cons 'equal? (remove (lambda (x) (zero? (cdr x))) l)))) (define (order-lex a b) (let loop ((a a) (b b)) (cond ((null? a) #f) ((null? b) #t) ((> (car a) (car b)) #t) ((< (car a) (car b)) #f) (else (loop (cdr a) (cdr b)))))) (define (order-grlex a b) (let ((sum-a (fold + 0 a)) (sum-b (fold + 0 b))) (cond ((> sum-a sum-b) #t) ((< sum-a sum-b) #f) ((= sum-a sum-b) (order-lex a b))))) (define (order-grevlex a b) (let ((sum-a (fold + 0 a)) (sum-b (fold + 0 b))) (cond ((> sum-a sum-b) #t) ((< sum-a sum-b) #f) ((= sum-a sum-b) (order-lex (reverse b) (reverse a)))))) (define (multideg order f) (fold (lambda (a b) (if (order a b) a b)) '() (hash-table-keys f))) (define (LC order f) (hash-table-get f (multideg order f))) (define (LM order f) (cons (multideg order f) 1)) (define (LT order f) (cons (multideg order f) (LC order f))) (define (divide-term a b) (cons (map - (car a) (car b)) (/ (cdr a) (cdr b)))) (define (zero-poly? f) (every zero? (hash-table-values f))) (define (+poly a b) (define ht (poly)) (hash-table-for-each a (lambda (akey avalue) (hash-table-put! ht akey avalue))) (hash-table-for-each b (lambda (bkey bvalue) (hash-table-update! ht bkey (cut + <> bvalue) 0))) (hash-table-for-each ht (lambda (key value) (when (zero? value) (hash-table-delete! ht key)))) ht) (define (-poly a b) (define ht (poly)) (hash-table-for-each a (lambda (akey avalue) (hash-table-put! ht akey avalue))) (hash-table-for-each b (lambda (bkey bvalue) (hash-table-update! ht bkey (cut - <> bvalue) 0))) (hash-table-for-each ht (lambda (key value) (when (zero? value) (hash-table-delete! ht key)))) ht) (define (*poly a b) (define ht (poly)) (hash-table-for-each a (lambda (akey avalue) (hash-table-for-each b (lambda (bkey bvalue) (hash-table-update! ht (map + akey bkey) (cut + <> (* avalue bvalue)) 0))))) (hash-table-for-each ht (lambda (key value) (when (zero? value) (hash-table-delete! ht key)))) ht) (define (quotient&remainder order f g-list) (define quotients (make-vector (length g-list) (poly))) (let loop ((f f) (intermediate-divident (poly))) (if (zero-poly? f) (values (vector->list quotients) intermediate-divident) (let ((ind (list-index (lambda (x) (every >= (multideg order f) (multideg order x))) g-list))) (if ind (let* ((g (list-ref g-list ind)) (p (poly (divide-term (LT order f) (LT order g))))) (vector-set! quotients ind (+poly p (vector-ref quotients ind))) (loop (-poly f (*poly p g)) intermediate-divident)) (loop (-poly f (poly (LT order f))) (+poly (poly (LT order f)) intermediate-divident))))))) (define (quotient-poly order f g-list) (receive (q r) (quotient&remainder order f g-list) q)) (define (remainder-poly order f g-list) (receive (q r) (quotient&remainder order f g-list) r)) (define (S-poly order f g) (define term-r (cons (map max (multideg order f) (multideg order g)) 1)) (-poly (*poly (poly (divide-term term-r (LT order f))) f) (*poly (poly (divide-term term-r (LT order g))) g))) (define (groebner order f-list) (let ((l (remove zero-poly? (map (lambda (x) (remainder-poly order (S-poly order (car x) (cadr x)) f-list)) (combinations f-list 2))))) (if (null? l) f-list (groebner order (append f-list l)))))
データ構造は、単項式を'(1 2 1)、項を'((1 2 1) . 4)、多項式をハッシュテーブルで(キーに単項式、値にその係数)としました。
多項式について、辞書式順序の場合、以下が成り立つ。
(define f (poly '((1 2 1) . 4) '((0 0 2) . 4) '((3 0 0) . -5) '((2 0 2) . 7))) (multideg order-lex f) == (3 0 0) (LC order-lex f) == -5 (LM order-lex f) == ((3 0 0) . 1) (LT order-lex f) == ((3 0 0) . -5)
S多項式はこうです。
のときgrlex順序に関するS多項式は
(S-poly order-grlex (poly '((3 2) . 1) '((2 3) . -1) '((1 0) . 1)) (poly '((4 1) . 3) '((0 2) . 1))) == '(((3 3) . -1) ((2 0) . 1) ((0 3) . -1/3))
グレブナ基底はこうです。
のgrlex順序に関するグレブナ基底は、
(groebner order-grlex (list (poly '((3 0) . 1) '((1 1) . -2)) (poly '((2 1) . 1) '((0 2) . -2) '((1 0) . 1)))) == '((((3 0) . 1) ((1 1) . -2)) (((2 1) . 1) ((0 2) . -2) ((1 0) . 1)) (((2 0) . -1)) (((1 1) . -2)) (((0 2) . -2) ((1 0) . 1)))