Natural Language processing with prolog error - parsing

I'm new to using prolog and I'm trying things to get a text parsed and translated in this way:
?- go.
|: All boys run.
s(np(det(all),noun(boys)),vp(verb(run)))
S = all(_4326, boy(_4326)->run(_4326))
but I'm having an error: I run go. to get the translation, I get the following error:
go.
|: All boys run
**ERROR: Stream user_input:242:4 Syntax error: Operator expected**
Here is my code.
% Tokenizer
go1(Out):-
read(X),
name(X,L),
tokenize(L,Out).
tokenize([],[]):- !.
tokenize(L,[Word|Out]):- L\==[],
tokenize(L,Rest,WordChs),
name(Word,WordChs),
tokenize(Rest,Out).
tokenize([],[],[]):- !.
tokenize([46|_],[],[]):- !.
tokenize([32|T],T,[]):- !.
tokenize([H|T],Rest,[H|List]):-
tokenize(T,Rest,List).
% Main predicate
go :-
%go1(X),
readln(X, _, _, _, lowercase),
reset_gensym,
sentence(P, X, []),
translator(P, R),
write(R).
%Operator's definition
:- op(600,xfy,=>).
:- op(500,xfy,&).
%Grammar + Parser
sentence(sentence(NP, VP)) --> noun_phrase(Num, NP), verb_phrase(Num, VP).
%test cases
% All boys run
% All boys like all watermelons that contain some divine flavor
% Some boy eats some apple
% Some government conscripts some pacifist people
% All government that conscripts pacifist people are evil
noun_phrase(Num, np(DET, N)) --> determiner(Num, DET), noun(Num, N).
noun_phrase(Num, np(ADJ, N)) --> adjective(ADJ), noun(Num, N).
noun_phrase(Num, np(DET, ADJ, N)) --> determiner(Num, DET), adjective(ADJ), noun(Num, N).
noun_phrase(Num, np(DET, N, RCL)) --> determiner(Num, DET), noun(Num, N), relative_clause(Num, RCL).
noun_phrase(Num, np(N)) --> noun(Num, N).
verb_phrase(Num, vp(V)) --> verb(Num, itrans, V).
verb_phrase(Num, vp(V, NP)) --> verb(Num, trans, V), noun_phrase(_, NP).
verb_phrase(Num, vp(BV, ADJ)) --> beVerb(Num, BV), adjective(ADJ).
relative_clause(Num, rcl(REL, VP)) --> rel(REL), verb_phrase(Num,VP).
relative_clause(Num, rcl(REL, NP, V)) --> rel(REL), noun_phrase(Num,NP), verb(Num, itrans, V).
adjective(adj(good)) --> [good].
adjective(adj(evil)) --> [evil].
adjective(adj(big)) --> [big].
adjective(adj(divine)) --> [divine].
adjective(adj(pacifist)) --> [pacifist].
adjective(adj(nice)) --> [nice].
is_det(plural, all).
is_det(singular, a).
is_det(_, the).
is_det(_, some).
determiner(Num, determiner(D)) --> [D], {is_det(Num, D)}.
is_noun(plural, boys).
is_noun(singular, boy).
is_noun(plural, girls).
is_noun(singular, girl).
is_noun(plural, people).
is_noun(singular, person).
is_noun(plural, apples).
is_noun(singular, apple).
is_noun(plural, watermelons).
is_noun(singular, watermelon).
is_noun(plural, rabbits).
is_noun(plural, carrots).
is_noun(plural, evil).
is_noun(plural, governments).
is_noun(singular, government).
is_noun(singular, flavor).
noun(Num,noun(N)) --> [N], {is_noun(Num,N)}.
is_verb(plural, trans, like).
is_verb(singular, trans, likes).
is_verb(plural, _, eat).
is_verb(singular, _, eats).
is_verb(plural, itrans, run).
is_verb(singular, itrans, runs).
is_verb(plural, trans, contain).
is_verb(singular, trans, contains).
is_verb(plural, trans, conscript).
is_verb(singular, trans, conscripts).
verb(Num, Tp, v(V)) --> [V], {is_verb(Num, Tp, V)}.
beVerb(plural, bv(tastes)) --> [taste].
beVerb(plural, bv(iss)) --> [are].
beVerb(singular, bv(iss)) --> [iss].
beVerb(singular, bv(sounds)) --> [sounds].
rel(rel(that)) --> [that].
% Rules for translator
translator(sentence(NP,VP),F) :-
% genera un unico atomo de la X y lo unifica en Var
gensym(x,Var),
np(Var,NP,T),
vp(Var,T,VP,F).
% Translation of noun phrase
np(Var, np(DET,N), R) :-
n(Var, N, P1),
det(DET, P1, R).
np(Var, np(DET,ADJ,N), R) :-
adj(Var, ADJ, P1),
n(Var, N, P1, P2),
det(DET, P2, R).
np(Var, np(ADJ, N), R) :-
adj(Var, ADJ, P1),
n(Var, N, P1, R).
np(Var, np(DET, N, RCL), R) :-
n(Var, N, P1),
rcl(Var, RCL, P1, P2),
det(DET, P2, R).
np(Var, np(N), R) :-
n(Var, N, R).
rcl(Var, rcl(_, VP), T, R) :- vp(Var, T, VP, R).
% This predicate add an implication or conjuction between F1 and F2
q_join(all, V, F1, F2, all(V, F1 => F2)).
q_join(exists, V, F1, F2, exists(V, F1 & F2)).
% Translation of verb phrase
vp(Var, P, vp(V), R) :-
P =.. [Q, V1, F1],
v(Var, V, C),
q_join(Q, V1, F1, C, R).
vp(Var, P, vp(bv(BVERB), adj(ADJ)), R) :-
P =.. [Q, V1, F1],
C =.. [BVERB, Var, ADJ],
q_join(Q, V1, F1, C, R).
vp(Var, P, vp(V, NP), R) :-
P =.. [Q1, V1, F1],
gensym(x,X),
v(Var, X, V, C),
np(X, NP, T),
T =.. [Q2, V2, F2],
q_join(Q2, V2, F2, C, R1),
q_join(Q1, V1, F1, R1, R).
% Terminals symbols, they create functors
det(determiner(all), P, R) :-
P =.. [_, V, F],
R =.. [all, V, F],
!.
det(determiner(_), P, P).
n(Var, noun(N), exists(Var, P)) :- P =.. [N, Var].
n(Var, noun(N), A, exists(Var, (P & A))) :- P =.. [N, Var].
v(Var, v(V), P) :- P =.. [V, Var].
v(V1, Var, v(V), P) :- P =.. [V, V1, Var].
adj(Var,adj(ADJ),P) :- P =.. [ADJ, Var].

