Q-BPM:Process Diagram Images

Many of process diagram images based on BPMN in q-BPM.org are generated by using Graphviz extension. This page explains the way to draw BPMN diagrams by using Graphviz.

Overview of Graphviz
Graphviz is an open source software (OSS) to draw "graphs," and published by AT&T Research under CPL1.0 license. Graphviz interprets the description written in DOT, a graph description language, and generates a image file. Samples included in the [official instruction manual] of DOT are shown below.

Tools in Graphviz
Graphviz can draw directed graphs, undirected graph, cyclic graphs, and so on. (Because the primary focus here is "to define BPD by using BPMN," directed graphs are mainly considered.)

What Is Graph?
Originally, "graph" is a terminology used in "Graph Theory" area, and it means "what can be expressed by using nodes and edges." In addition to flow charts, such as business process diagrams (BPD), it is widely used to model various information, including dependencies, data structures, and map information.

When BPD, which is a flow chart, is drawn, each edge has direction. Such a graph is called "Directed Graph." On the contrary, a graph whose edges do not have direction is called "Undirected Graph." Additionally, a graph that can be drawn without any edge intersections is called "Plane Graph," and a graph that is consisted of only vertical and horizontal edges is called "Orthogonal Graph."

Official Sample A
 digraph test123 { a -> b -> c; a -> {x y}; b [shape=box]; c [label="hello\nworld",color=blue,fontsize=24,fontname="Palatino-Italic",fontcolor=red,style=filled]; a -> z [label="hi", weight=100]; x -> z [label="multi-line\nlabel"]; edge [style=dashed,color=red]; b -> x; {rank=same; b x} } digraph test123 { a -> b -> c; a -> {x y}; b [shape=box]; c [label="hello\nworld",color=blue,fontsize=24,fontcolor=red,style=filled]; a -> z [label="hi", weight=100]; x -> z [label="multi-line\nlabel"]; edge [style=dashed,color=red]; b -> x; {rank=same; b x} }

Official Sample B
 graph test123 { a -- b -- c; a -- {x y}; x -- c [w=10.0]; x -- y [w=5.0,len=3]; } graph test123 { a -- b -- c; a -- {x y}; x -- c [w=10.0]; x -- y [w=5.0,len=3]; }

Example of BPMN
Graphviz can not completely or accurately express objects and markers defined in BPMN. However, because images are automatically generated based on text data, it makes creation of BPD images and translation of BPD images efficient. In this site, it is recommended to follow the notations shown below.

Overall Properties of Graph
In order to draw directed graphs, "digraph" must be specified. In addition, "rankdir=LR;" needs to be specified to make the flow direction left-to-right. (By default, it is top-to-bottom.)

Sequence Flow

 * Unconditional Flow: After activity "A1" is completed, subsequent activities, "A2" and "A3" are started at the same time (AND-Split). It is not necessary to specify any special edge properties.
 * Conditional Flow: It is used in case of exclusive splits (XOR-Split) etc. When "A2" is completed, if the condition "x > 100" is true, "A4" is executed after that. In this case, "arrowtail=odiamond" needs to be specified as an edge property. In addition, condition statements are specified as values of "label," "headlabel," or "taillabel."
 * Default Flow: This is used with conditional flow and is chosen only when none of the condition specified in the conditional flow is not satisfied. "arrowtail=rcrowlvee" is specified as an edge property. (In order to invert a backslash, the edge property needs to be "arrowtail=lcrowrvee.")

＜DOT Definition＞ digraph G { rankdir=LR; A1 -> {A2 A3}; A2 -> A4 [arrowtail=odiamond, label="X>100"]; A2 -> A5 [arrowtail=rcrowlvee]; } digraph G { rankdir=LR; A1 -> {A2 A3}; A2 -> A4 [arrowtail=odiamond, label="X>100"]; A2 -> A5 [arrowtail=rcrowlvee]; }

Activity
In order to display rounded rectangle, "shape=box, style=rounded" is specified as a node property. Label can be changed by setting text as a value of "label." ＜DOT Definition＞ digraph G { rankdir=LR;

A1 [shape=box, style=rounded]; A2 [shape=box, style=rounded, label=""]; A3 [shape=box, style=rounded, label="Apply"];

A1 -> A2 -> A3 ; } digraph G { rankdir=LR;

A1 [shape=box, style=rounded]; A2 [shape=box, style=rounded, label=""]; A3 [shape=box, style=rounded, label="Apply"];

A1 -> A2 -> A3 ; }

