Counter machine
≈ 15 min read
Names in other languages
No names in other languages are held for this entry yet.
Article bodies are English and are not machine-translated. A name in another language is not a translation of the article.
A counter machine or counter automaton is an abstract machine used in a formal logic and theoretical computer science to model computation. It is the most primitive of the four types of register machines. A counter machine comprises a set of one or more unbounded registers, each of which can hold a single non-negative integer, and a list of (usually sequential) arithmetic and control instructions for the machine to follow. The counter machine is typically used in the process of designing parallel algorithms in relation to the mutual exclusion principle. When used in this manner, the counter machine is used to model the discrete time-steps of a computational system in relation to memory accesses. By modeling computations in relation to the memory accesses for each respective computational step, parallel algorithms may be designed in such a matter to avoid interlocking, the simultaneous writing operation by two (or more) threads to the same memory address. Counter machines with three counters can compute any partial recursive function of a single variable. Counter machines with two counters are Turing complete: they can simulate any appropriately-encoded Turing machine. Counter machines with only a single counter can recognize a proper superset of the regular languages and a subset of the deterministic context free languages.
A counter machine or counter automaton is an abstract machine used in a formal logic and theoretical computer science to model computation. It is the most primitive of the four types of register machines. A counter machine comprises a set of one or more unbounded registers, each of which can hold a single non-negative integer, and a list of (usually sequential) arithmetic and control instructions for the machine to follow. The counter machine is typically used in the process of designing parallel algorithms in relation to the mutual exclusion principle. When used in this manner, the counter machine is used to model the discrete time-steps of a computational system in relation to memory accesses. By modeling computations in relation to the memory accesses for each respective computational step, parallel algorithms may be designed in such a matter to avoid interlocking, the simultaneous writing operation by two (or more) threads to the same memory address. Counter machines with three counters can compute any partial recursive function of a single variable. Counter machines with two counters are Turing complete: they can simulate any appropriately-encoded Turing machine. Counter machines with only a single counter can recognize a proper superset of the regular languages and a subset of the deterministic context free languages. Elgot–Robinson model, used to define their RASP model (1964). This model requires one empty register at the start (e.g. [r0] =0). (They augmented the same model with indirect addressing by use of an additional register to be used as an "index" register.) { INC (r), CPY ( r s , r d ), JE ( r j , r k , z ) } Shepherdson–Sturgis machine, because these authors formally stated their model in an easily accessible exposition (1963). Uses instruction set (1) augmented with additional convenience instructions (JNZ is "Jump if Not Zero, used in place of JZ): { INC ( r ), DEC ( r ), CLR ( r ), CPY ( r j , r k ), JNZ ( r, z ), J ( z ) } Other counter machines: Minsky (1967) demonstrates how to build the three base models (program/Minsky/Lambek-abacus, successor, and Elgot–Robinson) from the superset of available instructions described in the lead paragraph of this article. The Melzak (1961) model is quite different from the above because it includes 'add' and 'subtract' rather than 'increment' and 'decrement'. The proofs of Minsky (1961, 1967) that a single register will suffice for Turing equivalence requires the two instructions { MULtiply k, and DIV k } to encode and decode the Gödel number in the register that represents the computation. Minsky shows that if two or more registers are available then the simpler INC, DEC etc. are adequate (but the Gödel number is still required to demonstrate Turing equivalence; also demonstrated in Elgot–Robinson 1964). { Increment (r), Decrement (r), Clear (r); Copy (r j ,r k ), conditional Jump if contents of r=0, conditional Jump if r j =r k , unconditional Jump, HALT } Some models have either further atomized some of the above into no-parameter instructions, or combined them into a single instruction such as "Decrement" preceded by conditional jump-if-zero "JZ ( r, z )" . The atomization of instructions or the inclusion of convenience instructions causes no change in conceptual power, as any program in one variant can be straightforwardly translated to the other. Alternative instruction-sets are discussed in the supplement Register-machine models. [2] = [3].
The partial recursive functions: building "convenience instructions" using recursion
The example above demonstrates how the first basic instructions { INC, DEC, JZ } can create three more instructions—unconditional jump J, CLR, CPY. In a sense CPY used both CLR and J plus the base set. If register #3 had had contents initially, the sum of contents of #2 and #3 would have ended up in #3. So to be fully accurate CPY program should have preceded its moves with CLR (1) and CLR (3). However, we do see that ADD would have been possible, easily. And in fact the following is summary of how the primitive recursive functions such as ADD, MULtiply and EXPonent can come about. Beginning instruction set: { DEC, INC, JZ, H } Define unconditional "Jump J (z)" in terms of JZ ( r0, z ) given that r0 contains 0. { J, DEC, INC, JZ, H } Define "CLeaR ( r ) in terms of the above: { CLR, J, DEC, INC, JZ, H } Define "CoPY ( r j , r k )" while preserving contents of r j in terms of the above: { CPY, CLR, J, DEC, INC, JZ, H } The above is the instruction set of Shepherdson–Sturgis (1963). Define "ADD ( r j , r k , r i )", (perhaps preserving the contents of r j , and r k ), by use of the above: { ADD, CPY, CLR, J, DEC, INC, JZ, H } Define " MULtiply ( r j , r k , r i )" (MUL) (perhaps preserving the contents of r j , r k ), in terms of the above: { MUL, ADD, CPY, CLR, J, DEC, INC, JZ, H } Define "EXPonential ( r j , r k , r i )" (EXP) (perhaps preserving the contents of r j , r k ) in terms of the above, { EXP, MUL, ADD, CPY, CLR, J, DEC, INC, JZ, H } In general, we can build any partial- or total- primitive recursive function that we wish, by using the same methods. Indeed, Minsky (1967), Shepherdson–Sturgis (1963) and Boolos–Burgess–Jeffrey (1974) give demonstrations of how to form the five primitive recursive function "operators" (1-5 below) from the base set (1). But what about full Turing equivalence? We need to add the sixth operator—the μ operator—to obtain the full equivalence, capable of creating the total- and partial- recursive functions: Zero function (or constant function) Successor function Identity function Composition function Primitive recursion (induction) μ operator (unbounded search operator) The authors show that this is done easily within any of the available base sets (1, 2, or 3) (an example can be found at μ operator). This means that any mu recursive function can be implemented as a counter machine, despite the finite instruction set and program size of the counter machine design. However, the required construction may be counter-intuitive, even for functions that are relatively easy to define in more complex register machines such as the random-access machine. This is because the μ operator can iterate an unbounded number of times, but any given counter machine cannot address an unbounded number of distinct registers due to the finite size of its instruction list. For instance, the above hierarchy of primitive recursive operators can be further extended past exponentiation into higher-ordered arrow operations in Knuth's up-arrow notation. For any fixed k , the function Q(x, y) = x \uparrow^k y is primitive recursive, and can be implemented as a counter machine in a straightforward way. But the function R(n, x, y) = x \uparrow^n y is not primitive recursive. One may be tempted to implement the up-arrow operator R using a construction similar to the successor, addition, multiplication, and exponentiation instructions above, by implementing a call stack so that the function can be applied recursively on smaller values of n . This idea is similar to how one may implement the function in practice in many programming languages. However, the counter machine cannot use an unbounded number of registers in its computation, which would be necessary to implement a call stack that can grow arbitrarily large. The up-arrow operation can still be implemented as a counter machine since it is mu recursive, however the function would be implemented by encoding an unbounded amount of information inside a finite number of registers, such as by using Gödel numbering. JUMP IF [r] =0 to instruction I z Minsky (1967) expanded his 2-instruction set { INC (z), JZDEC (r, I z ) } to { CLR (r), INC (r), JZDEC (r, I z ), J (I z ) } before his proof that a "Universal Program Machine" can be built with only two registers (p. 255ff).
Two-counter machines are Turing equivalent (with a caveat)
For every Turing machine, there is a 2CM that simulates it, given that the 2CM's input and output are properly encoded. This is proved in Minsky's book (Computation, 1967, p. 255-258), and an alternative proof is sketched below in three steps. First, a Turing machine can be simulated by a finite-state machine (FSM) equipped with two stacks. Then, two stacks can be simulated by four counters. Finally, four counters can be simulated by two counters. The two counters machine use the set of instruction { INC ( r, z ), JZDEC ( r, z true , z false ) }.
Step 1: A Turing machine can be simulated by two stacks.
A Turing machine consists of an FSM and an infinite tape, initially filled with zeros, upon which the machine can write ones and zeros. At any time, the read/write head of the machine points to one cell on the tape. This tape can be conceptually cut in half at that point. Each half of the tape can be treated as a stack, where the top is the cell nearest the read/write head, and the bottom is some distance away from the head, with all zeros on the tape beyond the bottom. Accordingly, a Turing machine can be simulated by an FSM plus two stacks. Moving the head left or right is equivalent to popping a bit from one stack and pushing it onto the other. Writing is equivalent to changing the bit before pushing it.
Step 2: A stack can be simulated by two counters.
A stack containing zeros and ones can be simulated by two counters when the bits on the stack are thought of as representing a binary number (the topmost bit on the stack being the least significant bit). Pushing a zero onto the stack is equivalent to doubling the number. Pushing a one is equivalent to doubling and adding 1. Popping is equivalent to dividing by 2, where the remainder is the bit that was popped. Two counters can simulate this stack, in which one of the counters holds a number whose binary representation represents the bits on the stack, and the other counter is used as a scratchpad. To double the number in the first counter, the FSM can initialize the second counter to zero, then repeatedly decrement the first counter once and increment the second counter twice. This continues until the first counter reaches zero. At that point, the second counter will hold the doubled number. Halving is performed by decrementing one counter twice and increment the other once, and repeating until the first counter reaches zero. The remainder can be determined by whether it reached zero after an even or an odd number of steps, where the parity of the number of steps is encoded in the state of the FSM.
Step 3: Four counters can be simulated by two counters.
As before, one of the counters is used as scratchpad. The other holds an integer whose prime factorization is 2 a 3 b 5 c 7 d . The exponents a, b, c, and d can be thought of as four virtual counters that are being packed (via Gödel numbering) into a single real counter. If the real counter is set to zero then incremented once, that is equivalent to setting all the virtual counters to zero. If the real counter is doubled, that is equivalent to incrementing a, and if it's halved, that's equivalent to decrementing a. By a similar procedure, it can be multiplied or divided by 3, which is equivalent to incrementing or decrementing b. Similarly, c and d can be incremented or decremented. To check if a virtual counter such as c is equal to zero, just divide the real counter by 5, see what the remainder is, then multiply by 5 and add back the remainder. That leaves the real counter unchanged. The remainder will have been nonzero if and only if c was zero. As a result, an FSM with two counters can simulate four counters, which are in turn simulating two stacks, which are simulating a Turing machine. Therefore, an FSM plus two counters is at least as powerful as a Turing machine. A Turing machine can easily simulate an FSM with two counters, therefore the two machines have equivalent power.
A practical example of calculation by counting
The Friden EC-130 calculator had no adder logic as such. Its logic was highly serial, doing arithmetic by counting. Internally, decimal digits were radix-1 — for instance, a six was represented by six consecutive pulses within the time slot allocated for that digit. Each time slot carried one digit, least significant first. Carries set a flip-flop which caused one count to be added to the digit in the next time slot. Adding was done by an up-counter, while subtracting was done by a down-counter, with a similar scheme for dealing with borrows. The time slot scheme defined six registers of 13 decimal digits, each with a sign bit. Multiplication and division were done basically by repeated addition and subtraction. The square root version, the EC-132, effectively subtracted consecutive odd integers, each decrement requiring two consecutive subtractions. After the first, the minuend was incremented by one before the second subtraction.
See also
Counter-machine model One-instruction set computer Pointer machine Post–Turing machine Random-access machine Register machine Wang B-machine Vector addition system
References
Bibliography
The original Boolos–Jeffrey text has been extensively revised by Burgess: more advanced than an introductory textbook. "Abacus machine" model is extensively developed in Chapter 5 Abacus Computability; it is one of three models extensively treated and compared—the Turing machine (still in Boolos' original 4-tuple form) and recursion the other two. , reprinted in Develops time hierarchy and space hierarchy theorems for counter machines, analogous to the hierarchies for Turing machines. A difficult book centered around the issues of machine-interpretation of "languages", NP-Completeness, etc. Cf pages 462-463 where he defines "a new kind of abstract machine or 'automaton' which deals with linked structures. In his Appendix II, Lambek proposes a "formal definition of 'program'. He references Melzak (1961) and Kleene (1952) Introduction to Metamathematics. Melzak offers no references but acknowledges "the benefit of conversations with Drs. R. Hamming, D. McIlroy and V. Vyssots of the Bell telephone Laborators and with Dr. H. Wang of Oxford University. In particular see chapter 11: Models Similar to Digital Computers and chapter 14: Very Simple Bases for Computability. In the former chapter he defines "Program machines" and in the later chapter he discusses "Universal Program machines with Two Registers" and "...with one register", etc. A valuable reference paper. In their Appendix A the authors cite 4 others with reference to "Minimality of Instructions Used in 4.1: Comparison with Similar Systems. English translation, Automat. Express 1 (1959), 20-23. Wherein Schönhage shows the equivalence of his SMM with the "successor RAM" (Random Access Machine), etc. The author references Minsky 1967 and notes that "Frances Yao independently proved the non-computability using a similar method in April 1971. Van Emde Boas' treatment of SMMs appears on pp. 32–35. This treatment clarifies Schōnhage 1980—it closely follows but expands slightly the Schōnhage treatment. Both references may be needed for effective understanding. Presented at the meeting of the Association, June 23–25, 1954.
Further reading
External links
Igblan - Minsky Register Machines
Text derived from https://en.wikipedia.org/w/index.php?oldid=1378902742 under CC BY-SA 4.0; modifications have been made.