Related

How to combine two sums and factor out a common element expression?

Here's the initial premise: two sums s1 and s2 are added; the sum element expressions have a common factor a[n].
s1: sum(r1[m,q]*b[m,n]*a[n],n,0,N)$
s2: sum(r2[m,q]*c[m,n]*a[n],n,0,N)$
s1+s2;
I expect the sums to be combined and the common element expression a[n] factored out:
s12: sum(a[n]*(r1[m,q]*b[m,n]+r2[m,q]*c[m,n]),n,0,N);
However, I'm unable to make Maxima produce such contraction. The most simplification I was able to obtain was using sumcontract(s1+s2) and it results in two sums without the common element being factored out:
r1[m,q]*sum(b[m,n]*a[n], n,0,N) + r2[m,q]*sum(c[m,n]*a[n], n,0,N);
How to make Maxima produce the factored out expression from s1+s2 as in s12 above?
NOTE: If we remove the r1 and r2, then the factor(sumcontract(s1+s2)) indeed results in the expected s12 expression. However, with both present, it results in two sums and does not factor out the a[n] as mentioned.
How about this. I've applied sumcontract, intosum, and factor.
(%i1) s1: sum(r1[m,q]*b[m,n]*a[n],n,0,N)$
(%i2) s2: sum(r2[m,q]*c[m,n]*a[n],n,0,N)$
(%i3) s1 + s2;
N N
==== ====
\ \
(%o3) r2 > c a + r1 > b a
m, q / m, n n m, q / m, n n
==== ====
n = 0 n = 0
(%i4) intosum (%);
N N
==== ====
\ \
(%o4) > c r2 a + > b r1 a
/ m, n m, q n / m, n m, q n
==== ====
n = 0 n = 0
(%i5) sumcontract (%);
N
====
\
(%o5) > (c r2 a + b r1 a )
/ m, n m, q n m, n m, q n
====
n = 0
(%i6) factor (%);
N
====
\
(%o6) > (c r2 + b r1 ) a
/ m, n m, q m, n m, q n
====
n = 0
In this, intosum is pushing constant factors back into the sum.