A reserved keyword "node" can be used to change the default values of all nodes. ＜DOT Definition＞ digraph G { rankdir=LR; node [shape=box, style=rounded];

A1 ; A2 [label=""]; A3 [label="Apply"];

A1 -> A2 -> A3 ; } digraph G { rankdir=LR; node [shape=box, style=rounded];

A1 ; A2 [label=""]; A3 [label="Apply"];

A1 -> A2 -> A3 ; }

Event
In order to draw "a small circles without a label," "label="", shape=circle, width=0.3" is specified as a node property. (Default width is set to be 0.75.) To draw a termination event as a bold circle, "style=bold" needs to be additionally specified. ＜DOT Definition＞ digraph G { rankdir=LR; node [shape=box, style=rounded];

AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", syle=bold];

A1 ; A2 [label=""]; A3 [label="Apply"];

AS -> A1 -> A2 -> A3 -> AE; } digraph G { rankdir=LR; node [shape=box, style=rounded];

AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold];

A1 ; A2 [label=""]; A3 [label="Apply"];

AS -> A1 -> A2 -> A3 -> AE; }

Swimlane
In order to create a swimlane (subgraph), "subgraph clusterXXX" is used. (Here, "cluster" is used as a prefix of the name of the subgraph. It is called clustering of subgraphs.) In addition, to indicate participants (concerned humans/computer systems) of the swimlane, "label="marketing@company.com";" is used. To make the label left-aligned, "labeljust=l;" is specified. ＜DOT Definition＞ digraph G { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="marketing@company.com";

AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:Create Document"]; A2 [label="A2:Revision and Check"];

AS -> A1; A1 -> A2 [style=invis]; // Define an invisible edge to make AS, A1, A2, and AE are horizontally-placed A2 -> AE; }

subgraph clusterB { labeljust=l; label="marketing-leader@company.com";

B1 [label="B1:Check Document"]; B2 [label="B2:Comment"];

B1 -> B2; }

A1 -> B1; // Sequence flow crossing swimlanes is drawn outside of cluster definition B2 -> A2;

} digraph G { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="marketing@company.com";

AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:Create Document"]; A2 [label="A2:Revision and Check"];

AS -> A1; A1 -> A2 [style=invis]; // Define an invisible edge to make AS, A1, A2, and AE are horizontally-placed A2 -> AE; }

subgraph clusterB { labeljust=l; label="marketing-leader@company.com";

B1 [label="B1:Check Document"]; B2 [label="B2:Comment"];

B1 -> B2; }

A1 -> B1; // Sequence flow crossing swimlanes is drawn outside of cluster definition B2 -> A2;

}

"Appearance of clusters" can be changed by setting values of style, color, fillcolor, etc. Additionally, by setting compound property to be true in the top-level graph, it is possible to draw a message flow (edge) that connects an activity (node) and a swimlane (cluster). (Refer to the references for detail.)

Alignment (Adding "invis" Edge)
Basically, activities are placed from left to right. However, in the example shown above, A1 and B1 are expected to have the same X coordinate (the same rank). In such a case, A1 and B1 can be placed in the same rank by "giving tensile force" between A1 and B2.

In addition, if activities A1 and A2 are in the same graph (and in the same cluster), the rank can be specified by using "{rank=same; A1 A2}." (See "Specifying Rank.") digraph G { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="marketing@company.com";

AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:Create Document"]; A2 [label="A2:Revision and Check"];

AS -> A1; A1 -> A2 [style=invis]; A2 -> AE; }

subgraph clusterB { labeljust=l; label="marketing-leader@company.com";

B1 [label="B1:Check Document"]; B2 [label="B2:Comment"];

B1 -> B2; }

A1 -> B1; B2 -> A2; A1 -> B2 [style=invis]; // *Make A1 and A2 closer to each other by using an invisible edge*

} ＜DOT Definition＞ digraph G01 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="marketing@company.com";

AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:Create Document"]; A2 [label="A2:Revision and Check"];

AS -> A1; A1 -> A2 [style=invis]; A2 -> AE; }

subgraph clusterB { labeljust=l; label="marketing-leader@company.com";

B1 [label="B1:Check Document"]; B2 [label="B2:Comment"];

B1 -> B2; }

A1 -> B1; B2 -> A2; A1 -> B2 [style=invis]; // *Make A1 and A2 closer to each other by using an invisible edge*

}

