Adding output from different rules in prolog - prolog

my_list([this,is,a,dog,.,what,is,your,name,?,i,simply,adore,you,!]).
count(_, [], 0) :- !.
count(X, [X|Q], N) :- !, count(X, Q, N1), N is N1+1.
count(X, [_|Q], N) :- count(X, Q, N).
number_of_sentence(N) :- my_list(L),count(.,L,N).
number_of_sentence(N) :- my_list(L),count(?,L,N).
number_of_sentence(N) :- my_list(L),count(!,L,N).
in the above code there are three types of sentences in the list(my_list) 1 affirmative, 1 question and 1 exclamatory and when i do this
?- number_of_sentence(N).
N = 1 ;
N = 1 ;
N = 1.
now how can i add the values in N and show "total = 3"
can any one help me please......

if your Prolog has library(aggregate) you can do
?- aggregate(sum(C), (my_list(L), (count(.,L,C);count(?,L,C);count(!,L,C))), N).
but mbratch' suggestion seems better. Another method, without count/3:
?- aggregate(count, E^(my_list(L), member(E, L), memberchk(E, [.,?,!])), N).
L = [this, is, a, dog, '.', what, is, your, name|...],
N = 3.

Related

Calculating syntactic complexity of a prolog predicate

Currently working on an exercise where, given some predicate, the syntactic complexity has to be calculated. The syntactic complexity of some predicate is calculated as follows:
If the predicate is atomic or a function, its complexity is 2.
If the predicate is a variable, its complexity is 1.
For example, the syntactic complexity of loyalty(father(bob, Y), X) is worked out as follows:
loyalty = 2 (function)
father = 2 (function)
bob = 2 (atom)
Y = 1 (variable)
X = 1 (variable)
Total = 8
The approach taken was calculating such complexity if the predicate was in the form of a nested list, i.e. loyalty(father(bob, Y), X) = [loyalty, father, bob, Y, X], as follows:
complexity([], 0).
complexity([H|L], C) :- atomic(H), complexity(L, C1), C is C1+2.
complexity([H|L], C) :- var(H), complexity(L, C1), C is C1+1.
The remaining issue is converting the predicate to a flat list, as shown above. The ..= is useful, but its output is not complete, that is:
loyalty(father(bob, Y), X) ..= ["loyalty", "father(bob, Y)", "X"]
Any help would be appreciated.
You must apply =.. recursively as follows:
% term_to_list(+Term, -List)
term_to_list(Term, [Term]) :- var(Term), !.
term_to_list(Term, [Term]) :- atomic(Term), !.
term_to_list(Term, List) :-
compound(Term),
Term =.. Components,
maplist(term_to_list, Components, ListOfLists),
flatten(ListOfLists, List).
Example:
?- term_to_list(loyalty(father(bob, Y), X), L).
L = [loyalty, father, bob, Y, X].
Alternatively, you can define complexity/2 as follows:
% complexity(+Term, -Complexity)
complexity(Term, 1) :- var(Term), !.
complexity(Term, 2) :- atomic(Term), !.
complexity(Term, Complexity) :-
compound(Term),
Term =.. Components,
maplist(complexity, Components, Complexities),
sum_list(Complexities, Complexity).
Example:
?- complexity(loyalty(father(bob, Y), X), L).
L = 8.
Remark SWI-Prolog defines maplist/3 and sum_list/2 as follows:
maplist(Goal, List1, List2) :-
maplist_(List1, List2, Goal).
maplist_([], [], _).
maplist_([Elem1|Tail1], [Elem2|Tail2], Goal) :-
call(Goal, Elem1, Elem2),
maplist_(Tail1, Tail2, Goal).
sum_list(Xs, Sum) :-
sum_list(Xs, 0, Sum).
sum_list([], Sum, Sum).
sum_list([X|Xs], Sum0, Sum) :-
Sum1 is Sum0 + X,
sum_list(Xs, Sum1, Sum).

Prolog: why this predicate finds the answer but ignores it and goes on to unify with []?