Proof about a function that uses rewrite: a "vertical bars in goals" question

I have a function that uses rewrite to satisfy the Agda type checker. I thought that I had a reasonably good grasp of how to deal with the resulting "vertical bars" in proofs about such functions. And yet, I fail completely at dealing with these bars in my seemingly simple case.
Here are the imports and my function, step. The rewrites make Agda see that n is equal to n + 0 and that suc (acc + n) is equal to acc + suc n, respectively.
module Repro where
open import Relation.Binary.PropositionalEquality as P using (_≡_)
open import Data.Nat
open import Data.Nat.DivMod
open import Data.Nat.DivMod.Core
open import Data.Nat.Properties
open import Agda.Builtin.Nat using () renaming (mod-helper to modₕ)
step : (acc d n : ℕ) → modₕ acc (acc + n) d n ≤ acc + n
step zero d n rewrite P.sym (+-identityʳ n) = a[modₕ]n<n n (suc d) 0
step (suc acc) d n rewrite P.sym (+-suc acc n) = a[modₕ]n<n acc (suc d) (suc n)
Now for the proof, which pattern matches on acc, just like the function. Here's the zero case:
step-ok : ∀ (acc d n : ℕ) → step acc d n ≡ a[modₕ]n<n acc d n
step-ok zero d n with n | P.sym (+-identityʳ n)
step-ok zero d n | .(n + 0) | P.refl = ?
At this point, Agda tells me I'm not sure if there should be a case for the constructor P.refl, because I get stuck when trying to solve the following unification problems (inferred index ≟ expected index): w ≟ w + 0 [...]
I am also stuck in the second case, the suc acc case, albeit in a different way:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n)
step-ok (suc acc) d n | .(acc + suc n) | P.refl = ?
Here, Agda says suc (acc + n) != w of type ℕ when checking that the type [...] of the generated with function is well-formed
Update after Sassa NF's response
I followed Sassa NF's advice and reformulated my function with P.subst instead of rewrite. I.e., I changed my right-hand side from being about n + 0 to being about n, instead of conversely changing the goal from being about n to being about n + 0:
step′ : (acc d n : ℕ) → modₕ acc (acc + n) d n ≤ acc + n
step′ zero d n = P.subst (λ # → modₕ 0 # d # ≤ #) (+-identityʳ n) (a[modₕ]n<n n (suc d) 0)
step′ (suc acc) d n = P.subst (λ # → modₕ (suc acc) # d n ≤ #) (+-suc acc n) (a[modₕ]n<n acc (suc d) (suc n))
During the proof, the P.subst in the function definition needs to be eliminated, which can be done with a with construct:
step-ok′ : ∀ (acc d n : ℕ) → step′ acc d n ≡ a[modₕ]n<n acc d n
step-ok′ zero d n with n + 0 | +-identityʳ n
... | .n | P.refl = P.refl
step-ok′ (suc acc) d n with acc + suc n | +-suc acc n
... | .(suc (acc + n)) | P.refl = P.refl
So, yay! I just finished my very first Agda proof involving a with.
Some progress on the original problem
My guess would be that my first issue is a unification issue during dependent pattern matching: there isn't any substitution that makes n identical to n + 0. More generally, in situations where one thing is a strict subterm of the other thing, I suppose that we may run into unification trouble. So, maybe using with to match n with n + 0 was asking for problems.
My second issue seems to be what the Agda language reference calls an ill-typed with-abstraction. According to the reference, this "happens when you abstract over a term that appears in the type of a subterm of the goal or argument types." The culprit seems to be the type of the goal's subterm a[modₕ]n<n (suc acc) d n, which is modₕ [...] ≤ (suc acc) + n, which contains the subterm I abstract over, (suc acc) + n.
It looks like this is usually resolved by additionally abstracting over the part of the goal that has the offending type. And, indeed, the following makes the error message go away:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n) | a[modₕ]n<n (suc acc) d n
... | .(acc + suc n) | P.refl | rhs = {!!}
So far so good. Let's now introduce P.inspect to capture the rhs substitution:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n) | a[modₕ]n<n (suc acc) d n | P.inspect (a[modₕ]n<n (suc acc) d) n
... | .(acc + suc n) | P.refl | rhs | P.[ rhs-eq ] = {!!}
Unfortunately, this leads to something like the original error: w != suc (acc + n) of type ℕ when checking that the type [...] of the generated with function is well-formed
One day later
Of course I'd run into the same ill-typed with-abstraction again! After all, the whole point of P.inspect is to preserve a[modₕ]n<n (suc acc) d n, so that it can construct the term a[modₕ]n<n (suc acc) d n ≡ rhs. However, preserved a[modₕ]n<n (suc acc) d n of course still has its preserved original type, modₕ [...] ≤ (suc acc) + n, whereas rhs has the modified type modₕ [...] ≤ acc + suc n. That's what's causing trouble now.
I guess one solution would be to use P.subst to change the type of the term we inspect. And, indeed, the following works, even though it is hilariously convoluted:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n) | a[modₕ]n<n (suc acc) d n | P.inspect (λ n → P.subst (λ # → modₕ (suc acc) # d n ≤ #) (P.sym (+-suc acc n)) (a[modₕ]n<n (suc acc) d n)) n
... | .(acc + suc n) | P.refl | rhs | P.[ rhs-eq ] rewrite +-suc acc n = rhs-eq
So, yay again! I managed to fix my original second issue - basically by using P.subst in the proof instead of in the function definition. It seems, though, that using P.subst in the function definition as per Sassa NF's guidance is preferable, as it leads to much more concise code.
The unification issue is still a little mysterious to me, but on the positive side, I unexpectedly learned about the benefits of irrelevance on top of everything.
I'm accepting Sassa NF's response, as it put me on the right track towards a solution.
Your use of P.refl indicates some misunderstanding about the role of _≡_.
There is no magic in that type. It is just a dependent type with a single constructor. Proving that some x ≡ y resolves to P.refl does not tell Agda anything new about x and y: it only tells Agda that you managed to produce a witness of the type _≡_. This is the reason it cannot tell n and .(n + 0) are the same thing, or that suc (acc + n) is the same as .(acc + suc n). So both of the errors you see are really the same.
Now, what rewrite is for.
You cannot define C x ≡ C y for dependent type C _. C x and C y are different types. Equality is defined only for elements of the same type, so there is no way to even express the idea that an element of type C x is comparable to an element of type C y.
There is, however, an axiom of induction, which allows to produce elements of type C y, if you have an element of type C x and an element of type x ≡ y. Note there is no magic in the type _≡_ - that is, you can define your own type, and construct such a function, and Agda will be satisfied:
induction : {A : Set} {C : (x y : A) -> (x ≡ y) -> Set} (x y : A) (p : x ≡ y) ((x : A) -> C x x refl) -> C x y p
induction x .x refl f = f x
Or a simplified version that follows from the induction axiom:
transport : {A : Set} {C : A -> Set} (x y : A) (x ≡ y) (C x) -> C y
transport x .x refl cx = cx
What this means in practice, is that you get a proof for something - for example, A x ≡ A x, but then transport this proof along the equality x ≡ y to get a proof A x ≡ A y. This usually requires specifying the type explicitly, in this case {C = y -> A x ≡ A y}, and provide the x, the y and the C x. As such, it is a very cumbersome procedure, although the learners will benefit from doing these steps.
rewrite then is a syntactic mechanism that rewrites the types of the terms known before the rewrite, so that such transport is not needed after that. Because it is syntactic, it does interpret the type _≡_ in a special way (so if you define your own type, you need to tell Agda you are using a different type as equality). Rewriting types is not "telling" Agda that some types are equal. It just literally replaces occurrences of x in type signatures with y, so now you only need to construct things with y and refl.
Having said all that, you can see why it works for step. There rewrite P.sym ... literally replaced all occurrences of n with n + 0, including the return type of the function, so now it is modₕ acc (acc + (n + 0)) d (n + 0) ≤ acc + (n + 0). Then constructing a value of that type just works.
Then step-ok didn't work, because you only pattern-matched values. There is nothing to tell that n and (n + 0) are the same thing. But rewrite will. Or you could use a function like this transport.

MergeSort and Quicksort in Erlang not working

Can someone help me figure out what's wrong with my sorting algorithms. I get no errors but get stuck in some kind of infinite loop. The functions seem to work individually.
msort([])->
[];
msort(L)->
{L3, L4} = msplit(L, [],[]),
merge(msort(L3), msort(L4)).
msplit([], L1, L2)->
{L1, L2};
msplit([H|[]], L1, L2)->
msplit([], [H]++L1, L2);
msplit([H|[H2|T]], A, B)->
msplit(T, A++[H], B++[H2]).
merge(L, [])->L;
merge([], R)->R;
merge([H1|T1], [H2|T2])->
if H1 < H2
-> [H1|merge(T1, [H2|T2])];
true-> [H2|merge([H1|T1], T2)]
end.
qsort([])->[];
qsort([H|T])->
{A, B} =qsplit(T, H, [], []),
Small =qsort(A),
Large = qsort(B),
lists:append(Small,Large).
qsplit([], H, A, B)->
{A++[H], B};
qsplit([H|T], P, A, B)->
if H > P->
qsplit(T, P, A++[H], B);
true-> qsplit(T, P, A, B++[H])
end.
After some changes the code is working properly:
msort([]) ->
[];
msort([_] = L) ->
L;
msort(L)->
{L3, L4} = msplit(L, [],[]),
merge(msort(L3), msort(L4)).
msplit([], L1, L2)->
{L1, L2};
msplit([H|[]], L1, L2)->
msplit([], [H|L1], L2);
msplit([H|[H2|T]], A, B)->
msplit(T, [H|A], [H2|B]).
merge(L, [])->L;
merge([], R)->R;
merge([H1|T1], [H2|T2])->
if H1 < H2
-> [H1|merge(T1, [H2|T2])];
true-> [H2|merge([H1|T1], T2)]
end.
qsort([])->[];
qsort([_] = L)->L;
qsort([H|T])->
{A, B} =qsplit(T, H, [], []),
Large =qsort(A),
Small = qsort(B),
lists:append(Small,[H|Large]).
qsplit([], _, A, B)->
{A, B};
qsplit([H|T], P, A, B)->
if H > P->
qsplit(T, P, [H|A], B);
true-> qsplit(T, P, A, [H|B])
end.
If you call msort/1 with a list containing just one item [X] your msplit/1 will return {[X], []} where you call msort/1 with one item [X] and so on. You can fix it by adding msort/1 function clause:
msort([])->
[];
msort([_] = L) ->
L;
msort(L)->
...
A similar problem is in your qsort/1.
There are more problems in your code. You should replace all your A++[H] with [H] ++ A which is even better written as [H|A]. It has big impact to an efficiency of your code. You can use [H, H2 | T] instead of [H | [H2 | T]], it is nice syntactic sugar which helps readability.

Using Prolog to Parse Grammar

I would like to use Prolog to parse the following grammar:
E -> E + T | E - T |T
T -> T * F | T / F | F
F -> ( E ) | number | letter
Here's a test case that should be true (My problem is that it is currently coming out as false):
e([ 34 , *, '(', 45, +, b, ')']).
i.e. 34 * (45 + b)
And here is my attempt:
e(X) :- append(List1, [+ | List2], X), e(List1), t(List2).
e(X) :- append(List1, [- |List2], X), e(List1), t(List2).
t(X) :- append(List1, [* | List2], X), t(List1), f(List2).
t(X) :- append(List1, [/ | List2], X), t(List1), f(List2).
t(X) :- f(X).
f(X) :- append(['(' | List], [')'], X), e(List).
letter(X) :- member(X, [a, b, c, d, e, f, g, h, i, j, k, l, m,
n, o, p, q, r, s, t, u, v, w, x, y, z]).
f([X]) :- number(X).
f([X]) :- letter(X).

semantic web rule use "all"

Assume that I have the following statements:
A p B, A p C, B p C ( p is a symmetric property, i.e. B p A, C p A and C p B)
A v 2, B v 1, C v 1,
I want to use a rule to do something like:
?a p all(?b)
if ?b v 1
than ?a q 'Yes'
that means that you can infer (A q 'Yes'), but B can't since B p A and A v 2(although B p C and C v 1).
[rule: (?a eg:p ?b), (?b eg:v 1) -> (?a eg:q 'Yes')]
I've used the above rule in Jena, but I got A,B,C eg:q 'Yes', which is wrong.
Any help will be greatly appreciated.
Update (originally posted as an answer)
the meaning of (?a p all(?b)) is that I like to get a set which all ?mem in this set fulfill the (?a p ?mem). And all member must fulfill (?mem v 1) to infer (?a q 'Yes').
For example,
A p B and A p C,so I get a set which contains (B, C).since B and C v 1,so A q 'Yes.
B p A and B p C,so I get a set(A, C),but A v 2,so can't infer that B q 'Yes'.
Problem Solved
Thanks to Joshua Taylor.
Firstly, these two rules can't use at the same time.The rule2 should be used after rule1.
And, the rule2 should be [rule2: (?s ?p ?o) noValue(?s, connectedToNonOne) -> (?s q 'Yes')].
but I got A,B,C eg:q 'Yes', which is wrong.
The rule you have actually written in Jena says
For any two individuals X and Y, if (X p Y) and (Y v 1) then (X q 'Yes').
From the rule you've written, this is correct, by:
(A p C), (C v 1) &rightarrow; (A q 'Yes')
(B p C), (C v 1) &rightarrow; (B q 'Yes')
(C p B), (B v 1) &rightarrow; (C q 'Yes')
What you're actually trying to say is:
For any individual X, if for every individual Y, (X p Y) implies (Y v 1), then (X q 'Yes').
In first order logic, your original rule could be written as:
∀ x,y ([p(x,y) &wedge; v(y,1)] &rightarrow; q(x,'yes')
What you're actually trying to capture would be:
∀x[(∀y[p(x,y) &rightarrow; v(y,1)]) &rightarrow; q(x,'yes')]
That's harder to capture in Jena rules, because to check whether (∀y[p(x,y) &rightarrow; v(y,1)]) holds or not, all Jena can do is check whether there are currently any counterexamples. If one were added later, you might have incorrect inferences.
Using the builtins available in the rule reasoner, you could do something with noValue and notEqual along the lines of:
#-- If an individual is disqualified by being
#-- connected to a something that is connected
#-- to something that is not equal to 1, then
#-- add a connectedToNonOne triple.
[rule1:
(?x p ?y), (?y v ?z), notEqual(?z,1)
->
(?x connectedToNonOne true)]
#-- Mark everything that is *not* disqualified
#-- with `q 'Yes'`.
[rule2:
noValue(?x, connectedToNonOne)
->
(?x q 'Yes')

Resources