如何从python

问题描述

我正在使用networkx手动将(u,v,权重)输入到图形中。但是,当输入变得更大时,手动插入节点和边将变得非常繁琐且容易出错。我正在尝试,但还没有弄清楚如何在没有人工的情况下执行此任务。

示例输入:

my_list = [“ s1 [0]”,“ d1 [0,2]”,“ s2 [0]”,“ d2 [1,3]”,“ d3 [0,2]”,“ d4 [ 1,4]“,” d5 [2, 3]“,” d6 [1,4]“]

手动插入:

在将节点插入图中之前,我需要给它们编号,因此可以将“ s”或“ d”的首次出现与以后的类似字符区分开,例如s1,s2,s3,...和d1,d2,d3,... 我知道这与SSA表单(编译器)相似,但是找不到对我的案子有用的东西。

手动将(u,v,权重)插入DiGraph()

my_graph.add_weighted_edges_from([("s1","d1",0),("d1","s2","d3",2),("s2",(
    "d2","d4",1),("d2","d5",3),("d3",("d4","d6",4)])

问题:

如何将输入列表(my_list)自动转换为DAG(my_graph),避免手动插入?

完整代码: 这是我到目前为止所写的。

import networkx as nx
from networkx.drawing.nx_agraph import write_dot,graphviz_layout
from matplotlib import pyplot as plt

my_graph = nx.DiGraph()
my_graph.add_weighted_edges_from([("s1",4)])


write_dot(my_graph,"graph.dot")

plt.title("draw graph")
pos = graphviz_layout(my_graph,prog='dot')



nx.draw(my_graph,pos,with_labels=True,arrows=True)

plt.show()
plt.clf()

说明:

  1. 的'和'd'是一些指令,分别需要1个或2个寄存器来执行操作。

  2. 在上面的示例中,我们有2个's'操作和6个'd'操作,并且有五个寄存器[0,1,2,3,4]。

  3. 每个操作都会执行一些计算,并将结果存储在相关的寄存器中。

  4. 从输入中我们可以看到d1使用寄存器0和2,因此直到两个寄存器都释放后它才能工作。因此,d1依赖于s1,因为s1在d1之前并且正在使用寄存器0。一旦s1完成,d1就可以操作,因为寄存器2已经是空闲的。

  5. 例如我们用1初始化所有寄存器。s1将其输入加倍,而d1将两个输入求和,并将结果存储在第二个寄存器中:

因此s1 [0] reg-0 * 2-> 1 * 2 => reg-0 = 2

并且在d1 [0,2] reg-0 + reg-2-> 2 +1 => reg-0 = 2和reg-2 = 3

之后

更新1:该图将是基于某些资源[0 ... 4]的依赖关系图,每个节点将需要1(对于's')或2(对于'd' ')的这些资源。

更新2:两个问题引起了混乱,因此我将它们分开。现在,我已经更改了输入列表,只有一个任务就是将该列表转换为DAG。我还包括一个说明部分。

PS:如果尚未安装graphviz,则可能需要点安装它。

解决方法

好了,现在我对映射的工作方式有了一个更好的了解,它可以归结为用代码描述过程,保留对哪个op正在使用哪个资源的映射,并在操作使用资源时进行迭代。通过前面的操作,我们生成了一条边。我认为这符合您的需求:

import ast
class UniqueIdGenerator:
    def __init__(self,initial=1):
        self.auto_indexing = {}
        self.initial = initial
    def get_unique_name(self,name):
        "adds number after given string to ensure uniqueness."
        if name not in self.auto_indexing:
            self.auto_indexing[name] = self.initial
        unique_idx = self.auto_indexing[name]
        self.auto_indexing[name] += 1
        return f"{name}{unique_idx}"

def generate_DAG(source):
    """
    takes iterable of tuples in format (name,list_of_resources) where
    - name doesn't have to be unique
    - list_of_resources is a list of resources in any hashable format (list of numbers or strings is typical)
    
    generates edges in the format (name1,name2,resource),- name1 and name2 are unique-ified versions of names in input
    - resource is the value in the list of resources
    each "edge" represents a handoff of resource,so name1 and name2 use the same resource sequentially.
    """
    # format {resource: name} for each resource in use.
    resources = {}
    g = UniqueIdGenerator()
    for (op,deps) in source:
        op = g.get_unique_name(op)
        for resource in deps:
            # for each resource this operation requires,if a previous operation used it
            if resource in resources:
                # yield the new edge
                yield (resources[resource],op,resource)
            # either first or yielded an edge,this op is now using the resource.
            resources[resource] = op

my_list = ["s[0]","d[0,2]","s[0]","d[1,3]",4]","d[2,4]"]
data = generate_DAG((a[0],ast.literal_eval(a[1:])) for a in my_list)
print(*data,sep="\n")

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...