From: Thomas Walker Lynch Date: Thu, 23 Jul 2026 05:26:13 +0000 (+0000) Subject: . X-Git-Url: https://git.reasoningtechnology.com/%27%20%20%20window.RT.dirpr_library%20%20%20%27/Hindu-Arabic%20number%20fig%204.png?a=commitdiff_plain;h=547d880fc33db9d51f17569baa18c9a319fd9148;p=TM-2026 . --- diff --git a/document/book/TM-2026.html b/document/book/TM-2026.html index 4da6c6f..578281a 100644 --- a/document/book/TM-2026.html +++ b/document/book/TM-2026.html @@ -337,7 +337,6 @@ then we can say without qualification that T is computation theoretic inconsequential. Though still implied are the sets of machines and tapes.

- The computation theoretic Turing Machine

The Hopcroft and Ullman Turing Machine

@@ -374,7 +373,7 @@

State transitions are gated by the read value from the tape. Each state transition function includes actions to be taken; hence, their programmable controller is a Mealy style state machine. The step action is mandatory, though it can be in either direction. The write action must be specified, but the write could be the same symbol that is read, making it effectively an optional action.

-

This machine makes use of a single ended tape. If a computation specifies a two way infinite tape, it can be emulated 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 emulation requires taking two steps instead of one to advance in a given logical direction. When analyzing the time complexity of an algorithm, this overhead 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 a computation theory inconsequential variation of the two way tape machine. +

This machine makes use of a single ended tape. If a computation specifies a two way infinite tape, it can be emulated 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 emulation requires taking two steps instead of one to advance in a given logical direction. When analyzing the time complexity of an algorithm, this overhead 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 a computation theoretic inconsequential variation of the two way tape machine.

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 δ(q, X_i) = (p, Y, L); i.e., the next move is leftward. Then, @@ -655,7 +654,7 @@

For clarity of presentation, the definition will be partitioned according to separation of concerns. The first section defines the fixed parts of the Turing Machine definition. The second section defines the memory elements (variables). The third section describes the programmable components, which vary between specific Turing Machines depending on their purposes.

-

There is a mechanical procedure for converting a Moore Machine into a Mealy Machine, and the reverse. Two such converted machines are equally expressive. Making the read operation an explicit action, instead of having it implied by a state transition, increases the number of states in a controller, and consequently the number of steps that must be taken. However, the new machine can do in two steps anything the former machine could do in one; consequently, this change affects the multiplier constant on the linear term of the step count formula but does not change the computation complexity class determined from such a step count. The layers of next-state functions can be collapsed into one layer, where the missing arguments are filled in with all possible unused values. This potentially increases the number of state transition arcs that must be specified, but the state transition logic and the number of states remain unchanged. Partitioning the machine definition by separation of concerns does not change the total specification. Hence, these modifications are computationally inconsequential.

+

There is a mechanical procedure for converting a Moore Machine into a Mealy Machine, and the reverse. Two such converted machines are equally expressive. Making the read operation an explicit action, instead of having it implied by a state transition, increases the number of states in a controller, and consequently the number of steps that must be taken. However, the new machine can do in two steps anything the former machine could do in one; consequently, this change affects the multiplier constant on the linear term of the step count formula but does not change the computation complexity class determined from such a step count. The layers of next-state functions can be collapsed into one layer, where the missing arguments are filled in with all possible unused values. This potentially increases the number of state transition arcs that must be specified, but the state transition logic and the number of states remain unchanged. Partitioning the machine definition by separation of concerns does not change the total specification. Hence, these modifications are computation theoretic inconsequential.

The TTCA Machine fixed part

@@ -1222,275 +1221,29 @@

Adding heads is not a general method for improving performance complexity. A quadratic performance improvement does not always occur and when it does it is not strong enough to change the asymptotic performance if there are higher-order terms in a step count polynomial. Furthermore, eliminating shuttling will never reduce a linear step count to a constant time step count; the simple reason is that n is unbounded, while adding k heads can only divide the work by a fixed constant k. Consequently, while the transformation is consequential in specific cases, it cannot change the broader time complexity class.

