Traversing Graphs

On occasion, we need to navigate through a maze of one-way streets. Or, we may wish to draw a graph of whom we consider a friend, whom they consider a friend, and so on. Or, we need to plan a route through a network of pipelines. Or, we ask the Internet to find some way to send a message from one place to another. All these situations share a common element: a <#36635#>directed graph<#36635#>. Specifically, there is always some collection of <#36636#>nodes<#36636#> and a collection of <#36637#>edges<#36637#>. The edges represent one-way connections between the nodes. Consider figure~#figgraph#36638>. The black bullets are the nodes; the arrows between them are the one-way connections. The sample graph consists of seven nodes and nine edges. Now suppose we wish to plan routes in the graph of figure~#figgraph#36639>. For example, if we plan to go from C to D, the route is simple: it consists of the origination node C and the destination node D. In contrast, if we wish to travel from E to D, we have two choices:
  1. We either travel from E to F and then to D.
  2. Or, we travel from E to C and then to D.
For some nodes, however, it is impossible to connect them. In particular, it is impossible in our sample graph to move from C to G by following the arrows. rawhtml49
<#36642#>Figure: A directed graph<#36642#>
In the real world, graphs have more than just seven nodes and many more edges. Hence it is natural to develop functions that plan routes in graphs. Following the general design recipe, we start with a data analysis. Here is a compact representation of the graph in figure~#figgraph#36644> using lists:
<#36649#>(d<#36649#><#36650#>efine<#36650#> <#36651#>Graph<#36651#> 
  <#36652#>'<#36652#><#36653#>(<#36653#><#36654#>(A<#36654#> <#36655#>(B<#36655#> <#36656#>E))<#36656#> 
    <#36657#>(B<#36657#> <#36658#>(E<#36658#> <#36659#>F))<#36659#> 
    <#36660#>(C<#36660#> <#36661#>(D))<#36661#> 
    <#36662#>(D<#36662#> <#36663#>())<#36663#> 
    <#36664#>(E<#36664#> <#36665#>(C<#36665#> <#36666#>F))<#36666#> 
    <#36667#>(F<#36667#> <#36668#>(D<#36668#> <#36669#>G))<#36669#> 
    <#36670#>(G<#36670#> <#36671#>())))<#36671#> 
