Prolog methods with certain conditions - recursion

I am trying to write a function where it gets new values on each recursion call and if it fails, then increase the the numbers and try it again until the number has reached 6 or 1.
The important part here is that it should go to the second part only if it has succeeded once and increase or lower the number. And if it has succeeded once and increased/lowered it should check whether or not the function try_to_do_math works with the new number and if it doesn't then increase or lower the number again until the number reaches 6 or 1 unless it succeeds before the number hits 6 or 1.
Also it should check whether it should add or substract by checking th value of higer_or_lower.
?- iterate_over(1, 1, Z, X).
iterate_over(X,Y,Z,higher_or_lower):-
try_to_do_math(X,Y,X1,Y1,high_low),
iterate_over(X1, Y1,1,high_low).
iterate_over(X,Y,Z,higher_or_lower):-
higher_or_lower = 1, %Go higher
Z = 1,
X1 is X+1, X=<6,
Y1 is Y+1, Y=<6,
iterate_over(X1, Y1, 0,higher_or_lower).
iterate_over(X,Y,Z,higher_or_lower):-
higher_or_lower = 2, %Go lower
Z = 1,
X1 is X-1, 1=< X,
Y1 is Y-1, 1=< Y,
iterate_over(X1, Y1, 0,higher_or_lower).
I am using variable Z to check if it succeeded before or not. If it is 1, that means it has succeeded and if it is _ empty then it has not.
With this code it always fails on Z=1 because it does not have the value 1 when it reaches there to check it.
If try_to_do_math does not succeed on the first try then nothing should happen and false is returned.
If try_to_do_math succeeds the first time then it gives back new X1 and Y1 and higer/lower. And then I tried to pass on the variable Z as the state variable that is changed to 1 just on calling it again here iterate_over(X1, Y1,1,high_low)..
EDIT
I will try to do an example that would succeed.
Lets say the correct one is X = 5 and Y = 5.
First ?- iterate_over(1, 1, Z, X). is called.
Then it goes to try_to_do_math(1, 1, X, Y, Z) and gives back try_to_do_math(1, 1, 3, 3, 0).
Then it should try it again by calling ?- iterate_over(3, 3, 1, 0).. Now it tries to call the try_to_do_math(3,3,X1,Y1,higher_or_lower), and it fails.
Now it should go to the lower iterate_over methods with values iterate_over(3, 3, 1, 0), but this is where it does not work as I want it to. The method is called with numbers iterate_over(3, 3, _, 0) and since 1 != _ it all fails.
I am not sure if this is helpful, but I tried to explain it the way I see it.
Also if it succeedes then I do not care about the response as the try_to_do_math will only be changing things.

Related

Robot in a Grid - how to get all possible paths

I'm trying to solve this problem:
There is a grid with with r rows and c columns. A robot sitting in top left cell can only move in 2 directions, right and down. But certain cells have to be avoided and the robot cannot step on them. Find a path for the robot from the top left to the bottom right.
The problem specifically asks for a single path, and that seems straight forward:
Having the grid as boolean[][], the pseudocode I have is
List<String> path = new ArrayList<String>()
boolean found = false
void getPath(r, c){
if (!found) {
if ( (r or c is outofbounds) || (!grid[r][c]) )
return
if (r==0 AND c==0) // we reached
found = true
getPath(r-1, c)
getPath(r, c-1)
String cell = "(" + r + ", " + c + ")"
path.add(cell)
}
}
Though I was wondering how can I get all the possible paths (NOT just the count, but the path values as well). Note that it has r rows and c columns, so its not a nxn grid. I'm trying to think of a DP/recursive solution but unable to come up with any and stuck. It's hard to think when the recursion goes in two ways.
Any pointers? And also any general help on how to "think" about such problems would be appreciated :).
Any pointers? And also any general help on how to "think" about such problems would be appreciated :).
Approach to the problem:
Mentally construct graph G of the problem. In this case the vertices are cells in the grid and directed edges are created where a valid robot move exist.
Search for properties of G. In this case G is a DAG (Directed Acyclic Graph).
Use such properties to come up with a solution. In this case (G is a DAG) its common to use topological sort and dynamic programming to find the amount of valid paths.
Actually you don't need to construct the graph since the set of edges is pretty clear or to do topological sort as usual iteration of the matrix (incremental row index and incremental column index) is a topological sort of this implicit graph.
The dynamic programming part can be solved by storing in each cell [x][y] the amount of valid paths from [0][0] to [x][y] and checking where to move next.
Recurrence:
After computations the answer is stored in dp[n - 1][m - 1] where n is amount of rows and m is amount of columns. Overall runtime is O(nm).
How about find all possible valid paths:
Usual backtracking works and we can speed it up by applying early pruning. In fact, if we calculate dp matrix and then we do backtracking from cell [n - 1][m - 1] we can avoid invalid paths as soon the robot enters at a cell whose dp value is zero.
Python code with dp matrix calculated beforehand:
n, m = 3, 4
bad = [[False, False, False, False],
[ True, True, False, False],
[False, False, False, False]]
dp = [[1, 1, 1, 1],
[0, 0, 1, 2],
[0, 0, 1, 3]]
paths = []
curpath = []
def getPath(r, c):
if dp[r][c] == 0 or r < 0 or c < 0:
return
curpath.append((r, c))
if r == 0 and c == 0:
paths.append(list(reversed(curpath)))
getPath(r - 1, c)
getPath(r, c - 1)
curpath.pop()
getPath(n - 1, m - 1)
print(paths)
# valid paths are [[(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3)],
# [(0, 0), (0, 1), (0, 2), (1, 2), (1, 3), (2, 3)],
# [(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (2, 3)]]
Notice that is very similar to your code, there is a need to store all valid paths together and take care that appended lists are a copy of curpath to avoid ending up with an list of empty lists.
Runtime: O((n + m) * (amount of valid paths)) since simulated robot moves belong to valid paths or first step into an invalid path detected using foresight (dp). Warning: This method is exponential as amount of valid paths can be .

