問題3.73-3.76

全然毎日出来てないですが、とりあえずストリーム続きです。
信号処理をストリームでモデル化するようです。
しばらく別のことをやらなければならないので、飛び飛びの更新か、毎日1、2問の更新になるかもです。

3.73

時間空けるとよく分からなくなりますね。一気にやった方がやっぱり進みが早いような気がします。頭に残るかどうかはともかく。


信号流れ図どおりに書くとたぶんこんな感じ。

(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 (scale-stream i r)
                 (integral (scale-stream i (/ 1.0 c)) v0 dt))))

3.74

(define zero-crossings
  (stream-map sign-change-detector sense-data (stream-cdr sense-data)))

と思ったけど、これだと一個ずれるので、

(define zero-crossings
  (stream-map sign-change-detector (cons-stream 0 sense-data) sense-data))

こうですね。たぶん。

3.75

Louisのコードでは、平滑化した値と生の信号の値との平均によって新しい平滑化の値を得ているが、本来ならば生の信号の値同士の平均を取らなければいけないはず。次のように変更する。

(define (make-zero-crossings input-stream last-input last-avpt)
  (let ((avpt (/ (+ (stream-car input-stream) last-input) 2)))
    (cons-stream (sign-change-detector avpt last-avpt)
                 (make-zero-crossings (stream-cdr input-stream)
                                      (stream-car input-stream)
                                      avpt))))

3.76

Eva Luからのダメ出し。3.75は確かに部品化できてませんし、抽象もうまくないです。これを改善します。

(define (smooth s)
  (stream-map (lambda (x y) (/ (+ x y) 2.0)) s (stream-cdr s)))

> (define s (smooth integers))
> (disp-stream-n s 10)
(1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5 10.5)

smoothでストリームの連続する二つの要素の平均のストリームを生成します。

(define (make-zero-crossings input)
  (stream-map sign-change-detector (smooth (cons-stream 0 input)) (smooth input)))

smoothを使うとmake-zero-crossingsが簡潔にかけます。せっかくなのでsign-change-detectorを書いて動かしてみます。xが前の要素、yが現在の要素ということにして書きます。

(define (sign-change-detector x y)
  (cond ((and (>= x 0) (>= y 0)) 0)
        ((and (>= x 0) (< y 0)) -1)
        ((and (< x 0) (>= y 0)) 1)
        ((and (< x 0) (< y 0)) 0)))

> (define (make-stream . args)
    (if (null? args)
        the-empty-stream
        (cons-stream (car args) (apply make-stream (cdr args)))))
> (define s (make-stream 1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2 3 4))
> (define cs (make-zero-crossings s))
> (disp-stream-n s 11)
(1 2 1.5 1 0.5 -0.1 -2 -3 -2 -0.5 0.2)
> (disp-stream-n cs 11)
(0 0 0 0 0 -1 0 0 0 0 1)

で、教科書の例どおりに動いていると分かります。

きりがいいので今日はここまで。