Recursion and basecase in prolog - recursion

I have a function which I can not get to run correctly and I cant figure out why. I think it may have to do with the base case.
This is what I have:
recursion(Start, [Tail|Tails], [Alpha|Alphas], Beta, [X|Xs]):-
third(Start, Alpha, S),
second(S,Beta,Tail,X),
recursion(Start, Tails, Alphas, Beta,Xs).
recursion([],[],[],_,[]).
I know that the second function works correctly but when I run this:
recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, X).
I get:
T Call: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G3980)
T Fail: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G3980)
false.
My other predicates can be found:
second(A,B,_,1) :- A > B.
second(A,B,C,C) :- A == B.
second(A,B,_,-1) :- A < B.
third([A|As], [B|Bs], X) :-
third(As, Bs, Z),
X is Z + A* B.
third([],[],0).
UPDATE:
Start and Tail will both be the exact same list entered into the predicate. Thats why in the example they are both [1,2]. When I change my base case to recursion(_,[],[],_,[]). I get:
98 ?- recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, X).
T Call: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G1632)
T Redo: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G1632)
T Fail: (6) recursion([1, 2], [1, 2], [[1, 1], [2, 2]], 0, _G1632)
false.
Any ideas?

Your base case is not getting accessed because Start is passed to recursion unchanged. Therefore, it will never unify with the empty list, meaning that only the first clause of recursion will be used.
It does not look like Start is being used in your function, so you might either ignore it, like that
recursion(_, [],[],_,[]).
or remove it altogether, like this:
recursion([Tail|Tails], [Alpha|Alphas], Beta, [X|Xs]):-
second(5,Beta,Tail,X),
recursion(Tails, Alphas, Beta,Xs).
recursion([],[],_,[]).

Related

Julia JuMP: define a multidimensional variable when a dimension depends on other dimension

While I am defining a linear programming variables, I have to consider
index_i = 1:3 index_j = J = [1:2, 1:5, 1:3]
I want to define a variable x indexed with both i and j such that i is {1,2,3} and j is in {1,2} if i is 1, {1,2,3,4,5} if i is 2 and {1,2,3} if i is 3.
I tried several syntaxes but non of them delivered it successfully. Any suggestion?
I wonder why this is not working
#variable(m, e[i for i in I, j for j in J[i]])
I m expecting a result like this
e[1,1]
e[1,2]
e[1,3]
e[2,1]
e[2,2]
e[2,3]
e[2,4]
e[2,5]
e[3,1]
e[3,2]
e[3,3]
Assuming I=1:3 and J=[1:2, 1:5, 1:3]
you can do:
julia> #variable(m, e[i in I, j in J[i]])
JuMP.Containers.SparseAxisArray{VariableRef, 2, Tuple{Int64, Int64}} with 10 entries:
[1, 1] = e[1,1]
[1, 2] = e[1,2]
[2, 1] = e[2,1]
[2, 2] = e[2,2]
[2, 3] = e[2,3]
[2, 4] = e[2,4]
[2, 5] = e[2,5]
[3, 1] = e[3,1]
[3, 2] = e[3,2]
[3, 3] = e[3,3]

how can i separate between two arrays inside a parent array

this code is a small example of what i want to do, i have this small example right here:
y=[[[1,0],[0,0],[1,1],[1,0],[1,0],[0,1]],[[1,0],[0,0],[1,1],[0,0]],[[1,0],[0,0],[1,1],[1,0],[1,0],[1,0]]]
array=[]
all_array=[]
for i in 1:length(y)
for j in 1: length(y[i])
if y[i][j]==[1,0]
push!(array,y[i][j])
end
end
end
what i'm expecting when you return array is this :
[[[1,0],[1,0],[1,0]],[[1,0]],[[1,0],[1,0],[1,0],[1,0]]]
which is 3-element Array{Array{Array{Int64,1},1},1}
but instead i get this:
8-element Array{Any,1}:
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
[1, 0]
i don't know what i'm missing here.
You are pushing all the elements that satisfy your condition one after another in array. You could create your array instead like:
julia> array=[[],[],[]]
And modify your loop to push! into each subarray array[i] like this:
julia> for i in 1:length(y)
for j in 1: length(y[i])
if y[i][j]==[1,0]
push!(array[i],y[i][j])
end
end
end
Which then gives you your desired array.
julia> array
3-element Array{Array{Any,1},1}:
[[1, 0], [1, 0], [1, 0]]
[[1, 0]]
[[1, 0], [1, 0], [1, 0], [1, 0]]

Walking through multidimensional space in a proper way

