;;;;; #################################################################### ;;;;; FCG tutorial 2.3: Feature matrices and the expand-operator. ;;;;; #################################################################### ;; Load the root templates: ;; (asdf:operate 'asdf:load-op :root-templates) (in-package :fcg) ;; Evaluate the following: (progn (activate-monitor trace-fcg) (setf *constructions* (make-default-cxn-set))) ;;;;; #################################################################### ;;;;; 1. Why feature matrices? ;;;;; #################################################################### ;;;;; ;;;;; There is abundant ambiguity in human language. For example, the ;;;;; paradigm of German definite articles looks as follows (ignoring the ;;;;; genitive): ;;;;; ;;;;; SG-M | SG-N | SG-F | PL ;;;;; ------------------------------------------ ;;;;; NOM: der | das | die | die ;;;;; ACC: den | das | die | die ;;;;; DAT: dem | dem | der | den ;;;;; ;;;;; Examples: "der Mann" (the man), "die Frau" (the woman), ;;;;; "das Tier" (the animal), and so on. ;;;;; ;;;;; Note: SG = Singular, PL = Plural ;;;;; M = masculine, N = neuter, F = feminine ;;;;; NOM = nominative, ACC = accusative, DAT = dative ;;;;; ;;;;; First attempt at modeling German case agreement: DISJUNCTIONS ;;;;; ------------------------------------------------------------- (def-lex-cxn definite-article (def-lex-skeleton definite-article :meaning (== (select-referent ?referent)) :args (?referent)) (def-lex-cat definite-article :sem-cat ((sem-function selector)) :syn-cat (==1 (lex-id der) (lex-class article) ;; We will make our uncertainty explicit by using ;; the feature "potential-case": (potential-case ?case)))) (def-morphs-for definite-article (def-morph der-morph :string "der" ;; List all possibilities (~ disjunctions) :syn-cat (==1 (potential-case (nom-sg-m dat-sg-f)))) (def-morph das-morph :string "das" :syn-cat (==1 (potential-case (nom-sg-n acc-sg-n)))) (def-morph die-morph :string "die" :syn-cat (==1 (potential-case (nom-sg-f nom-pl acc-sg-f acc-pl)))) (def-morph den-morph :string "den" :syn-cat (==1 (case (acc-sg-m)))) (def-morph dem-morph :string "dem" :syn-cat (==1 (case (dat-sg-m dat-sg-n))))) ;; A small lexicon: (def-lex-cxn drawing-lex ;; A singular-feminine word. (def-lex-skeleton drawing-lex :meaning (== (drawing ?x)) :args (?x) :string "Zeichnung") (def-lex-cat drawing-lex :sem-cat ((sem-function identifier)) :syn-cat (==1 (lex-id zeichnung) (lex-class noun) (potential-case (nom-sg-f acc-sg-f dat-sg-f))))) (def-lex-cxn children-lex ;; Nominative or accusative plural. (def-lex-skeleton children-lex :meaning (== (children ?x)) :args (?x) :string "Kinder") (def-lex-cat children-lex :sem-cat ((sem-function identifier)) :syn-cat (==1 (lex-id kind) (lex-class noun) (potential-case (nom-pl acc-pl))))) (def-lex-cxn female-teacher-lex ;; Singular-feminine word. (def-lex-skeleton female-teacher-lex :meaning (== (female-teacher ?x)) :args (?x) :string "Lehrerin") (def-lex-cat female-teacher-lex :sem-cat ((sem-function identifier)) :syn-cat (==1 (lex-id lehrerin) (lex-class noun) ;; Potential-case: (potential-case (nom-sg-f acc-sg-f dat-sg-f))))) (def-lex-cxn gaben-lex ;; Simplified verb form. (def-lex-skeleton gaben-lex :meaning (== (give ?event) (giver ?event ?giver) (gift ?event ?gift) (receiver ?event ?receiver)) :args (?event) :string "gaben") (def-lex-cat gaben-lex :sem-cat ((sem-function predicator)) :syn-cat (==1 (lex-class verb) (lex-id geben))) (def-lex-valence gaben-lex :sem-valence (==1 (actor ?event ?giver) (undergoer ?event ?gift) (recipient ?event ?receiver)) ;; German verb impose case restrictions on their arguments: :syn-valence (==1 (subject ?subject ;; We assume only one option for the subject: (case (nom-pl))) ;; For SV-agreement (direct-object ?direct-object (potential-case (acc-sg-m acc-sg-f acc-sg-n acc-pl))) (indirect-object ?indirect-object (potential-case (dat-sg-m dat-sg-f dat-sg-n dat-pl)))))) ;; Phrasal construction: (def-phrasal-cxn determined-noun-cxn (def-phrasal-skeleton determined-noun-cxn :phrase (?np :form (== (meets ?determiner ?noun)) :sem-cat (==1 (sem-function referring-expression)) :syn-cat (==1 (phrase-type np))) :constituents ((?determiner :sem-cat (==1 (sem-function selector)) :syn-cat (==1 (lex-class article))) (?noun :sem-cat (==1 (sem-function identifier)) :syn-cat (==1 (lex-class noun)))) :head ?noun) (def-phrasal-linking determined-noun-cxn (?np :args (?referent)) (?determiner :args (?referent)) (?noun :args (?referent))) (def-phrasal-agreement determined-noun-cxn ;; We impose case agreement on the determiner and noun: (:units (?np) ;; The NP is only allowed a single value: :syn-cat (==1 (case ?case))) (:units (?determiner ?noun) :syn-cat (==1 (potential-case (==1 ?case)))))) (parse '("die" "Kinder" "gaben" "der" "Frau" "die" "Zeichnung") *constructions*) ;; Ditransitive construction: (def-construction ditransitive-cxn (:label cxn) ((?verb (footprints (==0 arg-cxn)) (args (?event)) (sem-valence (==1 (actor ?event ?actor) (undergoer ?event ?undergoer) (recipient ?event ?recipient)))) (?subject (args (?actor)) (sem-cat (==1 (sem-function referring-expression)))) (?direct-object (args (?undergoer)) (sem-cat (==1 (sem-function referring-expression)))) (?indirect-object (args (?recipient)) (sem-cat (==1 (sem-function referring-expression)))) ((J ?verb) (footprints (==1 arg-cxn))) ((J ?ditransitive-clause) (sem-subunits (?verb ?subject ?direct-object ?indirect-object)))) <--> ((?verb (syn-valence (==1 (subject ?subject (case (==1 ?nominative))) (direct-object ?direct-object (potential-case (==1 ?accusative))) (indirect-object ?indirect-object (potential-case (==1 ?dative))))) (footprints (==0 arg-cxn))) (?subject (syn-cat (==1 (phrase-type np) (case ?nominative)))) (?direct-object (syn-cat (==1 (phrase-type np) (case ?accusative)))) (?indirect-object (syn-cat (==1 (phrase-type np) (case ?dative)))) ((J ?verb) (footprints (==1 arg-cxn))) ((J ?ditransitive-clause) (syn-subunits (?verb ?subject ?direct-object ?indirect-object))))) ;; Testing: ;; ------------------------------------------------------------------------------------- (defmethod cip-goal-test ((node cip-node) (mode (eql :arg-applied))) (let* ((pole (right-pole-structure (car-resulting-cfs (cipn-car node)))) (arg-match (match-structures '((?unit (footprints (== arg-cxn)))) pole))) (set-data (goal-test-data node) 'arg-match arg-match) (if arg-match t nil))) (set-configuration *constructions* :parse-goal-tests '(:arg-applied)) ;; Parse the following: ;; -------------------------------------------------------------------------------------------- (parse '("die" "Kinder" "gaben" "der" "Lehrerin" "die" "Zeichnung") *constructions*) (parse-all '("die" "Kinder" "gaben" "der" "Lehrerin" "die" "Zeichnung") *constructions*) ;; Is there a problem in terms of search? Why? ;;;;; #################################################################### ;;;;; 2. What is the philosophy behind feature matrices? ;;;;; #################################################################### ;;;;; Often, values of features are a COMPLEX ARRAYS. In these cases, using atomic values is ;;;;; potentially dangerous in terms of processing effort / search space. By using a more elaborate ;;;;; value (which represents the whole paradigm), decisions can be postponed until sufficient ;;;;; information is available. ;;;;; ;;;;; (a) Defining the paradigm as a background reference: (define-paradigm *german-case* :dimensions ((nom acc dat gen) (s-m s-f s-n pl))) (describe *german-case*) ;;;;; (b) Now the function #'fcg-make-matrix can be used for instantiating ;;;;; the paradigm. (defun define-article (name &key string dimensions paradigm) (let ((unit-name (make-symbol (format nil "?~a-word" name))) (matrix (fcg-make-matrix dimensions paradigm))) (add-cxn (make-instance 'scored-construction :name name :attributes '((:label . morph)) :domain 'syn :left-pole `((,unit-name (footprints (==0 morph)) (syn-cat (==1 (lex-id der) (lex-class article) (case ,matrix)))) ((J ,unit-name) (footprints (==1 morph)))) :right-pole `((root (tag ?the-form (form (== (string ,unit-name ,string))))) ((J ,unit-name) ?the-form))) *constructions*))) (define-article 'der-morph :string "der" :dimensions '(nom-s-m dat-s-f) :paradigm *german-case*) (define-article 'die-morph :string "die" :dimensions '(nom-s-f nom-pl acc-s-f acc-pl) :paradigm *german-case*) (define-article 'das-morph :string "das" :dimensions '(nom-s-n acc-s-n) :paradigm *german-case*) (define-article 'den-morph :string "den" :dimensions '(acc-s-m dat-pl) :paradigm *german-case*) (define-article 'dem-morph :string "dem" :dimensions '(dat-s-m dat-s-n) :paradigm *german-case*) ;;;;; (c) For lexical constructions, we can use the template def-lex-feature-matrix. ;; A small lexicon: (def-lex-cxn drawing-lex ;; A singular-feminine word. (def-lex-skeleton drawing-lex :meaning (== (drawing ?x)) :args (?x) :string "Zeichnung") (def-lex-cat drawing-lex :sem-cat ((sem-function identifier)) :syn-cat (==1 (lex-id zeichnung) (lex-class noun))) (def-lex-feature-matrix drawing-lex :feature (:syn-cat :case) :dimensions (s-f) :paradigm *german-case*)) (def-lex-cxn children-lex ;; Nominative or accusative plural. (def-lex-skeleton children-lex :meaning (== (children ?x)) :args (?x) :string "Kinder") (def-lex-cat children-lex :sem-cat ((sem-function identifier)) :syn-cat (==1 (lex-id kind) (lex-class noun))) (def-lex-feature-matrix children-lex :feature (:syn-cat :case) :dimensions (pl) :paradigm *german-case*)) (def-lex-cxn female-teacher-lex ;; Singular-feminine word. (def-lex-skeleton female-teacher-lex :meaning (== (female-teacher ?x)) :args (?x) :string "Lehrerin") (def-lex-cat female-teacher-lex :sem-cat ((sem-function identifier)) :syn-cat (==1 (lex-id lehrerin) (lex-class noun))) (def-lex-feature-matrix female-teacher-lex :feature (:syn-cat :case) :dimensions (s-f) :paradigm *german-case*)) ;;;;;; (d) We adapt the determined-noun-cxn: (def-phrasal-cxn determined-noun-cxn (def-phrasal-skeleton determined-noun-cxn :phrase (?np :form (== (meets ?determiner ?noun)) :sem-cat (==1 (sem-function referring-expression)) :syn-cat (==1 (phrase-type np))) :constituents ((?determiner :sem-cat (==1 (sem-function selector)) :syn-cat (==1 (lex-class article))) (?noun :sem-cat (==1 (sem-function identifier)) :syn-cat (==1 (lex-class noun)))) :head ?noun) (def-phrasal-linking determined-noun-cxn (?np :args (?referent)) (?determiner :args (?referent)) (?noun :args (?referent))) (def-phrasal-agreement determined-noun-cxn :units (?np ?determiner ?noun) :syn-cat (==1 (case ?case)))) ;; Evaluate the following: ;; -------------------------------------------------------------------------------------------- (set-configuration *constructions* :parse-goal-tests '(:no-applicable-cxns)) ;; Parse the following: ;; -------------------------------------------------------------------------------------------- (parse '("die" "Kinder" "gaben" "der" "Lehrerin" "die" "Zeichnung") *constructions*) ;; Has the search problem been solved? ;;;;; #################################################################### ;;;;; 3. Using the expand-operator. ;;;;; #################################################################### ;;;;; From now on, we can just write the possibilities in a construction, ;;;;; and ask the ++-operator to expand these possibilities into an actual ;;;;; feature matrix. (defmethod fcg-expand ((type (eql :case)) &key value source bindings merge?) (declare (ignore source bindings merge?)) (fcg-make-matrix value *german-case*)) ;; Note: within fcg-expand, you can always retrieve the full transient structure ;; at that time using the following function call: (get-self) ;;;;; Modifying the verb: (def-lex-cxn gaben-lex ;; Simplified verb form. (def-lex-skeleton gaben-lex :meaning (== (give ?event) (giver ?event ?giver) (gift ?event ?gift) (receiver ?event ?receiver)) :args (?event) :string "gaben") (def-lex-cat gaben-lex :sem-cat ((sem-function predicator)) :syn-cat (==1 (lex-class verb) (lex-id geben))) (def-lex-valence gaben-lex :sem-valence (==1 (actor ?event ?giver) (undergoer ?event ?gift) (recipient ?event ?receiver)) :syn-valence (==1 (subject ?subject (case (++ :case (nom-pl)))) (direct-object ?direct-object) (indirect-object ?indirect-object)))) ;;;;; Modifying the argument structure construction: (def-construction ditransitive-cxn (:label cxn) ((?verb (footprints (==0 arg-cxn)) (args (==1 (event-type ?event-type) (referent ?event))) (sem-valence (==1 (actor ?event ?actor) (undergoer ?event ?undergoer) (recipient ?event ?recipient)))) (?subject (args (==1 (referent ?actor))) (sem-cat (==1 (sem-function referring-expression)))) (?direct-object (args (==1 (referent ?undergoer))) (sem-cat (==1 (sem-function referring-expression)))) (?indirect-object (args (==1 (referent ?recipient))) (sem-cat (==1 (sem-function referring-expression)))) ((J ?verb) (footprints (==1 arg-cxn))) ((J ?ditransitive-clause) (sem-subunits (?subject ?verb ?direct-object ?indirect-object)))) <--> ((?verb (syn-valence (==1 (subject ?subject (case ?case-agreement)) (direct-object ?direct-object) (indirect-object ?indirect-object))) (footprints (==0 arg-cxn))) (?subject (syn-cat (==1 (phrase-type np) (case ?case-agreement)))) (?direct-object (syn-cat (==1 (phrase-type np) (case (++ :case (acc)))))) (?indirect-object (syn-cat (==1 (phrase-type np) (case (++ :case (dat)))))) ((J ?verb) (footprints (==1 arg-cxn))) ((J ?ditransitive-clause) (syn-subunits (?subject ?verb ?direct-object ?indirect-object))))) ;; We try again: ;; -------------------------------------------------------------------------------------------- (parse '("die" "Kinder" "gaben" "der" "Lehrerin" "die" "Zeichnung") *constructions*) (parse-all '("die" "Kinder" "gaben" "der" "Lehrerin" "die" "Zeichnung") *constructions*)