Sample usage for ccg_semantics

Combinatory Categorial Grammar with semantics

Chart

>>> from nltk.ccg import chart, lexicon
>>> from nltk.ccg.chart import printCCGDerivation

No semantics

>>> lex = lexicon.fromstring('''
...     :- S, NP, N
...     She => NP
...     has => (S\\NP)/NP
...     books => NP
...     ''',
...     False)
>>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
>>> parses = list(parser.parse("She has books".split()))
>>> print(str(len(parses)) + " parses")
3 parses
>>> printCCGDerivation(parses[0])
 She      has      books
 NP   ((S\NP)/NP)   NP
     -------------------->
            (S\NP)
-------------------------<
            S
>>> printCCGDerivation(parses[1])
 She      has      books
 NP   ((S\NP)/NP)   NP
----->T
(S/(S\NP))
     -------------------->
            (S\NP)
------------------------->
            S
>>> printCCGDerivation(parses[2])
 She      has      books
 NP   ((S\NP)/NP)   NP
----->T
(S/(S\NP))
------------------>B
      (S/NP)
------------------------->
            S

Simple semantics

>>> lex = lexicon.fromstring('''
...     :- S, NP, N
...     She => NP {she}
...     has => (S\\NP)/NP {\\x y.have(y, x)}
...     a => NP/N {\\P.exists z.P(z)}
...     book => N {book}
...     ''',
...     True)
>>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
>>> parses = list(parser.parse("She has a book".split()))
>>> print(str(len(parses)) + " parses")
7 parses
>>> printCCGDerivation(parses[0])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
                                        ------------------------------------->
                                                NP {exists z.book(z)}
          ------------------------------------------------------------------->
                         (S\NP) {\y.have(y,exists z.book(z))}
-----------------------------------------------------------------------------<
                       S {have(she,exists z.book(z))}
>>> printCCGDerivation(parses[1])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
          --------------------------------------------------------->B
                   ((S\NP)/N) {\P y.have(y,exists z.P(z))}
          ------------------------------------------------------------------->
                         (S\NP) {\y.have(y,exists z.book(z))}
-----------------------------------------------------------------------------<
                       S {have(she,exists z.book(z))}
>>> printCCGDerivation(parses[2])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
---------->T
(S/(S\NP)) {\F.F(she)}
                                        ------------------------------------->
                                                NP {exists z.book(z)}
          ------------------------------------------------------------------->
                         (S\NP) {\y.have(y,exists z.book(z))}
----------------------------------------------------------------------------->
                       S {have(she,exists z.book(z))}
>>> printCCGDerivation(parses[3])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
---------->T
(S/(S\NP)) {\F.F(she)}
          --------------------------------------------------------->B
                   ((S\NP)/N) {\P y.have(y,exists z.P(z))}
          ------------------------------------------------------------------->
                         (S\NP) {\y.have(y,exists z.book(z))}
----------------------------------------------------------------------------->
                       S {have(she,exists z.book(z))}
>>> printCCGDerivation(parses[4])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
---------->T
(S/(S\NP)) {\F.F(she)}
---------------------------------------->B
        (S/NP) {\x.have(she,x)}
                                        ------------------------------------->
                                                NP {exists z.book(z)}
----------------------------------------------------------------------------->
                       S {have(she,exists z.book(z))}
>>> printCCGDerivation(parses[5])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
---------->T
(S/(S\NP)) {\F.F(she)}
          --------------------------------------------------------->B
                   ((S\NP)/N) {\P y.have(y,exists z.P(z))}
------------------------------------------------------------------->B
                (S/N) {\P.have(she,exists z.P(z))}
----------------------------------------------------------------------------->
                       S {have(she,exists z.book(z))}
>>> printCCGDerivation(parses[6])
   She                 has                           a                book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (NP/N) {\P.exists z.P(z)}  N {book}
---------->T
(S/(S\NP)) {\F.F(she)}
---------------------------------------->B
        (S/NP) {\x.have(she,x)}
------------------------------------------------------------------->B
                (S/N) {\P.have(she,exists z.P(z))}
----------------------------------------------------------------------------->
                       S {have(she,exists z.book(z))}

Complex semantics

