User:Marc Schroeder/sandbox

″

LOOP is a simple register language designed to precisely capture the primitive recursive functions. The language is derived from the counter-machine model. Like the counter machines the LOOP language comprises a set of one or more unbounded registers, each of which can hold a single non-negative integer. A few arithmetic instructions (like 'Increment', 'Clear', 'Copy', 'Decrement', ...) operate on the registers. The only control flow instruction is LOOP x { ... }. It causes the instructions within its scope to be repeated $$x$$ times.

In contrast to GOTO programs and WHILE programs, LOOP programs always terminate,. The running time is known in advance. Therefore, the set of functions computable by LOOP-programs is a proper subset of computable functions (and thus a subset of the computable by WHILE and GOTO program functions).

History
The LOOP language was formulated in a 1967 paper by Albert R. Meyer and Dennis M. Ritchie. They showed the correspondence between the LOOP language and primitive recursive functions, proving that each primitive recursive function is LOOP-computable and vice versa.

The language also was the topic of the unpublished PhD thesis of Ritchie.

It was presented by Uwe Schöning, along with GOTO and WHILE.

An example of a total computable function that is not LOOP computable is the Ackermann function.

Syntax
A LOOP program consists of
 * 1) a finite number of registers, any of which may contain an arbitrary integer of $$\mathbb{N} = \{0, 1, 2, ...\}$$;
 * 2) a sequence of instructions as specified below.

The set of all LOOP programs L is defined by the following rules:


 * Each of the arithmetic instructions, as well as the empty program, are elements of L.


 * If $$P$$ ∈ L and x is a register, then the program
 * belongs to L.
 * belongs to L.


 * If $$P$$ ∈ L and $$Q$$ ∈ L, then the program
 * belongs to L.
 * belongs to L.

Formal definition

Compare with Python grammar

The specification below — in EBNF — uses whitespace to delimit control flow blocks (following the off-side rule).


 * The symbol "::=" serves the same purpose as colon in Bison.
 * Parentheses group.
 * A trailing asterisk (*) indicates 0 or more repetitions.
 * A trailing plus indicates 1 or more repetitions.

program ::= instruction*

instruction ::= (arithmetic_instruction | loop_instruction) NEWLINE

arithmetic_instruction ::= inc_instruction       /* increment */ | clr_instruction       /* clear     */ | cpy_instruction       /* copy      */ | dec_instruction       /* decrement */

inc_instruction ::= register "++" clr_instruction ::= register "= 0" cpy_instruction ::= register "=" register dec_instruction ::= register "--"

loop_instruction ::= "loop" register ":" NEWLINE INDENT instruction+ DEDENT

register ::= char (char | digit)* char    ::= "A" | "B" | ... | "Z" | "_" | "a" | "b" | ... | "z" digit   ::= "0" | "1" | ... | "9" $$m$$ input registers are specified immediately above the program:


 * $$\text{// INPUT ( } \underbrace{\langle \operatorname{register} \rangle_{\scriptscriptstyle 1}, \langle \operatorname{register} \rangle_{\scriptscriptstyle 2}, \ldots, \langle \operatorname{register} \rangle_{\scriptscriptstyle m}}_{m \ge 0 \text{, repetitions allowed}} \text{ )}$$

$$n$$ output registers are specified immediately below the program:


 * $$\text{// OUTPUT ( } \underbrace{\langle \operatorname{register} \rangle_{\scriptscriptstyle 1}, \langle \operatorname{register} \rangle_{\scriptscriptstyle 2}, \ldots, \langle \operatorname{register} \rangle_{\scriptscriptstyle n}}_{n \ge 1 \text{, repetitions allowed}} \text{ )}$$

Semantics
Each register of a LOOP program may contain an arbitrary integer of $$\mathbb{N} = \{0, 1, 2, ...\}$$.

The instructions are executed sequentially in the order in which they occur. The instruction LOOP x { ... } causes the included code to be executed $$x$$ times in succession, where $$x$$ denotes the contents of the register x upon entering the loop.

Definition

A LOOP program P is said to compute a function $$f \colon \mathbb{N}^m \rightarrow \mathbb{N}^n$$, when
 * 1) $$\mathtt{INPUT}$$, considered as an m-tuple, specifies $$m$$ registers which contain the arguments of $$f (x_1, \ldots, x_m)$$; the remaining registers contain $$0$$;
 * 2) $$\mathtt{OUTPUT}$$, considered as an n-tuple, specifies $$n$$ registers;
 * 3) after the execution of P the output registers contain $$(y_1, \ldots, y_n) = f(x_1, \ldots, x_m)$$.

