Graphviz
思いました。 gvprプログラムに任せることでbashかcmdかなんてことはあまり気にしなくて済むではないか、と。 Graphvizで閉じる方針もここまでくるともう何だか無理矢理くさい。 gvpr "BEGIN{int i;for(i=0;i<4;i++)system(sprintf('gvpr -cf next_gen.g gli…
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が生成したものを一旦ファイルに落とし、 テキストエデ…
Blinkerばかりで飽きたので別のパターンにしたい。 が、その前に、第0世代のDOTファイルのエッジ群をいちいち手で構成するのはさすがに面倒なので、 以前言及したように、メッシュサイズを与えるとエッジ構成を自動生成するプログラムを作成する。 その生成…
さらにデザインをリファインしてみる。 pos属性を与えることでノード位置が固定されているので、 ノード名を表示して確認する必要もないだろう。 また、エッジも明示する必要もあまり感じない。 この辺りを考慮することでもっと図をコンパクトにする。 gvpr …
どうも斜めになっているのが少し気になる。 ノード名がメッシュ上での座標としているので、これを利用してノードに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);…
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これらのグ…
blinker_0.gvを視覚化してみる。 dot -Gsize=8 -Tpng -oblinker_0.png blinker_0.gvサイズ指定をしないとちょっと大きいのでデフォルトよりも少し小さ目で出力した。 このレイアウトはあまりおいしくない。 ということでdotでなくneatoを使う。 gvpr -c "N[a…
前述のテストデータでは単純すぎるので、 それより少しだけ複雑な、でも分かりやすいものを作成してみる。 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…
題記そのままの事柄についてである。 一部のノードに対して属性aが設定されたグラフを次のようなgvprプログラムに与える。 $ gvpr " > N [a] { > print('[a] ', name, ' has attrib a=', a); > } > > N [!a] { > print('[!a] ', name, ' doesn\'t have attri…
現世代のグラフを入力とし次世代のグラフを出力とするフィルタを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…
人生でなく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 …
以降の話でのDOTファイルの文字エンコードはUTF-8になっていることが前提。linux*1でやっている分には日本語でも全然問題ないのだが、 success1.gv (UTF-8) digraph 魚 { rankdir = LR; イナダ -> ハマチ -> 鰤; } のようなDOTをWindows上のdotコマンドで画…
これはGraphvizというよりもはてなダイアリーの話題になる。 スーパーpre記法でシンタックスハイライトを行える構文タイプのリストの中にdotがあるのを見つけた。 このdotはGraphvizのDOT形式のことなのだろうか? digraph mv { "meta variable" -> { foo; h…
サブグラフを一個ずつクローンするくらいならグラフそのものをクローンしてしまえばいいのではと思った。 $ gvpr "BEG_G { graph_t g = graph(name, 'U'); clone(g, $); write(g); }" shiritori.gv graph kobutanukituneko { subgraph kobutanukituneko { pi…
まだ問題が残っていた。 mv.gv digraph mv { "meta variable" -> { foo; hoge; piyo; }; ham; style = filled; color = gray; subgraph cluster1 { foo -> bar -> zot; baz; } subgraph cluster2 { hoge -> hogehoge; } }のようにサブグラフが存在する場合、…
前掲の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…
有向グラフ 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…
Pasacalの三角形を介することなくSierpinskiの三角形を直接生成するなら、 二項係数そのものの値は不要であり、前段が偶数か奇数かさえ記録しておけば済む。 sierpinski_g.g BEGIN { if (ARGC != 1) { print("usage: gvpr -fsierpinski_g.g -a <step>"); exit(0); </step>…
60段目までPascalの三角形の値を計算すると、 そこに現れる最大値は60段目の中央の値=118264581564861424である。 実際にpascal3.gが生成したグラフ中でname属性が"60_30"のノードのlabel属性は、 $ gvpr -fpascal3.g -a60 | gvpr "N [name == '60_30'] { pr…
全てのノードのlabel属性を統一することで歪みが無くなったのだが、 label = "_";を label = "";のように空文字にしてしまってはいけない。 これは対象ノードのlabel属性自身の抹消を意味しており、 name属性がノードの表示値として使用されるようになる。 …
歪みの原因が分かった。 ノードはsierpinski.gによって不可視になったり塗り潰されたりするだけで、 label属性自体は生きているため下の方ほどlabelが長くなっているのだった。 つまりノードの大きさが場所によって異なることが原因なので単にlabel属性を同…
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"; }…
示したgvprプログラムが出力しているグラフは無向グラフだが、dotコマンドを使って画像化していた。 マニュアルによればdotは主に有向グラフの描画用ということになっている。 もちろん無向グラフでもpascal.pngのようにまさに欲しいものを得ることもできる…
create()を定義する前のpascal2.gの形に引きずられてうっかりしていたが、 ノードを作成する部分はもっと簡単にできるのだった。 q[0], q[i]の作成部分はforループ本体と全く同じ形なので、 ...snip for (i = 0; i <= step; i++) { # create nodes in i-th s…
man 1 gvprやPDF化された文書などに書かれていないように思うが、 gvprではユーザ定義関数を定義することができる。 pascal2.gでノードを作成する部分がまとめられそうなので関数化してみる。 pascal3.g BEGIN { if (ARGC != 1) { print("usage: gvpr -fpasc…
さて、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の三角形を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>…
collatz11.gやcollatz12.gでは入力のグラフデータが不要にも関わらず、 gvprの入力ファイルにナルデバイスを指定しなければならなかった。 実はEND節に書いてあるコードをBEGIN節に書けば済む話だった。 END節に書いてしまうのはどうも出力だからEND節やEND_…
collatz11.gの結果からこのグラフが自己相似的であるような感じがする。 ノード8まで操作回数10回以内で到達しうるノードで構成されたこのレベルでは、 ノード16で合流する左右二つの経路群は合同であるように思える。 しかし、これを例えば操作回数15回以内…