FRACTRAN explained

FRACTRAN is a Turing-complete esoteric programming language invented by the mathematician John Conway. A FRACTRAN program is an ordered list of positive fractions together with an initial positive integer input n. The program is run by updating the integer n as follows:

  1. for the first fraction f in the list for which nf is an integer, replace n by nf
  2. repeat this rule until no fraction in the list produces an integer when multiplied by n, then halt.

gives the following FRACTRAN program, called PRIMEGAME, which finds successive prime numbers:

\left(\frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac \right)

Starting with n=2, this FRACTRAN program generates the following sequence of integers:

After 2, this sequence contains the following powers of 2:

2^2=4,\, 2^3=8,\, 2^5=32,\, 2^7=128,\, 2^=2048,\, 2^=8192,\, 2^=131072,\, 2^=524288,\, \dots

The exponent part of these powers of two are primes, 2, 3, 5, etc.

Understanding a FRACTRAN program

A FRACTRAN program can be seen as a type of register machine where the registers are stored in prime exponents in the argument n.

Using Gödel numbering, a positive integer n can encode an arbitrary number of arbitrarily large positive integer variables.[1] The value of each variable is encoded as the exponent of a prime number in the prime factorization of the integer. For example, the integer

60 = 2^2 \times 3^1 \times 5^1

represents a register state in which one variable (which we will call v2) holds the value 2 and two other variables (v3 and v5) hold the value 1. All other variables hold the value 0.

A FRACTRAN program is an ordered list of positive fractions. Each fraction represents an instruction that tests one or more variables, represented by the prime factors of its denominator. For example:

f_1 = \frac = \frac

tests v2 and v5. If

v2\ge2

and

v5\ge1

, then it subtracts 2 from v2 and 1 from v5 and adds 1 to v3 and 1 to v7. For example:

60 \cdot f_1 = 2^2 \times 3^1 \times 5^1 \cdot \frac = 3^2 \times 7^1

Since the FRACTRAN program is just a list of fractions, these test-decrement-increment instructions are the only allowed instructions in the FRACTRAN language. In addition the following restrictions apply:

Creating simple programs

Addition

The simplest FRACTRAN program is a single instruction such as

\left(\frac \right)

This program can be represented as a (very simple) algorithm as follows:

FRACTRAN
instruction
ConditionAction
3
2
v2 > 0Subtract 1 from v2
Add 1 to v3
v2 = 0Stop

Given an initial input of the form

2a3b

, this program will compute the sequence

2a-13b+1

,

2a-23b+2

, etc., until eventually, after

a

steps, no factors of 2 remain and the product with
3
2
no longer yields an integer; the machine then stops with a final output of

3a

. It therefore adds two integers together.

Multiplication

We can create a "multiplier" by "looping" through the "adder". In order to do this we need to introduce states into our algorithm. This algorithm will take a number

2a3b

and produce

5ab

:
Current stateConditionActionNext state
Av7 > 0Subtract 1 from v7
Add 1 to v3
A
v7 = 0 and
v2 > 0
Subtract 1 from v2B
v7 = 0 and
v2 = 0 and
v3 > 0
Subtract 1 from v3A
v7 = 0 and
v2 = 0 and
v3 = 0
Stop
Bv3 > 0Subtract 1 from v3
Add 1 to v5
Add 1 to v7
B
v3 = 0NoneA

State B is a loop that adds v3 to v5 and also moves v3 to v7, and state A is an outer control loop that repeats the loop in state B v2 times. State A also restores the value of v3 from v7 after the loop in state B has completed.

We can implement states using new variables as state indicators. The state indicators for state B will be v11 and v13. Note that we require two state control indicators for one loop; a primary flag (v11) and a secondary flag (v13). Because each indicator is consumed whenever it is tested, we need a secondary indicator to say "continue in the current state"; this secondary indicator is swapped back to the primary indicator in the next instruction, and the loop continues.

Adding FRACTRAN state indicators and instructions to the multiplication algorithm table, we have:

FRACTRAN
instruction
Current stateState
indicators
ConditionActionNext state
3
7
ANonev7 > 0Subtract 1 from v7
Add 1 to v3
A
11
2
v7 = 0 and
v2 > 0
Subtract 1 from v2B
1
3
v7 = 0 and
v2 = 0 and
v3 > 0
Subtract 1 from v3A
v7 = 0 and
v2 = 0 and
v3 = 0
Stop
5 ⋅ 7 ⋅ 13
3 ⋅ 11

