home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.yorku.ca 2015 / ftp.cs.yorku.ca.tar / ftp.cs.yorku.ca / pub / peter / SVT / GNU / wang.pl < prev   
Text File  |  2002-12-05  |  6KB  |  174 lines

  1. /*******************************************************************************
  2. *  Wang's Algorithm 
  3. * (c) P. H. Roosen-Runge, 2002.
  4.  
  5. *  Checks a file of propositions and reports for each proposition
  6. *  whether it is a tautology.  Each proposition is a term constructed from
  7. *  'not', 'and', 'or', 'xor', 'implies', 'iff', 'true', 'false', 
  8. *  and Prolog terms.  Each term must end in '.'.
  9. *
  10. *  The predicate tautology(Term) succeeds if Term represents a tautology. It
  11. *  uses Wang's algorithm for proving theorems in the propositional calculus
  12. *  using sequents.
  13. *
  14. ******************************************************************************/
  15. % Ver 1.0, P. H. Roosen-Runge, December 1990.
  16. % Ver 1.2, December 6, 1991:  modified for Quintus Prolog 3.1
  17. %     1.2.2  Feb. 23, 1992: input must be a ground term.
  18. %     1.3.1 July 5: rewritten for optimization, using Prolog's indexing
  19. %       on the principal functor of the first argument. Tracing removed.
  20. %     1.4   Dec. 12, 1999: shows counter-example
  21.  
  22. %     1.4GNU November 4, 2002: Gnu Prolog version
  23. %     1.41GNU Dec. 5: fixed counter-example printing
  24. /*****************************************************************************/
  25.  
  26. :-op(995,xfy,'>>').    % sequent
  27. :-op(990, yfx, iff).  % Left-associative (yfx) for consistency with
  28.                       % commutative arithmetic operators.
  29.  
  30. :-op(990,yfx,implies). % for consistency with iff
  31. :-op(980,yfx, [or, cor]).
  32. :-op(970,xfx,xor). % xor isn't associative.  force parenthesization.
  33. :-op(960,yfx,[and, cand]).
  34. :-op(950,fy,not).
  35. :-op(700,yfx,['<=','<', '>','=>', '>=', '<>', '!=']). % was right-associative
  36. :-op(400, xfx, [div, mod]).
  37. :-op(200, xfy,'**').
  38. :-op(200, xf, '!').
  39.  
  40. :- initialization(activate).   % gprolog      
  41.  
  42. error(X) :- write('!! '), write(X), nl.
  43. activate :- 
  44.       set_linedit_prompt('|:'),
  45.       write('wang: version 1.41GNU, December 5, 2002.'), nl,
  46.       propositions
  47.      ;
  48.       nl, error('Something wrong.'), halt.
  49.  
  50. propositions :- read(T),
  51.     (  T==end_of_file, halt
  52.      ; 
  53.             nl, write(T), nl,
  54.        \+ ground(T) -> nl,  % defined below; not in gprolog.
  55.                error('Prolog variable in input. Use lower-case or quote it.')
  56.      ; 
  57.         check(T)
  58.     ), 
  59.     propositions.
  60.  
  61. check(T) :- 
  62.         (
  63.          tautology(T), nl, display('* Valid.'), nl, nl  
  64.         ;
  65.         nl, display('* Not valid.')
  66.         ), 
  67.         nl, nl.
  68.  
  69. tautology(Term) :- (!), sweepR(Term, ([]>>[]), ([]>>[])).
  70.  
  71. checkAtoms(S, LAtoms>>RAtoms) :- 
  72.     ok(LAtoms, RAtoms), (!)  % gprolog parser problem?
  73.     ;
  74.     S \== ([]>>[]) -> sweep(S, LAtoms>>RAtoms)
  75.     ; 
  76.         noLogical(LAtoms), noLogical(RAtoms),
  77.          showCounterExample(LAtoms, RAtoms),(!), fail
  78.         ;
  79.         RAtoms = [false], noLogical(LAtoms),
  80.         nl, write('Counterexample: '),
  81.         writeSet(LAtoms), write(' is true.'), (!), fail
  82.         ;
  83.         LAtoms = [true], noLogical(RAtoms),
  84.         nl, write('Counterexample: '),
  85.         writeSet(RAtoms), write(' is false.'), (!), fail 
  86.         ; 
  87.         fail. %  no counterexample for [true] >> [false], etc.
  88.  
  89. ok(LAtoms, RAtoms) :-
  90.     memberchk(false, LAtoms) ; memberchk(true, RAtoms)
  91.         ;
  92.         member(M, LAtoms), member(M, RAtoms).
  93.  
  94.  
  95. noLogical([]).
  96. noLogical([First | Rest]) :- 
  97.      \+ logical(First),
  98.      noLogical(Rest).
  99.  
  100. logical(First) :- 
  101.         functor(First, true, 0) ; functor(First, false, 0) ;
  102.     functor(First, not, 1) ;
  103.     functor(First, F, 2), member(F, [and, or, iff, xor, implies]).
  104.     
  105. showCounterExample(Left, Right) :-
  106.     nl, write('Counterexample: '),
  107.     Left = [] -> writeSet(Right), write(' is false.')
  108.     ;
  109.         Right = [] -> writeSet(Left), write(' is true.')
  110.         ;
  111.     writeSet(Left), write(' is true and '),
  112.     writeSet(Right), write(' is false.').
  113.        
  114. writeSet([X]) :- write(X).
  115. writeSet(X) :- 
  116.     list_to_set(X, Set),
  117.        (
  118.         Set = [Single], write(Single)
  119.         ;
  120.     write('each of '), write(Set)
  121.        ).
  122.  
  123. sweep([P | Rest]>>R, Atoms) :- (!), sweepL(P, Rest>>R, Atoms).
  124. sweep(L>>[P | Rest], Atoms) :- (!), sweepR(P, L>>Rest, Atoms).
  125.  
  126. sweepR(not P, S, Atoms) :- (!), sweepL(P, S, Atoms).
  127. sweepR(C1 or C2, L>> Rest, Atoms) :- (!), sweepR(C1, L>>[C2 | Rest], Atoms).
  128. sweepR(C1 implies C2, L>>R, Atoms) :- 
  129.         (!), sweepR(C2, [C1 | L]>>R, Atoms).        
  130. sweepR(C1 and C2, S, Atoms) :-
  131.         (!), sweepR(C1, S, Atoms), (!),
  132.         sweepR(C2, S, Atoms).
  133. sweepR(C1 iff C2, L>>R, Atoms) :-
  134.         (!), sweepR(C2, [C1 | L]>>R, Atoms), (!),
  135.                 sweepR(C1, [C2 | L]>>R, Atoms).
  136. sweepR(C1 xor C2, S, Atoms) :-  (!), sweepL(C1 iff C2, S, Atoms).
  137. sweepR(P, S, LAtoms>>RAtoms) :- checkAtoms(S, LAtoms>>[P | RAtoms]).
  138.  
  139. sweepL(not P, S, Atoms) :- (!), sweepR(P, S, Atoms).
  140. sweepL(C1 and C2,  Rest>>R, Atoms) :- (!), sweepL(C1, [C2 | Rest] >> R, Atoms).
  141. sweepL(C1 or C2, S, Atoms) :-
  142.                 (!), sweepL(C1, S, Atoms), (!), sweepL(C2, S, Atoms).
  143. sweepL(C1 implies C2, S, Atoms) :-
  144.                 (!), sweepR(C1, S, Atoms), (!), sweepL(C2, S, Atoms).
  145. sweepL(C1 iff C2, Rest>>R, Atoms) :-
  146.         (!), sweepL(C1 implies C2, [C2 implies C1 | Rest]>>R, Atoms).
  147. sweepL(C1 xor C2, S, Atoms) :-    (!), sweepR(C1 iff C2, S, Atoms).
  148.     
  149. sweepL(P, S, LAtoms>>RAtoms) :- checkAtoms(S, [P | LAtoms]>>RAtoms).
  150.  
  151. ground(T) :-
  152.     nonvar(T),
  153.    (
  154.      functor(T, _, 0)
  155.     ;
  156.      T =.. [_ | Args], grounds(Args)
  157.    ).
  158.  
  159. grounds([T]) :- ground(T).
  160. grounds([H | T]) :- ground(H), grounds(T).
  161.  
  162. %   list_to_set(+List, ?Set)
  163.  
  164. %   Authors: Lawrence Byrd + Richard A. O'Keefe
  165. %   Updated: 19 Jan 1994
  166.  
  167. list_to_set([], []).
  168. list_to_set([Head|Tail], Set) :-
  169.     memberchk(Head, Tail),
  170.     (!),
  171.     list_to_set(Tail, Set).
  172. list_to_set([Head|Tail], [Head|Set]) :-
  173.     list_to_set(Tail, Set).
  174.