(sicp46)m3.73~m3.80

  • defineの部分をletrecに変えるところ以外は、特に変わったところはない。
  • @map=stream-map

(でも、最後の方とかは、教科書に書いてある図を頼りにcodeに変換しただけのような気がします><)

(use my-stream)

(define (@add s1 s2)
  (@map + s1 s2))

(define (@scale s n)
  (@map (cut * n <>) s))

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

;; m3.73
;;多分、教科書の図は右から読んでいけば良いんだと思う。
;;2つに分かれたところはadd-streamで
;;これでいいのかな?

(define (RC r c dt)
  (lambda (is v0)
    ;is = i stream
    (@add (@scale (integral is v0 dt) (/ c 1))
          (@scale is r))))

(define RC1 (RC 5 1 0.5))
(define ones  (@cons 1 ones))
(@>list (RC1 ones 0))
;; 8:user> => (5 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5)
	;;この出力結果はvを表している。

;; m3.74
(define (make-zero-crossings input-stream last-value)
  (let1 this (@car input-stream)
    (@cons
     (sign-change-detector this last-value)
     (make-zero-crossings (@cdr input-stream)
                       this))))

(define zero-crossings (make-zero-crossings sense-data 0))
	;;sense-dataが存在しない。

;;sign-change-detectorは存在しないのかー
(define (sign-change-detector x y)
  (define (same-type? x y)
    (or (and (negative? x) (negative? y))
        (and (positive? x) (positive? y))))
  (if (same-type? x y)
      0
      (if (< x y) 1 -1)))

;; (let ((l (list 1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4)))
;;   (cons 0 (map sign-change-detector l (cdr l))))
;; ;; 19:user> => (0 0 0 0 0 -1 0 0 0 0 1 0 0)
;; 	;;教科書と合っている
(define sense-data (RC1 ones -7))
(define zero-crossings (make-zero-crossings sense-data 0))
(@>list zero-crossings)
;; 36:user> => (1 0 0 0 -1 -1 0 0 0 0)

;; 問題に入ろう
	;;こんな感じかな?
(define zero-crossings
  (@map sign-change-detector
        sense-data
        (@cons 0 sense-data)))

(@>list zero-crossings)
;; 48:user> => (1 0 0 0 -1 -1 0 0 0 0)
	;;同じ

;; m3.75
(define (make-zero-crossings input-stream last-value)
  (let ((avpt (/ (+ (@car input-stream) last-value) 2)))
    (@cons (sign-change-detector avpt last-value)
           (make-zero-crossings (@cdr input-stream)
                                avpt))))
;;last-valueが平均ととったあとの値になっている。
;;こんな風にすればいい。
(define (make-zero-crossings input-stream last-value last-avpt)
  (let ((avpt (/ (+ (@car input-stream) last-value) 2)))
    (@cons (sign-change-detector avpt last-avpt)
           (make-zero-crossings (@cdr input-stream)
                                (@car input-stream)
                                avpt))))


;; m3.76
(define (smooth s)
  (@map (lambda (x y) (/ (+ x y) 2)) s (@cdr s)))

;; (define (integers-from n)
;;   (@cons n (integers-from (+ n 1))))
;; (define integers (integers-from 1))
;; (@>list (smooth (integers 1)))
;; ;; 57:user> => (3/2 5/2 7/2 9/2 11/2 13/2 15/2 17/2 19/2 21/2)
;; (@>list (smooth ones))
;; ;; 62:user> => (1 1 1 1 1 1 1 1 1 1)
	;;たぶん合っている。

;;零交差を調べるのに、元のstreamは使ってないような気がする。
(define (extendable-make-zero-crossings box)
    (define (make box-stream last-box-value)
      (let1 box-value (@car box-stream)
        (@cons
         (sign-change-detector box-value last-box-value)
         (make (@cdr box-stream) box-value))))
    (lambda (input-stream last-value)
      (make (box input-stream) last-value)))


(define make-zero-crossings
  (extendable-make-zero-crossings smooth))

 ;;こんな感じかな?

