@comment(Hey, EMACS, this is -*- SCRIBE -*- input)
@device(dover)
@make(6001)

@modify(excounter, numbered [Exercise @1], referenced [@1])

@PageHeading(left "6.001 -- Spring Semester 1986",
             center "@Value(Page)",
             right "Problem set 5")

@begin(center)
MASSACHUSETTS INSTITUTE OF TECHNOLOGY
Department of Electrical Engineering and Computer Science
6.001 Structure and Interpretation of Computer Programs
Spring Semester, 1986

Problem Set 5
@end(center)
@blankspace(0.25 in)

@begin(flushleft)
Issued: Tuesday, 4 March 1986

@begin(itemize)
on Wednesday, 12 March 1986
for recitations meeting at 9:00, 10:00, and 11:00

on Friday, 14 March 1986
for recitations meeting at 12:00, 1:00, and 2:00
@end(itemize)

Reading assignment:
@begin(itemize)
Chapter 2 through section 2.4.1

programs (attached): @a[ps5-res.scm], @a[ps5-net.scm], @a[ps5-sets.scm]
@end(itemize)
@end(flushleft)

@b[Quiz announcement:] Quiz 1 is on Wednesday, 19 March 1986.  The
quiz will be held in Walker Memorial Gymnasium (50-340) from 5-7PM xor
7-9PM.  You may take the quiz during either one of these two periods,
but students taking the quiz during the first period will not be
allowed to leave the room until the end of the period.  The quiz will
cover material from the beginning of the semester through this problem
set and through section 2.4.1 of the textbook.


@section(Series-Parallel Resistive Networks)

Louis Reasoner, appalled by his tuition bill, is trying to put his
computer background to good use by implementing an on-line electrical
circuit analyzer that he will rent out to 6.002 students.  Louis's
partner in this scheme is his roommate, Lem E. Tweakit, a 6-1 major
with a flair for hardware.  Lem suggests that they begin with a
program that computes resistances of simple ``linear resistive
networks.''@foot{In this problem set, we use the words ``network'' and
``circuit'' interchangeably.  In the context of Louis's program, there
is no distinction.} These are constructed from primitive elements
called @a[resistors].  A resistor is characterized by a number @a[R]
called the @a[resistance] of the resistor.  It can be depicted as
follows:
@begin(smallfigurebody)

                          o---/\/\/\/\----o
                                  R
@end(smallfigurebody)
For computational purposes, it is also convenient to consider the
@a[conductance] of a resistor, which is defined to be the reciprocal of
the resistance. (Conductance is traditionally denoted by the letter
@a[G].)
@begin(smallfigurebody)

                          o---/\/\/\/\----o
                                G = 1/R
@end(smallfigurebody)

A resistor is the simplest example of a kind of element called a
@i[two-terminal network], i.e., a network that has exactly two terminals to
which other objects can be connected:
@begin(smallfigurebody)
                               --------
                               |      |
                          o----|  N   |----o
                               |      |
                               --------

@end(smallfigurebody)

Networks can be combined by attaching their terminals together.  A
network has a resistance (and conductance) that is determined by the
resistances of its parts and the ways in which they are
interconnected.  Louis's and Lem's initial system will provide two
basic methods of combination for constructing two-terminal networks
from simpler two-terminal networks.  The first method is called @a[series]
combination:
@begin(smallfigurebody)
                       --------       --------
                       |      |       |      |
               o-------|  A   |-------|  B   |--------o
                       |      |       |      |
                       --------       --------

                             R = R  +  R
                                  A     B
@end(smallfigurebody)
The combined resistance of two networks connected in series is the sum
of the resistances.

The second method is @a[parallel] combination: 
@begin(smallfigurebody)
                    --------
                    |      |
               -----|  A   |-----                   
               |    |      |    |                   
               |    --------    | 
        o------|                |-----o         G = G  +  G
               |                |                    A     B
               |    --------    |                    
               |    |      |    |                     
               -----|  B   |-----     
                    |      |         
                    --------              
@end(smallfigurebody)                                            
The combined conductance of two networks joined in parallel is the sum
of the conductances of the pieces.

After a few hours of work, Louis and Lem have quite an
elegant program that handles such series and parallel
combinations.@foot{Networks that can be constructed as series and
parallel combinations of primitive two-terminal elements are called
@i[series-parallel networks].} The program is provided in the first
appendix to this handout, labeled @a[ps5-res.scm].

You should read through this code now to get some idea of how it
works.  There are constructors @a[make-resistor], @a[make-series], and
@a[make-parallel], and an operation called @a[resistance] that
computes the resistance of a network by finding the resistances of the
parts of a network and combining them appropriately.

Louis and Lem test their program by computing the resistance of the
following network:
@begin(smallfigurebody)

               R=10         R=30
    o---------\/\/\/-------\/\/\/--------o
         |                           |
         |           R=20            |
         |    -----\/\/\/-----       |
         -----|              |--------
              -----\/\/\/-----
                     R=40
@end(smallfigurebody)
They type:
@begin(programexample)

