Collections of Structures with Cycles

Many objects in our world are related with each other in a circular manner. We have parents; our parents have children. A computer may connect to another computer, which in turn may connect to the first. And we have seen data definitions that refer to each other. Since data represents information about real-world objects, we will encounter situations that call for the design of a class of structures with a circular relationship. In the past, we have skirted the issue, or we used a trick to represent such collections. The trick is to use an indirection. For example, in section~#sectraversegraph1#59206>, we associated each structure with a symbol, kept a table of symbols and structures around, and placed symbols into structures. Then, when we needed to find out whether some structure refers to another, we extracted the relevant symbol and looked in the table to find the structure for the symbol. While this use of indirection allows us to represent structures with mutual references or structures in a cyclic relationship, it also leads to awkward data representations and programs. This section demonstrates that we can simplify the representation of collections with structure mutation. To make this idea concrete, we discuss two examples: family trees and simple graphs. Consider the case of family trees. Thus far, we have used two kinds of family trees to record family relationships. The first is the ancestor tree; it relates people to their parents, grandparents, and so on. The second is the descendant tree; it relates people to their children, grandchildren, and so on. In other words, we have avoided the step of combining the two family trees into one, the way it is done in the real world. The reason for skirting the joint representation is also clear. Translated into our data language, a joint tree requires that a structure for a father should contain the structures for his children, and each of the child structures should contain the father structure. In the past, we couldn't create such collections of structures. With structure mutations, we can now create them. Here is structure definition that makes this discussion concrete:
<#59211#>(define-struct<#59211#> <#59212#>person<#59212#> <#59213#>(name<#59213#> <#59214#>social<#59214#> <#59215#>father<#59215#> <#59216#>mother<#59216#> <#59217#>children))<#59217#>
The goal is to create family trees that consist of <#70443#><#59221#>person<#59221#><#70443#> structures. A person structure has five fields. The contents of each is specified by the following data definition:
An <#70444#><#59223#>family tree node<#59223#><#70444#> (<#70445#><#59224#>ftn<#59224#><#70445#>) is either
  1. <#70446#><#59226#>false<#59226#><#70446#> or
  2. a <#70447#><#59227#>person<#59227#><#70447#>.
A <#70448#><#59229#>person<#59229#><#70448#> is a structure:

<#72107#><#70449#><#59230#>(make-person<#59230#>\ <#59231#>n<#59231#>\ <#59232#>s<#59232#>\ <#59233#>f<#59233#>\ <#59234#>m<#59234#>\ <#59235#>c)<#59235#><#70449#><#72107#> where <#70450#><#59236#>n<#59236#><#70450#> is a symbol, <#70451#><#59237#>s<#59237#><#70451#> is number, <#70452#><#59238#>f<#59238#><#70452#> and <#70453#><#59239#>m<#59239#><#70453#> are <#70454#><#59240#>ftn<#59240#><#70454#>s, and <#70455#><#59241#>c<#59241#><#70455#> is a <#70456#><#59242#>(listof<#59242#>\ <#59243#>person)<#59243#><#70456#>.

As usual, the <#70457#><#59245#>false<#59245#><#70457#> in the definition of <#70458#><#59246#>family<#59246#><#59247#> <#59247#><#59248#>tree<#59248#>\ <#59249#>node<#59249#><#70458#>s represents missing information about a portion of the family tree. Using <#70461#><#59254#>make-person<#59254#><#70461#> alone, we cannot establish the mutual reference between a family tree node for a father and his child. Suppose we follow an ancestoral tree strategy, that is, we create the structure for the father first. Then we can't add any child to the <#70462#><#59255#>children<#59255#><#70462#> field, because, by assumption, the corresponding structure doesn't exist yet. Conversely, if we follow a descendant tree strategy, we first create a structure for all of a father's children but those structures can't contain any information about the father yet.
rawhtml69 <#59256#>Figure: Adding a child<#59256#>
What this suggests is that a simple constructor for this kind of data isn't really enough. Instead, we should define a <#70463#><#59258#>GENERALIZED CONSTRUCTOR<#59258#><#70463#> that not only creates a <#70464#><#59259#>person<#59259#><#70464#> structure but also initializes it properly when possible. To develop this function, it is best to follow the real world where upon the birth of a child, we create a new entry in the family tree, record the child's parents, and record in the existing parents' entries that they have a newborn. Here is the specification for just such a function:
<#72109#>;; <#70465#><#59264#>add-child!<#59264#> <#59265#>:<#59265#> <#59266#>symbol<#59266#> <#59267#>number<#59267#> <#59268#>person<#59268#> <#59269#>person<#59269#> <#59270#><#59270#><#59271#>-;SPMgt;<#59271#><#59272#><#59272#> <#59273#>person<#59273#><#70465#><#72109#>
<#72110#>;; to construct a <#70466#><#59274#>person<#59274#><#70466#> structure for a newborn <#72110#> 
<#72111#>;; effect: to add the new structure to the cildren of <#70467#><#59275#>father<#59275#><#70467#> and <#70468#><#59276#>mother<#59276#><#70468#><#72111#> 
<#59277#>(define<#59277#> <#59278#>(add-child!<#59278#> <#59279#>name<#59279#> <#59280#>soc-sec<#59280#> <#59281#>father<#59281#> <#59282#>mother)<#59282#> <#59283#>...)<#59283#> 
Its task is to create a new structure for a newborn child and to add the structure to an existing family tree. The function consumes the child's name, social security number, and the structures representing the father and the mother. The first step of the design of <#70469#><#59287#>add-child!<#59287#><#70469#> is to create the new structure for the child:
<#59292#>(d<#59292#><#59293#>efine<#59293#> <#59294#>(add-child!<#59294#> <#59295#>name<#59295#> <#59296#>soc-sec<#59296#> <#59297#>father<#59297#> <#59298#>mother)<#59298#>
  <#59299#>(l<#59299#><#59300#>ocal<#59300#> <#59301#>((d<#59301#><#59302#>efine<#59302#> <#59303#>the-child<#59303#> 
            <#59304#>(make-person<#59304#> <#59305#>name<#59305#> <#59306#>soc-sec<#59306#> <#59307#>father<#59307#> <#59308#>mother<#59308#> <#59309#>empty)))<#59309#> 
    <#59310#>...))<#59310#> 
