[tex: ]

C言語とGNU plot

学部時代に教わったC言語GNU plotのスキルのみで、このAI時代の荒波に立ち向かおうと奮闘しているわけですが、、、

 

 C言語による計算

C言語macのパソコンなら開封した瞬間から使えるようです。C言語の基礎的なことはオンラインでも学べます。例えば

なんか東大の講座https://www.cspp.cc.u-tokyo.ac.jp/ohshima/201509c/lecture201509c_1.pdf

および https://www.cspp.cc.u-tokyo.ac.jp/ohshima/201509c/lecture201509c_2.pdf

誰かのページ http://www.nmn.jp/~hidai/c/

別の人のページ https://tcs.c.titech.ac.jp/csbook/c_lang/index.html

 

当初はPARI/GPをC言語で使いたかったのですが、何をどうすればPARIが動き始めるのかわからず挫折しました。パッケージを読み込む呪文が

#include<pari/pari.h>

であることだけはわかりました。PARI/GPを使いたかったのは、数体の整数環での素イデアル分解を計算して欲しかったからです。仕方ないのでPARIが使えるようになるまでは、自前で済ませることにしました。$\mathbb Z[i]$などの具体的な環での計算を、一から書くのです。(たとえば、Gauss整数$a+bi$を2個の整数からなる配列{a,b}で表して、積の計算の仕方を具体的に書いて、素元をリストアップして、与えられた元の素因数分解をサーチするプログラムを書いて・・・。)

今回図らず苦労したのは、割り算のあまりを求める関数 a%b において、余りを負の値として出す場合もあるということです。たとえば -1%2 は -1 になるようです。何故 1 でないのか。これを知らなかったせいで、ある種の割り算が割り切れているか否かの判定を、正しく行えていなかったことに、かなり後の段階で気付きました。

それから、アホなことですが、$\mathbb Z^2$の元から$\mathbb Z^2$の元を作る関数$f(a,b)$を利用して(a,b)の値を更新する箇所で

a=f(a,b)[0];

b=f(a,b)[1];

とする痛恨のミスを犯していることも、予想外の挙動としばらく格闘した後で、ようやく気付きました。当たり前の事ですが、これでは2行目で新しいaを使ってしまい、bが正しく計算できていません。現在はダミー変数c, dを用いて(スマートな方法でないのはわかっていますが)

c=f(a,b)[0];

d=f(a,b)[1];

a=c;

b=d;

のようにやりくりしています。

 

GNU plotによる可視化

C言語で計算ができたら、次のような具合で .dat ファイルを吐き出して、

./a.out -> result.dat

これを別のアプリケーションに放り込むことで可視化しましょう。ここで拡張子 .dat は .txt でも構いません。(また、データファイルを出力するにも、-> を使うよりはfprintfを使った方がスマートです。ターミナルの方にはprintfで作業の途中経過を表示させられるようになるので。)

プロットについては、この記事ではGNU plotによる方法を説明します。

GNU plot をインストールするには(一例)、Homebrewをインストールした状態でターミナルで

brew install gnuplot

を実行します。

 

gnuplot の基本的な使い方としてはターミナルで

gnuplot

を実行してgnuplotを立ち上げたあと、

gnuplot> plot "yourfile.dat"

を実行します。yourfile.dat は実際にはあなたのファイルの名前を入れてください。3次元データならsplotというコマンドを使うようです。データの中身は

x y z

a b c

u v w

...

のように用意するのが標準です。

出来上がりのグラフの仕様を予め指定するために、「set ...」系の命令がたくさん存在するようです。

 

 

GNU plot で2次元平面上の関数を色で表現するには、次のリンクに従って、http://taichasooo.hatenablog.jp/entry/2016/11/25/230150

gnuplot> set pm3d map

(gnuplot> set palette gray)

gnuplot> splot "yourfile.dat"

をすれば良いです。

 

そうして出来上がったのが次の図となります。

f:id:motivichomotopy:20201028114858p:plain

問題発覚

メデタシと思いましたが、pm3dでは各点の値を色に変換してプロットするのではなく、四角形の4角の平均値を色にしていることがわかりました。http://www.gnuplot.info/docs_4.6/gnuplot-ja.pdf

たしかに普通は連続関数を扱うシーンが多いでしょうから、気を利かせているつもりなのでしょうね。

 

マシな策

・・・結局、次のような設定でプロットさせることにしました。

gnuplot> set size 1,1

(これは縦横比をキッチリ1:1にしています)

gnuplot> set palette gray

(これは色をグレイスケールにしています。)

gnuplot> plot "yourfile.txt" using 1:2:3 palette ps 0.4 pt 5

(これはオプションをいくつか付けてファイルをプロットさせています。using 1:2:3 は、与えたファイルの第1、2列の座標に点をプロットすべきこと、及び、第3列の数値をpaletteに照らして点を色付けすべきことを指示しています。

ps 0.4 はpointsizeが0.4ということです。pt 5はpointtypeが5番ということです。5番は正方形です。番号と点の形の対応は、「gnuplot point type」で画像検索するとすぐ見つかります。)

 

根本的な解決策

さっきの策では、データ量が変わるとpoint sizeを調整せねばなりません。また、正方形どうしがへりでぴったりと接してくれる訳ではありません。

根本的な解決は、描画スタイルimageを使うことのように思われます。ただし、これを使おうと思ったら、データの準備の仕方を変えなくてはなりません。今までは

x座標 y座標 値

と並べていたものを、値のみを正しい位置に並べたデータ

値 値 値 値

値 値 値 値

値 値 値 値

値 値 値 値

としなければなりません(上下は反転されます)。そもそもスタイルimage自体が、ピクセル毎の色番号を並べたものを実際の画像にするものだからです。

 

・・・これやってみましたが、プロットしたい点が多すぎると、厳密なプロットはしてくれないみたいです。画像を作るためのスタイルだから仕方ありませんかね。

f:id:motivichomotopy:20201030120744p:plain



所詮は、図とはそもそも、生データを可視化してわかりやすくするためのものなので、生データを各点レベルで厳密に表した図などというものを作ろう(しかも巨大なデータサイズで)という意図自体が的外れなんだという気がしてきました。