Remarks


 * When $$\mathtt{OUTPUT}$$ specifies a single register the program defines a scalar-valued function. Otherwise the program defines a vector-valued function.


 * Primitive recursive functions have the signature $$f \colon \mathbb{N}^m \rightarrow \mathbb{N}$$, i.e. they map n arguments to a scalar value. LOOP-programs define exactly the primitive recursive functions. By consequence a LOOP-program executes a primitive recursive function iff $$\mathtt{OUTPUT}$$ specifies exactly one register.


 * As any list of registers may be designated as input and output, in general a LOOP program can compute several functions, depending on the given mapping.


 * It is natural to extend the notion of primitive recursiveness to vector-valued functions.


 * Definition: A (vector-valued) function is primitive recursive iff it can be computed by a LOOP program.

Remark on the choice of arithmetic instructions The LOOP language has been defined by many authors. The definitions do not agree on the arithmetic instructions. The minimum requirement is that it must be possible to increment registers and to set them to zero. This is achieved by the instructions xi := xi + 1, and either xi := 0 or xi := xj.

From the instructions (1) and (2) the remaining instructions can be derived.

From the instructions (1) and (3) the remaining instructions can be derived.

No subroutines, but ...
Let P be any LOOP program.

Let $$f \colon \mathbb{N}^m \rightarrow \mathbb{N}^n$$ be a primitive recursive function. Then $$f$$ is computed by some LOOP program Q.

If P and Q do not share registers, Q can be inserted anywhere into P such that the programs do not affect each other.

The operation to rename the registers of Q is called alpha-conversion. This results in the program Q'.

Assume that P and Q' share no registers.

Wherever n registers of P need to be updated with the output of Q, given m registers of P as input, one can insert Q' into P and connect the input/output of Q' to the relevant registers of P. The resulting code is

One can allow as an extra arithmetic instruction the instruction to indicate that the LOOP program has computed f on the side, and copied the output to the registers (y1, y2, ..., yn). This is a short-hand notation to indicate that

added to the LOOP language the extra instruction Let P and Q be LOOP programs. can be patched into another loop program. The following workaround is possible.

Then P can be patched into a LOOP program Q, provided that
 * (to avoid name collision) the local registers of P and m new registers (like tmpx1, tmpx2, ..., tmpxm) are not mentioned in Q;
 * before the first line of P:
 * the registers x1, x2, ..., xm are backed up to tmpx1, tmpx2, ..., tmpxm respectively;
 * each register y1, y2, ..., yn is initialised to 0, if not mentioned in INPUT list;
 * each local register of P is initialised to 0;
 * after the last line of P:
 * the registers x1, x2, ..., xm are restored from tmpx1, tmpx2, ..., tmpxm respectively.

This simulates the behaviour of an activation record, as far as needed here.

We write

Addition
Addition is the hyperoperation function $$\operatorname{H_1}$$.

$$\operatorname{H_1}(x,y)$$ can be implemented by the LOOP program ADD( x, y )

INPUT  &#x251C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510; &#x250C;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510;   &#x2554;&#x2567;&#x2557; &#x2502;x = x + 1&#x2502;   &#x2551;y&#x2551; &#x2514;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518;   &#x255A;&#x2564;&#x255D; &#x251C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518; OUTPUT 

&#x2502; &#x2554;&#x2567;&#x2557; &#x2551;x&#x2551; &#x255A;&#x2564;&#x255D;

Assignment x = y without using type 3 instruction
If in the previous program — ADD — the register x is initialized to 0, the program copies the contents of register y to register x.

As the example shows the assignment instruction (x = y) can be removed from the list of arithmetic instructions without loss of expressive power.

Clearance x = 0 without using the type 2 instruction
If in the addition program — ADD — the register y holds the value 0 at start, the program sets register x to 0.

So one might remove all registers from INPUT.

As the example shows the assignment instruction (x = 0) can be removed from the list of arithmetic instructions without loss of expressive power.

ONZIN, x ZAL IMMERS NIET 0 ZIJN ???

Multiplication
Multiplication is the hyperoperation function $$\operatorname{H_2}$$.

$$\operatorname{H_2}(x,y)$$ can be computed by the LOOP program MULT( x, y )

The program uses the ADD program as a "convenience instruction". Expanded, the MULT program is a LOOP-program with two nested LOOP instructions. ADD counts for one.

More hyperoperators
Given a LOOP program for a hyperoperation function $$\operatorname{H_i}$$, one can construct a LOOP program for the next level.

$$\operatorname{H_3}(x,y)$$ for instance — exponentiation — can be implemented by the LOOP program POWER( x, y )

The exponentiation program, expanded, has three nested LOOP instructions.