This covers the first part of the contract. By naming the structure in a <#59314#>local<#59314#>-expression\ we can mutate it in the body of the expression. The second step of the design of <#70470#><#59315#>add-child!<#59315#><#70470#> is to add a body to the <#59316#>local<#59316#>-expression\ that performs the desired effects:
<#59321#>(d<#59321#><#59322#>efine<#59322#> <#59323#>(add-child!<#59323#> <#59324#>name<#59324#> <#59325#>soc-sec<#59325#> <#59326#>father<#59326#> <#59327#>mother)<#59327#>
  <#59328#>(l<#59328#><#59329#>ocal<#59329#> <#59330#>((d<#59330#><#59331#>efine<#59331#> <#59332#>the-child<#59332#> 
            <#59333#>(make-person<#59333#> <#59334#>name<#59334#> <#59335#>soc-sec<#59335#> <#59336#>father<#59336#> <#59337#>mother<#59337#> <#59338#>empty)))<#59338#> 
    <#59339#>(b<#59339#><#59340#>egin<#59340#> 
      <#59341#>(set-person-children!<#59341#> <#59342#>father<#59342#> 
                            <#59343#>(cons<#59343#> <#59344#>the-child<#59344#> <#59345#>(person-children<#59345#> <#59346#>father)))<#59346#> 
      <#59347#>(set-person-children!<#59347#> <#59348#>mother<#59348#> 
                            <#59349#>(cons<#59349#> <#59350#>the-child<#59350#> <#59351#>(person-children<#59351#> <#59352#>mother)))<#59352#> 
      <#59353#>the-child)))<#59353#> 
Since there are two specified effects and since the purpose statement also specifies a result, the body of the <#59357#>local<#59357#>-expression\ is a <#59358#>begin<#59358#>-expression\ with three subexpressions. The first mutates <#70471#><#59359#>father<#59359#><#70471#>, adding <#70472#><#59360#>the-child<#59360#><#70472#> to the list of children. The second mutates <#70473#><#59361#>mother<#59361#><#70473#> in an analogous manner. The last one produces the desired result. Figure~#figbuildafamily#59362> illustrates the evaluation of an application of <#70474#><#59363#>add-child!<#59363#><#70474#>:
<#59368#>(add-child!<#59368#> <#59369#>'<#59369#><#59370#>Ludwig<#59370#> <#59371#>3<#59371#>
            <#59372#>(make-person<#59372#> <#59373#>'<#59373#><#59374#>Adam<#59374#> <#59375#>...<#59375#> <#59376#>...<#59376#> <#59377#>...)<#59377#> 
            <#59378#>(make-person<#59378#> <#59379#>'<#59379#><#59380#>Eve<#59380#> <#59381#>...<#59381#> <#59382#>...<#59382#> <#59383#>...))<#59383#> 