>>> lex = lexicon.fromstring('''
...     :- S, NP, N
...     She => NP {she}
...     has => (S\\NP)/NP {\\x y.have(y, x)}
...     a => ((S\\NP)\\((S\\NP)/NP))/N {\\P R x.(exists z.P(z) & R(z,x))}
...     book => N {book}
...     ''',
...     True)
>>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
>>> parses = list(parser.parse("She has a book".split()))
>>> print(str(len(parses)) + " parses")
2 parses
>>> printCCGDerivation(parses[0])
   She                 has                                           a                                 book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (((S\NP)\((S\NP)/NP))/N) {\P R x.(exists z.P(z) & R(z,x))}  N {book}
                                        ---------------------------------------------------------------------->
                                               ((S\NP)\((S\NP)/NP)) {\R x.(exists z.book(z) & R(z,x))}
          ----------------------------------------------------------------------------------------------------<
                                       (S\NP) {\x.(exists z.book(z) & have(x,z))}
--------------------------------------------------------------------------------------------------------------<
                                     S {(exists z.book(z) & have(she,z))}
>>> printCCGDerivation(parses[1])
   She                 has                                           a                                 book
 NP {she}  ((S\NP)/NP) {\x y.have(y,x)}  (((S\NP)\((S\NP)/NP))/N) {\P R x.(exists z.P(z) & R(z,x))}  N {book}
---------->T
(S/(S\NP)) {\F.F(she)}
                                        ---------------------------------------------------------------------->
                                               ((S\NP)\((S\NP)/NP)) {\R x.(exists z.book(z) & R(z,x))}
          ----------------------------------------------------------------------------------------------------<
                                       (S\NP) {\x.(exists z.book(z) & have(x,z))}
-------------------------------------------------------------------------------------------------------------->
                                     S {(exists z.book(z) & have(she,z))}

Using conjunctions

# TODO: The semantics of “and” should have been more flexible >>> lex = lexicon.fromstring(‘’’ … :- S, NP, N … I => NP {I} … cook => (S\NP)/NP {\x y.cook(x,y)} … and => var\.,var/.,var {\P Q x y.(P(x,y) & Q(x,y))} … eat => (S\NP)/NP {\x y.eat(x,y)} … the => NP/N {\x.the(x)} … bacon => N {bacon} … ‘’’, … True)

>>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
>>> parses = list(parser.parse("I cook and eat the bacon".split()))
>>> print(str(len(parses)) + " parses")
7 parses
>>> printCCGDerivation(parses[0])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
                                                                                                                           ------------------------------->
                                                                                                                                   NP {the(bacon)}
        -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
----------------------------------------------------------------------------------------------------------------------------------------------------------<
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}
>>> printCCGDerivation(parses[1])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
        --------------------------------------------------------------------------------------------------------------------------------------->B
                                                  ((S\NP)/N) {\x y.(eat(the(x),y) & cook(the(x),y))}
        -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
----------------------------------------------------------------------------------------------------------------------------------------------------------<
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}
>>> printCCGDerivation(parses[2])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
-------->T
(S/(S\NP)) {\F.F(I)}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
                                                                                                                           ------------------------------->
                                                                                                                                   NP {the(bacon)}
        -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}
>>> printCCGDerivation(parses[3])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
-------->T
(S/(S\NP)) {\F.F(I)}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
        --------------------------------------------------------------------------------------------------------------------------------------->B
                                                  ((S\NP)/N) {\x y.(eat(the(x),y) & cook(the(x),y))}
        -------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       (S\NP) {\y.(eat(the(bacon),y) & cook(the(bacon),y))}
---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}
>>> printCCGDerivation(parses[4])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
-------->T
(S/(S\NP)) {\F.F(I)}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
--------------------------------------------------------------------------------------------------------------------------->B
                                            (S/NP) {\x.(eat(x,I) & cook(x,I))}
                                                                                                                           ------------------------------->
                                                                                                                                   NP {the(bacon)}
---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}
>>> printCCGDerivation(parses[5])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
-------->T
(S/(S\NP)) {\F.F(I)}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
        --------------------------------------------------------------------------------------------------------------------------------------->B
                                                  ((S\NP)/N) {\x y.(eat(the(x),y) & cook(the(x),y))}
----------------------------------------------------------------------------------------------------------------------------------------------->B
                                                  (S/N) {\x.(eat(the(x),I) & cook(the(x),I))}
---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}
>>> printCCGDerivation(parses[6])
   I                 cook                                       and                                        eat                     the            bacon
 NP {I}  ((S\NP)/NP) {\x y.cook(x,y)}  ((_var0\.,_var0)/.,_var0) {\P Q x y.(P(x,y) & Q(x,y))}  ((S\NP)/NP) {\x y.eat(x,y)}  (NP/N) {\x.the(x)}  N {bacon}
