使用pyDatalog解析依赖关系图

时间:2016-03-04 13:46:40

标签: python algorithm logic-programming datalog pydatalog

我正在努力编写更具可读性的声明性程序。所以我决定实现一个我们目前使用的简单算法。程序实施如下:

  1. 有命令和资源
  2. 每个命令都可以提供并需要多个资源
  3. 算法将遍历所有命令并安排提供所有要求的命令。
  4. 现在提供了该命令提供的所有资源
  5. 如果安排了所有命令,我们就完成了
  6. 如果还有命令,我们无法满足依赖关系,我们无法为算法的迭代安排新命令
  7. 所以我想出的数据记录变体看起来不错但有两个问题:

    1. 错误
    2. 我需要一个循环来读取结果
    3. 您可以找到完整的来源here

      这取决于假设,您可以使用pytest轻松运行它。

      在失败的测试之下:如果我们需要先前“排名”或订单提供的资源。它找不到它。我试图使跟随递归,但即使在简单的例子中它也失败了。

      def test_graph_multirequire():
          """Test if the resolver can handle a graph with multiple requires"""
          tree = [
              [('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ('G'), ()],
              [(), ('A'), ('B'), ('C', 'A'), ('D'), ('E'), ('F'), ('G')]
          ]
          run_graph(tree)
      
      
      def run_graph(tree):
          """Run an example"""
          try:
              tree_len = len(tree[0])
              index = list(range(tree_len))
              random.shuffle(index)
              for i in index:
                  + is_command(i)
                  for provide in tree[0][i]:
                      + provides(i, provide)
                  for require in tree[1][i]:
                      + requires(i, require)
              ##############################
              is_root(X) <= is_command(X) & ~requires(X, Y)
              follows(X, Z) <= (
                  provides(X, Y) & requires(Z, Y) & (X != Z)
              )
              order(0, X) <= is_root(X)
              order(N, X) <= (N > 0) & order(N - 1, Y) & follows(Y, X)
              ##############################
              ordered = []
              try:
                  for x in range(tree_len):
                      nodes = order(x, N)
                      if not nodes:
                          break
                      ordered.extend([x[0] for x in nodes])
              except AttributeError:
                  ordered = index
              assert len(ordered) >= tree_len
              print(ordered)
              provided = set()
              for command in ordered:
                  assert set(tree[1][command]).issubset(provided)
                  provided.update(tree[0][command])
          finally:
              pd.clear()
      

      我的问题:

      1. 我使用的是错误的工具吗?
      2. 有人知道综合数据记录怎么样?
      3. 你如何解决上述问题?
      4. 编辑:

        1. 我缺少像all()和exists()这样的量词,我怎样才能在pyDatalog中表达这个?

1 个答案:

答案 0 :(得分:2)

pyDatalog(和prolog)很适合这样的问题。挑战在于偏离传统的程序编程思维模式。您可能希望在网上搜索关于prolog的课程:许多原则也适用于pyDatalog。

用声明性语言编写循环涉及3个步骤:

1)定义一个谓词,其中所有变量在循环时都会发生变化。

在这种情况下,您希望跟踪部分计划,已经生成的内容以及剩余的计划内容:

partial_plan(Planned, Produced, Todo)

例如,partial_plan([0,],[&#39; A&#39;,],[1,2,3,4,5,6,7])为真。要查找计划,您可以查询:

partial_plan([C0,C1,C2,C3,C4,C5,C6,C7], L, [])

2)描述基(=最简单)的情况。在这里,起点是仍然需要计划所有命令。

+ partial_plan([], [], [0,1,2,3,4,5,6,7])

3)描述迭代规则。在这里,您要选择要完成的命令,并且已经生成了其要求,并将其添加到计划中:

partial_plan(Planned1, Produced1, Todo1) <= (
    # find a smaller plan first
    (Planned0 == Planned1[:-1]) &
    partial_plan(Planned0, Produced0, Todo0) &
    # pick a command to be done, reducing the list of todos, 
    pick(Command, Todo0, Todo1) &
    # verify that it can be done with what has been produced already
    subset(requirement[Command], Produced0) &
    # add it to the plan 
    (Planned1 == Planned0 + [Command, ]) &
    (Produced1 == Produced0 + result[Command])
    )

我们现在必须定义第3步中引入的谓词。

# pick
pick(Command, Todo0, Todo1) <= (
    (X._in(enumerate(Todo0))) & # X has the form [index, value]
    (Command == X[1]) &
    (Todo1 == Todo0[:X[0]] + Todo0[X[0]+1:]) # remove the command from Todo0
    )

# result and requirement are defined as logic functions, 
# so that they can be used in expressions
for i in range(len(tree[0])):
    result[i] = tree[0][i]
    requirement[i] = tree[1][i]

子集检查L1的所有元素是否在L2中(注意所有量词)。它也被定义为循环:

subset([], List2) <= (List2 == List2) # base case
subset(L1, L2) <= (
    (0 < len(L1)) &
    (L1[0]._in(L2)) & # first element in L2
    subset(L1[1:], L2) # remainder is a subset of L2
    )

然后,您必须声明上面的所有pyDatalog变量和谓词,并且&#39;枚举&#39;,&#39;结果&#39;和&#39;要求&#39;功能

注意:这尚未经过测试;可能需要做一些小改动。