Representing an expression in prolog - list

Trying to convert a CNF expression such as
(a'+b+c')(a+b+c)
to a list in prolog such that it is similar to
[[-a,+b,-c],[+a,+b,+c]].
Each literal is represented either as positive or negative. i.e. if a'this is equivalent to an atom that is -a.

I think you can try something like this:
cnf(A, F) :-
atom_chars(A, C),
conjunction(F, C, []), !.
conjunction([D|C]) --> disjunction(D), conjunction(C).
conjunction([C]) --> disjunction(C).
disjunction(D) --> ['('], disjuncts(D), [')'].
disjunction(L) --> literal(L).
disjuncts([L|D]) --> literal(L), disjuncts(D).
disjuncts([L]) --> literal(L).
literal(-P) --> [+], proposition(P), ['\''].
literal(+P) --> [+], proposition(P).
literal(-P) --> proposition(P), ['\''].
literal(+P) --> proposition(P).
proposition(P) --> [P], { char_type(P,lower) }.
Some examples:
?- cnf('a', F).
F = [+a].
?- cnf('a\'', F).
F = [-a].
?- cnf('(a\')(+b)', F).
F = [[-a], [+b]].
?- cnf('(a\'+b+c\')', F).
F = [[-a, +b, -c]].
?- cnf('a\'+b+c\'', F).
F = [-a, +b, -c].
?- cnf('(a\'+b+c\')(a+b+c)', F).
F = [[-a, +b, -c], [+a, +b, +c]].

Related

Extract other tuple member in Prolog

I want to write a predicate that takes a member of a tuple, that tuple, and outputs the other member of the tuple. You may assume tuples always have 2 elements, and the supplied member is always present.
extract_from_tuple(_, [], _).
extract_from_tuple(X, [H|T], R) :-
( X \= H -> R is X, ! ; X = H -> extract_from_tuple(X, T, R) ).
I tried to implement a simple if-else statement syntax I found on How to write IF ELSE conditions in Prolog.
So for example,
extract_from_tuple(a, [b,a], R).
should output b in the result variable R
Same should be for other way around:
extract_from_tuple(a, [a,b], R).
Only this time it 'should' hit the else statement and recursively call the predicate with the other element of the supplying list.
I think this problem is very simple and can be solved using just unification:
extract(X, [X,Y], Y).
extract(Y, [X,Y], X).
Examples:
?- extract(a, [b,a], R).
R = b.
?- extract(a, [a,b], R).
R = b ;
false.
To avoid spurious choice point, you can code extract/3 as:
extract_deterministic(Item, [First,Second], Rest) :-
( Item = First
-> Rest = Second
; Rest = First ).
Notice, however, this last version is less general than the first one! For example:
?- extract(X, [a,b], R). % two answers!
X = a,
R = b ;
X = b,
R = a.
?- extract_deterministic(X, [a,b], R). % only one answer!
X = a,
R = b.

How to get all consecutive sublists/subsets in Prolog?

