From: Thomas Walker Lynch Date: Sat, 6 Jun 2026 17:29:45 +0000 (+0000) Subject: doc work X-Git-Url: https://git.reasoningtechnology.com/%27%20%20%20resolved_path%20%20%20%27?a=commitdiff_plain;h=9b94cd308f671facdd79985e1afb6461294fb632;p=TM-2026 doc work --- diff --git a/document/TM-2026.html b/document/TM-2026.html index 019b1fc..ee413f1 100644 --- a/document/TM-2026.html +++ b/document/TM-2026.html @@ -28,15 +28,19 @@

- For Hilbert and Ackermann's question to be truly answered by Alan Turing, a mathematical isomorphism between Turing Machine programs and algorithms as understood by Hilbert must be established. Turing addressed this in his paper, and with many reviewers over decades acting as a jury, he did so successfully. For Turing's purposes in his 1936 paper, the equivalence between algorithms and Turing Machine programs was sufficient. + For Hilbert and Ackermann's question to be truly answered by Alan Turing, a mathematical isomorphism between Turing Machine programs and algorithms as understood by Hilbert must be established. Turing addressed this in his paper, and with many reviewers over decades acting as a jury, he did so successfully.

- Furthermore, a connection must be made to modern computer architectures to confirm that Turing Machine results apply to them. While the Universal Turing Machine conceptually introduced programs stored as data on a tape, Turing could not provide the formal explanation of the connection to modern architectures, if for no other reason than the fact such architectures did not yet exist. The practical engineering context of 1936 was limited to calculating machines programmed via patch panels. Though Charles Babbage's 1842 Analytical Engine touched on these concepts, they would wait until the 1940s to re-emerge. For example, there is no explanation in his paper as to why a von Neumann architecture machine (1945) running a program would have the same computation theoretic results as a Turing Machine (1936). Here, by modern, I refer to physical computer organizations utilizing random-access system memory, dedicated instruction fetch streams with dynamic branching, and discrete processing units. To establish this missing connection, the volumes of the TTCA, starting in the following chapters, transform the Turing Machine into a modern architecture in a stepwise fashion, while ensuring that at each step the modifications are inconsequential to existence proofs and complexity class results. + For Turing's purposes in his 1936 paper, the equivalence between algorithms and Turing Machine programs was sufficient to tie the theory he presented into the targeted problem. However, in our computing epoch the Turing Machine can be used as the basis of computation theory, so if we could connect it to modern computer architectures, we would know that computation theory results apply to them. If the connection happens to be imperfect, that might elucidate the limitations of relying upon computation theory.

- The Turing Machine is structurally limited to stepping the read/write head over one cell per machine execution step. Thus, for any finite number of steps, only a finite amount of tape is ever used. But for a given computation, how much tape is that? Resolving this by assuming more tape is simply attached when needed is analogous to cheating in a 'guess the bigger number' game by declaring, "My number is always one bigger than the given number, so I will tell you my guess after you state your number." Some mathematicians suggest that what is meant by infinity is precisely a rule of this sort. For engineers building physical hardware, however, to state that a resource starts finite and expands incrementally over time is structurally a very different proposition than being asked to install infinite memory on a machine in the first place. + Although the Universal Turing Machine conceptually introduced programs stored as data on a tape, Turing could not provide the formal explanation of the connection to modern architectures, if for no other reason than the fact such architectures did not yet exist. The practical engineering context of 1936 was limited to calculating machines programmed via patch panels. Though Charles Babbage's 1842 Analytical Engine touched on these concepts, they would wait until the 1940s to re-emerge. For example, there is no explanation in his paper as to why a von Neumann architecture machine (1945) running a program would have the same computation theoretic results as a Turing Machine (1936). Here, by modern, I refer to physical computer organizations utilizing random-access system memory, dedicated instruction fetch streams with dynamic branching, and discrete processing units. To establish this missing connection, the volumes of the TTCA, starting in the following chapters, transform the Turing Machine into a modern architecture in a stepwise fashion, while ensuring that at each step the modifications are inconsequential to existence proofs and complexity class results. +

+ +

+ The Turing Machine is limited to stepping the read/write head over one cell per machine execution step. Thus, for any finite number of steps, only a finite amount of tape is ever used. But for a given computation, how much tape is that? Resolving this by assuming more tape is simply attached when needed is analogous to cheating in a 'guess the bigger number' game by declaring, "My number is always one bigger than the given number, so I will tell you my guess after you state your number." Some mathematicians suggest that what is meant by infinity is precisely a rule of this sort. For engineers building physical hardware, however, to state that a resource starts finite and expands incrementally over time is a very different proposition than being asked to install infinite memory on a machine in the first place.

@@ -48,7 +52,7 @@

- In reading Alan Turing's 1936 paper, it is striking how modern the text feels, specifically because he discusses algorithms, stored programs, and the mechanical limits of computation. Turing was not alone in conducting theoretical computational analysis; he explicitly notes Alonzo Church in his paper as also formulating the set of computable numbers. During this era, the academic community produced a flurry of foundational logic: Jacques Herbrand (providing the initial structural definition of computable recursive functions, 1931), Kurt Gödel (publishing the Incompleteness Theorems and formalizing general recursive functions, 1931 and 1934), Alonzo Church (inventing the lambda calculus to definitively model computable functions, 1936), Emil Post (defining "Finite Combinatory Processes" as a theoretical architecture mathematically identical to Turing, 1936), and Stephen Kleene (proving the absolute mathematical equivalence of lambda calculus, recursive functions, and theoretical machines, 1936). However, while his contemporaries largely built purely mathematical and logical frameworks, Turing uniquely tied computation theory directly to the abstraction of machines executing stored programs. Because physical hardware capable of executing stored memory programs had not yet been invented, this explicit architectural grounding makes Turing's work remarkably prescient and gives it a distinctly modern feel. + In reading Alan Turing's 1936 paper, it is striking how modern the text feels, specifically because he discusses algorithms, stored programs, and the mechanical limits of computation. Turing was not alone in conducting theoretical computational analysis; he explicitly notes Alonzo Church in his paper as also formulating the set of computable numbers. During this era, the academic community produced a flurry of foundational logic: Jacques Herbrand (providing the initial definition of computable recursive functions, 1931), Kurt Gödel (publishing the Incompleteness Theorems and formalizing general recursive functions, 1931 and 1934), Alonzo Church (inventing the lambda calculus to definitively model computable functions, 1936), Emil Post (defining "Finite Combinatory Processes" as a theoretical architecture mathematically identical to Turing, 1936), and Stephen Kleene (proving the absolute mathematical equivalence of lambda calculus, recursive functions, and theoretical machines, 1936). However, while his contemporaries largely built purely mathematical and logical frameworks, Turing uniquely tied computation theory directly to the abstraction of machines executing stored programs. Because physical hardware capable of executing stored memory programs had not yet been invented, this explicit architectural grounding makes Turing's work remarkably prescient and gives it the aforementioned distinctly modern feel.

@@ -75,7 +79,7 @@

- A realization is a physical box full of plastic, metal, fiberglass, and silicon, along with a smattering of exotic materials. A realization is created by manufacturing engineers, technicians, and product line workers, with the assistance of some of the most sophisticated machines ever built by humankind. + A realization is a physical box full of plastic, metal, fiberglass, and silicon, along with a smattering of exotic materials. A realization is made by manufacturing engineers, technicians, and product line workers, with the assistance of some of the most sophisticated machines ever built by humankind.

@@ -83,7 +87,7 @@

- Organization is the register-transfer level description of the machine, which includes internal buses, external buses and the state machines that implement the protocols used, control units, interrupt structures, methods of doing I/O, and ALU layout. It dictates the logical arrangement of hardware and the procedures that force the data to flow to satisfy the architectural constraints. The organization is created by a design architect. This level, and the next level, are defined in detail in the classic text by Hamacher, Vranesic, and Zaky . + Organization is the register-transfer level description of the machine, which includes internal buses, external buses and the state machines that implement the protocols used, control units, interrupt structures, methods of doing I/O, and ALU layout. It dictates the logical arrangement of hardware and the procedures that force the data to flow to satisfy the architectural constraints. The organization is made by a design architect. This level, and the next level, are defined in detail in the classic text by Hamacher, Vranesic, and Zaky .

