Graphviz

gvprでシェルスクリプト代わり

思いました。 gvprプログラムに任せることでbashかcmdかなんてことはあまり気にしなくて済むではないか、と。 Graphvizで閉じる方針もここまでくるともう何だか無理矢理くさい。 gvpr "BEGIN{int i;for(i=0;i<4;i++)system(sprintf('gvpr -cf next_gen.g gli…

ライフゲーム #9

Gliderパターンの第0世代を作ってみる。 gvpr -f gen_mesh.g -a "6 6" | gvpr -c "N{if (name=='n2_2'||name=='n2_3'||name=='n3_2'||name=='n3_4'||name=='n4_2'){alive=1;}}" > glider_0.gvgen_mesh.gが生成したものを一旦ファイルに落とし、 テキストエデ…

ライフゲーム #8

Blinkerばかりで飽きたので別のパターンにしたい。 が、その前に、第0世代のDOTファイルのエッジ群をいちいち手で構成するのはさすがに面倒なので、 以前言及したように、メッシュサイズを与えるとエッジ構成を自動生成するプログラムを作成する。 その生成…

ライフゲーム #7

さらにデザインをリファインしてみる。 pos属性を与えることでノード位置が固定されているので、 ノード名を表示して確認する必要もないだろう。 また、エッジも明示する必要もあまり感じない。 この辺りを考慮することでもっと図をコンパクトにする。 gvpr …

ライフゲーム #6

どうも斜めになっているのが少し気になる。 ノード名がメッシュ上での座標としているので、これを利用してノードにpos属性を与えてみる。 gvpr -c -f vis_alive.g blinker_0.gv | gvpr -c "N{int x,y;sscanf(name,'n%d_%d',&x,&y);pos=sprintf('%d,%d',x,y);…

ライフゲーム #5

blinker_0.gvがどう遷移していくか見てみる。 next_gen.gで第0世代(blinker_0.gv)から始めて第1、第2世代のグラフを順番に生成する。 gvpr -c -f next_gen.g -o blinker_1.gv blinker_0.gv gvpr -c -f next_gen.g -o blinker_2.gv blinker_1.gvこれらのグ…

ライフゲーム #4

blinker_0.gvを視覚化してみる。 dot -Gsize=8 -Tpng -oblinker_0.png blinker_0.gvサイズ指定をしないとちょっと大きいのでデフォルトよりも少し小さ目で出力した。 このレイアウトはあまりおいしくない。 ということでdotでなくneatoを使う。 gvpr -c "N[a…

ライフゲーム #3