I wrote a predicate that is supposed to traverse through a list of numbers and compare current number to the next one then adds the bigger number to a list that it is supposed to return. The last number is simply added to the list.
For example:
[1,2,3] should return [2,3,3]
[3,5,6,6,5,9] should return [5,6,6,6,9,9]
Problem
The predicate finds the answer (it writes it out), but it doesn't unify(?) with it and goes on to return [].
Code:
head([H|_], H).
head([],[]).
maximize([], X) :- write(X).
maximize([H|T], X) :-
(head(T, N), N = []) -> (append(X, [H], L), maximize([], L)) ;
(head(T, N), H < N) -> (append(X, [N], L), maximize(T, L)) ; (append(X, [H], L), maximize(T, L)).
A solution for the problem you describe is:
maximize([], []).
maximize([X| Xs], M) :-
maximize(Xs, X, M).
maximize([], X, [X]).
maximize([Y| Ys], X, M) :-
( Y > X ->
M = [Y| T]
; M = [X| T]
),
maximize(Ys, Y, T).
Sample calls:
| ?- maximize([1,2,3], M).
M = [2,3,3]
yes
| ?- maximize([3,5,6,6,5,9], M).
M = [5,6,6,6,9,9]
yes
This solution takes advantage of first-argument indexing to avoid spurious choice points.

how can i call prolog rule while asking prolog

my_list([hello,hello,hello])
counthowmany(_, [], 0) :- !.
counthowmany(X, [X|Q], N) :- !, counthowmany(X, Q, N1), N is N1+1.
counthowmany(X, [_|Q], N) :- counthowmany(X, Q, N).
in the code above if ask Prolog after compile buffer
my_list(L),counthowmany(hello,L,N).
this question then it gives me the number of hello.....
now if i modify the code in the following way
my_list([hello,hello,hello])
counthowmany(_, [], 0) :- !.
counthowmany(X, [X|Q], N) :- !, counthowmany(X, Q, N1), N is N1+1.
counthowmany(X, [_|Q], N) :- counthowmany(X, Q, N).
numberofhello :- my_list(L), counthowmany(hello,L,N).
% i. e. I want to insert the question in a rule
and after compile buffer (though i get a singleton variable warning) if i ask Prolog
numberofhello.
it just gives me "true" and i don't get the number of hello.
Your problem is the fact that your query (numberofhello.) does not have a variable (i.e. a "wh-word"), thus becomes "Can you count how many hellos?" yes-no question instead of "How many hellos". This should fix it:
numberofhello(N) :- my_list(L), counthowmany(hello, L, N).
With this,
?- numberofhello(N).
you should be getting your N = 3.

how to turn a number from the unit form into an integer in prolog?

I have his code in prolog:
int2term(0,0).
int2term(N,s(T)) :- N>0, M is N-1, int2term(M,T).
int2term(N,p(T)) :- N<0, M is N+1, int2term(M,T).
that shows a number from this form s(s(0)) to this form 2 .
I tried to make the reversed version specically 2 -> s(s(0)) using this but nothing :
term2int(0,0).
term2int(N,T) :- N>0, M is N-1, term2int(M,s(T)).
Any suggestions ?
I have not tested this but it should work:
term2int(0,0).
term2int(s(T),N) :- term2int(T,N1), N is N1+1.
term2int(p(T),N) :- term2int(T,N1), N is N1-1.
No need to check if > 0 or otherwise, just use s and p for that case. Also N works as a counter.
This is a slightly different version which is tail recursive and avoids some of the infinite recursion cases (e.g., try term2int(T, 2). and press ; after the first solution):
term2int(0, 0).
term2int(s(X), Y) :-
term2int(s(X), 0, Y).
term2int(p(X), Y) :-
term2int(p(X), 0, Y).
term2int(0, Y, Y) :- !.
term2int(s(X), A, Y) :-
(integer(Y) -> Y > 0 ; true),
A1 is A+1,
term2int(X, A1, Y).
term2int(p(X), A, Y) :-
(integer(Y) -> Y < 0 ; true),
A1 is A-1,
term2int(X, A1, Y).

Prolog Programming

