GRINEditを使ってソースコードの可視化
可視化する対象のコードは、 竹迫さんのTAKESAKO @ Yet another Cybozu Labs: Brainf*ckで100までの素数を列挙してみるテストと、奥さんのKazuho@Cybozu Labs: brainf*ck でマジメに素数探索。
まず、竹迫さんのコードの全体像。
そして一部拡大した物がこれ。 各頂点が1つの命令で、太い辺が命令の隣接関係、 細い辺が括弧の対応関係です。+が赤、-が青、.が緑になっています。
竹迫さんのコードは実は数字を作って表示するだけのコードなので、 大局的な構造がありません。 大まかに見ると「小さなループが所々にある1本の紐」です。 可視化する際も、頂点を徐々にy座標を増やしながら作るだけでこんな風に ほとんどもつれずに表示されました。
いっぽう奥さんのコードはこんな感じ。
ぱっとみで、竹迫さんのコードより緑の頂点が少ないことに気づきます。
一部拡大。
括弧のネストがあるために、複雑な構造をしています。
少し引っ張って見たのがこちら。 赤い頂点(+)が、かなり局在していることがわかります。
赤丸で囲んだ部分を拡大したのが次の図。
実はこの部分にしか緑の頂点がありません。 つまりこの固まりが「表示ルーチン」に相当する物だと考えられます。
= コードはPythonでXML-RPCを使って個々の頂点を投げる物で、 コード中に直接貼り付けたBrainf*ckのコードを除けば 50行程度。 GRINEditの次のリリースの時にでもサンプルの中に入れます。
思ったこと。 反発力を使った整形は、 こういう「長いヒモ」状の構造を整形するのにはあまりむいていません。 また、かりに十分時間をかけて整形させたとして、竹迫さんのコードのうねうね曲がっているヒモが、 一直線に伸びたら、それは本当に見やすい可視化なのだろうか?と言われると多少疑問です。 適切に折りたたまれている方が見やすいです。
竹迫さんのコードを適切に折りたたんで可視化するのは難しくないですね。 例えば20個おきの頂点に「左右に引っ張る力」を足してやれば、自然と折りたたまれるはずです。
問題は奥さんのコードの方です。 大局的な構造があるために、竹迫さんのコードを可視化する際に使った 「頂点の初期位置を順番にずらす」という方法ではきれいになりません。 かといって今の手動整形では頂点の移動しかできないので、つまんで引っ張っても 「隣の頂点が半分くらいの速度で付いてくる+ その隣の頂点がさらに半分の速度で付いてくる+ その隣の頂点がさらに半分の速度で付いてくる…」 となって、いまいちです。
これは今まで考えなかったわけではないのですけど、 いい「整形しづらさを感じるグラフ」が手元になかったので対策していませんでした。 これに対処する方法は、一つは前処理です。 ある種の性質を持っているグラフには、 見やすく表示することができる「静的なレイアウト」があります。 例えば今回の場合は平面グラフなので、 辺が交叉しないように平面に埋め込むアルゴリズムがあります。 実はそういう静的な処理を動的な整形の前に挟む機能がすでにGRINEditに実装されています。 今は「非連結グラフを連結成分ごとにばらして配置する」っていうシンプルな物だけですけども、 「平面グラフを交叉しないように埋め込む」っていう前処理は汎用性も高いので 用意しておくのもいいですね。
もう一つは、よりリッチな動的整形手法を作ること。 こちらの方がどちらかというと萌えます。 例えば頂点でマウスダウンした際に、 その頂点が紐の一部であることの判定や、 紐を構成する頂点を取得することは難しくありません。 そこで紐をドラッグ中だけ一時的に剛体化してしまうこともできます。 使い勝手は実装して試してみないとわかりませんが。
他のアイデア: 辺の間に角度バネをつけると、 反発力が届きにくいような長い構造でもきれいに伸びる、かも。 紐状の部分を一時的に1つの頂点に置き換えてしまう。 ソースコードのフォールディングみたいな感じ。 必要なときにダブルクリックすれば元通りに展開されるとか。 n本の辺からなるパスを自然長nの辺で置き換えてみると、 すばやく大局的な整形が行われる、かも。