The top-half shows the new structure for <#70475#><#59387#>'<#59387#><#59388#>Ludwig<#59388#><#70475#> and how it refers to the <#70476#><#59389#>father<#59389#><#70476#> and <#70477#><#59390#>mother<#59390#><#70477#> structures. Just as in section~#secstructinstruct#59391>, the picture uses arrows to relate the nodes of a family tree. But now this choice isn't just a convenience, it is dictated by necessity. As the bottom half of the figure shows, the structure mutation of <#70478#><#59392#>add-child!<#59392#><#70478#> modify the <#70479#><#59393#>children<#59393#><#70479#> fields of the <#70480#><#59394#>father<#59394#><#70480#> and <#70481#><#59395#>mother<#59395#><#70481#> structure. They add an additional item to the list in this field, and this new item is the structure for <#70482#><#59396#>'<#59396#><#59397#>Ludwig<#59397#><#70482#>. Without arrows, we wouldn't be able to draw this constellation of structures because it is impossible to draw the two structures as nested in each other. With <#70483#><#59398#>add-child!<#59398#><#70483#> we can create family trees, one child at a time. What we need to learn is to design functions that process this new class of family trees. In this case, we can almost always pick one of the two views that we used before: the ancestor family tree or the descendant family tree. Either view just ignores certain fields in the structures. Once we have chosen a view, we design the desired functions following the known recipes. Even if we decide to use the bi-directional relations in the new family tree representation, designing a function is usually simply a matter of formulating those auxiliary functions that correspond to the real-world family relationships and to compose them properly. The following few exercises demonstrate these principles.
<#59401#>Exercise 43.2.1<#59401#> Modify <#70484#><#59403#>add-child!<#59403#><#70484#> so that it has the following contract:
<#72112#>;; <#70485#><#59408#>add-child!<#59408#> <#59409#>:<#59409#> <#59410#>symbol<#59410#> <#59411#>number<#59411#> <#59412#>ftn<#59412#> <#59413#>ftn<#59413#> <#59414#><#59414#><#59415#>-;SPMgt;<#59415#><#59416#><#59416#> <#59417#>person<#59417#><#70485#><#72112#>
The function otherwise behaves just like the original version. Once we have the modified function, there is no need for <#70486#><#59421#>make-person<#59421#><#70486#> any more. We can create all forms of <#70487#><#59422#>person<#59422#><#70487#> structures with <#70488#><#59423#>add-child!<#59423#><#70488#> directly. Transliterate the family tree in figure~#figfamilyA#59424> into the new representation; use the new modified <#70489#><#59425#>add-child!<#59425#><#70489#> function exclusively.~ external Solution<#70490#><#70490#> <#59431#>Exercise 43.2.2<#59431#> Develop the function <#70491#><#59433#>how-many-ancestors<#59433#><#70491#>, which consumes a family tree node and determines how many ancestors there are. The node itself counts as an ancestor.~ external Solution<#70492#><#70492#> <#59439#>Exercise 43.2.3<#59439#> Develop <#70493#><#59441#>how-many-descendants<#59441#><#70493#>, which consumes a family tree node and determines how many descendants there are. The node itself counts as a descendant.~ external Solution<#70494#><#70494#> <#59447#>Exercise 43.2.4<#59447#> Develop <#70495#><#59449#>names-of-cousins<#59449#><#70495#>. The function consumes a <#70496#><#59450#>person<#59450#><#70496#> and produces the names of the cousins. <#59451#>Hints:<#59451#> \ (1) Don't forget to use Scheme's built-in functions for processing lists. (2) Use a sufficiently large portion of your own family tree to test the functions. (3) For the testing step, compare the names of the results of the auxiliary functions with the expected results. Because the structures are mutually referential, it is difficult to compare them automatically. Alternatively, use <#70497#><#59452#>eq?<#59452#><#70497#>, Scheme's intensional equality predicate, to compare two structures. Why does this work?~ external Solution<#70498#><#70498#>
In sections~#sectraversegraph1#59460> and~#seclossgenerative#59461>, we encountered the problem of representing and traversing graphs. Recall that a graph is a collection of nodes and connections between nodes. The graph traversal problem is to determine whether there is a route from a node labeled <#70499#><#59462#>orig<#59462#><#70499#> to one called <#70500#><#59463#>dest<#59463#><#70500#>. In a simple graph, each node has exactly one one-way connection to another node. Originally, we represented a graph as a list of named nodes. If one node was connected to another, the corresponding structure for the first node contained the name of the second node, not the node itself. Exercise~#exfindroutevector#59464> introduced a vector-based representation. Still, all of our representations used the indirection trick, so that if we wanted to move from one node to another, we first had to lookup the connection in a table. Using structure mutation, we can eliminate this indirection and create structures for nodes that contain each other, even if the gaph contains a cycle. To understand how this works in a concrete manner, let's discuss how to model simple graphs such as those in figure~#figsimgraph#59465> and how to design programs that find routes through such graphs. First, we need a structure definition for nodes:
<#59470#>(define-struct<#59470#> <#59471#>node<#59471#> <#59472#>(name<#59472#> <#59473#>to))<#59473#>
The <#70501#><#59477#>name<#59477#><#70501#> field records the name of the node, and the <#70502#><#59478#>to<#59478#><#70502#> field specifies to which other node it is connected. Second, we need a data definition:
An <#70503#><#59480#>simple graph node<#59480#><#70503#> (<#70504#><#59481#>node<#59481#><#70504#>) is a structure:

<#72113#><#70505#><#59482#>(make-node<#59482#>\ <#59483#>n<#59483#>\ <#59484#>t)<#59484#><#70505#><#72113#> where <#70506#><#59485#>n<#59485#><#70506#> is a symbol and <#70507#><#59486#>t<#59486#><#70507#> is a <#70508#><#59487#>node<#59487#><#70508#>.