The list contains one list per node. Each of these lists starts with the name of a node followed by the list of its <#36675#>neighbors<#36675#>. For example, the second list represents node B with its two outgoing edges to E and F.
<#36678#>Exercise 28.1.1<#36678#> Translate the above definition into proper list form using <#66788#><#36680#>list<#36680#><#66788#> and proper symbols. The data definition for node is straightforward:
A <#66789#><#36682#>node<#36682#><#66789#> is a symbol.
Formulate a data definition for graphs with arbitrarily many nodes and edges. The data definition must specify a class of data that contains <#66790#><#36684#>Graph<#36684#><#66790#>.~ external Solution<#66791#><#66791#>
Based on the data definitions for <#66792#><#36692#>node<#36692#><#66792#> and <#66793#><#36693#>graph<#36693#><#66793#>, we can now produce the first draft of a contract for <#66794#><#36694#>find-route<#36694#><#66794#>, the function that searches a route in a graph:
<#71521#>;; <#66795#><#36699#>find-route<#36699#> <#36700#>:<#36700#> <#36701#>node<#36701#> <#36702#>node<#36702#> <#36703#>graph<#36703#> <#36704#><#36704#><#36705#>-;SPMgt;<#36705#><#36706#><#36706#> <#36707#>(listof<#36707#> <#36708#>node)<#36708#><#66795#><#71521#>
<#71522#>;; to create a path from <#66796#><#36709#>origination<#36709#><#66796#> to <#66797#><#36710#>destination<#36710#><#66797#> in <#66798#><#36711#>G<#36711#><#66798#><#71522#> 
<#36712#>(define<#36712#> <#36713#>(find-route<#36713#> <#36714#>origination<#36714#> <#36715#>destination<#36715#> <#36716#>G)<#36716#> <#36717#>...)<#36717#> 
What this header leaves open is the exact shape of the result. It implies that the result is a list of nodes, but it does not say exactly which nodes the list contains. To understand this aspect, we must study some examples. Consider the first problem mentioned above. Here is an expression that formulates the problem in Scheme:
<#36725#>(find-route<#36725#> <#36726#>'<#36726#><#36727#>C<#36727#> <#36728#>'<#36728#><#36729#>D<#36729#> <#36730#>Graph)<#36730#>
A route from <#66799#><#36734#>'<#36734#><#36735#>C<#36735#><#66799#> to <#66800#><#36736#>'<#36736#><#36737#>D<#36737#><#66800#> consists of just two nodes: the origination and the destination node. Hence, we should expect the answer <#66801#><#36738#>(list<#36738#>\ <#36739#>'<#36739#><#36740#>C<#36740#>\ <#36741#>'<#36741#><#36742#>D)<#36742#><#66801#>. Of course, one might argue that since both the origination node and the destination node are known, the result should be <#66802#><#36743#>empty<#36743#><#66802#>. Here we choose the first alternative since it is more natural, but it requires only a minor change of the final function definition to produce the latter. Now consider our second problem, going from <#66803#><#36744#>'<#36744#><#36745#>E<#36745#><#66803#> to <#66804#><#36746#>'<#36746#><#36747#>D<#36747#><#66804#>, which is more representative of the kinds of problems we might encounter. One natural idea is to inspect all of the neighbors of <#66805#><#36748#>'<#36748#><#36749#>E<#36749#><#66805#> and to find a route from one of them to <#66806#><#36750#>'<#36750#><#36751#>D<#36751#><#66806#>. In our sample graph, <#66807#><#36752#>'<#36752#><#36753#>E<#36753#><#66807#> has two neighbors: <#66808#><#36754#>'<#36754#><#36755#>C<#36755#><#66808#> and <#66809#><#36756#>'<#36756#><#36757#>F<#36757#><#66809#>. Suppose for a moment that we didn't know the route yet. In that case, we could again inspect all of the neighbors of <#66810#><#36758#>'<#36758#><#36759#>C<#36759#><#66810#> and find a route from those to our goal. Of course, <#66811#><#36760#>'<#36760#><#36761#>C<#36761#><#66811#> has a single neighbor and it is <#66812#><#36762#>'<#36762#><#36763#>D<#36763#><#66812#>. Putting together the results of all stages shows that the final result is <#66813#><#36764#>(list<#36764#>\ <#36765#>'<#36765#><#36766#>E<#36766#>\ <#36767#>'<#36767#><#36768#>C<#36768#>\ <#36769#>'<#36769#><#36770#>D)<#36770#><#66813#>. Our final example poses a new problem. Suppose <#66814#><#36771#>find-route<#36771#><#66814#> is given the arguments <#66815#><#36772#>'<#36772#><#36773#>C<#36773#><#66815#>, <#66816#><#36774#>'<#36774#><#36775#>G<#36775#><#66816#>, and <#66817#><#36776#>Graph<#36776#><#66817#>. In this case, we know from inspecting figure~#figgraph#36777> that there is no connecting route. To signal the lack of a route, <#66818#><#36778#>find-route<#36778#><#66818#> should produce a value that cannot be mistaken for a route. One good choice is <#66819#><#36779#>false<#36779#><#66819#>, a value that isn't a list and naturally denotes the failure of a function to compute a proper result. This new agreement requires another change in our contract:
<#71523#>;; <#66820#><#36784#>find-route<#36784#> <#36785#>:<#36785#> <#36786#>node<#36786#> <#36787#>node<#36787#> <#36788#>graph<#36788#> <#36789#><#36789#><#36790#>-;SPMgt;<#36790#><#36791#><#36791#> <#36792#>(listof<#36792#> <#36793#>node)<#36793#> <#36794#>or<#36794#> <#36795#>false<#36795#><#66820#><#71523#>
<#71524#>;; to create a path from <#66821#><#36796#>origination<#36796#><#66821#> to <#66822#><#36797#>destination<#36797#><#66822#> in <#66823#><#36798#>G<#36798#><#66823#><#71524#> 
<#71525#>;; if there is no path, the function produces <#66824#><#36799#>false<#36799#><#66824#><#71525#> 
<#36800#>(define<#36800#> <#36801#>(find-route<#36801#> <#36802#>origination<#36802#> <#36803#>destination<#36803#> <#36804#>G)<#36804#> <#36805#>...)<#36805#> 
Our next step is to understand the four essential pieces of the function: the ``trivial problem'' condition, a matching solution, the generation of a new problem, and the combination step. The discussion of the three examples suggest answers. First, if the <#66825#><#36809#>origination<#36809#><#66825#> argument of <#66826#><#36810#>find-route<#36810#><#66826#> is equal to its <#66827#><#36811#>destination<#36811#><#66827#>, the problem is trivial; the matching answer is <#66828#><#36812#>(list<#36812#>\ <#36813#>destination)<#36813#><#66828#>. Second, if the arguments are different, we must inspect all neighbors of <#66829#><#36814#>origination<#36814#><#66829#> in <#66830#><#36815#>graph<#36815#><#66830#> and determine whether there is a route from one of those to <#66831#><#36816#>destination<#36816#><#66831#>. Since a node can have an arbitrary number of neighbors, this task is too complex for a single primitive. We need an auxiliary function. The task of the auxiliary function is to consume a list of nodes and to determine for each one of them whether there is a route to the destination node in the given graph. Put differently, the function is a list-oriented version of <#66832#><#36817#>find-route<#36817#><#66832#>. Let us call this function <#66833#><#36818#>find-route/list<#36818#><#66833#>. Here is a translation of this informal description into a contract, header, and purpose statement:
<#71526#>;; <#66834#><#36823#>find-route/list<#36823#> <#36824#>:<#36824#> <#36825#>(listof<#36825#> <#36826#>node)<#36826#> <#36827#>node<#36827#> <#36828#>graph<#36828#> <#36829#><#36829#><#36830#>-;SPMgt;<#36830#><#36831#><#36831#> <#36832#>(listof<#36832#> <#36833#>node)<#36833#> <#36834#>or<#36834#> <#36835#>false<#36835#><#66834#><#71526#>
<#71527#>;; to create a path from some node on <#66835#><#36836#>lo-originations<#36836#><#66835#> to <#66836#><#36837#>destination<#36837#><#66836#><#71527#> 
<#71528#>;; if there is no path, the function produces <#66837#><#36838#>false<#36838#><#66837#><#71528#> 
<#36839#>(define<#36839#> <#36840#>(find-route/list<#36840#> <#36841#>lo-originations<#36841#> <#36842#>destination<#36842#> <#36843#>G)<#36843#> <#36844#>...)<#36844#> 
Now we can write a first draft of <#66838#><#36848#>find-route<#36848#><#66838#> as follows:
<#36853#>(d<#36853#><#36854#>efine<#36854#> <#36855#>(find-route<#36855#> <#36856#>origination<#36856#> <#36857#>destination<#36857#> <#36858#>G)<#36858#>
  <#36859#>(c<#36859#><#36860#>ond<#36860#> 
    <#36861#>[<#36861#><#36862#>(symbol=?<#36862#> <#36863#>origination<#36863#> <#36864#>destination)<#36864#> <#36865#>(list<#36865#> <#36866#>destination)]<#36866#> 
    <#36867#>[<#36867#><#36868#>else<#36868#> <#36869#>...<#36869#> <#36870#>(find-route/list<#36870#> <#36871#>(neighbors<#36871#> <#36872#>origination<#36872#> <#36873#>G)<#36873#> <#36874#>destination<#36874#> <#36875#>G)<#36875#> <#36876#>...]<#36876#><#36877#>))<#36877#> 