- The Turing Machine architecture/organization +The TTCA Machine design
Figure 1: A Turing Machine
Figure 1 A Turing Machine
+

The prior chapter on the computation theoretic TTCA machine serves as the architectural template. The controller is practical to implement, and it is specified in terms of tables. In order to extend the tape, the machine will stop and ask the operator to mount a new reel. As this is a constant time operation, it is computation theoretic inconsequential.

-

Symbol in mathematics

- -

- A symbol is a distinct mathematical object capable of being instantiated. Within a given context, any instance of a specific symbol evaluates as equal to any other instance of that identical symbol, and evaluates as not equal to any instance of a different symbol. -

- -

- Put more formally, given a set of instantiable objects and a collection of instances made from them, for these objects to be symbols, two 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. -

- -

Symbol in computing

- -

- 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. -

- -

- A symbol instance newly minted by the factory is said to come direct from the factory. A symbol instance direct from the factory is also called an original. -

- -

Required properties of symbol factories

- -

- Any two symbol instances returned directly from two distinct factories will always evaluate to False during an equality comparison. In other words, two distinct originals will always be not equal. -

- -

- Given an original, all copies stemming from it will be equal to each other and to the original. By stemming from, this definition includes all direct copies and copies of copies. -

- -

- Given any two originals, say A and B, it is established that A is not equal to B, as discussed above. Note also that A is not equal to any copy stemming from B, and B is not equal to any copy stemming from A. -

- -

- Though symbol instances are integer like in that copy and equality comparison operations can be used with them, symbol instances are disallowed from being used with other integer operators. Symbols cannot be compared for greater than or less than; they cannot be incremented, added, nor subtracted, etc. -

- -

Instance implementation

- -

- Within a process, a reference to the factory can be used as a symbol instance, which will cause the factory to become trivial. Making a new instance will merely require copying the factory reference, and there will be nothing in memory that the base factory reference is pointing to. -

- -

- In general, memory addresses are built in symbol instances, hence within the context of a single process run, a program can make use of these symbols. However, this diminishes the size of the address space and leaves the memory at those addresses unused. A common hedge is then to use references into a dictionary, where the data looked up in the dictionary is the name of the symbol. -

- -

- 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. -

- -

- An alternative implementation is to have the factory return an integer value. Each factory has a base integer that is distinct from that of other factories. Calling make then returns the base integer. -

- -

- As another alternative, each factory can be given a base string, and then make returns a copy of the base string. Here we refer literally to the string as the symbol instance. There is no separate name, and the string data, not the reference to the string, becomes the symbol instance. This is however merely an architectural constraint, under the hood an implementation could use string references as long as it always appears to the programmer that the string value is being used. -

- -

- 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). 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. -

- -

Distinctness across contexts

- -

- If a symbol persists across contexts (such as across scopes or processes), it must remain distinct from all other symbols in its new context. -

- -

- 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 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. -

- -

Symbol copy consequentiality

- -

- Copying symbol instances is an integral part of the operation of the Turing machine. Typically the programmed control steps are used as a cost metric for running a program. Such steps integrate operations of copying symbols to and from the tape. Thus from a pure step count perspective the cost of the symbol copy is inconsequential, not due to any behavior of a symbol copy, but rather due the symbol copy being subsumed within the definition of the step.

-

- However, this is feels unsatisfactory. Here we are tying to build a bridge from computation theory to architecture, and thus we want a step to be a constant time occurrence at least in the average, or at least approximately. To model the symbol copy time, a symbol could be copied a tranche of bits per step, thus giving the copy a step count. Then, if symbols were to grow in tranche count as a program ran longer, then symbol copy of ever longer symbols would be computationally consequential. -

- -

- Fortunately, the Turing Machine is defined with a finite alphabet and a couple of additional symbols. As these are part of the machine definition, and thus do not change at run time, there is no growth in size, and the time to copy them is inconsequential. -

- -

