Link to the the Google Colaboratory notebook
pip install pyrampl
# To install from this notebook, run this cell.
%pip install pyrampl
# This should also work:
#!pip install --upgrade pyrampl
# After installation, you have to restart this notebook.
# Make sure to comment the %pip or !pip lines above to avoid reinstall each time you run this notebook.
# To uninstall the package use:
#%pip uninstall pyrampl
# or
#!pip uninstall pyrampl
Requirement already satisfied: pyrampl in d:\python\my_pkgs\pyrampl (1.3) Note: you may need to restart the kernel to use updated packages.
WARNING! Our current very early version of PyRamPL is not yet making good syntactical checks, so make sure to write your RAM programs correctly or else you will not get any meaningful feedback! Since RAM programs have a very simple syntax we do not expect this to be a real problem.

| Instruction | Description |
|---|---|
| $a=b$ | Load register $b$ to register $a$ |
| $a=i$ | Load integer $i$ to register $a$ |
| $a = b+c$ | Add $b$ and $c$ and store the result in $a$ |
| $a=b-c$ | Subtraction |
| $a = b * c$ | Multiplication |
| JUMP(i) | Jump to instruction i (PC = i) |
| JZERO(r, i) | If $r=0$ jump to instruction i |
| JPOS(r, i) | If $r>0$ jump to instruction i |
| JE(a, b, i) | If $a=b$ jump to instruction i |
| HALT | Stop the program |
</font>
The following RAM program computes the integer quotient and a remainder ($y_1$ and $y_2$) after dividing $x_1$ by $x_2$
PROGRAM DIVMOD(x1, x2 : y1, y2)
1. r1 = x1
2. r2 = x2
3. r0 = r2 - r1
4. JPOS(r0, 8)
5. r3 = r3 + 1
6. r1 = r1 - r2
7. JUMP(3)
8. y1 = r3
9. y2 = r1
10. HALT
DIVMOD we have also added
instruction labels that correspond to the RAM code (these are normally
not part of a flow diagram) to make it easier to comprehend the
RAM program.
from pyrampl import *
from IPython.display import display, Markdown, Latex
code = """
PROGRAM DIVMOD(x1, x2 : y1, y2)
1. r1 = x1
2. r2 = x2
3. r0 = r2 - r1
4. JPOS(r0, 8)
5. r3 = r3 + 1
6. r1 = r1 - r2
7. JUMP(3)
8. y1 = r3
9. y2 = r1
10. HALT
"""
DIVMOD = Ram("DIVMOD", code)
y1, y2 = DIVMOD(17,5)
print(f"Dividing 17 by 5 result: y1={y1}, y2={y2}")
Dividing 17 by 5 result: y1=3, y2=2
code,
and then create a Ram object by invoking the Ram Python class.Ram class accepts two arguments:DIVMOD = Ram("DIVMOD", "divmod.ram")
Ram objects.
Usually identical to their internal names.
code = """
PROGRAM EXP(x1, x2 : y1, y2)
1. r1 = x1
2. r2 = x2
3. JZERO(r1, 9)
4. r3 = 1
5. JZERO(r2, 14)
6. r3 = r3 * r1
7. r2 = r2 - 1
8. JUMP(5)
9. JZERO(r2, 12)
10. y1 = 0
11. JUMP(15)
12. y2 = 1
13. JUMP(15)
14. y1 = r3
15. HALT
"""
EXP version has two outputs $y_1$ and $y_2$EXP = Ram("EXP", code)
y1,y2 = EXP(2,5)
print(f"y1={y1}, y2={y2}")
y1=32, y2=0
y1,y2 = EXP(0,0)
print(f"y1={y1}, y2={y2}")
y1=0, y2=1
DIVMOD, we can use it as an instruction within
a new RAM machine.PRIME algorithm is using the DIVMOD instruction which we have defined above.
code = """
PROGRAM PRIME(x1 : y1)
1. y1 = 1
2. r1 = x1 - 3
3. JPOS(r1, 5)
4. HALT
5. r0 = 2
6. r1,r2 = DIVMOD(x1,r0)
7. JZERO(r2, 11)
8. r0 = r0 + 1
9. JE(r0, x1, 12)
10. JUMP(6)
11. y1 = 0
12. HALT
"""
PRIME = Ram("PRIME", code)
y = PRIME(19)
print(f"y={y}")
y=1
PRIME for the input $x_1=7$.display_table(PRIME, 7)
| Frame | Instruction | x1 | r0 | r1 | r2 | y1 |
|---|---|---|---|---|---|---|
| 0 | Init | 7 | 0 | 0 | 0 | 0 |
| 1 | 1. y1 = 1 | 7 | 0 | 0 | 0 | 1 |
| 2 | 2. r1 = x1 - 3 | 7 | 0 | 4 | 0 | 1 |
| 3 | 3. JPOS(r1, 5) | 7 | 0 | 4 | 0 | 1 |
| 4 | 5. r0 = 2 | 7 | 2 | 4 | 0 | 1 |
| 5 | 6. r1,r2 = DIVMOD(x1,r0) | 7 | 2 | 3 | 1 | 1 |
| 6 | 7. JZERO(r2, 11) | 7 | 2 | 3 | 1 | 1 |
| 7 | 8. r0 = r0 + 1 | 7 | 3 | 3 | 1 | 1 |
| 8 | 9. JE(r0, x1, 12) | 7 | 3 | 3 | 1 | 1 |
| 9 | 10. JUMP(6) | 7 | 3 | 3 | 1 | 1 |
| 10 | 6. r1,r2 = DIVMOD(x1,r0) | 7 | 3 | 2 | 1 | 1 |
| 11 | 7. JZERO(r2, 11) | 7 | 3 | 2 | 1 | 1 |
| 12 | 8. r0 = r0 + 1 | 7 | 4 | 2 | 1 | 1 |
| 13 | 9. JE(r0, x1, 12) | 7 | 4 | 2 | 1 | 1 |
| 14 | 10. JUMP(6) | 7 | 4 | 2 | 1 | 1 |
| 15 | 6. r1,r2 = DIVMOD(x1,r0) | 7 | 4 | 1 | 3 | 1 |
| 16 | 7. JZERO(r2, 11) | 7 | 4 | 1 | 3 | 1 |
| 17 | 8. r0 = r0 + 1 | 7 | 5 | 1 | 3 | 1 |
| 18 | 9. JE(r0, x1, 12) | 7 | 5 | 1 | 3 | 1 |
| 19 | 10. JUMP(6) | 7 | 5 | 1 | 3 | 1 |
| 20 | 6. r1,r2 = DIVMOD(x1,r0) | 7 | 5 | 1 | 2 | 1 |
| 21 | 7. JZERO(r2, 11) | 7 | 5 | 1 | 2 | 1 |
| 22 | 8. r0 = r0 + 1 | 7 | 6 | 1 | 2 | 1 |
| 23 | 9. JE(r0, x1, 12) | 7 | 6 | 1 | 2 | 1 |
| 24 | 10. JUMP(6) | 7 | 6 | 1 | 2 | 1 |
| 25 | 6. r1,r2 = DIVMOD(x1,r0) | 7 | 6 | 1 | 1 | 1 |
| 26 | 7. JZERO(r2, 11) | 7 | 6 | 1 | 1 | 1 |
| 27 | 8. r0 = r0 + 1 | 7 | 7 | 1 | 1 | 1 |
| 28 | 9. JE(r0, x1, 12) | 7 | 7 | 1 | 1 | 1 |
| 29 | 12. HALT | 7 | 7 | 1 | 1 | 1 |
display_table(EXP, 5, 2)
| Frame | Instruction | x1 | x2 | r1 | r2 | r3 | y1 | y2 |
|---|---|---|---|---|---|---|---|---|
| 0 | Init | 5 | 2 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1. r1 = x1 | 5 | 2 | 5 | 0 | 0 | 0 | 0 |
| 2 | 2. r2 = x2 | 5 | 2 | 5 | 2 | 0 | 0 | 0 |
| 3 | 3. JZERO(r1, 9) | 5 | 2 | 5 | 2 | 0 | 0 | 0 |
| 4 | 4. r3 = 1 | 5 | 2 | 5 | 2 | 1 | 0 | 0 |
| 5 | 5. JZERO(r2, 14) | 5 | 2 | 5 | 2 | 1 | 0 | 0 |
| 6 | 6. r3 = r3 * r1 | 5 | 2 | 5 | 2 | 5 | 0 | 0 |
| 7 | 7. r2 = r2 - 1 | 5 | 2 | 5 | 1 | 5 | 0 | 0 |
| 8 | 8. JUMP(5) | 5 | 2 | 5 | 1 | 5 | 0 | 0 |
| 9 | 5. JZERO(r2, 14) | 5 | 2 | 5 | 1 | 5 | 0 | 0 |
| 10 | 6. r3 = r3 * r1 | 5 | 2 | 5 | 1 | 25 | 0 | 0 |
| 11 | 7. r2 = r2 - 1 | 5 | 2 | 5 | 0 | 25 | 0 | 0 |
| 12 | 8. JUMP(5) | 5 | 2 | 5 | 0 | 25 | 0 | 0 |
| 13 | 5. JZERO(r2, 14) | 5 | 2 | 5 | 0 | 25 | 0 | 0 |
| 14 | 14. y1 = r3 | 5 | 2 | 5 | 0 | 25 | 25 | 0 |
| 15 | 15. HALT | 5 | 2 | 5 | 0 | 25 | 25 | 0 |
display_table(DIVMOD, 18, 5)
| Frame | Instruction | x1 | x2 | r0 | r1 | r2 | r3 | y1 | y2 |
|---|---|---|---|---|---|---|---|---|---|
| 0 | Init | 18 | 5 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1. r1 = x1 | 18 | 5 | 0 | 18 | 0 | 0 | 0 | 0 |
| 2 | 2. r2 = x2 | 18 | 5 | 0 | 18 | 5 | 0 | 0 | 0 |
| 3 | 3. r0 = r2 - r1 | 18 | 5 | -13 | 18 | 5 | 0 | 0 | 0 |
| 4 | 4. JPOS(r0, 8) | 18 | 5 | -13 | 18 | 5 | 0 | 0 | 0 |
| 5 | 5. r3 = r3 + 1 | 18 | 5 | -13 | 18 | 5 | 1 | 0 | 0 |
| 6 | 6. r1 = r1 - r2 | 18 | 5 | -13 | 13 | 5 | 1 | 0 | 0 |
| 7 | 7. JUMP(3) | 18 | 5 | -13 | 13 | 5 | 1 | 0 | 0 |
| 8 | 3. r0 = r2 - r1 | 18 | 5 | -8 | 13 | 5 | 1 | 0 | 0 |
| 9 | 4. JPOS(r0, 8) | 18 | 5 | -8 | 13 | 5 | 1 | 0 | 0 |
| 10 | 5. r3 = r3 + 1 | 18 | 5 | -8 | 13 | 5 | 2 | 0 | 0 |
| 11 | 6. r1 = r1 - r2 | 18 | 5 | -8 | 8 | 5 | 2 | 0 | 0 |
| 12 | 7. JUMP(3) | 18 | 5 | -8 | 8 | 5 | 2 | 0 | 0 |
| 13 | 3. r0 = r2 - r1 | 18 | 5 | -3 | 8 | 5 | 2 | 0 | 0 |
| 14 | 4. JPOS(r0, 8) | 18 | 5 | -3 | 8 | 5 | 2 | 0 | 0 |
| 15 | 5. r3 = r3 + 1 | 18 | 5 | -3 | 8 | 5 | 3 | 0 | 0 |
| 16 | 6. r1 = r1 - r2 | 18 | 5 | -3 | 3 | 5 | 3 | 0 | 0 |
| 17 | 7. JUMP(3) | 18 | 5 | -3 | 3 | 5 | 3 | 0 | 0 |
| 18 | 3. r0 = r2 - r1 | 18 | 5 | 2 | 3 | 5 | 3 | 0 | 0 |
| 19 | 4. JPOS(r0, 8) | 18 | 5 | 2 | 3 | 5 | 3 | 0 | 0 |
| 20 | 8. y1 = r3 | 18 | 5 | 2 | 3 | 5 | 3 | 3 | 0 |
| 21 | 9. y2 = r1 | 18 | 5 | 2 | 3 | 5 | 3 | 3 | 3 |
| 22 | 10. HALT | 18 | 5 | 2 | 3 | 5 | 3 | 3 | 3 |
DIVMOD machine which we defined earlier
in two different places (re rectangles)
code = """
PROGRAM GCD(x1, x2 : y1)
1. r1 = x1
2. r2 = x2
3. JZERO(r1, 11)
4. JZERO(r2, 13)
5. r0 = r1 - r2
6. JPOS(r0, 15)
7. r0 = r2 - r1
8. JPOS(r0, 17)
9. y1 = r1
10. HALT
11. y1 = r2
12. HALT
13. y1 = r1
14. HALT
15. r3, r1 = DIVMOD(r1, r2)
16. JUMP(3)
17. r3, r2 = DIVMOD(r2, r1)
18. JUMP(4)
19. HALT
"""
GCD = Ram("GCD", code)
y = GCD(72,54)
print(f"The greatest common divisor of 72 and 54 is {y}")
The greatest common divisor of 72 and 54 is 18
code = """
PROGRAM MAX4(x1, x2, x3, x4 : y1)
1. y1 = x1
2. r0 = y1 - x2
3. JPOS(r0,5)
4. y1 = x2
5. r0 = y1 - x3
6. JPOS(r0,8)
7. y1 = x3
8. r0 = y1 - x4
9. JPOS(r0,11)
10. y1 = x4
11. HALT
"""
MAX4 = Ram("MAX4", code)
MAX4(2, 26, 9, 4)
26
GETBIT and SETBIT are important for simulating a Turing machine by a RAM machine.GETBIT functions extracts the binary bit of an integer at a given place.SETBIT function sets the bit of an integer at a given location.
code1 = """
PROGRAM GETBIT(x1, x2 : y1)
1. r1 = x1
2. r2 = x2
3. r1,r0 = DIVMOD(r1, 2)
4. JZERO(r2, 7)
5. r2 = r2 -1
6. JUMP(3)
7. y1 = r0
8. HALT
"""
code2 = """
PROGRAM SETBIT(x1, x2, x3 : y1)
1. r0 = GETBIT(x1, x2)
2. JE(r0, x3, 9)
3. r1,r2 = EXP(2, x2)
4. JPOS(x3, 7)
5. y1 = x1 - r1
6. HALT
7. y1 = x1 + r1
8. HALT
9. y1 = x1
10. HALT
"""
GETBIT = Ram("GETBIT", code1)
SETBIT = Ram("SETBIT", code2)
y1 = SETBIT(41, 2, 1)
print(y1)
45
display_table(SETBIT,9, 2, 1)
| Frame | Instruction | x1 | x2 | x3 | r0 | r1 | r2 | y1 |
|---|---|---|---|---|---|---|---|---|
| 0 | Init | 9 | 2 | 1 | 0 | 0 | 0 | 0 |
| 1 | 1. r0 = GETBIT(x1, x2) | 9 | 2 | 1 | 0 | 0 | 0 | 0 |
| 2 | 2. JE(r0, x3, 9) | 9 | 2 | 1 | 0 | 0 | 0 | 0 |
| 3 | 3. r1,r2 = EXP(2, x2) | 9 | 2 | 1 | 0 | 4 | 0 | 0 |
| 4 | 4. JPOS(x3, 7) | 9 | 2 | 1 | 0 | 4 | 0 | 0 |
| 5 | 7. y1 = x1 + r1 | 9 | 2 | 1 | 0 | 4 | 0 | 13 |
| 6 | 8. HALT | 9 | 2 | 1 | 0 | 4 | 0 | 13 |
DIVMOD.init(17,5)
DIVMOD.run()
frames = DIVMOD.frames
for ic,instruction,vardict in frames:
y1 = vardict['y1']
y2 = vardict['y2']
print(f"{ic:<5} {instruction:<20} y1={y1} y2={y2}")
0 Init y1=0 y2=0 1 1. r1 = x1 y1=0 y2=0 2 2. r2 = x2 y1=0 y2=0 3 3. r0 = r2 - r1 y1=0 y2=0 4 4. JPOS(r0, 8) y1=0 y2=0 5 5. r3 = r3 + 1 y1=0 y2=0 6 6. r1 = r1 - r2 y1=0 y2=0 7 7. JUMP(3) y1=0 y2=0 8 3. r0 = r2 - r1 y1=0 y2=0 9 4. JPOS(r0, 8) y1=0 y2=0 10 5. r3 = r3 + 1 y1=0 y2=0 11 6. r1 = r1 - r2 y1=0 y2=0 12 7. JUMP(3) y1=0 y2=0 13 3. r0 = r2 - r1 y1=0 y2=0 14 4. JPOS(r0, 8) y1=0 y2=0 15 5. r3 = r3 + 1 y1=0 y2=0 16 6. r1 = r1 - r2 y1=0 y2=0 17 7. JUMP(3) y1=0 y2=0 18 3. r0 = r2 - r1 y1=0 y2=0 19 4. JPOS(r0, 8) y1=0 y2=0 20 8. y1 = r3 y1=3 y2=0 21 9. y2 = r1 y1=3 y2=2 22 10. HALT y1=3 y2=2
for ic,instruction,vardict in frames:
r0 = vardict['r0']
r1 = vardict['r1']
r2 = vardict['r2']
r3 = vardict['r3']
print(f"ic={ic:<4} : {instruction:<16} : r0 ={r0:<3} : r1 = {r1:<3} : r2 = {r2:<3} : r3 = {r3:<3}")
ic=0 : Init : r0 =0 : r1 = 0 : r2 = 0 : r3 = 0 ic=1 : 1. r1 = x1 : r0 =0 : r1 = 17 : r2 = 0 : r3 = 0 ic=2 : 2. r2 = x2 : r0 =0 : r1 = 17 : r2 = 5 : r3 = 0 ic=3 : 3. r0 = r2 - r1 : r0 =-12 : r1 = 17 : r2 = 5 : r3 = 0 ic=4 : 4. JPOS(r0, 8) : r0 =-12 : r1 = 17 : r2 = 5 : r3 = 0 ic=5 : 5. r3 = r3 + 1 : r0 =-12 : r1 = 17 : r2 = 5 : r3 = 1 ic=6 : 6. r1 = r1 - r2 : r0 =-12 : r1 = 12 : r2 = 5 : r3 = 1 ic=7 : 7. JUMP(3) : r0 =-12 : r1 = 12 : r2 = 5 : r3 = 1 ic=8 : 3. r0 = r2 - r1 : r0 =-7 : r1 = 12 : r2 = 5 : r3 = 1 ic=9 : 4. JPOS(r0, 8) : r0 =-7 : r1 = 12 : r2 = 5 : r3 = 1 ic=10 : 5. r3 = r3 + 1 : r0 =-7 : r1 = 12 : r2 = 5 : r3 = 2 ic=11 : 6. r1 = r1 - r2 : r0 =-7 : r1 = 7 : r2 = 5 : r3 = 2 ic=12 : 7. JUMP(3) : r0 =-7 : r1 = 7 : r2 = 5 : r3 = 2 ic=13 : 3. r0 = r2 - r1 : r0 =-2 : r1 = 7 : r2 = 5 : r3 = 2 ic=14 : 4. JPOS(r0, 8) : r0 =-2 : r1 = 7 : r2 = 5 : r3 = 2 ic=15 : 5. r3 = r3 + 1 : r0 =-2 : r1 = 7 : r2 = 5 : r3 = 3 ic=16 : 6. r1 = r1 - r2 : r0 =-2 : r1 = 2 : r2 = 5 : r3 = 3 ic=17 : 7. JUMP(3) : r0 =-2 : r1 = 2 : r2 = 5 : r3 = 3 ic=18 : 3. r0 = r2 - r1 : r0 =3 : r1 = 2 : r2 = 5 : r3 = 3 ic=19 : 4. JPOS(r0, 8) : r0 =3 : r1 = 2 : r2 = 5 : r3 = 3 ic=20 : 8. y1 = r3 : r0 =3 : r1 = 2 : r2 = 5 : r3 = 3 ic=21 : 9. y2 = r1 : r0 =3 : r1 = 2 : r2 = 5 : r3 = 3 ic=22 : 10. HALT : r0 =3 : r1 = 2 : r2 = 5 : r3 = 3