clauses for the same predicate should be grouped - turbo-prolog

Here I want to make a prolog implementation that will generate the list of permutations of n,n+1,...2*n-1, having the absolute difference between 2 consecutive values <=2.
Ex: for n=4 the list on which I make the permutations would be [4,5,6,7] , a valid permutation would be [5,4,6,7] and not a valid one would be [7,4,6,5] because 7-4 is 3 . The problem is that I get the following error clauses for the same predicate should be grouped. I don't understand what I did wrong..Please help me
domains
el=integer
list=el*
lista=list*
predicates
perm(list,list)
permutations(integer,list)
delete(integer,list,list)
generate(integer,lista)
create(integer,list)
create_list(integer,integer,list)
permutations_aux(integer,list)
diff(list,integer).
clauses
create(N,L):-
M = 2*N,
create_list(N,M,L).
create_list(N,M,[N|R]):-
N<M,
N1=N+1,
create_list(N1,M,R).
create_list(M,M,[]).
perm([],[]).
perm(Y,[A|X]):-
delete(A,Y,Y1),
perm(Y1,X).
delete(A,[A|X],X).
delete(A,[B|X],[B|Y]):-
delete(A,X,Y).
permutations(N,X):-
create(N,X1),
perm(X1,X).
diff(X,2).
permutations_aux(N,X):-
permutations(N,X).
diff([],_).
diff([_],_).
diff([X,Y|T],M):-
abs(Y-X) <=M,!,
diff([Y|T],M).
generate(N,R):-
findall(X,permutations_aux(N,X),R).
goal
generate(4,P),
write(P).

The error or warning:
Clauses for the same predicate should be grouped
Means that you have interleaved definition of different clauses. In other words, clauses for a predicate with the same name should all be defined together in a group. Such as:
foo(X) :-
some stuff
foo(Y) :-
some stuff
bar(X) :-
some stuff
bar(Y) :-
some stuff
You will get the warning/error if you do:
foo(X) :-
some stuff
bar(X) :-
some stuff
foo(Y) :-
some stuff
bar(Y) :-
some stuff
Your error is that you have a period after perm(X1,X). in your permutations clause. It should be a comma:
permutations(N,X):-
create(N,X1),
perm(X1,X). <--- Error here
diff(X,2).
permutations_aux(N,X):-
permutations(N,X).
diff([],_).
So it really thinks you have:
permutations(N,X):-
create(N,X1),
perm(X1,X).
diff(X,2).
permutations_aux(N,X):-
permutations(N,X).
diff([],_).
Which is an interleave of definitions for diff.

Related

Creating 2 occurrence predicates out of another predicate based on min/max number of other index in the original predicate

I have the following input in Clingo:
val(a,2,3).
val(a,4,5).
val(b,0,6).
val(b,1,2).
the required is to have two predicates representing the first and second occurrence of each letter where the first one is the minimum number of the third index of val (case 1: only based on min of 3rd index), in case they are the same, then based on minimum number of the second index (case 2: both conditions).
Note that the maximum number of occurrences for each letter is 2.
The expected results is having two predicates with these values (only for this case, as sometimes the input is different):
first(a,2,3), first(b,1,2), second(a,4,5), second(b,0,6)
I tried the following code for case 1:
val(X,Y,W) :- val(X,Y,W).
first(X,Y,Z) :- val(X,Y,Z), not val(X,Y',Z'), Z'>Z,Y'!=Y.
second(X,Y,Z) :- val(X,Y,Z), not first(X,_,_).
but an error messages showed saying that Z' and Y' are unsafe.
Yes, Z' and Y' are unsafe because they do not appear in any positive predicate.
Moreover:
val(X,Y,W) :- val(X,Y,W). is a tautology and, therefore, it is useless;
it is not clear to me why you are imposing that Y'!=Y;
not first(X,_,_) is wrong, since it is checking that there doesn't exist ANY predicate first with variable X in the first argument (but this should always happen).
If I've correctly understood your requirements, this should be the correct implementation:
first(X,Y,Z) :- val(X,Y,Z), val(X,Y',Z'), Z'>Z . % case 1
first(X,Y,Z) :- val(X,Y,Z), val(X,Y',Z'), Z'=Z, Y'>Y . % case 2
second(X,Y,Z) :- val(X,Y,Z), not first(X,Y,Z) .

How can I convert this select statement to functional form?