;;;=3.5.4=
(define (solve f y0 dt)
  (define y (integral dy y0 dt))
  (define dy (@map f y))
  y)
	;;dyを定義していない状態で,dyを使ってyを定義できる。
;delayed-argument
(define (integral delayed-integrand initial-value dt)
  (define int
    (@cons initial-value
           (let1 integrand (force delayed-integrand)
             (@add (@scale integrand dt)
                   int))))
  int)

(@ref (solve (lambda (y) y) 1 0.001) 1000)
;; 73:user> *** ERROR: pair required, but got #<undef>
	;;何でだろう?

;; 75:user> *** ERROR: operation + is not defined between 1 and #<undef>

;;少し調べる
;;相互に呼べないみたい。(from http://d.hatena.ne.jp/yukoba/20080123/p2)

;;letrecを使えば大丈夫
(define (solve f y0 dt)
  (letrec ((y (integral (delay dy) y0 dt))
           (dy (@map f y)))
    y))
    
(@ref (solve (lambda (y) y) 1 0.001) 1000)
;; 83:user> => 2.716923932235896

;; m3.77
;;integer-starting-fromに似たintegralの手続き
(define (integral integrand initial-value dt)
  (@cons initial-value
         (if (@null? integrand)
             @null
             (integral (@cdr integrand)
                       (+ (* dt (@car integrand))
                          initial-value)
                       dt))))

;;これを遅延引数を使った形に変更する。
	;;単純にdelayを加えるだけで良さそう
(define (integral delayed-integrand initial-value dt)
  (@cons initial-value
         (let1 integrand (force delayed-integrand)
             (if (@null? integrand)
                 @null
                 (integral (delay (@cdr integrand))
                           (+ (* dt (@car integrand))
                              initial-value)
                           dt)))))

	;;直接streamを書こうとする時にこのあたりの知識が必要になるのかもしれない
(@ref (solve (lambda (y) y) 1 0.001) 1000)
;; 87:user> => 2.716923932235896


;;m3.78
	;;教科書の図の通りにコードを書けばいいのかな?
(define (solve-2nd a b dt y0 dy0)
  (letrec ((y (integral (delay dy) y0 dt))
           (dy (integral (delay ddy) dy0 dt))
           (ddy (@add (@scale dy a)
                      (@scale y b))))
    y))

;; m3.79
;;教科書のsolveみたいにddyの部分を変更すれば良いんだよね。きっと。
(define (solve-2nd f dt y0 dy0)
  (letrec ((y (integral (delay dy) y0 dt))
           (dy (integral (delay ddy) dy0 dt))
           (ddy (@map f dy y)))
    y))
;;合っているかどうか確かめるにはどうすればいいんだろう?
(stream-ref (solve-2nd (lambda (a b) (+ (* 5 a) (* -4 b))) 0.001 1 1) 2000)
;; http://d.hatena.ne.jp/tostudycs/20071228/1198812138
;;	上のページと結果が同じなので合っていることにしたいとおもいます。


;; m3.80
; Vr = ir * R
; Vl = L * (dil / dt)
; ic = C * (dvc / dt)

(define (RLC R L C dt)
  (lambda (Vc0 Il0)
    (letrec ((Vc (integral (delay (@scale Il (- (/ 1 C)))) Vc0 dt))
             (Il (integral (delay dil) Il0 dt))
             (dil (@add (@scale Il (- (/ R L)))
                        (@scale Vc (/ 1 L)))))
      (@map cons Vc Il))))
(define RLC0 (RLC 1 1 0.2 0.1))
(@>list (RLC0 10 0))
;; 120:user> => ((10 . 0) (10 . 1.0) (9.5 . 1.9) (8.55 . 2.66) (7.220000000000001 . 3.249) (5.5955 . 3.6461) (3.77245 . 3.84104) (1.8519299999999999 . 3.834181) (-0.0651605000000004 . 3.6359559) (-1.8831384500000004 . 3.2658442599999997))