sicp-ex-3.80



<< Previous exercise (3.79) | Index | Next exercise (3.81) >>


meteorgan

  
  
 (define (RLC R L C dt) 
   (define (rcl vc0 il0) 
     (define vc (integral (delay dvc) vc0  dt)) 
     (define il (integral (delay dil) il0 dt)) 
     (define dvc (scale-stream il (- (/ 1 C)))) 
     (define dil (add-streams (scale-stream vc (/ 1 L)) 
                              (scale-stream il (- (/ R L))))) 
     (define (merge-stream s1 s2) 
       (cons-stream (cons (stream-car s1) (stream-car s2)) 
                    (merge-stream (stream-cdr s1) (stream-cdr s2)))) 
     (merge-stream vc il)) 
   rcl) 

why not simply (cons vc il) at the end of the procedure instead of merging? the exercise says "a pair of the streams".

If we use oscillometer, then vc and il should be displayed independently. IMHO (cons vc il) and merge-stream version are both reasonable.



  
 We could first compute the integral then scale the stream 
  
 (define (RLC R L C dt) 
   (define (proc vc0 il0) 
     (define vc 
       (scale-stream (integral (delay il) 
                               (* (- C) vc0) dt) 
                     (/ -1 C))) 
     (define il (integral (delay dil) il0 dt)) 
     (define dil (add-streams (scale-stream il (/ (- R) L)) 
                              (scale-stream vc (/ 1 L)))) 
     (stream-map cons vc il)) 
   proc) 
  

Two quick points:

1) I interpreted the "pair of streams" as a simple consing instead of a mapping/merging (which produced a "stream of pairs".

2) More importantly, the hack mentioned in 4.1.6 seems necessary to run this in the #lang sicp environment in Racket so I have written out my solution in case you find too that your solution doesnt work in Racket...

Now the solution doesnt really need the definitions of dvC and diL so four lines could be removed from below code but I think the longer code is clearer...

 (define (RLC R L C dt) 
   (lambda (vC-init iL-init) 
     (let ((vC '*unassigned*) 
           (iL '*unassigned*) 
           (dvC '*unassigned*) 
           (diL '*unassigned*)) 
       (set! vC (d-integral (delay dvC) vC-init dt)) 
       (set! iL (d-integral (delay diL) iL-init dt)) 
       (set! dvC (stream-map 
                  (lambda (x) 
                    (/ (- x) C)) 
                  iL)) 
       (set! diL (stream-map 
                  (lambda (x y) 
                    (+ (/ x L) 
                       (/ (* (- R) y) L))) 
                  vC 
                  iL)) 
       (cons vC iL)))) 

Thank you so much karthikk. I met the same issue in the #lang sicp env in Racket.



Here is my solution. The exercise asks for pair of streams instead of stream of pairs. Therefore, I just cons-ed the two streams instead of doing mapping on two streams.

 (define (RLC R L C dt) 
   (lambda (vC0 iL0) 
     (define vC (integral (delay dvC) vC0 dt)) 
     (define iL (integral (delay diL) iL0 dt)) 
     (define diL (add-streams (scale-stream vC (/ 1 L)) 
                              (scale-stream iL (/ (- R) L)))) 
     (define dvC (scale-stream iL (/ -1 C))) 
     (cons vC iL))) 

While I ultimately ended up with Shawn's solution, I initially came up with this solution which has some cool Time Lord shit in it.

I wanted to delay the argument to scale-streams to create dvC but since scale-streams doesn't have a force I just delayed the entire scaling operation. Then the line before dvC is defined I use it as an argument, but I must delay it. However it contain's a delayed operation itself I must wrap that in a force call, which is wrapped in a delay! Pretty cool that you can do this, and while I did get to a simpler solution it's easy to see how combining strict and lazy evaluation can become problematic.

 (define (RLC R L C dt) 
   (define (RLC-proc vC0 iL0) 
     (define vC (integral-delay-from (delay (force dvC)) vC0 dt)) 
     (define dvC (delay (scale-stream iL (/ -1 C)))) 
     (define iL (integral-delay-from (delay diL) iL0 dt)) 
     (define diL (add-streams (scale-stream vC (/ 1 L)) 
                              (scale-stream  iL (/ (* -1 R) L)))) 
     (cons vC iL)) 
   RLC-proc) 
  

An alternative approach would be to derive an equivalent second order differential equation, solve it and differentiate to get the stream for the other variable