-------->T
(S/(S\NP)) {\F.F(I)}
                                      ------------------------------------------------------------------------------------->
                                                    (((S\NP)/NP)\.,((S\NP)/NP)) {\Q x y.(eat(x,y) & Q(x,y))}
        -------------------------------------------------------------------------------------------------------------------<
                                             ((S\NP)/NP) {\x y.(eat(x,y) & cook(x,y))}
--------------------------------------------------------------------------------------------------------------------------->B
                                            (S/NP) {\x.(eat(x,I) & cook(x,I))}
----------------------------------------------------------------------------------------------------------------------------------------------->B
                                                  (S/N) {\x.(eat(the(x),I) & cook(the(x),I))}
---------------------------------------------------------------------------------------------------------------------------------------------------------->
                                                       S {(eat(the(bacon),I) & cook(the(bacon),I))}

Tests from published papers

An example from “CCGbank: A Corpus of CCG Derivations and Dependency Structures Extracted from the Penn Treebank”, Hockenmaier and Steedman, 2007, Page 359, https://www.aclweb.org/anthology/J/J07/J07-3004.pdf

>>> lex = lexicon.fromstring('''
...     :- S, NP
...     I => NP {I}
...     give => ((S\\NP)/NP)/NP {\\x y z.give(y,x,z)}
...     them => NP {them}
...     money => NP {money}
...     ''',
...     True)
>>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
>>> parses = list(parser.parse("I give them money".split()))
>>> print(str(len(parses)) + " parses")
3 parses
>>> printCCGDerivation(parses[0])
   I                     give                     them       money
 NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}  NP {money}
        -------------------------------------------------->
                ((S\NP)/NP) {\y z.give(y,them,z)}
        -------------------------------------------------------------->
                        (S\NP) {\z.give(money,them,z)}
----------------------------------------------------------------------<
                        S {give(money,them,I)}
>>> printCCGDerivation(parses[1])
   I                     give                     them       money
 NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}  NP {money}
-------->T
(S/(S\NP)) {\F.F(I)}
        -------------------------------------------------->
                ((S\NP)/NP) {\y z.give(y,them,z)}
        -------------------------------------------------------------->
                        (S\NP) {\z.give(money,them,z)}
---------------------------------------------------------------------->
                        S {give(money,them,I)}
>>> printCCGDerivation(parses[2])
   I                     give                     them       money
 NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}  NP {money}
-------->T
(S/(S\NP)) {\F.F(I)}
        -------------------------------------------------->
                ((S\NP)/NP) {\y z.give(y,them,z)}
---------------------------------------------------------->B
                (S/NP) {\y.give(y,them,I)}
---------------------------------------------------------------------->
                        S {give(money,them,I)}

An example from “CCGbank: A Corpus of CCG Derivations and Dependency Structures Extracted from the Penn Treebank”, Hockenmaier and Steedman, 2007, Page 359, https://www.aclweb.org/anthology/J/J07/J07-3004.pdf

>>> lex = lexicon.fromstring('''
...     :- N, NP, S
...     money => N {money}
...     that => (N\\N)/(S/NP) {\\P Q x.(P(x) & Q(x))}
...     I => NP {I}
...     give => ((S\\NP)/NP)/NP {\\x y z.give(y,x,z)}
...     them => NP {them}
...     ''',
...     True)
>>> parser = chart.CCGChartParser(lex, chart.DefaultRuleSet)
>>> parses = list(parser.parse("money that I give them".split()))
>>> print(str(len(parses)) + " parses")
3 parses
>>> printCCGDerivation(parses[0])
   money                    that                     I                     give                     them
 N {money}  ((N\N)/(S/NP)) {\P Q x.(P(x) & Q(x))}  NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}
                                                  -------->T
                                            (S/(S\NP)) {\F.F(I)}
                                                          -------------------------------------------------->
                                                                  ((S\NP)/NP) {\y z.give(y,them,z)}
                                                  ---------------------------------------------------------->B
                                                                  (S/NP) {\y.give(y,them,I)}
           ------------------------------------------------------------------------------------------------->
                                         (N\N) {\Q x.(give(x,them,I) & Q(x))}
------------------------------------------------------------------------------------------------------------<
                                     N {\x.(give(x,them,I) & money(x))}
>>> printCCGDerivation(parses[1])
   money                    that                     I                     give                     them
 N {money}  ((N\N)/(S/NP)) {\P Q x.(P(x) & Q(x))}  NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}
