Prolog DCG definition with additional arguments
I am trying to define Prolog DCG for a set of rows 0 ^ N 1 ^ M 2 ^ N + M of length 2N + 2M for N, M> = 0 using additional arguments. An example of a valid string would be "011222" but not "012".
I used the following code to create this DCG.
s --> a(N), b(M), c(N), c(M).
a(0) --> [].
a(succ(X)) --> [0], a(X).
b(0) --> [].
b(succ(X)) --> [1], b(X).
c(0) --> [].
c(succ(X)) --> [2], c(X).
When I run the request
s([0,1,1,2,2,2], []).
Prolog returns true as expected.
However, when I run
s(X, []).
Prolog returns the following:
X = []
X = [1,2]
X = [1,1,2,2]
X = [1,1,1,2,2,2]
These are invalid strings. I think this might be due to the fact that N and M are decremented by predicate c before the prologue executes predicates a and b. This is true? How can this be solved?
Edit: I've tried modifying the s version for this:
s --> a(N), b(M), c(NplusM), {NplusM is N + M}.
but this results in an error when executing queries.
source to share
You are using succ / 2 incorrectly, perhaps because you expect Prolog to evaluate functions in head templates. This is not true. Then try replacing your rules with
a(0) --> [].
a(Y) --> {succ(X,Y)}, [0], a(X).
etc.
since succ / 2 needs at least one argument created for an integer, we could put N, M in the DCG record, or using CLP (FD):
:- use_module(library(clpfd)).
s --> a(N), b(M), c(N), c(M).
a(0) --> [].
a(Y) --> {Y #= X-1}, [0], a(X).
b(0) --> [].
b(Y) --> {Y #= X-1}, [1], b(X).
c(0) --> [].
c(Y) --> {Y #= X-1}, [2], c(X).
but the length of the list must be specified. for example
?- length(L,_),phrase(s,L). L = [] ; L = [1, 2] ; L = [0, 2] ; L = [1, 1, 2, 2] ; L = [0, 1, 2, 2] ; L = [0, 0, 2, 2] ; ...
source to share
IMO the answers you get are correct!
I renamed your grammar from s
to aN_bM_cNM
and added two additional arguments, one for N
and one for M
. Also, I renamed succ
to s
:
aN_bM_cNM (N, M) -> n_reps (N, 0), n_reps (M, 1), n_reps (N, 2), n_reps (M, 2). n_reps (0, _) -> []. n_reps (s (N), E) -> [E], n_reps (N, E).
Now run the query that @CapelliC gave. The goal length(Xs, _)
provides a fair listing of an infinite set of solutions aN_bM_cNM//2
:
? - length (Xs, _), phrase (aN_bM_cNM (N, M), Xs). (Xs = [], N = 0, M = 0 ; Xs = [1,2], N = 0, M = s (0) ; Xs = [0.2], N = s (0), M = 0 ; Xs = [1,1,2,2], N = 0, M = s (s (0)) ; Xs = [0,1,2,2], N = s (0), M = s (0) ; Xs = [0,0,2,2], N = s (s (0)), M = 0 ; Xs = [1,1,1,2,2,2], N = 0, M = s (s (s (0))) ; Xs = [0,1,1,2,2,2], N = s (0), M = s (s (0)) ; Xs = [0,0,1,2,2,2], N = s (s (0)), M = s (0) ; Xs = [0,0,0,2,2,2], N = s (s (s (0))), M = 0 ; Xs = [1,1,1,1,2,2,2,2], N = 0, M = s (s (s (s (0)))) ...
To raise the bottom border N
or M
, just provide an additional shape target X = s(s(_))
(for a minimum value of 2). In the next request, the values N
and M
must be greater 0
:
? - N = s (_), M = s (_), length (Xs, _), phrase (aN_bM_cNM (N, M), Xs). (N = s (0), M = s (0), Xs = [0,1,2,2] ; N = s (0), M = s (s (0)), Xs = [0,1,1,2,2,2] ; N = s (s (0)), M = s (0), Xs = [0,0,1,2,2,2] ; N = s (0), M = s (s (s (0))), Xs = [0,1,1,1,2,2,2,2] ...
source to share