計算機プログラムの構造と解釈 第二版 P204 問題3.73

RC回路というと、回路とかもう忘れてしまったのでびっくりする。
だがよく問題を読む。回路の知識は特にいらない。

やらなければ行けない事は二つ

1.
教科書にある以下の式を表現する手続きRCを教科書の定義通り作る。
 v={v}_0 + 1/c\int_{0}^{t}idt + Ri


2.
1でつくったRCを利用して

(define RC1 (RC 5 1 0.5))

を作ってみる。


まず「1」から。
そもそも積分の部分はP203で定義されていた(integral itegrand initial-value dt)を使えばよいんだから、後は上手い事考えればよい。
手続きの入力インターフェースは文章を読んでてもわかりずらいんだけど、
RC1の手続きの定義をみて考えると

(RC R C dt)

みたいな感じ。
RCでアウトプットされるのは、

入力として電流iを表現するストリームとキャパ下の電圧の初期値v0をとり,出力として電圧vのストリームを返すものとする.

ということなので
(lambda (i v0)みたいなのは確実にでてくるでしょう。


ということで、v0がinitial-valueになる事v0って名前からも確実。
itegrand(被積分関数)がどこまでかってことで、1/cは積分の中に入れちゃう。
そうすると、積分の部分は

(integral (scale-stream (scale-stream i (/ 1 C)) v0 dt)

って感じになる。
あとは、

(scale-stream i R)

を足せば良いので

(define (RC R C dt) 
  (lambda (i v0) 
    (add-streams  (integral (scale-stream i (/ 1 C)) v0 dt) 
                  (scale-stream i R))))

か。


「2」はそのままなので省略

#!/usr/local/bin/gosh
;; -*- coding: utf-8 -*-

(load "./modules/stream.scm")


(define ones (cons-stream 1 ones))


(define seconds (cons-stream 2 seconds))

(define (scale-stream stream factor)
  (stream-map (lambda (x) (* x factor)) stream))

(define (add-streams s1 s2)
  (stream-map + s1 s2))


(define integers (cons-stream 1 (add-streams ones integers)))


(define (integral integrand initial-value dt)
  (define int
    (cons-stream initial-value
                 (add-streams (scale-stream integrand dt)
                              int)))
  int)


(define (RC R C dt)
  (lambda (i v0)
    (add-streams  (integral (scale-stream i (/ 1 C)) v0 dt)
                  (scale-stream i R))))


(define RC1 (RC 5 1 0.5))

(RC1 ones 1)


;; main
(define (main args)

  (print (RC1 ones 0))

  (print (stream-car (stream-cdr (RC1 ones 0))))
  (print (stream-car (stream-cdr (stream-cdr (RC1 ones 0)))))
  (print (stream-car (stream-cdr (stream-cdr (stream-cdr (RC1 ones 0))))))

  (print (stream-car (stream-cdr (stream-cdr (stream-cdr (stream-cdr (RC1 ones 0)))))))
  0)


./modules/stream.scmは
http://d.hatena.ne.jp/rucifer_hacker/20090127/1233037207
から引用

;; stream.scm
(define (memo-proc proc)
  (let ((already-run? #f)
        (result #f))
    (lambda ()
      (if (not already-run?)
        (begin (set! result (proc))
               (set! already-run? #t)
               result)
        result))))


;;非メモ化 delay
(define-macro (delay exp) `(lambda () ,exp))

;;メモ化 delay
(define-macro (delay exp) `(memo-proc (lambda () ,exp)))

(define (force exp) (exp))

(define the-empty-stream '())

(define stream-null? null?)

(define-macro (cons-stream a b)
              `(cons ,a (delay ,b)))

(define (stream-car stream)
  (car stream))

(define (stream-cdr stream)
  (force (cdr stream)))

;;;;


(define (stream-ref s n)
  (if (= n 0)
    (stream-car s)
    (stream-ref (stream-cdr s) (- n 1))))


;; (define (stream-map proc s)
;;   (if (stream-null? s)
;;     the-empty-stream
;;     (cons-stream (proc (stream-car s))
;;                  (stream-map proc (stream-cdr s)))))


;; 問題3.50で作成した一般化された stream-map
(define (stream-map proc . argstreams)
  (if (stream-null? (car argstreams))
    the-empty-stream
    (cons-stream
      (apply proc (map stream-car argstreams))
      (apply stream-map
             (cons proc (map stream-cdr argstreams))))))


(define (stream-for-each proc s)
  (if (stream-null? s)
    'done
    (begin (proc (stream-car s))
           (stream-for-each proc (stream-cdr s)))))

(define (display-stream s)
  (stream-for-each display-line s))

(define (display-line x)
  (newline)
  (display x))


;;;;

(define (stream-enumerate-interval low high)
  (if (> low high)
    the-empty-stream
    (cons-stream
      low
      (stream-enumerate-interval (+ low 1) high))))

(define (stream-filter pred stream)
  (cond ((stream-null? stream) the-empty-stream)
        ((pred (stream-car stream))
         (cons-stream (stream-car stream)
                      (stream-filter pred
                                     (stream-cdr stream))))
        (else (stream-filter pred (stream-cdr stream)))))

(define (show-stream s n)
  (if (= n 0)
    (newline)
    (begin
      (display " ")
      (display (stream-car s))
      (show-stream (stream-cdr s) (- n 1)))))

こんな感じで実行してみる。

(5 . #<closure (memo-proc memo-proc)>)
5.5
6.0
6.5
7.0

多分できていると思う。