----------->T
(N/(N\N)) {\F.F(money)}
                                                  -------->T
                                            (S/(S\NP)) {\F.F(I)}
                                                          -------------------------------------------------->
                                                                  ((S\NP)/NP) {\y z.give(y,them,z)}
                                                  ---------------------------------------------------------->B
                                                                  (S/NP) {\y.give(y,them,I)}
           ------------------------------------------------------------------------------------------------->
                                         (N\N) {\Q x.(give(x,them,I) & Q(x))}
------------------------------------------------------------------------------------------------------------>
                                     N {\x.(give(x,them,I) & money(x))}
>>> printCCGDerivation(parses[2])
   money                    that                     I                     give                     them
 N {money}  ((N\N)/(S/NP)) {\P Q x.(P(x) & Q(x))}  NP {I}  (((S\NP)/NP)/NP) {\x y z.give(y,x,z)}  NP {them}
----------->T
(N/(N\N)) {\F.F(money)}
-------------------------------------------------->B
       (N/(S/NP)) {\P x.(P(x) & money(x))}
                                                  -------->T
                                            (S/(S\NP)) {\F.F(I)}
                                                          -------------------------------------------------->
                                                                  ((S\NP)/NP) {\y z.give(y,them,z)}
                                                  ---------------------------------------------------------->B
                                                                  (S/NP) {\y.give(y,them,I)}
------------------------------------------------------------------------------------------------------------>
                                     N {\x.(give(x,them,I) & money(x))}

Lexicon

>>> from nltk.ccg import lexicon

Parse lexicon with semantics

>>> print(str(lexicon.fromstring(
...     '''
...     :- S,NP
...
...     IntransVsg :: S\\NP[sg]
...
...     sleeps => IntransVsg {\\x.sleep(x)}
...     eats => S\\NP[sg]/NP {\\x y.eat(x,y)}
...
...     and => var\\var/var {\\x y.x & y}
...     ''',
...     True
... )))
and => ((_var0\_var0)/_var0) {(\x y.x & y)}
eats => ((S\NP['sg'])/NP) {\x y.eat(x,y)}
sleeps => (S\NP['sg']) {\x.sleep(x)}

Parse lexicon without semantics

>>> print(str(lexicon.fromstring(
...     '''
...     :- S,NP
...
...     IntransVsg :: S\\NP[sg]
...
...     sleeps => IntransVsg
...     eats => S\\NP[sg]/NP {sem=\\x y.eat(x,y)}
...
...     and => var\\var/var
...     ''',
...     False
... )))
and => ((_var0\_var0)/_var0)
eats => ((S\NP['sg'])/NP)
sleeps => (S\NP['sg'])

Semantics are missing

>>> print(str(lexicon.fromstring(
...     '''
...     :- S,NP
...
...     eats => S\\NP[sg]/NP
...     ''',
...     True
... )))
Traceback (most recent call last):
  ...
AssertionError: eats => S\NP[sg]/NP must contain semantics because include_semantics is set to True

CCG combinator semantics computation

>>> from nltk.sem.logic import *
>>> from nltk.ccg.logic import *
>>> read_expr = Expression.fromstring

Compute semantics from function application

>>> print(str(compute_function_semantics(read_expr(r'\x.P(x)'), read_expr(r'book'))))
P(book)
>>> print(str(compute_function_semantics(read_expr(r'\P.P(book)'), read_expr(r'read'))))
read(book)
>>> print(str(compute_function_semantics(read_expr(r'\P.P(book)'), read_expr(r'\x.read(x)'))))
read(book)

Compute semantics from composition

>>> print(str(compute_composition_semantics(read_expr(r'\x.P(x)'), read_expr(r'\x.Q(x)'))))
\x.P(Q(x))
>>> print(str(compute_composition_semantics(read_expr(r'\x.P(x)'), read_expr(r'read'))))
Traceback (most recent call last):
  ...
AssertionError: `read` must be a lambda expression

Compute semantics from substitution

>>> print(str(compute_substitution_semantics(read_expr(r'\x y.P(x,y)'), read_expr(r'\x.Q(x)'))))
\x.P(x,Q(x))
>>> print(str(compute_substitution_semantics(read_expr(r'\x.P(x)'), read_expr(r'read'))))
Traceback (most recent call last):
  ...
AssertionError: `\x.P(x)` must be a lambda expression with 2 arguments

Compute type-raise semantics

>>> print(str(compute_type_raised_semantics(read_expr(r'\x.P(x)'))))
\F x.F(P(x))
>>> print(str(compute_type_raised_semantics(read_expr(r'\x.F(x)'))))
\F1 x.F1(F(x))
>>> print(str(compute_type_raised_semantics(read_expr(r'\x y z.P(x,y,z)'))))
\F x y z.F(P(x,y,z))