The data definition is unusual in that it is self-referential, but it doesn't consist of several clauses. This immediately raises the question of how we can construct a node that complies with this definition. Clearly, applying <#70509#><#59489#>make-node<#59489#><#70509#> doesn't work; instead, we need to define a generalized constructor that immediately sets the <#70510#><#59490#>to<#59490#><#70510#> field of a node. The generalized constructor consumes the atomic data for a <#70511#><#59491#>node<#59491#><#70511#> structure and constructs a legal node structure from there:
<#72114#>;; <#70512#><#59496#>create-node<#59496#> <#59497#>:<#59497#> <#59498#>symbol<#59498#> <#59499#><#59499#><#59500#>-;SPMgt;<#59500#><#59501#><#59501#> <#59502#>node<#59502#><#70512#><#72114#>
<#72115#>;; to create a simple legal graph node with <#70513#><#59503#>a-name<#59503#><#70513#> in the name field<#72115#> 
<#59504#>(d<#59504#><#59505#>efine<#59505#> <#59506#>(create-node<#59506#> <#59507#>a-name)<#59507#> 
  <#59508#>(local<#59508#> <#59509#>((define<#59509#> <#59510#>the-node<#59510#> <#59511#>(make-node<#59511#> <#59512#>a-name<#59512#> <#59513#>false)))<#59513#> <#59514#>...))<#59514#> 
The natural candidate to place into the <#70514#><#59518#>to<#59518#><#70514#> field is the node itself. In other words, the generalized constructor creates a node that contains itself:
<#72116#>;; <#70515#><#59523#>create-node<#59523#> <#59524#>:<#59524#> <#59525#>symbol<#59525#> <#59526#><#59526#><#59527#>-;SPMgt;<#59527#><#59528#><#59528#> <#59529#>node<#59529#><#70515#><#72116#>
<#72117#>;; to create a simple graph node that contains <#70516#><#59530#>a-name<#59530#><#70516#> and itself<#72117#> 
<#59531#>(d<#59531#><#59532#>efine<#59532#> <#59533#>(create-node<#59533#> <#59534#>a-name)<#59534#> 
  <#59535#>(l<#59535#><#59536#>ocal<#59536#> <#59537#>((define<#59537#> <#59538#>the-node<#59538#> <#59539#>(make-node<#59539#> <#59540#>a-name<#59540#> <#59541#>false)))<#59541#> 
    <#59542#>(b<#59542#><#59543#>egin<#59543#> 
      <#59544#>(set-node-to!<#59544#> <#59545#>the-node<#59545#> <#59546#>the-node)<#59546#> 
      <#59547#>the-node)))<#59547#> 
The generalized constructor makes the node using the ordinary constructor, initializing the <#70517#><#59551#>name<#59551#><#70517#> field properly and putting <#70518#><#59552#>false<#59552#><#70518#> into the <#70519#><#59553#>to<#59553#><#70519#> field. Although the latter is an improper action according to our data definition, it is acceptable because it is immediately corrected in the <#59554#>local<#59554#>-expression's body. Hence, the result of an application of <#70520#><#59555#>create-node<#59555#><#70520#> produces a <#70521#><#59556#>node<#59556#><#70521#> as promised. With <#70522#><#59557#>create-node<#59557#><#70522#> we can create the nodes in a graph, but we can't establish the connections between them. To connect two nodes, we must modify the <#70523#><#59558#>to<#59558#><#70523#> field of one of the structures so that it contains the other. While this suggestion is generally on target, it raises the problem of how to identify the nodes. The family tree example suggests one solution, namely, to introduce one variable definition per node. Another comes from our orginal work with graphs, where we represented graphs as lists of symbolic pairs of connections or lists of nodes or vectors of nodes. Here we pursue the second option:
An <#70524#><#59560#>simple graph<#59560#><#70524#> is a <#70525#><#59561#>(listof<#59561#>\ <#59562#>node)<#59562#><#70525#>.
Assuming we have a list of all nodes, say <#70526#><#59564#>the-graph<#59564#><#70526#>, and a function for looking up the node with a given name, say <#70527#><#59565#>lookup-node<#59565#><#70527#>, we can create a connection from one node to the other with a structure mutation:
<#59570#>(set-node-to!<#59570#> <#59571#>(lookup-node<#59571#> <#59572#>from-name<#59572#> <#59573#>the-graph)<#59573#>
              <#59574#>(lookup-node<#59574#> <#59575#>to-name<#59575#> <#59576#>the-graph))<#59576#> 