I would like to solve a simple problem, but even through I tried many different approaches, I couldn't find a solution for it. I am using SICStus Prolog (if that matters), and I want to get all sublists/subsets (I don't know which term is correct for this) of a list, which contains elements in succession. For example, if I have the list [1, 2, 3, 4], calling the sl/2 predicate as sl([1, 2, 3, 4], R)., the expected result is:
? - sl([1, 2, 3, 4], R).
R = [] ? ;
R = [1] ? ;
R = [1, 2] ? ;
R = [1, 2, 3] ? ;
R = [1, 2, 3, 4] ? ;
R = [2] ? ;
R = [2, 3] ? ;
R = [2, 3, 4] ? ;
R = [3] ? ;
R = [3, 4] ? ;
R = [4] ? ;
no
The best result I could reach until now is:
sl([], []).
sl([X|Xs], [X|Ys]) :-
sl(Xs, Ys).
sl([_|Xs], Ys) :-
sl(Xs, Ys).
But this also gives me the following unwanted results in addition:
R = [1,2,4] ? ;
R = [1,3,4] ? ;
R = [1,3] ? ;
R = [1,4] ? ;
R = [2,4] ? ;
How should I modify my predicates so I can get the desired result?
When writing a predicate in Prolog, you need to think about what the predicate means, or what relation it is defining. The reason your predicate gives non-solutions is that you are mixing meanings in your predicate clauses. They don't all really mean the same thing.
You have the predicate sl/2 which is intended to mean "sublist" (or "subsequence") but, more than that, means a sublist per the description you provided, which is a contiguous sublist (cannot have any "gaps" in it).
Now we can break down your clauses:
sl([], []).
This says the empty list is a contiguous sublist of the empty list. This is true, so is a valid fact.
sl([X|Xs], [X|Ys]) :-
sl(Xs, Ys).
This says that [X|Ys] is a contiguous sublist of [X|Xs] if Ys is a contiguous sublist of Xs. This relation is not true. What would really be true here would be: [X|Ys] is a contiguous sublist of [X|Xs] if Ys is a contiguous prefix sublist of Xs. That is, not only does Ys need to be a sublist of Xs, but it needs to be only from the start of the list and not somewhere within this list. This is a clue that you'll need another predicate since the meaning of the relation is different.
Your final clause says that Ys is a sublist of [_|Xs] if Ys is a sublist of Xs. This appears to be true.
If we simply adjust to the above updated definitions, we get:
subseq([], []).
subseq([_|Xs], Ys) :-
subseq(Xs, Ys).
subseq([X|Xs], [X|Ys]) :-
prefix_subseq(Xs, Ys).
prefix_subseq(_, []).
prefix_subseq([X|Xs], [X|Ys]) :-
prefix_subseq(Xs, Ys).
I offered the prefix_subseq/2 definition above without explanation, but I think you can figure it out.
This now yields:
| ?- subseq([a,b,c,d], R).
R = [a] ? a
R = [a,b]
R = [a,b,c]
R = [a,b,c,d]
R = [b]
R = [b,c]
R = [b,c,d]
R = [c]
R = [c,d]
R = [d]
R = []
(1 ms) yes
An interesting, compact way of defining your sublist (or subsequence) would be using the append/2 predicate:
subseq(L, R) :- append([_, R, _], L).
This says that L is the result of appending lists _, R, and _. The minor flaw in this simple implementation is that you'll get R = [] more than once since it satisfies the append([_, R, _], L) rule in more than one way.
Taking a fresh look at the definition, you can use a DCG to define a subsequence, as a DCG is perfect for dealing with sequences:
% Empty list is a valid subsequence
subseq([]) --> ... .
% Subsequence is any sequence, followed by sequence we want, followed by any sequence
subseq(S) --> ..., non_empty_seq(S), ... .
% Definition of any sequence
... --> [] | [_], ... .
% non-empty sequence we want to capture
non_empty_seq([X]) --> [X].
non_empty_seq([X|T]) --> [X], non_empty_seq(T).
And you can call it with phrase/2:
| ?- phrase(subseq(S), [a,b,c,d]).
S = [] ? ;
S = [a] ? ;
S = [a,b] ? ;
S = [a,b,c] ? ;
S = [a,b,c,d] ? ;
S = [b] ? ;
S = [b,c] ? ;
S = [b,c,d] ? ;
S = [c] ? ;
S = [c,d] ? ;
S = [d] ? ;
no
We can reswizzle this definition a little and make use of a common seq//1 definition to make it more compact:
subseq([]) --> seq(_) .
subseq([X|Xs]) --> seq(_), [X], seq(Xs), seq(_).
% alternatively: seq(_), seq([X|Xs]), seq(_).
seq([]) --> [].
seq([X|Xs]) --> [X], seq(Xs).

Split words from string in Prolog

I want to split words from string and put into a list in Prolog.
num --> [one] | [two] | [three] | [four] | [five].
?- split("onethreetwofive", Ls).
Ls = [one,three,two,five]. % expected answer
Here, I want to split the string with matching list from num and put the words in list. I am using SWI-Prolog. Any ideas? Thanks!
Use dcg!
:- set_prolog_flag(double_quotes, chars).
num --> "one" | "two" | "three" | "four" | "five".
nums --> "".
nums --> num, nums.
Using SWI-Prolog 7.3.15:
?- phrase(nums, Cs).
Cs = [] ;
Cs = [o, n, e] ;
Cs = [o, n, e, o, n, e] ;
Cs = [o, n, e, o, n, e, o, n, e] ;
...
?- phrase(nums, "onethreetwofive").
true ;
false.
OK! Next, we step up from num//0 to num//1 and from nums//0 to nums//1:
num(one) --> "one".
num(two) --> "two".
num(three) --> "three".
num(four) --> "four".
num(five) --> "five".
nums([]) --> "".
nums([X|Xs]) --> num(X), nums(Xs).
Let's run the query the OP suggested!
?- phrase(nums(Ls), "onethreetwofive").
Ls = [one, three, two, five] ;
false.
Lets try this code.
:-set_prolog_flag(double_quotes, codes).
any(A,K) --> {member(S,K)}, S, {atom_codes(A, S)}.
num(S) --> any(S, ["one","two","three","four","five"]).
nums([]) --> "".
nums([X|Xs]) --> num(X), nums(Xs).
split(Str,Ls):-phrase(nums(Ls),Str).
Ok Now Let's run the query.
?- split("onethreetwofive", Ls).
Ls = [one, three, two, five] ;

