如何创建命名边缘“类型"?在Graphviz/dot/neato中? [英] How can I create named edge "types" in Graphviz/dot/neato?

查看:164
本文介绍了如何创建命名边缘“类型"?在Graphviz/dot/neato中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要绘制一个带有graphviz/dot的图,其中节点之间存在常见的边类型,并且正在尝试找到一种为每种边类型定义标签的方法,然后在图中多次使用该标签.

I need to draw a diagram with graphviz/dot where there are common edge types between nodes and am trying to find a way to define a label for each type of edge and then use that label multiple times in the diagram.

例如,想象一下传统的吊扇FSM示例,该示例最初处于OFF状态,每当有人拉动电源线时,它就会根据风扇的速度更改为新状态:

For example imagine the traditional ceiling fan FSM example where it's initially in state OFF and every time someone pulls the cord it changes to a new state based on the speed of the fan:

     Pull         Pull        Pull
OFF ------> HIGH ------> MED ------> LOW
 ^                                    |
 |                Pull                |
 +------------------------------------+

每个边缘都被命名为拉",我可以使用以下命令在点中定义它:

Every edge is named "Pull" and I can define that in dot by using:

digraph fan {
    OFF  -> HIGH [label="Pull"];
    HIGH -> MED  [label="Pull"];
    MED  -> LOW  [label="Pull"];
    LOW  -> OFF  [label="Pull"];
}

但是我不想每次都指定相同的文本标签,因为

BUT I don't want to keep specifying the same textual label every time because

  1. 我的标签可能会很长,所以容易出错,并且
  2. 我的边缘除标签外还具有其他属性,例如颜色,
  3. 我有多种不同类型的边线可供选择,因此我想确保在图中不同上下文中使用的边线类型"A"始终具有所有相同的属性.

我希望点具有一种语法,该语法可以让我为边缘类型定义名称,例如:

I expected dot to have a syntax that would let me define names for my edge types, something like:

digraph fan {
    edge_a [label="Pull"];

    OFF  -> HIGH edge_a;
    HIGH -> MED  edge_a;
    MED  -> LOW  edge_a;
    LOW  -> OFF  edge_a;
}

但是,当然,真正要做的是创建一个名为"Pull"和未标记边缘的节点.

but of course what the really does is create a node named "Pull" and unlabeled edges.

我已经在网上搜索了几个小时,没有成功.有谁知道如何预先定义要在多个位置使用的边缘类型?

I've been searching online for a few hours with no success. Anyone know how to define edge types up front to be used in multiple locations?

更新: @vaettchen建议定义边缘类型,然后列出所有过渡对于该边缘类型,然后定义下一个边缘类型,然后定义其过渡.尽管从技术上来说这可以解决我的问题,但由于我今天的图形看起来像这样,它还会引入其他一些问题:

Update: @vaettchen had suggested defining an edge type then listing all of the transitions for that edge type, then defining the next edge type followed by it's transitions. While that would technically solve my problem, it would introduce a couple of others because my graphs today can look like:

digraph {
    subgraph cluster_1 {
        a -> b [label="type x", color=red, style=solid];
        b -> a [label="type y", color=green, style=dashed];

        b -> c [label="type x", color=red, style=solid];
        c -> b [label="type y", color=green, style=dashed];

        c -> d [label="type z", color=blue, style=dotted];
    }

    subgraph cluster_2 {
        d -> e [label="type x", color=red, style=solid];
        e -> d [label="type y", color=green, style=dashed];

        e -> f [label="type x", color=red, style=solid];
        f -> e [label="type y", color=green, style=dashed];

        f -> c [label="type z", color=blue, style=dotted];
    }
}

并按边缘类型重新排列,我将失去双向边缘彼此相邻的代码(a-> b和b-> a)的即时视觉清晰度,而我必须明确列出每个子图中的节点,我不得不将子图内部边缘定义拉入主图:

and to rearrange that by edge type I'd lose the immediate visual clarity in the code of having the bidirectional edges next to each other (a->b and b->a) and I'd have to explicitly list the nodes within each subgraph and I'd have to pull the subgraph-internal edge definitions up into the main graph:

digraph {
    edge [label="type x", color=red, style=solid];
    a -> b;
    b -> c;
    d -> e;
    e -> f;

    edge [label="type y", color=green, style=dashed];
    b -> a;
    c -> b;
    e -> d;
    f -> e;

    edge [label="type z", color=blue, style=dotted];
    c -> d;
    f -> c;

    subgraph cluster_1 {
        a; b; c;
    }

    subgraph cluster_2 {
        d; e; f;
    }
}

因此,尽管它可以解决我提出的问题,但我对此建议表示赞赏,但我不确定是否值得进行权衡,因为您最终得到的是等效于C程序的代码,在该程序中,您必须定义外部的所有变量功能并按其类型而不是逻辑关联进行组织.

So while it would solve the problem I asked about and I appreciate the suggestion, I'm not sure it's worth the tradeoff as you end up with the equivalent of a C program where you had to define all of your variables outside of the functions and organize them by their type rather than logical associations.

要清楚,给定上面的示例,如果存在这样的"edge_type"定义关键字,我真正希望的是以下内容:

To be clear, given the above example what I was really hoping for would look like the following if such an "edge_type" definition keyword existed:

digraph {
    edge_type edge_x [label="type x", color=red, style=solid];
    edge_type edge_y [label="type y", color=green, style=dashed];
    edge_type edge_z [label="type z", color=blue, style=dotted];

    subgraph cluster_1 {
        a -> b edge_x;
        b -> a edge_y;

        b -> c edge_x;
        c -> b edge_y;

        c -> d edge_z;
    }

    subgraph cluster_2 {
        d -> e edge_x;
        e -> d edge_y;

        e -> f edge_x;
        f -> e edge_y;

        f -> c edge_z;
    }
}

推荐答案

不是真正的答案,而是值得思考的东西",因为我认为graphviz中不存在命名标签:您可以为以下内容定义默认标签边缘.如果您的工作流程允许在一个地方定义所有边缘,那么效果很好.示例:

Not really an answer but "food for thought" as I don't think named labels exist in graphviz: You could define a default label for the following edges. That works well if your workflow allows to define edges all in one place. Example:

digraph rs
{
    node[ shape = box, style = rounded]

    edge[ label = "pull" ];
    { A B } -> C;
    G -> H;
    C -> D[ label = "stop" ];
    edge[ label = "push"];
    D -> { E F };
    edge[ color = red, fontcolor = red ];
    { E F } -> G;
}

产生

我也尝试过用

来实现您的图表

I have also tried to implement your diagramm with

digraph fan 
{
    splines = ortho;
    node [ shape=box ]

    edge [ xlabel = "Pull", minlen = 4 ];
    { rank = same; OFF  -> HIGH -> LOW; }
    LOW:s -> OFF:s;
}

产生

所以看起来不错,但是所有的调整都很难扩展.

so it looks good but with all the tweaking is difficult to expand.

这篇关于如何创建命名边缘“类型"?在Graphviz/dot/neato中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