I have a simple grammar such as
S::=a S b
S::=[] (empty string)
Now i want to write a parser for the above grammar like
cfg('S', [a,'S',b])
which generates a sentence aaabbb by left most derivation.
I'm not good enough to handle dcg/cfg in prolog.
So pls help me with this example so that i can go ahead and try something bigger.
Consider this DCG code:
s-->[].
s-->[a],s,[b].
to run a predicate you defined by DCG you should add two more arguments at the end: the "input" and what it's left. If you want to recognize the whole list you simply put []. So, when you run it you get:
38 ?- s(C,[]).
C = [] ;
C = [a, b] ;
C = [a, a, b, b] ;
C = [a, a, a, b, b, b] ;
C = [a, a, a, a, b, b, b, b] ;
...
If you wanted some sort of "return" string you could add it as an extra arg. To write prolog code in a dcg clause you use {}:
s('')-->[].
s(S)-->
[a],s(SI),[b],
{ atomic_list_concat([a,SI,b],S)}.
and you get:
40 ?- s(R,X,[]).
R = '',
X = [] ;
R = ab,
X = [a, b] ;
R = aabb,
X = [a, a, b, b] ;
R = aaabbb,
X = [a, a, a, b, b, b] ;
R = aaaabbbb,
X = [a, a, a, a, b, b, b, b] ;
R = aaaaabbbbb,
...
we generated all the strings that are recognized by this grammar; usually you just want to check if a string is recognized by the grammar. to do that you simply put it as input:
41 ?- s([a,b],[]).
true
42 ?- s([a,b,b],[]).
false.
note that we put the S::=[] rule first otherwise prolog would fall in a infinite loop if you asked to generate all the solutions. This problem might not be trivial to solve in more complex grammars. To get the solutions you can use length/2:
?- length(X,_),s(X,[]).
X = [] ;
X = [a, b] ;
X = [a, a, b, b] ;
X = [a, a, a, b, b, b] ;
X = [a, a, a, a, b, b, b, b]
even if your code is:
s-->[].
s-->[a],s,[b].
Related
I Have an automaton.
The question here is: how to find at least one word of even length accepted by my given finite automaton?
states /* states(Q) <=> Q is the list of automata's states */
symbols /* symbols(Sigma) <=> Sigma is the list of automata's input symbols */
transition /* transition(X, A, Y) <=> δ(X, A)=Y */
startState /* startState(S) <=> S is the start state of automata */
finalStates /* finalStates(F) <=> F is the list of automata's final states */
states([q0, q1, q2]).
symbols([a, b]).
transition(q0, a, q1).
transition(q0, b, q2).
transition(q1, a, q2).
transition(q1, b, q0).
transition(q2, a, q1).
transition(q2, b, q2).
startState(q0).
finalStates([q2]).
It looks like you have successfully encoded your automaton in Prolog. What you are actually missing is the code to execute it. So let's think about what's needed to do that. First, we need to kick off the execution by passing the input to something to run it. That first thing will find the start state and use that. Then we'll run a loop, finding the transition for this state and the next input value and next state. If we run out of input and are in a final state, then we have succeeded. So it seems like the only thing special about the first call is that it looks up the initial state.
In true inductive fashion, let's write the termination condition first.
step(State, []) :- finalStates(FinalStates), memberchk(State, FinalStates).
This simply says that if we try to perform a step when we're out of input, the state we were in is in the list of final states. Now let's try to run a step that is not the final step. We'll recursively call step/2 to implement a loop.
step(State, [Sym|Tape]) :-
transition(State, Sym, NextState),
step(NextState, Tape),
!.
This simply peels off the next symbol on the tape and finds the right next state based on it, and recurs. I have added the cut here to prevent it from attempting to find other transitions; if you were building an NFA you might want to remove that. Now what we are missing is the initial driver, which I'll just call evaluate:
evaluate(Tape) :-
startState(Start),
step(Start, Tape).
Let's try this out on a few inputs:
?- evaluate([a,a,a,a]).
true.
This succeeded because it transitioned from q0 -> q1 -> q2 -> q1 -> q2 and q2 is a final state.
?- evaluate([a,a,a]).
false.
This failed because it transitioned from q0 -> q1 -> q2 -> q1 and q1 is not a final state.
Now on to finding strings that match. We can generate them quite easily since we have the set of symbols on-hand; let's make a little helper predicate:
symbol(X) :- symbols(Symbols), member(X, Symbols).
This is something we can use easily with maplist/2 to generate sample inputs:
?- length(L, 3), maplist(symbol, L).
L = [a, a, a] ;
L = [a, a, b] ;
L = [a, b, a] ;
L = [a, b, b] ;
L = [b, a, a] ;
L = [b, a, b] ;
L = [b, b, a] ;
L = [b, b, b].
Now you can do a classic generate-and-test thing with Prolog:
?- length(L, 3), maplist(symbol, L), evaluate(L).
L = [a, a, b] ;
L = [a, b, b] ;
L = [b, a, a] ;
L = [b, b, b].
To find an even list of symbols that works, make a helper for finding evens and we'll use between/3 to generate lists of those lengths and then do the same kind of thing:
even(X) :- 0 is X mod 2.
Trying:
?- between(1,100,X), even(X).
X = 2 ;
X = 4 ;
X = 6 ;
X = 8 .
?- between(1,100,X), even(X), length(L, X).
X = 2,
L = [_2954, _2960] ;
X = 4,
L = [_2954, _2960, _2966, _2972] ;
X = 6,
L = [_2954, _2960, _2966, _2972, _2978, _2984] .
?- between(1,100,X), even(X), length(L, X), maplist(symbol, L).
X = 2,
L = [a, a] ;
X = 2,
L = [a, b] ;
X = 2,
L = [b, a] ;
X = 2,
L = [b, b] ;
X = 4,
L = [a, a, a, a] ;
X = 4,
L = [a, a, a, b] ;
X = 4,
L = [a, a, b, a] ;
X = 4,
L = [a, a, b, b] ;
X = 4,
L = [a, b, a, a] ;
X = 4,
L = [a, b, a, b] ;
X = 4,
L = [a, b, b, a] ;
X = 4,
L = [a, b, b, b] ;
X = 4,
L = [b, a, a, a] .
?- between(1,100,X), even(X), length(L, X), maplist(symbol, L), evaluate(L).
X = 2,
L = [a, a] ;
X = 2,
L = [b, b] ;
X = 4,
L = [a, a, a, a] ;
X = 4,
L = [a, a, b, b] ;
X = 4,
L = [a, b, a, a] ;
X = 4,
L = [a, b, b, b] ;
X = 4,
L = [b, a, a, b] ;
X = 4,
L = [b, a, b, b] ;
X = 4,
L = [b, b, a, a] ;
X = 4,
L = [b, b, b, b] ;
X = 6,
L = [a, a, a, a, a, a]
I'm new to Prolog and trying to figure out how it works. So could anyone help me with the following code:
whatisthis([]).
whatisthis([_, b| L]):- whatisthis(L).
So when would Prolog return 'True' if the query would have the following format:
?- whatisthis(X).
I experimented with some different inputs and the only X that returned 'True' was X = [].
This query is even that declarative that you can query what X will be true:
?- whatisthis(X).
X = [] ;
X = [_G1242, b] ;
X = [_G1242, b, _G1248, b] ;
X = [_G1242, b, _G1248, b, _G1254, b] ;
X = [_G1242, b, _G1248, b, _G1254, b, _G1260, b] ;
X = [_G1242, b, _G1248, b, _G1254, b, _G1260, b, _G1266|...]
If you hit the semicolon ; it will emit the next result. The _Gxxxx parts are unbound variables. You can write anything there.
So every X that is a list of even length where every second element is a b. So the following examples will succeed:
[]
[a, b]
[2, b]
[1, b, 4, b]
[a, b, 1, b]
[f(a,b), b, b(f,a), b]
[1, b, 4, b, 2, b, 5, b]
I'm quite new to Prolog. I got stuck with this problem:
If I have two lists, how do I check if list 1 contains all of the elements of the second list, but they don't have to be equal. So list 2 might contain more elements.
I know I can use member/2 to check if a certain element is in a list. But I don't know how to not include these members of both lists after I checked them. So for example:
If I have list A = [a,b,c,a] and list B = [a,b,c,d,e] and I start by checking if the first 'a' from list A is in list B. Obviously this returns a True, but if I check the last 'a' from list A, I should get a False returned, since list A has 2 'a's and B only 1, instead I get True returned. I really have no clue on how to fix this problem.
I would really appreciate if someone could help me :)
Thanks!
Edit: Explained my question a bit more
select/3 does exactly what we want:
is_sublist([], []).
is_sublist([], [_|_]).
is_sublist([H|T], L) :-
once(select(H, L, L2)),
is_sublist(T, L2).
We wrap it in once/1 to avoid redundant successes in cases where an element appears multiple times.
Note: you can remove once/1 to get more working behaviors:
?- is_sublist(Z,[a,b,c]). % Without once
Z = [] ;
Z = [a] ;
Z = [a, b] ;
Z = [a, b, c] ;
Z = [a, c] ;
Z = [a, c, b] ;
Z = [b] ;
Z = [b, a] ;
Z = [b, a, c] ;
Z = [b, c] ;
Z = [b, c, a] ;
Z = [c] ;
Z = [c, a] ;
Z = [c, a, b] ;
Z = [c, b] ;
Z = [c, b, a] ;
false.
This will not enumerate all possible answers in the opposite direction, so not everything is perfect:
?- is_sublist([a,b],Z). % Without once
Z = [a, b] ;
Z = [a, b, _886|_888] ;
Z = [a, _880, b|_888] ;
Z = [a, _880, _892, b|_900] ;
Z = [a, _880, _892, _904, b|_912]
…
Using Prolog I'm trying to write a predicate that recognizes context free grammar and returns true if the input list matches the CFG.
The alphabet of the input consists only of a,b.
The CFG i'm trying to match is
S-> TT
T -> aTb | ab
I'm not quite sure how to implement this, mainly the T rule.
s(S0,S):-t(S0,S),t(S1,S).
t(S0,S):-S0 = a, t(S1,S), S1 = b; S0 = a, S1 = b.
match([H|T] :- s(H,T).
So if I query [a, a, b, b] it should return true.
However, I'm just getting an infinite loop.
I'm not quite sure how to implement the a^n b^n rule.
I would write the CFG in this way:
S -> T
T -> a T b | {epsilon}
that translates directly to a DCG:
s --> t.
t --> [].
t --> a, t, b.
Note I swapped the epsilon rule, to get the ability to generate phrases.
Translating that DCG by hand :
s(S0,S) :- t(S0,S).
t(S0,S0).
t(S0,S) :- S0=[a|S1], t(S1,S2), S2=[b|S].
Yields
?- phrase(s,L).
L = [] ;
L = [a, b] ;
L = [a, a, b, b] ;
L = [a, a, a, b, b, b] ;
...
Consider the following list of states:
[Sin,S2,S3,...,Sout]
and following rules:
it is possible to go back from S(n) to S(n-1) if there is such
S(n-1)
it is not possible to go back from S(out)
a sentence always begins with S(in) and ends with S(out)
I would like to have a rule that could be activated like this:
?- sentence(X, backs)
in which 'backs' means how many times a "back" is allowed.
For this list [a,b,c,d]
?- sentence(x, 2)
would generate:
[a,b,c,d] %no backs
[a,b,a,b,c,d] %one back
[a,b,c,b,c,d] %from d we cannot go back
[a,b,a,b,c,b,c,d] %two backs
[a,b,c,b,a,b,c,d] %two backs
Here's something that seems to be working:
sentence( [A|B], N, [A|X]) :- B=[_|_] -> sentence(B,[A],N,X)
; B = X.
sentence( B, _, 0, B). % no more moves back left
sentence( [B,C], _, N, [B,C]):- N>0. % no going back from end node
sentence( [B|C], A, N, [B|X]):- N>0, C=[_|_],
sentence( C, [B|A], N, X). $ fore
sentence( [B|C], [A|D], N, [B|X]):- N>0, C=[_|_], N1 is N-1,
sentence( [A,B|C], D, N1, X). $ aft
Running it gives me
23 ?- sentence([a,b,c,d],2,X).
X = [a, b, c, d] ;
X = [a, b, c, b, c, d] ;
X = [a, b, c, b, c, b, c, d] ;
X = [a, b, c, b, a, b, c, d] ;
X = [a, b, a, b, c, d] ;
X = [a, b, a, b, c, b, c, d] ;
X = [a, b, a, b, a, b, c, d] ;
No