Understanding Computation (44 page)

Read Understanding Computation Online

Authors: Tom Stuart

Tags: #COMPUTERS / Programming / General

BOOK: Understanding Computation
4.87Mb size Format: txt, pdf, ePub
Note

For a full explanation of how a tag system simulation of a Turing
machine works, see Matthew Cook’s elegant construction in section 2.1 of
http://www.complex-systems.com/pdf/15-1-1.pdf
.

Cook’s simulation is more sophisticated than the one outlined
here. It cleverly uses the “alignment” of the current string to
represent the character beneath the simulated tape head instead of
incorporating it into one of the tape parts, and can easily be extended
to simulate a Turing machine with any number of characters by increasing
the tag system’s deletion number.

The fact that tag systems can simulate any Turing machine means that
they too are
universal.

Cyclic Tag Systems

A
cyclic tag system
is a
tag system that has been made even simpler by imposing some
extra constraints:

  • A cyclic tag system’s string can contain only two characters,
    0
    and
    1
    .

  • A cyclic tag system rule can only apply when the current string begins with
    1
    , never
    0
    .
    [
    60
    ]

  • A cyclic tag system’s deletion number is always 1.

By themselves, these constraints are too severe to support any kind of useful computation,
so cyclic tag systems get an extra feature to compensate: the first rule in a cyclic tag
system’s rulebook is the
current rule
when execution begins, and after
each step of computation, the next rule in the rulebook becomes current, wrapping back to the
first rule when the end of the rulebook is reached.

This kind of system is called “cyclic” because of the way the current rule cycles
repeatedly through the
rulebook. The use of a current rule, combined with the constraint that every rule
applies to strings beginning with
1
, avoids the overhead of
having to search through the rulebook to find an applicable rule at each step of execution; if
the first character’s a
1
, then the current rule applies,
otherwise, no rule does.

As an example, let’s look at the cyclic tag system with three rules
that append the characters
1
,
0010
, and
10
,
respectively. Here’s what happens when it’s started with the string
11
:

Current string
Current rule
Rule applies?
11
append the character
1
yes
 1
1
append the characters
0010
yes
  1
0010
append the characters
10
yes
   0010
10
append the character
1
no
    01010
append the characters
0010
no
     1010
append the characters
10
yes
      010
10
append the character
1
no
       1010
append the characters
0010
yes
        010
0010
append the characters
10
no
         100010
append the character
1
yes
          00010
1
append the characters
0010
no
           00101
append the characters
10
no
            0101
append the character
1
no
             101
append the characters
0010
yes
              01
0010
append the characters
10
no
               10010
append the character
1
yes
                0010
1
append the characters
0010
no
                 ⋮


Despite the extreme simplicity of this system, we can see a hint of complex behavior: it’s
not obvious what will happen next. With a bit of thought we can convince ourselves that the
system will run forever rather than dwindle to the empty string, because every rule appends a
1
, so as long as the initial string contains a
1
, it will never die out entirely.
[
61
]
But will the current string keep fitfully growing longer, or will it settle into a
repeating pattern of expansion and contraction? Just looking at the rules doesn’t answer that
question; we need to keep running the system to find out what happens.

We already have a Ruby implementation of a conventional tag system, so simulating a cyclic
tag system doesn’t require much extra work. We can implement a
Cyclic
TagRule
simply by subclassing
TagRule
and hardcoding
'1'
as its
first_character
:

class
CyclicTagRule
<
TagRule
FIRST_CHARACTER
=
'1'
def
initialize
(
append_characters
)
super
(
FIRST_CHARACTER
,
append_characters
)
end
def
inspect
"##{
append_characters
.
inspect
}
>"
end
end
Note

#initialize
is the
constructor
method that gets called automatically
when an instance of a class is created.
CyclicTagRule#initialize
calls the constructor
from the superclass,
TagRule
, to set
the
first_character
and
append_characters
attributes.

The rulebook for a cyclic tag system works slightly differently, so
we’ll build a
CyclicTagRulebook
class
from scratch, providing new implementations of
#applies_to?
and
#next_string
:

