Termination

Unfortunately, the standard recipe is not good enough for the design of algorithms. Up to now, a function has always produced an output for any legitimate input. That is, the evaluation has always stopped. After all, by the nature of our recipe, each natural recursion consumes an immediate piece of the input, not the input itself. Because data is constructed in a hierarchical manner, this means that the input shrinks at every stage. Hence, the function sooner or later consumes an atomic piece of data and stops. With functions based on generative recursion, this is no longer true. The internal recursions don't consume an immediate component of the input but some new piece of data, which is generated from the input. As exercise~#exmoveuntil1#33667> shows, this step may produce the input over and over again and thus prevent the evaluation from ever producing a result. We say that the program <#66246#><#33668#>LOOPS<#33668#><#66246#> or is in an <#66247#><#33669#>INFINITE LOOP<#33669#><#66247#>. In addition, even the slightest mistake in translating the process description into a function definition may cause an infinite loop. The problem is most easily understood with an example. Consider the following definition of <#66248#><#33670#>smaller-items<#33670#><#66248#>, one of the two ``problem generators'' for <#66249#><#33671#>quick-sort<#33671#><#66249#>:
<#71469#>;; <#66250#><#33676#>smaller-items<#33676#> <#33677#>:<#33677#> <#33678#>(listof<#33678#> <#33679#>number)<#33679#> <#33680#>number<#33680#> <#33681#><#33681#><#33682#>-;SPMgt;<#33682#><#33683#><#33683#> <#33684#>(listof<#33684#> <#33685#>number)<#33685#><#66250#><#71469#>
<#71470#>;; to create a list with all those numbers on <#66251#><#33686#>alon<#33686#><#66251#> <#71470#> 
<#71471#>;; that are smaller than or equal to <#66252#><#33687#>threshold<#33687#><#66252#><#71471#> 
<#33688#>(d<#33688#><#33689#>efine<#33689#> <#33690#>(smaller-items<#33690#> <#33691#>alon<#33691#> <#33692#>threshold)<#33692#> 
  <#33693#>(c<#33693#><#33694#>ond<#33694#> 
    <#33695#>[<#33695#><#33696#>(empty?<#33696#> <#33697#>alon)<#33697#> <#33698#>empty]<#33698#> 
    <#33699#>[<#33699#><#33700#>else<#33700#> <#33701#>(if<#33701#> <#33702#>(;SPMlt;=<#33702#> <#33703#>(first<#33703#> <#33704#>alon)<#33704#> <#33705#>threshold)<#33705#> 
              <#33706#>(cons<#33706#> <#33707#>(first<#33707#> <#33708#>alon)<#33708#> <#33709#>(smaller-items<#33709#> <#33710#>(rest<#33710#> <#33711#>alon)<#33711#> <#33712#>threshold))<#33712#> 
              <#33713#>(smaller-items<#33713#> <#33714#>(rest<#33714#> <#33715#>alon)<#33715#> <#33716#>threshold))]<#33716#><#33717#>))<#33717#> 
Instead of <#66253#><#33721#>;SPMlt;<#33721#><#66253#> it employs <#66254#><#33722#>;SPMlt;=<#33722#><#66254#> to compare numbers. As a result, this function produces <#66255#><#33723#>(list<#33723#>\ <#33724#>5)<#33724#><#66255#> when applied to <#66256#><#33725#>(list<#33725#>\ <#33726#>5)<#33726#><#66256#> and <#66257#><#33727#>5<#33727#><#66257#>. Worse, if the <#66258#><#33728#>quick-sort<#33728#><#66258#> function from figure~#figqsort#33729> is combined with this new version of <#66259#><#33730#>smaller-items<#33730#><#66259#>, it doesn't produce any output for <#66260#><#33731#>(list<#33731#>\ <#33732#>5)<#33732#><#66260#>:
  <#33737#>(quick-sort<#33737#> <#33738#>(list<#33738#> <#33739#>5))<#33739#>
<#33740#>=<#33740#> <#33741#>(append<#33741#> <#33742#>(quick-sort<#33742#> <#33743#>(smaller-items<#33743#> <#33744#>5<#33744#> <#33745#>(list<#33745#> <#33746#>5)))<#33746#> 
          <#33747#>(list<#33747#> <#33748#>5)<#33748#> 
          <#33749#>(quick-sort<#33749#> <#33750#>(larger-items<#33750#> <#33751#>5<#33751#> <#33752#>(list<#33752#> <#33753#>5))))<#33753#> 