(define r1 (make-resistor 10))
(define r2 (make-resistor 30))
(define r3 (make-resistor 20))
(define r4 (make-resistor 40))

(define N
  (make-parallel (make-series r1 r2)
                 (make-parallel r3 r4)))

-->(resistance N)
10.000
@end(programexample)
Indeed, the answer is correct (as Lem verifies).

@begin(exercise)
Consider the data structure representing the network @a[N].
@begin(alphaenumerate)
Draw the box-and-pointer structure that represents the object @a[N].

How many times was @a[resistance] called in computing the resistance of
@a[N]?  What were the arguments to @a[resistance] for each call?  (To
specify the arguments, you can sketch the part of the network that
each argument represents, or you can give a description in English,
e.g., ``@a[R3] in parallel with @a[R4]''.)

@end(alphaenumerate)
@end(exercise)

@paragraph(L-extensions)

Given a 2-terminal network @a[B], we can form a new two-terminal
network by attaching an ``L-section,'' which is itself constructed
from two two-terminal networks @a[S] and @a[P] as follows:
@begin(smallfigurebody)
            -----
            |    |
    o-------| S  |-------------------
            |    |       |          |
            ------     ------     ------
                       |    |     |    |
                       | P  |     | B  |
                       |    |     |    |
                       ------     ------
                         |          |
    o--------------------------------
@end(smallfigurebody)
This operation is called ``L-extension'' of a ``base'' @a[B] by a ``series
part'' @a[S] and a ``parallel part'' @a[P].

@begin(exercise)
Write a procedure @a[L-extend] that takes three two-terminal networks --
@a[base], @a[series-part], and @a[parallel-part] -- and combines them
using @a[make-series] and @a[make-parallel] to produce the extended
network as shown above.
@end(exercise)

@begin(exercise)
Use your @a[L-extend] procedure to make a new network that extends the
network @a[N] from Exercise 1 (as the base) by a 10-ohm resistor (the
series part) and another 10-ohm resistor (the parallel part).

Verify that the resulting network has a resistance of 15 ohms.  Show
the expressions that you typed in order to generate the network and to
check its resistance.
@end(exercise)


By repeatedly L-extending a base by a given series and parallel
part, we obtain a circuit called a ``ladder.''  The following diagram
shows a 4-stage ladder.
@begin(smallfigurebody)

   o-----S---------S-------S-------S---------
              |        |       |       |    |
              P        P       P       P    B
              |        |       |       |    |
   o----------------------------------------- 

@end(smallfigurebody)

Louis decides that he can easily implement a ladder by making use of
his @a[L-extend] procedure, together with the @a[repeated] procedure
below:

@begin(programexample)
(define (repeated f n)
  (lambda (x)
    (if (= n 0)
        x
        ((repeated f (-1+ n)) (f x)))))
@end(programexample)

He defines the following procedure to construct a ladder with a
given number of stages:

@begin(programexample)
(define (ladder-extension stages base series-part parallel-part)
  ((repeated @i[<EXP-1>] stages) @i[<EXP-2>]))
@end(programexample)

@begin(exercise)
Complete the @a[ladder-extension] procedure.  What are the missing
expressions
@i[<EXP-1>] and @i[<EXP-2>]?
@end(exercise)

@begin(exercise)
Louis and Lem demonstrate their system to Ben Bitdiddle.  As an
example, they try to compute the resistance of a long ladder.  To
their surprise, they find that although the program gets correct
answers, it seems to run more slowly than before.

Taking a careful look at the code, they find that Louis has changed
the definition of @a[resistance-parallel] so that it now reads:
@begin(programexample)
(define (resistance-parallel ckt)
  (/ (* (resistance (left-branch ckt))
        (resistance (right-branch ckt)))
     (+ (resistance (left-branch ckt))
        (resistance (right-branch ckt)))))
@end(programexample)
Explain why this change makes the program run so slowly.  As an
example, consider a ladder in which each of the series, parallel, and
base pieces is a simple resistor.  If the ladder has @a[N] stages:
@begin(alphaenumerate)
How many resistors are contained in the ladder?

In computing the resistance of the ladder, how many times will the
procedure @a[resistance-resistor] be run if the system uses the
original version of the @a[resistance-parallel] procedure?

After Louis installs the new version of @a[resistance-parallel], how
many times will @a[resistance-resistor] be run in computing the resistance
of the @a[N]-stage ladder?  (You should be able to obtain an exact answer
in terms of @a[N].  However, partial credit will be given for good partial
answers.  Show your work.)

How has Louis's change affected the running time of the system?
(E.g., slowed it down by a constant factor?  slowed it down
quadratically? slowed it down exponentially?)
@end(alphaenumerate)
@end(exercise)

@section(General Networks)

After developing the series-parallel resistors program our friends
discover that not all networks made up only of resistors consist only
of series or parallel combinations of resistors.  Consider, for
example the following ``bridge'' network made up of five resistors:

@begin(example)
             a
          --------
          |      |
          R1     R2
          |      |
         c---R5---d
          |      |
          R3     R4
          |      |
          --------
             b