- On a real machine, the factory would be used to make the data alphabet and a couple of additional symbols. As these are set up before the machine runs, and thus before we count steps, these actions are computationally inconsequential. -

- -

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, and a set of symbols could be finite or infinite.

- -

For a Turing machine there are a fixed number of alphabets that are all finite. The set of data symbols, control symbols, and controller state name symbols, are all finite and set in advance. -

- -

Symbol implementation examples

- -

- 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. -

- - - /* The enum definition acts as the factory. */ - typedef enum { - SYMBOL_EMPTY = 0, - SYMBOL_ZERO = 1, - SYMBOL_ONE = 2, - SYMBOL_A = 3, - SYMBOL_B = 4 - } TapeAlphabet; - - /* Instantiating copies of the symbols: */ - TapeAlphabet cell_1 = SYMBOL_A; - TapeAlphabet cell_2 = SYMBOL_A; - - /* Equality comparison over instances */ - if(cell_1 == cell_2){ - /* Evaluates to True */ - } - - -

- 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; - } - - 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"); - } - - -

Property

- -

- A property is a pair, where the components are called the name and the value. A name is an instance of a symbol and it must uniquely identify the property within its context. The value is a variable that can be written then read back. -

- -

Dictionary and reference

- -

A dictionary is a property context object. It is a set of properties, where a property may be selected from the set given its name, which is a symbol instance. The corresponding property value is then the referenced object.

- -

A reference is a dictionary key which uniquely identifies a property in the dictionary. A dictionary is also known as a symbol table. In hardware design, the symbols are often unsigned integers, AKA Natural Numbers, and a symbol table is implemented using an array that is indexed into using the key.

- -

Any programming object that holds other objects is a container, whereas a dictionary is a specific type of key access container.

- -

A Turing Machine tape cell

- -

- A cell is the square from Alan Turing's 1936 paper Alan M. Turing, "On Computable Numbers, with an Application to the Entscheidungsproblem," Proceedings of the London Mathematical Society s2 42, no. 1 (1936): 230 265.. Mathematically, a cell is a referencable distinct identifiable set, with one to three property members depending on the type of cell. -

- -

- A leftmost cell is a set of two properties named 'right neighbor' and 'data'. A rightmost cell is a set of two properties named 'left neighbor' and 'data'. An medial cell is a set holding three properties: a 'left neighbor', a 'right neighbor', and 'data'. While an island cell owns a single compulsory property, that of 'data'. -

- -

- The value of a neighbor property is a non-null single reference to a cell. The value of a data property is strictly an instance of an alphabet symbol, or alternatively, an instance of the empty symbol. -

- -

Tape

- -

- A tape is a set containing exactly one leftmost cell and an infinite number of medial cells. For each cell in the set, called cell A, if cell A has a right neighbor that is cell B, then cell B's left neighbor is cell A. Similarly, if cell A has a left neighbor of cell B, then cell B's right neighbor is cell A. Furthermore, any cell in the set must be reachable by traversing right neighbors starting from the leftmost cell, in a finite number of steps. -

- -

- To say that a tape is infinite, and to simultaneously require that any cell can be reached in a finite number of steps, means that after reaching said cell, there will always be further cells to the right. Consequently, though any cell can be reached in finite hops starting at the leftmost cell, a finite traversal of the tape can not visit all of the cells. This seeming contradiction is at the very heart of the definition of the countable infinity in mathematics. -

+

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 than that—precisely two cells. A program that counts the number of characters on its input tape using Arabic notation will execute in asymptotically linear time, as demonstrated later in the section analyzing the increment operation. Its working footprint, however, will be logarithmic in space complexity, because that is how fast an Arabic representation grows with a count.

-

- In conventional computation theory, once a tape is defined, the cell neighbor properties values are fixed. Cells don't move, new cells cannot be added, and cells existing on the tape cannot be removed. This fits the definition of a space, so we can say that a Turing Machine tape has a constant, fixed, linear topology. This permanence of cells matches the reality of hardware memories. On the other hand, it does not track well with general memory containers such as linked lists where destructive operations are often permitted. -

