【问题标题】:Extra branches being added to tree when generated生成时将额外的分支添加到树中
【发布时间】:2017-06-07 04:18:01
【问题描述】:

我已经实现了 CYK 解析算法,它使用自下而上的方法来构建解析树。当它遍历算法时,最终解决方案的路径存储在反向指针中。从反向指针,我们构造树。这最后一步是我遇到的问题。

这是我用来存储树的数据结构:

class GrammarTree(object):
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

    def insertLeft(self, new_node):
        self.left = GrammarTree(new_node)

    def insertRight(self, new_node):
        self.right = GrammarTree(new_node)

以下是我如何构建树,其中back 存储一个元组,其中split 是用于拆分树的索引,left_ruleright_rule 是由 int 表示的相应树的规则。如果到达叶节点,则没有元组,只有一个表示终止规则的 int。

def build_tree(start,end,idx,back):
    tree = GrammarTree(idx)
    node = back[start][end][idx]
    if isinstance(node,tuple):
        split,left_rule,right_rule = node
        tree.insertLeft(build_tree(start,split,left_rule,back))
        tree.insertRight(build_tree(split,end,right_rule,back))
        return tree
    else:
        tree.insertLeft(GrammarTree(node))
        return tree 

问题是当函数完成构建树时,会添加额外的分支,即节点没有正确粘合在一起。

这就是它的样子:

Lvl0                                root
                          /                            \
Lvl1                     L1                             R1
                  /       |    \             /           |       \
                 /        |     \           /            |        \
                /         |      \         /             |         \
               /          |       \       /              |          \
              /           |        \     /               |           \
Lvl2  L1.left=None L1.right=None L1.data R1.left=None R1.right=None R1.data
                                  /    \                            /    \
Lvl3                             L2     R2                         L3     R3

两棵树之间不应有data 节点。

编辑:

问题不在于多了一个数据节点(上面的说法不对),是Lvl1之后,Lvl2上的L1.left/rightR1.left/right不是新增分支,而是新增到L1R1'sdata 字段。所以L1/R1.data 最终成为一棵树,而L1.left/rightR1.left/right 没有被使用,因此None

应该是这样的:

                  root
           /               \
          /                 \
   L1=root.left         R1=root.right
     /    \                 /   \
    /      \               /     \
   /        \             /       \
L2=L1.left  R2=L1.right L3=R1.left R3=R1.right

这就是我所说的构建树:

back = [[[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 6, 0, 3, 0, 2], [0, 0, 0, (1, 6, 7), 0, 3, 0, (1, 7, 7)], [0, 0, 0, (1, 6, 7), 0, (1, 7, 3), 0, (1, 7, 7)], [0, 0, 0, (1, 6, 7), 0, (2, 7, 3), 0, (1, 7, 7)]],\ 
        [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 6, 0, 3, 0, 2], [0, 0, 0, (2, 6, 7), 0, (2, 7, 3), 0, (2, 7, 7)], [0, 0, 0, (2, 6, 7), 0, (2, 7, 3), 0, (3, 7, 7)]],\
        [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 6, 0, 3, 0, 2], [0, 0, 0, (3, 6, 7), 0, 3, 0, (3, 7, 7)]],\
        [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 6, 0, 3, 0, 2]],\
        [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]]
build_tree(0,4,5,back)

【问题讨论】:

  • 请阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。我没有看到任何定义为 Data 节点的东西,也没有驱动程序代码引发问题。
  • @Prune 所以我做了一些编辑以反映我遇到的实际问题。至于发布整个代码......它可能太大了,但我相信有足够的抽象我遇到的问题。
  • 您发布了一个 MCVE,而不是您的整个代码。我们大多数人(包括我)不会检查您的代码,也不会抽象地分析它。我们使用我们最喜欢的调试技术来跟踪数据和控制流。
  • @Prune 明白了。我相信代码现在符合 MCVE 规范。我完全按照发布的方式运行了示例。
  • 您的代码现在运行,但没有输出:没有跟踪或显示数据。此外,您假设任何可以帮助解决此问题的人都知道您的 CYK 术语和功能。我很擅长树,但我担心 CYK 会比我在计算语言学方面的研究生工作晚。您尚未将变量名称映射到常见概念;您还没有将输入映射到问题(语法);你还没有跟踪你的输出。 \\\ 是的,可能*有人可以帮助您解决此问题,但您给我们留下了大概半小时的时间来了解问题。

标签: python algorithm recursion tree cyk


【解决方案1】:

问题出在GrammarTree 类的insertLeft()insertRight() 方法中。你会看到我调用了GrammarTree 构造函数,而不是简单地连接分支,所以我实际上是在将一棵树包裹在另一棵树中。

我通过删除对构造函数的调用解决了这个问题。

class GrammarTree(object):
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

    def insertLeft(self, new_node):
        self.left = new_node  ## <- NOT GrammarTree(new_node) 

    def insertRight(self, new_node):
        self.right = new_node ## <- NOT GrammarTree(new_node)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    相关资源
    最近更新 更多