@end(example)

(Points like @a[a], @a[b], @a[c], and @a[d] to which the terminals of
the resistors are connected are called nodes.  For example, node @a[c]
represents the connection among @a[R1], @a[R5], and @a[R3].)

In order that networks may be connected as elements in bigger
networks, networks may have terminals like elements.  Assume that we
associate terminals of the network with nodes @a[a] and @a[b]:

@begin(example)
             a
 O----------------
          |      |
          R1     R2
          |      |
         c---R5---d                    Network 1
          |      |
          R3     R4
          |      |
 O----------------
              b
@end(example)

With respect to these terminals the network cannot be construed as a
series or parallel combination of resistors, although it is equivalent
to a single resistor (wait for 6.002 to see this).  But note that the
network can be construed as a series-parallel combination with respect
to a pair of terminals associated with nodes @a[c] and @a[d]:

@begin(example)
             a
          --------
          |      |
          R1     R2
         c|      |d
 O-----------R5---------               Network 2
          |      |     |
          R3     R4    |
          |      |     |
          --------     |
             b         |
                       |
 O----------------------
@end(example)

In fact, with respect to these terminals the network
can be represented as:

@begin(example)
(define network-sp
  (make-parallel (make-parallel r5 (make-series r1 r2))
                 (make-series r3 r4)))
@end(example)

To describe these more general networks we need a
more powerful language.  For example, we can describe any
network as a combination of connections of parts to nodes.  We will
use the following code to construct a representation of the bridge
network, with terminals associated with nodes @a[c] and @a[d].  Nodes,
like resistors, are objects so we must have a constructor,
@a[make-node], for them too.  @a[Connect] is a constructor for
connections.  @a[Make-net] is a constructor for general networks.  The
support for these new data types is supplied in the file
@a[ps5-net.scm].  @a[Make-net] takes two arguments, a set of nodes to
be used as terminals and a set of connections of elements to nodes:

@begin(programexample)
(define network-2
  (make-net (make-set c d) ; nodes c, d are associated with terminals
    (make-set
       (connect r1 a c)    ; resistor r1 is connected to nodes a and c
       (connect r2 a d)
       (connect r3 c b)
       (connect r4 d b)
       (connect r5 c d))))
@end(programexample)

Given such a description of a general network, it is useful to be able
to answer such questions as:  Is @a[R1] in parallel with @a[R3]?  Is
@a[R3] in series with @a[R4]?  In English we would say that two
elements are in parallel if and only if each terminal of each element
is connected to a terminal of the other.  Translating the definition
of parallel elements into Scheme we could write:

@begin(example)
(define (in-parallel? part1 part2 network)
  (equal-set? (nodes part1 network)
              (nodes part2 network)))
@end(example)

Where @a[equal-set?] determines if two sets have precisely the same
elements and where @a[nodes] finds the set of nodes associated
with terminals of the given part in the given network.

@begin(exercise)
Given the implementation of general networks supplied in @a[ps5-net.scm] and
the set procedures supplied in @a[ps5-sets.scm] write definitions for
@a[equal-set?] and for @a[nodes] that will allow you to test for
parts connected in parallel.  Demonstrate that your procedures work by
testing them independently and also demonstrate that @a[in-parallel?]
works with your definitions on some simple networks.
@end(exercise)

In English we would say that two elements are in series if and only if
there is a node to which they are both connected that is neither a
terminal of the network nor connected to any other element.
Translating the definition of parallel elements into Scheme we could
write:

@begin[programexample]
(define (in-series? part1 part2 network)
  (not (empty-set?
	(difference-set
	 (intersection-set (nodes part1 network) (nodes part2 network))
	 (union-set (reduce-set union-set
		       (map-set (lambda (part) (nodes part network))
			  (difference-set (all-parts network)
					  (make-set part1 part2))))
		    (terminals network))))))
@end[programexample]

@begin(exercise)
Write definitions for the set procedures used in the definition of the
@a[in-series?] procedure above that are not supplied in the file
@a[ps5-sets.scm] (attached to this problem set).  Also missing are a few 
procedures like @a[all-parts] that gets all of the parts in a network.
Demonstrate that your
procedures work by testing them independently and  also demonstrate
that the procedure @a[in-series?] works using your definitions by
testing it on some simple networks.
@end(exercise)

@begin(exercise)
Optional:  Caution -- this is very hard problem.  You must be sure
that all your other homework for all of your other classes is done
before you begin to attack this problem.

Given a general network and two nodes you are to produce a program
that, if possible, produces a series-parallel network that is
equivalent to the given general network with respect to those nodes.
For example, given the object named @a[network-2] described above your
program should return the object named @a[network-sp] described above.

If it is not possible to construct such a description of the given
network, your program should return @a[false].
@end(exercise)

@newpage()
@begin(programexample)
@include(ps5-res.SCM)
@end(programexample)
@newpage()
@begin(programexample)
@include(ps5-net.SCM)
@end(programexample)
@newpage()
@begin(programexample)
@include(ps5-sets.SCM)
@end(programexample)
@newpage()