+

If a program ran at human operator speed, it would be quite slow, likely so much so that the operator waiting for the results would abandon the process. This highlights another attribute of good programs: utility. It also demonstrates one of the limitations of computation theoretic analysis. Nevertheless, formal analysis retains a critical purpose. The execution time of an exponential time program explodes relative to the length of the input, quickly requiring more time than the universe has existed. Computation theory does not instruct upon wall-clock time; rather, it describes behavior against increasing input lengths for worst-case operands, which has important implications for wall-clock time.

-

- Nor can a cell data property be removed; however, unlike for cell neighbor property values, the cell data property value can be changed while the Turing Machine is running. In fact some people would say this is the whole point of running a Turing Machine. -

+

The same can be said for space complexity. Suppose a program doubled its memory footprint each time its input string increased by one. If an individual proton could hold one bit of memory, say via its spin, an input increase of merely 270 characters for such a program would exhaust all the protons in the universe. Allocating a cell of space requires the machine to take a step, so time complexity is at least equal to space complexity. If a computer ran at 10 GHz and a step required 10^{-10} seconds, this same extension would require 6 \times 10^{63} years. For perspective, the universe is approximately 1.4 \times 10^{10} years old.

-

- An empty tape is filled with empty symbols. However, as we noted above, a Turing Machine cannot visit all the cells on a tape, so a Turing Machine cannot erase a tape in advance for another Turing Machine to use. Say a Turing Machine tried to erase a tape by writing the empty symbol, then stepping right, then repeating. At some point it must halt. When it halts some number of cells will have been written with the empty symbols, but there will be further cells to the right of the cell the machine halted at, which have not yet been erased. So for example, if a machine wrote 10 cells with the empty symbol, then it might be the case that the prior user of the tape had written data to 11 of the cells. Without historical knowledge the eraser machine can not know where to stop. So here we see another meaning of infinity, it speaks to the situation of not having historical knowledge. And thus, we are left to decree into existence an empty tape, or as the mathematicians say, empty tapes are available by definition. +

This book provides the transformational steps needed to go from the Turing Machine to real machines, and one objective is to recover some correspondence between the machine steps of the model and the wall-clock time the machine takes to run. Given this, the system operator changing tapes creates a step that is disproportionately longer than the other steps, a factor that requires architectural mediation, but will not go away. For example, this structural penalty resurfaces in the form of cache misses causing a machine to reach into system memory, or worse, page faults, requiring a machine to go back to disk.

-

- 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. -

+

As a possible practical solution, note that if the program does not exhaust the current tape, the operator will never be called. How much tape is required to ensure this? An analyst could choose worst-case operands and measure the footprint when the program runs. At first, this appears to be the familiar 'my number is bigger than your number, I'll tell you mine after you tell me yours' game, which can be viewed as the definition for the countable infinity. However, there is a loophole. Running the system once with the worst-case operands to establish time and space ceilings guarantees the program can be allocated sufficient resources later for other operands. This is a practical approach, provided the program is a workhorse utility rather than an algorithm searching for a solution to an unsolved problem that only needs to run once.

-

- Mathematically, a Turing Machine tape can be expressed as a path graph. However, a tape model and a path graph model 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 programmed 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. -

+

Suppose a controller is not analyzed to determine its computation theoretic complexity, or even tested against worst-case inputs, but is instead run with random or everyday input to gather performance measurements. This process is called profiling. After many runs, a programmer might surmise the behavioral limits of the program. However, many programs are neither linear systems nor smooth functions. With a different set of inputs than those used for profiling—perhaps even values strictly adjacent to prior inputs—the program behavior can shift drastically. Take, for example, the Pentium divider. It did not matter how many millions of times the result was accurate; the fact remains that customers later found an input that yielded wildly inaccurate results. Only by elevating the analysis to the structural logic of the code can such an eventuality be categorically ruled out. This is why the K5 transcendental function development project included a proof writing, see Thomas Walker Lynch, A. Ahmed, M. Schulte, T. Callaway, and R. Tisdale, "The K5 Transcendental Functions," Proceedings of the 12th IEEE Symposium on Computer Arithmetic, 1995. DOI: 10.1109/ARITH.1995.465368.

