Prolog list splitting - prolog

I tried this to solve problem of splitting list in lists of length 2^0, 2^2, 2^3 ... 2^n
split(L, X) :- split(L, 1, X).
split(X, N, [X]) :-
length(X, L),
L < N.
split(L, N, [X|Xs]) :-
length(X, N),
M = N * 2,
append(X, R, L),
split(R, M, Xs).
but I have problem:
ERROR: Type error: integer' expected, found1*2' (a compound)
ERROR: In:
ERROR: [12] throw(error(type_error(integer,...),context(...,_9654)))
I'm using SWI-Prolog and have no clue how to fix it. I will really appreciate if you could help me

Related

Error counting occurrences in a list in Prolog

I trying to develop a small program in Prolog. Currently, I'm starting with Prolog and therefore there are issues that I do not understand well.
My program pretend to count the number of occurrences of an element in a list. In the end, it must to show next message: "Element X occurrs N times."
The code is as given below:
count_occur(X, [], N) :- format("Element ~d occurrs ~d times. ~n", [X,N]).
count_occur(X, [X|T], N) :-
count_occur(X, T, N2),
N is N2 + 1.
count_occur(X, [Y|T], N) :-
X \= Y,
count_occur(X, T, N).
Consulting with an example I always get following error:
?- count_occur(5,[2, 5, 5, 5, 6, 6, 8, 9, 9, 9], 0).
Element 5 ocurrs
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [19] format("Element ~d ocurrs ~d times. ~n",[5,_8398])
ERROR: [18] count_occur(5,[],_8428) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:1
ERROR: [11] count_occur(5,[5,6|...],_8456) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:3
ERROR: [10] count_occur(5,[5,5|...],_8496) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:3
ERROR: [9] count_occur(5,[5,5|...],0) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:3
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
I am using third params like counter but in the case base Prolog does not know the value of N.
If you insist on having that message printed, I would suggest to at least separate the output from the predicate describing the actual relation. Consider something along this pattern:
calling_predicate(...) :-
other_predicate(...), % <- predicate describing the actual relation
format(...). % <- output
You could, for instance, substitute count_occur/3 for calling_predicate and count_occur_/3 from #User9213's post for other_predicate. Alternatively you could opt for using CLP(FD) as suggested by #mat. Consider for example the following version using if_/3:
:- use_module(library(clpfd)).
count_occur(X, L, N) :-
list_x_count_(L,X,N,0), % <- actual relation
format("Element ~w occurs ~d times. ~n", [X,N]). % <- output
list_x_count_([],_X,N,N).
list_x_count_([Y|Ys],X,N,N0) :-
if_(Y=X,(N0 #< N, N1 #= N0+1), N1 #= N0),
list_x_count_(Ys,X,N,N1).
Since the elements in the list are not necessarily numbers, it is opportune to use the escape sequence ~w for the argument X instead of ~d (see the documentation of format/2 for more detail). If you query that with your given example, you get the desired result:
?- count_occur(5,[2,5,5,5,6,6,8,9,9,9], N).
Element 5 occurs 3 times.
N = 3.
Note that this query succeeds deterministically. That is, there are no superfluous choicepoints left, hence you don't need to enter ; after Prolog tells you the only answer. The example queries provided by #mat and #lambda.xy.x in the comments work as well:
?- count_occur(1,[2,X],0).
Element 1 occurs 0 times.
dif(X, 1).
?- count_occur(a, [a,b,c], N).
Element a occurs 1 times.
N = 1.
?- count_occur(X, [a,b,c], N).
Element a occurs 1 times.
X = a,
N = 1 ;
Element b occurs 1 times.
X = b,
N = 1 ;
Element c occurs 1 times.
X = c,
N = 1 ;
Element _G210 occurs 0 times.
N = 0,
dif(X, c),
dif(X, b),
dif(X, a).
I don't know how it can work like you have written it. Maybe write it like that:
count_occur(X, L, N) :- count_occur_(L, X, N).
count_occur_([], _, 0). % the 0 here is important (why?)
count_occur_([X|Xs], X, N) :-
count_occur_(Xs, X, N0),
succ(N0, N).
count_occur_([Y|Ys], X, N) :-
dif(Y, X),
count_occur_(Ys, X, N).
I found the error. The solution is:
count_occur(X, [], N) :- format("Element ~d occurrs ~d times. ~n", [X,N]).
count_occur(X, [X|T], N) :-
N2 is N + 1,
count_occur(X, T, N2).
count_occur(X, [Y|T], N) :-
X \= Y,
count_occur(X, T, N).
Second count_occur statement was wrong and it was not incrementing adequately.

ERROR: >/2: Arguments are not sufficiently instantiated

I want to get the length for the maximum sequence of even numbers but i get this error ERROR: >/2: Arguments are not sufficiently instantiated. I read something online but I can't understand.
Example:
max([2,4,6,7,4,8],R).
R=3
Here is my code:
max([H|T], L) :- max1(H, 1, T, L).
max1(H,_, [],0):-
H mod 2 =:=1.
max1(H, N, [], N):-
H mod 2 =:=0.
max1(X, N, [H|T], L) :-
X mod 2 =:=0,
M is N+1,
max1(H, M, T, L).
max1(X,N,[H|T],L):-
X mod 2 =:=1,
M>N,
max1(H, 1, T, M).
max1(X,N,[H|T],L):-
X mod 2 =:=1,
N>M,
max1(H,1,T,N).
In your last predicate max1, M isn't meaning anything. And in the predicate above you have the same problem because on the moment you are comparing M>N, M is also unknown.
I also don't understand why you are decoupling your list into X instead if immediately using [H|T]. Which simplifies the program.
Here is a solution that works with an accumulator.
max(L, R) :-
maxAcc(L, 0, 0, R). % list, currentBest, currentTot, Acc
maxAcc([],_, Best, Best).
maxAcc([H|T],Cur, Best, Acc) :-
H mod 2 =:=0,
CurN is Cur+1,
BestNext is max(CurN,Best),
maxAcc(T, CurN, BestNext, Acc).
maxAcc([H|T],Cur, Best, Acc) :-
H mod 2 =:=1,
BestNext is max(Cur,Best),
maxAcc(T, 0, BestNext, Acc).

Adding output from different rules in 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.

How to calculate all the possible divisions in a list?

I found this predicate for the calculation of all possible sums.
subset_sum(0,[],[]).
subset_sum(N,[_|Xs],L) :-
subset_sum(N,Xs,L).
subset_sum(N,[X|Xs],[X|Rest]) :-
R is N-X,
subset_sum(R,Xs,Rest).
Knowing that the division does not have the commutative property, how do I get the same result for the division?
This predicate only works for the division between the two elements and in order.
subset_div(1,[],[]).
subset_div(N,[_|Xs],L) :-
subset_div(N,Xs,L).
subset_div(N,[X|Xs],[X|Rest]) :-
R is X/N,
subset_div(R,Xs,Rest).
how you can get this result?
?-subset_div(20,[10,100,90,3,5],L).
L=[100,5].
?-subset_div(5,[10,4,59,200,12],L).
L=[200,10,4].
5= (200/10)/4 or 5 = (200/4)/10 but 5 \= (4/200)/10 or 5\= (10/4)/200
Thanks.
You can do it in terms of a product if you only care about left-associative solutions. Solutions when you can do, say [20 / (10 / 2) / 5] are harder, and would require a more complicated output format.
subset_prod(1, [], []).
subset_prod(N, [_|Xs], L) :-
subset_prod(N, Xs, L).
subset_prod(N, [X|Xs], [X|Rest]) :-
R is N/X,
subset_prod(R, Xs, Rest).
subset_div1(N, [X|Xs], [X|L]) :-
X1 is X / N,
integer(X1),
subset_prod(X1, Xs, L).
subset_div1(N, [_|Xs], L) :-
subset_div(N, Xs, L).
subset_div(N, L, M) :-
sort(L, L1),
reverse(L1, L2),
subset_div1(N, L2, M).

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