class
CyclicTagRulebook
<
Struct
.
new
(
:rules
)
DELETION_NUMBER
=
1
def
initialize
(
rules
)
super
(
rules
.
cycle
)
end
def
applies_to?
(
string
)
string
.
length
>=
DELETION_NUMBER
end
def
next_string
(
string
)
follow_next_rule
(
string
)
.
slice
(
DELETION_NUMBER
.
.
-
1
)
end
def
follow_next_rule
(
string
)
rule
=
rules
.
next
if
rule
.
applies_to?
(
string
)
rule
.
follow
(
string
)
else
string
end
end
end

Unlike a vanilla
TagRulebook
, a
CyclicTagRulebook
always applies to any nonempty string, even if
the current rule doesn’t.

Note

Array#cycle
creates an
Enumerator
(see
Native Ruby Streams
)
that cycles around the elements of an array forever:

>>
numbers
=
[
1
,
2
,
3
].
cycle
=> #
>>
numbers
.
next
=> 1
>>
numbers
.
next
=> 2
>>
numbers
.
next
=> 3
>>
numbers
.
next
=> 1
>>
[
:a
,
:b
,
:c
,
:d
].
cycle
.
take
(
10
)
=> [:a, :b, :c, :d, :a, :b, :c, :d, :a, :b]

This is exactly the behavior we want for a cyclic tag system’s
current rule, so
CyclicTagRulebook#initialize
assigns one of
these cycling
Enumerator
s to the
rules
attribute, and each call to
#follow_next_rule
uses
rules.next
to get the next rule in the
cycle.

Now we can create a
CyclicTagRulebook
full of
CyclicTagRule
s and plug it into a
TagSystem
to see it working:

>>
rulebook
=
CyclicTagRulebook
.
new
(
[
CyclicTagRule
.
new
(
'1'
),
CyclicTagRule
.
new
(
'0010'
),
CyclicTagRule
.
new
(
'10'
)
]
)
=> #
>>
system
=
TagSystem
.
new
(
'11'
,
rulebook
)
=> #
>>
16
.
times
do
puts
system
.
current_string
system
.
step
end
;
puts
system
.
current_string
11
11
10010
001010
01010
1010
01010
1010
0100010
100010
000101
00101
0101
101
010010
10010
00101
=> nil

That’s the same behavior we saw when we stepped through the
execution by hand. Let’s keep going:

>>
20
.
times
do
puts
system
.
current_string
system
.
step
end
;
puts
system
.
current_string
00101
0101
101
011
11
110
101
010010
10010
00101
0101
101
011
11
110
101
010010
10010
00101
0101
101
=> nil

So it turns out that this system
does
settle
down into repetitive behavior when it’s started with the string
11
: after an initial period of instability, a
pattern of nine consecutive strings emerges (
101
,
010010
,
10010
,
00101
, …) and repeats itself forever. Of course,
if we change the initial string or any of the rules, the long-term
behavior will be different.

Cyclic tag systems are extremely limited—they have inflexible rules, only two characters,
and the lowest possible deletion number—but surprisingly, it’s still possible to use them to
simulate
any
tag system.

The simulation of a normal tag system by a cyclic tag system works
like this:

  1. Determine the tag system’s
    alphabet
    —the
    set of characters it uses.

  2. Design an encoding scheme that associates each character with a unique string suitable
    for use in a cyclic tag system (i.e., containing only
    0
    s and
    1
    s).

  3. Convert each of the original system’s rules into a cyclic tag
    system rule by encoding the characters it appends.

  4. Pad out the cyclic tag system’s rulebook with empty rules to
    simulate the original tag system’s deletion number.

  5. Encode the original tag system’s input string and use it as
    input to the cyclic tag system.

Other books

Unison (The Spheral) by Papanou, Eleni
Murder at the Spa by Stefanie Matteson
Plunking Reggie Jackson by James Bennett
Nobody Walks by Mick Herron
Perfect Strangers by Liv Morris
Defender of Magic by S A Archer, S Ravynheart
The Lion's Mouth by Anne Holt