<#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.
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#>.~ Solution<#66791#><#66791#>
<#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>
<#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.
<#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#>
<#37099#>Backtracking in the Structural World<#37099#>:\ Intermezzo~3 briefly discusses
backtracking in the structural world. A particularly good example is
exercise #exlocalinterm3#37100>
<#37111#>Exercise 28.1.3<#37111#>
<#37135#>Figure: A directed graph with cycle<#37135#>
Consider the graph in figure~#figcyclicgraph#37137> <#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>
<#37239#>Exercise 28.1.5<#37239#>