Finding the minimum value out of all the outcomes of a predicate - prolog

I have the following predicates:
slow(a , 10 , b).
slow(b , 17 , c).
slow(c , 12 , d).
slow(d , 19 , e).
slow(e , 13 , f).
fast(a , 20 , c).
fast(b , 20 , d).
fast(d , 20 , f).
line(X,T,Y) :- slow(X,T,Y).
line(X,T,Y) :- fast(X,T,Y).
journey(X,N,Z) :-
line(X,L,Y),
journey(Y,M,Z),
N is L+M.
journey(X,0,X) :-
!.
I now need to create a new predicate of 2arity to find the minimum value of N defined in the journey predicate.
I've so far defined the new predicate as:
minimum(X,Y) :-
journey(X,N,Y),
write(N).
I've tried to use findall/3 and bagof/3 to make a list and find the minimum atom of that list, but I am not sure how to use them.
I'm not sure how else to go about it, so any advice would be greatly appreciated.
Thanks

(First, remove the !)
?- journey(A,N,B), false.
false. % your definition always terminates, good
?- journey(A,N,B), \+ ( journey(A,M,B), M < N ).
A = a, N = 49, B = e
; A = a, N = 50, B = f
; A = a, N = 30, B = d
; A = a, N = 10, B = b
; A = b, N = 17, B = c
; A = c, N = 31, B = e
; ... .
?- setof(N,journey(A,N,B),[N|_]).
N = 0, A = B
; N = 10, A = a, B = b
; N = 20, A = a, B = c
; N = 30, A = a, B = d
; N = 49, A = a, B = e
; N = 50, A = a, B = f
; N = 17, A = b, B = c
; ... .
?- setof(N,journey(A,N,B),[N|_]), journey(A,N,B).
... . % same as above but in general safer

Related

How to debug non-termination

I'm trying to implement n_factors/2 predicate that works in all directions.
:- use_module(library(clpz)).
n_factors(N, Fs) :-
integer(N),
N > 1,
primes(Ps),
n_factors0(N, Fs, Ps),
!.
n_factors(N, Fs) :-
var(N),
primes(Ps),
N #> 1,
above(2, N),
n_factors0(N, Fs, Ps).
above(I, I).
above(I, N) :- I1 is I + 1, above(I1, N).
n_factors0(N, [F|Fs], [P|Ps]) :-
N #> 1,
F #=< N,
P #=< N,
( P * P #> N ->
F = N, Fs = []
; ( N #= N1 * P ->
F #= P, n_factors0(N1, Fs, [P|Ps])
; F #> P, n_factors0(N, [F|Fs], Ps)
)
).
When I am issuing the following query I get:
?- C #> 6, C #< 12, n_factors(A, [B,C]).
C = 7, A = 14, B = 2
; C = 7, A = 21, B = 3
; C = 11, A = 22, B = 2
; C = 11, A = 33, B = 3
; C = 7, A = 35, B = 5
; C = 7, A = 49, B = 7
; C = 11, A = 55, B = 5
; C = 11, A = 77, B = 7
; C = 11, A = 121, B = 11
;
before the program moves on to exploring the realm of rather large numbers. So the question I've go is the following: knowing for certain that the mathematical problem is constraint enough to terminate, how do I find the missing constraint in my program? What I am doing right now is staring at the screen before trying to add "invariant" conditions here and there and see if they help.
primes(Ps) is a "frozen" infinite list with all prime numbers. I don't think the implementation thereof is important for this question but just in case
primes(Ps) :-
Ps = [2,3|T],
primes0(5, Ps, Ps, T),
!.
primes0(C, [D|Ds], Ps, T) :-
( D * D > C ->
T = [C|T1], C1 is C + 2, freeze(T1, primes0(C1, Ps, Ps, T1))
; ( C mod D =:= 0 ->
C1 is C + 2, primes0(C1, Ps, Ps, T)
; primes0(C, Ds, Ps, T)
)
).

Efficient Fibonacci in Prolog