I am having a couple of issues to put this in a functional format.
select from tableName where i=fby[(last;i);([]column_one;column_two)]
This is what I got:
?[tableName;fby;enlist(=;`i;(enlist;last;`i);(+:;(!;enlist`column_one`column_two;(enlist;`column_one;`column_two))));0b;()]
but I get a type error.
Any suggestions?
Consider using the following function, adjust from the buildQuery function given in the whitepaper on Parse Trees. This is a pretty useful tool for quickly developing in q, this version is an improvement on that given in the linked whitepaper, having been extended to handle updates by reference (i.e., update x:3 from `tab)
\c 30 200
tidy:{ssr/[;("\"~~";"~~\"");("";"")] $[","=first x;1_x;x]};
strBrk:{y,(";" sv x),z};
//replace k representation with equivalent q keyword
kreplace:{[x] $[`=qval:.q?x;x;"~~",string[qval],"~~"]};
funcK:{$[0=t:type x;.z.s each x;t<100h;x;kreplace x]};
//replace eg ,`FD`ABC`DEF with "enlist`FD`ABC`DEF"
ereplace:{"~~enlist",(.Q.s1 first x),"~~"};
ereptest:{((0=type x) & (1=count x) & (11=type first x)) | ((11=type x)&(1=count x))};
funcEn:{$[ereptest x;ereplace x;0=type x;.z.s each x;x]};
basic:{tidy .Q.s1 funcK funcEn x};
addbraks:{"(",x,")"};
//where clause needs to be a list of where clauses, so if only one whereclause need to enlist.
stringify:{$[(0=type x) & 1=count x;"enlist ";""],basic x};
//if a dictionary apply to both, keys and values
ab:{$[(0=count x) | -1=type x;.Q.s1 x;99=type x;(addbraks stringify key x),"!",stringify value x;stringify x]};
inner:{[x]
idxs:2 3 4 5 6 inter ainds:til count x;
x:#[x;idxs;'[ab;eval]];
if[6 in idxs;x[6]:ssr/[;("hopen";"hclose");("iasc";"idesc")] x[6]];
//for select statements within select statements
//This line has been adjusted
x[1]:$[-11=type x 1;x 1;$[11h=type x 1;[idxs,:1;"`",string first x 1];[idxs,:1;.z.s x 1]]];
x:#[x;ainds except idxs;string];
x[0],strBrk[1_x;"[";"]"]
};
buildSelect:{[x]
inner parse x
};
We can use this to create the functional query that will work
q)n:1000
q)tab:([]sym:n?`3;col1:n?100.0;col2:n?10.0)
q)buildSelect "select from tab where i=fby[(last;i);([]col1;col2)]"
"?[tab;enlist (=;`i;(fby;(enlist;last;`i);(flip;(lsq;enlist`col1`col2;(enlist;`col1;`col2)))));0b;()]"
So we have the following as the functional form
?[tab;enlist (=;`i;(fby;(enlist;last;`i);(flip;(lsq;enlist`col1`col2;(enlist;`col1;`col2)))));0b;()]
// Applying this
q)?[tab;enlist (=;`i;(fby;(enlist;last;`i);(flip;(lsq;enlist`col1`col2;(enlist;`col1;`col2)))));0b;()]
sym col1 col2
----------------------
bah 18.70281 3.927524
jjb 35.95293 5.170911
ihm 48.09078 5.159796
...
Glad you were able to fix your problem with converting your query to functional form.
Generally it is the case that when you use parse with a fby in your statement, q will convert this function into its k definition. Usually you should just be able to replace this k code with the q function itself (i.e. change (k){stuff} to fby) and this should run properly when turning the query into functional form.
Additionally, if you check out https://code.kx.com/v2/wp/parse-trees/ it goes into more detail about parse trees and functional form. Additionally, it contains a script called buildQuery which will return the functional form of the query of interest as a string which can be quite handy and save time when a functional form is complex.
I actually got it myself ->
?[tableName;((=;`i;(fby;(enlist;last;`i);(+:;(!;enlist`column_one`column_two;(enlist;`column_one;`column_two)))));(in;`venue;enlist`venueone`venuetwo));0b;()]
The issues was a () missing from the statement. Works fine now.
**if someone wants to add a more detailed explanation on how manual parse trees are built and how the generic (k){} function can be replaced with the actual function in q feel free to add your answer and I'll accept and upvote it

how to concate list of strings by element

I have two lists for example:
x:("AA","BB","CC")
y:("1","2","3")
I would like to target the concatenation of both lists element wise as below:
z = ("AA1","BB2","CC3")
I have tried the following which only works if the lists have one string:
(x,y)
Use eachboth adverb which takes one element from each list at a time and perform operation.
Also change comma to semicolon in your x and y list to get list with 3 items.
q) x:("AA";"BB";"CC")
q) y:("1";"2";"3")
q) x,'y
Output:
("AA1";"BB2";"CC3")

lparse/clingo: How to say AllOf(a,b,c) :- condition?

The following makes one or more literals true:
a,b,c :- condition.
a;b;c :- condition.
In the above a,b,c,condition is a valid model, but also (a,condition), (a,b,condition), etc. I want all of a, b, c to be true, always, if condition is true.
I can write the following to force a,b,c to be always true together.
:- condition, a, not b.
:- condition, b, not c.
:- condition, c, not a.
but these become very verbose and bug prone for complex rules.
You can write
3 { a ; b ; c } 3 :- condition.
That means that at least 3 and at most 3 atoms in the curly brackets are defined as true if the condition is true.
The constraints which you wrote have a very different meaning, for example the first constraint requires that some other rule must not define truth of condition and a unless there is also a rule that defines b to be true.

predicate encode in prolog

I'm new in prolog and I'm trying to write the predicate encode(L,L1) which counts the duplicates of elements in L ,for example:
encode([4,4,4,3,3],L).
L=[3,4,2,3].
This is what I have written:
encode(L,L1) :- encode(L,1,L1).
encode([],_,[]).
encode([H],N,[N,H]).
encode([H,H|T],N1,[N,H|T1]) :- M is N1+1, encode([H|T],M,[N,H|T1]).
encode([H,Y|T],N,[N,H|T1]) :- H\=Y, encode([Y|T],T1).
The above predicate is not reversible. It only works if the first parameter is provided.
How can I write encode reversible?
For example:
encode(L,[3,4,2,3]).
L = [4,4,4,3,3].
I think your algorithm has a redundant counter in it. A little simplified would be:
encoded([], []).
encoded([X], [1,X]).
encoded([X,Y|T], [1,X|R]) :-
dif(X, Y),
encoded([Y|T], R).
encoded([X,X|T], [N,X|R]) :-
N #> 1,
N #= N1 + 1,
encoded([X|T], [N1,X|R]).
Note in the last clause we need to ensure that N is greater than 1 as well.