The function <#66839#><#36881#>neighbors<#36881#><#66839#> generates a whole list of problems: the problems of finding routes from the neighbors of <#66840#><#36882#>origination<#36882#><#66840#> to <#66841#><#36883#>destination<#36883#><#66841#>. Its definition is a straightforward exercise in structural processing.
<#36886#>Exercise 28.1.2<#36886#> Develop the function <#66842#><#36888#>neighbors<#36888#><#66842#>. It consumes a node <#66843#><#36889#>n<#36889#><#66843#> and a graph <#66844#><#36890#>g<#36890#><#66844#> (see exercise~#exrepresentgraph#36891>) and produces the list of neighbors of <#66845#><#36892#>n<#36892#><#66845#> in <#66846#><#36893#>g<#36893#><#66846#>.~ external Solution<#66847#><#66847#>
Next we need to consider what <#66848#><#36901#>find-route/list<#36901#><#66848#> produces. If it finds a route from any of the neighbors, it produces a route from that neighbor to the final destination. But, if none of the neighbors is connected to the destination, the function produces <#66849#><#36902#>false<#36902#><#66849#>. Clearly, <#66850#><#36903#>find-route<#36903#><#66850#>'s answer depends on what <#66851#><#36904#>find-route/list<#36904#><#66851#> produces. Hence, we should distinguish the answers with a <#66852#><#36905#>cond<#36905#>-expression<#66852#>:
<#36910#>(d<#36910#><#36911#>efine<#36911#> <#36912#>(find-route<#36912#> <#36913#>origination<#36913#> <#36914#>destination<#36914#> <#36915#>G)<#36915#>
  <#36916#>(c<#36916#><#36917#>ond<#36917#> 
    <#36918#>[<#36918#><#36919#>(symbol=?<#36919#> <#36920#>origination<#36920#> <#36921#>destination)<#36921#> <#36922#>(list<#36922#> <#36923#>destination)]<#36923#> 
    <#36924#>[<#36924#><#36925#>else<#36925#> <#36926#>(l<#36926#><#36927#>ocal<#36927#> <#36928#>((d<#36928#><#36929#>efine<#36929#> <#36930#>possible-route<#36930#> 
                    <#36931#>(find-route/list<#36931#> <#36932#>(neighbors<#36932#> <#36933#>origination<#36933#> <#36934#>G)<#36934#> 
                                     <#36935#>destination<#36935#> <#36936#>G)))<#36936#> 
            <#36937#>(c<#36937#><#36938#>ond<#36938#> 
              <#36939#>[<#36939#><#36940#>(boolean?<#36940#> <#36941#>route)<#36941#> <#36942#>...]<#36942#> 
              <#36943#>[<#36943#><#36944#>e<#36944#><#36945#>lse<#36945#> <#71529#>; <#66853#><#36946#>(cons?<#36946#> <#36947#>route)<#36947#><#66853#> <#71529#> 
                <#36948#>...]<#36948#><#36949#>))]<#36949#><#36950#>))<#36950#> 