Alignment (Specifying Tensile Force)
In case specific activities, "A1," "A2," and "A3," are desired to be aligned linearly, tensile force (weight) "weight=10" is specified on "the main line" "A1->A2" at the split.

digraph G02 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="person@company.com";

AS [label="", shape=circle, width="0.3"]; AE1 [label="", shape=circle, width="0.3", style=bold]; AE2 [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:activity"]; A2 [label="A2:activity"]; A3 [label="A3:activity"]; Ae [label="Ae:activity"];

AS -> A1; A1 -> Ae [arrowtail=odiamond, label="NG"]; Ae -> AE1; A1 -> A2 [arrowtail=rcrowlvee, weight=10]; //*Tensile force "weight=10" makes "A1->A2" horizontal instead of "A1->Ae"* A2 -> A3 [style=invis]; A3 -> AE2 ; }

subgraph clusterB { labeljust=l; label="section-leader@company.com";

B1 [label="B1:activity"]; B2 [label="B2:activity"];

B1 -> B2; }

A2 -> B1; B2 -> A3; A2->B2 [style=invis]; }

＜DOT Definition＞ digraph G02 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="person@company.com";

AS [label="", shape=circle, width="0.3"]; AE1 [label="", shape=circle, width="0.3", style=bold]; AE2 [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:activity"]; A2 [label="A2:activity"]; A3 [label="A3:activity"]; Ae [label="Ae:activity"];

AS -> A1; A1 -> Ae [arrowtail=odiamond, label="NG"]; Ae -> AE1; A1 -> A2 [arrowtail=rcrowlvee, weight=10]; //*Tensile force "weight=10" makes "A1->A2" horizontal instead of "A1->Ae"* A2 -> A3 [style=invis]; A3 -> AE2 ; }

subgraph clusterB { labeljust=l; label="section-leader@company.com";

B1 [label="B1:activity"]; B2 [label="B2:activity"];

B1 -> B2; }

A2 -> B1; B2 -> A3; A2->B2 [style=invis]; }

Alignment (Specifying Rank)
In subgraph "clusterA," "{rank=same Ae A3};" is used to make X coordinates (ranks) of "Ae" and "A3" the same. digraph G03 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="person@company.com";

AS [label="", shape=circle, width="0.3"]; AE1 [label="", shape=circle, width="0.3", style=bold]; AE2 [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:activity"]; A2 [label="A2:activity"]; A3 [label="A3:activity"]; Ae [label="Ae:activity"];

AS -> A1; A1 -> Ae [arrowtail=odiamond, label="NG"]; Ae -> AE1; A1 -> A2 [arrowtail=rcrowlvee, weight=10]; A2 -> A3 [style=invis]; A3 -> AE2 ;

{rank=same Ae A3}; // *Make ranks of "Ae" and "A3" the same* }

subgraph clusterB { labeljust=l; label="section-leader@company.com";

B1 [label="B1:activity"]; B2 [label="B2:activity"];

B1 -> B2; }

A2 -> B1; B2 -> A3; A2->B2 [style=invis]; }

＜DOT Definition＞ digraph G03 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="person@company.com";

AS [label="", shape=circle, width="0.3"]; AE1 [label="", shape=circle, width="0.3", style=bold]; AE2 [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:activity"]; A2 [label="A2:activity"]; A3 [label="A3:activity"]; Ae [label="Ae:activity"];

AS -> A1; A1 -> Ae [arrowtail=odiamond, label="NG"]; Ae -> AE1; A1 -> A2 [arrowtail=rcrowlvee, weight=10]; A2 -> A3 [style=invis]; A3 -> AE2 ;

{rank=same Ae A3}; // *Make ranks of "Ae" and "A3" the same* }

subgraph clusterB { labeljust=l; label="section-leader@company.com";

B1 [label="B1:activity"]; B2 [label="B2:activity"];

B1 -> B2; }

A2 -> B1; B2 -> A3; A2->B2 [style=invis]; }