I am trying to implement a Fibonacci predicate that can be efficiently used with CLP.
:- module(fibonacci, [fibonacci/2]).
fibonacci(N, F) :-
( var(N) ; integer(N) ),
( var(F) ; integer(F) ),
( var(F) ->
( integer(N) ->
fib_1(N, F), !
; fib_3(0, N, F)
)
; ( integer(N) ->
fib_1(N, F0), F0 = F, !
; fib_2(0, F, N0), N0 = N, !
)
).
fib_3(I, J, F) :-
( I = J, fib_1(I, F) ) ;
( I1 is I + 1, fib_3(I1, J, F) ).
fib_2(I, F, J) :-
fib_1(I, F0),
( F = F0 ->
J = I, !
; ( F0 > F -> !, fail
; I1 is I + 1,
fib_2(I1, F, J)
)
).
fib_1(0, 0).
fib_1(1, 1).
fib_1(2, 1).
fib_1(N, F) :-
var(F),
N > 2,
( N mod 2 =:= 0 ->
N0 is div(N, 2),
N1 is N0 + 1,
fib_1(N0, F0),
fib_1(N1, F1),
F is F0 * (2 * F1 - F0)
; N0 is div(N + 1, 2),
N1 is N0 - 1,
fib_1(N0, F0),
fib_1(N1, F1),
F is F0 * F0 + F1 * F1
).
This is not the prettiest code, but it does what I want it to do.
?- fibonacci(A, 10).
false.
?- fibonacci(A, 13).
A = 7.
?- fibonacci(12, A).
A = 144.
?- fibonacci(12, 144).
true.
?- fibonacci(12, 145).
false.
?- fibonacci(A, B).
A = B, B = 0 ;
A = B, B = 1 ;
A = 2,
B = 1 ;
A = 3,
B = 2 ;
A = 4,
B = 3 ;
A = B, B = 5 .
What's the magic potion that is missing for this query to work:
fibonacci(_, B), B #< 1000
Is it rectifiable at all, or is CLP a completely different beast altogether, and every predicate that is CLP-compatible needs to understand more than just integers and vars?
You should avoid using ! within an algorithm that uses clp(FD) as they don't mix well. Also if-then-else may backfire too. I'd also keep an eye on using var/1 within an algorithm that uses clp.
Here goes a solution that uses clp(FD) and accumulators to avoid double recursion:
fibonacci(0, 0).
fibonacci(1, 1).
fibonacci(N, F):-
N #> 1,
zcompare(C, 2, N),
fibonacci(C, 2, N, 0, 1, F).
fibonacci(=, N, N, F1, F2, F):-
F #= F1+F2.
fibonacci(<, N0, N, F1, F2, F):-
N1 #= N0+1,
F3 #= F1+F2,
F #> F3,
zcompare(C, N1, N),
fibonacci(C, N1, N, F2, F3, F).
Also for the test you should issue the constraint over the expected number before calling fibonacci/2. So instead of fibonacci(_, B), B #< 1000. use B #< 1000, fibonacci(_, B).
sample runs:
?- fibonacci(10, F).
F = 55.
?- B #< 1000, fibonacci(_, B).
B = 0 ;
B = 1 ;
B = 1 ;
B = 2 ;
B = 3 ;
B = 5 ;
B = 8 ;
B = 13 ;
B = 21 ;
B = 34 ;
B = 55 ;
B = 89 ;
B = 144 ;
B = 233 ;
B = 377 ;
B = 610 ;
B = 987 ;
false.

How can labeling/2 generate solutions starting from the midpoint of a domain?