前述のテストデータでは単純すぎるので、 それより少しだけ複雑な、でも分かりやすいものを作成してみる。 blinker_0.gv graph { n0_0 -- n0_1 -- n0_2 -- n0_3 -- n0_4; n1_0 -- n1_1 -- n1_2 -- n1_3 -- n1_4; n2_0 -- n2_1 -- n2_2 -- n2_3 -- n2_4; n3_0…

gvprプログラムのN節の述部の!

題記そのままの事柄についてである。 一部のノードに対して属性aが設定されたグラフを次のようなgvprプログラムに与える。 $ gvpr " > N [a] { > print('[a] ', name, ' has attrib a=', a); > } > > N [!a] { > print('[!a] ', name, ' doesn\'t have attri…

ライフゲーム #2

現世代のグラフを入力とし次世代のグラフを出力とするフィルタをgvprプログラムで書いてみる。 next_gen.g BEGIN { int count_alive(node_t n) { int count = 0; edge_t e; for (e = fstedge(n); e != NULL; e = nxtedge(e, n)) { if ((e.tail == n && e.hea…

ライフゲーム #1

人生でなくConwayの方のゲーム。 グラフ的見方からすると次のように表現できる。 時間とともに変化する真偽値を属性として持つノードから成るグラフを考える。 何らかの規則で標本化された各時点の真偽値のみで、その変化を完全に記述できるとする。 ある標…

クリスマスイブ

christmas_star.gv graph tree_topper_star { graph [bgcolor=darkgreen]; node [shape=point, height=0.01, width=0.01, color=yellow]; edge [style=bold, color=yellow]; 1 [pos="2,2"]; 2 [pos="1,0"]; 3 [pos="4,1"]; 4 [pos="0,1"]; 5 [pos="3,0"]; 1 …

Windowsにおけるノードの日本語ラベルの使用

以降の話でのDOTファイルの文字エンコードはUTF-8になっていることが前提。linux*1でやっている分には日本語でも全然問題ないのだが、 success1.gv (UTF-8) digraph 魚 { rankdir = LR; イナダ -> ハマチ -> 鰤; } のようなDOTをWindows上のdotコマンドで画…

スーパーpre記法でのdotタイプ

これはGraphvizというよりもはてなダイアリーの話題になる。 スーパーpre記法でシンタックスハイライトを行える構文タイプのリストの中にdotがあるのを見つけた。 このdotはGraphvizのDOT形式のことなのだろうか? digraph mv { "meta variable" -> { foo; h…

有向グラフと無向グラフの変換 #4

サブグラフを一個ずつクローンするくらいならグラフそのものをクローンしてしまえばいいのではと思った。 $ gvpr "BEG_G { graph_t g = graph(name, 'U'); clone(g, $); write(g); }" shiritori.gv graph kobutanukituneko { subgraph kobutanukituneko { pi…

有向グラフと無向グラフの変換 #3

まだ問題が残っていた。 mv.gv digraph mv { "meta variable" -> { foo; hoge; piyo; }; ham; style = filled; color = gray; subgraph cluster1 { foo -> bar -> zot; baz; } subgraph cluster2 { hoge -> hogehoge; } }のようにサブグラフが存在する場合、…

有向グラフと無向グラフの変換 #2

前掲のgvprプログラムではうまく変換できないDOTデータがあった。 $ gvpr -c "BEG_G { node($, 'tubeworm'); }" shiritori.gv | tee fellows.gv digraph kobutanukituneko { piglet -> "raccoon dog"; "raccoon dog" -> fox; fox -> cat; cat -> piglet; tub…

有向グラフと無向グラフの変換 #1

有向グラフ shiritori.gv digraph kobutanukituneko { piglet -> "raccoon dog" -> fox -> cat -> piglet; }を無向グラフに変換する。 $ gvpr "BEG_G { graph_t g = graph(name, 'U'); } E { clone(g, $); } END_G { \$O = g; }" shiritori.gv graph kobutan…

Pascalの三角形 #10

Pasacalの三角形を介することなくSierpinskiの三角形を直接生成するなら、 二項係数そのものの値は不要であり、前段が偶数か奇数かさえ記録しておけば済む。 sierpinski_g.g BEGIN { if (ARGC != 1) { print("usage: gvpr -fsierpinski_g.g -a <step>"); exit(0); </step>…

Pascalの三角形 #9

60段目までPascalの三角形の値を計算すると、 そこに現れる最大値は60段目の中央の値=118264581564861424である。 実際にpascal3.gが生成したグラフ中でname属性が"60_30"のノードのlabel属性は、 $ gvpr -fpascal3.g -a60 | gvpr "N [name == '60_30'] { pr…

Pascalの三角形 #8

全てのノードのlabel属性を統一することで歪みが無くなったのだが、 label = "_";を label = "";のように空文字にしてしまってはいけない。 これは対象ノードのlabel属性自身の抹消を意味しており、 name属性がノードの表示値として使用されるようになる。 …

Pascalの三角形 #7

歪みの原因が分かった。 ノードはsierpinski.gによって不可視になったり塗り潰されたりするだけで、 label属性自体は生きているため下の方ほどlabelが長くなっているのだった。 つまりノードの大きさが場所によって異なることが原因なので単にlabel属性を同…

Pascalの三角形 #6

Pascalの三角形のグラフをSierpinskiの三角形*1っぽいものに変換してみる。 sierpinski.g BEG_G { size = "5"; ratio = "auto"; } N { if (label % 2 == 0) { style = "invis"; } else { style = "filled"; fillcolor = "black"; } } E { style = "invis"; }…

Pascalの三角形 #5

示したgvprプログラムが出力しているグラフは無向グラフだが、dotコマンドを使って画像化していた。 マニュアルによればdotは主に有向グラフの描画用ということになっている。 もちろん無向グラフでもpascal.pngのようにまさに欲しいものを得ることもできる…

Pascalの三角形 #4

create()を定義する前のpascal2.gの形に引きずられてうっかりしていたが、 ノードを作成する部分はもっと簡単にできるのだった。 q[0], q[i]の作成部分はforループ本体と全く同じ形なので、 ...snip for (i = 0; i <= step; i++) { # create nodes in i-th s…

Pascalの三角形 #3

man 1 gvprやPDF化された文書などに書かれていないように思うが、 gvprではユーザ定義関数を定義することができる。 pascal2.gでノードを作成する部分がまとめられそうなので関数化してみる。 pascal3.g BEGIN { if (ARGC != 1) { print("usage: gvpr -fpasc…

Pascalの三角形 #2

さて、pascal1.gを元にして、DOT言語で表したグラフとして出力するコードに変更する。 pascal2.g BEGIN { if (ARGC != 1) { print("usage: gvpr -fpascal2.g -a <step>"); exit(0); } int step = ARGV[0]; graph_t g = graph("pascal_triangle", "U"); node_t p[],</step>…

Pascalの三角形 #1

二項係数の列、いわゆるPascalの三角形をgvprで計算する。 pascal1.g BEGIN { if (ARGC != 1) { print("usage: gvpr -fpascal1.g -a <step>"); exit(0); } int step = ARGV[0]; int p[], q[]; int i, j; for (i = 0; i <= step; i++) { # calc i-th step for (j = </step>…

gvprで不要な入力ファイルの指定そのものを不要にする

collatz11.gやcollatz12.gでは入力のグラフデータが不要にも関わらず、 gvprの入力ファイルにナルデバイスを指定しなければならなかった。 実はEND節に書いてあるコードをBEGIN節に書けば済む話だった。 END節に書いてしまうのはどうも出力だからEND節やEND_…

Collatz問題 #20

collatz11.gの結果からこのグラフが自己相似的であるような感じがする。 ノード8まで操作回数10回以内で到達しうるノードで構成されたこのレベルでは、 ノード16で合流する左右二つの経路群は合同であるように思える。 しかし、これを例えば操作回数15回以内…