<#33754#>=<#33754#> <#33755#>(append<#33755#> <#72345#>#tex2html_wrap_inline73616#<#72345#> 
          <#33759#>(list<#33759#> <#33760#>5)<#33760#> 
          <#33761#>(quick-sort<#33761#> <#33762#>(larger-items<#33762#> <#33763#>5<#33763#> <#33764#>(list<#33764#> <#33765#>5))))<#33765#> 
The first recursive use demands that <#66262#><#33769#>quick-sort<#33769#><#66262#> solve the problem of sorting <#66263#><#33770#>(list<#33770#>\ <#33771#>5)<#33771#><#66263#>---but that is the exact problem that we started from. Since this is a circular evaluation, <#66264#><#33772#>(quick-sort<#33772#><#33773#> <#33773#><#33774#>(list<#33774#>\ <#33775#>5))<#33775#><#66264#> never produces a result. More generally, there is no guarantee that the size of the input for a recursive call brings us closer to a solution than the original input. The lesson from this example is that the design of algorithms requires one more step in our design recipe: a <#66265#><#33776#>TERMINATION ARGUMENT<#33776#><#66265#>, which explains why the process produces an output for every input and how the function implements this idea; or a <#66266#><#33777#>TERMINATION WARNING<#33777#><#66266#>, which explains when the process may not terminate. For <#66267#><#33778#>quick-sort<#33778#><#66267#>, the argument might look like this:
At each step, <#66268#><#33780#>quick-sort<#33780#><#66268#> partitions the list into two sublists using <#66269#><#33781#>smaller-items<#33781#><#66269#> and <#66270#><#33782#>larger-items<#33782#><#66270#>. Each function produces a list that is smaller than the input (the second argument), even if the threshold (the first argument) is an item on the list. Hence, each recursive application of <#66271#><#33783#>quick-sort<#33783#><#66271#> consumes a strictly shorter list than the given one. Eventually, <#66272#><#33784#>quick-sort<#33784#><#66272#> receives and returns <#66273#><#33785#>empty<#33785#><#66273#>.
Without such an argument an algorithm must be considered incomplete. A good termination argument may on occasion also reveal additional termination cases. For example, <#66274#><#33787#>(smaller-items<#33787#>\ <#33788#>N<#33788#>\ <#33789#>(list<#33789#>\ <#33790#>N))<#33790#><#66274#> and <#66275#><#33791#>(larger-items<#33791#>\ <#33792#>N<#33792#>\ <#33793#>(list<#33793#>\ <#33794#>N))<#33794#><#66275#> always produce <#66276#><#33795#>empty<#33795#><#66276#> for any <#66277#><#33796#>N<#33796#><#66277#>. Therefore we know that <#66278#><#33797#>quick-sort<#33797#><#66278#>'s answer for <#66279#><#33798#>(list<#33798#>\ <#33799#>N)<#33799#><#66279#> is <#66280#><#33800#>(list<#33800#>\ <#33801#>N)<#33801#><#66280#>. To add this knowledge to <#66282#><#33803#>quick-sort<#33803#><#66282#>, we simply add a <#66283#><#33804#>cond<#33804#><#66283#>-clause:
<#33809#>(d<#33809#><#33810#>efine<#33810#> <#33811#>(quick-sort<#33811#> <#33812#>alon)<#33812#>
  <#33813#>(c<#33813#><#33814#>ond<#33814#> 
    <#33815#>[<#33815#><#33816#>(empty?<#33816#> <#33817#>alon)<#33817#> <#33818#>empty]<#33818#> 
    <#33819#>[<#33819#><#33820#>(empty?<#33820#> <#33821#>(rest<#33821#> <#33822#>alon))<#33822#> <#33823#>alon]<#33823#> 
    <#33824#>[<#33824#><#33825#>else<#33825#> <#33826#>(a<#33826#><#33827#>ppend<#33827#> 
            <#33828#>(quick-sort<#33828#> <#33829#>(smaller-items<#33829#> <#33830#>alon<#33830#> <#33831#>(first<#33831#> <#33832#>alon)))<#33832#> 
            <#33833#>(list<#33833#> <#33834#>(first<#33834#> <#33835#>alon))<#33835#> 
            <#33836#>(quick-sort<#33836#> <#33837#>(larger-items<#33837#> <#33838#>alon<#33838#> <#33839#>(first<#33839#> <#33840#>alon))))]<#33840#><#33841#>))<#33841#> 
