<RT·article>
- <RT·counter·make counter="RT·Figure·counter" style="CountingNumber" mode="scoped"></RT·counter·make>
- <RT·counter·make counter="RT·Table·counter" style="CountingNumber" mode="scoped"></RT·counter·make>
- <RT·counter·make counter="RT·List·counter" style="CountingNumber" mode="scoped"></RT·counter·make>
- <RT·counter·make counter="RT·Equation·counter" style="CountingNumber" mode="scoped"></RT·counter·make>
- <RT·counter·make counter="RT·Code·counter" style="CountingNumber" mode="scoped"></RT·counter·make>
+ <RT·Counter·make counter="RT·Figure·counter" style="CountingNumber" mode="scoped"></RT·Counter·make>
+ <RT·Counter·make counter="RT·Table·counter" style="CountingNumber" mode="scoped"></RT·Counter·make>
+ <RT·Counter·make counter="RT·List·counter" style="CountingNumber" mode="scoped"></RT·Counter·make>
+ <RT·Counter·make counter="RT·Equation·counter" style="CountingNumber" mode="scoped"></RT·Counter·make>
+ <RT·Counter·make counter="RT·Code·counter" style="CountingNumber" mode="scoped"></RT·Counter·make>
<RT·title
title="Computational Naturalism"
<RT·section id="Section·acknowledgment">
<RT·name>Acknowledgment</RT·name>
- <p>This RT Iterator library work was sponsored by Reasoning Technology Inc. They have been kind enough to allow the library to be made public under an MIT license and placed on GitHub.</p>
+ <p>The RT Iterator library work was sponsored by Reasoning Technology Inc. They have been kind enough to allow the library to be made public under an MIT license and placed on GitHub.</p>
<p>This text was written separately, and was only possible due to the support of my loving wife Shihju.</p>
</RT·section>
<p>All communication is founded upon common knowledge, so here are some notes on the conventions used in this book.</p>
- <p>Generally in this book, containers such as sequences and sets are capital letters, even when in Greek. Mathematical objects that are not containers are represented with lower case letters. Character pairs or full symbol names can also be used to represent mathematical objects. The context will make it clear if a non-letter unicode character is used to represent a container or a non-container.
- </p>
-
- <p>The unicode middle dot, ·, is used as an ad hoc namespace operator in identifiers. Hence, <RT·code>N·x</RT·code>, would be the variable <RT·code>x</RT·code> from the <RT·code>N</RT·code> namespace. This is a typography symbol. It can be seen for example when words are broken into symbols, e.g. 'op·er·a·tor', and sometimes in names, such as 'Leonardo da·Vinci', and 'Vincent van·Gogh'. It is accepted in identifiers by modern C compilers, and it is part of the RT·gcc compiler mods for gcc.</p>
-
- <p>I have experimented with modern gender forms in technical language in past writings. For example, I used the plural-as-singular style in one piece, and was applauded by some, though categorized as illiterate by others. Since then, I have evolved a writing style that emphasizes using roles as subjects: the mathematician, the author, the programmer. Such subjects are singular, so for grammatical agreement, I use the <em>inclusive he</em>. It is structurally much cleaner to use <em>he</em> as inclusive of all people than it is to gray out an entire category of plural agreement pronouns by forcing words such as "they" to take on a singular form. I use "a person" when the subject is an unknown third party, potentially even being an AI. I prefer this over the 'one' of 'One does this, or one does that.' so that 'one' can be reserved to unambiguously refer to the number.</p>
-
- <p>In the prior edition of this book, the preface included a discussion on the meaning of the word "may" according to RFC 2119, the guidelines for specification writing. There is an important distinction between the 'may' of options or permission, and the more colloquial 'may' of probability. However, distinguishing between the two was too much of an ask of readers, most of whom skip the preface anyway. So in this edition, I avoid the temptation to use 'may' and replace it with a direct statement of what I mean. "It is of high probability that..." or "There are options for...". Directly saying what is meant, who would have thought of it? The RFC 2119 authors have apparently struggled with this as well, as they now require the MAY and the other words that appear in RFC 2119 to be capitalized so as to dodge the grammar debate.</p>
+ <p>In math spans and blocks, each container, such as a sequence or a set, is represented with a single capital letter, even when in Greek. Each object that is not a container is represented with a single lower case letter. Character pairs or full symbol names can also be used to represent math objects. In which case the same convention is followed for the first letter of the symbol, while the remain letters are lower case. The context will make it clear if a non-letter Unicode character represents a container or a non-container.</p>
- <p>Code examples in this text follow the distinctive RT code format conventions.<RT·endnote>For the complete specification, refer to RT-code-format.html and RT-code-format-Lisp.html located at https://github.com/Thomas-Walker-Lynch/RT-Style/tree/core-developer_branch/developer/document.</RT·endnote> For example, horizontal comma-separated lists apply a space before the comma to bind the punctuation to the item being appended to the list:</p>
+ <p>Code blocks and spans follow the RT code format conventions, which resemble the math conventions above but are not identical to them.<RT·endnote>For the complete specification, refer to RT-code-format.html and RT-code-format-Lisp.html located at https://github.com/Thomas-Walker-Lynch/RT-Style/tree/core-developer_branch/developer/document.</RT·endnote> For example, unlike for math scopes, comma-separated lists apply a space before the comma and bind the punctuation directly to the item being appended to the list:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·comma-list_example">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·comma-list_example"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·comma-list_example">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·comma-list_example"></RT·Counter·snapshot>
<RT·code>
int x ,y ,z;
</RT·code>
- Code <RT·counter·read snapshot="Code·comma-list_example"></RT·counter·read>. <RT·name>A horizontal comma-separated list</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·comma-list_example"></RT·Counter·read>. <RT·name>A horizontal comma-separated list</RT·name>
+ </RT·Counter·step>
<p>Multi-level enclosures receive a single space of padding only on the outermost boundary:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·enclosure-padding_example">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·enclosure-padding_example"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·enclosure-padding_example">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·enclosure-padding_example"></RT·Counter·snapshot>
<RT·code>
if( f(g(x)) ){
</RT·code>
- Code <RT·counter·read snapshot="Code·enclosure-padding_example"></RT·counter·read>. <RT·name>Padding applied to the outermost enclosure only</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·enclosure-padding_example"></RT·Counter·read>. <RT·name>Padding applied to the outermost enclosure only</RT·name>
+ </RT·Counter·step>
- <p>Identifier naming leverages both hyphens and underscores, when available, to establish semantic binding precedence. An example of this is:</p>
+ <p>Code containers are PascaleCase, and when allowed, non-container identifiers are snake-kebab_case, thus leveraging both hyphens and underscores to establish semantic binding precedence. An example of this is:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·identifier-separator_example">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·identifier-separator_example"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·identifier-separator_example">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·identifier-separator_example"></RT·Counter·snapshot>
<RT·code>
rounded_x-coordinate
</RT·code>
- Code <RT·counter·read snapshot="Code·identifier-separator_example"></RT·counter·read>. <RT·name>A hyphen binding tighter than an underscore within an identifier</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·identifier-separator_example"></RT·Counter·read>. <RT·name>A hyphen binding tighter than an underscore within an identifier</RT·name>
+ </RT·Counter·step>
- <p>In this coding culture, we say that argument values are <em>given</em> to a function. Functions do not <em>take</em> arguments, as it is the caller that has authority over making the call, and thus over sending the arguments. A function is only said to <em>accept</em> or <em>reject</em> a value in the context of guard code evaluating argument validity, something it has authority to do. Similarly, machines, factories, and software <em>make</em> objects by assembling components they are given; they do not <em>create</em> them, since bringing components into being is not within an engineer's authority. That leaves 'creation' to imply a more fundamental synthesis outside the scope of engineering, perhaps done by artists or supernatural beings.</p>
+ <p>Throughout, this text uses native Unicode characters rather than escape sequences. Where a mathematical or Greek symbol is wanted, the character itself appears, so the text carries 'δ' rather than <RT·code>\delta</RT·code>. This might lead to some small typesetting variations compared to what MathJax might otherwise have output.</p>
- <p>Whenever standard mathematical or Greek symbols are required, this text utilizes native Unicode characters rather than relying on escape sequences. For example, the text uses 'δ' directly instead of, say, "\delta"; this might lead to some small typesetting variations.</p>
+ <p>The Unicode middle dot, ·, is used as an ad hoc namespace operator in identifiers. Hence <RT·code>N·x</RT·code> would be the variable <RT·code>x</RT·code> from the <RT·code>N</RT·code> namespace. This is a typographic symbol with a long history of use as a separator. It appears in dictionaries where words are broken into syllables, e.g. 'op·er·a·tor'. It is a letter of the Catalan alphabet, the <em>punt volat</em>, which distinguishes the geminate <RT·code>l·l</RT·code> of 'col·legi' from the digraph <RT·code>ll</RT·code>. And Japanese uses it, as the <em>nakaguro</em>, to separate the components of a transliterated foreign name. It is accepted in identifiers by modern C compilers,<RT·endnote>C11 permits the character anywhere in an identifier, including as the first character: it falls in the 00B7−00BA range of Annex D.1, and appears in none of the ranges disallowed initially in D.2. C23 restates the rule in terms of Unicode UAX #31, where the character belongs to Other_ID_Continue and so remains permitted, though no longer in first position. ISO/IEC 9899:2011, Annex D; ISO/IEC 9899:2024, §6.4.2.</RT·endnote> and it is part of the RT·gcc compiler mods as an ad hoc namespace operator.</p>
- <p>Dates and times are given in the ISO 8601 format. The components run from the most-significant to the least-significant, year, then month, then day, in the same order the digits of a Hindu-Arabic numeral run. Two consequences follow from that ordering, and both are the reason for choosing it. A lexicographic comparison of two such dates agrees with their chronological comparison, so a list of them sorts correctly with no collation rules particular to dates. And the format is unambiguous, whereas a date such as 03/04/2026 is read as the third of April by some readers and the fourth of March by others. A time of day, when one is given, follows the date, and a trailing <RT·code>Z</RT·code> marks the time as UTC. Hence <RT·code>2026-06-01 08:28:00Z</RT·code>. Where a date appears without a time, the date alone is intended, e.g. <RT·code>2026-06-01</RT·code>. As per the standard, if the day is not to be specified it is simply dropped, e.g. <RT·code>2026-06</RT·code>.</p>
+ <p>In the RT coding culture, we say that argument values are <em>given</em> to a function. Functions do not <em>take</em> arguments, as it is the caller that has authority over making the call, and thus over sending the arguments. A function is only said to <em>accept</em> or <em>reject</em> a value in the context of guard code evaluating argument validity, something it has authority to do. Similarly, machines, factories, and software <em>make</em> objects by assembling components they are given; they do not <em>create</em> them, since bringing components into being is not within an engineer's authority. That leaves 'creation' to imply a more fundamental synthesis outside the scope of engineering, perhaps done by artists or supernatural beings.</p>
- <p>
- Several words in this book carry a formal definition that displaces their ordinary English sense, and those are capitalized: <RT·term>Peano Number</RT·term>, <RT·term>Integer</RT·term>, <RT·term>Rational</RT·term>, <RT·term>Real</RT·term>. The word <em>real</em> is the best example of why this is done. It was too much of an ask by mathematics to take a common English adjective and hold it to a technical meaning, and a reader is entitled to know which sense is in play. So a Real is the object mathematics defines, and a real problem or a real difficulty is the ordinary English word. Integer suffers no such ambiguity. It is capitalized for consistency with its siblings.
- </p>
- <p>
- The leading capital letter on the mathematical number types does not distinguish the classical notion from the one constructed herein, because this book denies that the two are distinct in the first place. A Real is a Real whether a mathematician defines it or a machine produces the definition.
- </p>
- <p>
- What mathematics calls the natural numbers are called <RT·term>Peano Numbers</RT·term> in this book. A Peano Number is what a Peano Machine outputs. This convention frees the word 'Natural' to refer to the philosophy only, so a reader never has to work out which of the two is meant. Note that herein Peano Numbers are taken to begin at zero, while <RT·term>Counting Numbers</RT·term> begin at one, and the two are not the same.<RT·endnote>Peano's own axioms began at one. Modern presentations of Peano arithmetic begin at zero, and that is the convention followed here. Giuseppe Peano, <em>Arithmetices principia, nova methodo exposita</em> (Turin: Bocca, 1889), §1.</RT·endnote> An Integer, a Rational, and a Real are likewise the outputs of machines, each constructed in its turn.
- </p>
+ <p>I have experimented with modern gender forms in technical language in past writings. For example, I used the plural-as-singular style in one piece, and was applauded by some, though categorized as illiterate by others. Since then, I have evolved a writing style that emphasizes using roles as subjects: the mathematician, the author, the programmer. Such subjects are singular, so for grammatical agreement, I use the <em>inclusive he</em>. It is structurally much cleaner to use <em>he</em> as inclusive of all people than it is to gray out an entire category of plural agreement pronouns by forcing words such as 'they' to take on a singular form. I use 'a person' when the subject is an unknown third party, who might even be an AI. I prefer this over the 'one' of 'One does this, or one does that', so that 'one' can be reserved to unambiguously refer to the number.</p>
+
+ <p>In the prior edition of this book, the preface included a discussion on the meaning of the word 'may' according to RFC 2119, which fixes the requirement level key words used in specification writing. There is an important distinction between the 'may' of options or permission, and the more colloquial 'may' of probability. However, distinguishing between the two was too much of an ask of readers, most of whom skip the preface anyway. So in this edition, I avoid the temptation to use 'may' and replace it with a direct statement of what I mean. "It is of high probability that..." or "There are options for...". Directly saying what is meant, who would have thought of it? The RFC series has since narrowed the word further. RFC 8174 amended RFC 2119 so that the key words carry their defined meanings only when written in capitals, which leaves a lower case 'may' in an RFC with no normative force at all.<RT·endnote>Scott Bradner, <em>Key words for use in RFCs to Indicate Requirement Levels</em>, RFC 2119, March 1997. Barry Leiba, <em>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</em>, RFC 8174, May 2017.</RT·endnote></p>
+
+ <p>Dates and times are given in the ISO 8601 format. The components run from the most-significant to the least-significant, year, then month, then day, in the same order the digits of a Hindu-Arabic numeral run. Two consequences follow from that ordering, and both are the reason for choosing it. A lexicographic comparison of two such dates agrees with their chronological comparison, so a list of them sorts correctly with no collation rules particular to dates. And the format is unambiguous, whereas a date such as 03/04/2026 is read as the third of April by some readers and the fourth of March by others. A time of day, when one is given, follows the date, and a trailing <RT·code>Z</RT·code> marks the time as UTC. Hence <RT·code>2026-06-01 08:28:00Z</RT·code>. ISO 8601 itself separates the date from the time with a <RT·code>T</RT·code>, which is difficult to read. RFC 3339 anticipates the objection and permits a space in its place, and that is the option taken here.<RT·endnote>Graham Klyne and Chris Newman, <em>Date and Time on the Internet: Timestamps</em>, RFC 3339, July 2002, §5.6.</RT·endnote> Where a date appears without a time, the date alone is intended, e.g. <RT·code>2026-06-01</RT·code>. As per the standard, if the day is not to be specified, it is simply dropped, e.g. <RT·code>2026-06</RT·code>.</p>
+
+ <p>Several words in this book carry a formal definition that displaces their ordinary English sense, and those are capitalized: <RT·term>Peano Number</RT·term>, <RT·term>Integer</RT·term>, <RT·term>Rational</RT·term>, <RT·term>Real</RT·term>. The word <em>real</em> is the best example of why this is done. It was too much of an ask by mathematics to take a common English adjective and hold it to a technical meaning, and a reader is entitled to know which sense is in play. So a Real is the object mathematics defines, and a real problem or a real difficulty is the ordinary English word. Integer suffers no such ambiguity. It is capitalized for consistency with its siblings.</p>
+
+ <p>The leading capital letter on the mathematical number types does not distinguish the classical notion from the one constructed herein, because this book denies that the two are distinct in the first place. A Real is a Real whether a mathematician defines it or a machine produces the definition.</p>
+ <p>What mathematics calls the natural numbers are called <RT·term-em>Peano Number</RT·term-em>s in this book. A Peano Number is what a Peano Machine outputs. This convention frees the word 'Natural' to refer to the philosophy only, so a reader never has to work out which of the two is meant. Note that herein Peano Numbers are taken to begin at zero, while <RT·term>Counting Numbers</RT·term> begin at one, and the two are not the same.<RT·endnote>Peano's own axioms began at one. Modern presentations of Peano arithmetic begin at zero, and that is the convention followed here. Giuseppe Peano, <em>Arithmetices principia, nova methodo exposita</em> (Turin: Bocca, 1889), §1.</RT·endnote> An Integer, a Rational, and a Real are likewise the outputs of machines, each constructed in its turn.</p>
- <p>This book discusses four theoretical computing machines: two kinds of Turing Machine, which are not realizable, and two kinds of <RT·term>RT Machine</RT·term>, which are.</p>
+ <p>This book discusses four theoretical computing machines: two types of Turing Machine, which are not realizable, and two types of RT Machine, which are. What blocks realization of the first pair, and what removes the block from the second, is the subject of the chapters that follow.</p>
- <p>The first kind of <RT·term>Turing Machine</RT·term> has a fixed controller, and that controller determines the machine's behavior. Colloquially, a person could say that the program it runs is built-in. There can be many instances of this kind, each with a different built-in program, which is why the term Turing Machine is sometimes used in the sense of a computer program, and is sometimes plural. The program of such a machine cannot be changed, though the same input tape can be mounted on another Turing Machine having a different controller.</p>
+ <p>The first type of <RT·term>Turing Machine</RT·term> has a fixed controller, and that controller determines the machine's behavior. Colloquially, a person could say that the program it runs is built-in. There can be many instances of this type, each with a different built-in program, which is why the term Turing Machine is sometimes used in the sense of a computer program, and is sometimes plural. The program of such a machine cannot be changed, though the same input tape can be mounted on another Turing Machine having a different controller.</p>
- <p>The second kind is the <RT·term>Universal Turing Machine</RT·term>, which reads its program from its tape. Each tape then gives the machine its own personality, so the built-in controller of a Universal Turing Machine is an interpreter. There is no reason there could not be several Universal Turing Machines, each with a different interpreter for reading the program from the tape. Hence, where this text speaks of a Turing Machine reading a program from a tape, it refers to a Universal Turing Machine; and where it speaks of a program, it refers to data that, when written to a tape, could be executed by a Universal Turing Machine.</p>
+ <p>The second type is the <RT·term>Universal Turing Machine</RT·term>, which reads its program from its tape. Each tape then gives the machine its own personality, so the built-in controller of a Universal Turing Machine is an interpreter. There is no reason there could not be several Universal Turing Machines, each with a different interpreter for reading the program from the tape. Hence, where this text speaks of a Turing Machine reading a program from a tape, it refers to a Universal Turing Machine; and where it speaks of a program, it refers to data that, when written to a tape, could be executed by a Universal Turing Machine.</p>
- <p>The <RT·term>RT Machine</RT·term> is a variation on the Turing Machine, and it comes in the same two kinds: one with a built-in controller, and one that reads its program from the tape. Unlike the Turing Machine, the RT Machine belongs to a class of realizable machines.</p>
+ <p>The <RT·term>RT Machine</RT·term> is a variation on the Turing Machine, and it comes in the same two types: one with a built-in controller, and one that reads its program from the tape. Unlike the Turing Machine, the RT Machine belongs to a class of realizable machines.</p>
</RT·section>
<RT·section id="Section·preface">
<RT·name>Preface</RT·name>
- <p>One afternoon I was fortunate to have lunch in Berkeley with Bill Kahan, a pioneer in applied number theory, and our conversation turned to errors in numeric computation. I observed that an error is merely an opportunity to do more computing. Bill seemed to like the remark; he repeated it in a <em>Dr. Dobb's</em> interview, where it was credited to him. When we met again, I asked him about it. He apologized, explaining that the interviewer had created something rather than reporting it, and that he was surprised himself by what he read. The apology was unnecessary. I had intended to summarize Kahan's own work. He was instrumental in creating IEEE Std. 754, where an exceptional condition, more informally an "error", need not end computation but can serve as a gateway to a higher symbolic algebra. I found that architecture inspiring, and my comment had been intended to acknowledge his inspiration.</p>
+ <p>One afternoon I was fortunate to have lunch in Berkeley with Bill Kahan, a pioneer in applied number theory, and our conversation turned to errors in numeric computation. I observed that an error is merely an opportunity to do more computing. Bill seemed to like the remark; he repeated it in a <em>Dr. Dobb's</em> interview, where it was credited to him.<RT·endnote>TODO·cite: the <em>Dr. Dobb's</em> interview, issue and date.</RT·endnote> When we met again, I asked him about it. He apologized, explaining that the interviewer had created something rather than reporting it, and that he was himself surprised by what he read. The apology was unnecessary. I had intended to summarize Kahan's own work. He was instrumental in creating IEEE Std 754, where an exceptional condition, more informally an 'error', need not end computation but can serve as a gateway to a higher symbolic algebra. I found that architecture inspiring, and my comment had been meant to acknowledge the debt.</p>
- <p>In practical computing the symbol algebra of the IEEE Std. 754 quickly devolves into the catch-all indeterminate value, the so-called <em>NaN</em>, which tends to leave programmers wishing to extend the system. Kulisch and Miranker attempted to formalize computer arithmetic, and started by reasoning about a screen that laid out over the real number space. Boehm and Cartwright introduced a concept of Constructive Real Numbers, where precision of computation was extended upon demand. And through Stephen Wolfram's vision, Mathematica provides a complete symbolic math manipulation package, where a symbolic expression can be reduced before being evaluated. For evaluation they then track loss of precision through significance arithmetic. In my own work, I have suggested an analysis step first, where required precision is derived, followed by computation. However, among these there is still missing a formalism of passing through the gateway upon an error, so to speak. Mathematica comes the closest.</p>
+ <p>In practical computing the symbol algebra of IEEE Std 754 quickly devolves into the catch-all indeterminate value, the so-called <em>NaN</em>, which tends to leave programmers wishing to extend the system. Kulisch and Miranker attempted to formalize computer arithmetic, and started by reasoning about a screen that lay over the real number space.<RT·endnote>Ulrich W. Kulisch and Willard L. Miranker, <em>Computer Arithmetic in Theory and Practice</em> (New York: Academic Press, 1981).</RT·endnote> Boehm and Cartwright introduced a concept of Constructive Real Numbers, where precision of computation was extended upon demand. And through Stephen Wolfram's vision, Mathematica provides a complete symbolic math manipulation package, where a symbolic expression can be reduced before being evaluated. Mathematica then tracks loss of precision through significance arithmetic. In my own work, I have suggested an analysis step first, where required precision is derived, followed by computation. However, among these there is still missing a formalism of passing through the gateway upon an error, so to speak. Mathematica comes the closest. Each of these is taken up in its turn later in this book, and the citations are given there.</p>
- <p>John Gustafson also brought up the topic of the nature of error shortly before publishing "The End of Error". He now has another proposal based on variable precision arithmetic known as "posits". There was so much I wanted to say when we spoke, but I could not formulate the thoughts. I had learned a great deal while doing formal analysis of the algorithms I had put on the Am29050, Am486, and K5 processors at AMD, but when I tried to articulate this, I only stammered. I feel that I fell short, as all I could do was point at my already published work at that time on high radix online arithmetic. So this volume is my answer to John's question. Albeit it is a little late, well years late, but I hope it will still have some value.</p>
+ <p>John Gustafson also brought up the topic of the nature of error shortly before publishing <em>The End of Error</em>. He now has another proposal, the posit, which abandons the variable width operands of his earlier unums in favour of a fixed width whose internal field boundaries move, so that accuracy is greatest for magnitudes near one and tapers toward the extremes of the range. John grilled me over the method I had used, and what he was pressing on was the question of how a computation is to know what precision it needs. I answered with High Radix Online Arithmetic and with the importance of variable precision, but I could not formulate the rest of the thoughts. I had learned a great deal while doing formal analysis of the algorithms I had put on the Am29050, Am486, and K5 processors at AMD, yet when I tried to articulate this, I only stammered. I feel that I fell short, as all I could do was point at my already published work at that time on High Radix Online Arithmetic. So this volume is my answer to John's question. It is a little late, well years late, but I hope it will still have some value.</p>
- <p>There is a first edition of this book. The same concepts are described in those pages, but the story is not as well told, and no one has come full circle to say it made any sense to them. Well, one colleague, after reviewing the first edition, admitted he was bewildered by it and asked if I was proposing that we build Turing Machines. After all we are the music makers, in the music business, so to speak; only instead of being written in notes, our music is written in transistors and layout. So then, he rightfully asks, what is the proposal here? I can only point him at Mitch Alsup's book, and ponder how I can tell this story differently.</p>
+ <p>There is a first edition of this book.<RT·endnote>TODO·cite: the first edition, and the Quicklisp release of the Lisp library.</RT·endnote> The same concepts are described in those pages, but the story is not as well told, and no one has come full circle to say that it made sense. Well, one reader did come back. Kelvin Goveas, a colleague and a dear friend, reviewed the first edition, admitted he was bewildered by it, and asked whether I was proposing that we build Turing Machines. After all, we are the music makers,<RT·endnote>Arthur O'Shaughnessy, "Ode", in <em>Music and Moonlight</em> (London: Chatto and Windus, 1874).</RT·endnote> in the music business, so to speak; only instead of being written in notes, our music is written in transistors and layout. So then, he rightly asked, what is the proposal here? I have yet to give him an answer. The best I can do is point him at Mitch Alsup's architecture book,<RT·endnote>TODO·cite: Mitch Alsup's architecture book. Title and publication details to be confirmed; his My 66000 architecture is the subject.</RT·endnote> where the proposals are, and go on pondering how I can tell this story differently.</p>
- <p>There is not a hardware specification for a new proposed machine in this book. This book is not proposing to build in hardware a Turing Machine. This is an absolute. Building a RT Machine might be interesting, and the organization for it is described in this book, but that is certainly not the proposal here. Rather this book lays the foundation for a proposal for another machine. It explains and justifies that other machine's features. But the details, the architecture, of this other machine are not found in these pages.</p>
+ <p>There is no hardware specification for a new machine in this book, and no proposal to build a Turing Machine in hardware. This is an absolute. The RT Machine is an improved computation theoretic model, and what distinguishes it from the Turing Machine is that it can be realized, which is what saves the Naturalist thesis. Its organization is described in these pages, and building one might be interesting, but there is no suggestion here that microprocessors should be made that way. This volume is the second edition of the first of four that were envisioned, leading in the end to the TTCA Machine, which is a real machine, and which I proposed building in 2005. What this book does is lay the foundation for that proposal, and explain and justify the features such a machine will need. The architecture itself is not found in these pages.</p>
- <p>There is a practical aspect to this work. A software library that is of general usefulness can be found in these pages, and downloaded from GitHub. The library was first articulated in the Lisp language in the first edition of the book and released on Quicklisp. Lisp is in a sense pure, and formal statements can be made with it. Using it for the library made the library a natural small step away from the formal discussion that came before it was presented. Since that time I have written parts of the library in other languages and found it very useful. This volume presents the Python API.</p>
+ <p>There is a practical aspect to this work. A software library that is of general usefulness can be found in these pages, and downloaded from GitHub. It was first articulated in the Lisp language in the first edition of the book and released on Quicklisp. Lisp is in a sense pure, and formal statements can be made with it, so writing the library there kept it a small and natural step away from the formal discussion that precedes it. Since that time I have written parts of the library in other languages and found it useful. This volume presents the Python API.</p>
<p>A Peano Number is a computational structure, as its name records. It starts with emptiness, a zero, and is then built up by repeated application of the successor function. Because a number is a computational structure, number theory was already computation theory before Church, Turing, and their contemporaries gave the subject its name. It is a computation theory whose discussion is confined to the relationships among Peano structures, which is to say, to Peano Numbers. Then the activity of writing algorithms and designing circuits that relate those structures to one another, in the service of solving real problems, is applied number theory.</p>
</p>
<p>
- The authority to remove Russell's Paradox set formulation comes from the set <RT·math>S</RT·math>. If we know its definition, then the authority comes through that definition. However, if we merely stipulate that <RT·math>S</RT·math> must be defined, then we are expressing our authority through <RT·math>S</RT·math> by declaring, "Undefined sets are not allowed." In the explanation above, it is only after discovering a set is undefined that we conclude it is not a member of <RT·math>S</RT·math>. I sometimes wonder how mathematics might have evolved had Frege simply taken that approach. We take this question up again in chapter <RT·counter·read snapshot="Section·computational-naturalism"></RT·counter·read>, Computational Naturalism, and discover there is a deeper issue.
+ The authority to remove Russell's Paradox set formulation comes from the set <RT·math>S</RT·math>. If we know its definition, then the authority comes through that definition. However, if we merely stipulate that <RT·math>S</RT·math> must be defined, then we are expressing our authority through <RT·math>S</RT·math> by declaring, "Undefined sets are not allowed." In the explanation above, it is only after discovering a set is undefined that we conclude it is not a member of <RT·math>S</RT·math>. I sometimes wonder how mathematics might have evolved had Frege simply taken that approach. We take this question up again in chapter <RT·Counter·read snapshot="Section·computational-naturalism"></RT·Counter·read>, Computational Naturalism, and discover there is a deeper issue.
</p>
<p>
Turing employed an enumerative diagonal argument to establish this result. A simpler proof by contradiction that is commonly used today was first published by Christopher Strachey in 1965 <RT·endnote>Christopher Strachey, "An Impossible Program," <em>The Computer Journal</em> 7, no. 4 (January 1965): 313. In his letter, Strachey explicitly attributed the distilled logic to an existing "well known piece of folklore among programmers."</RT·endnote>. To begin the proof, assume a person builds a perfect decider program, <RT·math>H(p, i)</RT·math>, that evaluates any given program <RT·math>p</RT·math> executing with input <RT·math>i</RT·math>, then outputs 'Y' if <RT·math>p(i)</RT·math> halts, and 'N' if it does not halt. Next, a person writes a malicious program, <RT·math>M(x)</RT·math>, that incorporates <RT·math>H</RT·math> as a subroutine. When <RT·math>M</RT·math> receives an input program <RT·math>x</RT·math>, it evaluates <RT·math>H(x, x)</RT·math> to determine how program <RT·math>x</RT·math> behaves when given itself as input. If <RT·math>H(x, x)</RT·math> outputs 'Y', <RT·math>M</RT·math> enters an infinite loop; if <RT·math>H(x, x)</RT·math> outputs 'N', <RT·math>M</RT·math> immediately halts.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·halting_diagonal-machine">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·halting_diagonal-machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·halting_diagonal-machine">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·halting_diagonal-machine"></RT·Counter·snapshot>
<RT·code>
M( x ){
if( H(x ,x) == 'Y' ) while( true );
else if( H(x ,x) == 'N' ) return;
}
</RT·code>
- Code <RT·counter·read snapshot="Code·halting_diagonal-machine"></RT·counter·read>. <RT·name>The diagonal machine that defeats a supposed halting decider</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·halting_diagonal-machine"></RT·Counter·read>. <RT·name>The diagonal machine that defeats a supposed halting decider</RT·name>
+ </RT·Counter·step>
<p>
The evil part occurs when we give program <RT·math>M(x)</RT·math> itself as input, <RT·math>M(M)</RT·math>. Program <RT·math>M</RT·math> calls its subroutine and asks <RT·math>H(M, M)</RT·math> what <RT·math>M</RT·math> will do. If <RT·math>H</RT·math> outputs 'Y', it is wrong, because <RT·math>M</RT·math> loops infinitely. If <RT·math>H</RT·math> outputs 'N', then it is wrong, because <RT·math>M</RT·math> halts. The decider <RT·math>H</RT·math> is forced into an inescapable failure, proving that no universal decider can exist.
These are the discernible levels of the computer design abstraction stack:
</p>
- <RT·counter·step counter="RT·List·counter" id="List·abstraction-stack_levels">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·abstraction-stack_levels"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·abstraction-stack_levels">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·abstraction-stack_levels"></RT·Counter·snapshot>
<ol>
<li><RT·term-em>mathematical logic</RT·term-em></li>
<li><RT·term-em>computation theory</RT·term-em></li>
<li><RT·term-em>implementation</RT·term-em></li>
<li><RT·term-em>realization</RT·term-em></li>
</ol>
- List <RT·counter·read snapshot="List·abstraction-stack_levels"></RT·counter·read>. <RT·name>The six levels of the computer design abstraction stack</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·abstraction-stack_levels"></RT·Counter·read>. <RT·name>The six levels of the computer design abstraction stack</RT·name>
+ </RT·Counter·step>
<p>
<RT·term>Mathematical logic</RT·term> underpins the computation theory level. <RT·term>Computation theory</RT·term> speaks of the time and space complexity of algorithms and the existence of solutions to decider problems, which in turn guides the goals of the architecture and organization levels.
</p>
<p>
- It is not a requirement of a computer organization, nor of an architecture, that it be capable of physical realization. The abstract Turing Machine organization developed in chapter <RT·counter·read snapshot="Section·RT_machine-design"></RT·counter·read> serves as an example. Instead, an abstract organization can serve other purposes, in this case as a stepping stone to another organization that can be realized.
+ It is not a requirement of a computer organization, nor of an architecture, that it be capable of physical realization. The abstract Turing Machine organization developed in chapter <RT·Counter·read snapshot="Section·RT_machine-design"></RT·Counter·read> serves as an example. Instead, an abstract organization can serve other purposes, in this case as a stepping stone to another organization that can be realized.
</p>
<p>
The Turing Machine is a computation theory object that is suggestive of a simple architecture, and a computer organization. A person who has had to do homework problems centered on Turing Machines will have tracked the flow of data through the machine, i.e. worked at the register-transfer level. However, a little work is needed to complete the architecture analog. The fundamentals are present: the read/write head, the tape, and the procedure for using the tape. Other things are missing, or are left unspecified:
</p>
- <RT·counter·step counter="RT·List·counter" id="List·Turing-Machine_missing-components">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·Turing-Machine_missing-components"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·Turing-Machine_missing-components">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·Turing-Machine_missing-components"></RT·Counter·snapshot>
<ol>
<li>The manipulation of symbols remains ungrounded.</li>
<li>The tape is not well defined.</li>
<li>The tape transport is not articulated, though it is implied.</li>
<li>The read buffer is not identified as a component. One is required so that the programmed controller can do a write without clobbering the read data needed for the next transition.</li>
</ol>
- List <RT·counter·read snapshot="List·Turing-Machine_missing-components"></RT·counter·read>. <RT·name>What the Turing Machine leaves out of its architecture</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·Turing-Machine_missing-components"></RT·Counter·read>. <RT·name>What the Turing Machine leaves out of its architecture</RT·name>
+ </RT·Counter·step>
<p>
As we proceed, we will likely discover other missing components.
Suppose we are given a Turing Machine <RT·math>m_i</RT·math>, which will potentially be run after being given any one of a number of input tapes <RT·math>x_{i,j}</RT·math>. For each of those inputs, the same tape with the results written upon it will be <RT·math>r_{i,j}</RT·math>. We notate this as:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·machine_result_notation">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·machine_result_notation"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·machine_result_notation">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·machine_result_notation"></RT·Counter·snapshot>
<RT·math>
m_i(x_{i,j}) = r_{i,j}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·machine_result_notation"></RT·counter·read> <RT·name>Machine m_i given input tape x_{i,j} writes result tape r_{i,j}</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·machine_result_notation"></RT·Counter·read> <RT·name>Machine m_i given input tape x_{i,j} writes result tape r_{i,j}</RT·name>
+ </RT·Counter·step>
<p>
Here the subscripts of the same name set up a correspondence. <RT·math>x_{i,j}</RT·math> is the <RT·math>j</RT·math>th input to the machine <RT·math>m_i</RT·math>, etc. The free variable <RT·math>j</RT·math> runs over all the interesting distinct input tapes to be given to machine <RT·math>m_i</RT·math>. So for example, if we had a machine, say <RT·math>m_8</RT·math>, and we had a set of three inputs to be given to <RT·math>m_8</RT·math>, then:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·machine_result_example">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·machine_result_example"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·machine_result_example">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·machine_result_example"></RT·Counter·snapshot>
<RT·math>
\begin{aligned}
m_8(x_{8,0}) &= r_{8,0} \\
m_8(x_{8,2}) &= r_{8,2}
\end{aligned}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·machine_result_example"></RT·counter·read> <RT·name>Machine m_8 over a set of three input tapes</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·machine_result_example"></RT·Counter·read> <RT·name>Machine m_8 over a set of three input tapes</RT·name>
+ </RT·Counter·step>
<p>
Another machine, perhaps machine <RT·math>m_7</RT·math>, would have its own distinct inputs <RT·math>x_{7,j}</RT·math>, etc.
Now suppose that a machine <RT·math>m_{i.1}</RT·math> is the result of a transformation, <RT·math>T</RT·math>, applied to machine <RT·math>m_i</RT·math>.
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·transform_notation">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·transform_notation"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·transform_notation">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·transform_notation"></RT·Counter·snapshot>
<RT·math>
m_i \xrightarrow{T} m_{i.1}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·transform_notation"></RT·counter·read> <RT·name>Transform T carries machine m_i to machine m_{i.1}</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·transform_notation"></RT·Counter·read> <RT·name>Transform T carries machine m_i to machine m_{i.1}</RT·name>
+ </RT·Counter·step>
<p>
We can then assign a property to transform <RT·math>T</RT·math> called its <RT·neologism>doesn't change results</RT·neologism> property, as follows. If and only if:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·same-results_single-machine">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·same-results_single-machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·same-results_single-machine">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·same-results_single-machine"></RT·Counter·snapshot>
<RT·math>
\forall j \colon r_{i,j} = r_{i.1,j}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·same-results_single-machine"></RT·counter·read> <RT·name>The doesn't change results condition for one machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·same-results_single-machine"></RT·Counter·read> <RT·name>The doesn't change results condition for one machine</RT·name>
+ </RT·Counter·step>
<p>
then <RT·math>T</RT·math> doesn't change <RT·math>m_i</RT·math> results. Here we note that we are evaluating a specific machine <RT·math>m_i</RT·math>, so we must add the qualifier '<RT·math>m_i</RT·math> results'. It might be that for another machine with another corresponding set of interesting inputs, the transform would lead to a new machine that produces different results.
If, and only if, it is the case that
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·same-results_all-machines">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·same-results_all-machines"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·same-results_all-machines">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·same-results_all-machines"></RT·Counter·snapshot>
<RT·math>
\forall i, \forall j \colon r_{i,j} = r_{i.1,j}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·same-results_all-machines"></RT·counter·read> <RT·name>The same results transform property, over all machines</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·same-results_all-machines"></RT·Counter·read> <RT·name>The same results transform property, over all machines</RT·name>
+ </RT·Counter·step>
<p>
then we can say without qualification that <RT·math>T</RT·math> is a <RT·neologism>same results transform</RT·neologism>. Though still implied are the sets of machines and tapes.
Suppose we also have a computation theory <RT·math>C</RT·math> that allows us to analyze some machines so as to answer some questions we find interesting. Suppose furthermore that among these questions are questions of time and space complexity, along with zero or more questions about decidability. Furthermore, we are given a machine, say <RT·math>m_i</RT·math>, for which these questions have answers. We represent this as:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·question_answer_notation">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·question_answer_notation"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·question_answer_notation">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·question_answer_notation"></RT·Counter·snapshot>
<RT·math>
a_{i,k} = q_{i,k}(m_i, \{x_{i,j}\})
</RT·math>
- eq: <RT·counter·read snapshot="Equation·question_answer_notation"></RT·counter·read> <RT·name>A computation theoretic question and the answer it has for a machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·question_answer_notation"></RT·Counter·read> <RT·name>A computation theoretic question and the answer it has for a machine</RT·name>
+ </RT·Counter·step>
<p>
Here, <RT·math>\{x_{i,j}\}</RT·math> represents the entire domain of <RT·math>j</RT·math> tapes being passed as arguments to the question <RT·math>q_{i,k}</RT·math>. From this, we can observe that if there are <RT·math>n_k</RT·math> questions, then we will have <RT·math>n_k</RT·math> answers. Also, for a specific machine <RT·math>m_i</RT·math>, where there are <RT·math>n_j</RT·math> <RT·math>j</RT·math> values, the domain over which <RT·math>m_i</RT·math> will be analyzed will have <RT·math>n_j</RT·math> tapes in it.
As we had already discovered when determining that <RT·math>T</RT·math> is a same results transform, <RT·math>T</RT·math> transforms machine <RT·math>m_i</RT·math> into machine <RT·math>m_{i.1}</RT·math>.
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·transform_restated">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·transform_restated"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·transform_restated">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·transform_restated"></RT·Counter·snapshot>
<RT·math>
m_i \xrightarrow{T} m_{i.1}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·transform_restated"></RT·counter·read> <RT·name>Transform T carries machine m_i to machine m_{i.1}, restated</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·transform_restated"></RT·Counter·read> <RT·name>Transform T carries machine m_i to machine m_{i.1}, restated</RT·name>
+ </RT·Counter·step>
<p>
For our specific machine <RT·math>m_i</RT·math>, if and only if:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·inconsequential_single-machine">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·inconsequential_single-machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·inconsequential_single-machine">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·inconsequential_single-machine"></RT·Counter·snapshot>
<RT·math>
\forall k \colon a_{i,k} = a_{i.1,k}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·inconsequential_single-machine"></RT·counter·read> <RT·name>The inconsequential condition for one machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·inconsequential_single-machine"></RT·Counter·read> <RT·name>The inconsequential condition for one machine</RT·name>
+ </RT·Counter·step>
<p>
then <RT·math>T</RT·math> is computation theoretic inconsequential for <RT·math>m_i</RT·math>.
If, and only if, it is the case that:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·inconsequential_all-machines">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·inconsequential_all-machines"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·inconsequential_all-machines">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·inconsequential_all-machines"></RT·Counter·snapshot>
<RT·math>
\forall i, \forall k \colon a_{i,k} = a_{i.1,k}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·inconsequential_all-machines"></RT·counter·read> <RT·name>The computation theoretic inconsequential transform property</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·inconsequential_all-machines"></RT·Counter·read> <RT·name>The computation theoretic inconsequential transform property</RT·name>
+ </RT·Counter·step>
<p>
then we can say without qualification that <RT·math>T</RT·math> is <RT·neologism>computation theoretic inconsequential</RT·neologism>. Though still implied are the sets of machines, tapes, and questions.
<p>This definition comes from Hopcroft and Ullman's book with minor terminology changes to make it flow into the text here <RT·endnote>John E. Hopcroft and Jeffrey D. Ullman, <em>Introduction to Automata Theory, Languages, and Computation</em> (Reading: Addison-Wesley, 1979).</RT·endnote>.
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·conventional-machine_definition">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-machine_definition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·conventional-machine_definition">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-machine_definition"></RT·Counter·snapshot>
<RT·math>
M = (Q, Σ, Γ, δ, q_0, □, F)
</RT·math>
- eq: <RT·counter·read snapshot="Equation·conventional-machine_definition"></RT·counter·read> <RT·name>The conventional Turing Machine as a seven tuple</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·conventional-machine_definition"></RT·Counter·read> <RT·name>The conventional Turing Machine as a seven tuple</RT·name>
+ </RT·Counter·step>
<p>Each component of the Machine, <RT·math>M</RT·math>, is defined as follows:</p>
- <RT·counter·step counter="RT·List·counter" id="List·conventional-machine_components">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·conventional-machine_components"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·conventional-machine_components">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·conventional-machine_components"></RT·Counter·snapshot>
<ul>
<li><RT·math>Q</RT·math>: The finite set of <em>states</em> of the programmed finite state machine controller.</li>
<li><RT·math>Σ</RT·math>: The finite set of <em>input symbols</em>.</li>
<li><RT·math>F</RT·math>: The set of <em>final</em> or <em>accepting</em> states, a subset of <RT·math>Q</RT·math>.</li>
</ul>
- List <RT·counter·read snapshot="List·conventional-machine_components"></RT·counter·read>. <RT·name>The components of the conventional Turing Machine M</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·conventional-machine_components"></RT·Counter·read>. <RT·name>The components of the conventional Turing Machine M</RT·name>
+ </RT·Counter·step>
<p>I introduced the qualifier <em>programmed</em> in front of the <em>finite state machine controller</em> because each Turing Machine that accomplishes a different task has a different finite state machine controller. A <RT·term-em>program</RT·term-em> is then a set of assignments to the variable parts of the Turing Machine definition. Notice that additional variables are needed by the Turing Machine executor beyond those that appear in the definition, such as the current state variable. In alternative terminology, the definition above defines a Turing Machine <RT·term-em>type</RT·term-em>, and a set of assignments to the variable parts of the definition constitutes an <RT·term-em>instance</RT·term-em>. Accordingly, then, when a computer arithmetician says he has two Turing Machine<em>s</em>, he is saying that he has two distinct sets of Turing Machine variable assignments, and as these sets are distinct, each can be manipulated independently.</p>
<p>Hopcroft and Ullman explain a step of the machine by showing a representation of the tape with the state variable melded in to the left of the currently scanned symbol. Suppose <RT·math>δ(q, X_i) = (p, Y, L)</RT·math>; i.e., the next move is leftward. Then,
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·instantaneous-description_left-move">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·instantaneous-description_left-move"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·instantaneous-description_left-move">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·instantaneous-description_left-move"></RT·Counter·snapshot>
<RT·math>
X_1 X_2 ⋯ X_{i-1} q X_i X_{i+1} ⋯ X_n \underset{M}{⊢} X_1 X_2 ⋯ X_{i-2} p X_{i-1} Y X_{i+1} ⋯ X_n
</RT·math>
- eq: <RT·counter·read snapshot="Equation·instantaneous-description_left-move"></RT·counter·read> <RT·name>An instantaneous description rewritten by a leftward move</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·instantaneous-description_left-move"></RT·Counter·read> <RT·name>An instantaneous description rewritten by a leftward move</RT·name>
+ </RT·Counter·step>
<p>So first the tape is <RT·math>X_1 X_2 ⋯ X_{i-1} X_i X_{i+1} ⋯ X_n</RT·math>, with the head over <RT·math>X_i</RT·math>, and in state <RT·math>q</RT·math>. Then after a step of the machine, the tape is <RT·math>X_1 X_2 ⋯ X_{i-1} Y X_{i+1} ⋯ X_n</RT·math>, with the head over <RT·math>X_{i-1}</RT·math>, and in state <RT·math>p</RT·math>. Thus <RT·math>X_i</RT·math> was overwritten with <RT·math>Y</RT·math>, and the head stepped left.
</p>
<p>Here is the programmed controller for a Turing Machine that reverses a binary string. Although by definition each state transition matches exactly one value under the head, as a practical matter, disjunctive selection is allowed via a comma list. A conjunctive phrasing for a state transition proposition would require stringing intermediate states in series.</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·conventional_reverse-machine">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·conventional_reverse-machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·conventional_reverse-machine">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·conventional_reverse-machine"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="HU_style_TM_reverse.png" class="RT·diagram" alt="HU reverse machine">
</figure>
- Figure <RT·counter·read snapshot="Figure·conventional_reverse-machine"></RT·counter·read>. <RT·name>A conventional Turing Machine that reverses a binary string</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·conventional_reverse-machine"></RT·Counter·read>. <RT·name>A conventional Turing Machine that reverses a binary string</RT·name>
+ </RT·Counter·step>
<p>Provided the site is still alive, the following YAML can be entered at TuringMachine.io to watch the machine run.</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·conventional-reverse_YAML">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·conventional-reverse_YAML"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·conventional-reverse_YAML">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·conventional-reverse_YAML"></RT·Counter·snapshot>
<RT·code>
# YAML
# Reverses a binary string using a single marker and an EOM terminator.
done:
</RT·code>
- Code <RT·counter·read snapshot="Code·conventional-reverse_YAML"></RT·counter·read>. <RT·name>The conventional reverse machine, as TuringMachine.io YAML</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·conventional-reverse_YAML"></RT·Counter·read>. <RT·name>The conventional reverse machine, as TuringMachine.io YAML</RT·name>
+ </RT·Counter·step>
<p>By default a newly initialized machine always starts with the head on the leftmost tape cell. The input is specified to be placed one square past the initial blank on the tape. This allows the leftmost blank to be used as a reliable start of input marker later when it is scanning left. The machine begins by reading this initial blank and stepping right. If it immediately encounters another blank, the string is empty and the machine is done. Otherwise, it sweeps right to place an end of message marker, E, immediately after the string. It then enters a repetitive process: it walks left to locate the next unprocessed input symbol, overwrites it with an asterisk to mark it as read, and then carries that remembered value rightward to deposit it at the new end of the sequence. By executing this back and forth shuttle, the machine systematically builds the reversed string to the right of the E, finishing by sweeping through to erase its temporary markers.</p>
<p>The following trace demonstrates the reversal of the string "110" using the same head embedded in the tape diagram as was used above, with a small variation. Here the head position is indicated using a bullet character, while the current state is listed in the left column. The empty symbol prints as a space. If you align the first line at the top of your window and scroll down, the execution plays out like an animation.</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·conventional-reverse_trace">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·conventional-reverse_trace"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·conventional-reverse_trace">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·conventional-reverse_trace"></RT·Counter·snapshot>
<RT·code>
q_init • 1 1 0
q1 •1 1 0
q5 •0 1 1
done • 0 1 1
</RT·code>
- Code <RT·counter·read snapshot="Code·conventional-reverse_trace"></RT·counter·read>. <RT·name>A step-by-step trace of the conventional reverse machine</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·conventional-reverse_trace"></RT·Counter·read>. <RT·name>A step-by-step trace of the conventional reverse machine</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>The total number of steps for reversing an <RT·math>n</RT·math> symbol string:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·conventional-reverse_step-count">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-reverse_step-count"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·conventional-reverse_step-count">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-reverse_step-count"></RT·Counter·snapshot>
<RT·math>
\text{steps} =
\begin{cases}
3n^2 + 6n + 5 & \text{if } n \ge 1
\end{cases}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·conventional-reverse_step-count"></RT·counter·read> <RT·name>Steps taken by the conventional reverse machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·conventional-reverse_step-count"></RT·Counter·read> <RT·name>Steps taken by the conventional reverse machine</RT·name>
+ </RT·Counter·step>
<p>This shows string reversal to be an <RT·math>O(n^2)</RT·math> complexity problem, which might appear to some programmers as a peculiar result, as the same problem can be solved in <RT·math>O(n)</RT·math> time with a C program. This justifies further analysis.</p>
<p>For a realized machine, symbols are machine word encodings. For example, ASCII uses 7 data bits, so there are 128 symbols available. If the width of the word for encoding symbols is <RT·math>n</RT·math> bits, then the total number of states required for this string reverse machine is:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·conventional-reverse_state-count">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-reverse_state-count"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·conventional-reverse_state-count">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-reverse_state-count"></RT·Counter·snapshot>
<RT·math>
\text{states} = 2^n + 8
</RT·math>
- eq: <RT·counter·read snapshot="Equation·conventional-reverse_state-count"></RT·counter·read> <RT·name>States required by the conventional reverse machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·conventional-reverse_state-count"></RT·Counter·read> <RT·name>States required by the conventional reverse machine</RT·name>
+ </RT·Counter·step>
<p>The number of arcs in the machine:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·conventional-reverse_arc-count">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-reverse_arc-count"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·conventional-reverse_arc-count">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·conventional-reverse_arc-count"></RT·Counter·snapshot>
<RT·math>
\text{arcs} = 2^{2n} + 9(2^n) + 12
</RT·math>
- eq: <RT·counter·read snapshot="Equation·conventional-reverse_arc-count"></RT·counter·read> <RT·name>Arcs required by the conventional reverse machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·conventional-reverse_arc-count"></RT·Counter·read> <RT·name>Arcs required by the conventional reverse machine</RT·name>
+ </RT·Counter·step>
<p>These equations show that the state controller size explodes with word width. It would be impractical to implement for all but the smallest of word sizes. This is one of the reasons that computation theory books use modest-sized symbol alphabets in their examples, perhaps the first few letters of the Latin alphabet, or the letter 's' for unary arithmetic. Previous sections discussed challenges transitioning the Turing Machine to a modern architecture due to the tape length, and discussed how this could be mitigated. In contrast, there is no practical mediation for implementing a Turing Machine controller even for modest-sized real problems.</p>
<p>The observation runs the other way as well. There is not a single chapter dedicated to computation theory in Hennessy and Patterson's definitive textbook on computer architecture. <RT·endnote>John L. Hennessy and David A. Patterson, <em>Computer Architecture: A Quantitative Approach</em>, 6th ed. (Cambridge: Morgan Kaufmann, 2017).</RT·endnote></p>
- <RT·counter·step counter="RT·Table·counter" id="Table·Hennessy-Patterson_chapters">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·Hennessy-Patterson_chapters"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·Hennessy-Patterson_chapters">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·Hennessy-Patterson_chapters"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<tbody>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·Hennessy-Patterson_chapters"></RT·counter·read>. <RT·name>The chapter list of Hennessy and Patterson, Computer Architecture: A Quantitative Approach</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·Hennessy-Patterson_chapters"></RT·Counter·read>. <RT·name>The chapter list of Hennessy and Patterson, Computer Architecture: A Quantitative Approach</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>Because emptiness is a property of a container, Turing's first statement can be modeled with a sequence of sets. For a Turing Machine tape, each sequence member is either an empty set or a singleton set. In the language of mathematics an empty tape can be defined as a empty sets:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·empty-tape_as_empty-sets">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·empty-tape_as_empty-sets"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·empty-tape_as_empty-sets">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·empty-tape_as_empty-sets"></RT·Counter·snapshot>
<RT·math>
T_0 = [ \{ \}, \{ \}, \{ \}, \dots ]
</RT·math>
- eq: <RT·counter·read snapshot="Equation·empty-tape_as_empty-sets"></RT·counter·read> <RT·name>An empty tape written as a sequence of empty sets</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·empty-tape_as_empty-sets"></RT·Counter·read> <RT·name>An empty tape written as a sequence of empty sets</RT·name>
+ </RT·Counter·step>
<p>Here, each tape member set is called a <RT·term>cell</RT·term>. This definition for an empty tape is specific to Turing Machines, as in mathematics an empty sequence has zero length. An empty tape is not an empty sequence, rather it is an infinite sequence where every member is an empty set. In one sense this is a little peculiar that something said to be empty is infinite, in another sense it is consistent for the model that an empty Turing Machine tape keeps its defining characteristics. That is, it remains a single-ended Turing Machine tape, where any cell of the tape could be written with a symbol value, while the basic form of the tape will not change.</p>
<p>So we might imagine a tape machine, say called machine A, where, upon attempting to read an empty cell, the machine head instead returns a control symbol representing that the cell was empty. To accomplish this, the head would have to do some work; it would have to be able to detect emptiness, and then choose to return the empty symbol instead of a read value. This feature would fix the problem of not having any defined next-state behavior for an empty cell. Furthermore, suppose the inverse process is also special in that upon attempting to write the empty symbol, the machine takes action, emptying the cell out. This would facilitate an erase operation.</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·empty-cell_read">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·empty-cell_read"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·empty-cell_read">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·empty-cell_read"></RT·Counter·snapshot>
<RT·code>
def read(c):
if is_empty(c):
else:
return c.get()
</RT·code>
- Code <RT·counter·read snapshot="Code·empty-cell_read"></RT·counter·read>. <RT·name>Reading a cell that can be empty</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·empty-cell_read"></RT·Counter·read>. <RT·name>Reading a cell that can be empty</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Code·counter" id="Code·empty-cell_write">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·empty-cell_write"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·empty-cell_write">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·empty-cell_write"></RT·Counter·snapshot>
<RT·code>
def write(c ,x):
if not is_empty(c):
if x != 'empty':
c.put(x) # Place the new symbol unless we are erasing
</RT·code>
- Code <RT·counter·read snapshot="Code·empty-cell_write"></RT·counter·read>. <RT·name>Writing a cell, where writing the empty symbol erases it</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·empty-cell_write"></RT·Counter·read>. <RT·name>Writing a cell, where writing the empty symbol erases it</RT·name>
+ </RT·Counter·step>
<p>Now imagine machine B, where the concept of an empty cell is jettisoned, and what remains is the mere memory of emptiness, a symbol called <RT·code>empty</RT·code>. Then using the language of mathematics, the mathematician defines an initial empty tape as:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·empty-tape_with_empty-symbol">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·empty-tape_with_empty-symbol"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·empty-tape_with_empty-symbol">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·empty-tape_with_empty-symbol"></RT·Counter·snapshot>
<RT·math>
T_0 = [ \mathtt{empty}, \mathtt{empty}, \mathtt{empty}, \ldots ]
</RT·math>
- eq: <RT·counter·read snapshot="Equation·empty-tape_with_empty-symbol"></RT·counter·read> <RT·name>An empty tape written with the empty symbol</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·empty-tape_with_empty-symbol"></RT·Counter·read> <RT·name>An empty tape written with the empty symbol</RT·name>
+ </RT·Counter·step>
<p>For machine B, no modifications are required to the native <RT·code>read</RT·code> and <RT·code>write</RT·code> functions.</p>
<p>Like the <RT·code>empty</RT·code> symbol, <RT·code>unspecified</RT·code> is a meta-symbol. It describes the data, or lack thereof, rather than being the data. Specifically, the <RT·code>unspecified</RT·code> symbol says that another machine, a machine A, would have a singular alphabet symbol at the memory location, but our machine B is not being informed as to which symbol it is. Because the Turing Machine state transition function requires a specific symbol value, reading an <RT·code>unspecified</RT·code> symbol, and then using it to make a decision as though it were a concrete symbol, would be an error, unless that control path was for the very purpose of detecting this error.</p>
<p>Reasons that memory can be <RT·code>unspecified</RT·code> include:</p>
- <RT·counter·step counter="RT·List·counter" id="List·unspecified_causes">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·unspecified_causes"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·unspecified_causes">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·unspecified_causes"></RT·Counter·snapshot>
<ol>
<li>The memory was not initialized.</li>
<li>The memory holds stale data written by an unrelated process, such as a reused memory allocation.</li>
<li>The data is effectively unspecified because the program, by design, does not make decisions based upon its value.</li>
</ol>
- List <RT·counter·read snapshot="List·unspecified_causes"></RT·counter·read>. <RT·name>Reasons a memory location can hold an unspecified value</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·unspecified_causes"></RT·Counter·read>. <RT·name>Reasons a memory location can hold an unspecified value</RT·name>
+ </RT·Counter·step>
<p>An example of effectively unspecified data would be a program that reverses a string without looking at the values being reversed. A string reverse function need not inspect the value of the string; it only needs to recognize the structural boundaries established by the writing protocol. Yet the conventional Turing Machine is incapable of doing this, and worse, as we saw, there is an explosion in the number of states for the reverse string controller against word length.</p>
<RT·name>The modifications</RT·name>
<p>The specific architectural modifications are as follows:</p>
- <RT·counter·step counter="RT·List·counter" id="List·RT_modifications">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·RT_modifications"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·RT_modifications">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·RT_modifications"></RT·Counter·snapshot>
<ol>
<li>There is one unified alphabet <RT·math>Σ</RT·math> to which both status symbols and data symbols belong.</li>
<li>The machine utilizes a Moore-style programmed state controller, with zero or one instruction specified per state, so that instructions are independent and managed separately from state transitions.</li>
</ol>
</li>
</ol>
- List <RT·counter·read snapshot="List·RT_modifications"></RT·counter·read>. <RT·name>The architectural modifications that distinguish the RT Machine</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·RT_modifications"></RT·Counter·read>. <RT·name>The architectural modifications that distinguish the RT Machine</RT·name>
+ </RT·Counter·step>
<p>Here the subscript <RT·math>i</RT·math> is a device used to emphasize that <RT·math>q_i</RT·math> and <RT·math>q_{i+1}</RT·math> can be any members of the total set of states, <RT·math>Q</RT·math>. State <RT·math>q_0</RT·math> refers specifically to the initial state. Also note, later the spartan <RT·math>q</RT·math> will be used to denote the contents of the <RT·code>q register</RT·code>, the current state register.</p>
<p>The Hopcroft and Ullman machine definition specified a next-state function, <RT·math>δ</RT·math>. Here we instead use next-state tables that cascade, and as tables are containers, we denote these using a capital letter as <RT·math>Δ_0</RT·math>, <RT·math>Δ_1</RT·math>, <RT·math>Δ_2</RT·math>, and <RT·math>Δ_3</RT·math>.</p>
<p>The new machine evaluates next-state transitions through these four layers, in order, progressing to the next layer only when no transition is found in the prior layer:</p>
- <RT·counter·step counter="RT·List·counter" id="List·transition_layers">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·transition_layers"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·transition_layers">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·transition_layers"></RT·Counter·snapshot>
<ol>
<li><strong>Conditional (<RT·math>Δ_0</RT·math>):</strong> Selects the transition rule that matches the current state and the value of the status register.</li>
<li><strong>State Default (<RT·math>Δ_1</RT·math>):</strong> Selects the default transition rule that matches the current state.</li>
<li><strong>Status Default (<RT·math>Δ_2</RT·math>):</strong> Selects the default transition rule that matches the current machine status.</li>
<li><strong>Global Default (<RT·math>Δ_3</RT·math>):</strong> A single table that holds the next-state of last resort.</li>
</ol>
- List <RT·counter·read snapshot="List·transition_layers"></RT·counter·read>. <RT·name>The four next-state transition layers, in evaluation order</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·transition_layers"></RT·Counter·read>. <RT·name>The four next-state transition layers, in evaluation order</RT·name>
+ </RT·Counter·step>
<p>Programmers will typically use the Global Default arc, <RT·math>Δ_3</RT·math>, to take the machine to an error state when they have mistakenly left the next-state transition undefined. However, it is conceivable for some machines that if no other next-state is defined, there is a single logical state that should be visited, and this condition is not an error. If no Global Default arc is specified, and no next-state is found, the machine hangs.</p>
<RT·section>
<RT·name>The RT Machine fixed part</RT·name>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-part">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-part"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-part">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-part"></RT·Counter·snapshot>
<RT·math>
\mathit{MF} = (\mathit{QF}, \mathit{ΣF}, \mathit{AF})
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_fixed-part"></RT·counter·read> <RT·name>MF, the fixed part of the RT Machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_fixed-part"></RT·Counter·read> <RT·name>MF, the fixed part of the RT Machine</RT·name>
+ </RT·Counter·step>
<p>In the following, the middle dot acts as a namespace operator, <RT·math>N{·}x</RT·math>. By doing this we assure there will be no aliasing with the symbols provided by the programmer when he defines a programmed state controller.</p>
<p>The set of predefined <em>states</em>:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-states">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-states"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-states">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-states"></RT·Counter·snapshot>
<RT·math>
\mathit{QF} = \{\mathit{QF}{·}\mathtt{initial}\}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_fixed-states"></RT·counter·read> <RT·name>QF, the set of predefined states</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_fixed-states"></RT·Counter·read> <RT·name>QF, the set of predefined states</RT·name>
+ </RT·Counter·step>
<p>The state controller always starts in the <RT·code>QF·initial</RT·code> state. This is a symbol representing the state; it is not a register that holds a state. The 'F' values are all fixed.</p>
<p>The programmer cannot add instructions to the machine definition, so there are no symbol aliasing issues here:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-instructions">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-instructions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-instructions">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-instructions"></RT·Counter·snapshot>
<RT·math>
\begin{aligned}
\mathit{AF} = \{& \\
\}
\end{aligned}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_fixed-instructions"></RT·counter·read> <RT·name>AF, the set of predefined instructions</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_fixed-instructions"></RT·Counter·read> <RT·name>AF, the set of predefined instructions</RT·name>
+ </RT·Counter·step>
<p>where <RT·math>σ</RT·math> must be in <RT·math>Σ</RT·math>.</p>
<p>The set of predefined symbols:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-symbols">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-symbols"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_fixed-symbols">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_fixed-symbols"></RT·Counter·snapshot>
<RT·math>
\mathit{ΣF} = \{\mathit{ΣF}{·}\mathtt{leftmost}, \mathit{ΣF}{·}\mathtt{rightmost}\}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_fixed-symbols"></RT·counter·read> <RT·name>ΣF, the set of predefined symbols</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_fixed-symbols"></RT·Counter·read> <RT·name>ΣF, the set of predefined symbols</RT·name>
+ </RT·Counter·step>
<p>
Note that the machine does not report having stepped off the end of the tape. There are no errors of the "you did it, shame on you" kind in this architecture. Instead the status register carries the cell type, and <RT·code>rightmost</RT·code> is one of the types it can carry. A controller that cannot prove it will stay on the tape must therefore consult the status before stepping right, and decide. Often the proof is available, in which case no test is needed and no cycles are spent on one. Where it is not available, the machine has told the program what it needs to know in advance rather than punished it afterwards. This is the same discipline applied to <RT·code>empty</RT·code> and to unspecified data, and it is what allows the fault taxonomy given earlier to hold: a program stops because its logic said to, because it has a flaw, or because a physical resource ran out and somebody must bring more. Walking off the end of the tape is not a fourth reason, because the machine gives the program the means to see the end coming.
<RT·section>
<RT·name>Machine variables</RT·name>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_machine-variables">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_machine-variables"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_machine-variables">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_machine-variables"></RT·Counter·snapshot>
<RT·math>
\mathit{MV} = (q, s, d)
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_machine-variables"></RT·counter·read> <RT·name>MV, the machine variables</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_machine-variables"></RT·Counter·read> <RT·name>MV, the machine variables</RT·name>
+ </RT·Counter·step>
<p><RT·code>q</RT·code>: is the current state of the machine.</p>
<RT·section>
<RT·name>Programmable part</RT·name>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_programmable-part">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmable-part"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_programmable-part">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmable-part"></RT·Counter·snapshot>
<RT·math>
\mathit{MP} = (\mathit{QP}, \mathit{ΣP}, \mathit{ΛP}, Δ_0, Δ_1, Δ_2, Δ_3, \mathit{HP})
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_programmable-part"></RT·counter·read> <RT·name>MP, the programmable part of the RT Machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_programmable-part"></RT·Counter·read> <RT·name>MP, the programmable part of the RT Machine</RT·name>
+ </RT·Counter·step>
<p>A set of programmed <em>state</em> symbols:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_programmed-states">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmed-states"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_programmed-states">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmed-states"></RT·Counter·snapshot>
<RT·math>
\mathit{QP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_programmed-states"></RT·counter·read> <RT·name>QP, the set of programmed state symbols</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_programmed-states"></RT·Counter·read> <RT·name>QP, the set of programmed state symbols</RT·name>
+ </RT·Counter·step>
<p>A set of programmed data symbols:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_programmed-symbols">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmed-symbols"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_programmed-symbols">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmed-symbols"></RT·Counter·snapshot>
<RT·math>
\mathit{ΣP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_programmed-symbols"></RT·counter·read> <RT·name>ΣP, the set of programmed data symbols</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_programmed-symbols"></RT·Counter·read> <RT·name>ΣP, the set of programmed data symbols</RT·name>
+ </RT·Counter·step>
<p>The programmed instructions. A set of pairs of the form:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_programmed-instructions">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmed-instructions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_programmed-instructions">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_programmed-instructions"></RT·Counter·snapshot>
<RT·math>
\mathit{ΛP} = \{ \langle q_i, a \rangle, \dots \}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_programmed-instructions"></RT·counter·read> <RT·name>ΛP, the programmed instructions, as state and action pairs</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_programmed-instructions"></RT·Counter·read> <RT·name>ΛP, the programmed instructions, as state and action pairs</RT·name>
+ </RT·Counter·step>
<p>where <RT·math>q_i</RT·math> is matched to the current state, and <RT·math>a</RT·math> is a member of <RT·math>\mathit{A}</RT·math>.
</p>
<p>The conditional transition table. A set of state transition triples; each triple is of the form:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_conditional-transitions">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_conditional-transitions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_conditional-transitions">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_conditional-transitions"></RT·Counter·snapshot>
<RT·math>
Δ_0 = \{ \langle q_i, σ, q_{i+1} \rangle, \dots \}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_conditional-transitions"></RT·counter·read> <RT·name>Δ₀, the conditional transition table</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_conditional-transitions"></RT·Counter·read> <RT·name>Δ₀, the conditional transition table</RT·name>
+ </RT·Counter·step>
<p>Here <RT·math>q_i</RT·math> and <RT·math>q_{i+1}</RT·math> are two states from the total set of <RT·math>Q</RT·math>. They need not be distinct. While the machine is running, state <RT·math>q_i</RT·math> is to be matched against the contents of the <RT·code>q register</RT·code>, the current state. Symbol <RT·math>σ</RT·math> is a member of the total set <RT·math>Σ</RT·math> and is to be matched against the contents of the <RT·code>s register</RT·code>, the machine status. When <RT·math>q_i</RT·math> matches the current state and <RT·math>σ</RT·math> matches the current status, then <RT·math>q_{i+1}</RT·math> becomes the next-state.</p>
<p>The state default transition table. A set of state transition pairs; each pair is of the form:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_state-default-transitions">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_state-default-transitions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_state-default-transitions">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_state-default-transitions"></RT·Counter·snapshot>
<RT·math>
Δ_1 = \{ \langle q_i, q_{i+1} \rangle, \dots \}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_state-default-transitions"></RT·counter·read> <RT·name>Δ₁, the state default transition table</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_state-default-transitions"></RT·Counter·read> <RT·name>Δ₁, the state default transition table</RT·name>
+ </RT·Counter·step>
<p>where <RT·math>q_i</RT·math> is matched to the current state, and upon a match <RT·math>q_{i+1}</RT·math> will be taken as the next-state.</p>
<p>The status default transition table. A set of state transition pairs; each pair is of the form:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_status-default-transitions">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_status-default-transitions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_status-default-transitions">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_status-default-transitions"></RT·Counter·snapshot>
<RT·math>
Δ_2 = \{ \langle σ, q_{i+1} \rangle, \dots \}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_status-default-transitions"></RT·counter·read> <RT·name>Δ₂, the status default transition table</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_status-default-transitions"></RT·Counter·read> <RT·name>Δ₂, the status default transition table</RT·name>
+ </RT·Counter·step>
<p>where <RT·math>σ</RT·math> matches the symbol in <RT·code>s register</RT·code>, and upon a match <RT·math>q_{i+1}</RT·math> will be taken as the next-state.</p>
<p>The global default next-state:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_global-default-transition">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_global-default-transition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_global-default-transition">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_global-default-transition"></RT·Counter·snapshot>
<RT·math>
Δ_3 = q_{i+1}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_global-default-transition"></RT·counter·read> <RT·name>Δ₃, the global default next-state</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_global-default-transition"></RT·Counter·read> <RT·name>Δ₃, the global default next-state</RT·name>
+ </RT·Counter·step>
<p>This is the transition of last resort. It is unconditional; the next-state becomes <RT·math>q_{i+1}</RT·math>.</p>
<p>A set of programmer-defined halting states:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_halt-states">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_halt-states"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_halt-states">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_halt-states"></RT·Counter·snapshot>
<RT·math>
\mathit{HP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_halt-states"></RT·counter·read> <RT·name>HP, the set of programmed halting states</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_halt-states"></RT·Counter·read> <RT·name>HP, the set of programmed halting states</RT·name>
+ </RT·Counter·step>
</RT·section>
<RT·section>
<RT·name>The RT Machine definition in total</RT·name>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_machine_definition">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_machine_definition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_machine_definition">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_machine_definition"></RT·Counter·snapshot>
<RT·math>
M = (q, s, d, Q, Σ, A, Λ, Δ, H)
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_machine_definition"></RT·counter·read> <RT·name>The RT Machine in total</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_machine_definition"></RT·Counter·read> <RT·name>The RT Machine in total</RT·name>
+ </RT·Counter·step>
<p>The variables used by the executor, <RT·math>\mathit{MV} = (q, s, d)</RT·math>.</p>
<p>The complete set of states, uniting the fixed predefined states and the programmed states:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_state-set">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_state-set"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_state-set">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_state-set"></RT·Counter·snapshot>
<RT·math>
Q = \mathit{QF} \cup \mathit{QP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_state-set"></RT·counter·read> <RT·name>Q, the complete state set, fixed united with programmed</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_state-set"></RT·Counter·read> <RT·name>Q, the complete state set, fixed united with programmed</RT·name>
+ </RT·Counter·step>
<p>The complete set of symbols, uniting the fixed control symbols and the programmed data symbols:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_symbol-set">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_symbol-set"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_symbol-set">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_symbol-set"></RT·Counter·snapshot>
<RT·math>
Σ = \mathit{ΣF} \cup \mathit{ΣP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_symbol-set"></RT·counter·read> <RT·name>Σ, the complete symbol set, fixed united with programmed</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_symbol-set"></RT·Counter·read> <RT·name>Σ, the complete symbol set, fixed united with programmed</RT·name>
+ </RT·Counter·step>
<p>All members of the set of available instructions are fixed:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_instruction-set">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_instruction-set"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_instruction-set">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_instruction-set"></RT·Counter·snapshot>
<RT·math>
A = \mathit{AF}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_instruction-set"></RT·counter·read> <RT·name>A, the instruction set, entirely fixed</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_instruction-set"></RT·Counter·read> <RT·name>A, the instruction set, entirely fixed</RT·name>
+ </RT·Counter·step>
<p>The table of state-instruction pairs is strictly programmed.</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_instruction-table">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_instruction-table"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_instruction-table">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_instruction-table"></RT·Counter·snapshot>
<RT·math>
Λ = \mathit{ΛP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_instruction-table"></RT·counter·read> <RT·name>Λ, the instruction table, entirely programmed</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_instruction-table"></RT·Counter·read> <RT·name>Λ, the instruction table, entirely programmed</RT·name>
+ </RT·Counter·step>
<p>The ordered sequence of next-state transition rules:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_transition-sequence">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_transition-sequence"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_transition-sequence">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_transition-sequence"></RT·Counter·snapshot>
<RT·math>
Δ = [Δ_0 \mid Δ_1 \mid Δ_2 \mid Δ_3]
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_transition-sequence"></RT·counter·read> <RT·name>Δ, the transition rules as an ordered sequence</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_transition-sequence"></RT·Counter·read> <RT·name>Δ, the transition rules as an ordered sequence</RT·name>
+ </RT·Counter·step>
<p>The set of halt states is strictly programmed, and thus could be empty.</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT_halt-set">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_halt-set"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT_halt-set">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT_halt-set"></RT·Counter·snapshot>
<RT·math>
H = \mathit{HP}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT_halt-set"></RT·counter·read> <RT·name>H, the halt state set, entirely programmed</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT_halt-set"></RT·Counter·read> <RT·name>H, the halt state set, entirely programmed</RT·name>
+ </RT·Counter·step>
</RT·section>
<RT·section>
<RT·name>Initialization stage</RT·name>
<p>Before the first cycle begins, a tape is selected and mounted. The read/write head is positioned over the leftmost tape cell. The machine variables are initialized as follows:</p>
- <RT·counter·step counter="RT·List·counter" id="List·initialization_values">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·initialization_values"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·initialization_values">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·initialization_values"></RT·Counter·snapshot>
<ul>
<li>The current state <RT·code>q</RT·code> is set to <RT·math>\mathit{QF}{·}\mathtt{initial}</RT·math>.</li>
<li>The data register <RT·code>d</RT·code> is initialized to hold the <RT·math>\mathit{ΣF}{·}\mathtt{unspecified}</RT·math> symbol.</li>
<li>The status register <RT·code>s</RT·code> is initialized to hold the <RT·math>\mathit{ΣF}{·}\mathtt{unspecified}</RT·math> symbol.</li>
</ul>
- List <RT·counter·read snapshot="List·initialization_values"></RT·counter·read>. <RT·name>The initial values given to the machine variables</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·initialization_values"></RT·Counter·read>. <RT·name>The initial values given to the machine variables</RT·name>
+ </RT·Counter·step>
</RT·section>
<RT·section>
<RT·name>Phase 1: Instruction issue and execution</RT·name>
- <RT·counter·step counter="RT·List·counter" id="List·phase-1_steps">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·phase-1_steps"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·phase-1_steps">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·phase-1_steps"></RT·Counter·snapshot>
<ol>
<li>Given the current state <RT·code>q</RT·code>, lookup the instruction <RT·math>λ</RT·math>, within the instruction table <RT·math>Λ</RT·math>.</li>
<li>Perform the instruction <RT·math>λ</RT·math>.</li>
</ol>
- List <RT·counter·read snapshot="List·phase-1_steps"></RT·counter·read>. <RT·name>The two steps of instruction issue and execution</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·phase-1_steps"></RT·Counter·read>. <RT·name>The two steps of instruction issue and execution</RT·name>
+ </RT·Counter·step>
<p>If the instruction is <RT·code>left</RT·code> and the machine walks off the tape, the machine hangs.</p>
</RT·section>
<p>Because the RT Machine separates the data path from the control path, it is possible to reverse a string without inspecting the payload. The programmed controller only needs to recognize the structural boundaries of the data protocol. When a payload symbol is encountered, the controller executes a <RT·code>read(d)</RT·code> instruction, placing the value into the data register, which is not examined for decision-making purposes. When a value is used to base a decision upon, the controller executes a <RT·code>read(s)</RT·code>, placing the value into the status register. Because instructions are bound to states rather than transitions, reading and stepping are distinct states. This combination of features results in a controller that has threads of serialized execution.</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·RT-reverse_controller">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·RT-reverse_controller"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·RT-reverse_controller">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·RT-reverse_controller"></RT·Counter·snapshot>
<RT·code>
# RT Machine String Reverse
# Domains:
δ:
Q·Done
</RT·code>
- Code <RT·counter·read snapshot="Code·RT-reverse_controller"></RT·counter·read>. <RT·name>The RT Machine string reverse controller</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·RT-reverse_controller"></RT·Counter·read>. <RT·name>The RT Machine string reverse controller</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·RT_reverse-machine">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·RT_reverse-machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·RT_reverse-machine">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·RT_reverse-machine"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="RT_style_TM_reverse.png" class="RT·diagram" alt="RTM reverse machine">
</figure>
- Figure <RT·counter·read snapshot="Figure·RT_reverse-machine"></RT·counter·read>. <RT·name>The RT Machine that reverses a binary string</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·RT_reverse-machine"></RT·Counter·read>. <RT·name>The RT Machine that reverses a binary string</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>The form of this diagram shows a lead-in, a long loop, and a tail leading to done. This is suggestive of code followed by a while loop that breaks out, with further code completing the program.</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·RT-reverse_in_C">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·RT-reverse_in_C"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·RT-reverse_in_C">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·RT-reverse_in_C"></RT·Counter·snapshot>
<RT·code>
void RT·reverse_string() {
// Initialization: Scan to EOM and setup the EOR boundary
return;
}
</RT·code>
- Code <RT·counter·read snapshot="Code·RT-reverse_in_C"></RT·counter·read>. <RT·name>The RT reverse controller written as C</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·RT-reverse_in_C"></RT·Counter·read>. <RT·name>The RT reverse controller written as C</RT·name>
+ </RT·Counter·step>
<p>The total number of steps for reversing an <RT·math>n</RT·math> symbol string using the RT Machine:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·RT-reverse_step-count">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT-reverse_step-count"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·RT-reverse_step-count">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·RT-reverse_step-count"></RT·Counter·snapshot>
<RT·math>
\text{steps} =
\begin{cases}
4.5n^2 + 11.5n + 5 & \text{if } n \ge 1
\end{cases}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·RT-reverse_step-count"></RT·counter·read> <RT·name>Steps taken by the RT reverse machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·RT-reverse_step-count"></RT·Counter·read> <RT·name>Steps taken by the RT reverse machine</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>The reverse string machine spends a lot of time shuttling the head between two context areas: one for the original string, and one for the resulting reversed string. This suggests that a two-head version would be faster. The following is the two-head state machine definition:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_controller">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_controller"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_controller">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_controller"></RT·Counter·snapshot>
<RT·code>
# RT Two-Head String Reverse
# input: (σ ∈ Σ)* EOM (starting on the leftmost cell)
δ:
Q·Done
</RT·code>
- Code <RT·counter·read snapshot="Code·two-headed-reverse_controller"></RT·counter·read>. <RT·name>The two-headed string reverse controller</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·two-headed-reverse_controller"></RT·Counter·read>. <RT·name>The two-headed string reverse controller</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·RT_two-headed_reverse-machine">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·RT_two-headed_reverse-machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·RT_two-headed_reverse-machine">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·RT_two-headed_reverse-machine"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="RT_2_hd_reverse.png" class="RT·diagram" alt="RTM 2 hd reverse machine">
</figure>
- Figure <RT·counter·read snapshot="Figure·RT_two-headed_reverse-machine"></RT·counter·read>. <RT·name>A two-headed RT Machine that reverses a binary string</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·RT_two-headed_reverse-machine"></RT·Counter·read>. <RT·name>A two-headed RT Machine that reverses a binary string</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>The number of states has dropped from 24 to 18, while the speed increase is dramatic, with the former quadratic performance becoming linear performance. The total number of steps for reversing an <RT·math>n</RT·math> symbol string using a two-head RT architecture:</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·two-headed-reverse_step-count">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·two-headed-reverse_step-count"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·two-headed-reverse_step-count">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·two-headed-reverse_step-count"></RT·Counter·snapshot>
<RT·math>
\text{steps} =
\begin{cases}
9n + 4 & \text{if } n \ge 1
\end{cases}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·two-headed-reverse_step-count"></RT·counter·read> <RT·name>Steps taken by the two-headed RT reverse machine</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·two-headed-reverse_step-count"></RT·Counter·read> <RT·name>Steps taken by the two-headed RT reverse machine</RT·name>
+ </RT·Counter·step>
<p>The two paths through the state machine, and the one loop, translate well into code:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_in_C">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_in_C"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_in_C">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_in_C"></RT·Counter·snapshot>
<RT·code>
void RT·reverse_string_2_head() {
// Phase 1: Both heads scan right to the EOM pivot
return;
}
</RT·code>
- Code <RT·counter·read snapshot="Code·two-headed-reverse_in_C"></RT·counter·read>. <RT·name>The two-headed reverse controller written as C</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·two-headed-reverse_in_C"></RT·Counter·read>. <RT·name>The two-headed reverse controller written as C</RT·name>
+ </RT·Counter·step>
<p>This machine has a single tape with two heads marking two separate context areas. Because the areas do not overlap, this situation is indistinguishable from the case of the machine having two separate tapes, each with its own head. Hartmanis and Stearns established the original proof that simulating a Turing Machine with multiple tapes, each with its own head, on a single-tape, single-head machine incurs a quadratic time penalty <RT·endnote>J. Hartmanis and R. E. Stearns, "On the computational complexity of algorithms," <em>Transactions of the American Mathematical Society</em> 117 (1965): 285-306.</RT·endnote>. Hopcroft and Ullman formalize this relationship in their text <RT·endnote>John E. Hopcroft and Jeffrey D. Ullman, <em>Introduction to Automata Theory, Languages, and Computation</em> (Reading: Addison-Wesley, 1979), 292.</RT·endnote>. This explains why in this example of a string reverse machine, when the second head was added to eliminate the head shuttling, the quadratic term disappeared. Not all quadratic terms in step-count formulas are due to shuttling, but this one happens to be such a case.</p>
<RT·section id="Section·RT_machine-design">
<RT·name>The RT Machine design</RT·name>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·Turing-Machine">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·Turing-Machine"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·Turing-Machine">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·Turing-Machine"></RT·Counter·snapshot>
<!-- first edition: Figure 1 -->
<figure>
<img src="machine fig.png" class="RT·diagram" alt="Figure 1: A Turing Machine">
</figure>
- Figure <RT·counter·read snapshot="Figure·Turing-Machine"></RT·counter·read>. <RT·name>A Turing Machine</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·Turing-Machine"></RT·Counter·read>. <RT·name>A Turing Machine</RT·name>
+ </RT·Counter·step>
- <p>The prior chapter on the computation theoretic RT Machine, chapter <RT·counter·read snapshot="Section·RT_computation-theoretic"></RT·counter·read>, serves as the architectural template, with only a few modifications. The architecture requires explicit data rather than accepting meta-symbols like 'unspecified' as presumed initial values 'by definition'. Actual values are transacted. Now that data and control have been separated, the controller is practical to implement, and even more so because it was defined in terms of tables that can be built in hardware. As the read status instruction returns the cell type, it will in its current form be able to return 'rightmost', so the right end of the tape can be detected. In order to extend the tape, the machine will stop and ask the operator to mount a new reel. This could be signaled when the user attempts to step right of rightmost, either by a panel light that illuminates upon the machine finding a rightmost status, or by the program printing a message on the console teletype. As this is a constant-time operation, it is computation theoretic inconsequential.</p>
+ <p>The prior chapter on the computation theoretic RT Machine, chapter <RT·Counter·read snapshot="Section·RT_computation-theoretic"></RT·Counter·read>, serves as the architectural template, with only a few modifications. The architecture requires explicit data rather than accepting meta-symbols like 'unspecified' as presumed initial values 'by definition'. Actual values are transacted. Now that data and control have been separated, the controller is practical to implement, and even more so because it was defined in terms of tables that can be built in hardware. As the read status instruction returns the cell type, it will in its current form be able to return 'rightmost', so the right end of the tape can be detected. In order to extend the tape, the machine will stop and ask the operator to mount a new reel. This could be signaled when the user attempts to step right of rightmost, either by a panel light that illuminates upon the machine finding a rightmost status, or by the program printing a message on the console teletype. As this is a constant-time operation, it is computation theoretic inconsequential.</p>
- <p>Because a Turing Machine can only reach another cell further out on the tape by stepping to it, space complexity and time complexity are related. A program that runs for ten steps can consume at most ten cells of tape. However, if that program merely bounces between two cells, it will require less space, precisely two cells. As another example, a program that counts the number of characters on its input tape using Hindu-Arabic notation will execute in asymptotically linear time, as demonstrated in section <RT·counter·read snapshot="Section·Hindu-Arabic_representation"></RT·counter·read>, which analyses the increment operation. Its working footprint, however, will be logarithmic in space complexity, because that is how fast an Hindu-Arabic representation grows with a count.</p>
+ <p>Because a Turing Machine can only reach another cell further out on the tape by stepping to it, space complexity and time complexity are related. A program that runs for ten steps can consume at most ten cells of tape. However, if that program merely bounces between two cells, it will require less space, precisely two cells. As another example, a program that counts the number of characters on its input tape using Hindu-Arabic notation will execute in asymptotically linear time, as demonstrated in section <RT·Counter·read snapshot="Section·Hindu-Arabic_representation"></RT·Counter·read>, which analyses the increment operation. Its working footprint, however, will be logarithmic in space complexity, because that is how fast an Hindu-Arabic representation grows with a count.</p>
<p>If a program executed at the speed of a human operator, the operator would likely abandon the process before it finished. This highlights a necessary attribute of good software: <RT·term>utility</RT·term>. It also exposes a limitation of pure computation theory, which abstracts away physical time. Nevertheless, formal analysis remains a necessity. Consider an exponential-time program processing worst-case operands: its execution time explodes relative to input length, rapidly exceeding the age of the universe. In such extremes, empirical wall-clock measurement becomes superfluous. Computation theory classifies a program's behavior, which establishes structural implications for wall-clock time, rather than calculating absolute durations.</p>
<p>An <RT·code>HU</RT·code> contains a head and a local controller. The local controller supports these instructions:</p>
- <RT·counter·step counter="RT·List·counter" id="List·HU_instructions">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·HU_instructions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·HU_instructions">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·HU_instructions"></RT·Counter·snapshot>
<ol>
<li><RT·code>read()</RT·code> → σ</li>
<li><RT·code>write(σ)</RT·code></li>
<li><RT·code>status()</RT·code> → s</li>
</ol>
- List <RT·counter·read snapshot="List·HU_instructions"></RT·counter·read>. <RT·name>The instructions supported by the head unit controller</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·HU_instructions"></RT·Counter·read>. <RT·name>The instructions supported by the head unit controller</RT·name>
+ </RT·Counter·step>
- <p>On this model of machine, the <RT·code>HU</RT·code> status is identical to the indicated cell's type. The cell type is not read from the tape; rather, it is derived from the head's physical relationship to the ends of the tape. With a physical tape drive, an unused leader and trailer are required to prevent the tape from departing from the reels, a condition difficult to reverse. Therefore, the format, or physical, markers will be on the ends of the usable portion of the tape, rather than on the physical end of the tape. Consequently, the <RT·code>HU</RT·code> works in conjunction with the <RT·code>TTU</RT·code> to derive the status. (The tape transport unit, the <RT·code>TTU</RT·code>, is discussed in the next section, section <RT·counter·read snapshot="Section·TTU"></RT·counter·read>.) As established in section <RT·counter·read snapshot="Section·tape-cell"></RT·counter·read>, cell types are:</p>
+ <p>On this model of machine, the <RT·code>HU</RT·code> status is identical to the indicated cell's type. The cell type is not read from the tape; rather, it is derived from the head's physical relationship to the ends of the tape. With a physical tape drive, an unused leader and trailer are required to prevent the tape from departing from the reels, a condition difficult to reverse. Therefore, the format, or physical, markers will be on the ends of the usable portion of the tape, rather than on the physical end of the tape. Consequently, the <RT·code>HU</RT·code> works in conjunction with the <RT·code>TTU</RT·code> to derive the status. (The tape transport unit, the <RT·code>TTU</RT·code>, is discussed in the next section, section <RT·Counter·read snapshot="Section·TTU"></RT·Counter·read>.) As established in section <RT·Counter·read snapshot="Section·tape-cell"></RT·Counter·read>, cell types are:</p>
- <RT·counter·step counter="RT·List·counter" id="List·cell_types">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·cell_types"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·cell_types">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·cell_types"></RT·Counter·snapshot>
<ol>
<li><RT·code>leftmost</RT·code></li>
<li><RT·code>rightmost</RT·code></li>
<li><RT·code>medial</RT·code></li>
<li><RT·code>island</RT·code></li>
</ol>
- List <RT·counter·read snapshot="List·cell_types"></RT·counter·read>. <RT·name>The cell types a head unit can report</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·cell_types"></RT·Counter·read>. <RT·name>The cell types a head unit can report</RT·name>
+ </RT·Counter·step>
<p>A computation theoretic Turing Machine would never encounter a status of <RT·code>rightmost</RT·code> or <RT·code>island</RT·code>. This is where a finite extendable tape structurally differs from a single-ended theoretical tape.</p>
<p>The <RT·code>TTU</RT·code> is the component where tapes are mounted and unmounted, and where read/write head units are installed. When multiple <RT·code>HU</RT·code>s are plugged in, the controller passes control among them so it appears that heads never collide. The <RT·code>TTU</RT·code> controller has these components:
</p>
- <RT·counter·step counter="RT·List·counter" id="List·TTU_components">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·TTU_components"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·TTU_components">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·TTU_components"></RT·Counter·snapshot>
<ol>
<li>one or more <RT·code>HU</RT·code>s</li>
<li>a <RT·term>data buffer</RT·term> holding a single symbol</li>
<li>a <RT·term>status buffer</RT·term> </li>
<li>a <RT·term>instruction buffer</RT·term>, written by the programmed controller, acted upon immediately by the <RT·code>TTU</RT·code></li>
</ol>
- List <RT·counter·read snapshot="List·TTU_components"></RT·counter·read>. <RT·name>The components of the tape transport unit controller</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·TTU_components"></RT·Counter·read>. <RT·name>The components of the tape transport unit controller</RT·name>
+ </RT·Counter·step>
<p>The <RT·code>TTU</RT·code> interfaces with the executor, which in turn gates the flow of data through the machine. The executor controls the clock and reset lines, and through this supervises the <em>customer programmed control unit</em>, the <RT·code>CPCU</RT·code>. This two-layer control system is single-threaded and issues the following instructions to each selected <RT·code>TTU</RT·code>:</p>
- <RT·counter·step counter="RT·List·counter" id="List·TTU_instructions">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·TTU_instructions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·TTU_instructions">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·TTU_instructions"></RT·Counter·snapshot>
<ol>
<li><RT·code>read(<em>head</em>)</RT·code> → σ</li>
<li><RT·code>write(<em>σ</em> ,<em>head</em>)</RT·code></li>
<li><RT·code>left(<em>head</em>)</RT·code></li>
<li><RT·code>right(<em>head</em>)</RT·code></li>
</ol>
- List <RT·counter·read snapshot="List·TTU_instructions"></RT·counter·read>. <RT·name>The instructions issued to a selected tape transport unit</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·TTU_instructions"></RT·Counter·read>. <RT·name>The instructions issued to a selected tape transport unit</RT·name>
+ </RT·Counter·step>
<p>The <em>head</em> argument multiplexes the instruction to the specified head. If the <RT·code>TTU</RT·code> has one head, the head argument is optional. The last two instructions cause the tape to be moved such that, relatively, the selected head moves left or right by one cell.</p>
<p>The controller is programmed via patch panels. The panels would look something like what is shown in the following ASCII art blocks. Note that <RT·code>●</RT·code> indicates an illuminated indicator light, whereas <RT·code>○</RT·code> is not illuminated. <RT·code>[/]</RT·code> represents an open toggle switch, while <RT·code>[—]</RT·code> is a closed one. <RT·code>{*}</RT·code> is a pushed button, while <RT·code>{ }</RT·code> is a button that is not pushed. <RT·code>( )</RT·code> represents a hole for a banana plug. Each patch cord has a banana plug on each end. Plugging a patch cord between separate panels will void the warranty ;-).</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·control-panel">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·control-panel"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·control-panel">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·control-panel"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<pre>
[ CONTROL PANEL ]
| RUN/STEP [/] ○ STEP { } |
+-----------------------------------+
</pre>
- Figure <RT·counter·read snapshot="Figure·control-panel"></RT·counter·read>. <RT·name>The control panel, carrying power, error, reset and single-step</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·control-panel"></RT·Counter·read>. <RT·name>The control panel, carrying power, error, reset and single-step</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·state-transition-table_panel">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·state-transition-table_panel"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·state-transition-table_panel">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·state-transition-table_panel"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<pre>
[ State Transition Table ]
destination state | ( ) ( ) ( ) ( ) ( ) ( ) |
+-------------------------------------------+
</pre>
- Figure <RT·counter·read snapshot="Figure·state-transition-table_panel"></RT·counter·read>. <RT·name>The state transition panel, with state indicators and halt switches</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·state-transition-table_panel"></RT·Counter·read>. <RT·name>The state transition panel, with state indicators and halt switches</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·instruction_panel">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·instruction_panel"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·instruction_panel">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·instruction_panel"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<pre>
[ Instruction ]
write('σ')| ( ) ( ) ( ) ( ) ( ) ( ) |
+-----------------------------------+
</pre>
- Figure <RT·counter·read snapshot="Figure·instruction_panel"></RT·counter·read>. <RT·name>The instruction panel, one patch row per instruction and one column per state</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·instruction_panel"></RT·Counter·read>. <RT·name>The instruction panel, one patch row per instruction and one column per state</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·sigma-select_panel">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·sigma-select_panel"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·sigma-select_panel">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·sigma-select_panel"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<pre>
[ Sigma Select for write('σ') ]
s4 | ( ) ( ) ( ) ( ) ( ) ( ) |
+-----------------------------------+
</pre>
- Figure <RT·counter·read snapshot="Figure·sigma-select_panel"></RT·counter·read>. <RT·name>The sigma select panel, choosing the symbol written by write(σ)</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·sigma-select_panel"></RT·Counter·read>. <RT·name>The sigma select panel, choosing the symbol written by write(σ)</RT·name>
+ </RT·Counter·step>
<p>The top panel has two toggle switches. One turns the machine on, and the other selects run or single-step mode. Immediately to the right of the two toggles are indicator lights. To the right of the indicator lights are two push buttons. One is for reset, which sends the machine back to state <RT·math>q_0</RT·math>, and the other is for stepping the machine when it is in single-step mode. This panel also has an error indicator light which will illuminate if no next-state is specified for a state transition, and thus the machine is hung, or if a head walks off the end of a tape.</p>
<RT·section>
<RT·name>The machine block diagram</RT·name>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·RT_block-diagram">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·RT_block-diagram"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·RT_block-diagram">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·RT_block-diagram"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="RT_machine.svg" class="RT·diagram" alt="Figure: RT block diagram">
</figure>
- Figure <RT·counter·read snapshot="Figure·RT_block-diagram"></RT·counter·read>. <RT·name>The RT Machine block diagram</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·RT_block-diagram"></RT·Counter·read>. <RT·name>The RT Machine block diagram</RT·name>
+ </RT·Counter·step>
- <p>This section describes the RT Machine organization. Figure <RT·counter·read snapshot="Figure·RT_block-diagram"></RT·counter·read> shows the major components and their channels of communications. The organization guides designers who will later draft schematics that specify all of the connections.</p>
+ <p>This section describes the RT Machine organization. Figure <RT·Counter·read snapshot="Figure·RT_block-diagram"></RT·Counter·read> shows the major components and their channels of communications. The organization guides designers who will later draft schematics that specify all of the connections.</p>
<p><strong>Components</strong></p>
- <RT·counter·step counter="RT·List·counter" id="List·block-diagram_components">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·block-diagram_components"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·block-diagram_components">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·block-diagram_components"></RT·Counter·snapshot>
<ol>
<li>Control Panel
<ol>
<li><RT·code>s</RT·code> register</li>
<li><RT·code>Status Decoder</RT·code></li>
</ol>
- List <RT·counter·read snapshot="List·block-diagram_components"></RT·counter·read>. <RT·name>The units and panels the machine is assembled from</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·block-diagram_components"></RT·Counter·read>. <RT·name>The units and panels the machine is assembled from</RT·name>
+ </RT·Counter·step>
- <p>As described in chapter <RT·counter·read snapshot="Section·RT_computation-theoretic"></RT·counter·read>, which is being used as the architectural template, the executor guides the machine through the initialization, programmed control, and halting stages of execution. The Executor contains the power, reset, and clock logic. It has two modes of execution: the run mode in which the clock runs free, and the single-step mode, in which clock pulses are sent with the push of a button. It also holds the halt state switch bank, and is ready to stop the clock when a halt state is reached. When in the programmed control stage, most of the active control comes from the <RT·code>CPCU</RT·code>.</p>
+ <p>As described in chapter <RT·Counter·read snapshot="Section·RT_computation-theoretic"></RT·Counter·read>, which is being used as the architectural template, the executor guides the machine through the initialization, programmed control, and halting stages of execution. The Executor contains the power, reset, and clock logic. It has two modes of execution: the run mode in which the clock runs free, and the single-step mode, in which clock pulses are sent with the push of a button. It also holds the halt state switch bank, and is ready to stop the clock when a halt state is reached. When in the programmed control stage, most of the active control comes from the <RT·code>CPCU</RT·code>.</p>
<p>The <RT·code>CPCU</RT·code> contains the current state register <RT·code>q</RT·code>, the <RT·code>Next-State Table</RT·code>, and the <RT·code>Instruction Table</RT·code>.</p>
<RT·section>
<RT·name>Head partition</RT·name>
- <RT·counter·step counter="RT·List·counter" id="List·head_partition">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·head_partition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·head_partition">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·head_partition"></RT·Counter·snapshot>
<ol>
<li>The left side: The finite set containing all of the cells to the left of the head cell.</li>
<li>Head: the head cell.</li>
<li>The right side: the infinite set containing all the cells to the right of the head.</li>
</ol>
- List <RT·counter·read snapshot="List·head_partition"></RT·counter·read>. <RT·name>The three areas of the head partition</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·head_partition"></RT·Counter·read>. <RT·name>The three areas of the head partition</RT·name>
+ </RT·Counter·step>
<p>If the head is on the leftmost cell, there is no left side area.</p>
<RT·section>
<RT·name>Leftmost/remaining partition</RT·name>
- <RT·counter·step counter="RT·List·counter" id="List·leftmost-remaining_partition">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·leftmost-remaining_partition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·leftmost-remaining_partition">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·leftmost-remaining_partition"></RT·Counter·snapshot>
<ol>
<li>Leftmost: the leftmost cell.</li>
<li>Remaining: the infinite set including the right neighbor of the leftmost cell, and all cells further to the right.</li>
</ol>
- List <RT·counter·read snapshot="List·leftmost-remaining_partition"></RT·counter·read>. <RT·name>The two areas of the leftmost and remaining partition</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·leftmost-remaining_partition"></RT·Counter·read>. <RT·name>The two areas of the leftmost and remaining partition</RT·name>
+ </RT·Counter·step>
</RT·section>
A nonempty tape, one with at least one cell holding an alphabet symbol, can be partitioned into the following areas:
</p>
- <RT·counter·step counter="RT·List·counter" id="List·active-area_partition">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·active-area_partition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·active-area_partition">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·active-area_partition"></RT·Counter·snapshot>
<ol>
<li>The left empty tail: if the leftmost cell of the tape is an alphabet cell, there is no left empty tail. Otherwise, it consists of the leftmost cell and the empty cells, if any, to the right of the leftmost cell, up to, but not including, the first alphabet cell.</li>
<li>The right empty tail: the infinite set extending from the right neighbor of the rightmost cell of the active area, extending rightward.</li>
</ol>
- List <RT·counter·read snapshot="List·active-area_partition"></RT·counter·read>. <RT·name>The three areas of the active area partition</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·active-area_partition"></RT·Counter·read>. <RT·name>The three areas of the active area partition</RT·name>
+ </RT·Counter·step>
<p>
A noncomputational tape is one that cannot be initialized by a Turing Machine, but can still be surmised to exist, perhaps in analysis due to its properties. The empty tape is an example. The tape holding the Peano Numbers is another example. For noncomputational tapes that have the property that the active area is open on the right, there is no right empty tail.
When a Turing Machine operates on a finite virtual tape, the structural logic of the partitions established earlier must be updated to reflect the absolute rightward boundary.
</p>
- <RT·counter·step counter="RT·List·counter" id="List·finite-virtual-tape_partitions">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·finite-virtual-tape_partitions"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·finite-virtual-tape_partitions">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·finite-virtual-tape_partitions"></RT·Counter·snapshot>
<ol>
<li>For the <strong>Head partition</strong> and <strong>Area implied partition</strong>, the right side is no longer infinite. It is a finite set containing all cells extending from the right neighbor of the head (or area) up to the absolute rightmost cell of the virtual tape. If the head (or area) includes the rightmost cell of the virtual tape, the right side set does not exist.</li>
<li>For the <strong>Leftmost/remaining partition</strong>, the remaining area is now a finite set terminating at the rightmost cell of the virtual tape.</li>
<li>For the <strong>Active area partition</strong>, the right empty tail is similarly a finite set extending to the rightmost boundary of the virtual tape. If the rightmost alphabet cell occupies the rightmost cell of the virtual tape, the right empty tail does not exist.</li>
</ol>
- List <RT·counter·read snapshot="List·finite-virtual-tape_partitions"></RT·counter·read>. <RT·name>The partitions of a finite virtual tape</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·finite-virtual-tape_partitions"></RT·Counter·read>. <RT·name>The partitions of a finite virtual tape</RT·name>
+ </RT·Counter·step>
</RT·section>
</RT·section>
So we now have two means for identifying a feature. One means is to state its address, and the other is to put a tape machine head on it.
</p>
- <p>As we noted in section <RT·counter·read snapshot="Section·area-and-partitioning"></RT·counter·read>, an area has two distinguishing features, being that it has a leftmost cell, and a rightmost cell. That definition is topological. If we start with the leftmost cell of a tape, we are either already on the leftmost cell of a defined area, or we can step right to find it. At the point of finding it we know this leftmost cell is part of the area, then we are either already on the rightmost cell, or we can continue to step right on cells in the area until we find the rightmost cell in the area. The right neighbor of the rightmost cell in the area, and all cells to that right of that, are excluded from the area.
+ <p>As we noted in section <RT·Counter·read snapshot="Section·area-and-partitioning"></RT·Counter·read>, an area has two distinguishing features, being that it has a leftmost cell, and a rightmost cell. That definition is topological. If we start with the leftmost cell of a tape, we are either already on the leftmost cell of a defined area, or we can step right to find it. At the point of finding it we know this leftmost cell is part of the area, then we are either already on the rightmost cell, or we can continue to step right on cells in the area until we find the rightmost cell in the area. The right neighbor of the rightmost cell in the area, and all cells to that right of that, are excluded from the area.
</p>
<p>With addresses we can now define an area with two addresses, two Peano Numbers, the address of the leftmost cell, and that of the rightmost cell. All Peano Numbers greater than or equal to the address of the leftmost cell, or less than or equal to the address of the rightmost cell, are addresses of cells that are in the area. This feels more satisfactory for most of us, as now we are talking about arithmetic rather than graph topology. Though should the topology of the tape be generalized, this could become limiting. It reminds me of Frege's admonition that perhaps math should be built on top of geometry.
<RT·section>
<RT·name>How cardinality is computed</RT·name>
- <RT·counter·step counter="RT·List·counter" id="List·cardinality_procedure">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·cardinality_procedure"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·cardinality_procedure">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·cardinality_procedure"></RT·Counter·snapshot>
<ol>
<li>We set Turing Machine <RT·math>P</RT·math> with its head on the leftmost cell of an area. We mount the initial tape, '·', on the <RT·math>A</RT·math> machine.</li>
<li>We step <RT·math>P</RT·math> and simultaneously run the <RT·math>A</RT·math> machine. Stepping stops when <RT·math>P</RT·math> reaches the rightmost cell of the area. At this point, the tape on the <RT·math>A</RT·math> machine holds the address space extent.</li>
<li>The <RT·math>A</RT·math> machine is run an additional time. The output on the tape is defined to be the cardinality of the address space, aka the cardinality.</li>
</ol>
- List <RT·counter·read snapshot="List·cardinality_procedure"></RT·counter·read>. <RT·name>The three steps for computing the cardinality of an address space</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·cardinality_procedure"></RT·Counter·read>. <RT·name>The three steps for computing the cardinality of an address space</RT·name>
+ </RT·Counter·step>
</RT·section>
Now here is an interesting result:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·aleph_difference">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·aleph_difference"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·aleph_difference">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·aleph_difference"></RT·Counter·snapshot>
<RT·math>
\aleph_{0} - \aleph_{-1} = 1
</RT·math>
- eq: <RT·counter·read snapshot="Equation·aleph_difference"></RT·counter·read> <RT·name>The difference of two transfinite cardinals is one</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·aleph_difference"></RT·Counter·read> <RT·name>The difference of two transfinite cardinals is one</RT·name>
+ </RT·Counter·step>
<p>
Neither machine can be run. However we can compose the two machines, then simplify the composition. When we do so, the ever larger Peano Number machines annihilate each other, and the increment machine remains. The increment machine can be run, so we end up with an output value.
For <RT·code>Hindu-Arabic_increment</RT·code>, the machine reads the cell under the head; upon finding a 0 or the terminator, it writes a 1 and halts. Upon finding a 1, it writes a 0, steps right, and repeats the procedure.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·increment_controller">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·increment_controller"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·increment_controller">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·increment_controller"></RT·Counter·snapshot>
<RT·code>
increment:
a = TTU.read()
TTU.step()
goto increment
</RT·code>
- Code <RT·counter·read snapshot="Code·increment_controller"></RT·counter·read>. <RT·name>A controller that increments a binary counter</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·increment_controller"></RT·Counter·read>. <RT·name>A controller that increments a binary counter</RT·name>
+ </RT·Counter·step>
<p>Here <RT·code>TTU</RT·code> is the tape transport unit. It has the number to be incremented mounted on it. This number is either zero, which would mean the leftmost cell is empty, or it is of the same form as a result from a Peano Number extension machine. A <RT·code>TTU.read</RT·code> places a copy of the symbol instance found in the cell under the head into the read buffer automatically when the machine enters a new state on the programmed controller, so it is not counted as a step. In contrast, the other actions are associated with the state of the programmed controller, so when the machine arrives at a <RT·code>write</RT·code>, <RT·code>step</RT·code>, or <RT·code>halt</RT·code> node, it means that the programmed state controller has taken a step. Sequential instructions mean unconditional next-state choices, whereas an <RT·code>if</RT·code> signals a conditional next-state choice. The <RT·code>if</RT·code> condition is a logical proposition based on the read symbol.</p>
<p>The loop form here is worth taking note of, as it will come up again. The controller executes a first action, that of a <RT·code>read</RT·code>, followed by a middle break test, and then the recursive form actions.</p>
<p>
- Each row shows an input tape, and actions taken to write the result tape. For any given row, the result tape is the same as the input tape on the next row down. Table <RT·counter·read snapshot="Table·increment_cost"></RT·counter·read> lists 7 increments, which is sufficient to reach the maximum count that can be held by a 3 bit counter.
+ Each row shows an input tape, and actions taken to write the result tape. For any given row, the result tape is the same as the input tape on the next row down. Table <RT·Counter·read snapshot="Table·increment_cost"></RT·Counter·read> lists 7 increments, which is sufficient to reach the maximum count that can be held by a 3 bit counter.
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·increment_cost">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·increment_cost"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·increment_cost">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·increment_cost"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<tr>
<td></td>
</tr>
</table>
- Table <RT·counter·read snapshot="Table·increment_cost"></RT·counter·read>. <RT·name>The cost in steps of each increment, through the range of a three bit counter</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·increment_cost"></RT·Counter·read>. <RT·name>The cost in steps of each increment, through the range of a three bit counter</RT·name>
+ </RT·Counter·step>
<p>
The number of programmable controller state transition steps required to reach a maximum 1 bit, 2 bit, and 3 bit count are: <RT·math>[2, 8, 22]</RT·math>. Note these are cumulative. The three bit maximum count cost includes that of the two bit maximum count cost, etc. Each maximum count is exponentially larger, so a better measure is the average cost per step: <RT·math>[2/1, 8/3, 22/7] = [2, 2.667, 3.143]</RT·math>
<p>This reveals a fundamental property of Arabic Representation: it encodes both the sequence of digit symbols (which map to a Peano Number) and the sequence's length (which exists at a meta level, governing computational operations). The representation of zero exposes a limitation. At zero, the representation retains length information necessary for computation but lacks an explicit numerical mapping to zero itself.</p>
<p>Structurally, this forces a design choice between two options:</p>
- <RT·counter·step counter="RT·List·counter" id="List·zero_representation_options">
- <RT·counter·snapshot counter="RT·List·counter" snapshot="List·zero_representation_options"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·List·counter" id="List·zero_representation_options">
+ <RT·Counter·snapshot counter="RT·List·counter" snapshot="List·zero_representation_options"></RT·Counter·snapshot>
<ul>
<li>Using an empty sequence <RT·code>[]</RT·code> and arbitrarily mapping it to zero. This allows a length function to return zero naturally, as the empty sequence is never scanned.</li>
<li>Using a lone zero symbol <RT·code>[0]</RT·code>, which introduces an effective length concept where <RT·code>[0]</RT·code> must be treated as though it has zero length in algorithmic operations.</li>
</ul>
- List <RT·counter·read snapshot="List·zero_representation_options"></RT·counter·read>. <RT·name>The two options for representing zero</RT·name>
- </RT·counter·step>
+ List <RT·Counter·read snapshot="List·zero_representation_options"></RT·Counter·read>. <RT·name>The two options for representing zero</RT·name>
+ </RT·Counter·step>
<p>Without explicit brackets, the empty sequence collapses into an empty space, conveying no meaning when written in conventional notation. To maintain visual clarity and avoid empty spaces where zero should appear, conventional architectures adopt the standard <RT·code>0</RT·code>. However, the length function must still return zero for <RT·code>[0]</RT·code>, despite its apparent length of one.</p>
<p>In the architectural terminology utilized here, viewing memory as a horizontal tape with bytes in the cells and addresses increasing while moving to the right, little-endian numbers have the least-significant digit on the left, and big-endian numbers have the least-significant digit on the right of an allocation. Stated structurally, little-endian numbers are zero padded on the right, and big-endian numbers are zero padded on the left.</p>
- <p>Figure <RT·counter·read snapshot="Figure·little-endian_digit-order"></RT·counter·read> depicts a word featuring byte addresses represented in hexadecimal, running from c0 to c3. (In decimal these addresses represent 192, 193, 194, 195). The address of the byte before c0 is bf. The address after c3 is c4. The address for the word itself evaluates to c0, as it is the minimum byte address. This word holds a little-endian number. Treating a byte as an octet digit, the binary encoding for the least-significant digit of this number is 0001 1000. The most-significant digit is 1010 1110.</p>
+ <p>Figure <RT·Counter·read snapshot="Figure·little-endian_digit-order"></RT·Counter·read> depicts a word featuring byte addresses represented in hexadecimal, running from c0 to c3. (In decimal these addresses represent 192, 193, 194, 195). The address of the byte before c0 is bf. The address after c3 is c4. The address for the word itself evaluates to c0, as it is the minimum byte address. This word holds a little-endian number. Treating a byte as an octet digit, the binary encoding for the least-significant digit of this number is 0001 1000. The most-significant digit is 1010 1110.</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·little-endian_digit-order">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·little-endian_digit-order"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·little-endian_digit-order">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·little-endian_digit-order"></RT·Counter·snapshot>
<!-- first edition: Figure 10 -->
<figure>
<img src="Hindu-Arabic number fig 1.png" class="RT·diagram" alt="Figure 10: Left justified, least-significant-digit-first">
</figure>
- Figure <RT·counter·read snapshot="Figure·little-endian_digit-order"></RT·counter·read>. <RT·name>A left-justified word holding a number least-significant-digit-first</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·little-endian_digit-order"></RT·Counter·read>. <RT·name>A left-justified word holding a number least-significant-digit-first</RT·name>
+ </RT·Counter·step>
- <p>In Figure <RT·counter·read snapshot="Figure·big-endian_digit-order"></RT·counter·read>, the same number populates the word using big-endian architecture. For all but very large numbers, the digit pointed at by the allocation pointer evaluates to zero. A system continues to scan zeros until reaching either the end of the allocation or the most-significant digit. If it reaches the end of the allocation, the contained number evaluates to zero. Because this is the exact same number shown in Figure <RT·counter·read snapshot="Figure·little-endian_digit-order"></RT·counter·read>, it retains the identical least-significant digit and most-significant digit.</p>
+ <p>In Figure <RT·Counter·read snapshot="Figure·big-endian_digit-order"></RT·Counter·read>, the same number populates the word using big-endian architecture. For all but very large numbers, the digit pointed at by the allocation pointer evaluates to zero. A system continues to scan zeros until reaching either the end of the allocation or the most-significant digit. If it reaches the end of the allocation, the contained number evaluates to zero. Because this is the exact same number shown in Figure <RT·Counter·read snapshot="Figure·little-endian_digit-order"></RT·Counter·read>, it retains the identical least-significant digit and most-significant digit.</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·big-endian_digit-order">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·big-endian_digit-order"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·big-endian_digit-order">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·big-endian_digit-order"></RT·Counter·snapshot>
<!-- first edition: Figure 11 -->
<figure>
<img src="Hindu-Arabic number fig 2.png" class="RT·diagram" alt="Figure 11: Same number using big-endian digit-order">
</figure>
- Figure <RT·counter·read snapshot="Figure·big-endian_digit-order"></RT·counter·read>. <RT·name>The same number held in big-endian digit-order</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·big-endian_digit-order"></RT·Counter·read>. <RT·name>The same number held in big-endian digit-order</RT·name>
+ </RT·Counter·step>
<p>If the specified word holds a count, the counting mechanics differ. When counting with the little-endian convention, a number grows into larger addresses as the count carries into new digits. In contrast, with big-endian architecture, counting carries into strictly smaller memory addresses.</p>
<p>Our Indian Number derived representations consist of sequences of digits. Words of allocation consist of consecutively addressed bytes. Hardware manages bytes atomically. Any bit encoding for the digits of a number must pack cleanly into bytes, otherwise the digits fracture. Achieving a clean packing requires padding the data with zeros to force alignment to an 8-bit boundary. When a system meets this criterion, treating a number as a sequence of bytes acting as digits maintains structural consistency. Due to this constraint, little-endian and big-endian are routinely classified as byte orders.</p>
- <p>Figure <RT·counter·read snapshot="Figure·in-address-order_byte-copy"></RT·counter·read> displays a stream of bytes arriving as data and being copied into a word. The digits of the word (the bytes) arrive in little-endian order and target a little-endian machine, so they are written in the exact order they are scanned off the channel.</p>
+ <p>Figure <RT·Counter·read snapshot="Figure·in-address-order_byte-copy"></RT·Counter·read> displays a stream of bytes arriving as data and being copied into a word. The digits of the word (the bytes) arrive in little-endian order and target a little-endian machine, so they are written in the exact order they are scanned off the channel.</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·in-address-order_byte-copy">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·in-address-order_byte-copy"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·in-address-order_byte-copy">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·in-address-order_byte-copy"></RT·Counter·snapshot>
<!-- first edition: Figure 12 -->
<figure>
<img src="Hindu-Arabic number fig 3.png" class="RT·diagram" alt="Figure 12: In-address-order byte by byte copy">
</figure>
- Figure <RT·counter·read snapshot="Figure·in-address-order_byte-copy"></RT·counter·read>. <RT·name>A byte-by-byte copy performed in address order</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·in-address-order_byte-copy"></RT·Counter·read>. <RT·name>A byte-by-byte copy performed in address order</RT·name>
+ </RT·Counter·step>
<p>In the second case, the identical data stream arrives with words serialized as bytes in little-endian order, but the receiving machine is big-endian. The system must reverse the bytes strictly on a word-by-word basis.</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·reverse-order_byte-copy">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·reverse-order_byte-copy"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·reverse-order_byte-copy">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·reverse-order_byte-copy"></RT·Counter·snapshot>
<!-- first edition: Figure 13 -->
<figure>
<img src="Hindu-Arabic number fig 4.png" class="RT·diagram" alt="Figure 13: Reverse order byte copy for words">
</figure>
- Figure <RT·counter·read snapshot="Figure·reverse-order_byte-copy"></RT·counter·read>. <RT·name>A reverse order byte copy performed word by word</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·reverse-order_byte-copy"></RT·Counter·read>. <RT·name>A reverse order byte copy performed word by word</RT·name>
+ </RT·Counter·step>
<p>When the data arrives, there is no way to know where the word boundaries are. Serialization destroys that structural boundary information. Without knowing where the words are, a system cannot determine when to perform the byte order reversal. Therefore, resolving this requires a different approach than the one used for bit order in bytes; the problem transfers into the software layer.</p>
</p>
<p>
- Let us put this into perspective. Suppose in ancient Roman times that a clock tick for a computer was scaled to be one day long, so that the action involves sending letters rather than variable values. Under this scale, a single nanosecond of real-world execution time equates to three days. Suppose a program initiated a read request for a location in memory on the Ides of March, the date when Caesar was assassinated on -0043-03-15. Surely that was a big day for posting letters. Table <RT·counter·read snapshot="Table·memory-tier_scaled-latency"></RT·counter·read> provides the historical date that the variable value would finally be loaded into the processor, depending on the memory tier being accessed:
+ Let us put this into perspective. Suppose in ancient Roman times that a clock tick for a computer was scaled to be one day long, so that the action involves sending letters rather than variable values. Under this scale, a single nanosecond of real-world execution time equates to three days. Suppose a program initiated a read request for a location in memory on the Ides of March, the date when Caesar was assassinated on -0043-03-15. Surely that was a big day for posting letters. Table <RT·Counter·read snapshot="Table·memory-tier_scaled-latency"></RT·Counter·read> provides the historical date that the variable value would finally be loaded into the processor, depending on the memory tier being accessed:
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·memory-tier_scaled-latency">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·memory-tier_scaled-latency"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·memory-tier_scaled-latency">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·memory-tier_scaled-latency"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·memory-tier_scaled-latency"></RT·counter·read>. <RT·name>Memory tier latency, scaled so that one clock tick lasts one day</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·memory-tier_scaled-latency"></RT·Counter·read>. <RT·name>Memory tier latency, scaled so that one clock tick lasts one day</RT·name>
+ </RT·Counter·step>
<p>
In computer architecture, there is a rule that the slower the access time, the larger the amount of data that should be transferred. The idea is then that of access time per bit, instead of access time per fetch. A common example given is that of a station wagon of hard drives driven across the country. <RT·endnote>Andrew S. Tanenbaum famously coined this concept in his 1981 textbook <em>Computer Networks</em>, stating: "Never underestimate the bandwidth of a station wagon full of tapes hurtling down the highway." This physical data transfer method is universally referred to as a sneakernet.</RT·endnote> Ten terabits, at three days, equates to 26 nanoseconds per bit. Not bad, if a user can wait three days to continue the program, but aliasing between data sets would make a program very slow. The Turing Machine model does not capture the effects of clumped data accesses.
<p>Applying this mechanical procedure to the RT two-headed reverse string example controller results in:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_linearized">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_linearized"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_linearized">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_linearized"></RT·Counter·snapshot>
<RT·code>
# Phase 1: Both heads scan right to the EOM pivot
L·initial:
write('σ' ,1 ,EOR)
halt
</RT·code>
- Code <RT·counter·read snapshot="Code·two-headed-reverse_linearized"></RT·counter·read>. <RT·name>The two-headed reverse controller as linear code with jumps</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·two-headed-reverse_linearized"></RT·Counter·read>. <RT·name>The two-headed reverse controller as linear code with jumps</RT·name>
+ </RT·Counter·step>
<p>The state labels have become addresses into the program tape, and the address of the cell indicated by the head on the first tape is now an Instruction Pointer (IP). In a sense the programmed controller has been replaced by a little Turing Machine of its own. One that controls the head on the first tape, and moves it in response to the control instructions found on the first tape. Such a controller on a processor is called a <RT·term>sequencer</RT·term>.</p>
<p>By separating the control path from the data path, utilizing an integrated symbol alphabet, replacing states with sequential instructions, and introducing an explicit addressable instruction pointer, the theoretical machine has physically crossed the bridge to conventional computing. The resulting architecture is a stored-program, von Neumann-style machine organization.</p>
- <p>Some of the default cases for the jump table unnecessarily jump to the instruction at the next sequential address. Code <RT·counter·read snapshot="Code·two-headed-reverse_linearized"></RT·counter·read> lacks the regularity to use a computed jump table, so this style of jump table becomes a Lisp <RT·code>cond</RT·code> statement, i.e. sequential conditional tests. So then by using the instructions <RT·code>test</RT·code>, <RT·code>beq</RT·code> (for branch on equal), and <RT·code>jump</RT·code> as control instructions, and rearranging to favor sequential execution, this code becomes:</p>
+ <p>Some of the default cases for the jump table unnecessarily jump to the instruction at the next sequential address. Code <RT·Counter·read snapshot="Code·two-headed-reverse_linearized"></RT·Counter·read> lacks the regularity to use a computed jump table, so this style of jump table becomes a Lisp <RT·code>cond</RT·code> statement, i.e. sequential conditional tests. So then by using the instructions <RT·code>test</RT·code>, <RT·code>beq</RT·code> (for branch on equal), and <RT·code>jump</RT·code> as control instructions, and rearranging to favor sequential execution, this code becomes:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_with_branches">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_with_branches"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·two-headed-reverse_with_branches">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·two-headed-reverse_with_branches"></RT·Counter·snapshot>
<RT·code>
# Phase 1: Both heads scan right to the EOM pivot
L·initial:
write('σ' ,1 ,EOR)
halt
</RT·code>
- Code <RT·counter·read snapshot="Code·two-headed-reverse_with_branches"></RT·counter·read>. <RT·name>The same controller using test, branch and jump instructions</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·two-headed-reverse_with_branches"></RT·Counter·read>. <RT·name>The same controller using test, branch and jump instructions</RT·name>
+ </RT·Counter·step>
<p>This is an assembly-level code description of an instruction sequence. To get it into final form, the labels that appear as instruction arguments would be replaced with their addresses. Symbolic labels would not appear on the tape. As an alternative to using absolute branches, relative branches could be used. Performance will be greatly enhanced for a sequencer that performs relative branching if it contains an adder circuit; otherwise, the addition of offsets would be another RT Machine program invocation.</p>
</p>
<p>
- At the time of this writing many machines use 64 bit words. This is equivalent to 8 ASCII characters, while the average size of an identifier is about 5 characters. Hence the approach of using a string as a symbol might not be as inefficient as it seems to be at first. Using strings has advantages. Symbol instances can carry semantic clues for the programmer. There is no hazard of conflating the string instance with the name, as they are the same. Also, a string instance will have integrity across contexts, such as between invocations or when passed between processes (note section <RT·counter·read snapshot="Section·distinctness_across-contexts"></RT·counter·read>, on crossing context boundaries). A drawback is in cases there is no language support, the strings are typically ad hoc so the guarantee of distinctness becomes merely a contract with the programmer.
+ At the time of this writing many machines use 64 bit words. This is equivalent to 8 ASCII characters, while the average size of an identifier is about 5 characters. Hence the approach of using a string as a symbol might not be as inefficient as it seems to be at first. Using strings has advantages. Symbol instances can carry semantic clues for the programmer. There is no hazard of conflating the string instance with the name, as they are the same. Also, a string instance will have integrity across contexts, such as between invocations or when passed between processes (note section <RT·Counter·read snapshot="Section·distinctness_across-contexts"></RT·Counter·read>, on crossing context boundaries). A drawback is in cases there is no language support, the strings are typically ad hoc so the guarantee of distinctness becomes merely a contract with the programmer.
</p>
</RT·section>
The <RT·code>enum</RT·code> of C is used to make alphabets of named symbols. Each entry in the enum is a static symbol factory, and instances are distinct Integers.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·symbol-factory_enum">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·symbol-factory_enum"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·symbol-factory_enum">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·symbol-factory_enum"></RT·Counter·snapshot>
<RT·code>
/* The enum definition acts as the factory. */
typedef enum {
/* Evaluates to True */
}
</RT·code>
- Code <RT·counter·read snapshot="Code·symbol-factory_enum"></RT·counter·read>. <RT·name>A static symbol factory made with a C enum</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·symbol-factory_enum"></RT·Counter·read>. <RT·name>A static symbol factory made with a C enum</RT·name>
+ </RT·Counter·step>
<p>
The <RT·code>enum</RT·code> is a static alphabet made by the compiler, where symbol instances are Integers. In the following example, the alphabet is made dynamically, where each symbol instance is a string pointer.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·symbol-factory_dynamic">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·symbol-factory_dynamic"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·symbol-factory_dynamic">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·symbol-factory_dynamic"></RT·Counter·snapshot>
<RT·code>
#include <string.h>
#include <stdlib.h>
if(e == NULL) printf("e is NULL\n");
}
</RT·code>
- Code <RT·counter·read snapshot="Code·symbol-factory_dynamic"></RT·counter·read>. <RT·name>A dynamic symbol factory whose instances are string pointers</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·symbol-factory_dynamic"></RT·Counter·read>. <RT·name>A dynamic symbol factory whose instances are string pointers</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>
The orders of analysis were named in section
- <RT·counter·read snapshot="Section·orders-of-analysis"></RT·counter·read>. This
+ <RT·Counter·read snapshot="Section·orders-of-analysis"></RT·Counter·read>. This
chapter takes the second-order as its working material.
</p>
Suppose our goal is to subtract 3 from 5 in the second-order. Consider a Turing Machine representation named <RT·code>five</RT·code> that outputs the number 5, i.e., it prints to the tape, 'sssss', using unary notation. Let us assume that the tape is initially empty and that the empty symbol '□' terminates the string. To preserve the code for second-order analysis, we define the program's Abstract Syntax Tree (AST) as a quoted <RT·code>progn</RT·code> block. This block can contain any native Lisp control structures, though for this generator it is a simple sequence:
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·five_AST">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·five_AST"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·five_AST">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·five_AST"></RT·Counter·snapshot>
<RT·code>
(defparameter *five-ast*
'(progn
(write s) (step)
))
</RT·code>
- Code <RT·counter·read snapshot="Code·five_AST"></RT·counter·read>. <RT·name>The abstract syntax tree for the Peano Number five</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·five_AST"></RT·Counter·read>. <RT·name>The abstract syntax tree for the Peano Number five</RT·name>
+ </RT·Counter·step>
<p>Similarly, the AST for the number 3:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·three_AST">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·three_AST"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·three_AST">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·three_AST"></RT·Counter·snapshot>
<RT·code>
(defparameter *three-ast*
'(progn
(write s) (step)
))
</RT·code>
- Code <RT·counter·read snapshot="Code·three_AST"></RT·counter·read>. <RT·name>The abstract syntax tree for the Peano Number three</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·three_AST"></RT·Counter·read>. <RT·name>The abstract syntax tree for the Peano Number three</RT·name>
+ </RT·Counter·step>
<p>
If we were to dynamically evaluate these ASTs in the first-order, the Hindu-Arabic representation of each number would be physically written in unary code on the tape.
For the second-order difference operation, we compose the ASTs to create a new program. Here we extract the body of the second operand's AST and substitute every <RT·code>(write s)</RT·code> followed by a <RT·code>(step)</RT·code> instruction with an inverted pair: a <RT·code>(left)</RT·code> instruction followed by writing the empty symbol <RT·code>(write □)</RT·code>.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·subtract_composer">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·subtract_composer"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·subtract_composer">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·subtract_composer"></RT·Counter·snapshot>
<RT·code>
(defun invert-direction (cmds)
(cond
,@(invert-direction body-b)
)))
</RT·code>
- Code <RT·counter·read snapshot="Code·subtract_composer"></RT·counter·read>. <RT·name>A composer that subtracts by inverting the direction of one machine</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·subtract_composer"></RT·Counter·read>. <RT·name>A composer that subtracts by inverting the direction of one machine</RT·name>
+ </RT·Counter·step>
<p>We pass our two Peano Number ASTs to this composer, and we get as a result a newly synthesized AST.</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·five-minus-three_primitive">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·five-minus-three_primitive"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·five-minus-three_primitive">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·five-minus-three_primitive"></RT·Counter·snapshot>
<RT·code>
(defparameter
*primitive-five-minus-3-ast*
;; (left) (write □)
;; )
</RT·code>
- Code <RT·counter·read snapshot="Code·five-minus-three_primitive"></RT·counter·read>. <RT·name>The composed but unsimplified tree for five minus three</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·five-minus-three_primitive"></RT·Counter·read>. <RT·name>The composed but unsimplified tree for five minus three</RT·name>
+ </RT·Counter·step>
<p>
I called this 'primitive' because it is missing the simplification. This sort of simplification is also known as compiler code optimization. Optimizations can be operation specific, or general in nature. Here we will send the primitive composition's body to an analyzer which scans the steps and removes the redundant operations.
For a program containing branched control logic, the simplifier would require a deep recursive walk of the AST to ensure operations aren't annihilated across conditional boundaries. For our explicit Peano Number generators, a linear scan of the <RT·code>progn</RT·code> body suffices. It calls itself recursively until the scan fails to find any further reductions, returning its optimized AST.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·machine_simplifier">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·machine_simplifier"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·machine_simplifier">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·machine_simplifier"></RT·Counter·snapshot>
<RT·code>
(defun remove-annihilations (cmds)
(cond
)))
</RT·code>
- Code <RT·counter·read snapshot="Code·machine_simplifier"></RT·counter·read>. <RT·name>A simplifier that removes annihilating instruction pairs</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·machine_simplifier"></RT·Counter·read>. <RT·name>A simplifier that removes annihilating instruction pairs</RT·name>
+ </RT·Counter·step>
<p>After giving the difference program to the simplifier, we get:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·five-minus-three_simplified">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·five-minus-three_simplified"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·five-minus-three_simplified">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·five-minus-three_simplified"></RT·Counter·snapshot>
<RT·code>
(defparameter
*simplified-five-minus-3-ast*
;; (write s) (step)
;; (write s) (step))
</RT·code>
- Code <RT·counter·read snapshot="Code·five-minus-three_simplified"></RT·counter·read>. <RT·name>The simplified tree for five minus three</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·five-minus-three_simplified"></RT·Counter·read>. <RT·name>The simplified tree for five minus three</RT·name>
+ </RT·Counter·step>
<p>This technique of composing Turing Machine programs in the presence of simplification is closely related to that of symbol computation and expression simplification that we find in math tools such as Mathematica. We can imagine our Turing Machines as functions with names, and then symbolic computation leaves them unevaluated as here. Then the Mathematica <RT·code>Simplify</RT·code> is the compiler optimization simplifier as above. A difference in these two systems is that of the functions being reduced to Turing Machine head and tape transport unit instructions.</p>
Let us take the multiplicative inverse of the additive identity as an example, AKA division by zero. In the second-order, when we attempt to compute a division, say 6/0, the machine will not reduce.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·divide-by-zero">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·divide-by-zero"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·divide-by-zero">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·divide-by-zero"></RT·Counter·snapshot>
<RT·code>
(divide 6 0)
</RT·code>
- Code <RT·counter·read snapshot="Code·divide-by-zero"></RT·counter·read>. <RT·name>A division by zero, which does not reduce</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·divide-by-zero"></RT·Counter·read>. <RT·name>A division by zero, which does not reduce</RT·name>
+ </RT·Counter·step>
<p>Now consider the compiler optimization like simplification of this expression:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·divide-by-zero_composed">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·divide-by-zero_composed"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·divide-by-zero_composed">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·divide-by-zero_composed"></RT·Counter·snapshot>
<RT·code>
(divide (divide 6 0) (divide 3 0))
</RT·code>
- Code <RT·counter·read snapshot="Code·divide-by-zero_composed"></RT·counter·read>. <RT·name>A composition of two unreduced divisions</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·divide-by-zero_composed"></RT·Counter·read>. <RT·name>A composition of two unreduced divisions</RT·name>
+ </RT·Counter·step>
<p>The result will be:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·divide-by-zero_result">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·divide-by-zero_result"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·divide-by-zero_result">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·divide-by-zero_result"></RT·Counter·snapshot>
<RT·code>
(multiply 2 (divide 0 0))
</RT·code>
- Code <RT·counter·read snapshot="Code·divide-by-zero_result"></RT·counter·read>. <RT·name>The reduced result, still carrying a divide of zero by zero</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·divide-by-zero_result"></RT·Counter·read>. <RT·name>The reduced result, still carrying a divide of zero by zero</RT·name>
+ </RT·Counter·step>
<p>
There is no special help here. Hence, <RT·code>(divide 0 0)</RT·code> remains as an error flag.
Let us construct a forward difference pyramid for the polynomial <RT·math>f(t) = t^2</RT·math>.
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·difference-table_for_t-squared">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·difference-table_for_t-squared"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·difference-table_for_t-squared">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·difference-table_for_t-squared"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·difference-table_for_t-squared"></RT·counter·read>. <RT·name>The forward difference table for f(t) = t²</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·difference-table_for_t-squared"></RT·Counter·read>. <RT·name>The forward difference table for f(t) = t²</RT·name>
+ </RT·Counter·step>
<p>
In order to design for indefinite extension, the Turing Machine tape must retain the function value alongside with its forward differences. Because the second difference is constant higher-order differences are all zero. Hence the tape requires a three component vector to hold the differences.
Here is the sequence of tape states as the machine is repeatedly called to extend the function from its initial conditions at <RT·math>t = 0</RT·math>. During each step, the machine adds <RT·math>δ^1</RT·math> to <RT·math>f</RT·math>, and <RT·math>δ^2</RT·math> to <RT·math>δ^1</RT·math>, as there is no <RT·math>δ^3</RT·math>, it is taken to be zero, so <RT·math>δ^2</RT·math> is merely copied down.
</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·difference-engine_tape-trace">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·difference-engine_tape-trace"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·difference-engine_tape-trace">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·difference-engine_tape-trace"></RT·Counter·snapshot>
<RT·code>
Initial Tape (t=0): [0, 1, 2]
Call 1 (t=1): [1, 3, 2]
Call 3 (t=3): [9, 7, 2]
Call 4 (t=4): [16, 9, 2]
</RT·code>
- Code <RT·counter·read snapshot="Code·difference-engine_tape-trace"></RT·counter·read>. <RT·name>The tape at each call while extending t²</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·difference-engine_tape-trace"></RT·Counter·read>. <RT·name>The tape at each call while extending t²</RT·name>
+ </RT·Counter·step>
<p>
For Call 1, the input tape is the Initial Tape. In Call 1 the machine will take the function value on the input tape, 0, and add the first difference, 1, writing the result 1, to the result tape. The machine will then continue on and take the first difference on the input tape, 1, and add the second difference on the input tape, 2, writing the result first difference to the result tape, 3. Then finishing up, the machine will not find a third difference on the input tape, so it will copy the second difference found on the input tape as the second difference for the result tape.
The exact algebraic composition of this mechanical expansion is formalized by Newton's calculus of finite differences <RT·endnote>Isaac Newton formalized this interpolation method in 1675, later published in his <em>Methodus Differentialis</em> (1711). For a comprehensive foundational treatment, see George Boole, <em>A Treatise on the Calculus of Finite Differences</em> (Cambridge: Macmillan and Co., 1860), Chapter II.</RT·endnote>. Instead of executing the machine incrementally, a person can calculate the function value at call <RT·math>\omega</RT·math> directly as a linear combination of the initial tape components using Newton's forward difference formula:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·Newton_forward-difference">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·Newton_forward-difference"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·Newton_forward-difference">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·Newton_forward-difference"></RT·Counter·snapshot>
<RT·math>
D_{\omega, 0} = \sum_{j=0}^{\omega} \binom{\omega}{j} D_{0, j}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·Newton_forward-difference"></RT·counter·read> <RT·name>Newton's forward difference formula for the value at call ω</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·Newton_forward-difference"></RT·Counter·read> <RT·name>Newton's forward difference formula for the value at call ω</RT·name>
+ </RT·Counter·step>
<p>
Because the binomial coefficient <RT·math>\binom{\omega}{j}</RT·math> evaluates to exactly zero for any Integer <RT·math>j > \omega</RT·math>, the summation naturally truncates at index <RT·math>\omega</RT·math>. This algebraic property perfectly mirrors the physical boundary established by the machine execution trace. Furthermore, the relationship is symmetric. A person can compute the specific components of the initial tape, <RT·math>D_{0, n}</RT·math>, directly from the sequence of evaluated function calls, <RT·math>D_{k, 0}</RT·math>, using the alternating binomial sum:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·initial-tape_from_evaluations">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·initial-tape_from_evaluations"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·initial-tape_from_evaluations">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·initial-tape_from_evaluations"></RT·Counter·snapshot>
<RT·math>
D_{0, n} = \sum_{k=0}^{n} (-1)^{n-k} \binom{n}{k} D_{k, 0}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·initial-tape_from_evaluations"></RT·counter·read> <RT·name>The initial tape components recovered from evaluated calls</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·initial-tape_from_evaluations"></RT·Counter·read> <RT·name>The initial tape components recovered from evaluated calls</RT·name>
+ </RT·Counter·step>
<p>
As a consequence of this lemma, we know that for any finite number of calls, i.e. finite <RT·math>\omega</RT·math>, that a finite prefix of <RT·math>D_0</RT·math> is used.
To observe the structural integrity of this progression, a person can array these relationships into a system of equations mapping the initial tape to the polynomial constants:
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·difference_equations">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·difference_equations"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·difference_equations">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·difference_equations"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·difference_equations"></RT·counter·read>. <RT·name>The initial differences as a system of equations in the polynomial constants</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·difference_equations"></RT·Counter·read>. <RT·name>The initial differences as a system of equations in the polynomial constants</RT·name>
+ </RT·Counter·step>
<p>
A pattern emerges. Because each successive forward difference operator annihilates the lowest power of <RT·math>t</RT·math>, the resulting algebraic system is upper triangular. For any extent <RT·math>\omega</RT·math>, the <RT·math>\omega</RT·math>th difference equation reduces to <RT·math>D_{0,\omega} = \omega! a_\omega</RT·math>. This structural guarantee permits a person to reliably recover <RT·math>a_\omega = D_{0,\omega} / \omega!</RT·math>. Because an initial tape of extent <RT·math>\omega</RT·math> dictates that <RT·math>D_{0,\omega}</RT·math> is nonzero, <RT·math>a_\omega</RT·math> is guaranteed to be nonzero. All subsequent lower-order constants are then systematically resolved through cascading back substitution.
To observe the formal mechanics of this progression, a person can alternatively array these relationships into a matrix equation mapping the polynomial constants, <RT·math>a_i</RT·math>, to the initial tape differences, <RT·math>D_{0,n}</RT·math>. The coefficients of this transformation are defined by the Stirling numbers of the second kind, denoted <RT·math>S(i,n)</RT·math>:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·Stirling-second_matrix">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·Stirling-second_matrix"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·Stirling-second_matrix">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·Stirling-second_matrix"></RT·Counter·snapshot>
<RT·math>
\begin{bmatrix} D_{0,0} \\ D_{0,1} \\ D_{0,2} \\ \vdots \\ D_{0,\omega} \end{bmatrix} =
\begin{bmatrix}
\end{bmatrix}
\begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_\omega \end{bmatrix}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·Stirling-second_matrix"></RT·counter·read> <RT·name>Polynomial constants carried to initial differences by Stirling numbers of the second kind</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·Stirling-second_matrix"></RT·Counter·read> <RT·name>Polynomial constants carried to initial differences by Stirling numbers of the second kind</RT·name>
+ </RT·Counter·step>
<p>
For any extent <RT·math>\omega</RT·math>, the final row of this strictly upper triangular matrix again simplifies to <RT·math>D_{0,\omega} = \omega! a_\omega</RT·math>.
</p>
<p>
- The main diagonal contains strictly non-zero factorials, ensuring the matrix is invertible. By inverting this matrix, a person replaces the cascading back substitution with a direct, closed form equation to recover any constant <RT·math>a_i</RT·math>. The inversion utilizes the signed Stirling numbers of the first kind, denoted <RT·math>s(n,i)</RT·math> (see the Appendix on Stirling numbers, section <RT·counter·read snapshot="Section·appendix_Stirling-numbers"></RT·counter·read>).
+ The main diagonal contains strictly non-zero factorials, ensuring the matrix is invertible. By inverting this matrix, a person replaces the cascading back substitution with a direct, closed form equation to recover any constant <RT·math>a_i</RT·math>. The inversion utilizes the signed Stirling numbers of the first kind, denoted <RT·math>s(n,i)</RT·math> (see the Appendix on Stirling numbers, section <RT·Counter·read snapshot="Section·appendix_Stirling-numbers"></RT·Counter·read>).
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·polynomial-constant_from_differences">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·polynomial-constant_from_differences"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·polynomial-constant_from_differences">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·polynomial-constant_from_differences"></RT·Counter·snapshot>
<RT·math>
a_i = \sum_{n=i}^{\omega} \frac{s(n,i)}{n!} D_{0,n}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·polynomial-constant_from_differences"></RT·counter·read> <RT·name>A polynomial constant recovered using signed Stirling numbers of the first kind</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·polynomial-constant_from_differences"></RT·Counter·read> <RT·name>A polynomial constant recovered using signed Stirling numbers of the first kind</RT·name>
+ </RT·Counter·step>
<p>
Thus, extending this procedure <RT·math>\omega</RT·math> times definitively recovers the constants for exactly a polynomial of degree <RT·math>\omega</RT·math>.
This mechanical recovery of standard polynomial constants is completely analogous to Newton's interpolation formula <RT·endnote>Ibid.</RT·endnote>. Instead of resolving the standard constants <RT·math>a_i</RT·math> through an upper triangular matrix, a person can construct the polynomial directly by treating the initial tape components as the exact coefficients for a basis of binomial terms:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·polynomial_from_initial-tape">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·polynomial_from_initial-tape"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·polynomial_from_initial-tape">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·polynomial_from_initial-tape"></RT·Counter·snapshot>
<RT·math>
f(t) = \sum_{n=0}^{\omega} D_{0, n} \binom{t}{n}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·polynomial_from_initial-tape"></RT·counter·read> <RT·name>The polynomial built directly on a basis of binomial terms</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·polynomial_from_initial-tape"></RT·Counter·read> <RT·name>The polynomial built directly on a basis of binomial terms</RT·name>
+ </RT·Counter·step>
<p>
Because the <RT·math>n</RT·math>th binomial coefficient expands into a polynomial of exactly degree <RT·math>n</RT·math>, and the summation is bounded by the finite extent <RT·math>\omega</RT·math> where <RT·math>D_{0, \omega}</RT·math> is definitively nonzero, the constructed function <RT·math>f(t)</RT·math> is structurally guaranteed to be a polynomial of degree <RT·math>\omega</RT·math>.
Here is the table of finite differences for the function <RT·math>2^t</RT·math>.
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·difference-table_for_2-to-the-t">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·difference-table_for_2-to-the-t"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·difference-table_for_2-to-the-t">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·difference-table_for_2-to-the-t"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·difference-table_for_2-to-the-t"></RT·counter·read>. <RT·name>The forward difference table for f(t) = 2ᵗ</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·difference-table_for_2-to-the-t"></RT·Counter·read>. <RT·name>The forward difference table for f(t) = 2ᵗ</RT·name>
+ </RT·Counter·step>
<p>
- The first difference of <RT·math>2^t</RT·math> is also <RT·math>2^t</RT·math>, so row 0 of the table will have an infinite number of values. Fortunately, due to the lemma of section <RT·counter·read snapshot="Section·lemma_evaluating-call"></RT·counter·read>, stating that evaluating call <RT·math>\omega</RT·math> requires an initial tape populated with components 0 through <RT·math>\omega</RT·math> of row 0, exactly those components are needed for the recurrence to proceed. Furthermore, when new values are needed, they are easily computed. A programmer need not store the entire infinite first row of the difference table on a static tape.
+ The first difference of <RT·math>2^t</RT·math> is also <RT·math>2^t</RT·math>, so row 0 of the table will have an infinite number of values. Fortunately, due to the lemma of section <RT·Counter·read snapshot="Section·lemma_evaluating-call"></RT·Counter·read>, stating that evaluating call <RT·math>\omega</RT·math> requires an initial tape populated with components 0 through <RT·math>\omega</RT·math> of row 0, exactly those components are needed for the recurrence to proceed. Furthermore, when new values are needed, they are easily computed. A programmer need not store the entire infinite first row of the difference table on a static tape.
</p>
<p>
Now suppose we want to express the quotient of these two functions.
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·quotient_definition">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·quotient_definition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·quotient_definition">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·quotient_definition"></RT·Counter·snapshot>
<RT·math>
h(t) = \frac{f(t)}{g(t)} = \frac{2^t - 32}{3t - 15}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·quotient_definition"></RT·counter·read> <RT·name>The quotient h(t), carrying a pole and a zero at t = 5</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·quotient_definition"></RT·Counter·read> <RT·name>The quotient h(t), carrying a pole and a zero at t = 5</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·singularity_plot">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·singularity_plot"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·singularity_plot">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·singularity_plot"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="singularity_plot.png" class="RT·diagram" alt="Figure singularity plot">
</figure>
- Figure <RT·counter·read snapshot="Figure·singularity_plot"></RT·counter·read>. <RT·name>The quotient h(t) plotted across the singularity at t = 5</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·singularity_plot"></RT·Counter·read>. <RT·name>The quotient h(t) plotted across the singularity at t = 5</RT·name>
+ </RT·Counter·step>
<p>
Suppose we move to a second-order evaluation, and for places the computation does not work, we return the machine that isn't evaluating. That is similar to what we did to get <RT·code>(divide 0 0)</RT·code>, but the zeros in that expression came from a prior step first-order evaluation. Let us instead give the quotient composer two machines to compose, and have it return a value when reduction to the first-order is possible, and return the full problem as posed to it when it can not be reduced.
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·quotient_difference-ratios">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·quotient_difference-ratios"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·quotient_difference-ratios">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·quotient_difference-ratios"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·quotient_difference-ratios"></RT·counter·read>. <RT·name>The quotient and the ratio of first differences through the singularity</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·quotient_difference-ratios"></RT·Counter·read>. <RT·name>The quotient and the ratio of first differences through the singularity</RT·name>
+ </RT·Counter·step>
<p>
The quotient machine, <RT·code>(divide f(5) g(5))</RT·code>, is no more representative of the value we expected here, than was <RT·code>(divide 0 0)</RT·code>. However, as we have the whole program, we could pass it to a L'Hôpital evaluator and get a value back. But I am wondering if we can't design function extension form that extends to the value and beyond without any hiccups, as most apparently there is a value to extend to.
</p>
<p>
- I included the first difference along with the evaluation results in Table <RT·counter·read snapshot="Table·quotient_difference-ratios"></RT·counter·read>. When building a first difference table an interesting thing happens at the singularity, the first difference and the function itself coincide, note calls 4 and 5. This makes sense because <RT·math>δ f(4) = f(5) - f(4)</RT·math>, which becomes <RT·math>δ f(4) = 0 - f(4)</RT·math>, and the same happens to <RT·code>g</RT·code> in the denominator, so the signs cancel. Note also <RT·math>δ f(5) = f(6) - f(5)</RT·math>, which becomes <RT·math>δ f(5) = f(6) - 0</RT·math>.
+ I included the first difference along with the evaluation results in Table <RT·Counter·read snapshot="Table·quotient_difference-ratios"></RT·Counter·read>. When building a first difference table an interesting thing happens at the singularity, the first difference and the function itself coincide, note calls 4 and 5. This makes sense because <RT·math>δ f(4) = f(5) - f(4)</RT·math>, which becomes <RT·math>δ f(4) = 0 - f(4)</RT·math>, and the same happens to <RT·code>g</RT·code> in the denominator, so the signs cancel. Note also <RT·math>δ f(5) = f(6) - f(5)</RT·math>, which becomes <RT·math>δ f(5) = f(6) - 0</RT·math>.
</p>
<p>Ostensibly it looks like we have happened upon a discrete version of L'Hôpital's rule, that we merely use the first difference quotient instead of the function quotient at the singularity. But alas, the coincidence occurs at <RT·math>h(4)</RT·math> rather than at <RT·math>h(5)</RT·math>. For the second coincidence, we find <RT·math>h(6)</RT·math> as the 5th first finite difference. In neither case did we learn anything about the value of <RT·math>h(5)</RT·math>.
So then, perhaps we set the value at the singularity to <RT·math>x</RT·math> build out the difference table, then solve for <RT·math>x</RT·math>?
</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·difference-table_with_x">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·difference-table_with_x"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·difference-table_with_x">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·difference-table_with_x"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="with_x_variable.png" class="RT·diagram" alt="Figure with x variable.">
</figure>
- Figure <RT·counter·read snapshot="Figure·difference-table_with_x"></RT·counter·read>. <RT·name>The difference table with the singular value carried as the variable x</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·difference-table_with_x"></RT·Counter·read>. <RT·name>The difference table with the singular value carried as the variable x</RT·name>
+ </RT·Counter·step>
<p>
As Newton pointed out, we can know the differences on the <RT·math>D_0</RT·math> row of the table from the quotient function:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·quotient_initial-differences">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·quotient_initial-differences"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·quotient_initial-differences">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·quotient_initial-differences"></RT·Counter·snapshot>
<RT·math>
D_{0,n} = \sum_{k=0}^n (-1)^{n-k} \binom{n}{k} \frac{f(k)}{g(k)}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·quotient_initial-differences"></RT·counter·read> <RT·name>The initial differences of the quotient, taken from the function</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·quotient_initial-differences"></RT·Counter·read> <RT·name>The initial differences of the quotient, taken from the function</RT·name>
+ </RT·Counter·step>
<p>
For <RT·math>k=5</RT·math> the difference evaluates to be <RT·code>(divide 0 0)</RT·code>, as it did for the quotient, and it also fails for all values above <RT·math>k=5</RT·math> due to the summation. So we can not use this to solve for <RT·math>x</RT·math>.
The L'Hôpital evaluator will discover that a transcendental constant is required. It will be returned as a higher-order object, a machine definition, because the value can not be written to the tape.
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·transcendental_constant">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·transcendental_constant"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·transcendental_constant">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·transcendental_constant"></RT·Counter·snapshot>
<RT·math>
T = \frac{32 \ln(2)}{3}
</RT·math>
- eq: <RT·counter·read snapshot="Equation·transcendental_constant"></RT·counter·read> <RT·name>The transcendental constant the quotient requires</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·transcendental_constant"></RT·Counter·read> <RT·name>The transcendental constant the quotient requires</RT·name>
+ </RT·Counter·step>
<p>The resulting <RT·math>D_0</RT·math> vector for the quotient is:</p>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·D_0-vector_for-quotient">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·D_0-vector_for-quotient"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·D_0-vector_for-quotient">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·D_0-vector_for-quotient"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="D_10.png" class="RT·diagram" alt="Figure D_0 h(t)">
</figure>
- Figure <RT·counter·read snapshot="Figure·D_0-vector_for-quotient"></RT·counter·read>. <RT·name>The D₀ vector for the quotient</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·D_0-vector_for-quotient"></RT·Counter·read>. <RT·name>The D₀ vector for the quotient</RT·name>
+ </RT·Counter·step>
- <RT·counter·step counter="RT·Figure·counter" id="Figure·difference-table_for_h">
- <RT·counter·snapshot counter="RT·Figure·counter" snapshot="Figure·difference-table_for_h"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Figure·counter" id="Figure·difference-table_for_h">
+ <RT·Counter·snapshot counter="RT·Figure·counter" snapshot="Figure·difference-table_for_h"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<figure>
<img src="h_of_t_D_table.png" class="RT·diagram" alt="Figure D table for h(t)">
</figure>
- Figure <RT·counter·read snapshot="Figure·difference-table_for_h"></RT·counter·read>. <RT·name>The difference table for h(t)</RT·name>
- </RT·counter·step>
+ Figure <RT·Counter·read snapshot="Figure·difference-table_for_h"></RT·Counter·read>. <RT·name>The difference table for h(t)</RT·name>
+ </RT·Counter·step>
<p>
I find it fascinating to watch the transcendental difference values march down the table, then all cancel out after <RT·math>h(5)</RT·math> is generated.
<p>And for the victory lap, evaluation versus higher-order computation and function extension:</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·direct-evaluation_vs_extended-quotient">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·direct-evaluation_vs_extended-quotient"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·direct-evaluation_vs_extended-quotient">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·direct-evaluation_vs_extended-quotient"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·direct-evaluation_vs_extended-quotient"></RT·counter·read>. <RT·name>Direct evaluation of f(t)/g(t) against the extended quotient vector H(t)</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·direct-evaluation_vs_extended-quotient"></RT·Counter·read>. <RT·name>Direct evaluation of f(t)/g(t) against the extended quotient vector H(t)</RT·name>
+ </RT·Counter·step>
</RT·section>
<p>The fundamental claim of computational analysis is that all functions can be viewed as discrete entities. Take this simple function:</p>
- <RT·counter·step counter="RT·Code·counter" id="Code·cubic_function">
- <RT·counter·snapshot counter="RT·Code·counter" snapshot="Code·cubic_function"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Code·counter" id="Code·cubic_function">
+ <RT·Counter·snapshot counter="RT·Code·counter" snapshot="Code·cubic_function"></RT·Counter·snapshot>
<RT·code>
f(t) = t^3
</RT·code>
- Code <RT·counter·read snapshot="Code·cubic_function"></RT·counter·read>. <RT·name>A simple cubic function</RT·name>
- </RT·counter·step>
+ Code <RT·Counter·read snapshot="Code·cubic_function"></RT·Counter·read>. <RT·name>A simple cubic function</RT·name>
+ </RT·Counter·step>
<p>It is said to be a continuous function over the real field. However, from a computational perspective, it is a string of 8 discrete symbols. A person might ask then, "If the function is not continuous, then how can a person take a derivative?" Often people view a derivative as a tangent line to a curve drawn on a plot. The computational analyst's answer is to use a machine that manipulates the symbols; it will move the 3 down in front of the <RT·math>t</RT·math>, decrement the power, and write 2. Those are all discrete operations.</p>
<RT·name>Does computation theory matter to computing?</RT·name>
<p>
- Let us put this into perspective. Suppose in ancient Roman times that a clock tick for a computer was scaled to be one day long. Under this scale, a single nanosecond of real-world execution time equates to three days. Suppose a program initiated a read request for a location in memory on the Ides of March, the date when Caesar was assassinated on 0043-03-15. Table <RT·counter·read snapshot="Table·memory-tier_scaled-latency_appendix"></RT·counter·read> provides the historical date that the variable value would finally be loaded into the processor, depending on the memory tier being accessed:
+ Let us put this into perspective. Suppose in ancient Roman times that a clock tick for a computer was scaled to be one day long. Under this scale, a single nanosecond of real-world execution time equates to three days. Suppose a program initiated a read request for a location in memory on the Ides of March, the date when Caesar was assassinated on 0043-03-15. Table <RT·Counter·read snapshot="Table·memory-tier_scaled-latency_appendix"></RT·Counter·read> provides the historical date that the variable value would finally be loaded into the processor, depending on the memory tier being accessed:
</p>
- <RT·counter·step counter="RT·Table·counter" id="Table·memory-tier_scaled-latency_appendix">
- <RT·counter·snapshot counter="RT·Table·counter" snapshot="Table·memory-tier_scaled-latency_appendix"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Table·counter" id="Table·memory-tier_scaled-latency_appendix">
+ <RT·Counter·snapshot counter="RT·Table·counter" snapshot="Table·memory-tier_scaled-latency_appendix"></RT·Counter·snapshot>
<!-- first edition: no number carried -->
<table>
<thead>
</tr>
</tbody>
</table>
- Table <RT·counter·read snapshot="Table·memory-tier_scaled-latency_appendix"></RT·counter·read>. <RT·name>Memory tier latency, scaled so that one clock tick lasts one day</RT·name>
- </RT·counter·step>
+ Table <RT·Counter·read snapshot="Table·memory-tier_scaled-latency_appendix"></RT·Counter·read>. <RT·name>Memory tier latency, scaled so that one clock tick lasts one day</RT·name>
+ </RT·Counter·step>
</RT·section>
</p>
<p>
- We then define the symbol in computational terms, as done in section <RT·counter·read snapshot="Section·symbol_in-computing"></RT·counter·read>. This begins with memory addresses, represented as charge arrays, acting as primitive symbols, and extends to the symbol factory, copy operations, and instance comparison.
+ We then define the symbol in computational terms, as done in section <RT·Counter·read snapshot="Section·symbol_in-computing"></RT·Counter·read>. This begins with memory addresses, represented as charge arrays, acting as primitive symbols, and extends to the symbol factory, copy operations, and instance comparison.
</p>
<p>
However, in the calculus of finite differences, standard exponents are clumsy. Because the Turing Machine evaluates discrete jumps, the natural basis is the falling factorial, denoted as <RT·math>t^{\underline{n}}</RT·math>:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·falling-factorial_definition">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·falling-factorial_definition"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·falling-factorial_definition">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·falling-factorial_definition"></RT·Counter·snapshot>
<RT·math>
t^{\underline{n}} = t(t - 1)(t - 2) ⋯ (t - n + 1)
</RT·math>
- eq: <RT·counter·read snapshot="Equation·falling-factorial_definition"></RT·counter·read> <RT·name>The falling factorial, the natural basis for discrete differences</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·falling-factorial_definition"></RT·Counter·read> <RT·name>The falling factorial, the natural basis for discrete differences</RT·name>
+ </RT·Counter·step>
<p>
When a person applies the discrete forward difference operator, <RT·math>δ</RT·math>, to a falling factorial, it behaves identically to the continuous derivative: <RT·math>δ(t^{\underline{n}}) = n t^{\underline{n - 1}}</RT·math>.
The signed Stirling numbers of the first kind perform the exact inverse operation. They reconstruct standard continuous powers from falling factorials:
</p>
- <RT·counter·step counter="RT·Equation·counter" id="Equation·falling-factorial_in_powers">
- <RT·counter·snapshot counter="RT·Equation·counter" snapshot="Equation·falling-factorial_in_powers"></RT·counter·snapshot>
+ <RT·Counter·step counter="RT·Equation·counter" id="Equation·falling-factorial_in_powers">
+ <RT·Counter·snapshot counter="RT·Equation·counter" snapshot="Equation·falling-factorial_in_powers"></RT·Counter·snapshot>
<RT·math>
t^{\underline{n}} = \sum_{k=0}^n s(n,k) t^k
</RT·math>
- eq: <RT·counter·read snapshot="Equation·falling-factorial_in_powers"></RT·counter·read> <RT·name>The falling factorial expanded over standard powers</RT·name>
- </RT·counter·step>
+ eq: <RT·Counter·read snapshot="Equation·falling-factorial_in_powers"></RT·Counter·read> <RT·name>The falling factorial expanded over standard powers</RT·name>
+ </RT·Counter·step>
<p>
Combinatorially, the unsigned magnitude of <RT·math>s(n,k)</RT·math> represents the number of ways to arrange <RT·math>n</RT·math> items into <RT·math>k</RT·math> disjoint cycles. The alternating signs account for the algebraic expansion of the falling factorial terms <RT·math>(t - 1)(t - 2)</RT·math>, etc.