Q-BPM:プロセスダイアグラム画像の書き方

q-BPM.orgにおけるBPMN記法に基づくプロセスダイアグラム画像の多くは、Graphvizエクステンションによって生成されている. ここではGraphvizを用いたBPMN図の作成方法について記述する.

Graphvizの概要
Graphvizは「グラフ」を描画するためのオープンソースソフトウェア(OSS)で、AT&T Researchにより公開されている(CPL1.0ライセンス). グラフ表記言語DOTによる記述を解読し、画像ファイルを生成する. DOTの[公式マニュアル]に記載されているサンプルは以下の通り.

Graphvizのツール群
Graphvizは、有向グラフ、無向グラフ、放射状グラフ、循環グラフなどを描画できる. （ここでは「BPMN記法を用いたBPDを定義する事」に主眼を置くため、有向グラフの作成を前提に記述する）

グラフとは
そもそも「グラフ」とは、「グラフ理論(Graph Theory)」分野における専門用語で「ノードとエッジによって表現できるもの」を指す. ビジネスプロセスダイアグラム(BPD)の様な流れ図に限らず、依存関係、データ構造、地図情報など様々な情報を模式化する為に広く利用される.

流れ図であるBPDを描くとき、そのエッジには向きが定義されるが、グラフ理論において、その様なグラフを特に「有向グラフ(Directed Graph)」と呼ぶ. その逆にエッジに向きが無いものを「無向グラフ(Undirected Graph)」、またエッジ交差がなく表記できるものを「平面グラフ(Plane Graph)」、すべてのエッジが水平垂直方向のみの直線で表現できるものを「直交グラフ(Orthogonal Graph)」と呼ぶ.

公式サンプルA
＜DOT表記＞ 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} }

公式サンプルB
＜DOT表記＞ 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]; }

BPMN記法の例
Graphvizは、BPMN記法におけるオブジェクトやマーカの全てを表現できるものではなく、また厳密に表現できるものでもない. しかしながらテキスト情報を元に画像を自動的に生成するため、BPD画像作成やBPD画像翻訳の効率を高められる. 当サイトでは以下の書式を推奨する.

グラフの全体属性
有向グラフを描くために「digraph」、流れる方向を左から右へとする（デフォルトは上から下）ために「rankdir=LR;」を指定する必要がある.

シーケンスフロー

 * 非制御フロー:アクティビティ「A1」が完了すれば、後続の「A2」「A3」が共に同時に実行される(AND-Split). 特別なエッジ属性を指定する必要はない.
 * 制御フロー:単一選択分岐(XOR-Split)等で利用される. 「A2」完了時、条件「x＞100」が真であれば「A4」が実行される. エッジ属性として「arrowtail=odiamond」を指定する. また条件文は「label」「headlabel」「taillabel」の値として指定する.
 * デフォルトフロー:制御フローと組み合わせて使用され、全ての制御フローの条件が満たされない場合に選択される. エッジ属性として「arrowtail=rcrowlvee」を指定する. (バックスラッシュの向きを逆転させたい場合には「arrowtail=lcrowrvee」)

＜DOT表記＞ 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]; }

アクティビティ
角が丸い長方形を表現するため、ノード属性「shape=box, style=rounded」を指定する. ラベルを変更する場合には「label」の値として指定する.

＜DOT表記＞ digraph G { rankdir=LR;

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

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

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

A1 -> A2 -> A3 ; }

全ノードのデフォルト値を変更する場合は、予約語「node」により設定する.

＜DOT表記＞ digraph G { rankdir=LR; node [shape=box, style=rounded];

A1 ; A2 [label=""]; A3 [label="申請"];

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

A1 ; A2 [label=""]; A3 [label="申請"];

A1 -> A2 -> A3 ; }

イベント
「ラベルの無い小さめの円」を表現するため、ノード属性を「label="", shape=circle, width=0.3」と指定する(デフォルトのwidthは0.75). 終了イベントは太線円にするため、加えて「style=bold」を指定する.

＜DOT表記＞ 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="申請"];

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="申請"];

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

スイムレーン
グラフの中にスイムレーン（サブグラフ）を作るために「subgraph clusterXXX」を記述する. （subgraphの名前の最初にclusterが付く. サブグラフのクラスタ機能と言う）. またスイムレーンのパーティシパント(参加者/関与システム)を記述すべく「label="marketing@company.com";」、また左寄せにすべく「labeljust=l;」を指定する.

＜DOT表記＞ 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:文書作成"]; A2 [label="A2:修正確認"];

AS -> A1; A1 -> A2 [style=invis]; // 不可視のエッジを定義し、AS、A1、A2、AEが水平に並ぶようにする A2 -> AE; }

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

B1 [label="B1:文書確認"]; B2 [label="B2:コメント"];

B1 -> B2; }

A1 -> B1; // スイムレーンをまたぐシーケンスフローはクラスタ定義の外に書く 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:文書作成"]; A2 [label="A2:修正確認"];