The two cases reflect the two kinds of answers we might receive: a boolean or a list. If <#66854#><#36954#>find-route/list<#36954#><#66854#> produces <#66855#><#36955#>false<#36955#><#66855#>, it failed to find a route from <#66856#><#36956#>origination<#36956#><#66856#>'s neighbors, and it is therefore impossible to reach <#66857#><#36957#>destination<#36957#><#66857#> at all. The answer in this case must therefore be <#66858#><#36958#>false<#36958#><#66858#>. In contrast, if <#66859#><#36959#>find-route/list<#36959#><#66859#> produces a list, the answer must be route from <#66860#><#36960#>origination<#36960#><#66860#> to <#66861#><#36961#>destination<#36961#><#66861#>. Since <#66862#><#36962#>possible-route<#36962#><#66862#> starts with one of <#66863#><#36963#>origination<#36963#><#66863#>'s neighbors, it suffices to add <#66864#><#36964#>origination<#36964#><#66864#> to the front of <#66865#><#36965#>possible-route<#36965#><#66865#>.
<#71530#>;; <#66866#><#36970#>find-route<#36970#> <#36971#>:<#36971#> <#36972#>node<#36972#> <#36973#>node<#36973#> <#36974#>graph<#36974#> <#36975#><#36975#><#36976#>-;SPMgt;<#36976#><#36977#><#36977#> <#36978#>(listof<#36978#> <#36979#>node)<#36979#> <#36980#>or<#36980#> <#36981#>false<#36981#><#66866#><#71530#>
<#71531#>;; to create a path from <#66867#><#36982#>origination<#36982#><#66867#> to <#66868#><#36983#>destination<#36983#><#66868#> in <#66869#><#36984#>G<#36984#><#66869#><#71531#> 
<#71532#>;; if there is no path, the function produces <#66870#><#36985#>false<#36985#><#66870#><#71532#> 
<#36986#>(d<#36986#><#36987#>efine<#36987#> <#36988#>(find-route<#36988#> <#36989#>origination<#36989#> <#36990#>destination<#36990#> <#36991#>G)<#36991#> 
  <#36992#>(c<#36992#><#36993#>ond<#36993#> 
    <#36994#>[<#36994#><#36995#>(symbol=?<#36995#> <#36996#>origination<#36996#> <#36997#>destination)<#36997#> <#36998#>(list<#36998#> <#36999#>destination)]<#36999#> 
    <#37000#>[<#37000#><#37001#>else<#37001#> <#37002#>(l<#37002#><#37003#>ocal<#37003#> <#37004#>((d<#37004#><#37005#>efine<#37005#> <#37006#>possible-route<#37006#> 
                    <#37007#>(find-route/list<#37007#> <#37008#>(neighbors<#37008#> <#37009#>origination<#37009#> <#37010#>G)<#37010#> <#37011#>destination<#37011#> <#37012#>G)))<#37012#> 
            <#37013#>(c<#37013#><#37014#>ond<#37014#> 
              <#37015#>[<#37015#><#37016#>(boolean?<#37016#> <#37017#>possible-route)<#37017#> <#37018#>false<#37018#><#37019#>]<#37019#> 
              <#37020#>[<#37020#><#37021#>else<#37021#> <#37022#>(cons<#37022#> <#37023#>origination<#37023#> <#37024#>possible-route)]<#37024#><#37025#>))]<#37025#><#37026#>))<#37026#> 
