Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
McCarthy 91 function
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{no footnotes|date=October 2015}} The '''McCarthy 91 function''' is a [[Recursion (computer science)|recursive function]], defined by the [[computer scientist]] [[John McCarthy (computer scientist)|John McCarthy]] as a test case for [[formal verification]] within [[computer science]]. The McCarthy 91 function is defined as :<math>M(n)=\begin{cases} n - 10, & \mbox{if }n > 100\mbox{ } \\ M(M(n+11)), & \mbox{if }n \le 100\mbox{ } \end{cases}</math> The results of evaluating the function are given by ''M''(''n'') = 91 for all integer arguments ''n'' β€ 100, and ''M''(''n'') = ''n'' − 10 for ''n'' > 100. Indeed, the result of M(101) is also 91 (101 - 10 = 91). All results of M(n) after n = 101 are continually increasing by 1, e.g. M(102) = 92, M(103) = 93. ==History== The 91 function was introduced in papers published by [[Zohar Manna]], [[Amir Pnueli]] and [[John McCarthy (computer scientist)|John McCarthy]] in 1970. These papers represented early developments towards the application of [[formal methods]] to [[formal verification|program verification]]. The 91 function was chosen for being nested-recursive (contrasted with [[single recursion]], such as defining <math>f(n)</math> by means of <math>f(n-1)</math>). The example was popularized by Manna's book, ''Mathematical Theory of Computation'' (1974). As the field of Formal Methods advanced, this example appeared repeatedly in the research literature. In particular, it is viewed as a "challenge problem" for automated program verification. It is easier to reason about [[tail recursion|tail-recursive]] control flow, this is an equivalent ([[extensionality|extensionally equal]]) definition: :<math>M_t(n)= M_t'(n,1)</math> :<math>M_t'(n, c)=\begin{cases} n, & \mbox{if }c = 0\\ M_t'(n-10, c-1), & \mbox{if }n > 100\mbox{ and } c \ne 0 \\ M_t'(n+11, c+1), & \mbox{if }n \le 100\mbox{ and } c \ne 0 \end{cases} </math> As one of the examples used to demonstrate such reasoning, Manna's book includes a tail-recursive algorithm equivalent to the nested-recursive 91 function. Many of the papers that report an "automated verification" (or [[termination proof]]) of the 91 function only handle the tail-recursive version. This is an equivalent [[mutual recursion|mutually]] tail-recursive definition: :<math>M_{mt}(n)= M_{mt}'(n,0)</math> :<math>M_{mt}'(n,c)=\begin{cases} M_{mt}''(n-10,c), & \mbox{if }n > 100\mbox{ } \\ M_{mt}'(n+11,c+1), & \mbox{if }n \le 100\mbox{ } \end{cases}</math> :<math>M_{mt}''(n,c)=\begin{cases} n, & \mbox{if }c = 0\mbox{ } \\ M_{mt}'(n,c-1), & \mbox{if }c \ne 0\mbox{ } \end{cases}</math> A formal derivation of the mutually tail-recursive version from the nested-recursive one was given in a 1980 article by [[Mitchell Wand]], based on the use of [[continuation]]s. ==Examples== Example A: M(99) = M(M(110)) since 99 β€ 100 = M(100) since 110 > 100 = M(M(111)) since 100 β€ 100 = M(101) since 111 > 100 = 91 since 101 > 100 Example B: M(87) = M(M(98)) = M(M(M(109))) = M(M(99)) = M(M(M(110))) = M(M(100)) = M(M(M(111))) = M(M(101)) = M(91) = M(M(102)) = M(92) = M(M(103)) = M(93) .... Pattern continues increasing till M(99), M(100) and M(101), exactly as we saw on the example A) = M(101) since 111 > 100 = 91 since 101 > 100 ==Code== Here is an implementation of the nested-recursive algorithm in [[Lisp (programming language)|Lisp]]: <syntaxhighlight lang="lisp"> (defun mc91 (n) (cond ((<= n 100) (mc91 (mc91 (+ n 11)))) (t (- n 10)))) </syntaxhighlight> Here is an implementation of the nested-recursive algorithm in [[Haskell]]: <syntaxhighlight lang="haskell"> mc91 n | n > 100 = n - 10 | otherwise = mc91 $ mc91 $ n + 11 </syntaxhighlight> Here is an implementation of the nested-recursive algorithm in [[OCaml]]: <syntaxhighlight lang="ocaml"> let rec mc91 n = if n > 100 then n - 10 else mc91 (mc91 (n + 11)) </syntaxhighlight> Here is an implementation of the tail-recursive algorithm in [[OCaml]]: <syntaxhighlight lang="ocaml"> let mc91 n = let rec aux n c = if c = 0 then n else if n > 100 then aux (n - 10) (c - 1) else aux (n + 11) (c + 1) in aux n 1 </syntaxhighlight> Here is an implementation of the nested-recursive algorithm in [[Python (programming language)|Python]]: <syntaxhighlight lang="python"> def mc91(n: int) -> int: """McCarthy 91 function.""" if n > 100: return n - 10 else: return mc91(mc91(n + 11)) </syntaxhighlight> Here is an implementation of the nested-recursive algorithm in [[C (programming language)|C]]: <syntaxhighlight lang="c"> int mc91(int n) { if (n > 100) { return n - 10; } else { return mc91(mc91(n + 11)); } } </syntaxhighlight> Here is an implementation of the tail-recursive algorithm in [[C (programming language)|C]]: <syntaxhighlight lang="c"> int mc91(int n) { return mc91taux(n, 1); } int mc91taux(int n, int c) { if (c != 0) { if (n > 100) { return mc91taux(n - 10, c - 1); } else { return mc91taux(n + 11, c + 1); } } else { return n; } } </syntaxhighlight> ==Proof== Here is a proof that the McCarthy 91 function <math>M</math> is equivalent to the non-recursive algorithm <math>M'</math>defined as: :<math>M'(n)=\begin{cases} n - 10, & \mbox{if }n > 100\mbox{ } \\ 91, & \mbox{if }n \le 100\mbox{ } \end{cases}</math> For ''n'' > 100, the definitions of <math>M'</math> and <math>M</math> are the same. The equality therefore follows from the definition of <math>M</math>. For ''n'' β€ 100, a [[strong induction]] downward from 100 can be used: For 90 β€ ''n'' β€ 100, M(n) = M(M(n + 11)), by definition = M(n + 11 - 10), since n + 11 > 100 = M(n + 1) This can be used to show ''M''(''n'') = ''M''(101) = 91 for 90 β€ ''n'' β€ 100: M(90) = M(91), M(n) = M(n + 1) was proven above = β¦ = M(101), by definition = 101 β 10 = 91 ''M''(''n'') = ''M''(101) = 91 for 90 β€ ''n'' β€ 100 can be used as the base case of the induction. For the downward induction step, let ''n'' β€ 89 and assume ''M''(''i'') = 91 for all ''n'' < ''i'' β€ 100, then M(n) = M(M(n + 11)), by definition = M(91), by hypothesis, since n < n + 11 β€ 100 = 91, by the base case. This proves ''M''(''n'') = 91 for all ''n'' β€ 100, including negative values. == Knuth's generalization == [[Donald Knuth]] generalized the 91 function to include additional parameters.<ref>{{cite journal |first=Donald E. |last=Knuth | title = Textbook Examples of Recursion | year = 1991 | journal = Artificial Intelligence and Mathematical Theory of Computation |pages=207β229 |doi=10.1016/B978-0-12-450010-5.50018-9 | arxiv = cs/9301113| bibcode = 1993cs........1113K |isbn=9780124500105 |s2cid=6411737 }}</ref> [[John Cowles (mathematician)|John Cowles]] developed a formal proof that Knuth's generalized function was total, using the [[ACL2]] theorem prover.<ref>{{cite book |first=John |last=Cowles | chapter = Knuth's generalization of McCarthy's 91 function |editor-first=M. |editor-last=Kaufmann |editor2-first=P. |editor2-last=Manolios |editor3-first=J |editor3-last=Strother Moore | title = Computer-Aided reasoning: ACL2 case studies | publisher = Kluwer Academic |isbn=9781475731880 |year=2013 |orig-year = 2000 | pages = 283β299 |chapter-url = http://www.cs.utexas.edu/users/moore/acl2/workshop-1999/Cowles-abstract.html}}</ref> == References == {{Reflist}} * {{cite journal |first1=Zohar |last1=Manna |first2=Amir |last2=Pnueli |title=Formalization of Properties of Functional Programs |journal=Journal of the ACM |date=July 1970 |volume=17 |issue=3 |pages=555β569 |doi=10.1145/321592.321606|s2cid=5924829 |doi-access=free }} * {{cite journal |first1=Zohar |last1=Manna |first2=John |last2=McCarthy |title=Properties of programs and partial function logic |journal=Machine Intelligence |year=1970 |volume=5 |oclc=35422131}} * {{cite book |first=Zohar |last=Manna |title=Mathematical Theory of Computation |publisher=McGraw-Hill |year=1974 |edition=4th |isbn=9780070399105}} * {{cite journal |first=Mitchell |last=Wand |title=Continuation-Based Program Transformation Strategies |journal=Journal of the ACM |date=January 1980 |volume=27 |issue=1 |pages=164β180 |doi=10.1145/322169.322183|s2cid=16015891 |doi-access=free }} {{John McCarthy}} [[Category:Articles with example C code]] [[Category:Articles with example Haskell code]] [[Category:Articles with example Lisp (programming language) code]] [[Category:Articles with example OCaml code]] [[Category:Articles with example Python (programming language) code]] [[Category:Formal methods]] [[Category:Recurrence relations]]
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)
Pages transcluded onto the current version of this page
(
help
)
:
Template:Cite book
(
edit
)
Template:Cite journal
(
edit
)
Template:John McCarthy
(
edit
)
Template:No footnotes
(
edit
)
Template:Reflist
(
edit
)