We can make connecting two nodes more convenient than that with an auxiliary function:
<#72118#>;; <#70528#><#59584#>connect-nodes<#59584#> <#59585#>:<#59585#> <#59586#>symbol<#59586#> <#59587#>symbol<#59587#> <#59588#>graph<#59588#> <#59589#><#59589#><#59590#>-;SPMgt;<#59590#><#59591#><#59591#> <#59592#>void<#59592#><#70528#><#72118#>
<#72119#>;; effect: to mutate the <#70529#><#59593#>to<#59593#><#70529#> field in the structure with<#72119#> 
<#72120#>;; <#70530#><#59594#>from-name<#59594#><#70530#> in the <#70531#><#59595#>name<#59595#><#70531#> field so that it contains<#72120#> 
<#72121#>;; the structure with <#70532#><#59596#>to-name<#59596#><#70532#> in the <#70533#><#59597#>name<#59597#><#70533#> field<#72121#> 
<#59598#>(d<#59598#><#59599#>efine<#59599#> <#59600#>(connect-nodes<#59600#> <#59601#>from-name<#59601#> <#59602#>to-name<#59602#> <#59603#>a-graph)<#59603#> 
  <#59604#>(set-node-to!<#59604#> <#59605#>(lookup-node<#59605#> <#59606#>from-name<#59606#> <#59607#>a-graph)<#59607#> 
                <#59608#>(lookup-node<#59608#> <#59609#>to-name<#59609#> <#59610#>a-graph)))<#59610#> 
Defining <#70534#><#59614#>lookup-node<#59614#><#70534#> is a exercise in structural function design, though it is best done using Scheme's <#70535#><#59615#>assf<#59615#><#70535#> function, which abstracts this situation.
<#72122#>;; <#70536#><#59620#>create-node<#59620#> <#59621#>:<#59621#> <#59622#>symbol<#59622#> <#59623#><#59623#><#59624#>-;SPMgt;<#59624#><#59625#><#59625#> <#59626#>node<#59626#><#70536#><#72122#>
<#59627#>;; to create a simple graph node that contains itself<#59627#> 
<#59628#>(d<#59628#><#59629#>efine<#59629#> <#59630#>(create-node<#59630#> <#59631#>name)<#59631#> 
  <#59632#>(l<#59632#><#59633#>ocal<#59633#> <#59634#>((define<#59634#> <#59635#>the-node<#59635#> <#59636#>(make-node<#59636#> <#59637#>name<#59637#> <#59638#>false)))<#59638#> 
    <#59639#>(b<#59639#><#59640#>egin<#59640#> 
      <#59641#>(set-node-to!<#59641#> <#59642#>the-node<#59642#> <#59643#>the-node)<#59643#> 
      <#59644#>the-node)))<#59644#> 
<#72123#>;; <#70537#><#59645#>connect-nodes<#59645#> <#59646#>:<#59646#> <#59647#>symbol<#59647#> <#59648#>symbol<#59648#> <#59649#>graph<#59649#> <#59650#><#59650#><#59651#>-;SPMgt;<#59651#><#59652#><#59652#> <#59653#>void<#59653#><#70537#><#72123#> 
<#72124#>;; effect: to mutate the <#70538#><#59654#>to<#59654#><#70538#> field in the structure named <#72124#> 
<#72125#>;; <#70539#><#59655#>from-name<#59655#><#70539#> so that it contains the structure named <#70540#><#59656#>to-name<#59656#><#70540#><#72125#> 
<#59657#>(d<#59657#><#59658#>efine<#59658#> <#59659#>(connect-nodes<#59659#> <#59660#>from-name<#59660#> <#59661#>to-name<#59661#> <#59662#>a-graph)<#59662#> 
  <#59663#>(set-node-to!<#59663#> <#59664#>(lookup-node<#59664#> <#59665#>from-name<#59665#> <#59666#>a-graph)<#59666#> 
                <#59667#>(lookup-node<#59667#> <#59668#>to-name<#59668#> <#59669#>a-graph)))<#59669#> 
<#72126#>;; <#70541#><#59670#>lookup-node<#59670#> <#59671#>:<#59671#> <#59672#>symbol<#59672#> <#59673#>graph<#59673#> <#59674#><#59674#><#59675#>-;SPMgt;<#59675#><#59676#><#59676#> <#59677#>node<#59677#> <#59678#>or<#59678#> <#59679#>false<#59679#><#70541#><#72126#> 
<#72127#>;; to lookup up the node named <#70542#><#59680#>x<#59680#><#70542#> in <#70543#><#59681#>a-graph<#59681#><#70543#><#72127#> 
<#59682#>(define<#59682#> <#59683#>(lookup-node<#59683#> <#59684#>x<#59684#> <#59685#>a-graph)<#59685#> <#59686#>...)<#59686#> 
<#72128#>;; <#70544#><#59687#>the-graph<#59687#> <#59688#>:<#59688#> <#59689#>graph<#59689#><#70544#><#72128#> 
<#59690#>;; the list of all available nodes <#59690#> 
<#59691#>(d<#59691#><#59692#>efine<#59692#> <#59693#>the-graph<#59693#> 
  <#59694#>(list<#59694#> <#59695#>(create-node<#59695#> <#59696#>'<#59696#><#59697#>A)<#59697#> 
        <#59698#>(create-node<#59698#> <#59699#>'<#59699#><#59700#>B)<#59700#> 
        <#59701#>(create-node<#59701#> <#59702#>'<#59702#><#59703#>C)<#59703#> 
        <#59704#>(create-node<#59704#> <#59705#>'<#59705#><#59706#>D)<#59706#> 
        <#59707#>(create-node<#59707#> <#59708#>'<#59708#><#59709#>E)<#59709#> 
        <#59710#>(create-<#59710#><#59711#>node<#59711#> <#59712#>'<#59712#><#59713#>F)))<#59713#> 
                
