;;; Copyright (c) 1998-2005
;;; John Carroll, Ann Copestake, Robert Malouf, Stephan Oepen;
;;; see `LICENSE' for conditions
(in-package "MRS")
;;; Variant of munging rules for generation heuristics for
;;; filtering items with no semantics
;;; (read-mrs-rule-file-aux "~aac/grammar/data/genrules.mrs" t)
(defun predict-for-gen nil
;;; for debugging
(format t "~%~A " lkb::*sentence*)
(dolist (edge lkb::*parse-record*)
(let ((mrs-struct (extract-mrs edge)))
(when mrs-struct
(unless lkb::*gen-rule-list*
(error "~%No heuristic rules defined"))
(format t "~%~S"
(genpredict-mrs-struct mrs-struct
lkb::*gen-rule-list*))))))
(defun test-gen-predict-on-parse (&optional parses sentence (ostream t))
#+:mt
(declare (special mt::*transfer-triggers*))
(dolist (parse (or parses *parse-record*))
(let* ((mrs-struct (extract-mrs parse))
(lex-ids (lkb::edge-lex-ids parse))
(null-sem-lex-ids
(loop for id in lex-ids
when (null-semantics-entry-p id)
collect id)))
(when mrs-struct
(let ((predicted-ids
(cond
#+:mt
((and (hash-table-p mt::*transfer-triggers*)
(> (hash-table-count mt::*transfer-triggers*) 0))
(oe-genpredict-mrs-struct mrs-struct))
(lkb::*gen-rule-list*
(genpredict-mrs-struct mrs-struct lkb::*gen-rule-list*))
(t (format ostream "~%Warning: no trigger rules defined")
nil))))
(unless (subsetp null-sem-lex-ids predicted-ids)
(format ostream "~%Missing predictions:")
(when sentence
(format ostream "~%~A" sentence))
(dolist (null-id null-sem-lex-ids)
(when (not (member null-id predicted-ids))
(format ostream " ~A" null-id)))))))))
#|
test-gen-predict-on-mrs-file
reads in:
outputs:
|#
#|
(test-gen-predict-on-nullsem-file "stuart/bnc.short.xml"
"stuart/bnc.short-pred.xml")
(test-gen-predict-on-nullsem-file "stuart/bnc_rand_subset.xml"
"stuart/bnc_rand_subset-pred.xml")
(defun test-gen-predict-on-nullsem-file (ifile ofile)
;;; reads from to , outputs to a tmp file
;;; then reads in the tmp file
(declare (special mt::*transfer-triggers*))
(let ((*package* (find-package :mrs)))
(with-open-file (istream ifile :direction :input)
(with-open-file (ostream ofile :direction :output :if-exists :supersede)
(loop
(let ((first-line nil)
(tmp-lines nil)
(next-line nil))
(loop
(setf first-line (read-line istream nil nil))
(when (or (equal first-line "")
(null first-line))
(return)))
(unless first-line
(return)) ; eof - get out of loop
(push first-line tmp-lines)
(loop
(setf next-line (read-line istream nil nil))
(unless next-line (return))
(push next-line tmp-lines)
(when (equal next-line "")
(return)))
(unless next-line (return)) ; eof - get out of loop
(setf tmp-lines (nreverse tmp-lines))
(with-open-file
(otmp "tmp-p" :direction :output :if-exists :supersede)
(dolist (line tmp-lines)
(write-line line otmp)))
(with-open-file
(itmp "tmp-p" :direction :input)
(let ((ns (parse-xml-removing-junk itmp)))
(test-gen-predict-on-ns ns ostream)))
(finish-output ostream)))))))
(defun test-gen-predict-on-ns (content ostream)
(unless (equal (car content) '|null-sem|)
(error "Tough"))
(setf content (cdr content))
(loop (let ((next-el (car content)))
(if (xml-whitespace-string-p next-el)
(pop content)
(return))))
(when content
(let ((sentence-rec (car content))
(sentence nil))
(unless (equal (car sentence-rec) '|sentence|)
(error "Not sentence"))
(setf sentence (cadr sentence-rec))
(write-line "" ostream)
(format ostream "~A~%" sentence)
(loop for pr in (cdr content)
unless (xml-whitespace-string-p pr)
do
(test-gen-predict-on-ns-pr pr ostream))
(write-line "" ostream))))
(defun test-gen-predict-on-ns-pr (content ostream)
(loop (let ((next-el (car content)))
(if (xml-whitespace-string-p next-el)
(pop content)
(return))))
(when content
(unless (eql (car content) '|parse-record|)
(error "Not parse record"))
(write-line "" ostream)
(setf content (cdr content))
(loop (let ((next-el (car content)))
(if (xml-whitespace-string-p next-el)
(pop content)
(return))))
(let ((mrs-struct (read-mrs-xml (car content))))
(unless mrs-struct
(error "No mrs"))
(let ((predicted-ids
(cond
#+:mt
((and (hash-table-p mt::*transfer-triggers*)
(> (hash-table-count mt::*transfer-triggers*) 0))
(oe-genpredict-mrs-struct mrs-struct))
(lkb::*gen-rule-list*
(genpredict-mrs-struct mrs-struct lkb::*gen-rule-list*))
(t (format t "~%Warning: no trigger rules defined")
nil))))
(output-mrs1 mrs-struct 'mrs-xml ostream)
(dolist (id predicted-ids)
(format ostream "~A~%" id)))
(loop for id in (cdr content)
unless (xml-whitespace-string-p id)
do
(unless (eql (car id) '|id|)
(error "id"))
(format ostream "~A~%" (cadr id)))
(write-line "" ostream))))
|#
#+:mt
(defun oe-genpredict-mrs-struct (input-sem)
;;; copied from lexlookup.lisp
(let ((triggers (mt::transfer-mrs
input-sem :filter nil :task :trigger)))
(remove-duplicates
(loop
for edge in triggers
for mtr = (mt::edge-rule edge)
for id = (mt::mtr-trigger mtr)
when (and id
(not (lkb::smember
id lkb::*duplicate-lex-ids*)))
collect id))))
(defun genpredict-mrs-struct (mrsstruct rules)
;;; takes an mrs structure and a set of generation rules
;;; using the output of the rules to predict null semantic
;;; items for generation
;;; Rules are applied in order and are not applied recursively
(if rules
(progn
(setf *original-variables* nil)
(let ((null-ids nil))
(dolist (rule rules)
(let ((new-results
(match-mrs-rule
mrsstruct
(mrs-munge-rule-input-condition rule))))
(when new-results
(pushnew (mrs-munge-rule-output-spec
rule) null-ids))))
null-ids))
;;; NB - we do only want one instance of an id
;;; despite the fact that more than one may be required in
;;; a sentence.
(progn
(format t "~%Warning: no generator prediction rules have been set")
*empty-semantics-lexical-entries*)))
;;; *************** Rule input ****************
#|
(read-mrs-rule-file-aux "~aac/grammar/data/genrules.mrs" t)
|#
(defun construct-gen-rule-from-fs (id fs funny-unifs)
;;; input and output are constructed using construct-mrs
;;; with a given variable-generator
(declare (ignore id))
(when funny-unifs
(error "Funny unifs not expected in generator rules"))
(let ((output-fs (path-value fs *mrs-rule-output-path*))
(condition-fs (path-value fs *mrs-rule-condition-path*)))
(if (and condition-fs output-fs)
(let* ((variable-generator (create-variable-generator 1000))
(output-spec (construct-output-id output-fs))
(condition-spec
(construct-mrs condition-fs variable-generator)))
(if (and condition-spec output-spec)
(progn
(pushnew output-spec *gen-rule-ids* :test #'eq)
(make-mrs-munge-rule
:output-spec output-spec
:input-condition condition-spec)))))))
(defun construct-output-id (fs)
(let ((res (fs-type fs)))
(if (stringp res)
(intern (string-upcase res) :lkb))))