home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / prolog / pdprolog / atnrpt.txt < prev    next >
Text File  |  1986-05-05  |  43KB  |  1,166 lines

  1. ..head01rCS680
  2. ..foot59ci
  3.  
  4.                   A Prolog Augmented Transition Network Parser
  5.  
  6.                                Table of Contents
  7.  
  8.  
  9. 1.  General                                                         1
  10.  
  11. 2.  ATN Form                                                        1
  12.  
  13.         Figure 1.  ATN Network                                      1
  14.         Figure 2.  Phrase Network                                   2
  15.  
  16. 3.  Approach                                                        2
  17.                                                                        
  18.         Phase I                                                     2
  19.         Phase II                                                    2
  20.         Phase III                                                   2
  21.  
  22. 4.  Phase I                                                         2
  23.  
  24. 5.  Phase II                                                        3
  25.  
  26. 6.  Phase III                                                       5
  27.                                                                     
  28.         ATNBLD                                                      6
  29.         ATNNEW                                                      8
  30.  
  31. 7.  Conclusions                                                     9
  32.  
  33. Attachements:                                                       
  34.  
  35. 1.  ATN.PRO                                                         
  36.  
  37.         Program Listing                                             1-1
  38.         Phase I - Example I                                         1-5
  39.         Phase I - Example II                                        1-6
  40.  
  41. 2.  ATNREV.PRO                                                      
  42.  
  43.         Program Listing                                             2-1
  44.         Phase II - Example I                                        2-4
  45.         Phase II - Example II                                       2-4
  46.  
  47. 3.  ATNBLD.PRO                                                      
  48.  
  49.         Program Listing                                             3-1
  50.         Example ATN Definition                                      3-3
  51.  
  52. 4.  ATNNEW1.PRO                                                     
  53.  
  54.         Program Listing                                             4-1
  55.         Phase III - Example I                                       4-4
  56.         Phase III - Example II (Subject Predicate Agreement)        4-5
  57. ..head01rCS680
  58. ..foot59c##
  59.                   A PROLOG AUGMENTED TRANSITION NETWORK PARSER
  60. 
  61.                                   submitted by
  62.  
  63.                               Ludwig J. Schumacher
  64.  
  65.                                November 26, 1985
  66.  
  67.  
  68. 1.  General.  This report documents the development of an Augmented Transition
  69. Network (ATN) sentence parser in the PROLOG language and is submitted in partial
  70. fulfillment of the requirements for CS 680, Natural Language Processing, George
  71. Mason University, Fall 1985.  It is assumed that the reader is familiar with
  72. natural language processing and PROLOG so associated terms will be used without
  73. explanation.  The author had no prior experience with logic programming and does
  74. not presume to evaluate the PROLOG language, only that small subset of commands
  75. he was able to master in attempting to apply the language to this specific
  76. project.  The examples contained herein are executed under A.D.A. PROLOG,
  77. ver 1.6c, (c) Automata Design Associates 1985.
  78.  
  79.  
  80. 2.  ATN Form.  The form of the ATN which is used in this paper is shown in
  81. Figure 1.  This form has been chosen not as comprehensive coverage of English
  82. sentence structure but to provide a simple form which does incorporate the major
  83. features of ATNs.  Figure 2 is the noun and prepositional phrase network.
  84. 
  85.               -  Transition from node to node based upon specified conditions.
  86.  
  87.               -  Optional conditions, such as the determiner and adjective in
  88.                  the noun phrase.
  89.                  
  90.               -  Augmentation with sub-networks such as the noun and
  91.                  prepositional phrases.
  92.  
  93.               -  Recursiveness such as the adjective in the noun phrase and the
  94.                  noun phrase at node 2.
  95.  
  96.  
  97.  
  98.  
  99.                                         np              pp
  100.                                       *   *           *   *
  101.                             verb     \/  *      pp   \/ * 
  102.       np  **** >  q1 ************** > q2/ ********** > q3/
  103.       *              *                /\
  104. q0 *                    *    aux      * verb
  105.       *                     *         *
  106.       aux **** >  q4 ************* >  q5
  107.                           np
  108. 
  109.  
  110.  
  111.  
  112.                              Figure 1.  ATN Network
  113.                    adj
  114.        det      *   *
  115.       ******    \/  *     noun                         prep
  116. qnp *       * >  qnp1 ********** > qnp2/        qpp ****** > qnp
  117.       ******
  118.        jump
  119.  
  120.                            Figure 2.  Phrase Network
  121.  
  122.  
  123. 3.  Approach.  The project was conducted in three phases.
  124.  
  125.     a.  Phase I.  Phase I was experimentation with PROLOG to develop some
  126. working application. An ATN parser was programmed but only by forcing PROLOG
  127. into a procedural mold.  This phase culminated in a briefing presented in class
  128. on 24 October.
  129.  
  130.     b.  Phase II.  Phase II was the translation of the procedures developed in
  131. Phase I into facts and rules appropriate for a logic program, which would more
  132. fully exploit the capabilities of PROLOG.
  133.  
  134.     c.  Phase III.  Phase III was additional experimentation to make the programs
  135. more dynamic and to exploit the power of an ATN to pass differing information
  136. depending upon the particular transition.  These experiments included procedures
  137. to automatically update the vocabulary, allow for user defined networks,
  138. refinement of the database search procedures, and incorporation of subject and
  139. predicate agreement verification.
  140.  
  141.  
  142. 4.  Phase I
  143.  
  144.     a.  The program developed during Phase I (Attachment 1) is not a logic
  145. program, but a set of procedures executed with the PROLOG language.  Procedures
  146. are defined as a set of 'q' rules which are passed the current node number and
  147. the unparsed and parsed parts of the sentence.  Each set of procedures defined
  148. the actions to be taken at that node. For example, q(0,_) are the procedures for
  149. node 0, q(1,_,_) are the procedures for node 1, etc.
  150.  
  151.     b.  There are a number of limitations to this approach.
  152.  
  153.               -  The addition of a node requires a new set of procedures and
  154. modification of the code for each node from which a transition can be made.
  155.  
  156.               -  It would be difficult to modify the code dynamically, since
  157. procedures must be executed in sequence, and changes would have to be inserted at
  158. specific points.
  159. 
  160.               -  Elimination of a node requires not only the elimination of the
  161. procedure for that node, but the removal of all calls to that node from other
  162. procedures.
  163.  
  164. ..page
  165. 5.  Phase II.  Phase II was the development of a logic program to accomplish the
  166. same functions as that developed during Phase I.  The approach was to translate
  167. the statement, "There is a transition from node X to node Y on condition Z", to
  168. the PROLOG equivalent "arc(X,Y,Z)".  The complete program is at Attachment 2 and
  169. appropriate sections are reproduced below.
  170. 
  171.     a.  The first step was to redefine the facts.  The transitions are in the
  172. form of arc(from node,to node,condition).
  173.  
  174.             arc(q0,q1,np).
  175.             arc(q1,q2,verb).
  176.             arc(q2,q2,np).
  177.             arc(q2,q3,pp).
  178.             arc(q0,q4,aux).
  179.             arc(q4,q5,np).
  180.             arc(q1,q5,aux).
  181.             arc(q5,q2,verb).
  182.  
  183.  
  184.     b. The terminal nodes are identified by term(at node,empty list), where the
  185. remainder of the sentence is the second variable.
  186.  
  187.             term(q2,[]).
  188.             term(q3,[]).
  189.  
  190.     c.  Since phrase transitions are based upon a series of words rather than a
  191. single condition, they are treated as separate networks.  The empty list as the
  192. transition condition is used to effect a jump.
  193.  
  194.             arc(qnp,qnp1,det).
  195.             arc(qnp,qnp1,[]).
  196.             arc(qnp1,qnp1,adj).
  197.             arc(qnp1,qnp2,noun).
  198.             arc(qpp,qnp,prep).
  199.  
  200.  
  201.     d.  With these 'facts' established, one can now use the recursive and
  202. backtracking nature of PROLOG to find a path from the initial point to a
  203. terminal node.
  204.  
  205.               1)  A sentence is input as a PROLOG list enclosed in brackets and
  206. with each word separated by a comma.  There is no punctuation at the end of the
  207. sentence.  All words must be in lower case.
  208.  
  209.               2)  Once the sentence, S, has been input, control is passed to the
  210. rule trans (transition).  The variables are: current node, next node, parsed
  211. sentence, sentence remaining to be parsed, and sentence remaining to be parsed
  212. after transition.
  213.  
  214.          trans(q0,Nq,Parse,S,S1)
  215. 
  216. ..page
  217.               3)  If the current node (Lq) is a terminal node and the remainder
  218. of the sentence (S1) is null, then the sentence has been parsed.
  219.  
  220. trans(Lq,_,Parse,S1,_) :- term(Lq,S1),nl,
  221.                           print('Completed ',Lq),
  222.                           nl,print(Parse).
  223.  
  224.  
  225.               4)  If the next word (S0) is the type (Type) to effect a
  226. transition, then trans is called recursively.  (Note: Nbr is a variable designed
  227. to provide information on the singularity or plurality of the word.  It is not
  228. used in this example.)
  229.  
  230. trans(Lq,Nq,Parse,[S0|S1],S1) :- word(S0,Type,Nbr),
  231.                                  arc(Lq,Nq,Type),
  232.                                  nl,
  233.                             print('Transition ',Lq,' ',Nq,' ',S0, ' ',Type),
  234.                                  append(Parse,[[Type],S0],P1),
  235.                                  !,
  236.                                  trans(Nq,Z,P1,S1,S2).
  237.  
  238.  
  239.               5)  If the next word in the sentence does not establish the
  240. criteria for a transition, check to determine if a phrase does. If so, the rest
  241. of the sentence is checked for the proper phrase, either np or pp. This requires
  242. the separate network check, ptrans, which allows parsing as the network is
  243. transitioned, but will return unchanged if it fails.
  244. 
  245.  
  246.  
  247. trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,np),
  248.                              ptrans(qnp,Nq,Lq,S0,[np],Parse).
  249.  
  250.  
  251. trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,pp),
  252.                              ptrans(qpp,Nq,Lq,S0,[pp],Parse).
  253.  
  254.  
  255.               6)  If no word or phrase has been found to effect a
  256. transition, the sentence will not parse.
  257.  
  258.  
  259. trans(Lq,Nq,Parse,S0,S1) :- !,nl,
  260.                             print('The sentence failed at ',Lq),
  261.                             nl,print('Parsed ',Parse),
  262.                             nl,print('Left ',S0).
  263.  
  264.  
  265.               7)  The phrase transition network code is almost identical to the
  266. primary code, except that it continues to call itself until such time as it
  267. reaches qnp2, which is the terminal node, or fails at a node other than qnp2.
  268. In the first case it will effect a transition to the next node (Nq) and call
  269. trans with the new data.  In the second case, ptrans will fail and conditions
  270. remain unchanged.
  271. ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :- word(S0,Type,Nbr),
  272.                                      arc(Bq,Zq,Type),
  273.                                      append(Pr,[[Type],S0],P1),
  274.                                      !,
  275.                                      ptrans(Zq,Nq,Lq,S1,P1,Parse).
  276.  
  277. ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :- nl,
  278.                                   print('Transition ',Lq,' ',Nq),
  279.                                   nl,
  280.                                   print(Pr),
  281.                                   append(Parse,Pr,P1),
  282.                                   !,
  283.                                   trans(Nq,Rq,P1,S0,S1).
  284.  
  285.  
  286. 6.  Phase III
  287. 
  288.     a.  These programs demonstrate that PROLOG can be used to develop an ATN
  289. parser but still do not exploit the power of PROLOG to operate in a dynamic
  290. environment.  Specific capabilities which should be included are:
  291.  
  292.               1)  The ATN should be able to provide additional information
  293. beyond whether or not the sentence parsed.
  294.  
  295.               2)  The program should assist the user in construction of the ATN
  296. definition.
  297.  
  298.               3)  The program should verify the words are in the vocabulary set
  299. before attempting to parse, and if not, allow them to be added.
  300.  
  301.               4)  The database search should be efficient. Especially in the
  302. case of a large vocabulary set, the initial form of word(Name,[type]) is
  303. unacceptable in that PROLOG must conduct a linear search of the entire set of
  304. words to identify success or failure.
  305.  
  306.                         (a)  Dr. Berghel, University of Nebraska, suggested in
  307. his presentation at George Mason that the vocabulary be stored as individual
  308. letters and the search space would be reduced to words of a particular length.
  309. For example, the word 'the' would be in the database as "word(t,h,e)".  In order
  310. to identify if "the" is in the vocabulary set, it is partitioned into the
  311. individual letters and only those words with arity 3 would need to be searched.
  312.  
  313.                         (b)  An alternative to the use of arity would be to
  314. construct each word as a separate fact.  Thus "the" would be represented as
  315. "the(word)".  It is assumed that PROLOG is more efficient searching a database
  316. of unique facts rather than one of fewer facts differentiated by arity.  There
  317. may, however, be some impact on memory requirements.  It must also be noted that
  318. this would not serve the spelling correction procedure outlined by Dr. Berghel.
  319.  
  320.                         (c)  A concept which could be integrated with either of
  321. the two approaches outlined above would be to allow the facts which are used
  322. more often to migrate to the front of the list. Specifically, exploit PROLOG's
  323. capability to alter the program by deleting facts when used and adding them to
  324. the front of the list.
  325.     b.  The two programs at Attachments 3 and 4 incorporate some of these
  326. concepts.  Attachment 3 is a listing and example use of the program 'ATNBLD'
  327. which can be used to build the primary transition network.  Attachment 4,
  328. 'ATNNEW', uses the network developed by ATNBLD, stores each word as a separate,
  329. unique fact, and identifies sentences in which the subject and predicate are not
  330. in number agreement.
  331.  
  332.               1) ATNBLD  ATNBLD requests the names of the nodes and the
  333. conditions for transition and establishes a separate database for the network
  334. defined by the user.  The initial node must be entered and all terminal nodes
  335. identified.  Then the user defines paths to each terminal node.
  336.  
  337.                         (a)  BUILD.  Build is the entry point into the program.
  338. It requests the start node (Q0), the terminal nodes, termnode, then transfers to
  339. flow.  The predicate 'ret', defined in a standard routine, is used to retract
  340. predicates.  It is used here to retract any predicates which would interfere
  341. with the construction of the network.  The predicates generated within the
  342. program are:
  343.  
  344.                         - term: defines that a node is a
  345.                                 terminal node
  346.  
  347.                         - qend: identifies nodes that have a
  348.                                 path to a terminal node
  349.  
  350.                         - arc:  identifies the transitions from
  351.                                 node to node
  352.  
  353.  
  354. build :- batch,ret(qend),nl,ret(arc),nl,ret(term),asserta(term([],[])),
  355.          consult(node),nl,print('Enter the start node: '),read(Q0),
  356.          asserta(qend(Q0)),termnode,flow(Q0).
  357.  
  358.  
  359. termnode :- print('Enter the next terminal node or the word done: '),
  360.             read(QT),
  361.             not(QT=done),
  362.             termck(QT),
  363.             assertfa(node,term(QT,[])),
  364.             asserta(qend(QT)),
  365.             termnode.
  366.  
  367. termnode  :-  !,true.
  368.  
  369.  
  370. termck(Qt)  :-  not(term(Qt,[]));
  371.                 nl,print('Terminal node ',Qt,' already entered'),nl.
  372.  
  373. ..page
  374.                         (b)  FLOW.  Flow is the primary control structure.  It
  375. requests the next node and the condition for transition.  It verifies that the
  376. condition is valid, that the arc has not been previously defined, and adds it to
  377. the database. The predicate 'qendck' verifies a path has been completed.
  378.  
  379. flow(Q0)  :- nl,print('Transition from ',Q0,' to ? '),read(Qnext),
  380.              print(' on condition ? '),read(Con),
  381.              con(Q0,Con),arcck(Q0,Qnext,Con),
  382.              assertfz(node,arc(Q0,Qnext,Con)),
  383.              qendck(Q0,Qnext).
  384.  
  385. con(Q0,Con) :- condition(Con).
  386.  
  387. con(Q0,Con) :- nl,print(Con,' is an invalid condition. '),
  388.                flow(Q0).
  389.  
  390. condition(verb).
  391. condition(noun).
  392. condition(aux).
  393. condition(prep).
  394. condition(aux).
  395. condition(pp).
  396. condition(np).
  397.  
  398.  
  399. arcck(Q0,Qn,Z)  :-  not(arc(Q0,Qn,Z));
  400.                     nl,print('Arc from ',Q0,' to ',Qn,' on ',Z,'
  401.                               exits.').
  402.  
  403.  
  404.                         (c) The predicate 'qendck' verifies that there is a path
  405. from the end node of the arc just entered to a terminal node.  If not, control
  406. is passed to 'flow', otherwise 'nextnode' allows a new path to be initiated or
  407. the program terminated. Pthck is used to verify that there is a path to each of
  408. the terminal nodes before the program is terminated. Checkstart prevents
  409. isolated nodes from being inserted into the network.
  410.  
  411.  
  412. qendck(Q0,Qnext)  :- qend(Qnext),(qend(Q0);asserta(qend(Q0))),nextnode.
  413.  
  414. qendck(Q0,Qnext)  :-  (qend(Q0);asserta(qend(Q0))),flow(Qnext).
  415.  
  416.  
  417. nextnode :- nl,print('Enter next start node or the word done ? '),
  418.             read(Ns),
  419.             not(Ns=done),
  420.             ((checkstart(Ns),
  421.             flow(Ns));nextnode).
  422.  
  423. ..page
  424. nextnode :-  pthck,
  425.              !,retract(term([],[])),
  426.              nl,print('Network completed'),
  427.              listing(arc),listing(term),
  428.              nl,print('Enter name of new ATN file '),read(S),
  429.              update(node,S),forget(node).
  430.  
  431.  
  432. nextnode :-  nextnode.
  433.  
  434.  
  435. pthck   :-    term(Q,[]),not(Q=[]),not(arc(_,Q,_)),
  436.               nl,print('No path to terminal node ',Q),
  437.               !,fail.
  438.  
  439. pthck    :-  term([],[]).
  440.  
  441.  
  442. checkstart(Ns) :-  qend(Ns);
  443.                    nl,print(Ns,' is an invalid node '),fail.
  444.  
  445.  
  446.               2) ATNNEW  One of the features of an ATN vis-a-vis other parsers
  447. is that the path of transversal can be used to provide information. ATNNEW is an
  448. example which demonstrates that this can be accomplished in PROLOG. This
  449. program, which is limited to the ATN in Figure 1, identifies the subject of the
  450. sentence as the noun (or nouns) in the noun phrase used to transition between
  451. nodes q0 and q1, or q4 and q5.  It also uses the 'p' or 's' associated with each
  452. noun or verb and checks the subject and predicate for agreement in number.  The
  453. code for the predicate ptrans, below, is annotated along the right-hand column
  454. with numbers to correspond to the notes below.
  455.  
  456.  ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :-  S0(Type,Nbr),                       -1
  457.                                        arc(Bq,Zq,Type),
  458.         ( ( not(Type=noun); subj(_) ); asserta(subj(Nbr)) ),               -2
  459.                                        append(Pr,[[Type],S0],P1),
  460.                                        ptrans(Zq,Nq,Lq,S1,P1,Parse).
  461.  
  462. ptrans(Bq,Nq,Lq,S,Pr,Parse)   :-  arc(Bq,Zq,[]),
  463.                                   ptrans(Zq,Nq,Lq,S,Pr,Parse).
  464.  
  465.  
  466. ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,(Lq=q4;Lq=q0),              -3
  467.                        ( ( subj(_),retract(subj(_)) ); not(subj(_)) ),     -4
  468.                                         asserta(subj(p)),                  -5
  469.                                         append(Pr,[and],P1),
  470.                                         ptrans(qnp,Nq,Lq,S1,P1,Parse).
  471.  
  472.  
  473. ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,                            -6
  474.                                         append(Pr,[and],P1),
  475.                                         ptrans(qnp,Nq,Lq,S1,P1,Parse).
  476.  
  477.  
  478.  
  479.  
  480. ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
  481.                                    print('Transition ',Lq,' ',Nq),
  482.                                    nl,
  483.                                    print(Pr),
  484.                                    append(Parse,Pr,P1),
  485.                                    trans(Nq,Rq,P1,S0,S1).
  486.  
  487.  
  488.  
  489.               -1.  S0 is the next word in the sentence.  Each word is defined as
  490. a unique fact with a type and number (p or s or x).
  491. 
  492.               -2.  This line establishes the number of the subject as that of
  493. the noun unless one has already been established.  The subject for all sentences
  494. covered by the ATN in Figure 1 will be located in noun phrases parsed before
  495. reaching node q2, hence nouns in noun phrases at node q2 or q3 will be ignored.
  496.  
  497.               -3.  This predicate is a special provision for the use of 'and' if
  498. the next word is 'and', and we are attempting to transition from node q4 or q0.
  499.  
  500.               -4.  Retract the predicate subj which contains the number for the
  501. subject.  The not(subj(_)) is actually not required, since the subj has had to
  502. been asserted if the program gets to this point but is included for balance.
  503.  
  504.               -5.  This part of the clause establishes the number associated with
  505. the subject as plural based on the use of and.
  506.  
  507.               -6.  This clause accounts for the case of an and in a noun phrase
  508. not at node q0 or q4.
  509.  
  510. 6.  Conclusions.  The programs developed for this project demonstrate that
  511. PROLOG is a powerful language that offers unique capabilities and interesting
  512. potential but little user interface. It is surprising that the power of the
  513. language has not been exploited to enhance the utility.
  514.  
  515.     a.  Any useful application will require some form of procedure.
  516. Construction of these procedures, such as in the Phase III example, is awkward
  517. in the current language.
  518.  
  519.     b.  Although all variables are local to a predicate, the dynamic nature of
  520. PROLOG enables the programmer to establish global variables through program
  521. modification.  It is this feature which appears to offer great potential.
  522.  
  523.     c.  There are some alternative search techniques, beyond the scope of this
  524. paper, which should be evaluated.
  525.  
  526.     d.  Given that these examples only employ the most rudimentary PROLOG
  527. commands, the language appears to offer a rich environment, limited primarily by
  528. the lack of user interface.
  529.  
  530.  
  531.  
  532. ..pgno1
  533. ..foot59c1-##
  534. /*                 Augmented Transition Network Program
  535.  
  536.                                   ATN.PRO
  537.  
  538.                                  10/22/85
  539. */
  540.  
  541.  
  542. /*  Standard routines for append & membership checking       */
  543.  
  544.  
  545. append([],L,L).
  546. append([Z|L1],L2,[Z|L3]) :- append(L1,L2,L3).
  547.  
  548. printstring([]).
  549. printstring([H|T]) :- put(H), printstring(T).
  550.  
  551. member(X,[X|_]).
  552. member(X,[_|Y]) :- member(X,Y).
  553.  
  554.  
  555. /*  The start module accepts a set of words, enclosed in brackets and
  556. separated by commas.  It calls wordck to verify that each of the words is
  557. in the vocabulary set.   */
  558.  
  559.  
  560.  
  561. start :- batch,nl,print('INPUT'),nl,print('-----'),nl,
  562.          nl,print('Input sentence: '),read(S),nl,
  563.          print('The working set is ',S),wordck(S),!,
  564.          nl,nl,print('TRANSFERS'),nl,nl,print('---------'),nl,nl,q(0,S).
  565.  
  566.  
  567.  
  568. /*  Wordck checks for the end of the set, [], then if the word is in the
  569. vocabulary.  If not, it asks for the category, and adds it to the file
  570. WORD.TEM which is joined with the program after it has run.*/
  571.  
  572.  
  573.  
  574. wordck([])   :-   !,true.
  575.  
  576. wordck([H|T]) :- word(H,Y),wordck(T).
  577.  
  578.  
  579. wordck([H|T]) :-  nl,print(H,' is not a recognized word '),
  580.                   nl,print(' enter verb,aux, .. '),read(Z),
  581.                   wordnew(H,Z),wordck(T).
  582.  
  583. wordnew(W,Z) :- assertz(word(W,Z)),open('word.tem',ar),
  584.                 nlf('word.tem'),
  585.                 printf('word.tem', 'word(', W, ',', Z, ').'),
  586.                 close('word.tem').
  587.  
  588.  
  589. /*  Trans checks the category of the current word (H) versus the category
  590. required to make a transition (Z).  */
  591.  
  592.  
  593. trans(H,Z)   :-  word(H,X), member(X,[Z]).
  594.  
  595.  
  596. qfail(Nq,S,E)  :-  !, nl,nl,print('The sentence failed at ',Nq),nl,
  597.                  print('The sentence form to this node is ',E),nl,
  598.                  print('The rest of the sentence is ',S),qend1.
  599.  
  600.  
  601. qend(Z,E)  :-  nl,nl,print('OUTPUT'),nl,print('------'),nl,nl,
  602.                print('The sentence is:'),nl,nl,print(E),nl,nl,
  603.                print('The sentence is completed at node ',Z),qend1.
  604.  
  605.  
  606. qend1 :- open('word.tem',ar),nlf('word.tem'),
  607.          close('word.tem'),exec('ren atn.pro atn.sav'),
  608.          exec('copy atn.sav+word.tem atn.pro'),
  609.          exec('erase atn.sav'),exec('erase word.tem').
  610.  
  611.  
  612. /*    Print transfer from node to node */
  613.  
  614.  
  615. qout(A,B,C,D,E,F) :- append(E,[C,'(',A,')'],F),
  616.                      nl, print('Transfer from node ',B,' to node ',D,
  617.                      ' by word ',A,' evaluated as a ',C).
  618.  
  619.  
  620. /*   Main program to check the conditions for transfer from node to node.
  621.      The first number is the number of the node, i.e. q(0.. is node 0.
  622.      The module either checks for a word type and transfers control
  623.      directly, or passes to np / pp the next node.                    */
  624.  
  625.  
  626. /*  Node 0 - aux to 4 / np to 1 / or fail          */
  627.  
  628.  
  629. q(0,[H|T])  :-  trans(H,[aux]),!,qout(H,0,[aux],4,E,F), q(4,T,F).
  630.  
  631. q(0,[H|T])  :-  np(H,T,1,[],0,[np]).
  632.  
  633. q(0,S)      :-  qfail(0,S,[]).
  634.  
  635.  
  636. /*  Node 1 - verb to 2 / aux to 5 / or fail    */
  637.  
  638.  
  639. q(1,[H|T],E)  :-  trans(H,[verb]),!,qout(H,1,[verb],2,E,F), q(2,T,F).
  640.  
  641. q(1,[H|T],E)  :-  trans(H,[aux]),!, qout(H,1,[aux],5,E,F), q(5,T,F).
  642.  
  643. q(1,S,E)      :-  qfail(1,S,E).
  644.  
  645. /*  Node 2 -  null to end / np to 2 / pp to 3 / or fail     */
  646.  
  647.  
  648. q(2,H,E)      :- member(H,[[]]), !,
  649.                    qend(2,E).
  650.  
  651. q(2,[H|T],E)  :-  np(H,T,2,E,2,[np]).
  652.  
  653.  
  654. q(2,[H|T],E)  :-  pp(H,T,3,E,2,[pp]).
  655.  
  656. q(2,S,E)      :-  qfail(2,S,E).
  657.  
  658.  
  659. /*  Node 3 - null to end / or fail         */
  660.  
  661.  
  662. q(3,H,E)  :- trans(H,[]), !,
  663.              qend(3,E).
  664.  
  665. q(3,S,E)      :-  qfail(3,S,E).
  666.  
  667.  
  668.  
  669. /*  Node 4 - np to 5 / or fail           */
  670.  
  671.  
  672. q(4,[H|T],E)  :-  np(H,T,5,E,4,[np]).
  673.  
  674. q(4,S,E)      :-  qfail(4,S,E).
  675.  
  676.  
  677.  
  678. /*  Node 5 - verb to 2 / or fail         */
  679.  
  680.  
  681. q(5,[H|T],E)  :-  trans(H,[verb]),!, qout(H,5,[verb],2,E,F), q(2,T,F).
  682.  
  683. q(5,S,E)      :-  qfail(5,S,E).
  684.  
  685.  
  686.  
  687. /*  Noun phrase -  (det) (adj) (adj) .. noun        */
  688.  
  689. /*  The np1 clause is required to allow recursive calls for adj   */
  690.  
  691.  
  692. np(H,[S|T],Nq,E,Lq,G)  :-  trans(H,[det]), !,
  693.                            append(G,['det(',H,')'],G1),
  694.                            np1([S|T],Nq,E,Lq,G1).
  695.  
  696.  
  697. np(H,Z,Nq,E,Lq,G)      :-  np1([H|Z],Nq,E,Lq,G).
  698.  
  699.  
  700.  
  701. np1([H|T],Nq,E,Lq,G)  :-  trans(H,[adj]),
  702.                           append(G,['adj(',H,')'],G1),
  703.                           np1(T,Nq,E,Lq,G1).
  704.  
  705.  
  706. np1([H|T],Nq,E,Lq,G)  :- trans(H,[noun]),!,nl,
  707.                          append(G,['noun(',H,')'],G1),
  708.                          append(E,G1,F),
  709.                          print('Transfer from node ',Lq,' to ',Nq),
  710.                          print(' by ',G1),q(Nq,T,F).
  711.  
  712.  
  713. /*  Prep phrase requires a prep followed by a np   */
  714.  
  715.  
  716. pp(H,[S|T],Nq,E,Lq,G)  :-  trans(H,[prep]),
  717.                            append(['prep(',H,')'],G,G1),
  718.                            np(S,T,Nq,E,Lq,G1).
  719.  
  720.  
  721. /*   Word defines the vocabulary set                  */
  722.  
  723.  
  724. word(the,[det]).
  725. word(boy,[noun]).
  726. word(runs,[verb]).
  727. word(happy,[adj]).
  728. word(john,[noun]).
  729. word(can,[aux]).
  730. word(run,[verb]).
  731. word(a,[det]).
  732. word(big,[adj]).
  733. word(small,[adj]).
  734. word(girl,[noun]).
  735. word(dog,[noun]).
  736. word(on,[prep]).
  737. word(pretty,[adj]).
  738. word(fast,[adj]).
  739. word(barks,[verb]).
  740. word(to,[prep]).
  741. word([],[]).
  742. word(giant, [noun]).
  743. word(is, [verb]).
  744. word(giant, [noun]).
  745. word(is, [verb]).
  746. word(sleeps, [verb]).
  747. word(mary, [noun]).
  748. word(likes, [verb]).
  749.  
  750. ..pgno1
  751. ..foot59c2-##
  752. /*                 Augmented Transition Network Program
  753.  
  754.                                 ATNREV.PRO
  755.  
  756.                                  11/24/85
  757. */
  758.  
  759.  
  760. /*  Standard routines for append & membership checking       */
  761.  
  762.  
  763. append([],L,L).
  764. append([Z|L1],L2,[Z|L3]) :- append(L1,L2,L3).
  765.  
  766. printstring([]).
  767. printstring([H|T]) :- put(H), printstring(T).
  768.  
  769. member(X,[X|_]).
  770. member(X,[_|Y]) :- member(X,Y).
  771.  
  772.  
  773. /*  The start module accepts a set of words, enclosed in brackets and
  774. separated by commas.  It calls wordck to verify that each of the words is
  775. in the vocabulary set.   */
  776.  
  777.  
  778. start :- batch,nl,print('INPUT'),nl,print('-----'),nl,
  779.          nl,print('Input sentence: '),read(S),nl,
  780.          print('The working set is ',S),wordck(S),!,
  781.          nl,nl,print('TRANSFERS'),nl,nl,print('---------'),nl,nl,
  782.          Parse=[],
  783.          trans(q0,Nq,Parse,S,S1).
  784.  
  785.  
  786. /*  Wordck checks for the end of the set, [], then if the word is in the
  787. vocabulary.  If not, it asks for the category, and adds it to the file
  788. WORD.TEM which is joined with the program after it has run.*/
  789.  
  790.  
  791. wordck([])   :-   !,true.
  792.  
  793. wordck([H|T]) :- word(H,_,_),wordck(T).
  794.  
  795.  
  796. wordck([H|T]) :-  nl,print(H,' is not a recognized word '),
  797.                   nl,print(' enter verb,aux, .. '),read(Z),
  798.                   wordnew(H,Z),wordck(T).
  799.  
  800. wordnew(W,Z) :- assertz(word(W,Z,s)),open('word.tem',ar),
  801.                 nlf('word.tem'),
  802.                 printf('word.tem', 'word(', W, ',', Z, ').'),
  803.  
  804.  
  805.  
  806.  
  807. /*  The arcs are defined in terms of from node, to node, condition.
  808. Terminal nodes are identified with the empty list.  Words are defined by
  809. type word name, type, and a character to be used in later examples with the
  810. number (plural or singular).  */
  811.  
  812.  
  813. arc(q0,q1,np).
  814. arc(q1,q2,verb).
  815. arc(q2,q2,np).
  816. arc(q2,q3,pp).
  817. arc(q0,q4,aux).
  818. arc(q4,q5,np).
  819. arc(q1,q5,aux).
  820. arc(q5,q2,verb).
  821.  
  822. term(q2,[]).
  823. term(q3,[]).
  824.  
  825.  
  826. word(boy,noun,s).
  827. word(boys,noun,pl).
  828. word(run,verb,pl).
  829. word(runs,verb,s).
  830. word(the,det,s).
  831.  
  832. arc(qnp,qnp1,det).
  833. arc(qnp,qnp1,_).
  834. arc(qnp1,qnp1,adj).
  835. arc(qnp1,qnp2,noun).
  836. arc(qpp,qnp,prep).
  837.  
  838.  
  839. /*  Trans recursively checks the conditions for transition from the last
  840. node (Lq) to the next node (Nq).  Phrases are specifically treated as pp or
  841. np in order to allow the type of phrase to be identified in the parsed
  842. sentence.  */
  843.  
  844.  
  845. trans(Lq,_,Parse,S1,_) :- term(Lq,S1),nl,
  846.                           print('Completed ',Lq),
  847.                           nl,print(Parse).
  848.  
  849.  
  850. trans(Lq,Nq,Parse,[S0|S1],S1) :-  word(S0,Type,Nbr),
  851.                                   arc(Lq,Nq,Type),
  852.                                   nl,
  853.                                   print('Transition ',Lq,' ',Nq,' ',S0,
  854.                                             ' ',Type),
  855.                                   append(Parse,[[Type],S0],P1),
  856.                                   !,
  857.                                   trans(Nq,Z,P1,S1,S2).
  858.  
  859.  
  860. trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,np),
  861.                              ptrans(qnp,Nq,Lq,S0,[np],Parse).
  862.  
  863.  
  864. trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,pp),
  865.                              ptrans(qpp,Nq,Lq,S0,[pp],Parse).
  866.  
  867.  
  868.  
  869. trans(Lq,Nq,Parse,S0,S1) :- !,nl,
  870.                             print('The sentence failed at ',Lq),
  871.                             nl,print('Parsed ',Parse),
  872.                             nl,print('Left ',S0).
  873.  
  874. /*  Ptrans checks the transition of the phrase network.  The first clause
  875. calls itself recursively until node qnp2 has been reached, which concludes
  876. the transition.  Success results in trans being called  with the new node.
  877. Failure returns the trans with conditions unchanged.  */
  878.  
  879.  
  880. ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :-  word(S0,Type,Nbr),
  881.                                 arc(Bq,Zq,Type),
  882.                                 append(Pr,[[Type],S0],P1),
  883.                                 !,
  884.                                 ptrans(Zq,Nq,Lq,S1,P1,Parse).
  885.  
  886. ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
  887.                                    print('Transition ',Lq,' ',Nq),
  888.                                    nl,
  889.                                    print(Pr),
  890.                                    append(Parse,Pr,P1),
  891.                                    !,
  892.                                    trans(Nq,Rq,P1,S0,S1).
  893.  
  894. ..page
  895. ..pgno1
  896. ..foot59c3-##
  897. /*        PROGRAM TO BUILD PRIMARY AUGMENTED TRANSITION NETWORK
  898.  
  899.                                 ATNBLD.PRO
  900.  
  901.                                  11/24/85
  902.  
  903. */
  904.  
  905.  
  906. /*  Build is the entry point into the program.  It requires that the
  907. program with standard routines and the program node, which is empty, have
  908. already been consulted.  */
  909.  
  910. /*  The program requests the start and terminal nodes, the paths and
  911. transition conditions, then establishes a node program with a name
  912. specified by the user.  */
  913.  
  914. /*  Ret removes any data from memory which might interfere with network
  915. construction.  Term([],[]) is required to prevent failure when checkint
  916. terminal conditions.  Qend identifies all nodes for which there is a path
  917. to a terminal node.  The start node is identified initially since the
  918. program will require this path be completed before any other can be
  919. constructed.  Termnode accepts the terminal nodes.  Flow accepts the
  920. transition arcs and conditions.  */
  921.  
  922.  
  923. build :- batch,ret(qend),nl,ret(arc),nl,ret(term),asserta(term([],[])),
  924.          nl,print('Enter the start node: '),read(Q0),
  925.          asserta(qend(Q0)),termnode,flow(Q0).
  926.  
  927.  
  928. termnode :-  print('Enter the next terminal node or the word done: '),
  929.              read(QT),
  930.              not(QT=done),
  931.              termck(QT),
  932.              assertfa(node,term(QT,[])),
  933.              asserta(qend(QT)),
  934.              termnode.
  935.  
  936. termnode  :-  !,true.
  937.  
  938.  
  939. /*  Flow requests transitions from node to node and adds each arc and new
  940. node to the database.  Qendck will continue to call flow until such time as
  941. a terminal node has been reached then allow a new path to be initiated.  */
  942.  
  943.  
  944.  
  945. flow(Q0)  :- nl,print('Transition from ',Q0,' to ? '),read(Qnext),
  946.              print(' on condition ? '),read(Con),
  947.              con(Q0,Con),arcck(Q0,Qnext,Con),
  948.              assertfz(node,arc(Q0,Qnext,Con)),
  949.              qendck(Q0,Qnext).
  950.  
  951. con(Q0,Con) :- condition(Con).
  952.  
  953. con(Q0,Con) :- nl,print(Con,' is an invalid condition. '),
  954.                flow(Q0).
  955.  
  956. termck(Qt)  :-  not(term(Qt,[]));
  957.                 nl,print('Terminal node ',Qt,' already entered'),nl.
  958.  
  959. arcck(Q0,Qn,Z)  :-  not(arc(Q0,Qn,Z));
  960.                     nl,print('Arc from ',Q0,' to ',Qn,' on ',Z,' exits.').
  961.  
  962. qendck(Q0,Qnext)  :-  qend(Qnext),(qend(Q0);asserta(qend(Q0))),nextnode.
  963.  
  964. qendck(Q0,Qnext)  :-  (qend(Q0);asserta(qend(Q0))),flow(Qnext).
  965.  
  966.  
  967. /*  Nextnode allows a new path to be initiated or the program to be
  968. terminated.  Before termination it calls pthck to insure there is a path to
  969. each terminal node.  Checkstart prevents an isolated node from being
  970. entered.  */
  971.  
  972. nextnode :-  nl,print('Enter next start node or the word done ? '),
  973.              read(Ns),
  974.              not(Ns=done),
  975.              ((checkstart(Ns),
  976.              flow(Ns));nextnode).
  977.  
  978. nextnode :-  pthck,
  979.              !,retract(term([],[])),
  980.              nl,print('Network completed'),
  981.              listing(arc),listing(term),
  982.              nl,print('Enter name of new ATN file '),read(S),
  983.              update(node,S).
  984.  
  985. nextnode :-  nextnode.
  986.  
  987. pthck   :-    term(Q,[]),not(Q=[]),not(arc(_,Q,_)),
  988.               nl,print('No path to terminal node ',Q),
  989.               !,fail.
  990.  
  991. pthck    :-  term([],[]).
  992.  
  993. checkstart(Ns) :-  qend(Ns);
  994.                    nl,print(Ns,' is an invalid node '),fail.
  995.  
  996. /*  Condition lists the acceptable conditions for a transition.   */
  997.  
  998. condition(verb).
  999. condition(noun).
  1000. condition(aux).
  1001. condition(prep).
  1002. condition(aux).
  1003. condition(pp).
  1004. condition(np).
  1005. ..pgno1
  1006. ..foot59c4-##
  1007. /*              FINAL AUGMENTED TRANSITION NETWORK PROGRAM
  1008.  
  1009.                                 ATNNEW1.PRO
  1010.  
  1011.                                  11/24/85
  1012. */
  1013.  
  1014.  
  1015. /*  Start is the entry into the program.  It requires that a set of
  1016. standard routines has already been consulted (append in particular).  It
  1017. allows the user to specify the network program, which can be build using
  1018. ATNBLD.  Words is a file with the vocabulary set.  The sentences is a list
  1019. of words separated by commas and enclosed in brackets.  Wordck verifies
  1020. that the words are in the vocabulary set, and if not requests required
  1021. data. Parse is the sentence as it is parsed.  Trans controls the flow from
  1022. node to node.  */
  1023.  
  1024. start :- nl,print('ATN network file? '),read(Fn),
  1025.          consult(Fn),nl,
  1026.          asserta(file(Fn)),
  1027.          consult(words),nl,
  1028.          batch,nl,print('INPUT'),nl,print('-----'),nl,
  1029.          nl,print('Input sentence: '),read(S),nl,
  1030.          print('The working set is ',S),wordck(S),
  1031.          nl,nl,print('TRANSFERS'),nl,nl,print('---------'),nl,nl,
  1032.          Parse=[],
  1033.          trans(q0,Nq,Parse,S,S1).
  1034.  
  1035.  
  1036. wordck([])   :-   true.
  1037.  
  1038. wordck([H|T]) :- H(_,_),wordck(T).
  1039.  
  1040. wordck([H|T]) :-  nl,print(H,' is not a recognized word '),
  1041.                   nl,print(' enter verb,aux, .. '),read(Z),
  1042.                   nl,print(' enter p or s or x  '),read(Z1),
  1043.                   wordnew(H,Z,Z1),wordck(T).
  1044.  
  1045. wordnew(W,Z,Z1) :- assertfz(words,W(Z,Z1)).
  1046.  
  1047.  
  1048. /*  Since the phrase transition network includes more specific procedures
  1049. than the primary network, it is included in this program rather than in the
  1050. network file consulted by start.  It could be more dynamic, but that was
  1051. considered beyond the scope of this project.  */
  1052.  
  1053.  
  1054. arc(qnp,qnp1,det).
  1055. arc(qnp,qnp1,[]).
  1056. arc(qnp1,qnp1,adj).
  1057. arc(qnp1,qnp2,noun).
  1058. arc(qpp,qnp,prep).
  1059.  
  1060.  
  1061. /*  Trans controls the flow along the network.  If a terminal node has been
  1062. reached and the entire sentence has been parsed, the agreement in number
  1063. (plural or singular) between the subject and predicate is checked.  If they
  1064. do not agree, this fact is displayed.  Update words creates a file
  1065. WORDS.$$$ which contains the new vocabulary.
  1066.  
  1067. If a conditions for termination has not been met, trans checks for a
  1068. transition word or a transition phrase.  If none of these conditions are
  1069. met, the sentence will not parse.
  1070.  
  1071. When a verb is encountered the number (singular or plural) is 'filed'.
  1072. This procedure is unique for a specific network in which only one verb can
  1073. be encountered.  */
  1074.  
  1075. trans(Lq,_,Parse,S1,_) :- term(Lq,S1),nl,
  1076.                           print('Completed ',Lq),
  1077.                           nl,print(Parse),
  1078.                        (  ( subj(Nbr),pred(Nbr) );
  1079.                       (nl,print('The subject and predicate do not agree.')
  1080.                           ) ),
  1081.                           update(words),
  1082.                           exec('erase words.pro'),
  1083.                           exec('ren words.$$$ words.pro'),
  1084.                           forget(words),
  1085.                           file(Fn),
  1086.                           forget(Fn),
  1087.                           endclr.
  1088.  
  1089. endclr :-  (not(file(_));ret(file)),(not(subj(_));ret(subj)),
  1090.            (not(pred(_));ret(pred)).
  1091.  
  1092.  
  1093. trans(Lq,Nq,Parse,[S0|S1],S1) :-  S0(Type,Nbr),
  1094.                                   arc(Lq,Nq,Type),
  1095.                                  ((Type=verb,asserta(pred(Nbr)));
  1096.                                      not(type=verb)),
  1097.                                   nl,
  1098.                                   print('Transition ',Lq,' ',Nq,' ',S0,
  1099.                                             ' ',Type),
  1100.                                   append(Parse,[[Type],S0],P1),
  1101.                                   trans(Nq,Z,P1,S1,S2).
  1102.  
  1103.  
  1104. trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,np),
  1105.                              ptrans(qnp,Nq,Lq,S0,[' '+np],Parse).
  1106.  
  1107. trans(Lq,Nq,Parse,S0,S1) :-  arc(Lq,Nq,pp),
  1108.                              ptrans(qpp,Nq,Lq,S0,[' '+pp],Parse).
  1109.  
  1110. trans(Lq,Nq,Parse,S0,S1) :- nl,
  1111.                             print('The sentence failed at ',Lq),
  1112.                             nl,print('Parsed ',Parse),
  1113.                             nl,print('Left ',S0),
  1114.                             endclr.
  1115. /*  Ptrans checks the transition of the phrase network.  It calls itself
  1116. recursively until node qnp2 is reached.  Provisions are included to
  1117. establish the number (plural or singular) of the subject, which is designed
  1118. for a specific network in which the noun phrase in which the subject is
  1119. located will be encountered before any other noun phrase.
  1120.  
  1121. The upon reaching qnp2 a check is made for the word 'and'.  If encountered,
  1122. the number of the subject is changed to plural and a check for another noun
  1123. phrase is initiated.
  1124.  
  1125. The spacing of the parenthesis is to facilitate reading of the code.  */
  1126.  
  1127.  
  1128. ptrans(Bq,Nq,Lq,[S0|S1],Pr,Parse) :-  S0(Type,Nbr),
  1129.                                 arc(Bq,Zq,Type),
  1130.                           (
  1131.                              (
  1132.                                  not(Type=noun);
  1133.  
  1134.                                  subj(_)
  1135.                                           );
  1136.                                  asserta(subj(Nbr))
  1137.                                                   ),
  1138.                                 append(Pr,[[Type],S0],P1),
  1139.                                 ptrans(Zq,Nq,Lq,S1,P1,Parse).
  1140.  
  1141. ptrans(Bq,Nq,Lq,S,Pr,Parse)   :-  arc(Bq,Zq,[]),
  1142.                                   ptrans(Zq,Nq,Lq,S,Pr,Parse).
  1143.  
  1144.  
  1145. ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,(Lq=q4;Lq=q0),
  1146.                                        ( ( subj(_),retract(subj(_)) );
  1147.                                          not(subj(_)) ),
  1148.                                          asserta(subj(p)),
  1149.                                           append(Pr,[and],P1),
  1150.                                           ptrans(qnp,Nq,Lq,S1,P1,Parse).
  1151.  
  1152.  
  1153. ptrans(qnp2,Nq,Lq,[S0|S1],Pr,Parse) :-  S0=and,
  1154.                                           append(Pr,[and],P1),
  1155.                                           ptrans(qnp,Nq,Lq,S1,P1,Parse).
  1156.  
  1157.  
  1158.  
  1159.  
  1160. ptrans(qnp2,Nq,Lq,S0,Pr,Parse) :-  nl,
  1161.                                    print('Transition ',Lq,' ',Nq),
  1162.                                    nl,
  1163.                                    print(Pr),
  1164.                                    append(Parse,Pr,P1),
  1165.                                    trans(Nq,Rq,P1,S0,S1).
  1166.