Prefix in Prolog

I'm new in Prolog.
I have a problem about predicate prefix but a little bit different.
I want to get a prefix of a list but until an element
The list can have repeat elements.
An example:
prefix(Element, List, Prefix)
prefix(c, [a,b,c,d,e,f], [a, b])
The element is not included.
What I have so far is this
prefix(X, [X|T], []).
prefix(X, [Y|T], [Y|Z]):-
prefix(X, T, Z).
But it does not work.
L = [a,b,c] ? prefix(b, L, Prefix).
no
?-
Thanks
With dif/2 you can explicitly state that for any member X preceding Element, X \== Element:
prefix(Element, [Element|_], []).
prefix(Element, [Head|List], [Head|Prefix]) :-
dif(Element, Head),
prefix(Element, List, Prefix).
or equally, because I wanted to use append/3 in the first iteration of my answer:
prefix(Element, List, Prefix) :-
append(Prefix, [Element|_Suffix], List),
maplist(dif(Element), Prefix).
For the suffix it is basically the same:
suffix(Element, List, Suffix) :-
append(_Prefix, [Element|Suffix], List),
maplist(dif(Element), Suffix).
If you don't want to use maplist(dif(Element), List):
all_dif(_, []).
all_dif(X, [H|T]) :- dif(X, H), all_dif(X, T).
Here is a solution using Definite Clause Grammars dcg and the non-terminal all_seq//2:
prefix(X, Xs, Ys) :-
phrase( ( all_seq(dif(X), Ys), [X], ... ), Xs).
... --> [] | [_], ... .
So the grammar (within phrase/2) reads:
There is
1. an initial sequence Ys with all elements different to X, followed by 2. X, followed by 3. anything.
There is still a downside, which is often the case when using DCGs: The implementation is not as determinate as it could be and thus leaves superfluous choicepoints around.
prefix(X,[X|T],[]).
prefix(X,[Y|T],Z) :- prefix(X,T,M) , Z = [Y|M].
output:
?- L = [a,b,c,d,e,f] , prefix(d,L,G). L = [a, b, c, d, e, f], G = [a,
b, c] .
?- L = [a,b,c,d,e,f] , prefix(e,L,G). L = [a, b, c, d, e, f], G = [a,
b, c, d] .
EDIT #1
the original code is working , use (,) instead of (?) as following.
prefix(X,[X|T],[]).
prefix(X,[Y|T],[Y|Z]) :- prefix(X,T,Z).
output:
?- prefix(d , [a,b,c,d,e] , G). G = [a, b, c]
?- L = [a,b,c] , prefix(b, L, Prefix).
L = [a, b, c],
Prefix = [a] .
EDIT #2
as user false mentioned in comment, I can confirm that you are right, but in my solution, I assume that the list contains unique elements:
prefix(d,[d,d],[d]) succeeds - it should fail ,

How to predicate all pairs in a given list in Prolog?

