第1章 Mathematicamlab/_src/sc251/mathematica82cc8aee...第1章 Mathematicaの基本...

127
第1章 Mathematicaの基本 Mathematica れた 一つ げる する ,グラフィック あろう.データを してそ から ステップに めるこ っているこ ,一 たり,また プログラムを けれ かった.Mathematica 易に くこ き,それによって める. データ 扱い る. Mathematicaバージョン5.0 づいている ,それより以 バージョンを っている るこ がある 意されたい. する パッケージをま めて しておく. パッケージ り, パッケージにある にそ パッケージをロードしておか けれ い. パッケージを う. << Graphics`Graphics3D` H3 グラフックスL << LinearAlgebra`Orthogonalization` HProjectionL << Graphics`Arrow` HL << Miscellaneous`WorldNames` HL << Miscellaneous`CityData` Hする L << Graphics`Graphics` HグラフL .グラフィックスの表示方式 にグラフィクス して, あるい して よう メカニズム してい ていこう.インターフェースが れている Mathematica あるが,そ るために って して めて る. ちろんMathematicaったこ ある って Mathematica いこ すため ある. à ..式の表現方法と完全形式 プログラム して し,コード あるい して プログラム マニュアルを きる.た ,sin めたい Sin@π ê 3D êê N 0.866025 ように くようにキーボードから するだけ む.こ ように, いた 位をセル(右 にある右括 ついた ,括 意) いう. した ちに きるように,セルが セル ってこ を意 する.つまり, ようにセルを わってから,Enterキーまた Shift+Enterキーを いう)する.あるい ,メニューにある[カーネル][ ][セルを ][カーネル]メニュー [ ]サブメニ ューを き,[セルを ]する) する. しに,メニューにある[セル][セル プロパティ]

