問題3-73〜76
「信号としてのストリーム」というトピックです。電気回路の仕組みについては興味はあるものの、なかなか手をつけられていないのが現状です。そのため、問題を一応は解いてはみましたが、問題に書かれていることをそのままコードとして表現しただけで、その正否については検証することはできませんでした。
問題3-73。RC回路を作成します。まず、回路をモデル化するRC手続きを作り、そこに電流を表すストリームを渡すことで、電圧のストリームが出力されます。
(define (RC r c dt) (define (make-output input-stream init-v) (add-streams (scale-stream input-stream r) (integral (scale-stream input-stream (/ 1 c)) init-v dt))) make-output) (define RC1 (RC 5 1 0.5)) (display-stream-iter (RC1 integers 10) 10) ;=>15 ;=>20.5 ;=>26.5 ;=>33.0 ;=>40.0 ;=>47.5 ;=>55.5 ;=>64.0 ;=>73.0 ;=>82.5
問題3-74。ここからは零交差(zero-crossing)に関する問題になります。前の信号と今の信号を比べて、ゼロのラインをまたがっているかどうかを調べる点がキーになります。前後の入力信号を調べて、出力信号を生成する手続きsign-change-detectorは以下のように定義しました。
(define (sign-change-detector current last) (cond ((and (< current 0) (> last 0)) -1) ((and (> current 0) (< last 0)) 1) (else 0)))
Eva Lu Atorのzero-crossingの空欄を補うと、以下のようになります。sense-dataを一個ずらしてmapしてやればよさそうです。
(define zero-crossings (stream-map sign-change-detector sense-data (cons-stream 0 sense-data)))
問題3-75。入力信号を平滑化するロジックを組み込みます。Louisの実装の何が悪いのかがわからなかったので、ここのブログのエントリーを参考にしました。平滑化計算には、前後の入力信号をそのまま使いますが、そのあとのsign-change-detectorでは、前後の平滑化された値を渡す必要がありそうです。Louisの実装では、一つ前の平滑化された値が使われていないことになります。以下のようにしてやることで、必要な情報がmake-zero-crossingに渡せることになります。
(define (make-zero-crossings input-stream last-value last-avpt) (let ((avpt (/ (+ (stream-car input-stream) last-value) 2))) (cons-stream (sign-change-detector avpt last-avpt) (make-zero-crossings (stream-cdr input-stream) (stream-car input-stream) avpt))))
問題3-76。smooth手続きを定義して、平滑化ロジックを外部に出します。
(define (smooth input-stream) (cons-stream (/ (+ (stream-car input-stream) (stream-car (stream-cdr input-stream))) 2) (smooth (stream-cdr input-stream))))
これを使って、(cons-stream 0 smooth)というストリームを作れば、入力信号が平滑化されたバージョンのストリームを表現することができます。これをmake-zero-crossingに組み込みます。
(define (make-zero-crossings input-stream last-value smooth last-smooth) (cons-stream (sign-change-detector (stream-car smooth) last-smooth) (make-zero-crossings (stream-cdr input-stream) (stream-car input-stream) (stream-cdr smooth) (stream-car smooth)))) (define zero-crossings (make-zero-crossings sense-data 0 (cons-stream 0 (smooth sense-data)) 0))
last-smoothを排除してしまいたいところですが、どうも上手くいきませんでした。定義されていない部分のsense-dataがsmoothの中でstream-cdrされてしまうのが原因だと考えられます。