<#71533#>;; <#66871#><#37027#>find-route/list<#37027#> <#37028#>:<#37028#> <#37029#>(listof<#37029#> <#37030#>node)<#37030#> <#37031#>node<#37031#> <#37032#>graph<#37032#> <#37033#><#37033#><#37034#>-;SPMgt;<#37034#><#37035#><#37035#> <#37036#>(listof<#37036#> <#37037#>node)<#37037#> <#37038#>or<#37038#> <#37039#>false<#37039#><#66871#><#71533#> 
<#71534#>;; to create a path from some node on <#66872#><#37040#>lo-originations<#37040#><#66872#> to <#66873#><#37041#>destination<#37041#><#66873#><#71534#> 
<#71535#>;; if there is no path, the function produces <#66874#><#37042#>false<#37042#><#66874#><#71535#> 
<#37043#>(d<#37043#><#37044#>efine<#37044#> <#37045#>(find-route/list<#37045#> <#37046#>lo-Os<#37046#> <#37047#>D<#37047#> <#37048#>G)<#37048#> 
  <#37049#>(c<#37049#><#37050#>ond<#37050#> 
    <#37051#>[<#37051#><#37052#>(empty?<#37052#> <#37053#>lo-Os)<#37053#> <#37054#>false<#37054#><#37055#>]<#37055#> 
    <#37056#>[<#37056#><#37057#>else<#37057#> <#37058#>(l<#37058#><#37059#>ocal<#37059#> <#37060#>((define<#37060#> <#37061#>possible-route<#37061#> <#37062#>(find-route<#37062#> <#37063#>(first<#37063#> <#37064#>lo-Os)<#37064#> <#37065#>D<#37065#> <#37066#>G)))<#37066#> 
            <#37067#>(c<#37067#><#37068#>ond<#37068#> 
              <#37069#>[<#37069#><#37070#>(boolean?<#37070#> <#37071#>possible-route)<#37071#> <#37072#>(find-route/list<#37072#> <#37073#>(rest<#37073#> <#37074#>lo-Os)<#37074#> <#37075#>D<#37075#> <#37076#>G)]<#37076#> 
              <#37077#>[<#37077#><#37078#>else<#37078#> <#37079#>possible-route]<#37079#><#37080#>))]<#37080#><#37081#>))<#37081#> 