@@ -95,7 +99,7 @@

- The Turing Machine is a computation theory object that is suggestive of a simple architecture; however, a little work is needed to create that architecture analog. The fundamentals are present, the read/write head, the tape, the procedure for using the tape, but other components are missing. The manipulation of symbols remains ungrounded. The tape is not well defined. The use of emptiness is non-architecture like. The tape transport is not articulated, though it is implied. The read buffer that holds a value read so the state controller can use it is not identified as a component. As we proceed, we will likely discover other missing components. + The Turing Machine is a computation theory object that is suggestive of a simple architecture; however, a little work is needed to complete architecture analog. The fundamentals are present, the read/write head, the tape, the procedure for using the tape, but other components are missing. The manipulation of symbols remains ungrounded. The tape is not well defined. The use of emptiness is non-architecture like. The tape transport is not articulated, though it is implied. The read buffer that holds a value read, so the state controller can use it over multiple non-read steps, is not identified as a component. As we proceed, we will likely discover other missing components.

@@ -114,17 +118,17 @@

- Put more formally, given a set of instantiable objects and a collection of instances created from them, for these objects to be symbols, two structural conditions must be met. First, it must be possible to define an instance comparison operation, denoted =, that acts as an equivalence relation to partition the collection into discrete equivalence classes. Second, this partitioning must result in a strict one-to-one correspondence between the resulting equivalence classes and the original instantiable objects from which the member instances were derived. + Put more formally, given a set of instantiable objects and a collection of instances made from them, for these objects to be symbols, two structural conditions must be met. First, it must be possible to define an instance comparison operation, denoted =, that acts as an equivalence relation to partition the collection into discrete equivalence classes. There must be a one-to-one correspondence between the resulting equivalence classes and the original instantiable objects from which the member instances were derived.

- It follows from this definition that the distinct equivalence classes can be used as a proxy for the instantiable objects themselves. That is, a person can name either the instantiable object or the equivalence class, and then through this correspondence, find the other and definitively know the class members. + It follows from this definition that the distinct equivalence classes can be used as a proxy for the instantiable objects themselves. That is, a person can name either the instantiable object or the equivalence class, and then through this correspondence, find the other.

The factory interpretation

- In the context of real machines, the symbol itself can be defined as a factory that produces symbol instances. A new symbol instance of the given symbol is created by calling the factory's make function. All of the symbol instances created by the factory constitute the members of the corresponding equivalence class. + In the context of real machines, the symbol itself can be defined as a factory that produces symbol instances. A new symbol instance of the given symbol is then made, say, by calling the factory's make function. All of the symbol instances made by the factory constitute the members of the corresponding equivalence class.

@@ -160,7 +164,7 @@

- Such symbol names are non-structural strings, so do not need to follow the rules of symbols. For example, a program written where references to strings were used as symbol instances, could give multiple, or all, strings the same name, and the program would function. Conventionally, the names are also required to be distinct to avoid confusion. The hazard here is that a programmer will then conflate the string name with the symbol instance, and perform symbol operations with it. + Such symbol names are non-structural strings, so they do not need to follow the rules of symbols. For example, a program written where references to strings were used as symbol instances, could give multiple, or all, strings the same name, and the program would function. Conventionally, the names are made to be distinct so as to avoid confusion. The hazard here is that a programmer will then conflate the string name with the symbol instance, and perform symbol operations with it.

@@ -172,7 +176,7 @@

- 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 the section below on crossing context boundaries). The drawback is that the strings are typically ad hoc so the guarantee of distinctness becomes merely a contract with the programmer. Attempts at strengthening the contract can lead to frustrating errors and add complexity to programs. + 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 the section below on crossing context boundaries). The drawback is that the strings are typically ad hoc so the guarantee of distinctness becomes merely a contract with the programmer. Attempts at strengthening that contract can lead to frustrating errors and add complexity to programs.

Consequentiality

@@ -186,11 +190,11 @@

- On a real machine, the factory would be used to create the alphabet and a couple of additional symbols, but as the alphabet is finite, and set in advance, making it is similarly inconsequential. + On a real machine, the factory would be used to make the alphabet and a couple of additional symbols, but as the alphabet is finite, and set in advance, making it is similarly inconsequential.

- This leaves the question of the time to copy an instance. Such a copy is done when reading and writing a tape on the Turing Machine, and reading and writing memory on a real machine. As the alphabet is finite, each symbol can be encoded in a fixed number of bits. Hence, a copy time is constant. Typically the number of symbols involved is so small, that a single read or write of memory is required for doing a copy, but even if the number of symbols is enormous, it will be a fixed constant time. However, there are extenuating circumstances, such as cache misses and page faults. So generally symbol copy time is inconsequential, but it is possible in memory aliasing conditions with page faults, that they are not. + This leaves the question of the time to copy an instance. Such a copy is done when reading and writing a tape on the Turing Machine, and reading and writing memory on a real machine. As the alphabet is finite, each symbol can be encoded in a fixed number of bits. Hence, a copy time is constant. Typically the number of symbols involved is so small, that a single read or write of memory is required for doing a copy, but even if the number of symbols is enormous, it will be a fixed constant time. There can be extenuating circumstances, such as cache misses and page faults. So generally symbol copy time is inconsequential, but it is possible in address aliasing conditions, say with page faults, can muddy the picture.

Distinctness across contexts

@@ -200,23 +204,23 @@

- This structural boundary creates challenges in computer science across many contexts. One solution is to find a scope encompassing both contexts and to place the symbol factory there. Another solution is to give each context a distinct root symbol and to use an array of symbols in place of the imported symbol. Yet another approach is to associate an imported symbol with a new symbol in the given new context using a correspondence map. + One way to meet this requirement is to find a scope encompassing both contexts and to place the symbol factory there. Another solution is to give each context a distinct root symbol and to use an array of symbols in place of the imported symbol. Yet another approach is to associate an imported symbol with a new symbol in the given new context using a correspondence map.

- When utilizing memory addresses as symbols in a virtual memory environment, the most common approach in computing is to disallow addresses in one process from being used in another. If that isolation is insufficient, it is often adequate to use indexes instead of addresses, taking the address to the base of the data structure. Though the absolute address of the data structure might differ across contexts, the relative offset remains constant. Another approach is to reserve memory address blocks and to guarantee imported pages have the exact same addresses as before, though they might be imported sequentially to reuse the memory block. In architecture, this is generally known as the pointer swizzling problem. + When utilizing memory addresses as symbols in a virtual memory environment, the convention is to disallow addresses in one process from being used in another. If that isolation is insufficient, it is often adequate to use indexes instead of addresses, taking the address to the base of the data structure. Though the absolute address of the data structure might differ across contexts, the relative offset remains constant. Another approach is to reserve memory address blocks and to guarantee imported pages have the exact same addresses as before, though they might be imported sequentially to reuse the memory block. In architecture, this is generally known as the pointer swizzling problem.

Alphabet

- An alphabet is a finite set of symbols. Because it is simply a set, an infinite number of distinct alphabets can exist. The Turing Machine specification discusses 'the alphabet' strictly because a given Turing Machine instance utilizes only one specific alphabet. + An alphabet is another name for 'a set of symbols'. Because it is simply a set, an infinite number of distinct alphabets can exist. The Turing Machine specification discusses 'the alphabet' strictly because a given Turing Machine instance utilizes only one specific alphabet. A set of symbols could be finite or infinite. The Turing Machine alphabet is finite.

Examples

- The enum structure of C is an example of a mechanism for creating alphabets of named symbols. Each entry in the enum is a static symbol factory, where instances are distinct integers. + The enum 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.

