Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

# Natural Language Toolkit: Cooper storage for Quantifier Ambiguity 

# 

# Copyright (C) 2001-2012 NLTK Project 

# Author: Ewan Klein <ewan@inf.ed.ac.uk> 

# URL: <http://www.nltk.org/> 

# For license information, see LICENSE.TXT 

from __future__ import print_function 

 

from .logic import LambdaExpression, ApplicationExpression, Variable, LogicParser 

from nltk.parse import load_parser 

from nltk.parse.featurechart import InstantiateVarsChart 

 

class CooperStore(object): 

    """ 

    A container for handling quantifier ambiguity via Cooper storage. 

    """ 

    def __init__(self, featstruct): 

        """ 

        :param featstruct: The value of the ``sem`` node in a tree from 

            ``parse_with_bindops()`` 

        :type featstruct: FeatStruct (with features ``core`` and ``store``) 

 

        """ 

        self.featstruct = featstruct 

        self.readings = [] 

        try: 

            self.core = featstruct['CORE'] 

            self.store = featstruct['STORE'] 

        except KeyError: 

            print("%s is not a Cooper storage structure" % featstruct) 

 

    def _permute(self, lst): 

        """ 

        :return: An iterator over the permutations of the input list 

        :type lst: list 

        :rtype: iter 

        """ 

        remove = lambda lst0, index: lst0[:index] + lst0[index+1:] 

        if lst: 

            for index, x in enumerate(lst): 

                for y in self._permute(remove(lst, index)): 

                    yield (x,)+y 

        else: yield () 

 

    def s_retrieve(self, trace=False): 

        """ 

        Carry out S-Retrieval of binding operators in store. If hack=True, 

        serialize the bindop and core as strings and reparse. Ugh. 

 

        Each permutation of the store (i.e. list of binding operators) is 

        taken to be a possible scoping of quantifiers. We iterate through the 

        binding operators in each permutation, and successively apply them to 

        the current term, starting with the core semantic representation, 

        working from the inside out. 

 

        Binding operators are of the form:: 

 

             bo(\P.all x.(man(x) -> P(x)),z1) 

        """ 

        for perm, store_perm in enumerate(self._permute(self.store)): 

            if trace: 

                print("Permutation %s" % (perm+1)) 

            term = self.core 

            for bindop in store_perm: 

                # we just want the arguments that are wrapped by the 'bo' predicate 

                quant, varex = tuple(bindop.args) 

                # use var to make an abstraction over the current term and then 

                # apply the quantifier to it 

                term = ApplicationExpression(quant, LambdaExpression(varex.variable, term)) 

                if trace: 

                    print("  ", term) 

                term = term.simplify() 

            self.readings.append(term) 

 

 

def parse_with_bindops(sentence, grammar=None, trace=0): 

    """ 

    Use a grammar with Binding Operators to parse a sentence. 

    """ 

    if not grammar: 

        grammar = 'grammars/book_grammars/storage.fcfg' 

    parser = load_parser(grammar, trace=trace, chart_class=InstantiateVarsChart) 

    # Parse the sentence. 

    tokens = sentence.split() 

    return parser.nbest_parse(tokens) 

 

 

def demo(): 

    from nltk.sem import cooper_storage as cs 

    sentence = "every girl chases a dog" 

    #sentence = "a man gives a bone to every dog" 

    print() 

    print("Analyis of sentence '%s'" % sentence) 

    print("=" * 50) 

    trees = cs.parse_with_bindops(sentence, trace=0) 

    for tree in trees: 

        semrep = cs.CooperStore(tree.node['SEM']) 

        print() 

        print("Binding operators:") 

        print("-" * 15) 

        for s in semrep.store: 

            print(s) 

        print() 

        print("Core:") 

        print("-" * 15) 

        print(semrep.core) 

        print() 

        print("S-Retrieval:") 

        print("-" * 15) 

        semrep.s_retrieve(trace=True) 

        print("Readings:") 

        print("-" * 15) 

 

        for i, reading in enumerate(semrep.readings): 

            print("%s: %s" % (i+1, reading)) 

 

if __name__ == '__main__': 

    demo()