【问题标题】:CYK algorithm implementationCYK算法实现
【发布时间】:2023-04-11 08:36:01
【问题描述】:

我正在尝试实现wikipedia 提供的CYK 伪代码。 我输入的例句应该输出真,但输出假。考虑到提供的示例从 1 开始,我认为我在索引方面遇到了问题。

代码:

def is_in_language(self, tokens):
    n = len(tokens)
    rules = self.grammar.lhs_to_rules
    table = defaultdict(lambda: defaultdict(dict))
    #Initialize dictionary table[row][column][nonterminal r] = boolean
    for row in range(n+1):
        for col in range(n+1):
            for r in rules:
                table[row][col][r] = False

    for i in range(n):
        nonTerminalList = self.grammar.rhs_to_rules[(tokens[i],)]
        print(nonTerminalList)
        for nonTerminal in nonTerminalList:
            (r,right,prob) = nonTerminal
            table[0][i][r] =  True


    for l in range(2,n+1):
        for s in range(n-l+1):
            for p in range(l-1+1):
                for B in rules:
                    for C in rules:
                        AList = self.grammar.rhs_to_rules[B,C]
                        if(len(AList) > 0):
                            for A in AList:
                                (leftA, rightBC, prob) = A


                                try:
                                    if(table[p][s][B] and table[l-p][s+p][C]):
                                        table[l][s][leftA] = True
                                except:
                                    pass

    print(table[n][0][self.grammar.startsymbol])
    return table

【问题讨论】:

    标签: python algorithm nlp compiler-construction cyk


    【解决方案1】:

    python 中的以下代码实现了 CYK 动态规划算法(描述为 here),该算法可用于解决 CFG 的隶属问题,即,给定输入字符串 w 和一个chomosky范式(CNF)的CFG文法G,它可以在O(n^3|w|)时间内找出w是否在L(G)中。

    import numpy as np
    import pandas as pd
    
    def is_in_cartesian_prod(x, y, r):
        return r in [i+j for i in x.split(',') for j in y.split(',')]
    
    def accept_CYK(w, G, S):
        if w == 'ε':
            return 'ε' in G[S]
        n = len(w)
        DP_table = [['']*n for _ in range(n)]
        for i in range(n):
            for lhs in G.keys():
                for rhs in G[lhs]:
                     if w[i] == rhs: # rules of the form A -> a
                        DP_table[i][i] = lhs if not DP_table[i][i] else DP_table[i][i] + ',' + lhs
                        
        for l in range(2, n+1):       # span
            for i in range(n-l+1):    # start
                j = i+l-1             # right
                for k in range(i, j): # partition
                    for lhs in G.keys():
                        for rhs in G[lhs]:
                            if len(rhs) == 2: #rules of form A -> BC
                                if is_in_cartesian_prod(DP_table[i][k], DP_table[k+1][j], rhs):
                                    if not lhs in DP_table[i][j]:
                                        DP_table[i][j] = lhs if not DP_table[i][j] else DP_table[i][j] + ',' + lhs
    
        return S in DP_table[0][n-1]  
    

    现在,让我们将上述算法实现用于以下简单的 CFG G(已经在 CNF 中):

    S -> AB |公元前

    A -> BA |一个

    B -> 抄送 | b

    C -> AB |一个

    和输入字符串 w = baaba 来测试 w 在 L(G) 中的成员资格。

    # let's define the grammar productions and symbols first 
    NTs = ['S', 'A', 'B', 'C', 'D']
    Ts = ['a', 'b']
    rules = ['S -> AB | BC', 'A -> BA | a', 'B -> CC | b', 'C -> AB | a'] #, 'D -> ϵ']
    G = get_grammar(rules)
    print(G)
    # {'S': ['AB', 'BC'], 'A': ['BA', 'a'], 'B': ['CC', 'b'], 'C': ['AB', 'a']}
    
    # now check if the string w is a member of G
    accept_CYK('baaba', G, 'S')
    # True
    

    以下动画展示了 DP 表是如何构建的:

    这种带有反向指针的 DP 算法的概率版本可用于 PCFG 为 NLP 中的自然语言句子构建解析树。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-17
      • 2013-04-07
      • 1970-01-01
      • 2013-03-28
      • 2017-07-11
      • 2013-11-29
      • 2016-11-06
      • 2020-05-18
      相关资源
      最近更新 更多