Python 用pyDatalog解析依赖图

Python 用pyDatalog解析依赖图,python,algorithm,logic-programming,datalog,pydatalog,Python,Algorithm,Logic Programming,Datalog,Pydatalog,我正在努力编写更具可读性、声明性的程序。所以我决定实现一个我们目前使用的简单算法。程序实施如下: 有命令和资源 每个命令都可以提供和需要多个资源 该算法将在所有命令上循环,并调度为其提供所有需求的命令 命令提供的所有资源现在都已提供 如果所有命令都安排好了,我们就完成了 如果还有命令,我们就不能满足依赖关系,也不能为算法的迭代安排新的命令 因此,我提出的数据日志变体看起来不错,但有两个问题: 这是错误的 我需要一个循环来读取结果 您可以找到完整的源代码 这取决于假设,您可以使用pytest轻松运

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

  • 有命令和资源
  • 每个命令都可以提供和需要多个资源
  • 该算法将在所有命令上循环,并调度为其提供所有需求的命令
  • 命令提供的所有资源现在都已提供
  • 如果所有命令都安排好了,我们就完成了
  • 如果还有命令,我们就不能满足依赖关系,也不能为算法的迭代安排新的命令
  • 因此,我提出的数据日志变体看起来不错,但有两个问题:

  • 这是错误的
  • 我需要一个循环来读取结果
  • 您可以找到完整的源代码

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

    下面是失败的测试:如果我们需要以前的“等级”或订单提供的资源。它找不到它。我试图使下面的内容递归,但即使在简单的例子中也失败了

    def test_graph_multirequire():
    “”“测试冲突解决程序是否可以处理具有多个请求的图形”“”
    树=[
    [('A'),('B'),('C'),('D'),('E'),('F'),('G'),()],
    [(),('A'),('B'),('C','A'),('D'),('E'),('F'),('G')]
    ]
    运行图(树)
    def运行图(树):
    “运行示例”
    尝试:
    tree\u len=len(tree[0])
    索引=列表(范围(树)
    随机。随机(索引)
    对于索引中的i:
    +is_命令(i)
    对于在树[0][i]中提供的内容:
    +提供(i,提供)
    对于树[1][i]中的要求:
    +requires(我,require)
    ##############################
    is_root(X)pyDatalog(和prolog)很适合这种问题。挑战在于脱离传统的过程编程思维。你可能想在网上搜索一门关于prolog的课程:许多原则也适用于pyDatalog

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

    1) 使用循环时更改的所有变量定义谓词

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

    partial_plan(Planned, Produced, Todo)
    
    例如,部分_计划([0,],[A',],[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])
        )
    

    部分计划(计划1、生产1、Todo1)非常感谢您的回答。我解决了所有的问题(删除了评论)。但是我想得到一个更好的语法:“子集([],L2)
    
    # 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]
    
    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
        )