LaTeXでグラフ描画
数学ガール最新作、テトラちゃんとハーモニック・ナンバーに出てきた、反比例・調和数・対数関数のグラフを描くLaTeXのソースを生成するRubyスクリプトを作ります。
まずは、p.21, p.22に出てきた反比例と調和数のグラフ(make_invx_graph.rb)。
#!/usr/local/bin/ruby -Ks def output(lower) scale = 1 width = 15 height = 80.0 limit = 7.0 puts '% y = 1/x' print <<'EOD' \begin{figure}[h] \begin{center} \unitlength=1mm \begin{picture}(100,100)(0,0) \thinlines \put(0,0){\vector(1,0){100}}\put(101,0){$x$} \put(0,0){\vector(0,1){100}}\put(0,101){$y$} EOD puts '% curve : 1/x' x = 1.0 index = 0 while x < limit if !lower && (x + 1.0) >= limit break; end px = format("%.2f", if lower then (x - 1) * width else x * width end) py = format("%.2f", height * (1 / x)) if index % scale == 0 print "\\put(#{px},#{py}){\\circle*{1.0}}" print "\n" end index += 1 x += 0.1 end puts '% rectangle : 1/x' x = 1.0 y = 0.0 index = 0 print "\\put(#{0-1},#{-5}){$#{0}$}" while x < limit y = 1 / x px = format("%.2f", x * width) py = format("%.2f", y * height) px_ = format("%.2f", (x-1) * width) # 数値 sy = format("\\frac{1}{%d}", x) psx = format("%.2f", x * width + 1.0) psy = format("%.2f", y * height + 3.0) if index % scale == 0 print "\\put(#{px_},#{py}){\\line(1,0){#{width}}}" print "\\put(#{px},#{py}){\\circle*{1}}" print "\\put(#{px},0){\\line(0,1){#{py}}}" print "\\put(#{psx},#{psy}){$#{sy}$}" print "\\put(#{x * width - 1},#{-5}){$#{x.to_i}$}" print "\n" end index += 1 x += 1.0 end print <<"EOD" \\end{picture} \\end{center} \\caption{#{if lower then "lower" else "upper" end}} \\end{figure} \\newpage EOD end # Preamble. puts <<'EOD' \documentclass{jarticle} \usepackage{euler} \begin{document} EOD output(false) output(true) # Postamble. print <<'EOD' \end{document} EOD
それから、p.23, p.24, p.25に出てきた対数関数と調和数のグラフ(make_log_graph.rb)。
#!/usr/local/bin/ruby -Ks def output(scale) width = 15.0 / scale.to_f height = 40.0 / (1 + Math.log(scale.to_f) / 2.0) limit = 6.5 * scale.to_f STDERR.puts "scale = #{scale}" puts "\\section*{scale = #{scale}}" print <<'EOD' % y = log(x + 1) \begin{figure}[h] \begin{center} \unitlength=1mm \begin{picture}(100,100)(0,0) \thinlines \put(0,0){\vector(1,0){100}}\put(101,0){$x$} \put(0,0){\vector(0,1){100}}\put(0,101){$y$} EOD puts '% curve : log(x + 1)' x = 0.0 index = 0 while x < limit px = format("%.2f", x * width) py = format("%.2f", height * Math.log(x + 1.0)) if index % scale == 0 puts "\\put(#{px},#{py}){\\circle*{1.0}}" end index += 1 x += 0.05 end puts '% rectangle : sum 1/x' x = 1.0 y = 0.0 index = 0 puts "\\put(#{0-1},#{-5}){$#{0}$}" if scale == 1 while x < limit y += 1 / x px = format("%.2f", x * width) py = format("%.2f", y * height) px_ = format("%.2f", (x-1) * width) # numeric value sy = format("%.4f", y) psx = format("%.2f", x * width + 1.0) psy = format("%.2f", y * height + 8.0) # diff sdy = format("%.4f", y - Math.log(x + 1.0)) pdx = format("%.2f", x * width + 1.0) pdy = format("%.2f", y * height + 4.0) if index % scale == 0 print "\\put(#{px},#{py}){\\circle*{1}}" print "\\put(#{px},0){\\line(0,1){#{py}}}" print "\\put(#{psx},#{psy}){$#{sy}$}" print "\\put(#{pdx},#{pdy}){($#{sdy}$)}" print "\\put(#{x * width - 1},#{-5}){$#{x.to_i}$}" print "\n" end index += 1 x += 1.0 end print <<"EOD" \\end{picture} \\end{center} \\caption{scale = #{scale}} \\end{figure} \\newpage EOD end # Preamble. puts <<'EOD' \documentclass{jarticle} \usepackage{euler} \begin{document} EOD [1, 1000, 10000].each do |scale| output(scale) end # Postamble. print <<'EOD' \end{document} EOD
これらから実際にグラフを生成するには、たとえば以下のようにします。RubyとLaTeXがインストールされている必要があります。
ruby make_invx_graph.rb > 1.tex platex 1 dvipdfm 1 ruby make_log_graph.rb > 2.tex platex 2 dvipdfm 2
これを実行すると、1.pdf, 2.pdfというPDFファイルができます。
注意:ここではpicture環境を使って、ある意味「無理矢理」グラフを描いています。今回は時間がなかったので自分で作ってしまいましたが、本来は、LaTeX関連でグラフを作るための適切なパッケージやツールを探して使うべきでしょう。