<#37085#>Figure: Finding a route in a graph<#37085#>
Figure~#figfindroutecode#37087> contains the complete definition of <#66875#><#37088#>find-route<#37088#><#66875#>. It also contains a definition of <#66876#><#37089#>find-route/list<#37089#><#66876#>, which processes its first argument via structural recursion. For each node in the list, <#66877#><#37090#>find-route/list<#37090#><#66877#> uses <#66878#><#37091#>find-route<#37091#><#66878#> to check for a route. If <#66879#><#37092#>find-route<#37092#><#66879#> indeed produces a route, that route is the answer. Otherwise, if <#66880#><#37093#>find-route<#37093#><#66880#> fails and produces <#66881#><#37094#>false<#37094#><#66881#>, the function recurs. In other words, it backtracks its current choice of a starting position, <#66882#><#37095#>(first<#37095#>\ <#37096#>lo-Os)<#37096#><#66882#>, and instead tries the next one in the list. For that reason, <#66883#><#37097#>find-route<#37097#><#66883#> is often called a <#66884#><#37098#>BACKTRACKING ALGORITHM.<#37098#><#66884#>

<#37099#>Backtracking in the Structural World<#37099#>:\ Intermezzo~3 briefly discusses backtracking in the structural world. A particularly good example is exercise #exlocalinterm3#37100>, which concerns a backtracking function for family trees. The function first searches one branch of a family tree for a blue-eyed ancestor and, if this search produces <#66885#><#37101#>false<#37101#><#66885#>, it searches the other half of the tree. Since graphs generalize trees, comparing the two functions is an instructive exercise.~<#66886#><#66886#> Last, but not least, we need to understand whether the function produces an answer in all situations. The second one, <#66887#><#37104#>find-route/list<#37104#><#66887#>, is structurally recursive and therefore always produces some value, assuming <#66888#><#37105#>find-route<#37105#><#66888#> always does. For <#66889#><#37106#>find-route<#37106#><#66889#> the answer is far from obvious. For example, when given the graph in figure~#figgraph#37107> and two nodes in the graph, <#66890#><#37108#>find-route<#37108#><#66890#> always produces some answer. For other graphs, however, it does not always terminate.
<#37111#>Exercise 28.1.3<#37111#> Test <#66891#><#37113#>find-route<#37113#><#66891#>. Use it to find a route from A to G in the graph of figure~#figgraph#37114>. Ensure that it produces <#66892#><#37115#>false<#37115#><#66892#> when asked to find a route from C to G~ external Solution<#66893#><#66893#> <#37121#>Exercise 28.1.4<#37121#> Develop the function <#66894#><#37123#>test-on-all-nodes<#37123#><#66894#>, which consumes a graph <#66895#><#37124#>g<#37124#><#66895#> and tests <#66896#><#37125#>find-route<#37125#><#66896#> on all pairs of nodes in <#66897#><#37126#>g<#37126#><#66897#>. Test the function on <#66898#><#37127#>Graph<#37127#><#66898#>.~ external Solution<#66899#><#66899#>
rawhtml50


<#37135#>Figure: A directed graph with cycle<#37135#>
Consider the graph in figure~#figcyclicgraph#37137>. It radically differs from the graph in figure~#figgraph#37138> in that it is possible to start a route in a node and to return to the same node. Specifically, it is possible to move from B to E to C and back to B. And indeed, if applied <#66900#><#37139#>find-route<#37139#><#66900#> to <#66901#><#37140#>'<#37140#><#37141#>B<#37141#><#66901#>, <#66902#><#37142#>'<#37142#><#37143#>D<#37143#><#66902#>, and a representation of the graph, it fails to stop. Here is the hand-evaluation:
  <#37148#>(find-route<#37148#> <#37149#>'<#37149#><#37150#>B<#37150#> <#37151#>'<#37151#><#37152#>D<#37152#> <#37153#>Cyclic-graph)<#37153#>