When given a list I would like to compute all the possible combinations of pairs in the list.
e.g 2) input is a list (a,b,c) I would like to obtain pairs (a,b) (a,c) (b,c)
e.g 1) input is a list (a,b,c,d) I would like to obtain pairs (a,b) (a,c) (a,d) (b,c) (b,d) and (c,d)
Using select/3 twice (or select/3 once and member/2 once) will allow you to achieve what you want here. I'll let you work out the details and ask for help if it's still troublesome.
BTW, Prolog syntax for list isn't (a, b, c) but [a, b, c] (well, it's syntactic sugar but I'll leave it at that).
edit: as #WillNess pointed out, you're not looking for any pair (X, Y) but only for pairs where X is before Y in the list.
DCGs are a really good fit: as #false described, they can produce a graphically appealing solution:
... --> [] | [_], ... .
pair(L, X-Y) :-
phrase((..., [X], ..., [Y], ...), L).
Alternatively, if you use SWI-Prolog, a call to append/2 does the trick too, in a similar manner, but is less efficient than DCGs:
pair2(L, X-Y) :-
append([_, [X], _, [Y], _], L).
You can do it with a basic recursion, as #WillNess suggested in his comment. I'll leave this part for him to detail if needed!
OK, so to translate the Haskell definition
pairs (x:xs) = [ (x,y) | y <- xs ]
++ pairs xs
pairs [] = []
(which means, pairs in the list with head x and tail xs are all the pairs (x,y) where y is in xs, and also the pairs in xs; and there's no pairs in an empty list)
as a backtracking Prolog predicate, producing the pairs one by one on each redo, it's a straightforward one-to-one re-write of the above,
pair( [X|XS], X-Y) :- member( ... , XS) % fill in
; pair( XS, ... ). % the blanks
%% pair( [], _) :- false.
To get all the possible pairs, use findall:
pairs( L, PS) :- findall( P, pair( L, P), PS).
Consider using bagof if your lists can contain logical variables in them. Controlling bagof's backtracking could be an intricate issue though.
pairs can also be written as a (nearly) deterministic, non-backtracking, recursive definition, constructing its output list through an accumulator parameter as a functional programming language would do -- here in the top-down manner, which is what Prolog so excels in:
pairs( [X|T], PS) :- T = [_|_], pairs( X, T, T, PS, []).
pairs( [_], []).
pairs( [], []).
pairs( _, [], [], Z, Z).
pairs( _, [], [X|T], PS, Z) :- pairs( X, T, T, PS, Z).
pairs( X, [Y|T], R, [X-Y|PS], Z) :- pairs( X, T, R, PS, Z).
Here is a possible way of solving this.
The following predicate combine/3 is true
if the third argument corresponds to a list
contains pairs, where the first element of each pair
is equal to the first argument of combine/3.
The second element of each pair will correspond to an item
of the list in the second argument of the predicate combine/3.
Some examples how combine/3 should work:
?- combine(a,[b],X).
X = [pair(a,b)]
?- combine(a,[b,c,d],X).
X = [pair(a,b), pair(a,c), pair(a,d)]
Possible way of defining combine/3:
combine(A,[B],[pair(A,B)]) :- !.
combine(A,[B|T],C) :-
combine(A,T,C2), % Create pairs for remaining elements in T.
append([pair(A,B)],C2,C). % Append current pair and remaining pairs C2.
% The result of append is C.
Now combine/3 can be used to define pair/2:
pairs([],[]). % Empty list will correspond to empty list of pairs.
pairs([H|T],P) :- % In case there is at least one element.
nonvar([H|T]), % In this case it expected that [H|T] is instantiated.
pairs(H,T,P).
pairs(A,[B],[pair(A,B)]) % If remaining list contains exactly one element,
:- !. % then there will be only one pair(A,B).
pairs(A,[B|T],P) :- % In case there are at least two elements.
combine(A,[B|T],P2), % For each element in [B|T] compute pairs
% where first element of each pair will be A.
pairs(B,T,P3), % Compute all pairs without A recursively.
append(P2,P3,P). % Append results P2 and P3 together.
Sample usage:
?- pairs([a,b,c],X).
X = [pair(a, b), pair(a, c), pair(b, c)].
?- pairs([a,b,c,d],X).
X = [pair(a, b), pair(a, c), pair(a, d), pair(b, c), pair(b, d), pair(c, d)].
You can use append/ to iterate through the list:
?- append(_,[X|R],[a,b,c,d]).
X = a,
R = [b, c, d] ;
X = b,
R = [c, d] ;
X = c,
R = [d] ;
X = d,
R = [] ;
false.
Next, use member/2 to form a pair X-Y, for each Y in R:
?- append(_,[X|R],[a,b,c,d]), member(Y,R), Pair=(X-Y).
X = a,
R = [b, c, d],
Y = b,
Pair = a-b ;
X = a,
R = [b, c, d],
Y = c,
Pair = a-c ;
X = a,
R = [b, c, d],
Y = d,
Pair = a-d ;
X = b,
R = [c, d],
Y = c,
Pair = b-c ;
X = b,
R = [c, d],
Y = d,
Pair = b-d ;
X = c,
R = [d],
Y = d,
Pair = c-d ;
false.
Then, use findall/3 to collect all pairs in a list:
?- findall(X-Y, (append(_,[X|R],[a,b,c,d]), member(Y,R)), Pairs).
Pairs = [a-b, a-c, a-d, b-c, b-d, c-d].
Thus, your final solution can be expressed as:
pairs(List, Pairs) :-
findall(X-Y, (append(_,[X|R],List), member(Y,R)), Pairs).
An example of use is:
?- pairs([a,b,c,d], Pairs).
Pairs = [a-b, a-c, a-d, b-c, b-d, c-d].