Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 190 lines (153 sloc) 5.816 kb
72c6ab2 @tkuhn Initial commit: ape-6.6-110816
tkuhn authored
1 % This file is part of the Attempto Parsing Engine (APE).
89f4e65 @tkuhn Uniform copyright statements
tkuhn authored
2 % Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch).
72c6ab2 @tkuhn Initial commit: ape-6.6-110816
tkuhn authored
3 %
4 % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it
5 % under the terms of the GNU Lesser General Public License as published by the Free Software
6 % Foundation, either version 3 of the License, or (at your option) any later version.
7 %
8 % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT
9 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 % PURPOSE. See the GNU Lesser General Public License for more details.
11 %
12 % You should have received a copy of the GNU Lesser General Public License along with the Attempto
13 % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/.
14
15
16 :- module(are_equivalent, [
17 check_equivalence/2,
18 are_equivalent/2,
19 are_equivalent/3
20 ]).
21
22
23 /** <module> Equivalence checking of two Attempto DRSs
24
25 @author Kaarel Kaljurand
26 @version 2011-07-21
27
28 BUG: Think if this code is correct and complete.
29
30 OBSOLETE COMMENT: Note that the DRACE-tester also uses the notion of equivalence defined here,
31 but for DRACE it is sometimes too strict,
32 e.g. DRACE NP considers reversing the arguments of `be' equivalence-preserving,
33 to be able to perform the transformation:
34
35 ==
36 John is every man. --> Every man is John.
37 ==
38
39 But given the definition of equivalence here, they are not.
40 Similarly:
41
42 ==
43 If there is a man then it is necessary that a human is the man. --> Every man must be a human.
44 ==
45 */
46
47
48 :- use_module(drs_to_ascii).
49 :- use_module(is_wellformed).
50 :- use_module(drs_ops).
51
52 :- dynamic conds_unify/2.
53
54
55 %% check_equivalence(+Drs1:term, +Drs2:term) is det.
56 %
57 % @param Drs1 is an Attempto DRS
58 % @param Drs2 is an Attempto DRS
59 %
60 check_equivalence(Drs1, Drs2) :-
61 are_equivalent(Drs1, Drs2),
62 write('OK: the DRSs are equivalent.'), nl,
63 !.
64
65 check_equivalence(Drs1, Drs2) :-
66 write('ERROR: the DRSs are NOT equivalent.'), nl,
67 display_drs(Drs1),
68 display_drs(Drs2).
69
70
71 %% are_equivalent(+Drs1:term, +Drs2:term) is det.
72 %% are_equivalent(+Drs1:term, +Drs2:term, +Options:list) is det.
73 %% are_equivalent_x(+Drs1:term, +Drs2:term) is det.
74 %
75 % @param Drs1 is an Attempto DRS
76 % @param Drs2 is an Attempto DRS
77 % @param Options is a list of options
78 %
79 % The DRSs are equivalent iff they are well-formed and
80 % every condition list of Drs1 is a subset of some condition list
81 % of Drs2, and the other way around.
82 %
83 % Valid options are:
84 %
85 % * ignore_sid(Bool)
86 % If =|true|= then the sentence IDs are ignored during comparison,
87 % otherwise (default) the sentence IDs are taken into consideration.
88 %
89 are_equivalent(Drs1, Drs2) :-
90 are_equivalent(Drs1, Drs2, []).
91
92 are_equivalent(Drs1, Drs2, []) :-
93 are_equivalent(Drs1, Drs2, [ignore_sid(false)]).
94
95 are_equivalent(Drs1, Drs2, [ignore_sid(false)]) :-
96 retractall(conds_unify(_, _)),
97 assert(conds_unify(C-Id, C-Id)),
98 assert(conds_unify(C-SId/_, C-SId)),
99 assert(conds_unify(C-SId, C-SId/_)),
100 !,
101 are_equivalent_x(Drs1, Drs2).
102
103 are_equivalent(Drs1, Drs2, [ignore_sid(true)]) :-
104 retractall(conds_unify(_, _)),
105 assert(conds_unify(C-_, C-_)),
106 !,
107 are_equivalent_x(Drs1, Drs2).
108
109 are_equivalent_x(Drs1, Drs2) :-
110 is_wellformed(Drs1),
111 is_wellformed(Drs2),
112 is_subdrs_of(Drs1, Drs2),
113 is_subdrs_of(Drs2, Drs1).
114
115
116 %% is_subdrs_of(+Drs1:term, +Drs2:term) is det.
117 %% is_subdrs_of_x(+Drs1:term, +Drs2:term) is det.
118 %
119 % @param Drs1 is an Attempto DRS
120 % @param Drs2 is an Attempto DRS
121 %
122 % Both DRSs are first copied to protect the original variables.
123 % The 2nd DRS is then numbervared. It is then checked if all the
124 % conditions of the 1st DRS occur (i.e. can be unified with some condition)
125 % in the 2nd DRS.
126 %
127 is_subdrs_of(drs(_, Conds1), drs(_, Conds2)) :-
128 copy_term(Conds1, Conds1Copy),
129 copy_term(Conds2, Conds2Copy),
130 numbervars(Conds2Copy, 0, _),
131 is_subdrs_of_x(drs(_, Conds1Copy), drs(_, Conds2Copy)).
132
133 is_subdrs_of_x(drs(_, Conds1), drs(_, Conds2)) :-
134 is_subcl_of(Conds1, Conds2).
135
136
137 %% is_subcl_of(+ConditionList1:list, +ConditionList2:list) is det.
138 %
139 % @param ConditionList1 is a list of DRS conditions
140 % @param ConditionList2 is a list of DRS conditions
141 %
142 % eq:is_subcl_of([a(X)-1, b(Y)-1, c(X,Y)-1], [a(y)-1, b(x)-1, c(y,x)-1]).
143 % NOT eq:is_subcl_of([a(X)-1, b(Y)-1, c(X,Y)-1], [a(y)-1, b(x)-1, c(x,x)-1]).
144 %
145 is_subcl_of([], _).
146
147 is_subcl_of([Condition | ConditionList1], ConditionList2) :-
148 member_of_conds(Condition, ConditionList2),
149 is_subcl_of(ConditionList1, ConditionList2).
150
151
152 %% member_of_conds(+Condition:term, +ConditionList:list) is det.
153 %
154 % @param Condition is a DRS condition
155 % @param ConditionList is a list of DRS conditions
156 %
157 % BUG: it is probably better to use select/3 in order not
158 % to match the same condition more than once.
159 %
160 member_of_conds([H1|T1], [[H2|T2] | _]) :-
161 is_subdrs_of_x(drs([],[H1|T1]), drs([],[H2|T2])).
162
163 member_of_conds(Drs1, [Drs2 | _]) :-
164 Drs1 =.. [Op, SubDrs1],
165 Drs2 =.. [Op, SubDrs2],
166 unary_drs_operator(Op),
167 is_subdrs_of_x(SubDrs1, SubDrs2).
168
169 % Experimental: allow (binary) disjunctions to match if they match
170 % after reordering of the elements, e.g. the DRS of "John drinks or eats."
171 % is equivalent to the DRS of "John eats or drinks."
172 member_of_conds(v(SubDrs1a, SubDrs1b), [v(SubDrs2a, SubDrs2b) | _]) :-
173 is_subdrs_of_x(SubDrs1a, SubDrs2b), is_subdrs_of_x(SubDrs1b, SubDrs2a).
174
175 member_of_conds(Drs1, [Drs2 | _]) :-
176 Drs1 =.. [Op, SubDrs1a, SubDrs1b],
177 Drs2 =.. [Op, SubDrs2a, SubDrs2b],
178 binary_drs_operator(Op),
179 is_subdrs_of_x(SubDrs1a, SubDrs2a),
180 is_subdrs_of_x(SubDrs1b, SubDrs2b).
181
182 member_of_conds(Label:Drs1, [Label:Drs2 | _]) :-
183 is_subdrs_of_x(Drs1, Drs2).
184
185 member_of_conds(Cond1, [Cond2 | _]) :-
186 conds_unify(Cond1, Cond2).
187
188 member_of_conds(Cond, [_ | CondsTail]) :-
189 member_of_conds(Cond, CondsTail).
Something went wrong with that request. Please try again.