Using inttrap and diff to get the length of a curve in Scilab

How can you get the length of the curve down below between 0 and 4*pi? The commands you should use are inttrap and diff. Here is what I have now:
t=linspace(0,4*%pi)
x=(4+sin(a*t)).*cos(3*t)
y=(4+sin(a*t)).*sin(3*t)
z=cos(3*t)
xx=diff(x)
yy=diff(y)
zz=diff(z)
aid=sqrt(xx^2+yy^2+zz^2)
length=inttrap([t],aid)
Getting error message, the last step is not right.
The reason for error message is that t and aid have different sizes. And that is because diff returns a vector with 1 entry fewer than the input. You can see how it works on an example: diff([3 1 5]) is [-2 4].
To fix this, use t(1:$-1), which omits the last entry of t. That is,
len = inttrap(t(1:$-1), aid)
(Please don't use length, which is a function name in Scilab.)
Another problem you have is that diff is just differences, not a derivative. To get the derivative, you need to divide by the step size, which in your case is t(2)-t(1).
Also, the syntax xx^2 is deprecated for elementwise power; use xx.^2 instead
t = linspace(0,4*%pi)
a = 1
x = (4+sin(a*t)).*cos(3*t)
y = (4+sin(a*t)).*sin(3*t)
z = cos(3*t)
step = t(2)-t(1)
xx = diff(x)/step
xy = diff(y)/step
xz = diff(z)/step
aid = sqrt(xx.^2+yy.^2+zz.^2)
len = inttrap(t(1:$-1), aid)

Scilab round-off error

I cannot solve a problem in Scilab because it get stucked because of round-off errors. I get the message
!--error 9999
Error: Round-off error detected, the requested tolerance (or default) cannot be achieved. Try using bigger tolerances.
at line 2 of function scalpol called by :
at line 7 of function gram_schmidt_pol called by :
gram_schmidt_pol(a,-1/2,-1/2)
It's a Gram Schmidt process with the integral of the product of two functions and a weight as the scalar product, between -1 and 1.
gram_schmidt_pol is the process specially designed for polynome, and scalpol is the scalar product described for polynome.
The a and b are parameters for the weigth, which is (1+x)^a*(1-x)^b
The entry is a matrix representing a set of vectors, it works well with the matrix [[1;2;3],[4;5;6],[7;8;9]], but it fails with the above message error on matrix eye(2,2), in addition to this, I need to do it on eye(9,9) !
I have looked for a "tolerance setting" in the menus, there is some in General->Preferences->Xcos->Simulation but I believe this is not for what I wan't, I have tried low settings (high tolerance) in it and it hasn't change anything.
So how can I solve this rounf-off problem ?
Feel free to tell me my message lacks of clearness.
Thank you.
Edit: Code of the functions :
// function that evaluate a polynomial (vector of coefficients) in x
function [y] = pol(p, x)
y = 0
for i=1:length(p)
y = y + p(i)*x^(i-1)
end
endfunction
// weight function evaluated in x, parametrized by a and b
// (poids = weight in french)
function [y] = poids(x, a, b)
y = (1-x)^a*(1+x)^b
endfunction
// scalpol compute scalar product between polynomial p1 and p2
// using integrate, the weight and the pol functions.
function [s] = scalpol(p1, p2, a, b)
s = integrate('poids(x,a, b)*pol(p1,x)*pol(p2,x)', 'x', -1, 1)
endfunction
// norm associated to scalpol
function [y] = normscalpol(f, a, b)
y = sqrt(scalpol(f, f, a, b))
endfunction
// finally the gram schmidt process on a family of polynome
// represented by a matrix
function [o] = gram_schmidt_pol(m, a, b)
[n,p] = size(m)
o(1:n) = m(1:n,1)/(normscalpol(m(1:n,1), a, b))
for k = 2:p
s =0
for i = 1:(k-1)
s = s + (scalpol(o(1:n,i), m(1:n,k), a, b) / scalpol(o(1:n,i),o(1:n,i), a, b) .* o(1:n,i))
end
o(1:n,k) = m(1:n,k) - s
o(1:n,k) = o(1:n,k) ./ normscalpol(o(1:n,k), a, b)
end
endfunction
By default, Scilab's integrate routine tries to achieve absolute error at most 1e-8 and relative error at most 1e-14. This is reasonable, but its treatment of relative error does not take into account the issues that occur when the exact value is zero. (See How to calculate relative error when true value is zero?). For this reason, even the simple
integrate('x', 'x', -1, 1)
throws an error (in Scilab 5.5.1).
And this is what happens in the process of running your program: some integrals are zero. There are two solutions:
(A) Give up on the relative error bound, by specifying it as 1:
integrate('...', 'x', -1, 1, 1e-8, 1)
(B) Add some constant to the function being integrated, then subtract from the result:
integrate('100 + ... ', 'x', -1, 1) - 200
(The latter should work in most cases, though if the integral happens to be exactly -200, you'll have the same problem again)
The above works for gram_schmidt_pol(eye(2,2), -1/2, -1/2) but for larger, say, gram_schmidt_pol(eye(9,9), -1/2, -1/2), it throws the error "The integral is probably divergent, or slowly convergent".
It appears that the adaptive integration routine can't handle the functions of the kind you have. A fallback is to use the simple inttrap instead, which just applies the trapezoidal rule. Since at x=-1 and 1 the function poids is undefined, the endpoints have to be excluded.
function [s] = scalpol(p1, p2, a, b)
t = -0.9995:0.001:0.9995
y = poids(t,a, b).*pol(p1,t).*pol(p2,t)
s = inttrap(t,y)
endfunction
In order for this to work, other related functions must be vectorized (* and ^ changed to .* and .^ where necessary):
function [y] = pol(p, x)
y = 0
for i=1:length(p)
y = y + p(i)*x.^(i-1)
end
endfunction
function [y] = poids(x, a, b)
y = (1-x).^a.*(1+x).^b
endfunction
The result is guaranteed to work, though the precision may be a bit lower: you are going to get some numbers like 3D-16 which are actually zeros.

Prolog: ID number mapping to a list

I have a variable X that may contain multiple values: X = 1; X = 4; X = 7...
These values map to a list that contain x,y,z, or w. Each one of these value/list pairs are split into multiple facts, so I could have:
map(2,[x,y]).
map(3,[x]).
map(9,[y,w]).
I'm trying to write a program that, given X, I can look up these lists and count how many occurences of x,y,z, or w there are.
This is my attempt:
count(A,B,C,D,X) :- A = 0, B = 0, C = 0, D = 0,
check_list(X,x,A),
check_list(X,y,B),
check_list(X,z.C),
check_list(X,w,D).
check_list(X,Element,Counter) :-
map(X, List),
member(List, Element),
S is Counter + 1,
Counter = S.
The idea behind my program is I call check_list to check if there is a member that contains x,y,z,w for every possible value of X. If there is that member, I will increment the counter. I then want the values of A,B,C,D to have A = number of occurrences of x, B = number of occurrences of y, etc etc.
You are using Prolog variables wrong. Variables cannot change their values once they are instantiated unless Prolog backtracks to a choice-point previous to the instantiation. For example, in the rule for count/5 you unify A with zero and then you expect that satisfying check_list(X,x,A) will bind A to the number of occurrences of x, but A is not a free variable at that point.
So, you have to remove A = 0, ..., D = 0 from the first rule.
Next, you need a predicate that can be used to find the number of occurrences of an element in a list. You can use findall/3 for that:
occurrences(X, List, N):- findall(_, member(X, List), O), length(O, N).
Or you can write it yourself:
occurrences(_, [], 0).
occurrences(X, [X|Tail], N):-!, occurrences(X, Tail, N1), N is N1 + 1.
occurrences(X, [_|Tail], N):-occurrences(X, Tail, N).

How to make recursive nested loops which use loop variables inside?

I need to make a nested loop with an arbitrary depth. Recursive loops seem the right way, but I don't know how to use the loop variables in side the loop. For example, once I specify the depth to 3, it should work like
count = 1
for i=1, Nmax-2
for j=i+1, Nmax-1
for k=j+1,Nmax
function(i,j,k,0,0,0,0....) // a function having Nmax arguments
count += 1
end
end
end
I want to make a subroutine which takes the depth of the loops as an argument.
UPDATE:
I implemented the scheme proposed by Zoltan. I wrote it in python for simplicity.
count = 0;
def f(CurrentDepth, ArgSoFar, MaxDepth, Nmax):
global count;
if CurrentDepth > MaxDepth:
count += 1;
print count, ArgSoFar;
else:
if CurrentDepth == 1:
for i in range(1, Nmax + 2 - MaxDepth):
NewArgs = ArgSoFar;
NewArgs[1-1] = i;
f(2, NewArgs, MaxDepth, Nmax);
else:
for i in range(ArgSoFar[CurrentDepth-1-1] + 1, Nmax + CurrentDepth - MaxDepth +1):
NewArgs = ArgSoFar;
NewArgs[CurrentDepth-1] = i;
f(CurrentDepth + 1, NewArgs, MaxDepth, Nmax);
f(1,[0,0,0,0,0],3,5)
and the results are
1 [1, 2, 3, 0, 0]
2 [1, 2, 4, 0, 0]
3 [1, 2, 5, 0, 0]
4 [1, 3, 4, 0, 0]
5 [1, 3, 5, 0, 0]
6 [1, 4, 5, 0, 0]
7 [2, 3, 4, 0, 0]
8 [2, 3, 5, 0, 0]
9 [2, 4, 5, 0, 0]
10 [3, 4, 5, 0, 0]
There may be a better way to do this, but so far this one works fine. It seems easy to do this in fortran. Thank you so much for your help!!!
Here's one way you could do what you want. This is pseudo-code, I haven't written enough to compile and test it but you should get the picture.
Define a function, let's call it fun1 which takes inter alia an integer array argument, perhaps like this
<type> function fun1(indices, other_arguments)
integer, dimension(:), intent(in) :: indices
...
which you might call like this
fun1([4,5,6],...)
and the interpretation of this is that the function is to use a loop-nest 3 levels deep like this:
do ix = 1,4
do jx = 1,5
do kx = 1,6
...
Of course, you can't write a loop nest whose depth is determined at run-time (not in Fortran anyway) so you would flatten this into a single loop along the lines of
do ix = 1, product(indices)
If you need the values of the individual indices inside the loop you'll need to unflatten the linearised index. Note that all you are doing is writing the code to transform array indices from N-D into 1-D and vice versa; this is what the compiler does for you when you can specify the rank of an array at compile time. If the inner loops aren't to run over the whole range of the indices you'll have to do something more complicated, careful coding required but not difficult.
Depending on what you are actually trying to do this may or may not be either a good or even satisfactory approach. If you are trying to write a function to compute a value at each element in an array whose rank is not known when you write the function then the preceding suggestion is dead flat wrong, in this case you would want to write an elemental function. Update your question if you want further information.
you can define your function to have a List argument, which is initially empty
void f(int num,List argumentsSoFar){
// call f() for num+1..Nmax
for(i = num+1 ; i < Nmax ; i++){
List newArgs=argumentsSoFar.clone();
newArgs.add(i);
f(i,newArgs);
}
if (num+1==Nmax){
// do the work with your argument list...i think you wanted to arrive here ;)
}
}
caveat: the stack should be able to handle Nmax depth function calls
Yet another way to achieve what you desire is based on the answer by High Performance Mark, but can be made more general:
subroutine nestedLoop(indicesIn)
! Input indices, of arbitrary rank
integer,dimension(:),intent(in) :: indicesIn
! Internal indices, here set to length 5 for brevity, but set as many as you'd like
integer,dimension(5) :: indices = 0
integer :: i1,i2,i3,i4,i5
indices(1:size(indicesIn)) = indicesIn
do i1 = 0,indices(1)
do i2 = 0,indices(2)
do i3 = 0,indices(3)
do i4 = 0,indices(4)
do i5 = 0,indices(5)
! Do calculations here:
! myFunc(i1,i2,i3,i4,i5)
enddo
enddo
enddo
enddo
enddo
endsubroutine nestedLoop
You now have nested loops explicitly coded, but these are 1-trip loops unless otherwise desired. Note that if you intend to construct arrays of rank that depends on the nested loop depth, you can go up to rank of 7, or 15 if you have a compiler that supports it (Fortran 2008). You can now try:
call nestedLoop([1])
call nestedLoop([2,3])
call nestedLoop([1,2,3,2,1])
You can modify this routine to your liking and desired applicability, add exception handling etc.
From an OOP approach, each loop could be represented by a "Loop" object - this object would have the ability to be constructed while containing another instance of itself. You could then theoretically nest these as deep as you need to.
Loop1 would execute Loop2 would execute Loop3.. and onwards.

Resources