2:- module(miniWordNet,[compConcepts/2,
    3                       compISA/0,
    4                       graphMWN/2,
    5                       outputMWN/2,
    6                       axiomsWN/1,
    7                       cutDownMWN/0,
    8                       checkConsBK/0,
    9                       addTopMWN/0,
   10                       sizeMWN/1,
   11                       clearMWN/0]).   12
   13
   14/* ========================================================================
   15    Load Modules
   16======================================================================== */
   17
   18:- use_module(library(lists),[member/2,append/3,select/3]).   19:- use_module(semlib(options),[option/2]).   20:- use_module(semlib(errors),[error/2,warning/2]).   21:- use_module(semlib(drs2fol),[symbol/4,timex/2]).   22
   23
   24% :- use_module(knowledge(nationality),[nationality/2]).
   25
   26
   27/* ========================================================================
   28   Load WordNet
   29======================================================================== */
   30
   31:- [working/wordnet/wordnet].   32
   33%:- [working/wordnet/vanilla_train_s].
   34%:- [working/wordnet/vanilla_train_l].
   35%:- [working/wordnet/vanilla_train_xxxl].
   36
   37%:- [working/wordnet/vanilla_test_xl].
   38
   39%:- [working/wordnet/human_test].
   40
   41%:- [working/wordnet/elliesimple].
   42%:- [working/wordnet/ellie_train].
   43
   44%:- [working/wordnet/combined].
   45
   46
   47/* ========================================================================
   48    Declare Dynamic Predicates
   49======================================================================== */
   50
   51:- dynamic concept/2, % concept(Concept, ConceptId)
   52           isa/2,     % isa(ConceptId1, ConceptId2)
   53           isnota/2,  % isnota(ConceptId1, ConceptId2)
   54           word/5.    % word(Word,Cat,Sense,Freq,ConceptId),
   55
   56
   57/* ========================================================================
   58   Minimum Frequence for words under consideration
   59======================================================================== */
   60
   61minFreq(0).
   62
   63
   64/* ========================================================================
   65   Clear Background Knowledge
   66======================================================================== */
   67
   68clearMWN:-  
   69   retractall(word(_,_,_,_,_)),
   70   retractall(isa(_,_)),
   71   retractall(isnota(_,_)),
   72   retractall(concept(_,_)).
   73
   74
   75/* ========================================================================
   76   Compute Concepts for one DRS
   77======================================================================== */
   78
   79compConcepts(DRS,DRS):-
   80   findSymDrs(DRS,[]-_,[]-Concepts),
   81   selectConcepts(Concepts), !.
   82
   83compConcepts(DRS,DRS).
   84
   85
   86/* ========================================================================
   87   Get all symbols from a DRS
   88======================================================================== */
   89
   90findSymDrs(smerge(A,B),X1-X3,R1-R2):- !,
   91   findSymDrs(A,X1-X2,R1-R3),  
   92   findSymDrs(B,X2-X3,R3-R2).
   93
   94findSymDrs(merge(A,B),X1-X3,R1-R2):- !,
   95   findSymDrs(A,X1-X2,R1-R3),  
   96   findSymDrs(B,X2-X3,R3-R2).
   97
   98findSymDrs(alfa(_,A,B),X1-X3,R1-R2):- !,
   99   findSymDrs(A,X1-X2,R1-R3),  
  100   findSymDrs(B,X2-X3,R3-R2).
  101
  102findSymDrs(drs([_:Y1|Dom],Conds),X1-X3,R1-R2):- 
  103   select(Y2,X1,X2), Y1==Y2, !,
  104   findSymDrs(drs(Dom,Conds),X2-X3,R1-R2).
  105
  106findSymDrs(drs([_|Dom],Conds),X1-X2,R1-R2):- 
  107   findSymDrs(drs(Dom,Conds),X1-X2,R1-R2).
  108
  109findSymDrs(drs([],Conds),X1-X2,R1-R2):- !,
  110   findSymConds(Conds,X1-X2,R1-R2).
  111
  112
  113/* ========================================================================
  114   Get all symbols from a DRS-Condition
  115======================================================================== */
  116
  117findSymConds([],X-X,R-R).
  118
  119findSymConds([_:imp(B1,B2)|L],X1-X3,R1-R4):- !,
  120   findSymDrs(B1,X1-X2,R1-R2), 
  121   findSymDrs(B2,X2-_,R2-R3),   
  122   findSymConds(L,X1-X3,R3-R4).
  123
  124findSymConds([_:or(B1,B2)|L],X1-X2,R1-R4):- !,
  125   findSymDrs(B1,X1-_,R1-R2),
  126   findSymDrs(B2,X1-_,R2-R3),   
  127   findSymConds(L,X1-X2,R3-R4).
  128
  129findSymConds([_:duplex(_,B1,_,B2)|L],X1-X3,R1-R4):- !,
  130   findSymDrs(B1,X1-X2,R1-R2),
  131   findSymDrs(B2,X2-_,R2-R3),   
  132   findSymConds(L,X1-X3,R3-R4).
  133   
  134findSymConds([_:not(B)|L],X1-X2,R1-R3):- !,
  135   findSymDrs(B,X1-_,R1-R2),
  136   findSymConds(L,X1-X2,R2-R3).
  137
  138findSymConds([_:pos(B)|L],X1-X2,R1-R3):- !,
  139   findSymDrs(B,X1-_,R1-R2),
  140   findSymConds(L,X1-X2,R2-R3).
  141
  142findSymConds([_:nec(B)|L],X1-X2,R1-R3):- !,
  143   findSymDrs(B,X1-_,R1-R2),
  144   findSymConds(L,X1-X2,R2-R3).
  145
  146findSymConds([_:prop(_,B)|L],X1-X2,R1-R3):- !,
  147   findSymDrs(B,X1-_,R1-R2),
  148   findSymConds(L,X1-X2,R2-R3).
  149
  150findSymConds(L1,X1-X2,R1-R2):-
  151   select(_:pred(Y1,Sym,n,Sense),L1,L2), !,
  152   ( stoplist(Sym,n), !, findSymConds(L2,X1-X2,R1-R2) 
  153   ; member(Y0,X1), Y1==Y0, !, warning('symbol ~p not selected for MWN',[Sym]), findSymConds(L2,X1-X2,R1-R2)
  154   ; findSymConds(L2,[Y1|X1]-X2,[s(Sym,n,Sense)|R1]-R2) ).
  155
  156findSymConds(L1,X1-X2,R1-R2):-
  157   select(_:pred(Y,Sym,v,Sense),L1,L2), !,
  158   ( stoplist(Sym,v), !, findSymConds(L2,X1-X2,R1-R2) 
  159   ; findSymConds(L2,[Y|X1]-X2,[s(Sym,v,Sense),s(event,n,1)|R1]-R2) ).
  160
  161findSymConds(L1,X1-X2,R1-R2):-
  162   select(_:pred(Y,Sym,a,Sense),L1,L2), !,
  163   ( stoplist(Sym,a), !, findSymConds(L2,X1-X2,R1-R2) 
  164   ; findSymConds(L2,[Y|X1]-X2,[s(Sym,a,Sense)|R1]-R2) ).
  165
  166findSymConds(L1,X1-X2,R1-R2):-
  167   select(_:pred(Y,Sym,r,Sense),L1,L2), !,
  168   ( stoplist(Sym,r), !, findSymConds(L2,X1-X2,R1-R2) 
  169   ; findSymConds(L2,[Y|X1]-X2,[s(Sym,r,Sense)|R1]-R2) ).
  170
  171findSymConds([_:card(_,N,_)|L],X1-X2,R1-[s(Sym,cardinal,1),s(numeral,n,1)|R2]):- 
  172   option('--plural',false),
  173   integer(N), N > 0, !,
  174   symbol(c,number,N,Sym),
  175   findSymConds(L,X1-X2,R1-R2).
  176
  177findSymConds([_:timex(Y1,T)|L],X1-X2,R1-[s(Sym,timex,1),s(time,n,5)|R2]):- 
  178   \+ (member(Y0,X1), Y1==Y0), !,
  179   timex(T,Sym),
  180   findSymConds(L,[Y1|X1]-X2,R1-R2).
  181
  182findSymConds([_:named(Y1,Sym,Cat,Sense)|L],X1-X2,R1-[s(Sym,Cat,Sense)|R2]):-
  183%  \+ (member(Y0,X1), Y0==Y1), 
  184   !,
  185   findSymConds(L,[Y1|X1]-X2,R1-R2).
  186
  187findSymConds([_|L],X1-X2,R1-R2):-
  188   findSymConds(L,X1-X2,R1-R2).
  189
  190
  191/* ========================================================================
  192   Select relevant nouns and verbs as concepts
  193======================================================================== */
  194
  195selectConcepts([]).
  196
  197selectConcepts([s(_,ttl,_)|L]):- !,       % ignore titles
  198   selectConcepts(L).
  199
  200selectConcepts([s(X,Cat,0)|L]):- !,       % WSD (most frequent sense)
  201   selectConcepts([s(X,Cat,1)|L]).
  202
  203%selectConcepts([c(X,Syms,Cat,0)|L]):- !,  % WSD (most frequent sense)
  204%   selectConcepts([c(X,Syms,Cat,1)|L]).
  205
  206selectConcepts([s(X,Cat,Sense)|L]):- 
  207   word(X,Cat,Sense,_,ID), !,             % if word (token) is already
  208   retract(word(X,Cat,Sense,N1,ID)),      % in the database
  209   N2 is N1 + 1,                          % then increase frequency
  210   assert(word(X,Cat,Sense,N2,ID)),
  211   selectConcepts(L).
  212
  213selectConcepts([s(Sym1,Cat,Sense1)|L]):- 
  214   concept(Concept,ID),                   % if word is not in the database
  215   member(s(Sym2,Cat,Sense2),Concept),    % but a synonym is, then
  216   syn(Cat,Sym1,Sense1,Sym2,Sense2), !,   % extend list of synonyms
  217   assert(word(Sym1,Cat,Sense1,1,ID)),
  218   retract(concept(Concept,ID)),
  219   assert(concept([s(Sym1,Cat,Sense1)|Concept],ID)),
  220   selectConcepts(L).
  221
  222selectConcepts([s(X,Cat,Sense)|L]):- !,
  223   getConceptId(ID),                      % else add word
  224   assert(word(X,Cat,Sense,1,ID)),        % and its concept to database
  225   assert(concept([s(X,Cat,Sense)],ID)),
  226   selectConcepts(L).
  227
  228%selectConcepts([c(X,_,Cat,Sense)|L]):-
  229%   word(X,Cat,Sense,_,ID), !,             % if name is already
  230%   retract(word(X,Cat,Sense,N1,ID)),      % in the database
  231%   N2 is N1 + 1,                          % then increase frequency
  232%   assert(word(X,Cat,Sense,N2,ID)),
  233%   selectConcepts(L).
  234
  235%selectConcepts([c(X,Symbols,Cat,Sense)|L]):- !,
  236%   getConceptId(ID),
  237%   assert(word(X,Cat,Sense,1,ID)),
  238%   findall(s(Sym,Cat,Sense),member(Sym,Symbols),Syn),
  239%   assert(concept([s(X,Cat,Sense)|Syn],ID)),
  240%   selectConcepts(L).
  241
  242selectConcepts([_|L]):-
  243   selectConcepts(L).
  244
  245
  246/* ========================================================================
  247   Synonyms
  248======================================================================== */
  249
  250syn(n,Sym1,Sense1,Sym2,Sense2):-
  251   synn(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (nouns)
  252
  253syn(n,Sym1,Sense1,Sym2,Sense2):-
  254   synn(Sym2,Sense2,Sym1,Sense1), !.    %%% WordNet (nouns)
  255
  256syn(v,Sym1,Sense1,Sym2,Sense2):-
  257   synv(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (verbs)
  258
  259syn(v,Sym1,Sense1,Sym2,Sense2):-
  260   synv(Sym2,Sense2,Sym1,Sense1), !.    %%% WordNet (verbs)
  261
  262syn(a,Sym1,Sense1,Sym2,Sense2):-
  263   syna(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (adjectives)
  264
  265syn(a,Sym1,Sense1,Sym2,Sense2):-
  266   syna(Sym2,Sense2,Sym1,Sense1), !.    %%% WordNet (adjectives)
  267
  268syn(r,Sym1,Sense1,Sym2,Sense2):-
  269   synr(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (adverbs)
  270
  271syn(r,Sym1,Sense1,Sym2,Sense2):-
  272   synr(Sym2,Sense2,Sym1,Sense1), !.    %%% WordNet (adverbs)
  273
  274syn(per,Sym1,Sense1,Sym2,Sense2):-
  275   synp(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (names)
  276
  277syn(loc,Sym1,Sense1,Sym2,Sense2):-
  278   synp(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (names)
  279
  280syn(org,Sym1,Sense1,Sym2,Sense2):-
  281   synp(Sym1,Sense1,Sym2,Sense2), !.    %%% WordNet (names)
  282
  283
  284/* ========================================================================
  285   Calculate WordNet ISA Relations (first select all relevant concepts)
  286======================================================================== */
  287
  288compISA:- 
  289   minFreq(Min),
  290   setof(s(X,Cat,Sense,ID),N^(word(X,Cat,Sense,N,ID),N>Min),L), !,
  291   compISA(L),
  292   compISNOTA(L).
  293
  294compISA.
  295
  296
  297/* ========================================================================
  298   Calculate WordNet ISA Relations
  299======================================================================== */
  300
  301compISA([]).
  302
  303compISA([s(_,_,_,ID)|L]):-
  304   isa(ID,_), !,                         % already calculated superconcept
  305   compISA(L).
  306
  307
  308/* ------------------------------------------------------------------------
  309   Time and Numeric Expressions
  310------------------------------------------------------------------------ */
  311
  312compISA([s(_,timex,1,ID1)|L]):- !,       % timex
  313   addConcept(time,n,5,ID2),
  314   assert(isa(ID1,ID2)),
  315   compISA([s(time,n,5,ID2)|L]).
  316
  317compISA([s(_,cardinal,1,ID1)|L]):- !,    % cardinal
  318   addConcept(numeral,n,1,ID2),
  319   assert(isa(ID1,ID2)),
  320   compISA([s(numeral,n,1,ID2)|L]).
  321
  322/* ------------------------------------------------------------------------
  323   Locations
  324------------------------------------------------------------------------ */
  325
  326%compISA([s(Sym1,loc,Sense1,ID1)|L]):-    % location in WordNet
  327%   isap(Sym1,Sense1,Sym2,Sense2), !,
  328%   addConcept(Sym2,n,Sense2,ID2),
  329%   assert(isa(ID1,ID2)),
  330%   compISA([s(Sym2,n,Sense2,ID2)|L]).
  331
  332compISA([s(_,loc,_,ID1)|L]):-            % location not in WordNet
  333   addConcept(location,n,1,ID2), !,
  334   assert(isa(ID1,ID2)),
  335   compISA([s(location,n,1,ID2)|L]).
  336
  337/* ------------------------------------------------------------------------
  338   Organisations
  339------------------------------------------------------------------------ */
  340
  341%compISA([s(Sym1,org,Sense1,ID1)|L]):-    % organisation in WordNet
  342%   isap(Sym1,Sense1,Sym2,Sense2), !,
  343%   addConcept(Sym2,n,Sense2,ID2),
  344%   assert(isa(ID1,ID2)),
  345%   compISA([s(Sym2,n,Sense2,ID2)|L]).
  346
  347compISA([s(_,org,_,ID1)|L]):-            % organisation not in WordNet
  348   addConcept(organisation,n,1,ID2), !,
  349   assert(isa(ID1,ID2)),
  350   compISA([s(organisation,n,1,ID2)|L]).
  351
  352/* ------------------------------------------------------------------------
  353   Persons
  354------------------------------------------------------------------------ */
  355
  356%compISA([s(Sym1,per,Sense1,ID1)|L]):-    % person in WordNet
  357%   isap(Sym1,Sense1,Sym2,Sense2), !,
  358%   addConcept(Sym2,n,Sense2,ID2),
  359%   assert(isa(ID1,ID2)),
  360%   compISA([s(Sym2,n,Sense2,ID2)|L]).
  361
  362compISA([s(_,per,_,ID1)|L]):-            % person not in WordNet
  363   addConcept(somebody,n,1,ID2), !,
  364   assert(isa(ID1,ID2)),
  365   compISA([s(somebody,n,1,ID2)|L]).
  366
  367/* ------------------------------------------------------------------------
  368   Nouns
  369------------------------------------------------------------------------ */
  370
  371% take all isa relations
  372%
  373compISA([s(Sym1,n,Sense1,ID1)|L1]):-      % nouns in WordNet
  374%   option('--x',true),
  375   findall(s(Sym2,n,Sense2,ID2),( isan(Sym1,Sense1,Sym2,Sense2),
  376                                  addConcept(Sym2,n,Sense2,ID2),
  377                                  assert(isa(ID1,ID2)) ), New),
  378   New = [_|_], !,
  379   append(New,L1,L2),
  380   compISA(L2).
  381
  382% take only first isa relation
  383%
  384%compISA([s(Sym1,n,Sense1,ID1)|L]):-      % nouns in WordNet
  385%   option('--x',false),
  386%   isan(Sym1,Sense1,Sym2,Sense2), !,
  387%   addConcept(Sym2,n,Sense2,ID2),
  388%   assert(isa(ID1,ID2)),
  389%   compISA([s(Sym2,n,Sense2,ID2)|L]).
  390
  391/* ------------------------------------------------------------------------
  392   Verbs
  393------------------------------------------------------------------------ */
  394
  395compISA([s(Sym1,v,Sense1,ID1)|L]):-      % verbs in WordNet (+ ISA)
  396   isav(Sym1,Sense1,Sym2,Sense2), !,
  397   addConcept(Sym2,v,Sense2,ID2),
  398   assert(isa(ID1,ID2)),
  399   compISA([s(Sym2,v,Sense2,ID2)|L]).
  400
  401compISA([s(Sym,v,Sense,_)|L]):-          % verbs in WordNet (- ISA)
  402   synv(Sym,Sense,_,_), !,
  403   compISA(L).
  404
  405compISA([s(Sym,v,Sense,_)|L]):-          % verbs in WordNet (- ISA)
  406   isav(_,_,Sym,Sense), !,
  407   compISA(L).
  408
  409/* ------------------------------------------------------------------------
  410   All Other Cases
  411------------------------------------------------------------------------ */
  412
  413compISA([s(Sym1,nam,Sense1,ID1)|L]):-    % named entity in WordNet
  414   isap(Sym1,Sense1,Sym2,Sense2), !,
  415   addConcept(Sym2,n,Sense2,ID2),
  416   assert(isa(ID1,ID2)),
  417   compISA([s(Sym2,n,Sense2,ID2)|L]).
  418
  419compISA([s(Sym,Cat,Sense,ID)|L]):-       % outside WordNet
  420   word(Sym,Cat,Sense,F,ID), 
  421   minFreq(Min), F > Min, !,
  422   warning('unclassified token: ~p~p~p',[Cat,Sense,Sym]),
  423   compISA(L).
  424
  425compISA([_|L]):-
  426   compISA(L).
  427
  428
  429
  430/*========================================================================
  431   compISNOTA
  432========================================================================*/
  433
  434compISNOTA([]).
  435
  436compISNOTA([s(Sym1,a,Sense1,ID1)|L]):-    
  437   isnotaa(Sym1,Sense1,Sym2,Sense2), 
  438   member(s(Sym2,a,Sense2,ID2),L), !,
  439   assert(isnota(ID1,ID2)),
  440   compISNOTA(L).
  441
  442compISNOTA([_|L]):-    
  443   compISNOTA(L).
  444
  445
  446/*========================================================================
  447    Get a new concept Id
  448========================================================================*/
  449
  450getConceptId(I3):-
  451   concept(_,I1),
  452   \+ ( concept(_,I2), I2 > I1 ), !,
  453   I3 is I1 + 1.
  454
  455getConceptId(1).
  456
  457
  458/*========================================================================
  459   Calculate First-Order Axioms 
  460========================================================================*/
  461
  462axiomsWN(Axioms):-
  463   option('--modal',false), !,
  464   findall(isa(A,B),(isa(A,B),\+A=B,\+B=0),ISA),
  465
  466   findall(isnota(A,B),isnota(A,B),ISNOTA),
  467%  co-hyponyms
  468%   findall(isnota(A,B),(isa(A,C), concept([s(_,T,_)|_],A),
  469%                        isa(B,C), concept([s(_,T,_)|_],B),
  470%                        A<B       ),ISNOTA),
  471
  472   append(ISA,ISNOTA,Ax1),
  473   findall(iseq(A,B),(concept([A|L],Id1),
  474                      member(B,L),
  475                      \+ (concept(Other,Id2), \+ Id1=Id2, member(B,Other))),ISEQ),
  476   append(ISEQ,Ax1,Ax2),
  477   axiomsWN(Ax2,Axioms).
  478
  479axiomsWN(Axioms):-
  480   option('--modal',true), !,
  481   findall(isa(A,B),(isa(A,B),\+A=B,\+B=0),Ax1),
  482   findall(iseq(A,B),(concept([A|L],Id1),
  483                      member(B,L),
  484                      \+ (concept(Other,Id2), \+ Id1=Id2, member(B,Other))),ISEQ),
  485   append(ISEQ,Ax1,Ax2),
  486   axiomsWN(Ax2,Axioms).
  487
  488
  489/*========================================================================
  490   Calculate First-Order Axioms given isa/2, isnota/2, iseq/2
  491========================================================================*/
  492
  493axiomsWN([],[]):- !.
  494
  495axiomsWN([isa(I1,I2)|L1],[Axiom|L2]):- !,
  496   isa2fol(I1,I2,Axiom), 
  497   axiomsWN(L1,L2).
  498
  499axiomsWN([isnota(I1,I2)|L1],[Axiom|L2]):-
  500   option('--contradiction',true), !,
  501   isnota2fol(I1,I2,Axiom), 
  502   axiomsWN(L1,L2).
  503
  504axiomsWN([iseq(S1,S2)|L1],[Axiom|L2]):- !,
  505   iseq2fol(S1,S2,Axiom), 
  506   axiomsWN(L1,L2).
  507
  508axiomsWN([_|L1],L2):- !,
  509   axiomsWN(L1,L2).
  510
  511
  512/*========================================================================
  513   Translate IS-A to FOL 
  514========================================================================*/
  515
  516isa2fol(I1,I2,Axiom):-
  517   option('--modal',false), !,
  518   concept2sym(I1,B1),
  519   concept2sym(I2,B2),
  520   Axiom = all(X,imp(F1,F2)),
  521   F1 =.. [B1,X],
  522   F2 =.. [B2,X].
  523
  524isa2fol(I1,I2,Axiom):-
  525   option('--modal',true), !,
  526   concept2sym(I1,B1),
  527   concept2sym(I2,B2),
  528   Axiom = all(W,imp(possible_world(W),all(X,imp(F1,F2)))),
  529   F1 =.. [B1,W,X],
  530   F2 =.. [B2,W,X].
  531
  532
  533/*========================================================================
  534   Translate IS-NOT-A to FOL 
  535========================================================================*/
  536
  537isnota2fol(I1,I2,Axiom):-
  538   option('--modal',false), !,
  539   concept2sym(I1,B1),
  540   concept2sym(I2,B2),
  541   Axiom = all(X,imp(F1,not(F2))),
  542   F1 =.. [B1,X],
  543   F2 =.. [B2,X].
  544
  545isnota2fol(I1,I2,Axiom):-
  546   option('--modal',true), !,
  547   concept2sym(I1,B1),
  548   concept2sym(I2,B2),
  549   Axiom = all(W,imp(possible_world(W),all(X,imp(F1,not(F2))))),
  550   F1 =.. [B1,W,X],
  551   F2 =.. [B2,W,X].
  552
  553
  554/*========================================================================
  555   Translate IS-EQUAL to FOL 
  556========================================================================*/
  557
  558iseq2fol(s(A1,T1,S1),s(A2,T2,S2),Axiom):-
  559   option('--modal',false), !,
  560   symbol(T1,A1,S1,B1),
  561   symbol(T2,A2,S2,B2),
  562   Axiom = all(X,bimp(F1,F2)),
  563   F1 =.. [B1,X],
  564   F2 =.. [B2,X].
  565
  566iseq2fol(s(A1,T1,S1),s(A2,T2,S2),Axiom):-
  567   option('--modal',true), !,
  568   symbol(T1,A1,S1,B1),
  569   symbol(T2,A2,S2,B2),
  570   Axiom = all(W,imp(possible_world(W),all(X,bimp(F1,F2)))),
  571   F1 =.. [B1,W,X],
  572   F2 =.. [B2,W,X].
  573
  574
  575/*========================================================================
  576   Translate concept to symbol
  577========================================================================*/
  578
  579concept2sym(I,Sym):-
  580   concept([s(Sym,timex,1)|_],I), !.
  581
  582concept2sym(I,Sym):-
  583   concept([s(Sym,cardinal,1)|_],I), !.
  584
  585concept2sym(I,B):-
  586   concept([s(Sym,Type,Sense)|_],I), !,
  587   symbol(Type,Sym,Sense,B).
  588
  589
  590/*========================================================================
  591   Print MiniWordNet 
  592========================================================================*/
  593
  594graphMWN(Dir,File):-
  595   option('--graph',true),
  596   atomic_list_concat([Dir,'/',File,'.mwn','.dot'],DOT),
  597   atomic_list_concat([Dir,'/',File,'.mwn','.pdf'],PDF),
  598   open(DOT,write,Stream),
  599   format(Stream,'digraph mwn {~n~n',[]),
  600   setof(I,X^concept(X,I),Nodes),
  601   printNodes(Nodes,Stream),
  602   printIsa(Stream),
  603   close(Stream),
  604   createGraph(DOT,PDF), !.
  605
  606graphMWN(_,_).
  607
  608
  609/*========================================================================
  610   Create Graph using the dot program
  611========================================================================*/
  612
  613createGraph(File1,File2):-
  614   shell('which dot',0), 
  615   atomic_list_concat([dot,File1,'-Tpdf >',File2],' ',Command),
  616   shell(Command,0), !.
  617
  618createGraph(_,_):-
  619   error('failed to execute the dot program',[]).
  620
  621
  622/*------------------------------------------------------------------------
  623   Print Nodes
  624------------------------------------------------------------------------*/
  625
  626printNodes([],Stream):- !, nl(Stream).
  627
  628printNodes([I|L],Stream):- 
  629   concept(X,I), !,
  630   format(Stream,'   ~p [label="',[I]),
  631   printNode(X,Stream),
  632   printNodes(L,Stream).
  633
  634printNodes([_|L],Stream):- printNodes(L,Stream).
  635
  636
  637/*------------------------------------------------------------------------
  638   Print Single Node
  639------------------------------------------------------------------------*/
  640
  641printNode([s(Sym,Cat,Sense)],Stream):-
  642   frequency(Sym,Cat,Sense,F), !,
  643   format(Stream,'~p-~p-~p (F=~p)"];~n',[Sym,Cat,Sense,F]).
  644
  645printNode([s(Sym,Cat,Sense)|L],Stream):-
  646   frequency(Sym,Cat,Sense,F), !,
  647   format(Stream,'~p-~p-~p (F=~p)\\n',[Sym,Cat,Sense,F]),
  648   printNode(L,Stream).
  649
  650
  651/*------------------------------------------------------------------------
  652   Word Frequency
  653------------------------------------------------------------------------*/
  654
  655frequency(X,C,S,F):-
  656   word(X,C,S,F,_), !.
  657
  658frequency(_,_,_,0).
  659
  660
  661/*------------------------------------------------------------------------
  662   Print Relations
  663------------------------------------------------------------------------*/
  664
  665printIsa(Stream):-
  666   isa(I,J), 
  667   format(Stream,'   ~p -> ~p;~n',[J,I]),
  668   fail.
  669
  670printIsa(Stream):- 
  671   format(Stream,'~n}~n',[]).
  672
  673
  674/*========================================================================
  675   Add Concept 
  676========================================================================*/
  677
  678addConcept(Sym,Cat,Sense,ID):-
  679   concept(Concept,ID),
  680   member(s(Sym,Cat,Sense),Concept), !.
  681
  682addConcept(Sym1,Cat,Sense1,ID):-
  683   concept(Concept,ID),
  684   member(s(Sym2,Cat,Sense2),Concept), 
  685   syn(Cat,Sym1,Sense1,Sym2,Sense2),
  686   retract(concept(Concepts,ID)),
  687   assert(concept([s(Sym1,Cat,Sense1)|Concepts],ID)), !.  
  688
  689addConcept(Sym,Cat,Sense,ID):-
  690   getConceptId(ID),
  691   assert(concept([s(Sym,Cat,Sense)],ID)).
  692
  693
  694/*========================================================================
  695   Check for inconsistencies
  696========================================================================*/
  697
  698checkConsBK:-
  699   isa(A,B),
  700   isa(A,C), \+ C=B, !,
  701   format('inconsistent node ~p has two parents ~p and ~p~n',[A,B,C]).
  702
  703checkConsBK.
  704
  705
  706/*========================================================================
  707   Cut down redundant nodes
  708========================================================================*/
  709
  710cutDownMWN:-!,
  711   findall(I,concept(_,I),C), 
  712   cutDown(C).
  713
  714cutDown([]).
  715
  716cutDown([A|L]):-
  717   isa(A,B),                       %%% remove "hanging" nodes that are not
  718   \+ isa(_,A),                    %%% terminal symbols
  719   \+ word(_,_,_,_,A), !,
  720   retract(isa(A,B)),
  721   retract(concept(_,A)),
  722   cutDown(L).
  723
  724cutDown([B|L]):-
  725   isa(A,B), isa(B,C),              %%% two other nodes, but not for nodes that have an instance
  726   \+ word(_,_,_,_,B),
  727   \+ (isa(D,B), \+ D=A), !,
  728   retract(isa(A,B)),
  729   retract(isa(B,C)),
  730   retract(concept(_,B)),
  731   assert(isa(A,C)),
  732   cutDown(L).
  733
  734cutDown([_|L]):-
  735   cutDown(L).
  736
  737
  738/*========================================================================
  739   Add Top Concept (if there is not one yet)
  740========================================================================*/
  741
  742addTopMWN:-
  743   concept(E,B), member(s(event,n,1),E),     %%% place all verbs under
  744   concept(V,A), member(s(_,v,_),V),         %%% the event-1 concept
  745   \+ isa(A,_), !,
  746   assert(isa(A,B)), 
  747   addTopMWN.
  748
  749addTopMWN:-   
  750   concept(_,B), \+ isa(B,_),                %%% if there are at least two
  751   concept(_,C), \+ B=C, \+ isa(C,_), !,     %%% different nodes B and C without parent
  752   assert(concept([s('_top',n,0)],0)),       %%% then introduce a common top node
  753   assert(isa(B,0)),
  754   assert(isa(C,0)),
  755   addTopMWN1.
  756
  757addTopMWN.
  758
  759addTopMWN1:-                                 %%% second part of introducing top node
  760   concept([s('_top',n,0)],I),               %%% introduce top for all other nodes
  761   concept(_,B), \+ B=I,                     %%% without parents
  762   \+ isa(B,_), !,
  763   assert(isa(B,I)),
  764   addTopMWN1.
  765
  766addTopMWN1.
  767
  768
  769
  770/* ========================================================================
  771   Size WordNet (number of disjoint concepts)
  772======================================================================== */
  773
  774sizeMWN(Size):-
  775   findall(X,isa(X,_),L),
  776   length(L,Size).
  777
  778
  779/* ========================================================================
  780   Symbol Stop List
  781======================================================================== */
  782
  783stoplist(')',_).
  784stoplist('(',_).
  785stoplist('"',_).
  786stoplist('%',_).
  787stoplist('$',_).
  788stoplist('=',_).
  789stoplist('*',_).
  790stoplist('/',_).
  791stoplist('#',_).
  792stoplist('+',_).
  793stoplist('\\',_).
  794stoplist('>',_).
  795stoplist('<',_).
  796stoplist('\240',_).
  797
  798stoplist(quantity,n).
  799stoplist(more,n).
  800
  801
  802/*========================================================================
  803   Output MWN (prolog)
  804========================================================================*/
  805
  806outputMWN(Dir,File):-
  807   atomic_list_concat([Dir,'/',File,'.mwn'],Name),
  808   open(Name,write,Stream),
  809   printTerminals(Stream),
  810   close(Stream).
  811
  812
  813/*========================================================================
  814   Output terminal symbols
  815========================================================================*/
  816
  817printTerminals(Stream):-
  818   format(Stream,'%~n% word(+Word, +Cat, +Sense, +Frequency, +ConceptID).~n%~n',[]),
  819   word(X,C,S,N,I), \+ I = 0,
  820   format(Stream,'~q.~n',[word(X,C,S,N,I)]),
  821   fail.
  822
  823printTerminals(Stream):-
  824   format(Stream,'%~n% concept(+SynSet, +ConceptID).~n%~n',[]), 
  825   concept(I,J),
  826   format(Stream,'~q.~n',[concept(I,J)]),
  827   fail.
  828
  829printTerminals(Stream):-
  830   format(Stream,'%~n% isa(+SubConceptID, +SuperConceptID).~n%~n',[]),
  831   isa(I,J),
  832   format(Stream,'~p.~n',[isa(I,J)]),
  833   fail.
  834
  835printTerminals(Stream):-
  836   format(Stream,'%~n% isnota(+ConceptID, +ConceptID).~n%~n',[]),
  837   isnota(I,J),
  838   format(Stream,'~p.~n',[isnota(I,J)]),
  839   fail.
  840
  841printTerminals(_).
  842
  843
  844/*========================================================================
  845   Adjacent Indexes
  846========================================================================*/
  847
  848adjacent([I],[J]):- !, J is I + 1.
  849adjacent(Is,Js):- member(I,Is), member(J,Js), J is I + 1, !.
  850
  851
  852
  853/*------------------------------------------------------------------------
  854
  855   ALL BELOW IS NOT USED CURRENTLY --- SUBJECT TO REVISION!
  856
  857   Unknown word is a nationality
  858
  859unknownWord(Sym,_,Freq1):-
  860   nationality(Sym,_),
  861   minFreq(Min),
  862   word(inhabitant,n,Freq2,Id), 
  863   Freq2 > Min,
  864   getConceptId(NewId),
  865   assert(word(Sym,p,Freq1,NewId)),
  866   assert(concept([Sym],NewId)),
  867   assert(isa(NewId,Id)), !.
  868------------------------------------------------------------------------*/
  869
  870
  871/*------------------------------------------------------------------------
  872   Unknown word is known as a compound    
  873   (e.g. website -> web site)
  874
  875unknownWord(Sym1,n,Freq1):-
  876   minFreq(Min),
  877   name(Sym1,Codes1),
  878   append(Prefix,Postfix,Codes1),
  879   append(Prefix,[95|Postfix],Codes2),
  880   name(Sym2,Codes2),
  881   word(Sym2,Cat,Freq2,Id), 
  882   Freq2 > Min,
  883   \+ Id=0,
  884   assert(word(Sym1,Cat,Freq1,Id)),
  885   retract(concept(Concepts,Id)),
  886   assert(concept([Sym1|Concepts],Id)), !,  
  887   true.
  888%   format('Added word ~p similar to ~p~n',[Sym1,Sym2]).
  889------------------------------------------------------------------------*/
  890   
  891
  892/*------------------------------------------------------------------------
  893   Unknown compound word is known as a non compound 
  894   (e.g. web site -> website)
  895
  896unknownWord(Sym1,n,Freq1):-
  897   minFreq(Min),
  898   name(Sym1,Codes1),
  899   append(Prefix,[95|Postfix],Codes1),
  900   append(Prefix,Postfix,Codes2),
  901   name(Sym2,Codes2),
  902   word(Sym2,Cat,Freq2,Id), 
  903   Freq2 > Min,
  904   assert(word(Sym1,Cat,Freq1,Id)),
  905   retract(concept(Concepts,Id)),
  906   assert(concept([Sym1|Concepts],Id)), !,
  907   true.
  908%   format('Added word ~p similar to ~p~n',[Sym1,Sym2]).
  909------------------------------------------------------------------------*/
  910
  911   
  912/*------------------------------------------------------------------------
  913   Unknown compound word is hyponym of existing word
  914   E.g. winter_sport ISA sport
  915
  916unknownWord(Sym1,n,Freq1):-
  917   minFreq(Min),
  918   name(Sym1,Codes1),
  919   append(_,[95|Codes2],Codes1),
  920   name(Sym2,Codes2),
  921   word(Sym2,Cat,Freq2,Id), 
  922   Freq2 > Min,
  923   getConceptId(NewId),
  924   assert(word(Sym1,Cat,Freq1,NewId)),
  925   assert(concept([Sym1],NewId)),
  926   assert(isa(NewId,Id)), !,
  927   true. 
  928%   format('Hyponym word ~p of ~p~n',[Sym1,Sym2]).
  929------------------------------------------------------------------------*/
  930
  931
  932/*------------------------------------------------------------------------
  933   Unknown hyphenated word is hyponym of existing word
  934   E.g. Asian-American ISA American
  935
  936unknownWord(Sym1,Cat,Freq1):-
  937   member(Cat,[n,p]),
  938   minFreq(Min),
  939   name(Sym1,Codes1),
  940   append(_,[45|Codes2],Codes1),
  941   name(Sym2,Codes2),
  942   word(Sym2,Cat,Freq2,Id), 
  943   Freq2 > Min,
  944   getConceptId(NewId),
  945   assert(word(Sym1,Cat,Freq1,NewId)),
  946   assert(concept([Sym1],NewId)),
  947   assert(isa(NewId,Id)), !,
  948   true. 
  949%   format('Hyponym word ~p of ~p~n',[Sym1,Sym2]).
  950------------------------------------------------------------------------*/