<#59714#>(b<#59714#><#59715#>egin<#59715#> 
  <#59716#>(connect-nodes<#59716#> <#59717#>'<#59717#><#59718#>A<#59718#> <#59719#>'<#59719#><#59720#>B<#59720#> <#59721#>the-graph)<#59721#> 
  <#59722#>(connect-nodes<#59722#> <#59723#>'<#59723#><#59724#>B<#59724#> <#59725#>'<#59725#><#59726#>C<#59726#> <#59727#>the-graph)<#59727#> 
  <#59728#>(connect-nodes<#59728#> <#59729#>'<#59729#><#59730#>C<#59730#> <#59731#>'<#59731#><#59732#>E<#59732#> <#59733#>the-graph)<#59733#> 
  <#59734#>(connect-nodes<#59734#> <#59735#>'<#59735#><#59736#>D<#59736#> <#59737#>'<#59737#><#59738#>E<#59738#> <#59739#>the-graph)<#59739#> 
  <#59740#>(connect-nodes<#59740#> <#59741#>'<#59741#><#59742#>E<#59742#> <#59743#>'<#59743#><#59744#>B<#59744#> <#59745#>the-graph))<#59745#> 
<#59749#>Figure: Creating a simple graph via mutation<#59749#>
Now we can transliterate simple graphs into a Scheme representation. Suppose we start with the graph in figure~#figsimgraph#59751>, which is reproduced here in a tabular format:

#tabular59753#

The first step is to create a list of all the nodes and to name it. The second step is to establish the connections according to this table. Figure~#figsgimp#59759> shows the corresponding Scheme expressions. They are straight transliterations of the columns in the tabular representation of the graph. There is no need to re-connect the <#70545#><#59760#>'<#59760#><#59761#>F<#59761#><#70545#> node because it is already connected to itself.
<#59764#>Exercise 43.2.5<#59764#> Draw a picture of <#70546#><#59766#>(create-node<#59766#>\ <#59767#>'<#59767#><#59768#>A)<#59768#><#70546#>. Use the boxes-in-boxes approach and the boxes-and-arrow approach.~ external Solution<#70547#><#70547#> <#59774#>Exercise 43.2.6<#59774#> Transliterate the given simple graph without creating a list of all nodes.~ external Solution<#70548#><#70548#> <#59781#>Exercise 43.2.7<#59781#> Develop the function <#70549#><#59783#>symbolic-graph-to-structures<#59783#><#70549#>. It consumes a list of pairs and creates a <#70550#><#59784#>graph<#59784#><#70550#>. Example:

<#59789#>(d<#59789#><#59790#>efine<#59790#> <#59791#>the-graph<#59791#> 
  <#59792#>(symbolic-graph-to-structures<#59792#> <#59793#>'<#59793#><#59794#>((A<#59794#> <#59795#>B)<#59795#> <#59796#>(B<#59796#> <#59797#>C)<#59797#> <#59798#>(C<#59798#> <#59799#>E)<#59799#> <#59800#>(D<#59800#> <#59801#>E)<#59801#> <#59802#>(E<#59802#> <#59803#>B)<#59803#> <#59804#>(F<#59804#> <#59805#>F))))<#59805#> 
Evaluating this definition is equivalent to evaluating the definitions in figure~#figsgimp#59809>.~ external Solution<#70551#><#70551#>
Once we have a method for representing simple graphs, we can turn our attention to the problem of finding a route from one node in the graph to another. Recall the original specification from section~#seclossgenerative#59817>:
<#72129#>;; <#70552#><#59822#>route-exists?<#59822#> <#59823#>:<#59823#> <#59824#>node<#59824#> <#59825#>node<#59825#> <#59826#>simple-graph<#59826#> <#59827#><#59827#><#59828#>-;SPMgt;<#59828#><#59829#><#59829#> <#59830#>boolean<#59830#><#70552#><#72129#>
<#72130#>;; to determine whether there is a route from <#70553#><#59831#>orig<#59831#><#70553#> to <#70554#><#59832#>dest<#59832#><#70554#> in <#70555#><#59833#>sg<#59833#><#70555#><#72130#> 
<#59834#>(define<#59834#> <#59835#>(route-exists?<#59835#> <#59836#>orig<#59836#> <#59837#>dest<#59837#> <#59838#>sg)<#59838#> <#59839#>...)<#59839#> 
Of course, we must re-interpret the names for our data classes in the new context but otherwise the specification is perfectly fine. The development of the original function demonstrated two new ideas. First, the function uses generative recursion. Once it is known that <#70556#><#59843#>orig<#59843#><#70556#> and <#70557#><#59844#>dest<#59844#><#70557#> are distinct nodes, the search resumes from the node to which <#70558#><#59845#>orig<#59845#><#70558#> is connected. Second, the function requires an accumulator to remember which nodes have been visited. Without the accumulator, the function may re-visit the same node over and over again. So, let's start from the template for generative recursion:
<#59850#>(d<#59850#><#59851#>efine<#59851#> <#59852#>(route-exists?<#59852#> <#59853#>orig<#59853#> <#59854#>dest<#59854#> <#59855#>sg)<#59855#>
  <#59856#>(c<#59856#><#59857#>ond<#59857#> 
    <#59858#>[<#59858#><#59859#>(eq-node?<#59859#> <#59860#>orig<#59860#> <#59861#>dest)<#59861#> <#59862#>true]<#59862#> 
    <#59863#>[<#59863#><#59864#>else<#59864#> 
     <#59865#>(route-exists?<#59865#> <#59866#>...<#59866#> <#72314#>#tex2html_wrap_inline74302#<#72314#> <#59868#>...<#59868#> <#59869#>dest<#59869#> <#59870#>sg)]<#59870#><#59871#>))<#59871#> 