Alignment (Specifying Minimum Length)
By specifying "minlen=2" for the sequence flow from "Ae" to "termination event," "rank" can be inserted, and thereby two termination events are aligned. (*The same result can be achieved by "making ranks of two termination events the same.) digraph G04 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="person@company.com";

AS [label="", shape=circle, width="0.3"]; AE1 [label="", shape=circle, width="0.3", style=bold]; AE2 [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:activity"]; A2 [label="A2:activity"]; A3 [label="A3:activity"]; Ae [label="Ae:activity"];

AS -> A1; A1 -> Ae [arrowtail=odiamond, label="NG"]; Ae -> AE1 [minlen=2]; //*Minimum length between "AE1" and "Ae" is maintained by using "minlen=2" (inch)* A1 -> A2 [arrowtail=rcrowlvee, weight=10]; A2 -> A3 [style=invis]; A3 -> AE2 ; }

subgraph clusterB { labeljust=l; label="section-leader@company.com";

B1 [label="B1:activity"]; B2 [label="B2:activity"];

B1 -> B2; }

A2 -> B1; B2 -> A3; A2->B2 [style=invis]; }

＜DOT Definition＞ digraph G04 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="person@company.com";

AS [label="", shape=circle, width="0.3"]; AE1 [label="", shape=circle, width="0.3", style=bold]; AE2 [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:activity"]; A2 [label="A2:activity"]; A3 [label="A3:activity"]; Ae [label="Ae:activity"];

AS -> A1; A1 -> Ae [arrowtail=odiamond, label="NG"]; Ae -> AE1 [minlen=2]; //*Minimum length between "AE1" and "Ae" is maintained by using "minlen=2" (inch)* A1 -> A2 [arrowtail=rcrowlvee, weight=10]; A2 -> A3 [style=invis]; A3 -> AE2 ; }

subgraph clusterB { labeljust=l; label="section-leader@company.com";

B1 [label="B1:activity"]; B2 [label="B2:activity"];

B1 -> B2; }

A2 -> B1; B2 -> A3; A2->B2 [style=invis]; }

Avoiding Overlapped Flows (Specifying Ports)
In case "A1" and "B1" have the same X coordinate and round-trip sequence flows, "A1->B1" and "B1->A1" need to be drawn, it is necessary to specify a port of one of the sequence flow by using, for example, "[tailport=sw,headport=nw];" (the head is attached to the north west port, and the tail is attached to the south west port). ("n, nw, w, sw, s, se, e, and ne" can be specified, and the default is set to be "center.") (However, adjusting ranks usually makes the diagram look better.) digraph G05 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="any-section@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1: Daily\nReport"]; A2 [label="A2: Memo"];

AS -> A1; A2 -> AE; A1 -> A2 [style=invis]; }

subgraph clusterB { labeljust=l; label="section-leader@company.com"; B1 [label="B1: Review"]; }

A1 -> B1; B1 -> A1 [arrowtail=odiamond, label="NG"]; B1 -> A2 [arrowtail=rcrowlvee]; } digraph G05 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="any-section@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1: Daily\nReport"]; A2 [label="A2: Memo"];

AS -> A1; A2 -> AE; A1 -> A2 [style=invis]; }

subgraph clusterB { labeljust=l; label="section-leader@company.com"; B1 [label="B1: Review"]; }

A1 -> B1 [tailport=sw,headport=nw]; B1 -> A1 [arrowtail=odiamond, label="NG"]; B1 -> A2 [arrowtail=rcrowlvee]; }

＜DOT Definition＞ digraph G05 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="any-section@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1: Daily\nReport"]; A2 [label="A2: Memo"];

AS -> A1; A2 -> AE; A1 -> A2 [style=invis]; }

subgraph clusterB { labeljust=l; label="section-leader@company.com"; B1 [label="B1: Review"]; }

A1 -> B1 [tailport=sw,headport=nw]; // *Specify positions of tail port and head port* B1 -> A1 [arrowtail=odiamond, label="NG"]; B1 -> A2 [arrowtail=rcrowlvee]; } Example by means of adjusting ranks　（"Invisible edge (B1 -> AE [style=invis, weight=10];)" is added.) digraph G05 { rankdir=LR; node [shape=box, style=rounded];

subgraph clusterA { labeljust=l; label="any-section@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1: Daily\nReport"]; A2 [label="A2: Memo"];

AS -> A1; A2 -> AE; A1 -> A2 [style=invis]; }

subgraph clusterB { labeljust=l; label="section-leader@company.com"; B1 [label="B1: Review"]; }

A1 -> B1; B1 -> A1 [arrowtail=odiamond, label="NG"]; B1 -> A2 [arrowtail=rcrowlvee]; B1 -> AE [style=invis, weight=10]; }