<#37154#>=<#37154#> <#37155#>...<#37155#> <#37156#>(find-route<#37156#> <#37157#>'<#37157#><#37158#>B<#37158#> <#37159#>'<#37159#><#37160#>D<#37160#> <#37161#>Cyclic-graph)<#37161#> <#37162#>...<#37162#> 
<#37163#>=<#37163#> <#37164#>...<#37164#> <#37165#>(find-route<#37165#> <#37166#>(list<#37166#> <#37167#>'<#37167#><#37168#>E<#37168#> <#37169#>'<#37169#><#37170#>F)<#37170#> <#37171#>'<#37171#><#37172#>D<#37172#> <#37173#>Cyclic-graph)<#37173#> <#37174#>...<#37174#> 
<#37175#>=<#37175#> <#37176#>...<#37176#> <#37177#>(find-route<#37177#> <#37178#>'<#37178#><#37179#>E<#37179#> <#37180#>'<#37180#><#37181#>D<#37181#> <#37182#>Cyclic-graph)<#37182#> <#37183#>...<#37183#> 
<#37184#>=<#37184#> <#37185#>...<#37185#> <#37186#>(find-route<#37186#> <#37187#>(list<#37187#> <#37188#>'<#37188#><#37189#>C<#37189#> <#37190#>'<#37190#><#37191#>F)<#37191#> <#37192#>'<#37192#><#37193#>D<#37193#> <#37194#>Cyclic-graph)<#37194#> <#37195#>...<#37195#> 
<#37196#>=<#37196#> <#37197#>...<#37197#> <#37198#>(find-route<#37198#> <#37199#>'<#37199#><#37200#>C<#37200#> <#37201#>'<#37201#><#37202#>D<#37202#> <#37203#>Cyclic-graph)<#37203#> <#37204#>...<#37204#> 
<#37205#>=<#37205#> <#37206#>...<#37206#> <#37207#>(find-route<#37207#> <#37208#>(list<#37208#> <#37209#>'<#37209#><#37210#>B<#37210#> <#37211#>'<#37211#><#37212#>D)<#37212#> <#37213#>'<#37213#><#37214#>D<#37214#> <#37215#>Cyclic-graph)<#37215#> <#37216#>...<#37216#> 
<#37217#>=<#37217#> <#37218#>...<#37218#> <#37219#>(find-route<#37219#> <#37220#>'<#37220#><#37221#>B<#37221#> <#37222#>'<#37222#><#37223#>D<#37223#> <#37224#>Cyclic-graph)<#37224#> <#37225#>...<#37225#> 
<#37226#>=<#37226#> <#37227#>...<#37227#> 
where <#66903#><#37231#>Cyclic-Graph<#37231#><#66903#> stands for a Scheme representation of the graph in figure~#figcyclicgraph#37232>. The hand-evaluation shows that after seven applications of <#66904#><#37233#>find-route<#37233#><#66904#> and <#66905#><#37234#>find-route/list<#37234#><#66905#> the computer must evaluate the exact same expression from which we started. Since the same input produces the same output and the same behavior for functions, we know that the function loops forever and does not produce a value. In summary, if some given graph is cycle-free, <#66906#><#37235#>find-route<#37235#><#66906#> produces some output for any given inputs. After all, every route can only contain a finite number of nodes, and the number of routes is finite, too. The function therefore either exhaustively inspects all solutions starting from some given node or finds a route from the origination to the destination node. If, however, a graph contains a cycle, that is, a route from some node back to itself, <#66907#><#37236#>find-route<#37236#><#66907#> may not produce a result for some inputs. In the next part, we will study a programming technique that helps us finds routes even in the presence of cycles in a graph.
<#37239#>Exercise 28.1.5<#37239#> Test <#66908#><#37241#>find-route<#37241#><#66908#> on <#66909#><#37242#>'<#37242#><#37243#>B<#37243#><#66909#>, <#66910#><#37244#>'<#37244#><#37245#>C<#37245#><#66910#>, and the graph in figure~#figcyclicgraph#37246>. Use the strategy of section~#secequaltest#37247> to formulate the tests as boolean-valued expression.~ external Solution<#66911#><#66911#> <#37253#>Exercise 28.1.6<#37253#> Reorganize the <#66912#><#37255#>find-route<#37255#><#66912#> program into a single function definition. Then remove parameters from the locally defined functions following the hints in intermezzo~C on the pragmatics of <#66913#><#37256#>local<#37256#><#66913#>.~ external Solution<#66914#><#66914#>