Assuming I have a vector of say four dimensions in which every variable lays in a special interval. Thus we got:
Vector k = (x1,x2,x3,x4) with x1 = (-2,2), x2 = (0,2), x3 = (-4,1), x4 = (-1,1)
I am only interested in the points constraint by the intervals.
So to say v1 = (0,1,2,0) is important where v2 = (-5,-5,5,5) is not.
In additon to that the point i+1 should be relatively close to point i among my journey. Therefore I dont want to jump around in space.
Is there a proper way of walking through those interesting points?
For example in 2D space with x1,x2 = (-2,2) like so:
Note: The frequenz of the red line could be higher
There are many ways to create a space-filling curve while preserving closeness. See the Wikipedia article for a few examples (some have associated algorithms for generating them): https://en.wikipedia.org/wiki/Space-filling_curve
Regardless, let's work with your zig-zag pattern for 2D and work on extending it to 3D and 4D. To extend it into 3D, we just add another zig to the zig-zag. Take a look at the (rough) diagram below:
Essentially, we repeat the pattern that we had in 2D but we now have multiple layers that represent the third dimension. The extra zig that we need to add is the switch between bottom-to-top and top-to-bottom every layer. This is pretty simple to abstract:
In 2D, we have x and y axes.
We move across the x domain switching between positive and negative
directions most frequently.
We move across the y domain once.
In 3D, we have x, y, and z axes.
We move across the x domain switching between positive and negative directions most frequently.
We move across the y domain switching between positive and negative directions second most frequently.
We move across the z domain once.
It should be clear how this generalizes to higher dimensions. Now, I'll present some (Python 3) code that implements the zig-zag pattern for 4D. Let's represent the position in 4D space as (x, y, z, w) and the ranges in each dimension as (x0, x1), (y0, y1), (z0, z1), (w0, w1). These are our inputs. Then, we also define xdir, ydir, and zdir to keep track of the direction of the zig-zag.
x, y, z, w = x0, y0, z0, w0
xdir, ydir, zdir = +1, +1, +1
for iw in range(w1 - w0):
for iz in range(z1 - z0):
for iy in range(y1 - y0):
for ix in range(x1 - x0):
print(x, y, z, w)
x = x + xdir
xdir = -xdir
print(x, y, z, w)
y = y + ydir
ydir = -ydir
print(x, y, z, w)
z = z + zdir
zdir = -zdir
print(x, y, z, w)
w = w + 1
This algorithm has the guarantee that no two points printed out after each other have a distance greater than 1.
Using recursion, you can clean this up to make a very nice generalizable method. I hope this helps; let me know if you have any questions.
With the work of #Matthew Miller I implemented this generalization for any given multidimenisonal space:
'''assuming that we take three points out of our intervals [0,2] for a,b,c
which every one of them is corresponding to one dimension i.e. a 3D-space'''
a = [0,1,2]
b = [0,1,2]
c = [0,1,2]
vec_in = []
vec_in.append(a)
vec_in.append(b)
vec_in.append(c)
result = []
hold = []
dir = [False] * len(vec_in)
def create_points(vec , index, temp, desc):
if (desc):
loop_x = len(vec[index])-1
loop_y = -1
loop_z = -1
else:
loop_x = 0
loop_y = len(vec[index])
loop_z = 1
for i in range(loop_x,loop_y,loop_z):
temp.append(vec[index][i])
if (index < (len(vec) - 1)):
create_points(vec, index + 1, temp, dir[index])
else:
u = []
for k in temp:
u.append(k)
result.append(u)
temp.pop()
if (dir[index] == False):
dir[index] = True
else:
dir[index] = False
if len(temp) != 0:
temp.pop()
#render
create_points(vec_in, 0, hold, dir[0])
for x in (result):
print(x)
The result is a journey which covers every possible postion in a continous way:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 2]
[0, 1, 1]
[0, 1, 0]
[0, 2, 0]
[0, 2, 1]
[0, 2, 2]
[1, 2, 2]
[1, 2, 1]
[1, 2, 0]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]
[1, 0, 2]
[1, 0, 1]
[1, 0, 0]
[2, 0, 0]
[2, 0, 1]
[2, 0, 2]
[2, 1, 2]
[2, 1, 1]
[2, 1, 0]
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]

Sum of integers with restrictrions

Getting right to the gist of the problem:
In how many ways can we add k positive integers to reach a sum of exactly n if each number is smaller or equal to given number m?
The problem is solvable with dynamic programming but I am stuck because I cannot find the optimal substructure or recursion for the solution.
Here's a simple function in Python 3 that should fit your description. I assume that 0 is not an acceptable value but it's a trivial change if it is.
def howMany(k, n, m):
def sub(pos, currentSum, path):
if currentSum == n and pos == k: # reached the sum, print result and increase counter by 1
print(path)
return 1
elif currentSum < n and pos < k: # still worth trying
count = 0
for i in range(1, m):
count += sub(pos + 1, currentSum + i, path+[i])
return count
else: # abort
return 0
return sub(0, 0, [])
print(howMany(3, 10, 6))
yields
[1, 4, 5]
[1, 5, 4]
[2, 3, 5]
[2, 4, 4]
[2, 5, 3]
[3, 2, 5]
[3, 3, 4]
[3, 4, 3]
[3, 5, 2]
[4, 1, 5]
[4, 2, 4]
[4, 3, 3]
[4, 4, 2]
[4, 5, 1]
[5, 1, 4]
[5, 2, 3]
[5, 3, 2]
[5, 4, 1]
18
It could be optimised but that would obfuscate the logic at this stage.

Does RSpec support recursive approximate matching?

In RSpec I can do something like this:
[1, 2, 3].should =~ [2, 3, 1]
Is there a built-in way to make this recursively approximate? For example:
x = [
[1, 2],
[3, 4]
]
y = [
[4, 3],
[2, 1]
]
x.should =~ y
If there's no built-in way, I realize I can (and will) just write this myself.

Resources