Backward Flow (Changing "dir" Property)
Basically, activities and events (nodes) are placed so that all the sequence flows are right-pointing. If left-pointing sequence flows are intentionally drawn, "[dir=back]" needs to be specified. (The example below specifies [labelfloat=true] to allow an overlap of a sequence flow and label.)

digraph G06 { rankdir=LR; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="any-section@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1: Daily\nReport"]; A2 [label="A2: Confirm\n& Memo"];

AS -> A1; A1 -> AE [arrowtail=rcrowlvee]; AE -> A2 [dir=back]; //*Specifying backward flow* }

subgraph clusterB { labeljust=l; label="section-leader@company.com"; B1 [label="B1: Review"]; }

A1 -> B1 [arrowtail=odiamond, label="Review Flag"]; B1 -> A1 [arrowtail=odiamond, taillabel="NG", tailport=w, headport=s]; B1 -> A2 [arrowtail=rcrowlvee]; }

＜DOT Definition＞ digraph G06 { rankdir=LR; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="any-section@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1: Daily\nReport"]; A2 [label="A2: Confirm\n& Memo"];

AS -> A1; A1 -> AE [arrowtail=rcrowlvee]; AE -> A2 [dir=back]; //*Specifying backward flow* }

subgraph clusterB { labeljust=l; label="section-leader@company.com"; B1 [label="B1: Review"]; }

A1 -> B1 [arrowtail=odiamond, label="Review Flag"]; B1 -> A1 [arrowtail=odiamond, taillabel="NG", tailport=w, headport=s]; B1 -> A2 [arrowtail=rcrowlvee]; }

Specifying Size of Entire Graph
Although process diagrams tend to be horizontally lengthened, there should be at most 5 to 7 ranks owing to the screen size. (Also, text should contains enough "\n" so that it does not get lengthend.) In case the diagram gets big by necessity, the entire graph can be shrunk by specifying the size of the graph by using "[size="10,5"]." (It is recommended that the maximum width of the graph be 10 inches.) Here are examples with and without size specification.

digraph G07 { graph [rankdir=LR]; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="marketing@company.com"; MS [label="", shape=circle, width="0.3"]; ME [label="", shape=circle, width="0.3", style=bold]; M1 [label="M1:step1"]; M2 [label="M2:step2"]; M3 [label="M3:step3"]; M4 [label="M4:step4"]; M5 [label="M5:step5"]; M6 [label="M6:step6"]; M7 [label="M7:step7"];

MS -> M1; M1 -> M2 -> M3 -> M4 -> M5 -> M6 -> M7 [style=invis]; M7 -> ME; }

subgraph clusterB { labeljust=l; label="development@company.com"; D1 [label="D1:step1"]; D2 [label="D2:step2"]; D3 [label="D3:step3"]; D4 [label="D4:step4"]; D5 [label="D5:step5"]; D6 [label="D6:step6"];

D1 -> D2 -> D3 -> D4 -> D5 -> D6 [style=invis]; }

M1 -> D1 -> M2 -> D2 -> M3 -> D3 -> M4 -> D4 -> M5 -> D5 -> M6 -> D6 -> M7; } digraph G07 { graph [size="10,5", rankdir=LR]; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="marketing@company.com"; MS [label="", shape=circle, width="0.3"]; ME [label="", shape=circle, width="0.3", style=bold]; M1 [label="M1:step1"]; M2 [label="M2:step2"]; M3 [label="M3:step3"]; M4 [label="M4:step4"]; M5 [label="M5:step5"]; M6 [label="M6:step6"]; M7 [label="M7:step7"];

MS -> M1; M1 -> M2 -> M3 -> M4 -> M5 -> M6 -> M7 [style=invis]; M7 -> ME; }

subgraph clusterB { labeljust=l; label="development@company.com"; D1 [label="D1:step1"]; D2 [label="D2:step2"]; D3 [label="D3:step3"]; D4 [label="D4:step4"]; D5 [label="D5:step5"]; D6 [label="D6:step6"];

D1 -> D2 -> D3 -> D4 -> D5 -> D6 [style=invis]; }

