root/trunk/examples/logic/translator.lgt

Revision 4601, 8.1 KB (checked in by pmoura, 7 weeks ago)

Added svn:mime-type property to source files (set to text/x-logtalk).

  • Property svn:mime-type set to text/x-logtalk
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2:- object(translator).
3
4    :- info([
5        version is 1.1,
6        date is 2007/10/13,
7        author is 'Paulo Moura',
8        comment is 'Translator of logic propositions to clauses in conjunctive normal form.',
9        source is 'Code partially based on an example found on the Clocksin and Mellish Prolog book.']).
10
11    :- public(translate/2).
12    :- mode(translate(+nonvar, -list), zero_or_one).
13    :- info(translate/2, [
14        comment is 'Translates a proposition to a list of clauses.',
15        argnames is ['Propostion', 'Clauses']]).
16
17    :- public(step_by_step/2).
18    :- mode(step_by_step(+nonvar, -list), zero_or_one).
19    :- info(step_by_step/2, [
20        comment is 'Translates a proposition to a list of clauses, printing the result of each translation step.',
21        argnames is ['Propostion', 'Clauses']]).
22
23    :- private(gensym_counter_/1).
24    :- dynamic(gensym_counter_/1).
25
26
27    :- op(10,  fy, ~ ).     % negation
28    :- op(20, yfx, & ).     % conjunction
29    :- op(30, yfx, v ).     % disjunction
30    :- op(40, xfx, =>).     % implication
31    :- op(40, xfx, <=>).    % equivalence
32
33
34    translate(P, Cs) :-
35        remove_implications(P, P2),
36        distribute_negation(P2, P3),
37        remove_existential_quantifiers(P3, P4),
38        convert_to_prenex_normal_form(P4, P5),
39        remove_universal_quantifiers(P5, P6),
40        convert_to_conjunctive_normal_form(P6, P7),
41        convert_to_clauses(P7, Cs),
42        print_clauses(Cs).
43
44
45    step_by_step(P, Cs) :-
46        nl, write('Processing proposition: '), write(P), nl, nl,
47        write('  1. Remove implications: '),
48        remove_implications(P, P2),
49        write(P2), nl,
50        write('  2. Distribute negation: '),
51        distribute_negation(P2, P3),
52        write(P3), nl,
53        write('  3. Remove existential quantifiers: '),
54        remove_existential_quantifiers(P3, P4),
55        write(P4), nl,
56        write('  4. Convert to prenex normal form: '),
57        convert_to_prenex_normal_form(P4, P5),
58        write(P5), nl,
59        write('  5. Remove universal quantifiers: '),
60        remove_universal_quantifiers(P5, P6),
61        write(P6), nl,
62        write('  6. Convert to conjunctive normal form: '),
63        convert_to_conjunctive_normal_form(P6, P7),
64        write(P7), nl,
65        write('  7. Convert to clauses: '),
66        convert_to_clauses(P7, Cs),
67        write(Cs), nl, nl,
68        write('Clauses in Prolog-like notation:'), nl,
69        print_clauses(Cs).
70
71
72    remove_implications(all(X, P), all(X, P2)) :-
73        !,
74        remove_implications(P, P2).
75
76    remove_implications(exists(X, P), exists(X, P2)) :-
77        !,
78        remove_implications(P, P2).
79
80    remove_implications(P <=> Q, P2 & Q2 v ~P2 & ~Q2) :-
81        !,
82        remove_implications(P, P2),
83        remove_implications(Q, Q2).
84
85    remove_implications(P => Q, ~P2 v Q2) :-
86        !,
87        remove_implications(P, P2),
88        remove_implications(Q, Q2).
89
90    remove_implications(P & Q, P2 & Q2) :-
91        !,
92        remove_implications(P, P2),
93        remove_implications(Q, Q2).
94
95    remove_implications(P v Q, P2 v Q2) :-
96        !,
97        remove_implications(P, P2),
98        remove_implications(Q, Q2).
99
100    remove_implications(~P, ~P2) :-
101        !,
102        remove_implications(P, P2).
103
104    remove_implications(P, P).
105
106
107    distribute_negation(all(X, P), all(X, P2)) :-
108        !,
109        distribute_negation(P, P2).
110
111    distribute_negation(exists(X, P), exists(X, P2)) :-
112        !,
113        distribute_negation(P, P2).
114
115    distribute_negation(P & Q, P2 & Q2) :-
116        !,
117        distribute_negation(P, P2),
118        distribute_negation(Q, Q2).
119
120    distribute_negation(P v Q, P2 v Q2) :-
121        !,
122        distribute_negation(P, P2),
123        distribute_negation(Q, Q2).
124
125    distribute_negation(~P, P2) :-
126        !,
127        apply_negation(P, P2).
128
129    distribute_negation(P, P).
130
131
132    apply_negation(all(X, P), exists(X, P2)) :-
133        !,
134        apply_negation(P, P2).
135
136    apply_negation(exists(X, P), all(X, P2)) :-
137        !,
138        apply_negation(P, P2).
139
140    apply_negation(P & Q, P2 v Q2) :-
141        !,
142        apply_negation(P, P2),
143        apply_negation(Q, Q2).
144
145    apply_negation(P v Q, P2 & Q2) :-
146        !,
147        apply_negation(P, P2),
148        apply_negation(Q, Q2).
149
150    apply_negation(~P, P2) :-
151        !,
152        distribute_negation(P, P2).
153
154    apply_negation(P, ~P).
155
156
157    remove_existential_quantifiers(P, P2) :-
158        remove_existential_quantifiers(P, P2, []).
159
160    remove_existential_quantifiers(all(X, P), all(X, P2), Vars) :-
161        !,
162        remove_existential_quantifiers(P, P2, [X| Vars]).
163
164    remove_existential_quantifiers(exists(X, P), P2, Vars) :-
165        !,
166        gensym(f, F),
167        X =.. [F| Vars],
168        remove_existential_quantifiers(P, P2, Vars).
169
170    remove_existential_quantifiers(P & Q, P2 & Q2, Vars) :-
171        !,
172        remove_existential_quantifiers(P, P2, Vars),
173        remove_existential_quantifiers(Q, Q2, Vars).
174
175    remove_existential_quantifiers(P v Q, P2 v Q2, Vars) :-
176        !,
177        remove_existential_quantifiers(P, P2, Vars),
178        remove_existential_quantifiers(Q, Q2, Vars).
179
180    remove_existential_quantifiers(P, P, _).
181
182
183    convert_to_prenex_normal_form(P, P2) :-
184        collect_vars(P, P1, [], Vars),
185        add_vars_at_front(Vars, P1, P2).
186
187    collect_vars(all(X, P), P2, Acc, Vars) :-
188        !,
189        collect_vars(P, P2, [X| Acc], Vars).
190
191    collect_vars(P & Q, P2 & Q2, Acc, Vars) :-
192        !,
193        collect_vars(P, P2, Acc, Acc2),
194        collect_vars(Q, Q2, Acc2, Vars).
195
196    collect_vars(P v Q, P2 v Q2, Acc, Vars) :-
197        !,
198        collect_vars(P, P2, Acc, Acc2),
199        collect_vars(Q, Q2, Acc2, Vars).
200
201    collect_vars(P, P, Vars, Vars).
202
203
204    add_vars_at_front([], P, P).
205
206    add_vars_at_front([X| Vars], P, P2) :-
207        add_vars_at_front(Vars, all(X, P), P2).
208
209
210    remove_universal_quantifiers(all(_, P), P2) :-
211        !,
212        remove_universal_quantifiers(P, P2).
213
214    remove_universal_quantifiers(P & Q, P2 & Q2) :-
215        !,
216        remove_universal_quantifiers(P, P2),
217        remove_universal_quantifiers(Q, Q2).
218
219    remove_universal_quantifiers(P v Q, P2 v Q2) :-
220        !,
221        remove_universal_quantifiers(P, P2),
222        remove_universal_quantifiers(Q, Q2).
223
224    remove_universal_quantifiers(P, P).
225
226
227    convert_to_conjunctive_normal_form(P v Q, R) :-
228        !,
229        convert_to_conjunctive_normal_form(P, P2),
230        convert_to_conjunctive_normal_form(Q, Q2),
231        distribute_disjunction(P2 v Q2, R).
232
233    convert_to_conjunctive_normal_form(P & Q, P2 & Q2) :-
234        !,
235        convert_to_conjunctive_normal_form(P, P2),
236        convert_to_conjunctive_normal_form(Q, Q2).
237
238    convert_to_conjunctive_normal_form(P, P).
239
240
241    distribute_disjunction(P & Q v R, P2 & Q2) :-
242        !,
243        convert_to_conjunctive_normal_form(P v R, P2),
244        convert_to_conjunctive_normal_form(Q v R, Q2).
245
246    distribute_disjunction(P v Q & R, P2 & Q2) :-
247        !,
248        convert_to_conjunctive_normal_form(P v Q, P2),
249        convert_to_conjunctive_normal_form(P v R, Q2).
250
251    distribute_disjunction(P, P).
252
253
254    convert_to_clauses(P, Cs) :-
255        convert_to_clauses(P, [], Cs).
256
257
258    convert_to_clauses(P & Q, Acc, Cs) :-
259        !,
260        convert_to_clauses(Q, Acc, Acc2),
261        convert_to_clauses(P, Acc2, Cs).
262
263    convert_to_clauses(P, Acc, [cl(Pos, Negs)| Acc]) :-
264        convert_to_clauses(P, [], Pos, [], Negs),
265        !.
266
267    convert_to_clauses(_, Cs, Cs).
268
269
270    convert_to_clauses(P v Q, AccPos, Pos, AccNegs, Negs) :-
271        !,
272        convert_to_clauses(Q, AccPos, AccPos2, AccNegs, AccNegs2),
273        convert_to_clauses(P, AccPos2, Pos, AccNegs2, Negs).
274
275    convert_to_clauses(~P, Pos, Pos, AccNegs, [P| AccNegs]) :-
276        !,
277        not_member_of(P, Pos).
278
279    convert_to_clauses(P, AccPos, [P| AccPos], Negs, Negs) :-
280        !,
281        not_member_of(P, Negs).
282
283/*
284    convert_to_clauses(P & Q, {P2, Q2}) :-
285        !,
286        convert_to_clauses(P, P2),
287        convert_to_clauses(Q, Q2).
288
289    convert_to_clauses(P v Q, R) :-
290        !,
291        convert_to_clause(P v Q, R).
292
293    convert_to_clauses(P, {P}).
294
295
296    convert_to_clause(P & Q, R) :-
297        !,
298        convert_to_clauses(P & Q, {R}).
299
300    convert_to_clause(P v Q, {P2, Q}) :-
301        !,
302        convert_to_clause(P, P2).
303
304    convert_to_clause(P, P).
305*/
306
307    not_member_of(P, [P| _]) :-
308        !,
309        fail.
310
311    not_member_of(P, [_| Ps]) :-
312        !,
313        not_member_of(P, Ps).
314
315    not_member_of(_, []).
316
317
318    print_clauses([]) :-
319        nl.
320
321    print_clauses([cl(Pos, Negs)| Cs]) :-
322        print_clause(Pos, Negs), nl,
323        print_clauses(Cs).
324
325    print_clause(Pos, []) :-
326        !,
327        print_disjunctions(Pos), write(' :- .').
328
329    print_clause([], Negs) :-
330        !,
331        write(':- '), print_conjunctions(Negs), write('.').
332
333    print_clause(Pos, Negs) :-
334        !,
335        print_disjunctions(Pos), write(' :- '),
336        print_conjunctions(Negs), write('.').
337
338
339    print_disjunctions([P]) :-
340        !,
341        write(P).
342
343    print_disjunctions([P| Ps]) :-
344        !,
345        write(P), write('; '),
346        print_disjunctions(Ps).
347
348
349    print_conjunctions([P]) :-
350        !,
351        write(P).
352
353    print_conjunctions([P| Ps]) :-
354        !,
355        write(P), write(', '),
356        print_conjunctions(Ps).
357
358
359    gensym_counter_(0).
360
361
362    gensym(Base, Atom) :-
363        retract(gensym_counter_(Counter)),
364        Counter2 is Counter + 1,
365        number_codes(Counter2, Codes2),
366        atom_codes(Number, Codes2),
367        atom_concat(Base, Number, Atom),
368        assertz(gensym_counter_(Counter2)).
369
370
371:- end_object.
Note: See TracBrowser for help on using the browser.