Transcript of 第1章 Mathematicamlab/_src/sc251/mathematica82cc8aee...第1章 Mathematicaの基本...

  • 第1章 Mathematicaの基本 Mathematicaの優れた機能の中で一つとり上げるとするならば,グラフィック機能であろう.データを表示してその結果から思考過程を次のステップに進めることは日々行っていることで,一昔前なら紙に書いたり,また面倒なプログラムを作成しなければならなかった.Mathematicaでは容易に図を描くことができ,それによって思考過程の大幅な高効率化が望める.本章ではデータの扱いなど,基本的な事項を述べる.尚,本書はMathematicaバージョン5.0に基づいているので,それより以前のバージョンを使っている場合は関数の定義,計算方法など多少異なることがあるので注意されたい. 各章の冒頭で,利用する標準パッケージをまとめて記しておく.標準パッケージは組込み関数とは異なり,標準パッケージにある関数を使う前にそのパッケージをロードしておかなければならない.本章では以下に示す標準パッケージを使う.

  • [評価可能なセル]のチェックをはずすと,括弧の右上の記号が変わあり,何も起こらないことが分かる.ちなみに,この文章を書いているこのセルは,評価可能なセルのチェックが外れている.通常自動的に行われているが,手動ではセルをハイライト(マウスでポインタをセルに合せてクリックすると,セルの右括弧が黒くなる)してから,[書式]→[スタイル]で[Text](または,キーAlt+7を押す)に設定することによって行える. 上式のように最後に「//N」を付け加えた式,N[Sin[π/3]]と同じことで,詳細は後節で述べるが,数値に変換するためのコマンド(関数ともいう)である.これを取り去るとè!!!3 ë2となって,数値に変換されない(Sin[3.1]のよう場合は自動的に数値に変換される.実は,いちいちNを使わないで自動的に数値に変換するように$Postで変更できるが,これは本書では使わない).

     このように,シンボルNは特殊な目的に使われる.これ以外にも,Mathematicaでは多くの記号が特別な意味で使われるが,その意味を理解することがMathematicaを使いこなす早道である.たとえば,上の例では,[...]の代わりに(...)を用いて,Sin(π/3)としても計算されない.sin等のように,最初の文字が大文字になっている関数(コマンド)は組込み関数(組込みコマンド)と呼ばれ,C言語のような通常のプログラム言語と同様に,その使い方が予め決っている.三角関数のような初等関数,ベッセル関数のような特殊関数,後で見るように組込み関数として決められたグラフィックスの表示方法以外に,独自に工夫を凝らしたい場合やまた組込み関数を変更して使いたい場合も多々あるだろう.入門者はそのようなことまで立ち入ることはないだろうが,当然方策はある.Mathematicaは大変柔軟な構造をもっており,本書が目標にしているレベルに達したならば容易に実現できるようになる.

     実際に計算を実行するための方法は2種類あるが,通常はノートブックと呼ばれるこの画面から直接実行する.実行の仕方は先の述べたように,セルのどこかにポインタを置き,それから,EnterキーまたはShift+Enterキーを押す.普通はこのやり方である.もう一つの方法は,実際に計算を実行するカーネルをスタートメニューから起動するとコマンドプロンプトが開くので,コマンドラインに計算したい式をすべて文字列で入力する.あるいは,ドスプロンプトを開き,mathと入力しMathematicaを起動し,それから,コマンドラインから入力する.便利が悪いばかりか,グラフが文字列で表示されるのでは到底見られたものではない(グラフはどのように表されるか,実行して見てほしい.筆者が学生のころはこのようなグラフでも感激したものである). さて,Sin[π/3]に戻ろう.Sinは組込み関数で,π/3は変数である.Sin[π/3]は,変数がπ/3の時に評価した関数値を返す.関数の値を評価する方法として,これ以外に,

    Sin@Hπ ê3Lè!!!32

    あるいは,Hπ ê3L êê Sinè!!!32

    と記述することもできる.後者では,//Nと同じ使い方をした.Mathematicaは数式を評価するにもグラフ表示するにも異なる方法がいくつもあり,初めはどの方法を使えばよいのかと迷うところであるが,内部構造を知ると問題に応じて使い分けができるようになる.この記述方法では,@以降の記号が変数になるの

    で,ここでは(...)は重要である.つまり,Sin@π/3とすると,Sin@π( = 0)を先に計算しそれを3で割るので,結局0になってしまう.つまり,通常の数式のように,(...)は先にカッコ内の式を実行することを意味する.すると,

    Sin@HPrint@"sinHπê3Lの値は"D; π ê3LDsinHπê3Lの値は

    1

  • è!!!32

    がどのように印字しているのか理解できるだろう.つまり,まず(...)を実行することで,Print[...]でカッコ内の文字列"..."を印字してからsinHp ê 3Lを求める. Mathematicaの利便性の一端を見るため,複数の変数(あるいはデータともいう)に対してsinを計算する場合を考えよう.たとえば,

    Sin@8π, π ê6, π ê3

  • {Sin[a], Sin[b], Sin[c]}

    とすることでも分かる. 次に,Mathematicaで統一された式の表現を調べよう.Mathematicaではどのようなオブジェクトもすべて文字列だけで記述する統一された表現になっており,それを完全形式と呼んでいる.したがって,本来ならこの完全形式の形で入力するところを,上の例で見たような簡易な入力を可能とするInputFormを,さらにより分かり易い入力形式が使えるようにしたことで利便性を高めている.この完全形式は,Full-Formを用いることで,

    FullForm@Sin@8a, b, c

  • 入力形式 x2 + x y Sin@8a−1ê2, b

  • とする.ただし,{...}以外の括弧は用いてはならない.別の解釈がなされてしまいエラーがでる.{...}の中を眺めと,最初の式であるx2 + x yのFullFormは,Plus[Power[x,2],Times[x,y]]と表されていることが分かる.Power[x,2]はxの2乗をとってx2とすること意味し,Times[x,y]はxとyの積をとり,最後に,Plusは[...]内の要素を足し合せx2 + x yとしている.ただし,掛け算の順序が記述した通りにならないことに注意しよう.次に,2番目の式Sin@8a, b

  • となり,Length[1+2+3]は3でなく0を返す.理由は,Lengthを調べる前に,1 + 2 + 3 = 6を計算し,Length[6]=0となるからである.

    à 1.1.2 属性

     Sinの例から分かるように,1個の変数に値を評価するだけでなく,複数のデータに対して計算可能なように関数を拡張して定義している.しかし,関数によっては,また独自に作成した関数の場合,そのような拡張をするかどうかは定義次第である.その指定は,関数の付随する属性を調べるAttributesを用いて調べることができる.Sinに適用すると,

    Attributes@SinD8Listable, NumericFunction, Protected<

    となることから分かるようにListableとなっているが,これがリストに対して適用できることことを意味

    している.いま,未知の関数 f に対して,Sinと同様にf[{a,b,c}]と入力しても何もこらない. f がどのような関数なのか定義されていないのだから当然である.しかし,SetAttributesを使えば,Sinと同様

    にリストに適用できるように変更することができる.つまり, f の属性を,

    SetAttributes@f, ListableDと設定しよう.すると,

    f@8a, b, c

  • FrameBox@GridBox@8#, Attributes@#D< & ê@ 8Sin, Plus, Times

  • シンボル 整数 正 負 複素数π True False True False False

    True False True False False−∞ False False False True False2 False True True False False−0.2 False False False True Falseè!!!5 False False True False False2.1 − False False False False True

    となる.ここで,Positive[s]はsが正ならばTrue,sが負の場合Falseを返すコマンド,Negativeも同様なコマンドで,8Positive@−0.2D, Negative@−0.2D<

    8False, True<

    のようになる.シンボル,整数,複素数の場合はこのようなコマンドが無くSymbol[s],Integer[s],-Complex[s]とはできないので,頭部を使って,8Head@πD === Symbol, Head@2D === Integer, [email protected] − D === Complex<

    8True, True, True<

    と判断する.ここで,===は両辺が等しい場合はTrue, 等しくない場合はFalseになる.尚,上記のプロ

    グラムの骨格はMathematica特有の関数を使っているが,その定義の仕方,使い方などは後述するのでここでは結果だけを見ていただきたい. これまで,円周率を表すpが何度か出てきたが,pはシンボルpのままで表現され,その数値が必要な場合はNを使わなければならなかった.eとN[ ],2とN[2]の違いも同様で,実際,8π, N@πD, , N@ D, 2, N@2D<

    8π, 3.14159, , 2.71828, 2, 2.<

    である.pは記号で書かれたいわば抽象的なシンボルで,N[π]として初めてその数値が利用できることになる.数値はその精度を指定して初めて表現できるので,N[π]は実は精度を指定した表現になっている.実際,入力形式

    N@πD êê InputForm3.141592653589793

    から分かるように,N[π]は16桁(これは機械精度MachinePrecisionに等しい)の数値である.以上のことから,数の表現は精度を考慮していることを常に頭に入れておかなければならなく,記号pで与えたは場合,無限の精度をもった正確な数値として記号化しているのである.したがって,pをシンボルのままで表すことによって,任意の精度で表現するを可能にしている. 精度との関係で,「数値」的な量を表すNumericと,「数」を表すNumberの区別がある.この区別は分かり難いが,例8NumericQ@πD, NumberQ@πD, NumericQ@2D, NumberQ@2D<

    8True, False, True, True<

    から推察すると,πは「数値」的な量であるが「数」ではなく,整数2は数値的な量でもあり数でもある.つまり,Nで評価すれば数値になるようなシンボルが,「数値」的な量であるが「数」ではない.精度

    8

  • の面からはいえばこのようなシンボルは「数値」的に正確な値を持っていることになる.ここで,コマンドNumericQ[s]はsが「数値」ならばTrueを返し,一方,コマンドNumberQ[s]はsが「数」ならばTrueになる.以下には,いくつかの例を表にした.

    myNList = 8π, 2, 2.0, Log@πD, ∞, 2.1 −

  • ¤  精度の異なる2数の和,積の精度を調べよ.たとえば,123456789.123456789と123456789.12.また,N@Sin@1D, 100Dと N@[email protected], 100Dの精度の面での違いを調べよ.

     機械精度

    $MachinePrecision

    15.9546

    に関してもう少し述べておこう.桁数に大きな差のある数の差を用いた

    Sin@N@ 270 − 21DD === Sin@N@ 270DDTrue

    から分かるように,機械精度の演算ではその差は認められない.しかし,精度を上げると,

    Sin@N@ 270 − 21, 30DD === Sin@N@ 270, 30DDFalse

    となって,違いが分かる. pは無限大の精度を持っているので,任意の精度を指定することができ,たとえば,8InputForm@N@π, 4D, NumberMarks → FalseD,

    InputForm@N@π, 16D, NumberMarks → FalseD,InputForm@N@π, 100D, NumberMarks → FalseD<83.142, 3.141592653589793,3.141592653589793238462643383279502884197169399375105820974944592307816

    406286208998628034825342117068<

    とすると分かるように,精度をどんなに大きくしてもその精度での数値が出力される.しかし,一旦,N[π]として機械精度に落とすと,

    pai = N@πD;8InputForm@N@pai, 4D, NumberMarks → FalseD,InputForm@N@pai, 16D, NumberMarks → FalseD,InputForm@N@pai, 100D, NumberMarks → FalseD<83.141592653589793, 3.141592653589793, 3.141592653589793<

    となることから以下の2点が分かる.まず,機械精度のpaiの精度を4桁に落としても,依然として機械精度になっている.精度の低い数値設定は受けいれられない.次に,機械精度以上の精度に設定してもやはり機械精度になっている.これは当然であろう. 精度の関連するコマンドにAccuracyがある.これは,小数点以下の桁数を表す.したがって,8Accuracy@3D, [email protected], Accuracy@πD<

    8∞, 14.8406, ∞<

    となることは理解できるだろう.Accuracy[13.0]は機械精度から2を引いた値にほぼ等しい.また,同様に,

    10

  • 8Accuracy@N@π, 4DD, Accuracy@N@π, 16DD, Accuracy@N@π, 100DD<83.50285, 15.5029, 99.5029<

    となる.さらには,

    [email protected].

    となる. 精度や小数点以下の有効桁数をSetPrecisionで任意に設定できる.たとえば,8InputForm@N@π, 25D, NumberMarks → FalseD,

    InputForm@paiD, SetPrecision@pai, 25D< êê TableForm3.1415926535897932384626433.141592653589793

    3.141592653589793115997963

    のようにできるが,もともとpaiの精度は機械精度で,それ以降の桁には2進数の0が埋められるので,正確な値ではない. 精度を意識しなければならない場面に不等式の評価がある.シンボルで表された数を用いた不等式は無限の精度で比較されるので,8π < , 3.0 < π, π < π + 10−100<

    8False, True, True<

    のようにいつも正確な結果になるように思えるが,実はそうではない.実際には,不等式の評価には

    $MaxExtraPrecision

    50.

    で定められた精度の範囲で行われている.勿論のこの値を変更することもできる.

    ¤  Sqrt[(2-Sqrt[2+Sqrt[2]])/(2+Sqrt[2+Sqrt[2]])]

  • のようになる. 虚数は,

    Sqrt@−126D3 è!!!!!!14

    のように表現される.複素数の実部と虚部は[email protected] + 4.56 D, [email protected] + 4.56 D<81.23, 4.56<

    で取り出すことができ,絶対値と偏角は,[email protected] + 4.56 D, [email protected] + 4.56 D<84.72298, 1.30733<

    である.ここで,偏角はラジアンで表す. コンピュータ科学の分野では,通常の10進数以外に2進数に変換した数も扱う.ここでは,このような数の変換などの関して簡単に振れておこう.数字に各桁を表す整数に分解するには,

    IntegerDigits@123456789D81, 2, 3, 4, 5, 6, 7, 8, 9<

    とする.これは10進数で表した数字の各桁の整数であるが,これを2進数に変換した数字で各桁に現れる整数(0か1)および桁数は8IntegerDigits@123456789, 2D, Length@IntegerDigits@123456789, 2DD<

    881, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1,1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1

  • 881, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0

  • である.ここで,InputForm[myPlot]とするとたいへん長いコードが出てくるので,Shortでその一部分のみを出すようにした(InputForm[myPlot]としてすべてのコードを調べよう).上記のように複雑

    な構造が見られるが,これが,表示のためのMathematicaのInputForm形式で,ユーザはPlot[-Sin[x],{x,0,2π}]としか入力していないが,実際にはこれだけ複雑は式になっている.だからこそ,座

    標などを指定していないにも係わら図が描ける.これが,インターフェースが特に優れている強力なMathematicaの特徴で,ソフトの構造を熟知しなくとも初心者でも電卓感覚でマニュアルにも目を通さず直ぐに使える理由である.さて,上記の入力形式で,数値を出さないようにちょっと工夫して,myPlotの重要な骨格だけを取り出すと,

    InputForm@myPlot êê. 8Line@_D → Line@"デ−タ"D,8___?HHead@#D === Rule »» Head@#D === RuleDelayed &L< → "オプション"

  • 9AspectRatio → 1GoldenRatio

    , Axes → Automatic, AxesLabel → None,

    AxesOrigin → Automatic, AxesStyle → Automatic, Background → Automatic,

    ColorOutput → Automatic, Compiled → True, DefaultColor → Automatic,

    DefaultFont $DefaultFont, DisplayFunction $DisplayFunction,

    Epilog → 8

  •  次に,離散的なデータの表示を考える.MathematicaのグラフィクスはPlotに限らないが,Plotのような関数表示に適した描画関数と,離散的なデータに適したの描画関数に大別されている.Plotに対応する描画関数はListPlotである.いま,データを,

    myData = 980, 0

  • 9AspectRatio → 1GoldenRatio

    , Axes → Automatic, AxesLabel → None,

    AxesOrigin → Automatic, AxesStyle → Automatic, Background → Automatic,

    ColorOutput → Automatic, DefaultColor → Automatic,

    DefaultFont $DefaultFont, DisplayFunction $DisplayFunction,

    Epilog → 8

  • となる.後者がTraditionalFormで,行列で表現されいるので分かりやすいと思うかも知れないが,前者のStandardFormでは1行に収まることを考えれば前者の方がむしろ便利がいい.myPointsの各点を結んで線を引くにために,

    Show@H∗グラフィックスイメージを描画∗LGraphics@H∗グラフィックスイメージを作成∗LLine@myPointsDH∗グラフィックスプリミティブ∗LDD;

    と入力する.点をLineで結んで,Graphics[...]の括弧の中に書くことでグラフィックスのイメージが出来上がり,そのイメージをShowで表示している. これを見ると確かに4点を結んだ線を引いてるが,Plotと異なりそれ以外は何もないので座標軸がどこにあるかも分からない.そこで,Graphicsのオプションを調べよう.参考のためPlotのオプションとの違いをComplementを用いて,同時に調べると,

    Options@GraphicsDH∗Graphicsのオプション∗LComplement@Options@PlotD,Options@GraphicsDDH∗PlotとListPlotの異なるオプション∗L9AspectRatio → 1

    GoldenRatio, Axes → False, AxesLabel → None,

    AxesOrigin → Automatic, AxesStyle → Automatic, Background → Automatic,

    ColorOutput → Automatic, DefaultColor → Automatic,

    DefaultFont $DefaultFont, DisplayFunction $DisplayFunction,

    Epilog → 8

  • 1 2 3 4 5 6

    −1

    −0.5

    0.5

    1

    のように歪になってしまう.

    ¤  PlotPoints,PlotDivision,MaxBendをいろいろ変えて,Plot[Sin[x],{x,0,2π}]で描画した正弦波の変化を調べて,それぞれの役割を確かめよ.

     Plotを参考に,GraphicsのオプションAxesをTrueにすると,

    Show@Graphics@Line@myPointsD, Axes → True DD;

    −1 1 2 3 4

    1

    2

    3

    4

    5

    と座標が描かれる.ただ,オプションの使い方で迷うのは,TrueとAutomaticの使い分けで,後で詳しく述べるがこの場合Automaticとしても同じ結果になる.マニュアルにもはっきりした違いは書かれていない.実際,マニュアルでAxesの項目を見ると,TrueとFalseとあるが,別のところを見る,Auto-maticと設定することができるようになっている.いずれにしても,このようにして座標軸を付け加えることができる.その他のオプシンに関しては第2章以降で詳細に述べる.

     グラフィックスプリミティブにはLineだけでなく,多くのプリミティブが用意されている.塗り潰した多角形を描きたければPolygonを使って,

    Show@Graphics@Polygon@myPointsD, Axes → TrueDD;

    −1 1 2 3 4

    1

    2

    3

    4

    5

    とすればよい.ここで,Lineと同じデータmyPointsを使って表示した.円を表すプリミティブCir-cle(中を塗り潰さない),Disk(中を塗り潰す)を描く場合,座標軸がなければ円と楕円が区別できな

    くなるので,楕円と間違わないようにAspectRatioをAutomaticあるいは1にする必要がある(Aspect-Ratioの詳細な使い方は後で述べる).Circleプリミティブの基本的な使い方は,Circle[{円の中心の座標},半径]である.Diskも同様である.下記の例は,円,円弧または楕円Circleと,中を塗り潰した円,円弧または楕円Diskを表示した例である.

    19

  • Show@Graphics@8Circle@8−1, 1

  • Show@Graphics@8Text@"Matsuba", 80, 0

  • ここで,テキストをTraditionalFormに変更するためにStyleFormを使っていることに留意しよう.この例から分かるように,Text,Line,Circle,DiskだけでもPlotと同じように,座標,目盛はもちろん凡例なども自由に作成できることが分かるだろう.むしろ,組込み関数Plotよりも自由な発想でグラフを描ける. 最後に例をもう一つ.長方形プリミティブRectangle[{左下座標},{右上座標}]を使って,

    ShowAGraphicsA98GrayLevel@1D, Rectangle@8−1, −1

  • のようなグラフィクスが作成できる.Circle,Disk,Polygonを使っているが,それぞれ絵のどの部分に使っているか確認しよう.

    ¤ Circle,Disk,Polygon等のグラフィクスプリミティブを使って,いろいろな絵を描いてみよう.

    1.2 フォント

     Office,Texなどドキュメント用ソフトには豊富なフォントが用意されている.フォントの美しさにおいてはいまだTexが優越しているように思えるが,最近ではどのドキュメントも書籍並みに美しい.Mathemat-icaのノートブックもドキュメントとして用いることができ,現に本書はすべてノートブックで書いた.ただ,フォントに関してはやはりまだ不十分で特に日本語環境では使い難い.本節では,フォントの使い方とその限界について述べる.

    à 1.2.1 標準的な英数字

     Mathematicaで扱える標準的な英数字フォントにCourier,Times,Helveticaがある.これらのフォントはFontFamilyで指定することになっているが,マニュアルによるとこれらのフォント以外のフォントを指定すると自動的に近いフォントに置き換わる.特に指定しなければ,デフォルトとして,CourierあるいはTimesに設定される.グラフィックスプリミティブとしてTextがあった.StyleFormなどで特に指定しない場合は,目盛等にはデフォルトのフォント

    $DefaultFont

    8Courier, 10.<

    を使う.つまり,Courierでその大きさは10ポイントになっている.グラフィックス以外にも表で使うこともあり,フォントを自由に扱えるようにしたい.では,どのようなフォントが利用できるか,またどのようにして表示するか,いろいろな例を用いて調べよう. 最初の簡単な例として,平面に配置されたオブジェクトをボックス書式で表示するStyleBoxを用いて文字を表示する.英数字を文字として扱うためには"文字"のように囲む(これ以外の方法ある).文字列

    "Matsuba"を,フォントを"Times"とし,大きさFontSizeを10,フォントの太さFontWeightを"Plain",斜体文字FontSlantを"Plain"はとして表示させると,

    StyleBox@"Matsuba", FontFamily → "Times", FontSize → 12,FontWeight → "Plain", FontSlant → "Plain"D êê DisplayForm

    Matsuba

    23

  • となる.ここで,DisplayFormはStyleBoxで書く文字を通常のStandardFormで出力する.これは,StyleBoxで使用される標準的なデフォルトのフォントであり,したがって,StyleBox["-Matsuba"]//DisplayFormとしても同じ出力結果を得る.実際,

    Options@StyleBox, 8FontFamily, FontSize, FontWeight, FontSlant

  • GridBox@88StyleForm@""D, H∗表の見出し∗LStyleForm@"サイズ 10"D,StyleForm@"デフォルト\nサイズH12L", FontSize → 8D,StyleForm@"サイズ 16"D

  • I am an author of This Book.印字結果は実行する前に予想できるだろう.ただし,カラー表示RGBColorに関しては後章で述べる.

     標準的な英数字フォント以外に,実は数多くのフォントが使える.Mathematicaを標準的にインストールすれば,デレクトリ「Mathematica」の下にあるデレクトリ「SystemFiles」のデレクトリ「Fonts」にあるフォントを使えば,8StyleForm@"Matsuba", FontFamily → "mathematica1"D,

    StyleForm@"Matsuba", FontFamily → "mathematica6"D<8Matsuba, <

    とギリシャ文字なども使える.さらに,システム(本書ではWindowsにインストールしたフォント)で利用できるフォントを使えば,8StyleForm@"Matsuba", FontFamily → "Broadway"D,

    StyleForm@"Matsuba", FontFamily → "Wingdings"D<8Matsuba, <

    のような記号も使える.このように,記号を含めワープロのように多くのフォントが使えることが分かる.これらのフォントは使用しているコンピュータにインストールされているフォントに依存し,また,印刷する際にも機種依存性があるので使う時には予め確かめておく必要があろう. 各種の文字にはそれぞれASCII標準,Unicode規格等にしたがう固有の文字コードが対応している.To-CharacterCodeを使えば,

    ToCharacterCodeA9"matsuba", "α", "∞", "è!!!!π "=E88109, 97, 116, 115, 117, 98, 97

  • matsuba

    à 1.2.2 特殊な文字

     標準的な英数字フォント以外に各種のフォントが使えた.ここではさらに多様な特殊文字に関して述べよう. CharacterRangeは指定した範囲にある文字をリスト形式で返す.たとえば,

    Join@CharacterRange@"a", "z"D, CharacterRange@"A", "Z"DD8a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A,B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z<

    のようになる.数学や物理関係の書物でよく用いる特殊文字にギリシャ文字がある.利用可能なギリシャ文字等の特殊文字,記号等は,直接パレット[ファイル]→[パレット]で[CompleterCharacters]を指定すると現れる.ギリシャ文字をすべて表示すると,

    Join@CharacterRange@"α", "ª"D, CharacterRange@"Α", "µ"DD8α, β, γ, δ, ∂, ζ, η, θ, ι, κ, λ, µ, ν, ξ, ο, π, ρ, ς, σ, τ, υ, ϕ, χ, ψ, ω, ϊ, ϋ,ό, ύ, ώ, �, �, ϑ, ϒ, �, �, φ, ϖ, �, �, �, ≥, π, ≤, ∏, ¥, ∫, µ, ª, Α, Β, Γ, ∆,Ε, Ζ, Η, Θ, Ι, Κ, Λ, Μ, Ν, Ξ, Ο, Π, Ρ, �, Σ, Τ, Υ, Φ, Χ, Ψ, Ω, Ϊ, Ϋ, ά, έ, ή,ί, ΰ, α, β, γ, δ, ∂, ζ, η, θ, ι, κ, λ, µ, ν, ξ, ο, π, ρ, ς, σ, τ, υ, ϕ, χ,ψ, ω, ϊ, ϋ, ό, ύ, ώ, �, �, ϑ, ϒ, �, �, φ, ϖ, �, �, �, ≥, π, ≤, ∏, ¥, ∫, µ<

    となる.一部の文字が無かったりまた重なっている文字もある.文字の大きさをFontSizeで変えると,

    Table@StyleBox@"α,β,ξ", FontSize → i, Background → [email protected],8i, 10, 20

  • Ÿ Ÿ Ÿ Ÿ Ÿ Ÿ ŸŸŸ Ÿ Ÿ ŸŸŸŸ

    となる.ここでは,FrameBoxを用いて全体をフレームで囲んでおいた. さて,以上のような特殊文字や記号は,それぞれ符号化された固有のコードで表されている.そのコードはToCharacterCodeで調べることができる.たとえば,

    ToCharacterCodeA9"Ÿ ", "Ã", "¤", "⁄"=E888747

  • Characters@ToString@"α", InputForm, CharacterEncoding → "ASCII"DD8", \, @, A, l, p, h, a, D, "<

    のようになる.これを参考にすすと,4番目から最後から3個までの記号を取り出せば

    Take@Characters@ToString@"α", InputForm, CharacterEncoding → "ASCII"DD, 84, −3

  • ToCharacterCode@8"a,b", "まつ", "α,β"

  • となる.Courier Newであるが,それに近いゴシック体で置き換えているようである. さて,MSP明朝体で標準文字飾りの「松葉」のコードを調べよう.今,ToCharacterCodeに与える文字列を入力し,その入力文字自体をメニューバーで,[書式]→[フォントを選択]でMSP明朝体,標準体を選択して,True TypeのMSP明朝体に変換しよう.すると,

    ToCharacterCode@8"松", "葉"

  • 9ゴシック体, ゴシック体, ゴシック体, ゴシック体,

    ゴシック体,ゴシック体,ゴシック体=

    のようになる. それでは,入力した文字,MSP明朝体,MSPグシックの各フォントの標準書体に変換した文字列を,In-putFormを用いて調べてみよう.すると,

    InputForm@8"入力", "明朝", "ゴシック"

  • となる(ノートブックのスタイルに依存する).ただし,MSP明朝体などに変換した文字列を使っても結果はすべて同じになる. 最後に,文字列をグラフィックスとして表示しよう.前節では,線,円などを例に簡単なグラフィックの使い方を説明し,文字列のプリミティブTextを用いた例も示した.ここでは日本語フォントの例を以下に示しておこう.

    Show@Graphics@8Text@"松葉育雄", 8−0.5, 0.4

  • と順序が逆になった文字列ができる.文字列の長さは,

    StringLength@myNameD12

    とすれば分かる.あるいは,文字列を文字を要素とするリストにするCharactersを使い,そのリストの要素数を求めれば,8Characters@myNameD, Length@Characters@myNameDD<

    88I, k, u, o, , M, a, t, s, u, b, a

  • Show@Graphics@8Text@StyleForm@"縦軸のラベル", FontSize → 12D,8−0.5, 0

  • 考えれば,横軸と縦軸の値を8x, y

  • 20 40 60 80 100

    −1

    −0.5

    0.5

    1

    のようになる.これは,0から2pまで100等分した合計101個のデータ(両端の0と2pを入れている)をTableで作成して表示している.

    ¤  Plot[Sin[x],{x,0,2π}]]は連続的なグラフを描くが,離散的なデータを表示するのがListPlotである.PlotのInputFormを見ると,離散的な値をLineで結んでいることが分かる.その離散的な値がどのように値になっているか調べてみよう.詳しくは第4章で述べる.

     同じ図を別な関数で作成してみよう.複素数を変数にもつ指数関数

    Exp@ xD êê ExpToTrigCos@xD + Sin@xD

    を実部と虚部に分ければ,虚部はsinHxLになる.Imで虚部を取り出すことができるので,ListPlot@Table@Im@Exp@ xDD, 8x, 0, 2 π, 2 π ê100

  • 8Table@0, 83

  • TableForm@rect, TableAlignments → 8Center, Center

  • Distribution[0,1]]というふうに書く.尚,正規分布から乱数を発生するために予め,

  • ¤  この例を解析せよ.

     同じリストを作成するにも,作成方法によってはずいぶん効率が異なる.以下の例は,整数の単なる表を作るだけの関数であるが,計算時間をTimingで調べると,

    Timing@t1 = Table@N@jD, 8j, 105

  • à 1.3.2 動的なリストの作成

     これまでの述べたリストの作成方法は静的であった.つまり,1次元リスト8x1, x2, ... , xn

  • 8 , , −1, H−1L3 , 1<

    となる.

    ¤  この結果を確かめよ.

     Powerと同じ演算を, fをMathematicaに特有な関数(第3章で詳しく述べる)で記述すと,

    FoldList@Power@#1, #2D &, a, 8exp1, exp2, exp3

  • ¤  Random[Integer]は0か1の乱数を同じ確率で作り出す.Tableで多数の乱数を発生させて,0と1の数が同じかどうか確かめよ.生成した乱数を足し合せれば,1の数になる.

     したがって,ウォーカーの初期値を原点x0 = 0として,関数としてPlusを用いたFoldListで各時刻での位置rnが求められる.図示すると, 

    SeedRandom@5913D; H∗乱数の種を5913とする∗LListPlot@FoldList@Plus, 0, Table@2 Random@IntegerD − 1, 81000

  • −15 −10 −5 5 10 15

    −10

    −5

    5

    10

    15

    となる.同じ2次元ランダムウォークであるが,少々異なる方法で発生させよう.今,ウォーカーの移動方向を予め

    dir = 881, 0

  • とすると,2番目の要素bが取り出せる.あるいは,配列のように,8a, b, c

  • ¤  Part[Part[data0,2],1]とすれば,どの要素が取り出せる確認せよ.

     また,

    Part@data0, 2, 1Dc

    とすることもある.もっと簡便な方法は,8data0@@2DD, data0@@2DD@@1DD, data0@@2, 1DD<88c, d

  • Part@data, iDdata@@iDD i番目の要素

    Part@data, i, jDdata@@iDD@@jDD i番目の要素のj番目の要素

    Part@data0, −1D 最後の要素

    としてまとめておこう. リストのある部分の要素を使いたい場合,あるいは削除したい場合を考えよう.たとえば,2番目の要素から3番目の要素を使いたい場合,Takeを用いて,

    Take@data0, 82, 3

  • Position@data0, 8c, d

  • 88a, b

  • Partition@Flatten@data0D, 3D88a, b, c

  • myVector = Table@a@iD, 8i, 5

  • のようになる.同様に,一般の関数funを

    SetAttributes@fun, ListableD;と,リストに対応可能なようにしておけば,Sinと同様に,

    fun@myMatrixD êê MatrixFormi

    k

    jjjjjjjfun@a@1, 1DD fun@a@1, 2DD fun@a@1, 3DD fun@a@1, 4DD fun@a@1, 5DDfun@a@2, 1DD fun@a@2, 2DD fun@a@2, 3DD fun@a@2, 4DD fun@a@2, 5DDfun@a@3, 1DD fun@a@3, 2DD fun@a@3, 3DD fun@a@3, 4DD fun@a@3, 5DD

    y

    {

    zzzzzzz

    とできる.特別な行列として,対角成分のみが0でない,

    {IdentityMatrix[3]//MatrixForm,DiagonalMatrix[{a,b,c}]//MatrixForm}

    9i

    k

    jjjjjjj1 0 00 1 0

    0 0 1

    y

    {

    zzzzzzz,i

    k

    jjjjjjja 0 00 b 0

    0 0 c

    y

    {

    zzzzzzz=

    が使える.前者は単位行列IdentityMatrix,後者は対角行列DiagonalMatrixである. ベクトル,行列,テンソルの区別はその深さArrayDepthで調べることができる.実際,8ArrayDepth@myVectorD, ArrayDepth@myMatrixD<

    81, 2<

    から,深さが1,2の配列であることが分かる.バージョン5.0で廃止になっている同じ機能を持つTensor-Rankもまだ使えるようである.

    ¤  Length,Dimensions,ArrayDepthの関係を調べよ.

     深さが3の配列はテンソルで,たとえば,

    (myTensor=Table[Random[],{3},{2},{2}])//MatrixForm

    {Dimensions[myTensor],ArrayDepth[myTensor]}

    i

    k

    jjjjjjjjjjjjjjjjjjjjjjj

    J 0.2479570.975226

    N J 0.06907760.0885172

    N

    J 0.8200640.662845

    N J 0.2821960.509391

    N

    J 0.6720650.310443

    N J 0.420870.548753

    N

    y

    {

    zzzzzzzzzzzzzzzzzzzzzzz

    883, 2, 2

  • とするだけで済む.わざわざ,Table[c,{i,5}]とリストを作ってmyVectorと和をとる必要はない.こ

    れを知らなければ,各要素myVector[[i]]にcを加える操作を素直に,

    Module@8myNewVector

  •  要数が少ないと8a1, a2, a3

  • とする.1 µ 2行列の要素は,8myMatrix@@1, 2DD, Part@myMatrix, 1, 2D<8a12, a12<

    などで取り出せた.列自体を取り出したいならば,行列がリストの拡張と考えれば,たいへん簡単で,

    myMatrix@@3DD8a31, a32, a33, a34, a35<

    とすればよい.複数の列を取り出す場合には,

    myMatrix@@82, 4

  • i

    k

    jjjjjjjjjj

    a11 a12 a13 a14 a15a21 a22 a23 a24 a25a31 a32 x a34 a35a41 a42 a43 a44 a45

    y

    {

    zzzzzzzzzz

    すればよい.ある列にある要素すべての値を設定するのは,リストの拡張と捉えれば簡単で,

    myMatrix@@2DD = Range@5D;myMatrix êê MatrixFormi

    k

    jjjjjjjjjjj

    a11 a12 a13 a14 a151 2 3 4 5a31 a32 x a34 a35a41 a42 a43 a44 a45

    y

    {

    zzzzzzzzzzz

    とするだけで済む.しかし,行の場合はやはりちょっと工夫が必要で,たとえば,

    myMatrix@@All, 2DD = Range@−1, −4, −1D;myMatrix êê MatrixFormi

    k

    jjjjjjjjjjjj

    a11 −1 a13 a14 a151 −2 3 4 5a31 −3 x a34 a35a41 −4 a43 a44 a45

    y

    {

    zzzzzzzzzzzz

    あるいは,

    myMatrix@@Range@4D, 2DD = 8−1, −2, −3, −4

  • ikjjj a11 -1 a13 a14 a15a41 -4 a43 a44 a45 y{zzzとする. テンソルの場合も行列の場合と同様で,たとえば,HmyTensor = Array@Subscript@m, SequenceForm@##DD &, 82, 4, 2

  • として実行すると,

    MatrixForm ê@ rowSwitch2@myMatrix1, myMatrix2, 2, 3D9i

    kjjjjjja11 a12 a13 a14b31 b32 b33 b34a31 a32 a33 a34

    y

    {zzzzzz,

    i

    kjjjjjjb11 b12 b13 b14b21 b22 b23 b24a21 a22 a23 a24

    y

    {zzzzzz=

    となり,確かに交換されていることが分かる.

    ¤  関数の定義は別として,その本体のプログラムを解析せよ.

    à 1.4.3 表形式のデータへの応用

     これまで述べた事を具体的なデータに対して応用しよう.今,各年の産業別の就業者の比率(%)を,表形式として

    workers = 88"西暦", "人口H1000人L", "第1次産業", "第2次産業", "第3次産業"

  • とするのが便利である.最初の項目「西暦」も取り去りたい場合は,最も単純な方法としては,行と列を指定して,

    Part@workers, Range@2, 6D, Range@2, 5DD êê MatrixFormi

    k

    jjjjjjjjjjjjjjjjj

    93419 30.2 28. 41.8

    103720 17.4 35.2 47.3117060 10.4 34.8 54.6123611 7.2 33.6 58.7126926 5.1 30.7 63.7

    y

    {

    zzzzzzzzzzzzzzzzz

    とすることができる.一部のデータを取り出す例をいくつか並べると,8Part@workers, 2, 4D, workers@@2, 4DD, workers@@2DD@@4DD<Part@workers, 2, 5Dworkers@@82, 3

  • Hwl = 8a1, a2, a3

  • を比較しておこう. 以上の演算だけだと通常の内積と変らず大した特徴がなさそうであるが,Mathematicaでは他の演算と同様に通常の内積を拡張したInnerを用意している.行列の場合8Dot@8a1, a2

  • u2 êê InputFormSubscript[u, 2]

    から,推察される.

    ¤  Inner[f,Subscript[u,2],Subscript[v,3],g]を実行して,確認せよ.

     もう少し例を取り上げておこう.今,

    v1 = 8a, b, c

  • 80, 0<

    となっている.ここで,//Simplifyがないと式を変形しないので,0になっていないように見える.グラフィクスで直交する様子を見てみよう.まず,

  • などがある. 演算を一般的な関数に置き換えると,

    Outer@f, 8a, b

  • である.大きな次元のベクトル,行列は一見しては分からないことがあるので,これらは便利なコマンドである.線型方程式などでは,ベクトルと行列の積を扱うが,

    [email protected]@XDi

    kjjjjjja11 a12 a13a21 a22 a23a31 a32 a33

    y

    {zzzzzz.i

    kjjjjjjx1x2x3

    y

    {zzzzzz

    となる. 既にでてきたが,転置は行と列を入れ替える演算で

    Transpose@AD êê MatrixFormi

    kjjjjjja11 a21 a31a12 a22 a32a13 a23 a33

    y

    {zzzzzz

    とする.行列式が0でないとすると,逆行列はInverseを使って,

    InverseAJ a bc d

    NE êê MatrixFormikjjjj

    d−b c+a d −

    b−b c+a d

    − c−b c+a da

    −b c+a d

    y{zzzz

    と求められるが,3 x3行列A.Bの逆行列を求めようとすると,

    InverseAJ a ba b

    NEInverse::sing : 行列88a, b

  • で確かめられる.この結果は零空間ベクトルがなく逆行列が計算できることを意味する.実際,

    myInverse=Inverse[myRandomM]

    88−3.65329, −1.89328, −0.498777, 3.87132

  • 0.2 0.4 0.6 0.8 1

    0.2

    0.4

    0.6

    0.8

    1

    とする.ただし,座標の指定の仕方(Lineと異なる{...}は一重)に注意しよう.Arrowはグラフの注目点を強調するためのも有用で,

    Plot@Sin@xD, 8x, 0, 2 π

  •  行列の固有値の計算は重要である.固有値に関連する組込み関数に,Eigenvalues ,Eigenvectors,Eigensystemなどがある.たとえば,固有値は

    Eigenvalues[J 1 23 2

    N]84, −1<

    で,その固有ベクトルは,

    EigenvectorsAJ 1 23 2

    NE êê MatrixFormJ 2 3

    −1 1N

    で分かる.両者が同時に必要な場合は,8ev, eb< = EigensystemAJ 1 23 2

    NEPrint@"固有値は", ev, ", 固有ベクトルは", eb êê MatrixFormD884, −1

  • 後にcmである.つまり,Sortしたい対象が何らかの演算の結果であった場合には,このように(...;...)で括った式を用いることができる.もっとも,前もっとcm=Characters["matsuba"]を評価

    しておき,それから,Sort[cm]とすればいいのだが,このようにひとまとめにすることができるのも

    Mathematicaの特徴である. さて,通常,数字を扱うことが多いので,

    myS1D = 85, 3, 1, 7, 9, 2, 4

  • とする.これは結局,Sort[myS1D,Greater]と同じ操作である.尚,このような条件式は純関数といい第3章で詳しく説明する.次の例

    Sort@myS1D, Abs@#1 − #2D > 3 &D81, 3, 9, 4, 7, 2, 5<

    の結果は,元のmyS1Dから直ぐに分かるだろうか(後でもう一度で出てくる).今,-10から10までの一様乱数をSortとして表示すると,

    ListPlot@Sort@Table@Random@Real, 8−10, 10

  • 8Sort@81, 5, 3 2 &D,8HAbs@#1 − #2D > 2 &L@1, 5D, Abs@1 − 5D > 2, 888−5, −5

  • とすると,要素の1番目の値に対してソートしていることが分かる.もう一つ例をあげておく.今,-10から10までの一様乱数をSortすると,

    Sort@HPrint@"元のリスト:", rn = Table@8Random@Real, 8−10, 10

  • 824069.2, 23736.6, 22897.8, 22969.3,2460 , 14007.9, 13981.5, 13947., 13785.7<

    のようになっている.これらの値をxnとし,表示すると,

    ListPlot@nikkei, AxesLabel → 8"n", "xn"

  • SeedRandom@11111D;8evals, evecs< = Eigensystem@Table@Random@Real, 8−1, 1

  • のような操作を施す.RotateRight[...,n]は,n回右に回転させる.また,文字列が入っていてもかまわなく,

    RotateRight@8m, a, t, s, u, b, a

  • ¤  上記のプログラムを解析せよ.

    à 1.5.3 平坦化:Flatten

     深さ3のリストを

    myTable = Table@a@i j kD, 8i, 2

  • としよう.これから分かるように,8880, 0

  •  次に関数を取り上げよう.関数に関しては第3章でとり上げるが,当面は通常数学的に使う関数と同様であると考えておこう.たとえば,2変数の関数 f Hx, yLに対して,Mathematicaではf[x,y]と表すが,Flat-tenを適用すると,

    Flatten@f@f@a, bD, f@c, dDDDf@a, b, c, dD

    となる.ちょっと戸惑いそうな結果である.ただし,関数の変数がリストの場合には,

    Flatten@f@8f@8a, b

  • Show@Graphics@Line@myLineDDD;

    となる.今,myLineを2個づつに分け,

    Partition@myLine, 2D8880, 0

  • myRData = Table@8x, Sin@x + 0.1 Random@DD

  • のようにする.1.1節で述べたように,p,è!!!2などは数ではないが,N[π]は実数になることに注意しよう.また,

    SelectA9a, b, 1, 2.0, π, è!!!!2 , N@πD=, NumericQ, 3E81, 2., π<

    とすると,条件に合う最初の3個の要素を取り出している.また,

    Select@81, 2, 3, 4, 5

  • -4 -2 2 4

    -4

    -2

    2

    4

    のようになる.各種の応用では,リストからの抽出条件は純関数(第3章で詳しく述べる)で与えることが多い(!OddQ[#]&がそうであった).たとえば,8x, y0&と指定してプロットすると,

    ListPlot@Select@pts1, H#@@1DD + #@@2DDL > 0 &D,PlotStyle → [email protected], AspectRatio → AutomaticD;

    -4 -2 2 4

    -4

    -2

    2

    4

    のようになる.ここで,#[[1]]は要素の第1要素x,#[[2]]は要素の第2要素yである.また,8x, y

  • cTriQ@8x_, y_

  • -40 -20 20 40

    -40

    -20

    20

    40

    のようになる.次に,選択条件を論理和||を使って,

    cGreat@8x_, y_ 30として,実行すると

    Select@Names@"System`∗"D, longNameQD

    85

  • 8NeedCurrentFrontEndPackagePacket, NeedCurrentFrontEndSymbolsPacket,NotebookGetLayoutInformationPacket, NotebookSetupLayoutInformationPacket,

    UndocumentedTestGetSelectionPacket, VerboseConvertToPostScriptPacket<

    となって,いくつかあることが分かる.おそらく通常このようなコマンドは使わないと思うが.逆に,文字数が3以下のコマンドは

    shortNameQ@s_StringD := StringLength@sD ≤ 3なる選択条件を課すことで,

    Select@Names@"System`∗"D, shortNameQD8Abs, All, And, Arg, Box, C, Cos, Cot, Csc, D, Det, Do, Dot, Dt, E, End,Erf, Exp, Fit, For, GCD, Get, Hue, I, If, Im, In, K, LCM, Log, Map,

    Max, Min, Mod, N, Nor, Not, O, Off, On, Or, Out, Pi, Put, Raw, Re,

    Row, Run, Sec, Set, Sin, Sow, Sum, Tab, Tan, Top, Tr, Up, URL, Xor, $<

    と分かる.いずれも頻繁に使う関数である.

    à 1.5.6 その他の重要な関数

     これまでに述べなかった関数で,しばしば使う重要なコマンドに関してまとめて述べておく.いずれの使い方もこれまで述べたコマンドより簡単である.(1)最大値と最小値. 最大値,最小値を求めるコマンドMax,Minは,あらゆる場面で必要になる.たとえば,ベクトルに対して [email protected], 2.5, 1.0, 5.2

  • MaxA&''''''''''''''''''''''''''''''2 −

    "###############2 + è!!!2

    2 +"###############2 + è!!!2

    , TanA π16

    EE

    の場合は,メーセージから分かるように精度的(機械精度を使っても)に最大値を決定できない.実は比較している両者の数は厳密に等しく,内部精度の限界まで達しても判断できなかったからである.  前項で作成したリストpts2を用いて,各要素8x, y

  • 個ある.

    (3)条件に合う要素があるかどうか調べる. MemberQを使えば8MemberQ@81, 2, 3, 4, 5, a, b, 2 , 1 +

  • 91, − 12,

    13, −

    14,

    15=

    と求まる.ここで,x#の#には1から5までの数字が入る.

    ¤  Normalの機能を調べよ.

     応用例を示そう.60回サイコロを振って10回「1」の目がでれば「1」の目が出る確率は1 ê6,600回を振って正確に100回「1」の目がでればやはり1 ê6になるので,「1」の目が出る確率がp = 1 ê6といえる.しかし,実際にどのように変化するだろうか,サイコロを振って実験をしてみよう.といっても,何回もサイコロを振るの大変である.そこで,実際のサイコロを振るのではなく,模擬的に0から1までの値をとる一様乱数を用いてでてきた乱数の値が1 ê 6よりも小さいとき,「1」の目が出たとしよう.たとえば,1000回サイコロを振れば,各目の出る確率は

    TableA9i, NACountATable@Random@D, 81000

  • けでなく,効率面での有利さも考慮できるようになる.慣れてくると大変便利なものである.以下では,後章でしばしば使う基本的な演算を説明する.

    à 1.6.1 置換とルール

     式のある部分を別なものに置き換える置換演算にReplaceAll,あるいは簡略形であるスラッシュードット表記「/.」がある.たとえば,88a, b

  • p

    では,{{a,b},{c,d}}自体がリストなので,x_Listとすればそれをpで置き換えている. 簡単な例を示そう.まず,

    myPlot = Plot@Sin@xD, 8x, 0, 4 π

  • 2.5 5 7.5 10 12.5 15 17.5

    2.5

    5

    7.5

    10

    12.5

    15

    17.5

    となる. 三角関数を使う場合,cosHxL2 Ø 1 - sinHxL2のような等価な変換をしたい場合がしばしばある.この変換を置換を用いて

    Cos@xD2 ê. 8Cos@xD2 → 1 − Sin@xD2<1 − Sin@xD2

    とすることができる.これを一般化すると,

    Cos@xD4 ê. 9Cos@xDi_?EvenQ ExpandAH1 − Sin@xD2Liê2E=1 − 2 Sin@xD2 + Sin@xD4

    となる.ここで,置換「→」ではなく遅延型置換「 」を使っているが,これは置換した後にExpandでべき展開するためである.この使い型はたいへん重要なので直ぐ後で詳しく説明する.実際,置換「→」では

    Cos@xD4 ê. 9Cos@xDi_?EvenQ → ExpandAH1 − Sin@xD2Liê2E=H1 − Sin@xD2L2

    とすると,展開されない.また,Cos[x]のべきは偶数に限定されるので,iに条件i_?EvenQをつけた. さて,リストの要素数を与える関数Lengthを用いた変換ルール

    x_List → Length@xDx_List → 0

    を考えよう.ルールに関数Length[x]を使用しているが,本来xがリストならば,その要素の数が

    Length[x]になっているはずである.しかし,0になってるは,Length[x]がxが何かは判断せず即座にLength[x]を実行したためである.つまり,ルール「→」はそのルール適用する前に,Length[x]を実行している.これに対して,遅延型置換「 」を使うと

    x_List Length@xDx_List Length@xD

    となって,Length[x]が実行されていないのでLength[x]のままで現れる.そこで,遅延型置換「 」を使うと,88a, b

  • と2になる.「 」を適用するまではLength[x]評価をしないで,置換して後に始めて適用する.したがって,この場合,xがリストになるので,リスト{{a,b},{c,d}}には要素が2個あるのでこのような結果が得られる.尚,各種の演算において,記号「:」は遅延型の定義を与えるために用いられる. もう一つ簡単な例を挙げておく.8x, x, x< ê. 8x → Random@D

  • から分かるように,何個(0であってもよい)の要素にも対応する.以上のことを補足しておこう.8a, b< ê. 8x_, y_< リスト ê; Print@"置換:", "x → ", 8x

  • f@y, xDf@x, yD

    から分かるだろう.つまり,アルファベット順に変数を並び替えてしまう.このようなOrderlessの作用を考え,以下のような置換をしよう.8f@y, xD ê. 8f@x, yD → d

  • Flat:8f@a, xD, f@xD, x<

    とすると.以上の結果を理解するには,Orderlessの場合は自動的に整列され陽に書いた変数以外はないが,Flatでは,f[...]が省略されていると考えれば分かりやすい.まず,f[x]/.f[ ]→aを考えよ

    う. f HxLには f の変数であるスペースと同じシンボルが無いのでOrderlessの場合は何も置換されない.しかし,Flatの場合は,f[...]が省略されると考えれば,f[a,x]となることは理解できるだろう.さらに,Flatの場合,f[x]/.f[a_]→aとして,Orderlessの場合のようにxにならないのは,省略された変数があるためで,f[x]/.f[a__]→aとすればxになる.

     以上のように,置換すべき対象のシンボルなどが具体的に書き表されている場合は判断し易い.そうでない場合もある.

    f ê. 8f → a, g → b<a

    において,g→bは置換すべき対象がないので何もしない.ところが,

    f ê. 88f → a

  • 81, 2, 3, 4< êê. 8a___, b_, c_< HPrint@88a

  • となる.これならば,x[t_]にマッチさせることができるので,xHtLにt2を代入することができる.Hold@∂t x@tDD ê. 8x@tD → t2

  • とすればい.Transposeを2回使うことになる. 次の例は,各データに見出しのような文字列が入っている場合である.今,HmDataHead = 88"Name", "X", "Y"

  • 0.314573

    と入力すれば確かめられる.置換はそれが現れたら直ちに実行するので,ListPlot以前に,myDataを一つのシンボルと考え置換されてしまっているからである.この場合の対処法は,遅延型置換を用いて直ちに実行させないようにすることである.つまり,

    ListPlot@myData ê. x_ xê Max@Abs@myDataDD,PlotRange → All, PlotJoined → TrueD;

    10 20 30 40 50

    −1

    −0.5

    0.5

    1

    とすれば,図が描ける.もっとも作図前に予めClear[x]としてクリアしておけばよい.

    (3)プリミティブの変更:ポリゴン周りの辺とその長さ 塗り潰した多角形はPolygonで描ける.たとえば,

    poly = Show@Graphics@Polygon@884, 5

  • と分かる.頂点間の差を表すため,まず,左に回転させたリスト

    RotateLeft@polyLineD882, 1

  • 8f@aD, f@bD, f@cD<

    とするとすっきりした形で記述できしかもMathematicaらしくなる.さて,完全形式ではMapがどのよう作用を施しているのか見ておこう.上の例では,8FullForm@8a, b, c

  • となることから分かるように,確かに8a, b, c

  • 9è!!!!!!!!!!!!!!!!Sin@aD , è!!!!!!!!!!!!!!!!Sin@bD , è!!!!!!!!!!!!!!!!Sin@cD =

    などとする.つまり,純関数における最初の変数(#あるいは#1)の平方根のリストが得られる.また複雑なリストに対しては,

    # & ê@ 88a, b, c

  • a + c +b f@ 1a Dè!!!c

    2番目の要素はb ëè!!!c aであるが,この要素の1番目は要素bのような気がするが,そうではない.確かめるためには,

    FullForm@myExDPlus@a, Times@Power@a, −1D, b, Power@c, Rational@−1, 2DDD, cD

    とすると,確かに2番目の要素Times[Power[a,-1],b,Power[c,Rational[-1,2]]]の1番目の要素はPower[a,-1]となっている.このように,ある特定の要素にだけ作用させたい場合,まず,その要素の位置を,Positionを用いて

    myPos = Position@myEx, aD881

  • とする方が便利であろう.同様に,Pointの属性として点の大きさを指定したい場合はPointSizeを用いて, [email protected], Point@#D< & ê@ myPointData

    [email protected], Point@81, 3

  • ¤  上記のコ−ドを解析せよ.

    à 1.6.4 Mapの応用

     ここではMapの具体的な応用例をいくつか述べる.(1)10進数表記における最初の桁 もう少し難しい例を示そう.関数を

    headIn[x_]:= First[IntegerDigits[x]] == 1

    と定義するする.関数の定義の仕方は後章で詳しく述べるが,これが何を意味するかは,たとえば,

    {IntegerDigits[153],headIn[153]}

    881, 5, 3

  • 1 2 3 4 5 6

    −1

    −0.5

    0.5

    1

    とすると,{Sin[x],Sin[1/x]}をPlotにMapするので2個の関数を表示したグラフができる.次に,

    Map@Plot@#, 8x, 0, 2 π

  • ListPlot@#, PlotJoined → TrueD & ê@ 8Prime@Range@200DD

  • MapIndexed@f, 8x, y, z

  • 8f@Point@80, 0

  • ¤  このプログラムを解析せよ.

     最後に,行列に対して適用しよう.8MapIndexed@f, a@3, 2D, 81

  • となる.したがって,関数 fは変数が3個あるような関数に限られ,sinのような1個の変数を対象にする関数であればエラーになる.上記のように fと記しただけでは,変数に関してはMathematicaは分からないので適当に解釈し,エラーはでない.

    ¤  リスト 88a, b

  • とすればいい.同じ演算をいろいろなリストに対して計算できるように,少々拡張しよう.8a, b, c

  •  Mapと同様にApplyにもオプションとしてレベルがある.これまで述べた用法はレベル81

  • 100 200 300 400 500

    0.2

    0.4

    0.6

    0.8

    1

    を示しておこう. グラフィックスで良く用いるApplyの適用例を示そう.平面上の複数の位置8x, y

  • 1 2 3 4 5 6

    −1

    −0.5

    0.5

    1

    としよう.このような使い方は普通はしないが図は描ける.これまで述べた例との違いは,Plotには二つ

    変数があり,第1変数は表示する関数で,第2変数は表示の範囲である.したがって,Plotに適用するApplyに与える変数は,上記にように関数と表示範囲を対にしたリストでなければならない.二つの関数を同時に表示したいならば,

    Plot @@ 88Sin@xD, Cos@xD

  • −1 −0.5 0.5 1

    −1

    −0.5

    0.5

    1

    とすることも可能である.ただし,この例でのリストの構造に注意しよう.この場合,#(#1と同じ)は{Sin[x],Cos[x]}を指し示す.ほとんど同じことであるが,

    Plot@8#1@@1DD@xD, #1@@2DD@xD

  • 88f@aD, f@bD, f@cD

  • Thread@Hold@2 3 + 4ê5D, PlusDHold@2 3D + HoldA 4

    5E

    とすると,積をHoldで未評価のままにしておき和をとる.この値に

    MapAt@ReleaseHold, %, 81

  • がある.一つ具体例を述べる.複数の行列を比べて,対応する位置にある要素の大きい値で行列を構成しよう.まず,三つの行列を

    MatrixForm ê@8m1 = 881, 5

  • à 1.6.9 Sequence

     最初はSequenceの使い方には少々戸惑うかもしれない.今,変数が3個ある関数があって, f Ha, b, cLとしよう.そして,リストを

    limits = 8a, b, c

  • SumA ‰i=1

    Length@nDa@iDj@iD, Table@8j@iD, n@@iDD

  • Sequence @@ Table@8j@kD, −1, 1, 2

  • (2)リストのの深さ リストの深さはベクトルで1,行列で2である. ArrayDepthはリストの深さを返す関数で,

    ArrayDepth ê@ 98a, b

  • とする.以上のことをまとめると,nを配列の深さを表すパラメータとすると,nに関するTableを用いて

    MatrixForm ê@ Table@Table@a, Evaluate@Sequence @@ Table@82