Having a list with independent variables, whose domain is 1..N, how can we use labeling/2 so it starts producing solutions starting from the middle?
The flags i tried are [bisect], [enum], [max], [min], [ff], but no matter which i picked, i can't make it work.
My code is:
:-use_module(library(clpfd)).
combos(EMPLOYEES,POSTS,LIST):-
LIMIT is POSTS-EMPLOYEES+1,
length(LIST,EMPLOYEES),
LIST ins 1..LIMIT,
sum(LIST,#=,POSTS),
labeling([bisect],LIST).
after setting a query, for example:
?-combos(2,10,LIST).
i want it to return:
L = [5,5];
L = [4,6];
L = [6,4] ...
instead of:
L = [1,9];
L = [2,8];
L = [3,7] ...
As a rule of thumb, whenever you try to extend the functionality of clpfd, try to reuse as much as possible. It seems that you want solutions first whose sum of distances to the center is as small as possible.
combos2(EMPLOYEES,POSTS,LIST):-
LIMIT is POSTS-EMPLOYEES+1,
length(LIST,EMPLOYEES),
LIST ins 1..LIMIT,
sum(LIST,#=,POSTS),
Mid is (LIMIT+1) div 2, %%
maplist(dist(Mid), LIST, DISTS), %%
sum(DISTS,#=,Totaldist), %%
labeling([],[Totaldist|LIST]).
dist(Mid, E, D) :-
D #= abs(Mid-E).
?- combos2(2,10,L).
L = [5,5]
; L = [4,6]
; L = [6,4]
; L = [3,7]
; L = [7,3]
; ... .
Here you go!
combos(2,S,L) :- b2(S,L).
combos(C,S,[A|L]) :-
C > 2,
b2(S,[A,B]),
D is C-1,
combos(D,B,L).
b2(S,L) :- B is S-1, bisector(B,L).
bisector(Y,[A,B]) :-
odd(Y),
M is div(1+Y,2),
Z is M-1,
range(D,0,Z),
bisec1(D,M,A,B).
bisector(Y,[A,B]) :-
even(Y),
M is 1+Y,
Z is Y/2-1,
range(D,0,Z),
bisec2(D,M,A,B).
bisec1(0,M,M,M).
bisec1(D,M,A,B) :- D > 0, A is M + D, A > 0, B is M - D, B > 0.
bisec1(D,M,A,B) :- D > 0, A is M - D, A > 0, B is M + D, B > 0.
bisec2(D,M,A,B) :- A is (M+2*D+1)/2, A > 0, B is (M-2*D-1)/2, B > 0.
bisec2(D,M,A,B) :- A is (M-2*D-1)/2, A > 0, B is (M+2*D+1)/2, B > 0.
even(X) :- 0 is mod(X, 2).
odd(X) :- 1 is mod(X, 2).
range(M,M,_).
range(X,M,N) :- P is M + 1, P =< N, range(X,P,N).

How to find two numbers where a restriction is applied

Let's say that I want to find two numbers where the sum of these are 8, are from 1-9 and must be different(it is obvious that these numbers are (7,1),(6,2),etc).So I wrote.
dif_list([H|T]):- \+ member(H,T),dif_list(T).
dif_list([]).
check1_9([H|T]):-H>=1,H=<9,check1_9(T).
check1_9([]).
find_number([A,B],N) :- N =:= A+B,dif_list([A,B]),check1_9([A,B]).
Afterwards I will ask prolog
?-find_number([A,B],8).
ERROR: =:=/2: Arguments are not sufficiently instantiated
My goal is that prolog will print for me the results.For example:
?-find_number([A,B],8).
A = 7,
B = 1 ;
A = 6,
B = 2 ;
...
The best way to handle this kind of problem in Prolog is to use the CLP(FD) library:
:- [library(clpfd)].
sum_of(A, B, Sum) :-
A #> 0,
B #> 0,
A + B #= Sum.
?- sum_of(A, B, 8), label([A, B]).
A = 1,
B = 7 ;
A = 2,
B = 6 ;
A = 3,
B = 5 ;
A = B, B = 4 ;
A = 5,
B = 3 ;
A = 6,
B = 2 ;
A = 7,
B = 1.
?-
If you want the addends to be unique, you can further constrain it:
sum_of(A, B, Sum) :-
A #> 0,
B #>= A,
A + B #= Sum.
There's really no need to use a list to manage the variables A and B, but you can if you wish: sum_of([A,B], Sum).
Prolog is not that declarative: there are indeed answer set programming (ASP) or constraint logic programming (clp) languages where you can simply define a set of constraints and a finite domain solver aims to solve it (but these will take considerable time).
I would suggest that you define your program as follows:
find_number(A,B,N) :-
member(A,[1,2,3,4,5,6,7,8,9]),
member(B,[1,2,3,4,5,6,7,8,9]),
N is A+B,
A \= B.
Here member/2 will instantiate A and B to values that are provided by the list, so 1..9, next you use is/2 to calculate the sum and verify that the sum is equal to N. You can only call N is A+B if A and B are given a proper value. Finally we say A \= B (A is not equal to B).
When you run this predicate, it produces:
?- find_number(A,B,8).
A = 1,
B = 7 ;
A = 2,
B = 6 ;
A = 3,
B = 5 ;
A = 5,
B = 3 ;
A = 6,
B = 2 ;
A = 7,
B = 1 ;
false.
You can however also query with A and B already filled in, or one of them filled in, or where the sum is left open. So:
?- find_number(A,2,8).
A = 6 ;
false.
or:
?- find_number(A,2,N).
A = 1,
N = 3 ;
A = 3,
N = 5 ;
A = 4,
N = 6 ;
A = 5,
N = 7 ;
A = 6,
N = 8 ;
A = 7,
N = 9 ;
A = 8,
N = 10 ;
A = 9,
N = 11 ;
false.

Element to search in binary tree in Prolog

I'm very new to Prolog, and trying to find an element to search in binary tree, it finds it successfully but the problem is if it doesn't it still gives yes, I want it to say no or to say not found. My code is:
child(1,2,3).
child(2,4,5).
child(3,6,7).
node(1,a).
node(2,b).
node(3,c).
node(4,d).
node(5,f).
node(6,f).
node(7,g).
show(X):-
write('element is found in node: '),write(X),nl.
inc(X,Y,Z):-
Y is X+X,
Z is X+X+1.
find(A):-
traverse3(1,A).
traverse3(X,A):-
check(X,A),
inc(X,Y,Z),
child(X,Y,Z),
traverse3(Y,A),
traverse3(Z,A).
check(X,A):- not(node(X,A)).
check(X,A):-
node(X,A),
show(X).
traverse3(X,A):- not(child(X,Y,Z)).
This is an unusual binary tree. But anyway, since you have already "normalized" it to a database representation, all you have to do to find an element is to ask for it.
In other words, if your program tree.pl consists only of the child/3 and node/2 facts:
child(1,2,3).
child(2,4,5).
child(3,6,7).
node(1,a).
node(2,b).
node(3,c).
node(4,d).
node(5,f).
node(6,f).
node(7,g).
You can simply query for the element you need:
?- [tree].
true.
?- node(N, a).
N = 1.
?- node(N, f).
N = 5 ;
N = 6.
?- node(4, E).
E = d.
?- node(N, E).
N = 1, E = a ;
N = 2, E = b ;
N = 3, E = c ;
N = 4, E = d ;
N = 5, E = f ;
N = 6, E = f ;
N = 7, E = g.
Or is there something I am missing?

Resources