如何在 python 中实现 makefile 风格的算法

发布于 2024-10-04 22:35:27 字数 977 浏览 2 评论 0原文

我正在用 python 实现一个声学特征提取系统,我需要实现一个 makefile 风格算法以确保特征提取系统中的所有块都以正确的顺序运行,并且不重复任何特征提取阶段。

该特征提取系统的输入将是一个图表,详细说明特征提取块之间的链接,我想根据该图表确定要运行哪些函数。

这种系统的一个例子可能如下:

            ,-> [B] -> [D] ----+
input --> [A]           ^      v
            `-> [C] ----+---> [E] --> output

函数调用(假设每个块X是一个output = X(inputs)形式的函数)可能类似于:

a = A(input)
b = B(a)
c = C(a)
d = D(b,c)  # can't call D until both b and c are ready
output = E(d,c)   # can't call E until both c and d are ready

我已经以字典的形式加载了函数图,每个字典条目的形式为 (inputs, function) ,如下所示:

blocks = {'A' : (('input'), A),
          'B' : (('A'), B),
          'C' : (('A'), C),
          'D' : (('B','C'), D),
          'output' : (('D','C'), E)}

我目前只是在 makefile 算法的作用上画一个空白确切地说,以及如何去实现它,我的 google-fu 在这里似乎也不是很有帮助。

I am implementing an acoustic feature extraction system in python, and I need to implement a makefile-style algorithm to ensure that all blocks in the feature extraction system are run in the correct order, and without repeating any feature extractions stages.

The input to this feature extraction system will be a graph detailing the links between the feature extraction blocks, and I'd like to work out which functions to run when based upon the graph.

An example of such a system might be the following:

            ,-> [B] -> [D] ----+
input --> [A]           ^      v
            `-> [C] ----+---> [E] --> output

and the function calls (assuming each block X is a function of the form output = X(inputs) might be something like:

a = A(input)
b = B(a)
c = C(a)
d = D(b,c)  # can't call D until both b and c are ready
output = E(d,c)   # can't call E until both c and d are ready

I already have the function graph loaded in the form of a dictionary with each dictionary entry of the form (inputs, function) like so:

blocks = {'A' : (('input'), A),
          'B' : (('A'), B),
          'C' : (('A'), C),
          'D' : (('B','C'), D),
          'output' : (('D','C'), E)}

I'm just currently drawing a blank on what the makefile algorithm does exactly, and how to go about implementing it. My google-fu appears to be not-very-helpful here too. If someone at least can give me a pointer to a good discussion of the makefile algorithm that would probably be a good start.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦魇绽荼蘼 2024-10-11 22:35:28

blocks 基本上是(非循环)依赖图的邻接列表表示。因此,为了获得处理块的正确顺序,您可以执行拓扑排序。

blocks is basically an adjacency list representation of the (acyclic) dependency graph. Hence, to get the correct order to process the blocks, you can perform a topological sort.

尤怨 2024-10-11 22:35:28

正如其他有用的回答者已经指出的那样,我追求的是 拓扑排序,但是我认为我的特殊情况更简单一些,因为函数图必须始终从输入开始并以输出结束。

所以,这就是我最终所做的(我稍微编辑了它以删除一些依赖于上下文的内容,所以它可能不完全正确):

def extract(func_graph):
    def _getsignal(block,signals):
        if block in signals:
            return signals[block]
        else:
            inblocks, fn = func_graph[block]
            inputs = [_getsignal(i,signals) for i in inblocks]
            signals[block] = fn(inputs)
            return signals[block]

    def extract_func (input):
        signals = dict(input=input)
        return _getsignal('output',signals)

    return extract_func

所以现在我可以设置该函数

fn = extract(blocks)

并使用它多次我喜欢:

list_of_outputs = [fn(i) for i in list_of_inputs]

我可能还应该对循环进行一些检查,但这是另一天的问题。

As the other helpful answerers have already pointed out, what I'm after is a topological sort, but I think my particular case is a little simpler because the function graph must always start at input and end at output.

So, here is what I ended up doing (I've edited it slightly to remove some context-dependent stuff, so it may not be completely correct):

def extract(func_graph):
    def _getsignal(block,signals):
        if block in signals:
            return signals[block]
        else:
            inblocks, fn = func_graph[block]
            inputs = [_getsignal(i,signals) for i in inblocks]
            signals[block] = fn(inputs)
            return signals[block]

    def extract_func (input):
        signals = dict(input=input)
        return _getsignal('output',signals)

    return extract_func

So now given I can set up the function with

fn = extract(blocks)

And use it as many times as I like:

list_of_outputs = [fn(i) for i in list_of_inputs]

I should probably also put in some checks for loops, but that is a problem for another day.

星軌x 2024-10-11 22:35:28

对于包括 Python 在内的多种语言的代码,请尝试以下 Rosetta 代码链接:拓扑排序拓扑排序/提取顶部项目

For code in many languages, including Python try these Rosetta code links: Topological sort, and Topological sort/Extracted top item.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文