@@ -240,51 +244,85 @@ if (cell_1 == cell_2) {

- While the enum effectively demonstrates a static hardware mapping, a string interning symbol table is a rigorous example of a dynamic runtime factory. This physically demonstrates the make function taking an arbitrary string, checking a correspondence map, and returning a canonical, unique pointer in memory (the original). + The enum 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.

+ #include <string.h> +#include <stdlib.h> +#include <stdio.h> + +// maximum legal index into the symbol list +#define LIST_EXTENT 3 + +typedef const char *Instance; +typedef struct{ + Instance *head; + Instance *tail; + Instance *extent; +} List; + +static List SYM_LIST = {NULL ,NULL ,NULL}; + +Instance make_list(const char *name){ + size_t size = LIST_EXTENT + 1; + SYM_LIST.head = (Instance *)malloc( size * sizeof(Instance) ); + SYM_LIST.tail = SYM_LIST.head; + SYM_LIST.extent = SYM_LIST.head + LIST_EXTENT; + *SYM_LIST.head = strdup(name); + return *SYM_LIST.head; +} -#define TABLE_SIZE 100 -typedef const char* SymbolInstance; +Instance make_symbol(const char *name){ + if(!SYM_LIST.head) return make_list(name); -SymbolInstance symbol_table[TABLE_SIZE]; -int table_count = 0; + Instance *pt = SYM_LIST.head; + while(1){ + if( strcmp(*pt ,name) == 0 ) return *pt; -/* The Factory 'make' function */ -SymbolInstance make_symbol(const char* name) { - /* Search for an existing original */ - for (int i = 0; i < table_count; i++) { - if (strcmp(symbol_table[i], name) == 0) { - return symbol_table[i]; /* Return a copy of the instance */ - } + if(pt == SYM_LIST.extent){ + fprintf(stderr ,"symbol list overflow for %s\n" ,name); + return NULL; } - - /* Mint a new original if one does not exist */ - if (table_count < TABLE_SIZE) { - symbol_table[table_count] = strdup(name); - return symbol_table[table_count++]; + + if(pt == SYM_LIST.tail){ + *++SYM_LIST.tail = strdup(name); + return *SYM_LIST.tail; } - return NULL; /* Table capacity reached */ -} -/* Usage */ -SymbolInstance x = make_symbol("START"); -SymbolInstance y = make_symbol("START"); + pt++; + } +} -/* x == y evaluates to True based purely on the physical memory address, - bypassing the need for further string comparisons. */ +int main(){ + Instance a = make_symbol("a"); + Instance b = make_symbol("b"); + Instance c = make_symbol("c"); + Instance d = make_symbol("d"); + Instance e = make_symbol("e"); // overflows table + + Instance *pt = SYM_LIST.head; + Instance *pt_tail = SYM_LIST.tail; + while(1){ + puts(*pt); + if(pt == pt_tail) break; + pt++; + } + + if(e == NULL) printf("e is NULL\n"); +} +

The Turing Machine as an architecture

- In this interpretation of the Turing Machine, the architecture utilizes a single-ended tape, aligning with the foundational model presented by Hopcroft and Ullman . If a computation strictly requires a two-way infinite tape, the single-ended tape can simulate it by interleaving the addresses: assigning odd-addressed cells to represent the right-going half, and even-addressed cells to represent the left-going half. Structurally, this simulation requires taking two steps instead of one to advance in a given logical direction. When analyzing the time complexity of an algorithm, this structural overhead merely doubles the constant on the linear term, leaving the asymptotic order of complexity entirely unchanged. The outcomes of decider programs are unaffected. Therefore, utilizing a single-ended tape is an inconsequential variation of the two-way tape machine. + In this interpretation of the Turing Machine, the architecture utilizes a single-ended tape, as done in Hopcroft and Ullman's book . If a computation strictly requires a two-way infinite tape, the single-ended tape can simulate it by interleaving the addresses: assigning odd-addressed cells to represent the right-going half, and even-addressed cells to represent the left-going half. This simulation requires taking two steps instead of one to advance in a given logical direction. When analyzing the time complexity of an algorithm, this overhead merely doubles the constant on the linear term, leaving the asymptotic order of complexity entirely unchanged. The outcomes of decider programs are unaffected. Therefore, utilizing a single-ended tape is an inconsequential variation of the two-way tape machine.

- Furthermore, this definition adopts the language of hardware specification rather than formal mathematics. Because this is strictly a terminology change with direct structural correspondences between operations, the resulting model remains isomorphic to the Hopcroft and Ullman definition. Adopting this architectural perspective facilitates the overarching goal of building upward toward a physical computer architecture rather than strictly preparing for formal mathematical analysis, though it certainly does not preclude such analysis. In this model, the fixed components of the machine are conceptually hardwired, while the variable components represent memory or registers. As detailed in the control procedures below, data flows dynamically through the variable memory parts, while the fixed hardware components remain strictly read-only. + Furthermore, this definition adopts the language of hardware specification rather than formal mathematics. Because this is strictly a terminology change with direct correspondences between operations, the resulting model remains isomorphic to the Hopcroft and Ullman definition. Adopting this architectural perspective facilitates the overarching goal of building downward toward a computer architecture, rather than strictly preparing for highly abstract mathematical analysis, though it certainly does not preclude such analysis. In this model, the structural components are read-only, while the memory components will have data flowing through them. As detailed in the control procedures below, data flows dynamically at the command of the state controller.

@@ -297,70 +335,76 @@ SymbolInstance y = make_symbol("START"); -

The distinct empty-symbol can be any symbol that is excluded from the alphabet. Like the alphabet symbols, this empty-symbol can appear on the tape.

- -

Only instances of alphabet symbols or the empty-symbol are permitted to be written to the tape.

+

We will each highlighted terms as a short name the associated item.

-

Intuitively, a person might consider that the alphabet symbols are useful while the empty symbol is merely taking up space while waiting to be displaced, in the same manner that a person considers a bookshelf to be empty rather than being full of air. (And if a person puts a bookshelf underwater, is it still empty, or is it full of water?).

+

+ The distinct empty-symbol can be any symbol that is excluded from the alphabet. Only instances of alphabet symbols or the empty-symbol are permitted to be written to the tape. +

+

+ Intuitively, a person might consider that the alphabet symbols are useful while the empty symbol is merely taking up space while waiting to be displaced, in the same manner that a person considers a bookshelf to be empty rather than being full of air. (And if a person puts a bookshelf underwater, is it still empty, or is it full of water?). +

- Without reset being held during power up, a real machine can land in an illegal state that depending on the design might not be resetable, and could conceivably be damaging. Hence, reset is normally held during power up, and it is reset, not power up, that causes a machine to land in a known start state. This is a required component for a Turing Machine. + Depending on the design, without reset being held during power up, a real machine can land in an illegal state that might not be resetable, and could conceivably be damaging. Hence, reset is normally held during power up, and it is reset, not power up, that causes a machine to land in a known initial state.

+

- This design assumes that when reset is released, the then initialized machine starts running. This is fine for our purposes here, but for the delux model, we could contemplate a separate 'go' button and the associated logic. + This design assumes that when reset is released, the then initialized machine starts running. This is fine for our purposes, but surely the deluxe model would have a separate 'go' button and the associated logic.

- Note that we packaged a tape transport along with the head. In this volume we will talk about sending step commands to the head, but of course a head doesn't step, rather a tape transport mechanism steps. Hence, we when we talk about 'stepping the head' implied is that the head remains stationary, and the tape transport mechanism moves the tape. As the tape is normally very long and held on spools, even if we could move the head, that would not be very effective. + Note that we packaged a tape transport along with the head. In this volume we will talk about sending step commands to the head, but of course a head doesn't step, rather a tape transport mechanism steps. Hence, we when we talk about 'stepping the head' implied is that the head remains stationary, and the tape transport mechanism moves the tape. As the tape is normally very long and held on spools, even if we could move the head it would not be very effective.

- The constant procedure should not be conflated with the Turing Machine program. For a microcode controlled machine, the procedure will be found in microcode memory, and it will be execute as though a program. Each line of the procedure when read results in a set of bits connected to control lines. Some of those control lines will control what the procedure does, and some will extend out into the data path, give commands to execution units, and gate the flow of data. + The constant procedure should not be conflated with the Turing Machine program. For a microcode controlled machine, the procedure will be found in microcode memory, and it will be execute as though a program. Each line of the procedure, when read, results in a set of bits being connected to the machine's control lines. Some of those control lines will control what the procedure does, and some will extend out into the data path and be used to configure execution units and gate data on to busses.

- For a hardwired machine, the control program will be expressed with logic gates and flip-flops (single bit memory registers). Whether a machine is microcode controlled, or hardware controlled is a question of implementation. The architecture remains the same independent of implementation decisions, hence they are inconsequential to our architecture discussion. An implementation is the design given to the folks who actually build things. The result of what the design builds is called the realization. An realization is intended to function faithfully to the implementation so the realization is also inconsequential. And thus, the sole question remaining is the one of architecture. + For a hardwired machine, the control program will be expressed + with logic gates and flip-flops (single bit memory + registers). Whether a machine is microcode controlled, or + hardware controlled, is a question + of implementation. The values on the + control lines remain the same independent of those + implementation decisions, so those decisions + are inconsequential to our architecture + discussion.

The Turing Machine architecture specifies an infinite tape, which can neither be implemented, nor realized. Though we will successful address this issue in a later chapter.

-

A symbol can be any mathematical object for which there can be multiple instances, where within a given context, instances compare to be equal among other instances of the same symbol, but compare not equal to instances of other symbols. As a matter of convenience in this document, I use sequences of letters and/or digits for symbol instances.

- -

The Turing Machine tape cell

- A cell is the square from Alan Turing's 1936 paper . - A cell is a foundational mathematical object that has no meaning apart from its distinct identity and its capacity to hold specific structural properties. Due to its distinct identity, a cell can be referenced. + A cell is the square from Alan Turing's 1936 paper . A cell is a foundational mathematical object that has no meaning apart from its distinct identity and its capacity to hold specific properties. Due to its distinct identity, a cell can be referenced.

- A leftmost cell possesses exactly two compulsory properties: a right neighbor and data. A rightmost cell also possesses exactly two compulsory properties: a left neighbor and data. An interstitial cell possesses all three compulsory properties: a left neighbor, a right neighbor, and data. + A leftmost cell possesses exactly two compulsory properties: a right neighbor and data. A rightmost cell also possesses exactly two compulsory properties: a left neighbor and data. An interstitial cell possesses three compulsory properties: a left neighbor, a right neighbor, and data. While an island cell has a single compulsory property, that of data.

Said neighbor properties are singular. When the left neighbor property is present, there is exactly one left neighbor, and when the right neighbor property is present, there is exactly one right neighbor. Said data property is restricted to being either an instance of an alphabet symbol, or alternatively, an instance of the empty-symbol.

-

The Turing Machine tape

@@ -368,229 +412,248 @@ SymbolInstance y = make_symbol("START");

- Once a tape is defined, properties can not be added nor removed from the constituent cells. Further, the neighbor properties definitions are fixed. Cells don't move, new cells can not be added, and cells existing on the tape can not be removed. We can say that a Turing Machine tape has a constant, fixed, topology. + Once a tape is defined, properties cannot be added nor removed from the constituent cells. Further, the neighbor properties definitions are fixed. Cells don't move, new cells cannot be added, and cells existing on the tape cannot be removed. We can say that a Turing Machine tape has a constant, fixed, linear topology.

- Nor can the data property be removed; however, unlike neighbor properties, the data property is a variable. While a Turing Machine is operating, the data property can be set to different values. + Nor can the data property be removed; however, unlike neighbor properties, the data property value can be changed while the Turing Machine is running.

- Initially the Turing Machine tape is filled with empty symbols. A Turing Machine does not have the ability to fill an empty tape in a finite number of steps, so no Turing machine can compute and erase an entire tape. The initial tape must be made by other means, and at this point in our discussion we punt this issue, as all others have done thus far, and define that there is a supply of initially pristine tapes. Because empty tapes are made only by definition, the empty symbol is special. This is the reason that we defined the empty-symbol separately from the alphabet. As we will further discover later in this volume, the very concept of emptiness is special. + Initially the Turing Machine tape is filled with empty symbols. A Turing Machine does not have the ability to fill an empty tape in a finite number of steps, so no Turing machine can compute and erase an entire tape. The initial tape must be made by other means, and at this point in our discussion we punt this issue, as all others have done thus far, and define an initial tape to have empty symbols in all of its cells.

- There is no concept of 'in between' cells in the Turing Machine model. The head either points at one cell, or its neighbor. There is no half step. This is a feature of the tape, and this feature facilitates the view that the tape is an abstraction of an addressed computer memory. As there are no fractional addresses to a computer memory, there are in between address memory values. This is also theoretically important, as it ties back to the Peano Axioms and Peano arithmetic, which is often made use of in computation theoretic proofs. + The tape is intentionally defined in such a manner that there is no meaning to 'in between' two cells. The head of the machine is always on exactly one cell, with the option of stepping to neighbor cells. Taking a step is an atomic operation; there is no meaning to 'during the step'. Turing Machines are state machines controlled by a clock. A person only asks questions of them when the machine is in a defined state.

-

- It is because there is no 'in between', that the tape is a different object than a Path Graph, as a Path Graph has edge objects in between vertices, and those edges can carry properties. - It is possible to create a correspondence while carrying a this no properties constraint. I.e. that the cells in the tape correspond to vertices, that the neighbor properties correspond to edges, and, the adding the constraint that the edges are not allowed to have properties. Though again, that constraint causes the tape to a different object. However, this is not to say that a tape can not be used to hold the representation of a path graph. Doing so would require some additional overhead beyond that of an array of cells representing vertices. +

+ Mathematically, a Turing Machine tape can be expressed as a path graph. However, they imply different ontological contexts. The neighbor property of a Turing Machine tape cell specifically informs a clock-driven atomic step function where to place the machine head next. The machine only has defined meaning at the state points on the controller. In contrast, a path graph exists in the wider context of graph theory. A path graph has edges and each edge can be focused on, said to be traversed over, and given general properties. These are things we explicitly excluded in the tape definition. If we were to move the tape from the context of the machine and into the more abstract mathematical context by modeling the tape with a path graph, then we would do so for the purpose of analyzing the tape, which is a higher order and more abstract activity. However, in the current exercise we are not reaching towards the more abstract; rather, we are reaching in the other direction, towards machine architecture. This is one of the reasons that Alan Turing's use of a tape, rather than a path graph, so elegantly suggested that computation theory applied to real machines and was not merely limited to the Entscheidungsproblem.

-

The Turing Machine tape head

- The tape head is a set of four functions and a reference to exactly one of the tape cells. Namely, read, write, step-left, step-right. In addition the tape head can throw an error, left-of-leftmost if the Turing Machine attempts to step left of the leftmost cell. When stepping the cell reference in the head is changed based on the properties found in the currently referenced cell. The cell referenced by the head is called the cell the head is on, or more simply, the head cell. + The tape head consists of a reference to exactly one of the tape cells and a set of four functions: read, write, step-left, and step-right. In addition, the tape head can throw an error, left-of-leftmost, if the Turing Machine attempts to step left from the leftmost cell. When stepping, the cell reference in the head is updated based on the neighbor properties of the currently referenced cell. The cell referenced by the head is called the cell the head is on, or more simply, the head cell.

- We can say that the head indexes the cell, but his should not be confused with an index in the sense of indexing an array. This definition of the Turing Machine is built on fundamental principles and does not depend on the definition of Natural Numbers. We will discuss addresses, which are Natural Numbers, further on in this volume. -

- -

- We call a subset of contiguous cells an area. - A tape can be partitioned into multiple areas. -

- -

A tape that has no alphabet characters on it is said to be an empty tape. + A person can also say that the head indexes the head cell. This utilizes the classical mechanical definition, where an index is a mark for aligning gears. This physical meaning contrasts with an index integer used for addressing an array. The architectural definition of the Turing Machine developed here relies strictly upon the topological properties of the tape, independent of the definition of Natural Numbers. Addresses, which do rely on Natural Numbers, are discussed further on in this volume. This represents a minor divergence from Alan Turing's original paper, as he took it as a given that numbers naturally paired with the squares. We explicitly establish that pairing only after deriving Natural Numbers using the Turing Machine itself.

-

Some tape partitions

+

Area and partitions

-

Head partition

+

+ We call a subset of contiguous cells from a tape an area of said tape. A tape partition is a set of areas that completely span a tape. For any partition of a single-ended Turing Machine tape, at least one of the areas will necessarily be infinite. +

-
    -
  1. The left side: a potentially empty finite set containing all of the cells to the left of the cell the head is on.
  2. +

    Head partition

    -
  3. Head: the head cell
  4. +
      +
    1. The left side: a potentially empty finite set containing all of the cells to the left of the head cell.
    2. +
    3. Head: the head cell.
    4. +
    5. The right side: the infinite set extending from the right neighbor of the head cell.
    6. +
    -
  5. The right side: The infinite set extending from the right neighbor of the head cell.
  6. -
+

Leftmost/remaining partition

-

Leftmost/remaining partition

+
    +
  1. Leftmost: the leftmost cell.
  2. +
  3. Remaining: the infinite set including the right neighbor of the leftmost cell, and all cells further to the right.
  4. +
-
    -
  1. Leftmost: the leftmost cell
  2. -
  3. Remaining: the infinite set including the right neighbor of the leftmost cell, and all cells further to the right.
  4. -
+

Active area partition

-

Active area partition

+

+ A non-empty tape, one with at least one cell holding an alphabet symbol, can be partitioned into the following areas: +

-

A non-empty tape can be partitioned into the following areas: -

+
    +
  1. The left empty tail: this area is empty when the leftmost cell is not empty. Otherwise, it consists of the leftmost cell and the empty cells, if any, to the right of the leftmost cell, up to the first alphabet cell.
  2. -
      -
    1. The left empty tail: a potentially empty finite set containing all of the cells that have not been written thus far in the computation starting from the leftmost cell extending to the right up to, but not including the leftmost cell that has been written. (For a two way tape, this will be an infinite left going set.)
    2. +
    3. Active area: a finite area for computational problems, containing the cells extending from the leftmost alphabet cell up to and including the rightmost alphabet cell. It is possible that the leftmost alphabet cell and the rightmost alphabet cell will be the same cell.
    4. -
    5. Active area: A possibly empty finite subset containing the cells extending from the leftmost cell that has been written up to and including the rightmost cell that has been written
    6. +
    7. The right empty tail: The infinite set extending from the right neighbor of the rightmost cell of the active area, extending rightward.
    8. +
    -
  3. The right empty tail: The infinite set extending from the right neighbor of the rightmost cell the Turing machine has written thus far, extending rightward.
  4. -
+

The impossibility of recognizing an empty tape

-

- In general a Turing Machine can not step across a tape reading cells to find the right empty tail. Say this were attempted, an the machine discovered an empty cell, the Turing Machine could still not know if it continued stepping that it would discover another cell with an alphabet symbol written to it, or not. -

+

+ Recognition is a process where a Turing Machine decides if a pattern is present on a tape solely by reading symbols found on the tape. No meta-information, such as a message communicating something about the area being examined or the nature of the program that wrote the symbols, can be taken into account. +

- However, a Turing Machine which is aware that it started computing with an empty tape, could keep track of the address of the rightmost cell that it wrote, and thus know the rightmost cell of the active area. If a Turing Machine is started with a input tape, the problem becomes one of communicating control. + The active area partition of a tape only works for tapes that have at least one alphabet cell. As soon as a machine does its first write of an alphabet symbol, it is known the tape has at least one alphabet symbol. However, what if a tape of unknown status, whether completely empty or containing an alphabet cell, is mounted on a tape machine, and it is desired that the machine recognize if the tape is empty or has an alphabet cell? This is the equivalent problem of looking for the leftmost cell of an active area.

-

- By definition, a computation must finish in a finite number of steps. Hence the activate area when a Turing Machine halts will always be finite. Consequently, if a Turing Machine initially starts working with a tape that was computed by another Turing Machine, the length of the input will be finite. Still that input will be in the active area, so the receiving Turing Machine will likely need to be able read data control data that encodes the location of the end of the active area. -

+

+ Recognizing that a tape is empty is not possible. Suppose it were attempted, and a machine started scanning the tape rightward from the leftmost cell; for every cell that was empty, the machine would have to scan further rightward to check for an alphabet cell. If the tape is truly empty, the recognizer would never stop scanning, so no decision would be rendered. +

-

If an input tape is provided as a general mathematical object, either decreed by definition, or perhaps abstracted from 'what a Turing Machine computation would produce if it ran to an infinite limit number of steps', then the input can be either finite or infinite. -

+

The impossibility of recognizing the rightmost cell of the active area

+

+ In general, a Turing Machine cannot step across a tape reading cells to recognize the rightmost cell of the active area, or equivalently, the leftmost cell of the right empty tail. Suppose a recognizer attempted this by starting in the active area and stepping right, and the machine discovered an empty cell. The machine would not be able to distinguish between the case of said empty cell being embedded within the active area (meaning more alphabet cells lie further to the right), or the case where said cell is genuinely the leftmost cell of the right tail. To resolve the ambiguity, the machine would be obligated to continue stepping right. Yet, there would never come a time where finding another empty cell would not lead back to the exact same case ambiguity, so the machine would forever step right without returning a decision. +

-

The controlling state machine

+

+ It follows that if knowledge of the end of the active area is needed, this information must be encoded as a message. For example, a special symbol can be reserved in the alphabet specifically to serve as the end of active area marker. Each time a machine steps beyond the current end of active area marker and does a write, it writes the marker in the right neighbor cell, and goes back and erases the old mark. This method is related to communications theory and the science of signaling. Here, the active area marker is an out-of-band control signal. +

-

That controlling state machine can be either a Mealy or Moore style state machine graph, as these are equally expressive. In this volume we describe a Moore style machine and corresponding procedure here. +

+ If a tape is written by an initializing tape machine, unmounted, and then mounted on a second analyzing tape machine, the analyzing tape machine is not starting with an empty tape. Similarly, a mathematician can, by decree, define an initial tape that is not empty. In these cases, the analyzing machine cannot use the signaling method described in the prior paragraph, as it was not in control of all the writes of alphabet symbols to the tape. The only solution to this problem is for the initializing machine and the analyzing machine to use a shared communication protocol for signaling the end of the active area.

-

The state machine graph is a set containing three elements:

- +

+ By definition, a computation must finish in a finite number of steps. It follows that the active area when a Turing Machine halts a computation will always be finite. Consequently, if a Turing Machine initially starts working with a tape that was computed by another Turing Machine, the length of the input will be finite. Still, that input will be in the active area, so the receiving Turing Machine will need to read control data left on the tape under a common communication protocol to be able to find the bounds of the input area. +

- A state is a symbol. Instances of state symbols appear in a different context than those of alphabet symbols or the empty-symbol, and thus they do not need to be distinct from them. + When an input tape is provided as a general mathematical object, either decreed by definition or perhaps abstracted from 'what a Turing Machine computation would produce in the limit of step count', then the input can be either finite or infinite.

+

In-band and out-of-band control

+

- Each state has a command attached to it, <state, command>. Each state appears in exactly one such pairing. + In-band control occurs when control signals or structural metadata are mixed directly into the same channel and alphabet as the data payload. In-band signaling leads to ambiguities between what is control and what is data. As we saw, there are cases a recognizer, i.e. merely examining the data, is not capable of resolving even the simplest of control questions. A conventional approach for resolving these ambiguities makes use of escape sequence schemes that grow in length as the levels of communication grow. This has always been an after thought, a sort of hack.

- We have a fixed set of commands: { do-nothing, step-left, step-right, and write(value) }, where the value parameter is set when the controller is defined. + In contrast, out-of-band control communicates structural information through a strictly separate channel or by utilizing symbols definitively excluded from the programmer-visible data alphabet. The rightmost tape marker is an out-of-band mechanism because it utilizes an expanded hardware tape alphabet strictly reserved for machine management, guaranteeing it can never be conflated with the user's data. Modern architectures often do not have the luxury of inventing new symbols to serve as control rather than data. Another out-of-band signaling technique is to structure the data into channels; such structure is called formatting. We find formatting on hard drives, in frame-based and packet-based communication channels, and in data structures.

-

Data must be an instance of an alphabet symbol or an instance of the empty-symbol.

-

In addition, we should not forget the implied read command that returns a value from the tape, and is used by the fixed procedure.

+

The controlling state machine

+ +

The controlling state machine can be either a Mealy or Moore style state machine graph, as these are equally expressive. In this volume we describe a Moore style machine and corresponding procedure here. +

+ +

The state machine graph is a set containing three elements:

+ -

The arcs are triples of symbols, <from-state, to-state, value>.

+

+ A state is a symbol. Instances of state symbols appear in a different context than those of alphabet symbols or the empty-symbol, and thus they do not need to be distinct from them. +

-

The from-states, to-states, and values are set when the controller is defined.

+

+ Each state has a command attached to it, <state, command>. Each state appears in exactly one such pairing. +

-

The value is an instance of either an alphabet symbol or the empty-symbol.

+

+ We have a fixed set of commands: { do-nothing, step-left, step-right, and write(value) }, where the value parameter is set when the controller is defined. +

- - We require that for each from-state that there exists exactly one arc for each member of the alphabet, one for the empty-symbol, and for states with a step-left command, that there be one arc for the left from leftmost error. - +

Data must be an instance of an alphabet symbol or an instance of the empty-symbol.

-

Arcs can be dropped from diagrams if we can prove that they cannot be used.

+

In addition, we should not forget the implied read command that returns a value from the tape at the start of each step, and buffers it for use by the fixed procedure.

-

As a notational convenience we might also reduce the work of listing so many arcs by adopting the convention of explicitly providing only unique arcs, and then saying the rest of the arcs are identical to a default arc or an error arc.

+

The arcs are triples of symbols, <from-state, to-state, value>.

-

Here we present the fixed procedure in the form of a main procedure and two subprocedures, 'Initialize', and 'Take a Step'. To perform a computation follow the steps in Main, and its subprocedures, until being told to halt:

+

The from-states, to-states, and values are set when the controller is defined.

- - Deterministic (Uniplex) Procedure - - Initialize: - 1. place the input on the tape - 2. place the head on the leftmost element - 3. set the current state to the start state. - - Take a Step: - 1. read the symbol instance indicated by the head - 2. execute the command corresponding to the current state - 3. select the arc that has a from-state that matches the current-state, and a value that matches the instance just read. Take that arc's next state and make it the machine's next state. - 4. make the next state the current state. - - Main: - 1. Initialize - 2. if the current-state is the halt state, then halt - 3. Take a Step - 4. go to 2. - +

The value is an instance of either an alphabet symbol or the empty-symbol.

-

We initialize the machine by instantiating the input on the tape, putting the head on the leftmost element of the tape, and setting the current state to the start state.

+ + We require that for each from-state that there exists exactly one arc for each member of the alphabet, one for the empty-symbol, and for states with a step-left command, that there be one arc for the left from leftmost error. + -

We take a step by first reading the symbol under the head and storing that value in our read value buffer, executing the command associated with the state, and then following the arc selected by the element we read.

+

Arcs can be dropped from diagrams if we can prove that they cannot be used.

-

We must read the element before executing the command, because the command might perform a write to the cell.

+

As a notational convenience we might also reduce the work of listing so many arcs by adopting the convention of explicitly providing only unique arcs, and then saying the rest of the arcs are identical to a default arc or an error arc.

-

Consequently, as part of the Turing Machine definition we picked up the buffer for holding the read value.

+

Here we present the fixed procedure in the form of a main procedure and two subprocedures, 'Initialize', and 'Take a Step'. To perform a computation follow the steps in Main, and its subprocedures, until being told to halt:

-

Walking through this procedure is variously known as running the machine, performing a computation, evaluating the input, evaluating the function, or simply as computing.

+

Deterministic (Uniplex) Procedure

-

Note that while walking through this procedure we are always in exactly one state. This is because we required that there be one arc for each letter in the alphabet, empty-symbol, and possibly the left from leftmost error. We say that this property means that the machine is deterministic.

+

Initialize:

+
    +
  1. mount the tape
  2. +
  3. place the head on the leftmost cell
  4. +
  5. set the current-state to the initial-state
  6. +
  7. set the state controller stepping counter to 0
  8. +
-

To create a non-deterministic machine we allow multiple arcs to have the same read value as a second member, and we modify the second step of the procedure to follow all arcs that have matches with the symbol returned by read.

+

Take a Step:

+
    +
  1. read the symbol instance indicated by the head into the read data buffer
  2. +
  3. execute the command corresponding to the current-state
  4. +
  5. select the arc that has a from-state matching the current-state, and a value matching the instance in the read buffer. Take that arc's next-state and make it the machine's next-state.
  6. +
  7. make the next-state the current-state
  8. +
  9. increment the step counter
  10. +
-

When we do this we might find that zero, one, or many of the arcs are followed in one step, and thus that we have a probability to have zero or more next states.

+

Main:

+
    +
  1. Initialize
  2. +
  3. if the current-state is the halt-state, then halt
  4. +
  5. wait for the clock to synchronize, then Take a Step
  6. +
  7. go to 2
  8. +
-

Conceptually each of these states corresponds to a separate machine head with its own read buffer.

+

We initialize the machine by instantiating the input on the tape, putting the head on the leftmost cell of the tape, setting the current state to the initial-state, and zeroing the step counter.

-

At the end of the step we rename our next state set to be the current state set.

+

We take a step by first reading the symbol under the head and storing that value in our read data buffer, executing the command associated with the state, and then following the arc selected by the element we buffered.

-

Should the halt state ever be placed in the current state set, then we halt the machine.

+

We must read the element into the buffer before executing the command because the command might perform a write to the cell. If a machine were to write a new symbol to the tape before the transition arc was evaluated, the original symbol would be destroyed, and the controller would lose the information required to determine its next state. The read data buffer physically isolates the state controller from this write-overwrite hazard.

-

Should the current state set become empty without every having reached a halt state, we say the machine has failed.

+

Consequently, as part of the Turing Machine definition, we required the buffer for holding the read value.

- - Non-Deterministic (Multiplex) Procedure - - Initialize: - place the input on the tape - for each start state place a <start state, head location on leftmost> pair in the current state set - - Take a Step: - For each <state, head-location> member of the current state set: - read the symbol instance from the corresponding head location - execute the command corresponding to the state - for each arc match, add a <next-state, head-location> pair into the next state set - - Main: - Initialize - if the halt-state is a member of the current-state set, then halt, if current state set is empty, then halt with an error - Take a Step - go to 2 - +

Walking through this procedure is variously known as running the machine, performing a computation, evaluating the input, evaluating the function, or simply as computing.

-

As reviewed by Papadimitriou , such non-deterministic machines can be converted to deterministic ones. This is done by calling each unique 'state set' a state.

+

Note that while walking through this procedure we are always in exactly one state. This is because we required that there be one arc for each letter in the alphabet, empty-symbol, and possibly the left from leftmost error. We say that this property means that the machine is deterministic.

-

Thomas might recall from our definition of symbol, that we can use any mathematical object for which instances are comparable.

+

To make a non-deterministic machine we allow multiple arcs to have the same read value as a second member, and we modify the second step of the procedure to follow all arcs that have matches with the symbol returned by the buffer.

-

That includes sets. When two current state sets have the same members, we say they are instances of the same state. When they have different members we say they are different states.

+

When we do this we might find that zero, one, or many of the arcs are followed in one step, and thus that we have a probability to have zero or more next states.

-

Hence existence proofs on non-deterministic machines will turn out the same as for deterministic ones, but the non-deterministic machines might require fewer steps to evaluate.

+

Conceptually each of these states corresponds to a separate machine head with its own read buffer.

-

If we keep a trace of execution through a non-deterministic machine, and then walk backwards from each halt state, we find paths through the state machine, that, had we taken one of these paths, the machine would have reached the halt state.

+

At the end of the step we rename our next state set to be the current state set.

-

Had we known such a path in advance we could have saved ourselves from doing the work of following the other paths.

+

Should the halt-state ever be placed in the current state set, then we halt the machine.

-

This explains why such machines are called 'non-deterministic' - we don't know which of the paths we are following while running forward will be the path that leads to the halt state first.

+

Should the current state set become empty without ever having reached a halt-state, we say the machine has failed.

-

We might arbitrarily pick a path, then we would have some probability of eventually hitting the halt state.

+

Non-Deterministic (Multiplex) Procedure

-

But notice, that the conversion algorithm going from a non-deterministic machine to a deterministic machine is forward moving. It starts by giving the initial state set a state name, and moves forward by giving each unique set of states a state name, until hitting the halt state.

+

Initialize:

+
    +
  1. mount the tape
  2. +
  3. for each initial-state, place an <initial-state, head location on leftmost> pair into the current state set
  4. +
  5. set the step counter to 0
  6. +
-

No stochastic variables, or “guesses” are involved. Note also, when we run a non-deterministic machine we do so in a deterministic manner. There are no stochastic variables involved.

+

Take a Step:

+
    +
  1. clear the next state set
  2. +
  3. For each <state, head-location> member of the current state set: +
      +
    1. read the symbol instance from the corresponding head-location into the read data buffer
    2. +
    3. execute the command corresponding to the state (updating the head-location or tape)
    4. +
    5. for each arc matching the state and the buffered symbol, add a <next-state, updated head-location> pair into the next state set
    6. +
    +
  4. +
  5. rename the next state set to be the current state set
  6. +
  7. increment the step counter
  8. +
-

Hence, non-deterministic represents an interpretation rather than the machine definition or anything we are asked to do while walking through the fixed procedure.

+

Main:

+
    +
  1. Initialize
  2. +
  3. if the halt-state is a member of the current state set, then halt. If the current state set is empty, then halt with an error.
  4. +
  5. wait for the clock to synchronize, then Take a Step
  6. +
  7. go to 2
  8. +
-

So as to avoid any confusion due to this nuance, I am going to introduce a different term for non-deterministic machines. I am going to say they are multiplexed.

+

As reviewed by Papadimitriou , such non-deterministic machines can be converted to deterministic ones. This is done by calling each unique 'state set' a state.

-

Should the need arise to emphasize that a machine is excluded from multiplexing, I will say such a machine is uniplex.

+

A person might recall from the definition of a symbol, that any mathematical object for which instances are comparable can be used.

-

This new nomenclature is especially helpful when discussing the TM Library code, where the multiplexing of heads is readily apparent.

+

That includes sets. When two current state sets have the same members, we say they are instances of the same state. When they have different members we say they are different states.


@@ -638,7 +701,7 @@ SymbolInstance y = make_symbol("START");

The controller then steps the main tape head right one element, and it runs the increment routine on the address tape. The address tape then reads ‘s’, i.e. one. This is the address for the right neighbor of the leftmost element.

-

We then repeat this procedure while assigning addresses to each successive element, two, three, four, etc. We call the set of addresses created in this manner the ‘Natural Numbers’.

+

We then repeat this procedure while assigning addresses to each successive element, two, three, four, etc. We call the set of addresses made in this manner the ‘Natural Numbers’.

Though we can never run this machine to the point where it halts, we may analyze the Natural Number machine and reason about it.

@@ -764,7 +827,7 @@ SymbolInstance y = make_symbol("START"); a, b , Г, ε, ε, ε … -

It would appear that the answer to our question is that address 2 is locating different things at different times. First it was, c, then γ, then Г. Yet the address did not change. It feels a little unsatisfactory to suggest that our concept of location depends on the value addressed. Also, notice, that when we created the Natural Number Turing Machine, that the values on the tape that was placed into correspondence with the Natural Numbers were never mentioned. Yet, we can't seem to answer the question of 'what is being addressed' without giving a value.

+

It would appear that the answer to our question is that address 2 is locating different things at different times. First it was, c, then γ, then Г. Yet the address did not change. It feels a little unsatisfactory to suggest that our concept of location depends on the value addressed. Also, notice, that when we made the Natural Number Turing Machine, that the values on the tape that was placed into correspondence with the Natural Numbers were never mentioned. Yet, we can't seem to answer the question of 'what is being addressed' without giving a value.

Addresses speak to the structure of the tape rather than the values held on the tape. So as to facilitate this interpretation, we note that a sequence consists of a sequence of cells holding elements, rather than being simply a sequence of elements. Given the concept of a cell we can say that an address always locates the same cell, though the contents of that cell can change.

@@ -782,7 +845,7 @@ SymbolInstance y = make_symbol("START");

In a sense what we are doing while exploring the meaning of area, existence, and zero length with these delete and append examples is performing a discrete limit in analogy to a limiting operation in calculous. To support having such a limit operation, the location of an area is that of the left neighbor of the leftmost cell in the area.

-

Not all is satisfactory. When using the left neighbor of an area as the location for an area, we cannot locate an area that starts on the leftmost cell of the tape. If we make this a special case, then we have failed to create a first order definition for area, because the special case information will have to be stored in a higher level structure that describes attributes of the tape.

+

Not all is satisfactory. When using the left neighbor of an area as the location for an area, we cannot locate an area that starts on the leftmost cell of the tape. If we make this a special case, then we have failed to make a first order definition for area, because the special case information will have to be stored in a higher level structure that describes attributes of the tape.

Nor can this use the left cell approach work in the case of multiple areas.

@@ -830,7 +893,7 @@ SymbolInstance y = make_symbol("START");

Multiple machines and sharing tapes

-

Suppose we unmount a tape from a halted Turing Machine, say machine T0, and then mount the tape on another Turing Machine as input, say machine T1. Suppose we do this so that machine T1 may calculate the length of the output created by the first machine. When we do this, we run into some problems.

+

Suppose we unmount a tape from a halted Turing Machine, say machine T0, and then mount the tape on another Turing Machine as input, say machine T1. Suppose we do this so that machine T1 may calculate the length of the output made by the first machine. When we do this, we run into some problems.

Firstly, for a conventional Turing Machine, the tape that is mounted on T1 will be infinite, so no computational T1 machine will be able to process it unless there is a message on the tape telling T1 where the end of the input is. For our TTCA machines, if T0 starts with a null tape, and then expands it, and T0 is computational, then at the time T0 halts, the tape will be finite. T1 can then use the continuation of stepping beyond rightmost to know that it has processed all of its input.

@@ -850,11 +913,11 @@ SymbolInstance y = make_symbol("START");

A compact area is one that has only alphabet symbols (no empty-symbols). We can extend this concept to say that the density of an area is the ratio of alphabet symbols to empty-symbols.

-

The approach we use in modern computing is often the 3nd one listed above, that of the type system. We carefully account for the length of each instance of data. Then we build up each larger instance from smaller ones, and while doing so, we add the lengths of the smaller instances to calculate the length of the larger instance. All programs then specify when they create or compose instances and their types.

+

The approach we use in modern computing is often the 3nd one listed above, that of the type system. We carefully account for the length of each instance of data. Then we build up each larger instance from smaller ones, and while doing so, we add the lengths of the smaller instances to calculate the length of the larger instance. All programs then specify when they make or compose instances and their types.

A system for creating the appearance of many tapes over a single tape is called a memory manager or a memory allocation system. It is typically better to use one of these and multiple tape models rather than solving the problem of moving objects around in memory in an ad hoc manner.

-

Here is an important question for the TTCA model: is it possible to create a memory manager that creates the appearance of multiple expanding tapes over the top of a single expandable tape? This problem is solved for managing files on a hard disk. However, all current file systems break at some point when pumped. So the question being asked here is equivalent to asking if a files system can be made without such architectural limits. The answer to this is yes, it is possible, as we will see in a later chapter of this book.

+

Here is an important question for the TTCA model: is it possible to define a memory manager that creates the appearance of multiple expanding tapes over the top of a single expandable tape? This problem is solved for managing files on a hard disk. However, all current file systems break at some point when pumped. So the question being asked here is equivalent to asking if a files system can be made without such architectural limits. The answer to this is yes, it is possible, as we will see in a later chapter of this book.

Hence there are multiple conventions we may use for implementing the abstraction of multiple tapes on a tape machine. Multiple tape machine are equivalent in power to one tape machines, but sometimes they are easier to think about.

@@ -870,7 +933,7 @@ SymbolInstance y = make_symbol("START");

For a given Turing Machine, the input is the sole determiner of the output. I.e. each time the same input is given, we get the same output. The input and output are mathematical objects, hence Turing Machines are functions. However, it is common in computer science to speak of Turing Machines as 'solving problems' rather than saying they are functions. This is because we often think of the inputs and outputs of Turing Machines as being something other than mathematical objects. For example, when a Turing Machine sorts sequences found on its input, we might say that it solves a sorting problem.

-

Turing Machines will differ due to differing alphabets, state controller graphs, associated commands, start, and halt states. The choice of empty-symbol is inconsequential as long as it is distinct from the alphabet. As we will see in the later discussion on variations, the choice of alphabet is not very important. For two alphabets of the same cardinality we can create a one to one mapping, and for those of differing cardinalities we can use sequences of alphabet symbols that map to alphabet symbols. For example, given an alphabet of ‘T’ and ‘F’, and a second alphabet of ’t’, ‘f’, ‘x’, ‘z’ we may make the following map:

+

Turing Machines will differ due to differing alphabets, state controller graphs, associated commands, start, and halt states. The choice of empty-symbol is inconsequential as long as it is distinct from the alphabet. As we will see in the later discussion on variations, the choice of alphabet is not very important. For two alphabets of the same cardinality we can setup a one to one mapping, and for those of differing cardinalities we can use sequences of alphabet symbols that map to alphabet symbols. For example, given an alphabet of ‘T’ and ‘F’, and a second alphabet of ’t’, ‘f’, ‘x’, ‘z’ we may make the following map:

f @@ -984,13 +1047,13 @@ SymbolInstance y = make_symbol("START");

Now consider the case where we do not fix the length of the input, nor the number of steps allowed, and that space complexity is such that space usage grows with growing input length, at least for very long inputs. For such machines we can always find an input of sufficient length to trip the right from rightmost error.

-

As another approach to finite computing we can run computations twice. For a given input we first run the Turing Machine variation that does not step out of active area but still has an infinite tape. We watch this machine closely while it is running and find the bound on the active area. Now we can create a second machine that has a fixed length tape at least as long as our active area measurement but is otherwise the same. Now with this second machine we can run the same input and there will be no right of rightmost error, and thus there will be no difference between having the finite tape or an infinite one.

+

As another approach to finite computing we can run computations twice. For a given input we first run the Turing Machine variation that does not step out of active area but still has an infinite tape. We watch this machine closely while it is running and find the bound on the active area. Now we can make a second machine that has a fixed length tape at least as long as our active area measurement but is otherwise the same. Now with this second machine we can run the same input and there will be no right of rightmost error, and thus there will be no difference between having the finite tape or an infinite one.

Unlike for the constant space complexity proposal, and the bounded input length proposal, which only work for small subsets of potential inputs, this 'run twice' proposal derives a finite machine that works for any given input which a Turing Machine works for. Though, unfortunately, in all cases the second run will be moot, as we could have simply taken the output from the first run.

In a variation on the run it twice approach, instead of running the first machine, we might instead analyze it and should we be able to surmise a maximum tape length, we could use that.

-

In yet another approach we can extend the finite tape as needed. We create a control layer over the finite tape. When a step right command from the Turing controller invokes the right from rightmost error, the lower layer allocates memory, lengthens the tape, and then performs the requested step right. As long as this occurs in fixed time, (or of sufficient lesser order time than the dominate order of the time complexity), and as long as there is indeed more memory to allocate - this Turing Machine variation will yield the same order of computational complexity as one with an an infinite tape.

+

In yet another approach we can extend the finite tape as needed. We place a control layer over the finite tape. When a step right command from the Turing controller invokes the right from rightmost error, the lower layer allocates memory, lengthens the tape, and then performs the requested step right. As long as this occurs in fixed time, (or of sufficient lesser order time than the dominate order of the time complexity), and as long as there is indeed more memory to allocate - this Turing Machine variation will yield the same order of computational complexity as one with an an infinite tape.

I propose the following Turing Machine variation:

@@ -1056,7 +1119,7 @@ SymbolInstance y = make_symbol("START"); h◨ head is at rightmost examples -s ; step left - a◧ ; creates a new leftmost cell + a◧ ; make a new leftmost cell a◨ ; append to rightmost sn ; step n times to derive a longer command, combine them: @@ -1066,7 +1129,7 @@ SymbolInstance y = make_symbol("START");

The left direction is specified with a minus sign, otherwise the direction is taken as right going. So the letter s is the step-right command, and -s is the step-left command. The command s3 steps right three times.

-

The command a appends and writes a new cell to the right of the head. We use two special characters from the UTF character set to signify the rightmost and leftmost of the tape. This one looks like a little tape with its left cell inked in, ◧, so we use it to stand for leftmost. We use this one, ◨, to mean rightmost. Hence a◨ creates a new rightmost cell, and a◧ creates a new leftmost cell.

+

The command a appends and writes a new cell to the right of the head. We use two special characters from the UTF character set to signify the rightmost and leftmost of the tape. This one looks like a little tape with its left cell inked in, ◧, so we use it to stand for leftmost. We use this one, ◨, to mean rightmost. Hence a◨ makes a new rightmost cell, and a◧ makes a new leftmost cell.

In some cases it is possible to implement higher performance implementations for commands when the programmer tells us some additional information. For example a◨&h◨ has identical functionality as a◨, while the programmer also guarantees that we are on the rightmost cell. This saves the function from having to scan to the end of the tape.

@@ -1076,11 +1139,11 @@ SymbolInstance y = make_symbol("START");

The command esr is a compound command referring to sequentially applying three other commands. The e says to make an entangled copy of the head. The s says to step this copy, and the r says to do the read. The analogous esw does a write as the last step. This sort of combination of letters to make more complex commands was inspired by Lisp's car and cdr compositions. Though this is functionally what the command does, its actual implementation might be completely different.

-

The combination of multiplexing and cell deletion creates the hazard where one thread can delete a cell the head is on in another thread. We add a collision error continuation to our multiplexed Turing Machine interface because of this situation.

+

The combination of multiplexing and cell deletion leads to a hazard where one thread can delete a cell the head is on in another thread. We add a collision error continuation to our multiplexed Turing Machine interface because of this situation.

Chapter conclusion

-

The modifications made to the Turing Machine to create our TTCA machine were inconsequential, in that for order of complexity and existence proofs we may swap one machine for the other and the results will be the same.

+

The modifications to the Turing Machine leading to our TTCA machine were inconsequential, in that for order of complexity and existence proofs we may swap one machine for the other and the results will be the same.

The original Turing Machine had an infinite tape. In contrast the TTCA machine has a surprising property: for computational problems all of its components remain finite. This follows from the fact that during computation a machine makes a finite number of steps, so the tape can only be expanded to be a finite size.

diff --git a/document/example_list_symbol.c b/document/example_list_symbol.c new file mode 100644 index 0000000..8acbd04 --- /dev/null +++ b/document/example_list_symbol.c @@ -0,0 +1,83 @@ +#include +#include +#include + +// maximum legal index into the symbol list +#define LIST_EXTENT 3 + +typedef const char *Instance; +typedef struct{ + Instance *head; + Instance *tail; + Instance *extent; +} List; + +static List SYM_LIST = {NULL ,NULL ,NULL}; + +Instance make_list(const char *name){ + size_t size = LIST_EXTENT + 1; + SYM_LIST.head = (Instance *)malloc( size * sizeof(Instance) ); + SYM_LIST.tail = SYM_LIST.head; + SYM_LIST.extent = SYM_LIST.head + LIST_EXTENT; + *SYM_LIST.head = strdup(name); + return *SYM_LIST.head; +} + +Instance make_symbol(const char *name){ + if(!SYM_LIST.head) return make_list(name); + + Instance *pt = SYM_LIST.head; + while(1){ + if( strcmp(*pt ,name) == 0 ) return *pt; + + if(pt == SYM_LIST.extent){ + fprintf(stderr ,"symbol list overflow for %s\n" ,name); + return NULL; + } + + if(pt == SYM_LIST.tail){ + *++SYM_LIST.tail = strdup(name); + return *SYM_LIST.tail; + } + + pt++; + } +} + +int main(){ + Instance a = make_symbol("a"); + Instance b = make_symbol("b"); + Instance c = make_symbol("c"); + Instance d = make_symbol("d"); + Instance e = make_symbol("e"); // overflows table + + Instance *pt = SYM_LIST.head; + Instance *pt_tail = SYM_LIST.tail; + while(1){ + puts(*pt); + if(pt == pt_tail) break; + pt++; + } + + if(e == NULL) printf("e is NULL\n"); +} + +/* +2026-06-06 03:01:19 Z [TM-2026:developer] Thomas_developer@StanleyPark +§/home/Thomas/subu_data/developer/project/TM-2026/document§ +> gcc -g example_list_symbol.c + +2026-06-06 03:01:21 Z [TM-2026:developer] Thomas_developer@StanleyPark +§/home/Thomas/subu_data/developer/project/TM-2026/document§ +> ./a.out +symbol list overflow for e +a +b +c +d +e is NULL + +2026-06-06 03:01:23 Z [TM-2026:developer] Thomas_developer@StanleyPark +§/home/Thomas/subu_data/developer/project/TM-2026/document§ +> +*/