-

Head unit, HU

+

Head unit, HU

An HU contains a head and a local controller. The local controller supports these commands, but only when a tape is mounted under it:

@@ -1508,8 +1261,7 @@
  • rightmost
  • medial → γ

  • island → γ

    -
      - +

    A status of rightmost or island would never be returned for a computer theoretic Turing Machine tape, but it can be for an area of a tape, and such an area can be virtual tape. We will use this model to reconcile the difference between the architectural finite tape, and that of the infinite theoretical tape. Area is discussed in the section dedicated to that topic.

    @@ -1520,7 +1272,7 @@
    1. one or more read/write heads
    2. -
    3. a single symbol FIFO read data buss, written by the TTU, read by the executor
    4. +
    5. a single symbol FIFO read data buffer, written by the TTU, read by the executor
    6. a single symbol FIFO status buffer, written by the TTU, read by the executor
    7. a single symbol FIFO command buffer, written by the programmed controller, acted upon immediately by the TTU
    @@ -1594,37 +1346,16 @@

    Not shown on this diagram is the row of toggle switches, one per state, that if flipped on, the state becomes a halting state. Also not show is the action selection panel. It is another rectangle, with rows for actions, and a top row for the state. Each state can then be assigned to an action. Note, this is the control panel for a single TTU machine.

    -

    Stored Program Control

    +

    The machine block diagram

    -

    Configuring and debugging a patch panel is a long and cumbersome task. The patch panel can instead be programmed with an interpreter, and then the program can be read from the tape. This then realizes the Universal Turing Machine. The program being interpreted then can call out TTCU commands directly, as functions in software. -

    - - - [<TTU_ID>:][<buffer>:]symbol - -

    As multiple TTUs can be plugged in, an identifier starts with a TTU id. There are two buffers that on the TTU interface that interface can read, data and status, so that is specified next. Following that is the symbol to be matched. If the TTU_ID field is not present, the colon is also omitted, and the value is taken as 0. If the buffer name is ommitted, the colon is also omitted, and the value is taken as data.

    - -

    The default next state list is a list of next state specifier. This list is checked first, i.e. has precedence, over the state dictionary next state list

    - -

    Each entry in the state dictionary consists of one TTU command, followed by a next state list.

    - -

    The TTU command set consists of:

    -
      -
    1. no-op
    2. -
    3. step
    4. -
    5. step left
    6. -
    7. write(x)
    8. -
    - -

    Note that the write value, x must be a symbol from either the data alphabet or be the empty symbol.

    The structural portion of the programmed controller:

      -
    1. the TTU command set
    2. -
    3. the current state register
    4. -
    5. the reset control line
    6. +
    7. the TTU command set as selectable actions
    8. +
    9. the current state register, decoded to illuminate the panel light
    10. +
    11. the reset control line, from the reset button
    12. the clock
    13. -
    14. multiple comparators
    15. +
    16. multiple comparators, on bus from the g register

    The comparators are used to used to match the identifier with a the values read from each of the buffers. Note that if the same next state is specified for the same start state, then it is the same as though the identifiers are in disjunction. Also the no-op command to create conjunctive decisions. Hence as a shorthand notation arcs can be labeled with propositions made from the buffer values.

    @@ -1633,6 +1364,13 @@

    On the rising edge of the clock, the TTU writes the data and status buffers, and the state command is written to the TTU command buffer. On the falling edge of the clock, the TTU completes the state command, and the next state is written to the current state register.

    +

    Stored Program Control

    + +

    Configuring and debugging a patch panel is a cumbersome task. The patch panel can instead be programmed with an interpreter, and then the interpreter can interpret the program found as data on the tape. This is then a Universal Turing Machine. The program being interpreted then can call out TTCU commands directly, as functions in software. In fact, the stored program is so much easier to use, that some models of our machine will have the patch cords inserted at the factory with the patch panel placed inside the cabinet. +

    + +

    The next chapter discusses the stored program langauge.

    +

    Here is an example customer defined programmed controller for incrementing a unary number:

    @@ -1861,6 +1599,265 @@

    + The TTCA stored program + +

    Symbol in mathematics

    + +

    + A symbol is a distinct mathematical object capable of being instantiated. Within a given context, any instance of a specific symbol evaluates as equal to any other instance of that identical symbol, and evaluates as not equal to any instance of a different symbol. +

    + +

    + Put more formally, given a set of instantiable objects and a collection of instances made from them, for these objects to be symbols, two 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. +

    + +

    Symbol in computing

    + +

    + 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. +

    + +

    + A symbol instance newly minted by the factory is said to come direct from the factory. A symbol instance direct from the factory is also called an original. +

    + +

    Required properties of symbol factories

    + +

    + Any two symbol instances returned directly from two distinct factories will always evaluate to False during an equality comparison. In other words, two distinct originals will always be not equal. +

    + +

    + Given an original, all copies stemming from it will be equal to each other and to the original. By stemming from, this definition includes all direct copies and copies of copies. +

    + +

    + Given any two originals, say A and B, it is established that A is not equal to B, as discussed above. Note also that A is not equal to any copy stemming from B, and B is not equal to any copy stemming from A. +

    + +

    + Though symbol instances are integer like in that copy and equality comparison operations can be used with them, symbol instances are disallowed from being used with other integer operators. Symbols cannot be compared for greater than or less than; they cannot be incremented, added, nor subtracted, etc. +

    + +

    Instance implementation

    + +

    + Within a process, a reference to the factory can be used as a symbol instance, which will cause the factory to become trivial. Making a new instance will merely require copying the factory reference, and there will be nothing in memory that the base factory reference is pointing to. +

    + +

    + In general, memory addresses are built in symbol instances, hence within the context of a single process run, a program can make use of these symbols. However, this diminishes the size of the address space and leaves the memory at those addresses unused. A common hedge is then to use references into a dictionary, where the data looked up in the dictionary is the name of the symbol. +

    + +

    + 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. +

    + +

    + An alternative implementation is to have the factory return an integer value. Each factory has a base integer that is distinct from that of other factories. Calling make then returns the base integer. +

    + +

    + As another alternative, each factory can be given a base string, and then make returns a copy of the base string. Here we refer literally to the string as the symbol instance. There is no separate name, and the string data, not the reference to the string, becomes the symbol instance. This is however merely an architectural constraint, under the hood an implementation could use string references as long as it always appears to the programmer that the string value is being used. +

    + +

    + 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). 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. +

    + +

    Distinctness across contexts

    + +

    + If a symbol persists across contexts (such as across scopes or processes), it must remain distinct from all other symbols in its new context. +

    + +

    + 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 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. +

    + +

    Symbol copy consequentiality

    + +

    + Copying symbol instances is an integral part of the operation of the Turing machine. Typically the programmed control steps are used as a cost metric for running a program. Such steps integrate operations of copying symbols to and from the tape. Thus from a pure step count perspective the cost of the symbol copy is inconsequential, not due to any behavior of a symbol copy, but rather due the symbol copy being subsumed within the definition of the step.

    +

    + However, this is feels unsatisfactory. Here we are tying to build a bridge from computation theory to architecture, and thus we want a step to be a constant time occurrence at least in the average, or at least approximately. To model the symbol copy time, a symbol could be copied a tranche of bits per step, thus giving the copy a step count. Then, if symbols were to grow in tranche count as a program ran longer, then symbol copy of ever longer symbols would be computationally consequential. +

    + +

    + Fortunately, the Turing Machine is defined with a finite alphabet and a couple of additional symbols. As these are part of the machine definition, and thus do not change at run time, there is no growth in size, and the time to copy them is inconsequential. +

    + +

    + On a real machine, the factory would be used to make the data alphabet and a couple of additional symbols. As these are set up before the machine runs, and thus before we count steps, these actions are computationally inconsequential. +

    + +

    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, and a set of symbols could be finite or infinite.

    + +

    For a Turing machine there are a fixed number of alphabets that are all finite. The set of data symbols, control symbols, and controller state name symbols, are all finite and set in advance. +

    + +

    Symbol implementation examples

    + +

    + 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. +

    + + + /* The enum definition acts as the factory. */ + typedef enum { + SYMBOL_EMPTY = 0, + SYMBOL_ZERO = 1, + SYMBOL_ONE = 2, + SYMBOL_A = 3, + SYMBOL_B = 4 + } TapeAlphabet; + + /* Instantiating copies of the symbols: */ + TapeAlphabet cell_1 = SYMBOL_A; + TapeAlphabet cell_2 = SYMBOL_A; + + /* Equality comparison over instances */ + if(cell_1 == cell_2){ + /* Evaluates to True */ + } + + +

    + 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; + } + + 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"); + } + + +

    Property

    + +

    + A property is a pair, where the components are called the name and the value. A name is an instance of a symbol and it must uniquely identify the property within its context. The value is a variable that can be written then read back. +

    + +

    Dictionary and reference

    + +

    A dictionary is a property context object. It is a set of properties, where a property may be selected from the set given its name, which is a symbol instance. The corresponding property value is then the referenced object.

    + +

    A reference is a dictionary key which uniquely identifies a property in the dictionary. A dictionary is also known as a symbol table. In hardware design, the symbols are often unsigned integers, AKA Natural Numbers, and a symbol table is implemented using an array that is indexed into using the key.

    + +

    Any programming object that holds other objects is a container, whereas a dictionary is a specific type of key access container.

    + +

    A Turing Machine tape cell

    + +

    + A cell is the square from Alan Turing's 1936 paper Alan M. Turing, "On Computable Numbers, with an Application to the Entscheidungsproblem," Proceedings of the London Mathematical Society s2 42, no. 1 (1936): 230 265.. Mathematically, a cell is a referencable distinct identifiable set, with one to three property members depending on the type of cell. +

    + +

    + A leftmost cell is a set of two properties named 'right neighbor' and 'data'. A rightmost cell is a set of two properties named 'left neighbor' and 'data'. An medial cell is a set holding three properties: a 'left neighbor', a 'right neighbor', and 'data'. While an island cell owns a single compulsory property, that of 'data'. +

    + +

    + The value of a neighbor property is a non-null single reference to a cell. The value of a data property is strictly an instance of an alphabet symbol, or alternatively, an instance of the empty symbol. +

    + +

    Tape

    + +

    + A tape is a set containing exactly one leftmost cell and an infinite number of medial cells. For each cell in the set, called cell A, if cell A has a right neighbor that is cell B, then cell B's left neighbor is cell A. Similarly, if cell A has a left neighbor of cell B, then cell B's right neighbor is cell A. Furthermore, any cell in the set must be reachable by traversing right neighbors starting from the leftmost cell, in a finite number of steps. +

    + +

    + To say that a tape is infinite, and to simultaneously require that any cell can be reached in a finite number of steps, means that after reaching said cell, there will always be further cells to the right. Consequently, though any cell can be reached in finite hops starting at the leftmost cell, a finite traversal of the tape can not visit all of the cells. This seeming contradiction is at the very heart of the definition of the countable infinity in mathematics. +

    + +

    + In conventional computation theory, once a tape is defined, the cell neighbor properties values are fixed. Cells don't move, new cells cannot be added, and cells existing on the tape cannot be removed. This fits the definition of a space, so we can say that a Turing Machine tape has a constant, fixed, linear topology. This permanence of cells matches the reality of hardware memories. On the other hand, it does not track well with general memory containers such as linked lists where destructive operations are often permitted. +

    + +

    + Nor can a cell data property be removed; however, unlike for cell neighbor property values, the cell data property value can be changed while the Turing Machine is running. In fact some people would say this is the whole point of running a Turing Machine. +

    + +

    + An empty tape is filled with empty symbols. However, as we noted above, a Turing Machine cannot visit all the cells on a tape, so a Turing Machine cannot erase a tape in advance for another Turing Machine to use. Say a Turing Machine tried to erase a tape by writing the empty symbol, then stepping right, then repeating. At some point it must halt. When it halts some number of cells will have been written with the empty symbols, but there will be further cells to the right of the cell the machine halted at, which have not yet been erased. So for example, if a machine wrote 10 cells with the empty symbol, then it might be the case that the prior user of the tape had written data to 11 of the cells. Without historical knowledge the eraser machine can not know where to stop. So here we see another meaning of infinity, it speaks to the situation of not having historical knowledge. And thus, we are left to decree into existence an empty tape, or as the mathematicians say, empty tapes are available by definition. +

    + +

    + Mathematically, a Turing Machine tape is a specialized path graph. The neighbor properties are the edges. In this special form, properties are attached to the edges. A Turing Machine has a clock based state controller. Taking a step is an atomic operation. The machine is either in state S_i or in state S_{i+1}, there is no mathematical meaning given to the concept of during a step, which is why no properties are added to the edges of the tape path graph. This is not to say that some analysis of a Turing Machine program won't take pairs of nodes from the path graph and give them meaning, thus effectively giving properties to the arcs. However, this would not be part of the machine definition, such a program must go through the additional effort of making node pairs, because the machine itself does not provide the program with a feature for attaching properties directly to the neighbor property itself.

    + +

    An example of a non-Turing tape like model is the Emacs vertical line cursor model, where a cursor is said to be between characters. An ASCII file offers no such feature as 'in between' characters. Like a Turing Machine tape, a medial character in an ASCII file has a left neighbor and a right neighbor character. Any attempt to represent an in between cursor within the file itself would require inserting more characters into the file under the same model of every medial character having a left and a right character. Consequently, though emacs presents a model where cursor is located in between two characters, this model is only due to the interpretation of the functions' actual effects presented to users in the documentation. For example, instead of saying a cursor is located upon a character, and that inserting a character inserts the character to the right of the given character, the manual gives the description that the new character is inserted at the cursor location, where said cursor is in between the given character and its right neighbor. Thus the documentation presents the user with one model, which by necessity of using standard library calls to work with files, is built upon another model.

    + Or, does it go the other way? Computational Naturalism

    diff --git a/document/book/TTCA_machine.svg b/document/book/TTCA_machine.svg new file mode 100644 index 0000000..d5a977f --- /dev/null +++ b/document/book/TTCA_machine.svg @@ -0,0 +1,5289 @@ + +EXECUTORReset LogicStep/PhaseControlStep PulseCPCU(Programmed Controller)Next StateTable (δ)g REGISTER(Gate/Status)d REGISTERg registerComparators== σ== leftmost==rightmostTTU [n]TTU [1]TTU [0]DataHEADUNIT 0TAPE...qstatuscommandMuxMuxMuxr/wControl diff --git a/document/book/gemini-svg.svg b/document/book/gemini-svg.svg new file mode 100644 index 0000000..2152e1e --- /dev/null +++ b/document/book/gemini-svg.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + Reset Button + + + + Clock + + + + + EXECUTOR + + + Reset Logic + + + Step/Phase + Control + + + Step Pulse + + + + CPCU + (Programmed Controller) + + + Next State + Logic (δ) + + + Action + Logic (λ) + + + q + + + + g REGISTER + (Gate/Status) + + + d REGISTER + (Data) + + + q REGISTER + + + + + + Comparators + + + == σ + + + == leftmost + + + == unspecified + + + Default (dflt) + + + + To Next State Logic + + + + + TTU [n] + + + + TTU [1] + + + + TTU [0] + + + Command + Buffer (FIFO) + + + Status + Buffer (FIFO) + + + Read Data + Buffer (FIFO) + + + HEAD UNIT 0 + (Local Controller) + + + + + + TTU Command Bus + + + + Status Bus + + + + Read Data Bus + + + + Write Data + + + + + + + + + + + + + TAPE + ... + + + + Read / Write + +