The function <#70560#><#59875#>eq-node?<#59875#><#70560#> determines whether the two nodes are the same; this may just use <#70561#><#59876#>eq?<#59876#><#70561#>, Scheme's intentional equality predicate, or it may compare the names of the nodes, assuming they are unique. If the nodes are the same, a route exists. If not, we can generate a new, potentially useful problem by moving to the node to which <#70562#><#59877#>orig<#59877#><#70562#> is connected. In the graph representation of section~#seclossgenerative#59878>, this requires looking in <#70563#><#59879#>sg<#59879#><#70563#>. In our new graph representation, the connection is a part of the <#70564#><#59880#>node<#59880#><#70564#> representation. Hence, we can use <#70565#><#59881#>node-to<#59881#><#70565#> instead of looking in <#70566#><#59882#>sg<#59882#><#70566#>:
<#59887#>(d<#59887#><#59888#>efine<#59888#> <#59889#>(route-exists?<#59889#> <#59890#>orig<#59890#> <#59891#>dest<#59891#> <#59892#>sg)<#59892#>
  <#59893#>(c<#59893#><#59894#>ond<#59894#> 
    <#59895#>[<#59895#><#59896#>(eq-node?<#59896#> <#59897#>orig<#59897#> <#59898#>dest)<#59898#> <#59899#>true]<#59899#> 
    <#59900#>[<#59900#><#59901#>else<#59901#> <#59902#>(route-exists?<#59902#> <#59903#>(node-to<#59903#> <#59904#>orig)<#59904#> <#59905#>dest<#59905#> <#59906#>sg)]<#59906#><#59907#>))<#59907#> 
The function definition shows that, so far, <#70567#><#59911#>sg<#59911#><#70567#> is useless. Because a node in the new graph representation contains its neighbors, the neighbor contains its neighbor, and so on, there is no need to use the table. The termination argument for this function fails, just as for the original one in section~#seclossgenerative#59912>. To see why our new function may fail to terminate, take a look at its definition. It doesn't contain <#70568#><#59913#>false<#59913#><#70568#>, and the function cannot possible produce <#70569#><#59914#>false<#59914#><#70569#>---even though we know that our sample graph, for example, doesn't contain a path from <#70570#><#59915#>'<#59915#><#59916#>F<#59916#><#70570#> to <#70571#><#59917#>'<#59917#><#59918#>A<#59918#><#70571#> or anywhere else. If we inspect what happens with
<#59923#>(route-exists?<#59923#> <#59924#>(lookup-node<#59924#> <#59925#>the-graph<#59925#> <#59926#>'<#59926#><#59927#>F)<#59927#> <#59928#>(lookup-node<#59928#> <#59929#>the-graph<#59929#> <#59930#>'<#59930#><#59931#>A))<#59931#>
we see that <#70572#><#59935#>route-exists?<#59935#><#70572#> repeatedly visits the node <#70573#><#59936#>'<#59936#><#59937#>F<#59937#><#70573#>. In short, it forgets what it has processed so far. We know that equipping <#70574#><#59938#>route-exists?<#59938#><#70574#> with an accumulator overcomes this lack of knowledge, but that requires another table lookup. We can do better than that with a structure mutation that records a visit by the <#70575#><#59939#>route-exists?<#59939#><#70575#> function. To do that, the <#70576#><#59940#>node<#59940#><#70576#> structures need an addtional field; we call it <#70577#><#59941#>visited<#59941#><#70577#>:
<#59946#>(define-struct<#59946#> <#59947#>node<#59947#> <#59948#>(name<#59948#> <#59949#>visited<#59949#> <#59950#>to))<#59950#>
Initially the field contains <#70578#><#59954#>false<#59954#><#70578#>. As <#70579#><#59955#>route-exists?<#59955#><#70579#> visits a node, it puts <#70580#><#59956#>true<#59956#><#70580#> into the field:
<#59961#>(d<#59961#><#59962#>efine<#59962#> <#59963#>(route-exists?<#59963#> <#59964#>orig<#59964#> <#59965#>dest<#59965#> <#59966#>sg)<#59966#>
  <#59967#>(c<#59967#><#59968#>ond<#59968#> 
    <#59969#>[<#59969#><#59970#>(eq-node?<#59970#> <#59971#>orig<#59971#> <#59972#>dest)<#59972#> <#59973#>true]<#59973#> 
    <#59974#>[<#59974#><#59975#>(node-visited<#59975#> <#59976#>orig)<#59976#> <#59977#>false]<#59977#> 
    <#59978#>[<#59978#><#59979#>e<#59979#><#59980#>lse<#59980#> 
      <#59981#>(b<#59981#><#59982#>egin<#59982#> 
        <#59983#>(set-node-visited!<#59983#> <#59984#>orig<#59984#> <#59985#>true)<#59985#> 
        <#59986#>(route-exists?<#59986#> <#59987#>(node-to<#59987#> <#59988#>orig)<#59988#> <#59989#>dest<#59989#> <#59990#>sg))]<#59990#><#59991#>))<#59991#> 