The condition <#66284#><#33845#>(empty?<#33845#>\ <#33846#>(rest<#33846#>\ <#33847#>alon))<#33847#><#66284#> is one way to ask the question whether <#66285#><#33848#>alon<#33848#><#66285#> contains one item.
<#33851#>Exercise 26.1.1<#33851#> Define the function <#66286#><#33853#>tabulate-div<#33853#><#66286#>, which accepts a number <#66287#><#33854#>n<#33854#><#66287#> and tabulates the list of all of its divisors, starting with <#66288#><#33855#>1<#33855#><#66288#> and ending in <#66289#><#33856#>n<#33856#><#66289#>. A number <#66290#><#33857#>d<#33857#><#66290#> is a divisior of a number <#66291#><#33858#>n<#33858#><#66291#> if the remainder of dividing <#66292#><#33859#>n<#33859#><#66292#> by <#66293#><#33860#>d<#33860#><#66293#> is <#66294#><#33861#>0<#33861#><#66294#>, that is, <#66295#><#33862#>(=<#33862#>\ <#33863#>(remainder<#33863#>\ <#33864#>n<#33864#>\ <#33865#>d)<#33865#>\ <#33866#>0)<#33866#><#66295#> is true. The smallest divisior of any number is <#66296#><#33867#>1<#33867#><#66296#>; the largest one is the number itself.~ external Solution<#66297#><#66297#> <#33873#>Exercise 26.1.2<#33873#> Develop the function <#66298#><#33875#>merge-sort<#33875#><#66298#>, which sorts a list of numbers in ascending order, using the following two auxiliary functions:
  1. The first one, <#66299#><#33877#>make-singles<#33877#><#66299#>, constructs a list of one-item lists from the given list of numbers. For example,
      <#33882#>(make-singles<#33882#> <#33883#>(list<#33883#> <#33884#>2<#33884#> <#33885#>5<#33885#> <#33886#>9<#33886#> <#33887#>3))<#33887#>
    <#33888#>=<#33888#> <#33889#>(list<#33889#> <#33890#>(list<#33890#> <#33891#>2)<#33891#> <#33892#>(list<#33892#> <#33893#>5)<#33893#> <#33894#>(list<#33894#> <#33895#>9)<#33895#> <#33896#>(list<#33896#> <#33897#>3))<#33897#> 
    
  2. The second one, <#66300#><#33901#>merge-all-neighbors<#33901#><#66300#>, merges pairs of neighboring lists. More specifically, it consumes a list of lists (of numbers) and merges neighbors. For example,
      <#33906#>(merge-all-neighbors<#33906#> <#33907#>(list<#33907#> <#33908#>(list<#33908#> <#33909#>2)<#33909#> <#33910#>(list<#33910#> <#33911#>5)<#33911#> <#33912#>(list<#33912#> <#33913#>9)<#33913#> <#33914#>(list<#33914#> <#33915#>3)))<#33915#>
    <#33916#>=<#33916#> <#33917#>(list<#33917#> <#33918#>(list<#33918#> <#33919#>2<#33919#> <#33920#>5)<#33920#> <#33921#>(list<#33921#> <#33922#>3<#33922#> <#33923#>9))<#33923#> 
      <#33924#>(merge-all-neighbors<#33924#> <#33925#>(list<#33925#> <#33926#>(list<#33926#> <#33927#>2<#33927#> <#33928#>5)<#33928#> <#33929#>(list<#33929#> <#33930#>3<#33930#> <#33931#>9)))<#33931#> 
    <#33932#>=<#33932#> <#33933#>(list<#33933#> <#33934#>(list<#33934#> <#33935#>2<#33935#> <#33936#>3<#33936#> <#33937#>5<#33937#> <#33938#>9))<#33938#> 
    
    In general, this function yields a list that is approximately half as long as the input. Why is the output not always half as long as the input?
Make sure to develop the functions independently. The function <#66301#><#33943#>merge-sort<#33943#><#66301#> first uses <#66302#><#33944#>make-singles<#33944#><#66302#> to create a list of single lists; then it relies on <#66303#><#33945#>merge-all-neighbors<#33945#><#66303#> to shorten the list of lists until it contains a single list. The latter is the result.~ external Solution<#66304#><#66304#>