I have made two programs in Prolog for the nqueens puzzle using hill climbing and beam search algorithms.
Unfortunately I do not have the experience to check whether the programs are correct and I am in dead end.
I would appreciate if someone could help me out on that.
Unfortunately the program in hill climbing is incorrect. :(
The program in beam search is:
queens(N, Qs) :-
range(1, N, Ns),
queens(Ns, [], Qs).
range(N, N, [N]) :- !.
range(M, N, [M|Ns]) :-
M < N,
M1 is M+1,
range(M1, N, Ns).
queens([], Qs, Qs).
queens(UnplacedQs, SafeQs, Qs) :-
select(UnplacedQs, UnplacedQs1,Q),
not_attack(SafeQs, Q),
queens(UnplacedQs1, [Q|SafeQs], Qs).
not_attack(Xs, X) :-
not_attack(Xs, X, 1).
not_attack([], _, _) :- !.
not_attack([Y|Ys], X, N) :-
X =\= Y+N,
X =\= Y-N,
N1 is N+1,
not_attack(Ys, X, N1).
select([X|Xs], Xs, X).
select([Y|Ys], [Y|Zs], X) :- select(Ys, Zs, X).
I would like to mention this problem is a typical constraint satisfaction problem and can be efficiency solved using the CSP module of SWI-Prolog. Here is the full algorithm:
:- use_module(library(clpfd)).
queens(N, L) :-
N #> 0,
length(L, N),
L ins 1..N,
all_different(L),
applyConstraintOnDescDiag(L),
applyConstraintOnAscDiag(L),
label(L).
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
N is the number of queens or the size of the board (), and , where , being the position of the queen on the line .
Let's details each part of the algorithm above to understand what happens.
:- use_module(library(clpfd)).
It indicates to SWI-Prolog to load the module containing the predicates for constraint satisfaction problems.
queens(N, L) :-
N #> 0,
length(L, N),
L ins 1..N,
all_different(L),
applyConstraintOnDescDiag(L),
applyConstraintOnAscDiag(L),
label(L).
The queens predicate is the entry point of the algorithm and checks if the terms are properly formatted (number range, length of the list). It checks if the queens are on different lines as well.
applyConstraintOnDescDiag([]) :- !.
applyConstraintOnDescDiag([H|T]) :-
insertConstraintOnDescDiag(H, T, 1),
applyConstraintOnDescDiag(T).
insertConstraintOnDescDiag(_, [], _) :- !.
insertConstraintOnDescDiag(X, [H|T], N) :-
H #\= X + N,
M is N + 1,
insertConstraintOnDescDiag(X, T, M).
It checks if there is a queen on the descendant diagonal of the current queen that is iterated.
applyConstraintOnAscDiag([]) :- !.
applyConstraintOnAscDiag([H|T]) :-
insertConstraintOnAscDiag(H, T, 1),
applyConstraintOnAscDiag(T).
insertConstraintOnAscDiag(_, [], _) :- !.
insertConstraintOnAscDiag(X, [H|T], N) :-
H #\= X - N,
M is N + 1,
insertConstraintOnAscDiag(X, T, M).
Same as previous, but it checks if there is a queen on the ascendant diagonal.
Finally, the results can be found by calling the predicate queens/2, such as:
?- findall(X, queens(4, X), L).
L = [[2, 4, 1, 3], [3, 1, 4, 2]]
If I read your code correctly, the algorithm you're trying to implement is a simple depth-first search rather than beam search. That's ok, because it should be (I don't see how beam search will be effective for this problem and it can be hard to program).
I'm not going to debug this code for you, but I will give you a suggestion: build the chess board bottom-up with
queens(0, []).
queens(N, [Q|Qs]) :-
M is N-1,
queens(M, Qs),
between(1, N, Q),
safe(Q, Qs).
where safe(Q,Qs) is true iff none of Qs attack Q. safe/2 is then the conjunction of a simple memberchk/2 check (see SWI-Prolog manual) and your not_attack/2 predicate, which on first sight seems to be correct.
A quick check on Google has found a few candidates for you to compare with your code and find what to change.
My favoured solution for sheer clarity would be the second of the ones linked to above:
% This program finds a solution to the 8 queens problem. That is, the problem of placing 8
% queens on an 8x8 chessboard so that no two queens attack each other. The prototype
% board is passed in as a list with the rows instantiated from 1 to 8, and a corresponding
% variable for each column. The Prolog program instantiates those column variables as it
% finds the solution.
% Programmed by Ron Danielson, from an idea by Ivan Bratko.
% 2/17/00
queens([]). % when place queen in empty list, solution found
queens([ Row/Col | Rest]) :- % otherwise, for each row
queens(Rest), % place a queen in each higher numbered row
member(Col, [1,2,3,4,5,6,7,8]), % pick one of the possible column positions
safe( Row/Col, Rest). % and see if that is a safe position
% if not, fail back and try another column, until
% the columns are all tried, when fail back to
% previous row
safe(Anything, []). % the empty board is always safe
safe(Row/Col, [Row1/Col1 | Rest]) :- % see if attack the queen in next row down
Col =\= Col1, % same column?
Col1 - Col =\= Row1 - Row, % check diagonal
Col1 - Col =\= Row - Row1,
safe(Row/Col, Rest). % no attack on next row, try the rest of board
member(X, [X | Tail]). % member will pick successive column values
member(X, [Head | Tail]) :-
member(X, Tail).
board([1/C1, 2/C2, 3/C3, 4/C4, 5/C5, 6/C6, 7/C7, 8/C8]). % prototype board
The final link, however, solves it in three different ways so you can compare against three known solutions.

Resources