To exploit this new knowledge, the function checks the new structure field as one of the new termination condition. If <#70581#><#59995#>orig<#59995#><#70581#> has been visited before, there is no route because the function has discovered a cycle in the graph. The second structure mutation of this example illustrates two ideas. First, structure mutation can replace a table-based accumulator. In general, though, it is best to study a table-based version and to add structure mutations based on a solid understanding of the accumulated knowledge. Second, structure mutations can play a role in termination test for generative recursion. After all, state change is motivated by the desire to remember things across function applications and termination tests must discover whether things have changed. While the combination is rare, it is useful and appears time and again in the study of algorithms.
<#59998#>Exercise 43.2.8<#59998#> The function <#70582#><#60000#>route-exists?<#60000#><#70582#> assumes that the <#70583#><#60001#>visited<#60001#><#70583#> fields of all the nodes are initially <#70584#><#60002#>false<#60002#><#70584#>. A single use of the function, however, sets some of the fields in a graph to <#70585#><#60003#>true<#60003#><#70585#>. This implies that the function cannot be used twice in a row. Develop a revised version of <#70586#><#60004#>route-exists?<#60004#><#70586#>, with the same specification, that sets all <#70587#><#60005#>visited<#60005#><#70587#> fields to <#70588#><#60006#>false<#60006#><#70588#> before it searches for a route between the given nodes. Determine the abstract running time of the new function, assuming the graph has N nodes.~ external Solution<#70589#><#70589#> <#60012#>Exercise 43.2.9<#60012#> Develop the function <#70590#><#60014#>reachable<#60014#><#70590#>. It consumes a node in a simple graph. Its effect is to place <#70591#><#60015#>true<#60015#><#70591#> into the <#70592#><#60016#>visited<#60016#><#70592#> fields of all those nodes that are reachable from the given node and to ensure that the <#70593#><#60017#>visited<#60017#><#70593#> fields of all other nodes are <#70594#><#60018#>false<#60018#><#70594#>.~ external Solution<#70595#><#70595#> <#60024#>Exercise 43.2.10<#60024#> Develop <#70596#><#60026#>make-simple-graph<#60026#><#70596#>, a function that manages the state of a <#70597#><#60027#>local<#60027#><#70597#>ly defined graph. The function accepts a simple graph in the form of lists of pairs of symbols: <#70598#><#60028#>(listof<#60028#>\ <#60029#>(list<#60029#>\ <#60030#>symbol<#60030#>\ <#60031#>symbol))<#60031#><#70598#>. It supports four services:
  1. adding nodes that are connected to already existing nodes (by name);
  2. changing the connection of a node (by name);
  3. determining whether a route between two nodes exists;
  4. and removing nodes that are not reachable from some given node.
<#60034#>Hint:<#60034#> \ Instead of using a list, the manager should use a node sequence, which is analogous to the <#70599#><#60035#>hand<#60035#><#70599#> structure from section~#secdesignmutex2#60036>. A node sequence relies on the following structure:
<#60041#>(define-struct<#60041#> <#60042#>sequence<#60042#> <#60043#>(node<#60043#> <#60044#>next))<#60044#>
A sequence is similar to a list, but it supports structure mutations.~ external Solution<#70600#><#70600#>
The discussion of this section confirms the usefulness of the design recipes, even for collections of structures that refer to each other. The most important lesson is that such situations call for a generalized constructor, a function that creates a structure and immediately establishes the necessary connections. Generalized constructors correspond to the initializers of section~#secsetbang#60055>; we have also seen the idea in section~#secdesignmutex2#60056> where we created a hand from a single card. In some cases, such as the one for simple graphs, we may also want to introduce auxiliary functions for mutating the structures a second time. Once we have those functions, we can use the standard recipes, including those for introducing additional structure fields.