,

11
13
Bv11, v13v3 > 0Subtract 1 from v3
Add 1 to v5
Add 1 to v7
B
1
11
v3 = 0NoneA

When we write out the FRACTRAN instructions, we must put the state A instructions last, because state A has no state indicators - it is the default state if no state indicators are set. So as a FRACTRAN program, the multiplier becomes:

\left(\frac, \frac, \frac, \frac, \frac, \frac \right)

With input 2a3b this program produces output 5ab. [2]

Subtraction and division

In a similar way, we can create a FRACTRAN "subtractor", and repeated subtractions allow us to create a "quotient and remainder" algorithm as follows:

FRACTRAN
instruction
Current stateState
indicators
ConditionActionNext state
7 ⋅ 13
2 ⋅ 3 ⋅ 11

,

11
13
Av11, v13v2 > 0 and
v3 > 0
Subtract 1 from v2
Subtract 1 from v3
Add 1 to v7
A
1
3 ⋅ 11
v2 = 0 and
v3 > 0
Subtract 1 from v3X
5 ⋅ 17
11
v3 = 0Add 1 to v5B
3 ⋅ 19
7 ⋅ 17

,

17
19
Bv17, v19v7 > 0Subtract 1 from v7
Add 1 to v3
B
11
17
v7 = 0NoneA
1
3
Xv3 > 0Subtract 1 from v3X
v3 = 0Stop

Writing out the FRACTRAN program, we have:

\left(\frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac \right)

and input 2n3d11 produces output 5q7r where n = qd + r and 0 ≤ r < d.

Conway's prime algorithm

Conway's prime generating algorithm above is essentially a quotient and remainder algorithm within two loops. Given input of the form

2n7m

where 0 ≤ m < n, the algorithm tries to divide n+1 by each number from n down to 1, until it finds the largest number k that is a divisor of n+1. It then returns 2n+1 7k-1 and repeats. The only times that the sequence of state numbers generated by the algorithm produces a power of 2 is when k is 1 (so that the exponent of 7 is 0), which only occurs if the exponent of 2 is a prime. A step-by-step explanation of Conway's algorithm can be found in Havil (2007).

For this program, reaching the prime number 2, 3, 5, 7... requires respectively 19, 69, 281, 710,... steps .

A variant of Conway's program also exists, which differs from the above version by two fractions:\left(\frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac \right)

This variant is a little faster: reaching 2, 3, 5, 7... takes it 19, 69, 280, 707... steps . A single iteration of this program, checking a particular number N for primeness, takes the following number of steps:N - 1 + (6N+2)(N-b) + 2 \sum\limits^_ \left\lfloor \frac \right\rfloor,where

b<N

is the largest integer divisor of N and

\lfloorx\rfloor

is the floor function.

In 1999, Devin Kilminster demonstrated a shorter, ten-instruction program: \left(\frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac, \frac \right).For the initial input n = 10 successive primes are generated by subsequent powers of 10.

Other examples

The following FRACTRAN program:

\left(\frac, \frac, \frac, \frac, \frac, \frac, \frac \right)

calculates the Hamming weight H(a) of the binary expansion of a i.e. the number of 1s in the binary expansion of a.[3] Given input 2a, its output is 13H(a). The program can be analysed as follows:

FRACTRAN
instruction
Current stateState
indicators
ConditionActionNext state
3 ⋅ 11
22 ⋅ 5

,

5
11
Av5, v11v2 > 1Subtract 2 from v2
Add 1 to v3
A
13
2 ⋅ 5
v2 = 1Subtract 1 from v2
Add 1 to v13
B
1
5
v2 = 0NoneB
2
3
BNonev3 > 0Subtract 1 from v3
Add 1 to v2
B
2 ⋅ 5
7
v3 = 0 and
v7 > 0
Subtract 1 from v7
Add 1 to v2
A
7
2
v3 = 0 and
v7 = 0 and
v2 > 0
Subtract 1 from v2
add 1 to v7
B
v2 = 0 and
v3 = 0 and
v7 = 0
Stop

See also

References

External links

Notes and References

  1. [Gödel numbering]
  2. A similar multiplier algorithm is described at the Esolang FRACTRAN page.
  3. John Baez, Puzzle #4, The n-Category Café