Remark: To use MULT as a subroutine one has to take care of the clash of the variable z, which must have initial value 0 in MULT.

Predecessor
The predecessor function is defined as
 * $$\operatorname{pred}(n) = \begin{cases} 0 & \mbox{if }n=0, \\ n-1 & \mbox{otherwise}\end{cases}$$.

$$\operatorname{pred}$$ is computed by the built-in arithmetic  'dec_instruction' . This instruction could be dropped, as $$\operatorname{pred}$$ can be derived from  'cpy_instruction'  and  'inc_instruction' .

$$\operatorname{pred}$$ can also be derived from  'inc_instruction'  and  'clr_instruction' .

Remarks:
 * The reason to keep  'dec_instruction'  as an arithmetic instruction consists in the fact that $$\operatorname{pred}$$ cannot be programmed without wasting a LOOP in situations where a low LOOP nesting does matter.
 * If OUTPUT is set to (FirstTime) instead of to (x) the program computes the function
 * $$\operatorname{sgmin}(x) = \begin{cases} 1 & \mbox{if }x=0, \\ 0 & \mbox{otherwise}\end{cases}$$.

INPUT  &#x251C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510; &#x250C;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510;1         &#x2502; &#x2502;x = 0   &#x2502;           &#x2502; &#x2514;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518;          &#x2502; &#x251C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510;    &#x2502; &#x250C;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510;2  &#x2554;&#x2567;&#x2557;   &#x2554;&#x2567;&#x2557; &#x2502;x = x + 1&#x2502;   &#x2551;a&#x2551;   &#x2551;x&#x2551; &#x2514;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518;   &#x255A;&#x2564;&#x255D;   &#x255A;&#x2564;&#x255D; &#x251C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518;    &#x2502; &#x250C;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2510;3         &#x2502; &#x2502;a = a + 1&#x2502;          &#x2502; &#x2514;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518;          &#x2502; &#x251C;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2518; OUTPUT  This program can be used as a subroutine in other LOOP programs. The LOOP syntax can be extended with the following statement, equivalent to calling the above as a subroutine: x0 := x1 ∸ 1 Remark: Again one has to mind the side effects, see above

Direct sum of 2x3 matrix and 2x2 matrix
The direct sum (denoted by $$\oplus$$) of any pair of matrices A of size 2 &times; 3 and B of size 2 &times; 2 is a matrix C of size (2 + 2) &times; (3 + 2), defined as



\mathbf{A} \oplus \mathbf{B} = \begin{bmatrix} \mathbf{A} & \boldsymbol{0} \\ \boldsymbol{0} & \mathbf{B} \end{bmatrix} = \begin{bmatrix} a_{11} & a_{12} & a_{13} & 0 & 0 \\ a_{21} & a_{22} & a_{23} & 0 & 0 \\ 0     & 0      & 0      & b_{11} & b_{12} \\ 0     & 0      & 0      & b_{21} & b_{22} \end{bmatrix} $$ $$\mathbf{C} = \mathbf{A} \oplus \mathbf{B}$$ can be computed by an empty LOOP-program. The selection and the order of the input/output registers does the trick.

The 10-tuple < x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 > is designated as INPUT.

The input registers are associated with the matrices $$\mathbf{A}$$ and $$\mathbf{B}$$ as follows:

$$ \mathbf{A} = \begin{bmatrix} \text{x}_0 \leftarrow a_{11} & \text{x}_1 \leftarrow a_{12} & \text{x}_2 \leftarrow a_{13} \\ \text{x}_3 \leftarrow a_{21} & \text{x}_4 \leftarrow a_{22} & \text{x}_5 \leftarrow a_{23} \end{bmatrix} $$

$$ \mathbf{B} = \begin{bmatrix} \text{x}_6 \leftarrow b_{11} & \text{x}_7 \leftarrow b_{12} \\ \text{x}_8 \leftarrow b_{21} & \text{x}_9 \leftarrow b_{22} \end{bmatrix} $$

The 20-tuple < x0, x1, x2, x10, x11, x3, x4, x5, x12, x13, x14, x15, x16, x6, x7, x17, x18, x19, x8, x9 > is designated as OUTPUT.

The output registers are associated with the matrix $$\mathbf{C}$$ as follows:

