[数式処理][Scheme] 算術式を簡単にする

微分などで複雑になった算術式を簡素化するには次のようにする。

(define (simple exp)
  (define (flat lst op)
    (append-map! (lambda (x)
                   (if (and (pair? x) (eq? (car x) op))
                       (flat (cdr x) op)
                       (list x)))
                 lst))
  
  (define (constant-fold args init op)
    (define (cf args num acc)
      (cond ((null? args)
             (values acc num))
            ((number? (car args))
             (cf (cdr args) (op num (car args)) acc))
            (else
             (cf (cdr args) num (append! acc (list (car args)))))))
    (cf args init '() ))
  
  (define (simple-+ args)
    (set! args (map simple args))
    (set! args (flat args '+))
    (receive (exps num) (constant-fold args 0 +)
     (cond ((null? exps) num)
           (else `(+ ,@args num)))))
  
  (define (simple-* args)
    (call/cc
     (lambda (c)
       (set! args (map simple args))
       (set! args (flat args '*))
       (map (lambda (x)
              (when (and (number? x) (= x 0))
                    (c 0)))
            args)
       (set! args (constant-fold args 1 *))
       (set! args (remove (lambda (x)
                            (and (number? x)(= x 1)))
                          args))
       (if (= 1 (length args))
           (car args)
           `(* ,@args)))))

  (define (simple-expt base ex)
    (set! base (simple base))
    (set! ex (simple ex))
    (cond ((or (and (number? base) (= base 1))
               (and (number? ex) (= ex 0)))
           1)
          ((or (and (number? base) (= base 0))
               (and (number? ex) (= ex 1)))
           base)
          (else
           `(expt ,base ,ex))))

  (define (simple-- arg)
    (cond ((number? arg) (- arg))
          ((and (pair? arg)
                (eq? (car arg) '+))
           (simple-+ (map (lambda (x) (list '- x))
                          (cdr arg))))
          ((and (pair? arg)
                (eq? (car arg) '*))
           (simple-* (map (lambda (x) (list '- x))
                          (cdr arg))))
          (else
           `(- ,arg))))
  
  (cond ((not (pair? exp)) exp)
        ((eq? (car exp) '-)
         (simple-- (cadr exp)))
        ((eq? (car exp) '+)
         (simple-+ (cdr exp)))
        ((eq? (car exp) '*)
         (simple-* (cdr exp)))
        ((eq? (car exp) 'expt)
         (simple-expt (cadr exp) (caddr exp)))
        (else
         `(,(car exp) ,@(map simple (cdr exp))))))
> (simple (deriv '(expt (* (sin x) (cos x)) 1/2) 'x))
=> (* (expt (* (sin x) (cos x)) -1/2) (+ (* (cos x) (cos x)) (* (sin x) (- (sin x)))) 1/2)

`-‘ 演算子は単項演算子としてのみ使える。


Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/category.php on line 383
This entry was posted in コンピュータ and tagged , , by bugyo. Bookmark the permalink.

Deprecated: Creation of dynamic property WP_Query::$comments_by_type is deprecated in /usr/home/bugyo/public_html/b-log/wp-includes/comment-template.php on line 1528

Leave a Reply

Your email address will not be published. Required fields are marked *

*