M1 -> D1 -> M2 -> D2 -> M3 -> D3 -> M4 -> D4 -> M5 -> D5 -> M6 -> D6 -> M7; } ＜DOT Definition＞ digraph G07 { graph [size="10,5", rankdir=LR]; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="marketing@company.com"; MS [label="", shape=circle, width="0.3"]; ME [label="", shape=circle, width="0.3", style=bold]; M1 [label="M1:step1"]; M2 [label="M2:step2"]; M3 [label="M3:step3"]; M4 [label="M4:step4"]; M5 [label="M5:step5"]; M6 [label="M6:step6"]; M7 [label="M7:step7"];

MS -> M1; M1 -> M2 -> M3 -> M4 -> M5 -> M6 -> M7 [style=invis]; M7 -> ME; }

subgraph clusterB { labeljust=l; label="development@company.com"; D1 [label="D1:step1"]; D2 [label="D2:step2"]; D3 [label="D3:step3"]; D4 [label="D4:step4"]; D5 [label="D5:step5"]; D6 [label="D6:step6"];

D1 -> D2 -> D3 -> D4 -> D5 -> D6 [style=invis]; }

M1 -> D1 -> M2 -> D2 -> M3 -> D3 -> M4 -> D4 -> M5 -> D5 -> M6 -> D6 -> M7; }

Template for Drawing
Here is a template in which a lot of drawing techniques are utilized. (It is not a completely valid BPMN diagram.) digraph TMPG { graph [size="10,5", rankdir=LR]; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="sectionA@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:step1"]; A2 [label="A2:step2"]; A3 [label="A3:step3"]; A4 [label="A4:step4"]; Ae [label="Ae:error\ncase"]; A5 [label="A5:step5\nLong Name"];

AS -> A1; A5 -> AE [weight=10]; A1 -> A2 -> A3 -> A4 -> A5 [style=invis,weight=10]; A4 -> Ae; Ae -> AE; {rank=same Ae A5}; }

subgraph clusterB { labeljust=l; label="sectionB@company.com"; B1 [label="B1:step1"]; B2 [label="B2:step2"]; B3 [label="B3:step3"]; B4 [label="B4:step4", style="rounded,filled" fillcolor=red]; B5 [label="B5:step5", style="rounded,filled" fillcolor=green];

B1 -> B2 -> B3 -> B4 -> B5 [style=invis]; }

subgraph clusterBL { labeljust=l; label="sectionB-leader@company.com"; BL1 [label="BL1:step1"]; BL2 [label="BL2:Message", shape=ellipse, style=dotted]; BL3 [label="BL3:TEXT", shape=none];

BL1 -> BL2 [style=invis]; BL2 -> BL3 [minlen=2]; }

A1 -> B1 [arrowtail=odiamond, label="X>100"]; B1 -> BL1 [arrowtail=rcrowlvee]; B2 -> A4 [tailport=ne,headport=w]; B2 -> BL2 [arrowhead=onormal, style=dotted]

}

digraph TMPG { graph [size="10,5", rankdir=LR]; node [shape=box, style=rounded]; edge [labelfloat=true];

subgraph clusterA { labeljust=l; label="sectionA@company.com"; AS [label="", shape=circle, width="0.3"]; AE [label="", shape=circle, width="0.3", style=bold]; A1 [label="A1:step1"]; A2 [label="A2:step2"]; A3 [label="A3:step3"]; A4 [label="A4:step4"]; Ae [label="Ae:error\ncase"]; A5 [label="A5:step5\nLong Name"];

AS -> A1; A5 -> AE [weight=10]; A1 -> A2 -> A3 -> A4 -> A5 [style=invis,weight=10]; A4 -> Ae; Ae -> AE; {rank=same Ae A5}; }

subgraph clusterB { labeljust=l; label="sectionB@company.com"; B1 [label="B1:step1"]; B2 [label="B2:step2"]; B3 [label="B3:step3"]; B4 [label="B4:step4", style="rounded,filled" fillcolor=red]; B5 [label="B5:step5", style="rounded,filled" fillcolor=green];

B1 -> B2 -> B3 -> B4 -> B5 [style=invis]; }

subgraph clusterBL { labeljust=l; label="sectionB-leader@company.com"; BL1 [label="BL1:step1"]; BL2 [label="BL2:Message", shape=ellipse, style=dotted]; BL3 [label="BL3:TEXT", shape=none];

BL1 -> BL2 [style=invis]; BL2 -> BL3 [minlen=2]; }

A1 -> B1 [arrowtail=odiamond, label="X>100"]; B1 -> BL1 [arrowtail=rcrowlvee]; B2 -> A4 [tailport=ne,headport=w]; B2 -> BL2 [arrowhead=onormal, style=dotted]

}