$$ \mathbf{C} = \begin{bmatrix} \text{x}_0 \leftarrow c_{11} & \text{x}_1 \leftarrow c_{12} & \text{x}_2 \leftarrow c_{13} & \text{x}_{10} \leftarrow c_{14} & \text{x}_{11} \leftarrow c_{15} \\ \text{x}_3 \leftarrow c_{21} & \text{x}_4 \leftarrow c_{22} & \text{x}_5 \leftarrow c_{23} & \text{x}_{12} \leftarrow c_{24} & \text{x}_{13} \leftarrow c_{25} \\ \text{x}_{14} \leftarrow c_{31} & \text{x}_{15} \leftarrow c_{32} & \text{x}_{16} \leftarrow c_{33} & \text{x}_6 \leftarrow c_{34} & \text{x}_7 \leftarrow c_{35} \\ \text{x}_{17} \leftarrow c_{41} & \text{x}_{18} \leftarrow c_{42} & \text{x}_{19} \leftarrow c_{43} & \text{x}_8 \leftarrow c_{44} & \text{x}_9 \leftarrow c_{45} \end{bmatrix} $$

Remarks:
 * The function $$\oplus$$ is a vector-valued function.


 * Recall that a primitive recursive function $$f (x_1, \ldots, x_n)$$ maps its arguments to a scalar value. $$f \colon (\mathbb{N}_0)^n \rightarrow \mathbb{N}_0$$. Considering that LOOP-programs execute exactly the primitive recursive functions, it is natural to extend this notion to vector-valued functions $$f \colon (\mathbb{N}_0)^n \rightarrow (\mathbb{N}_0)^k$$ by the following

Definition: A (vector-valued) function is primitive recursive iff it can be implemented by a LOOP program.

Cut-off subtraction
If in the 'addition' program above the second loop decrements x0 instead of incrementing, the program computes the difference (cut off at 0) of the variables x1 and x2. x0 := x1 LOOP x2 DO x0 := x0 ∸ 1 END
 * 1)    x0 = x1
 * 2)    LOOP x2 DO
 * 3)        x0 = x0 ∸ 1
 * 4)    END

Remark



INPUT ⟨ x, y ⟩ LOOP y DO a := 0; LOOP x DO x := a;      a := a + 1; END END OUTPUT ⟨ x ⟩

Like before we can extend the LOOP syntax with the statement: x0 := x1 ∸ x2

If – then
The equality of two variables $$x$$ and $$y$$ is tested with the function
 * $$\operatorname{eq}(x, y) = \begin{cases} 1 & \mbox{if }x = y, \\ 0 & \mbox{otherwise}\end{cases}$$.

This function can be computed by the LOOP program

The control flow instruction ' if (x == y) then P' can then be simulated with

The steepest functions
Since the initial functions are all dominated by the successor function, iterations of it dominates all functions defined by iterations from the initial functions. Let $$h_i$$ be the (series of) functions



\begin{array}{lcl} h_{0}(x) & = & x+1 \\ h_{n+1}(x) & = & h_{n}^{x}(x) \\ \end{array} $$


 * where $$h_n^{x}$$ is the x-th iterate of $$h_n$$.

Consider any LOOP program P of length $$l>0$$. Then the function $$h_{l-1}(x)$$ dominates whatever function P might compute.

Also, on input $$x$$, P halts after the executions of at most $$h_{l-1}(x)$$ arithmetical imstructions. As LOOP programs have finite length, it follows that the generalized function $$H(n,x) = h_n(x)$$, an Ackermann function, cannot be computed by a LOOP program. This is a proof that the function $$H(n,x)$$ is not primitive recursive.

Example: the function $$h_4(x)$$ is computed by the following program of lenght 5: On input $$x > 1$$ no other LOOP program of length at most 5 can output a bigger number.

If the loop nesting $$k$$ is taken into account, then a more advantageous bounding function can be established.

Let $$c = \lceil \frac{l}{k+1} \rceil$$.

Then $$h_{k}^{c}$$ dominates whatever function any LOOP program P of length $$l$$ and maximal loop nesting $$k$$ might compute. The idea is that the program is chopped up into c subprograms each of which races to the max. Each subprogram takes as input the output of the preceding subprogram.

Example: If $$l = 7$$ and $$k = 2$$ then $$c = 3$$.

The structured program theorem
Consider the pseudocode listed in the strucured program article.

See and.

Marvin Minsky defined the following simple counter machine model, which is Turing complete. The instructions are INC ( r ): INCrement the constents of register r DEC ( r ): DECrement the constents of register r JZ ( r, z ): IF register r contains Zero THEN Jump to instruction z ELSE continue in sequence.

A so-called Program machine consists of a finite sequence of n instructions. It can be simulated by a while-program of the form

This rewriting procedure actually proves the folk version of the structured program theorem by [Bohm Jacopini, 1966].

The LOOP-language does not have the while-instruction. The replacement of the while-instruction by the instruction LOOP t results in a LOOP-program which does the same as the while-program but stops after t iterations.

proved that ...  xxx HIER VERDER 2