Unification algorithm example in WAM (Warren's Abstract Machine) - algorithm

Exercise 2.2 in Warren's Abstract Machine: A Tutorial Reconstruction
asks for representations for the terms f(X, g(X, a)) and f(b, Y) and then to perform unification on the address of these terms (denoted a1 and a2 respectively).
I've constructed the heap representations for the terms, and they are as follows:
f(X, g(X, a)):
0 STR 1
1 a/0
2 STR 3
3 g/2
4 REF 4
5 STR 1
6 STR 7
7 f/2
8 REF 4
9 STR 3
f(b, Y):
10 STR 11
11 b/0
12 STR 7
13 STR 11
14 REF 14
and I am now asked to trace unify(a1, a2), but following the algorithm on page 20 in 1 I get:
d1 = deref(a1) = deref(10) = 10
d2 = deref(a2) = deref(0) = 0
0 != 10 so we continue
<t1, v1> = STORE(d1) = STORE(10) = <STR, 11>
<t2, v2> = STORE(d2) = STORE(0) = <STR, 1>
t1 != REF and t2 != REF so we continue
f1 / n1 = STORE(v1) = STORE(11) = b / 0
f2 / n2 = STORE(v2) = STORE(1) = a / 0
and now b != a so the algorithm terminated with fail = true,
and thus unification failed, but obviously there exists
a solution with X = b and Y = g(b, a).
Where is my mistake?

I found the solution myself. Here's my corrections:
Each term should have their own definitions of the functors (ie. the f-functor in the second term should not just link to the first f-functor in the first term, but should have its own) and pointers to the terms (a1 and a2) should point to the outermost term functor.
This means that a1 = 6 and a2 = 12 in the following layout
f(X, g(X, a)):
0 STR 1
1 a/0
2 STR 3
3 g/2
4 REF 4
5 STR 1
6 STR 7
7 f/2
8 REF 4
9 STR 3
f(b, Y):
10 STR 11
11 b/0
12 STR 13
13 f/2
14 REF 11
15 REF 15

Related

How to build special turing machine

Good day. I have a question. Many people are familiar with the Turing machine. The following task arose, which I can’t solve for a long time: there is an alphabet consisting of the letters "X", "Y" "Z", if the number of letters "Z" in the word is exactly 2 more than the letters "X", replace the second letter "Z" with "X". Otherwise, leave the word unchanged. Considering that I cannot change the original word and the tape is infinite (that is, I cannot write an infinite number of states for the machine), I do not understand how to do this.
Just to make it more clear, if the input is for example:
XXXYZZZZZ
then the output you need is:
XXXYZXZZZZ
And if the input is:
XXYZZ
Then everything needs to stay the same, since (number of Z's) - (number of X's) != 2
XXYZZ
If I understood the problem correctly, in the way I defined above, then here comes the solution with Morphett's TM Simulator, with $ sign as left-end marker:
1 $ $ r 1
1 X A r 2
1 Y Y r 4
2 X X r 2
2 B B r 2
2 Y Y r 2
2 Z B R 3
3 Y Y l 3
3 B B l 3
3 X X l 3
3 A A r 1
3 Z Z l 3
4 Y Y r 4
4 B B r 4
4 Z B r 5
4 _ _ l 7
5 Z B r 6
5 _ _ l 7
6 Z Z l 7
6 _ _ l 8
7 B Z l 7
7 Y Y l 7
7 A X l 7
7 $ $ r 12
8 B Z l 8
8 Y Y l 8
8 A X l 8
8 $ $ r 9
9 X X r 9
9 Y Y r 9
9 Z Z r 10
10 Z X r 11
11 Z Z r 11
11 _ _ l halt
12 X X r 12
12 Y Y r 12
12 Z Z r 12
12 _ _ l halt
Copy this code and then paste it to http://morphett.info/turing/turing.html
From advanced options, set initial state to 1 from 0.
Do not forget to add a "$" to beginning of every input.

Algorithm for progressive matrix

I want to construct a matrix like so:
[ 0 1 2 3 4 5 ....
1 2 3 4 5 6 ....
2 3 4 5 6 7 ....
3 4 5 6 7 8 ....
4 5 6 7 8 9 ....
5 6 7 8 9 10 ... ] etc
The main goal is to use the algorithm to put to the power the elements of an already existing matrix.
I am programming in Fortran, and I used the following code but it's not working:
do i = 1, m+1
do j = 1, m+1
do while ( w < 2*m )
if ( i > j ) then
ma(i,j) = 0
else
w = i-1
ma(i, j) = w
w = w +1
end if
end do
end do
end do
I suggest you to use an implied-do in the array constructor syntax, possibly initialized in the same declaration:
integer, parameter :: n = 10, m = 5
integer :: i, j
integer :: ma(m,n) = reshape([((i+j, j=0, m-1), i=0, n-1)], [m,n])
The [...] syntax is posible in Fortran 2003 or higher. (/.../) should be used otherwise. My result with gfortran v7.1.1 is:
do i = 1, m
print *, ma(i, :)
end do
$gfortran test.f90 -o main
$main
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 10
2 3 4 5 6 7 8 9 10 11
3 4 5 6 7 8 9 10 11 12
4 5 6 7 8 9 10 11 12 13
Note: The initialization in the declaration would only be possible if n and m are constants (parameter). You could initialize it normally in the program body, otherwise, with the same implied-do syntax.
If you plan to read the values of m and n at runtime, you should make ma an allocatable array.
While there is nothing wrong with Rodrigo's answer personally I think it much clearer to just use two loops
ian#eris:~/work/stackoverflow$ cat floyd.f90
Program yes
Implicit None
Integer, Parameter :: n = 5
Integer, Dimension( 1:n, 1:n ) :: elp
Integer :: base, offset
Integer :: i, j
Do i = 1, n
base = i - 1
Do j = 1, n
offset = j - 1
elp( j, i ) = base + offset
End Do
End Do
Do j = 1, n
Write( *, '( 1000( i3, 1x ) )' ) elp( j, : )
End Do
End Program yes
ian#eris:~/work/stackoverflow$ gfortran -Wall -Wextra -std=f2003 -fcheck=all -O floyd.f90 -o genesis
ian#eris:~/work/stackoverflow$ ./genesis
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
I've seen that others already made an algorithm that solves your problem. But i also bring another algorithm that works for a non-square matrix. NI is the number of columns of the matrix, and NJ is the number of lines. MAT is the matrix you want.
PROGRAM MATRIX
IMPLICIT NONE
INTEGER :: I, J, NI, NJ
INTEGER, ALLOCATABLE :: MAT(:,:)
NI = 8
NJ = 5
ALLOCATE(MAT(NI,NJ))
DO I = 1, NI
MAT(I,1) = I-1
ENDDO
DO J = 2,NJ
MAT(:,J) = MAT(:,J-1) + 1
ENDDO
DO J = 1, NJ
WRITE(*,'(8I3)') MAT(:,J)
ENDDO
END PROGRAM
Thanks for the feedback, I managed to do it using the following code:
do i = 1, m+1
w = i-1
do j = 1, m+1
ma(i, j) = u**w
w = w+1
end do
end do
I would like to state that i'm using Fortran 90 and only 90 because of my circumstances, otherwise I would've went with c++, (university life !!).
Please note that I used the desired series to put to the power the elements of the matrix.
Finally, I noticed some "complex" answers maybe, or maybe I'm just a beginner, but i would really love to learn if there are some rules and or dos and don'ts and or advice to get better at coding ( scientific code, not development code).
Thank you very much for the feed back, and waiting for any responses.

Given 5 numbers, by only using addition multiplication and substraction check whether we can generate 42?

Given five numbers between 1-52 check whether you can generate 42 by using operations addition, multiplication and subtraction. You can use these operations any number of times.
I got this question during an online test and couldn't do it.
Assuming each number is to be used once and once only, with only five numbers and three operations, you can quite easily do this with a brute force approach.
It will only have to check 5 * 3 * 4 * 3 * 3 * 3 * 2 * 3 * 1, or about 10,000 potential solutions.
As proof-of-concept, here's a Python program for doing this:
import sys
import itertools
if len(sys.argv) != 6:
print "Usage: testprog.py <num1> <num2> <num3> <num4> <num5>"
sys.exit(1)
ops = ['+', '-', '*']
nums = []
for num in sys.argv[1:]:
nums.append(num)
for p in itertools.permutations(nums,len(nums)):
for op1 in ops:
for op2 in ops:
for op3 in ops:
for op4 in ops:
expr = p[0] + op1 + p[1] + op2 + p[2] + op3 + p[3] + op4 + p[4]
result = eval(expr)
if result == 42:
print expr, '=', result
Running that shows the results for the numbers { 1, 2, 3, 4, 5 }:
pax$ time python testprog.py 1 2 3 4 5
2*4*5-1+3 = 42
2*4*5+3-1 = 42
2*5*4-1+3 = 42
2*5*4+3-1 = 42
:
5*4*2-1+3 = 42
5*4*2+3-1 = 42
real 0m0.187s
user 0m0.093s
sys 0m0.077s
and you can see that it completes in about a fifth of a second (on my box).
assumtions:
any number may be used multiple times
operations are done immediately (no operator precedence)
do a breadth first search over the graph
from collections import defaultdict
def add(lhs, rhs):
return lhs+rhs
def sub(lhs, rhs):
return lhs-rhs
def mul(lhs, rhs):
return lhs*rhs
ops = [add, sub, mul] #allowed operations
graph = { 0:["0"]} #graph key is node(number); value is a list of shortest paths to this node
numbers=[1,2,3] #allowed numbers in operations
target=12 #target node(number)
gv_edges=[] #edges for optional graphviz output
#breadth first search until target is met
while not target in graph:
new_graph=defaultdict(list, graph)
for key in graph:
#inefficiently searches old nodes also
for n in numbers:
for op in ops:
newkey = op(key, n)
if newkey not in graph:
#not met in previous iterations, keep new edge
newvals = ["{} --{}({})--> {}".format(val, op.__name__, n, newkey) for val in new_graph[key]]
new_graph[newkey].extend(newvals)
gv_edges.append('"{}" -> "{}" [label="{}({})"]'.format(key, newkey, op.__name__, n))
else:
#already met in previous iterations (shorter paths), do not keep new
pass
graph=dict(new_graph)
#print all solutions
print "Solutions:"
print
for val in graph[target]:
print val
print
print
#print optional graphviz digraph
gv_digraph='digraph {{ rankdir=LR ranksep=2\n"{}" [color=green style=filled fillcolor=green]\n{}\n}}'.format(target,"\n".join(gv_edges))
print "Graphviz Digraph for paste into http://stamm-wilbrandt.de/GraphvizFiddle/"
print "do this for reasonable number of edges only"
print
print gv_digraph
results in the following solutions:
0 --add(1)--> 1 --add(3)--> 4 --mul(3)--> 12
0 --add(2)--> 2 --add(2)--> 4 --mul(3)--> 12
0 --add(2)--> 2 --mul(2)--> 4 --mul(3)--> 12
0 --add(3)--> 3 --add(1)--> 4 --mul(3)--> 12
0 --add(2)--> 2 --mul(3)--> 6 --mul(2)--> 12
0 --add(3)--> 3 --mul(2)--> 6 --mul(2)--> 12
0 --add(3)--> 3 --add(3)--> 6 --mul(2)--> 12
0 --add(3)--> 3 --mul(3)--> 9 --add(3)--> 12
the complete graph (only shortest paths!) for depth 3 looks like

Transpose and reshape a 3d array in matlab

Suppose I have an array X of size n by p by q. I would like to reshape it as a matrix with p rows, and in each row put the concatenation of the n rows of size q, resulting in a matrix of size p by nq.
I managed to do it with a loop but it takes a while say if n=1000, p=300, q=300.
F0=[];
for k=1:size(F,1)
F0=[F0,squeeze(X(k,:,:))];
end
Is there a faster way?
I think this is what you want:
Y = reshape(permute(X, [2 1 3]), size(X,2), []);
Example with n=2, p=3, q=4:
>> X
X(:,:,1) =
0 6 9
8 3 0
X(:,:,2) =
4 7 1
3 7 4
X(:,:,3) =
4 7 2
6 7 6
X(:,:,4) =
6 1 9
1 4 3
>> Y = reshape(permute(X, [2 1 3]), size(X,2), [])
Y =
0 8 4 3 4 6 6 1
6 3 7 7 7 7 1 4
9 0 1 4 2 6 9 3
Try this -
reshape(permute(X,[2 3 1]),p,[])
Thus, for code verification, one can look into a sample case run -
n = 2;
p = 3;
q = 4;
X = rand(n,p,q)
F0=[];
for k=1:n
F0=[F0,squeeze(X(k,:,:))];
end
F0
F0_noloop = reshape(permute(X,[2 3 1]),p,[])
Output is -
F0 =
0.4134 0.6938 0.3782 0.4775 0.2177 0.0098 0.7043 0.6237
0.1257 0.8432 0.7295 0.2364 0.3089 0.9223 0.2243 0.1771
0.7261 0.7710 0.2691 0.8296 0.7829 0.0427 0.6730 0.7669
F0_noloop =
0.4134 0.6938 0.3782 0.4775 0.2177 0.0098 0.7043 0.6237
0.1257 0.8432 0.7295 0.2364 0.3089 0.9223 0.2243 0.1771
0.7261 0.7710 0.2691 0.8296 0.7829 0.0427 0.6730 0.7669
Rather than using vectorization to solve the problem, you could look at the code to try and figure out what may improve performance. In this case, since you know the size of your output matrix F0 should be px(n*q), you could pre-allocate memory to F0 and avoid the constant resizing of the matrix at each iteration of the for loop
n=1000;
p=300;
q=300;
F0=zeros(p,n*q);
for k=1:size(F,1)
F0(:,(k-1)*q+1:k*q) = squeeze(F(k,:,:));
end
While probably not as efficient as the other two solutions, it is an alternative. Try the above and see what happens!

Bitwise modulus computation

Given two numbers a and b where b is of form 2k where k is unknown.What would be the efficient way of computing a%b using bitwise operator.
a AND (b-1) == a%b (when b is 2^k)
ex. a = 11 (1011b), b = 4 (0100b)
11 / 4 = 2 R3
11 % 4 == 11 AND (4-1)
11 (1011b) AND 3 (0011b) == 3 (0011b)

Resources