AS -> A1; A1 -> A2 [style=invis]; // 不可視のエッジを定義し、AS、A1、A2、AEが直線に並ぶようにする A2 -> AE; }

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

B1 [label="B1:文書確認"]; B2 [label="B2:コメント"];

B1 -> B2; }

A1 -> B1; // スイムレーンをまたぐシーケンスフローはクラスタ定義の外に書く B2 -> A2;

}

なお、sytle、color、fillcolor等の値を設定する事で「クラスタの外見」を変更する事も出来る. 更にトップレベルグラフでcompound属性をtrue に設定し、アクティビティ(ノード)とスイムレーン(クラスタ)を結ぶメッセージフロー(エッジ)を描くこともできる. （詳細は参考文献）

位置を揃える（invisエッジの追加）
原則としてアクティビティの配置は、左から右へ並べられる. しかし上記の例においては、A1とB1を同じX座標（同じランク）にしたいと思う. A1とB2の間に「張力を与える」事で、A1とB1を同じランクにする事ができる. なお、同じグラフ内(クラスタ内)のアクティビティであれば、「{rank=same; A1 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:文書作成"]; A2 [label="A2:修正確認"];

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

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

B1 [label="B1:文書確認"]; B2 [label="B2:コメント"];

B1 -> B2; }

A1 -> B1; B2 -> A2; A1 -> B2 [style=invis]; // ★不可視のエッジにより、A1とB2を近づける★

} ＜DOT表記＞ 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:文書作成"]; A2 [label="A2:修正確認"];

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

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

B1 [label="B1:文書確認"]; B2 [label="B2:コメント"];

B1 -> B2; }

A1 -> B1; B2 -> A2; A1 -> B2 [style=invis]; // ★不可視のエッジにより、A1とB2を近づける★

}

位置を揃える（張力の指定）
特定のアクティビティ「A1」「A2」「A3」を直線的に並べたい場合、分岐部分で“本線”たる「A1->A2」に「weight=10」の張力（重み）を指定する.

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]; //★張力「weight=10」により「A1->Ae」より「A1->A2」が直線的になる★ 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表記＞ 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]; //★張力「weight=10」により「A1->Ae」より「A1->A2」が直線的になる★ 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]; }

位置を揃える（ランクの指定）
サブグラフ「clusterA」内で、「Ae」と「A3」のX座標（ランク）を合わせるために「{rank=same Ae A3};」を指定する.

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}; // ★「Ae」と「A3」のランクを合わせる★ }

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表記＞ 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}; // ★「Ae」と「A3」のランクを合わせる★ }

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]; }

位置を揃える（最低距離の指定）
「Ae」から「終了イベント」に伸びるシーケンスフローに「minlen=2」を指定する事で、“ランク”を挿入する事ができる. 二つある終了イベントを並べる事ができる. （※二つの終了イベントに対して「ランクを揃える」を実行しても結果は同様）

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]; //★「minlen=2」(inch)により「AE1」と「Ae」の間に一定の距離が置かれる★ 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表記＞ 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]; //★「minlen=2」(inch)により「AE1」と「Ae」の間に一定の距離が置かれる★ 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]; }

フローの重なりを回避する（ポートの指定）
「A1」と「B1」が同じX座標にあって、かつ「A1→B1」と「B1→A1」の様な往復するシーケンスフローを書きたい場合、重なりを排除するために、どちらかのシーケンスフローのポート位置を「[tailport=sw,headport=nw];」(矢先が南西、矢尻が北西)の様に指定する必要がある（「n、nw、w、sw、s、se、e、ne」デフォルトは「center」）. （ただしランクをずらす方が綺麗に見える） 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表記＞ 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]; } ランクをずらした例　（「不可視のエッジ（B1 -> AE [style=invis, weight=10];）」を追加） 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]; }

フローを逆行させる（dir属性の変更）
原則として、アクティビティやイベント（ノード）は、シーケンスフローが全て右向きになる様に配置される. あえて左向きのシーケンスフローを描きたい場合には「[dir=back]」を指定する. （以下の例では、[labelfloat=true]を設定し、シーケンスフローとラベルの重なりを許可している） 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]; //★フローの逆行指定★ }

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表記＞ 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]; //★フローの逆行指定★ }

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]; }

グラフ全体のサイズを指定する
プロセスダイアグラムは横方向に長くなりがちであるが、画面の都合上、５～７ランク程度に収めたい. （文字列も改行「\n」を多用し横方向に長くならない様に努めたい）. やむを得ずダイアグラムが大きくなる場合には「[size="10,5"]」の様にグラフサイズの最大値を指定し、全体を縮尺する事が出来る. (横方向の最大値は10インチを推奨する). 以下、サイズ制限をしたケースと、していないケースを例示する. 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表記＞ 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; }

作図雛型
描画方法の例が多用されている雛型. （BPMN図としては成立していない）

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]

}

参考文献

 * Graphviz - Graph Visualization Software　本家サイト(英文)
 * dot User's Manual　マニュアル(January 26, 2006)(PDF;40p)(英文)