Mathematica

概要

ウルフラム・リサーチの創始者であるスティーブン・ウルフラムと彼のチームは、1986年から新たな数式処理システムの開発を開始し、1988年にその最初のバージョンをリリースした。ウルフラムは当初、このシステムをOmega、のちにPolyMathと呼んでいたが、当時NeXT社の社長であったスティーブ・ジョブズに相談したところ「ダサい名前だ」と一蹴され、なにか一般的な語をロマンチックに表現したもの、例えばトリニトロンのような名前が良いとして「Mathematica」と名付けられた。
歴代のMathematicaのロゴに使われているのは「スパイキー」と呼ばれる三次元多面体で、初代 Mathematicaでは大二十面体、それ以降のバージョンでは双曲二十面体を装飾したものが使われている。
プログラミング言語としてのMathematicaは、項書き換えを基本として関数型と手続き型の両方をサポートするマルチパラダイム・プログラミング言語である。Mathematicaは、ウルフラムらが1979年頃に開発した Symbolic Manipulation Program を起源とし、プログラミング言語ALGOL・LISP・APL、および数式処理システムMacsymaの影響を受けている。
MathematicaはC/C++およびJavaで実装されているが、拡張可能なライブラリはすべてWolfram言語で書かれている。実際、新しいコード（Wolfram言語で書かれたテキストファイル）はMathematicaの「パッケージ（.mファイル）」として追加される。Mathematicaには4,000以上の高度に洗練された組み込み関数が用意されており、それらをビルディング・ブロックとして組み合わせていくことで、簡単にプログラムを作ることができる。
システムとしてのMathematicaは、Wolfram言語を解釈し実際に計算を実行する「カーネル」と、その計算結果を表示する「フロントエンド」の2つの部分から構成される。カーネルとフロントエンドの間の通信には「MathLink」プロトコルが使われる。
Mathematica日本語版の最新バージョンは 12.0（2019年5月リリース）で、様々なコンピュータシステム上で利用可能となっている。

インタフェース

システムとしてのMathematicaは、ユーザーとの対話を行う「フロントエンド」と、演算を実行する「カーネル」の2つの部分から構成される。フロントエンドはMathematicaシステムのGUIを担当する部分で、自動構文カラーリング、入力補完、デバッガなどの開発ツールの機能がある。また、一般的なワードプロセッシング機能の大部分もサポートしている。
フロントエンドとカーネルは互いに独立に起動し、「MathLink」と呼ばれるプロトコルを使って通信している。実際、Mathematicaを起動した時点ではカーネルは起動しておらず、フロントエンドで最初の計算が実行された時にはじめてカーネルが起ち上がる。

ノートブック

Mathematicaの標準的なフロントエンドである「ノートブック」は対話型のドキュメントで、データ・数式・テキスト・コード・演算結果・グラフィックス・表・GUIコンポーネント・アニメーション・音声などを混在させることができる。ノートブックはウルフラム・リサーチの共同創始者であるセオドア・グレイによって設計され、Mathematica 2.0より採用された。
一つのノートブックの中でデータの処理から可視化、さらに文書作成までをシームレスに行えることが、Mathematicaの最大の利点の一つである。ノートブックにおいては、ユーザーの入力（テキストと Wolframコード）やカーネルの演算結果（グラフィックやサウンドも含む）は、すべて階層化された「セル」に納められ、文書のアウトライン化やセクション分割が容易に行える。
ノートブックの中身はすべてWolfram言語で記述されており、それ自体を Wolfram 言語で生成・修正・解析することが可能である。ノートブックからTeXやXMLなどの他のフォーマットへの変換は、この機能を用いた構文解析を通じて実現されている。

代替フロントエンド

Mathematica標準のノートブック以外にも、代替のフロントエンドが存在する。2006年にはEclipseベースのIDE、Wolfram Workbenchが登場した。プロジェクトベースのコード開発ツールとなっており、リビジョン管理、デバッグ、プロファイル、評価などの機能がある。またMathematicaには、テキスト型インタフェースが同梱されており、UNIXコマンドラインから直接カーネルを呼び出し対話することも可能である。

高性能計算

1999年のバージョン4でパックアレー、2003年のバージョン5で疎行列を導入し、GNU Multi-Precision Library を採用して高精度演算が可能となり、高性能計算向け機能が拡張された。
バージョン5.2 (2005) では、マルチコアコンピュータ上で動作する際に自動的にマルチスレッド化する機能を追加した。このバージョンから CPU 毎に最適化されたライブラリを採用している。また、ClearSpeed などのサードパーティ製高速化ハードウェアが Mathematica をサポートしている。
2002年、異機種混在型クラスターやマルチプロセッサシステムでのユーザレベルの並列計算を可能にする gridMathematica をリリース。2008年には、並列計算技術は通常の Mathematica ライセンスに含まれるようになり、Windows HPC Server 2008、Microsoft Compute Cluster Server、Sun Grid をサポートするようになった。
2010年からCUDAおよびOpenCL対応のGPUハードウェアをサポート。またバージョン8ではC言語コードを生成でき、Intel C++ CompilerやVisual Studio 2010のコンパイラで動的にコンパイルできる。

他のアプリケーションとの接続

MathLinkプロトコルは、Mathematicaのカーネルとフロントエンド間の通信だけでなく、任意のアプリケーションとカーネルとの通信にも使われる。Mathematicaは豊富な機能を備えているが、他のプログラムの機能を利用したり、古いコードにアクセスするためにいくつかのインタフェースが開発されてきた。

C、Java、.NET、データベース、Rとの接続

ウルフラム・リサーチはMathematicaカーネルとのMathLinkによる通信を行うアプリケーション開発者向けにC言語での開発キットを無料で配布している。
J/Linkと.NET/Linkは、それぞれMathLinkをベースにしたJavaおよび.NET用のコンポーネントである。J/Link を使うと、JavaプログラムからMathematicaに計算を依頼することができ、MathematicaプログラムがJavaのクラスをロードし、Javaオブジェクトを操作したりメソッドを呼び出したりできる。そうすると、例えばMathematicaから Java の GUIを構築できる。同様に、.NET/Linkを使えば.NETプログラムと同様のことが可能になる。
DatabaseLinkはSQLデータベースを扱うためのツールキットで、JDBC接続とODBC接続をサポートしている。RLinkは統計解析向けプログラミング言語Rと交信し Mathematica内からRのコードを実行するもので、バージョン9から正式にサポートされた。

その他の接続

その他にMathematicaと接続できるプログラミング言語としては、Haskell、AppleScript、Racket、Visual Basic、Python、Clojureがある。数学関係のソフトウェアでは、OpenOffice.org Calc、
Microsoft Excel、MATLAB、SINGULAR、Originに接続可能である。
Mathematicaはリアルタイムのデータストリームを受け付けることもでき、LabVIEW、金融関係用、GPIB (IEEE 488)、USB、シリアル接続などの方法がある。HIDデバイスからの入力を自動的に検出して読み込むこともできる。最近ではLEGO マインドストームで作ったロボットをBluetooth通信を介して操作する試みもなされている。
2014年1月6日、ウルフラム・リサーチは、Wolfram言語と外部装置の接続利用促進に向けたプロジェクトWolfram Connected Devices Projectを起ち上げた。

対応プラットフォームとライセンス

Mathematica 10は、Microsoft Windows（Vista・7・8）、macOS（10.6〜10.10）、Linuxの各種バージョンで動作する。どのプラットフォームも64ビット版をサポートしている。過去にサポートしていたOSとしては、NeXTSTEP、Solaris、AIX、Convex、HP-UX、IRIX、MS-DOS、OS/2、Ultrix、Windows Me、Windows XPなどがある。

ライセンス

Mathematicaはプロプライエタリなシステムであり、設定価格は比較的高めである。日本での商用版シングルユーザーライセンスの販売価格は423,500円で、これには、並列計算用の追加のカーネル、1年間のプレミアサービス、家庭での利用を許可するライセンス、Wolfram Lightweight Grid Manager、Wolfram Workbench、webMathematica Amateur Editionのライセンスが含まれる。一方で、政府機関、非営利組織、教育機関、学生、家庭用に向けては低価格を設定している。例えば、学生向けの製品（内容は正規品と同じ）は正規価格の5%程度で購入できる。教育機関向けライセンスで契約した場合、学生は家庭でもMathematicaを利用可能である。指定された数の Mathematica をネットワーク上で同時に起動できるネットワークライセンスも用意されている。
Mathematicaの価格設定は地域によっても大きく異なる。米国においては、商用版2,745ドル、学生版140ドル（日本では25,000円）、家庭版295ドル（日本では67,000円）となっている。日米での価格差は、電話対応を含め、国内宛に日本語で問い合わせができる点や、日本語技術サポート、有償セミナーの半額割引（一部代理店のみ）等のサービスの差により生じている。

無料バンドル

2013年11月21日、ウルフラム・リサーチとラズベリーパイ財団は、すべてのRaspberry PiにWolfram言語とMathematica 10のパイロット版を無料でバンドルすることを発表した。これにより、Raspberry Piの計算速度の問題は残るものの、Mathematicaの全機能を実質25ドル（Raspberry Pi Model A のボード1枚の価格）で利用できることになった。Mathematicaがコンピュータに無料でバンドルされるのは、1988年のNeXT以来、25年ぶり2度目の出来事である。
2014年1月6日、ウルフラム・リサーチとインテルは、2014年夏頃に発売予定のSD カードサイズコンピュータ Intel EdisonにWolfram言語とMathematicaを標準搭載すると発表した。

例

方程式 eˣ = x² + 2 において x = -1 を開始点としてその根を数値的に求める。
In[1]:= FindRoot[Exp[x] == x^2 + 2, {x, -1}]
Out[1]= {x -> 1.3190736768573652}
次の例では、インデックスの原点を0とする 6 × 6 の行列で i、j 番目のエントリの値が ij であり、0のエントリを1に置き換えたものの行列式を求めている。そのような行列式は0である。
In[2]:= Det[Array[Times, {6, 6}, 0] /. 0 -> 1]
Out[2]= 0
一般的なプログラミング言語と大きく異なる点として、Mathematica ではリストのインデックスが 1 から始まることに注意が必要である。

マルチパラダイムと一つの言語

Mathematicaはマルチパラダイム・プログラミング言語であり、一つの問題に対して複数のアプローチを取ることが可能である。
ここでは簡単な例として、最大公約数 GCD(x, y) のテーブルを作る問題を考える（ここで、1 ≤ x ≤ 5、1 ≤ y ≤ 5 とする）。これには、少なくとも次の4つのアプローチが考えられる。
1. 関数型のアプローチ：
In[3]:= Array[GCD, {5, 5}]
Out[3]= {{1, 1, 1, 1, 1}, {1, 2, 1, 2, 1}, {1, 1, 3, 1, 1}, {1, 2, 1, 4, 1}, {1, 1, 1, 1, 5}}
このアプローチは、表現が抽象的ではあるが、組み込み関数の性能を十分に引き出しており、簡潔で計算速度も速い。Array は引数として任意の関数を許容する（名前があるかどうかを問わない）ので、スロット #n を使って、& の後に対応する関数を記述することができる。したがって、上記の関数は Array[GCD[#1, #2]&, {5, 5}] とも記述できるが、Mathematicaではそれを上記のように省略してもよいようになっている。
2. APL 的なアプローチ：
In[5]:= Outer[GCD, Range[5], Range[[5]]
Out[5]= {{1, 1, 1, 1, 1}, {1, 2, 1, 2, 1}, {1, 1, 3, 1, 1}, {1, 2, 1, 4, 1}, {1, 1, 1, 1, 5}}
ここで、Outer とRange はそれぞれ APL の外積演算子とイオタ演算子に対応している。Outer も Array と同様、引数として任意の関数を許容する。
3. Table を使うアプローチ：
In[4]:= Table[GCD[x, y], {x, 1, 5}, {y, 1, 5}]
Out[4]= {{1, 1, 1, 1, 1}, {1, 2, 1, 2, 1}, {1, 1, 3, 1, 1}, {1, 2, 1, 4, 1}, {1, 1, 1, 1, 5}}
Table は任意の次元の表を作るのに使われる標準的な関数である。このアプローチは、GCD の取る引数が明示的で、直感的に理解しやすい。反面、上記1・2に比べると計算速度で若干劣る。
4. 手続き型のアプローチ：
In[6]:=
    lst1 = {}; (* 空のリストを初期化 *)
    For[i = 1, i <= 5, i++,
        lst2 = {}; 
        For[j = 1, j <= 5, j++,
            lst2 = Append[lst2, GCD[i, j]]
        ]; 
        lst1 = Append[lst1, lst2]; (* 部分リストを繋ぐ。これが行となる *)
    ];
    lst1
Out[6]= {{1, 1, 1, 1, 1}, {1, 2, 1, 2, 1}, {1, 1, 3, 1, 1}, {1, 2, 1, 4, 1}, {1, 1, 1, 1, 5}}
これは C 言語や FORTRAN などで馴染み深いアプローチである。しかし、組み込み関数を使った場合（上記1~3）に比べるとコードが冗長である。また、手続き型のアプローチは計算速度が遅くボトルネックになりやすいので、注意が必要である。
以上の例で見たように、Mathematicaプログラミングにおいては、組み込み関数を最大限に利用することが非常に重要である。Mathematicaの組み込み関数を有効に使うことで、問題を簡潔に表現することができる。また、Mathematicaの組み込み関数は、適切なアルゴリズムを用い、高度に最適化され、かつC言語で実装されているため、同じ機能を持つユーザー定義関数に比べて計算速度が圧倒的に速い。

すべては「式」である

Mathematicaは「すべては式である (Everything is an expression.)」という思想のもとに設計されている。ここで言う「式 (Expression)」とは、アトムと関数である。
Mathematicaにおいて、数式・リスト・グラフィックスを含むすべてのオブジェクトは head[e₁, e₂, ...] という共通の基本構造を持つ。そして、この構造は入れ子にできる（つまり、e₁ や e₂ もまたこの構造を持てる）。したがって、どんなに複雑なオブジェクトでも、この基本構造とその再帰的な繰り返しで表現できる。
例えば、x^4+1 という式を入力すると、出力は以下のように表示される。
In[7]:= x^4 + 1
Out[7]= 1+x⁴
FullForm を使うと、この式の完全形（Mathematica における内部表現）を見られる。
In[8]:= FullForm[x^4 + 1]
Out[8]= Plus[1, Power[x, 4]]
上記の例では、Plus が head であり、Power[x, 4] が入れ子になっている。x のような記号も実は Symbol["x"] という構造を持っている。
リストも List を head とする同様の構造である。例えば、x^4+1 と {1, x^4} という2つの表現は、外見はまったく異なるが、完全形で見れば head が Plus か List かの違いしかない。
この基本構造により、リストとは無関係の普通の式をリスト演算子で処理できる。
In[9]:= Expand[(Cos[x] + 2 Log[x^11])/13][[2, 1]]
Out[9]= 2/13
逆も同様で、リストを普通の式のように扱える。
In[10]:= Map[Apply[Log, #]&, {{2, x}, {3, x}, {4, x}}]
Out[10]= {Log[x]/Log[2], Log[x]/Log[3], Log[x]/Log[4]}
ここで、Apply は第二引数の head を第一引数で指定されたものに置換する関数である。また、Map は関数型言語によく見られる高階関数 map である。
Mathematica では、数学的オブジェクトがリスト構造と等価であるため、組み込み関数のいくつかは「スレッディング」可能であり、特に指定しなくてもリスト上の各要素にマップされるときにマルチスレッド化される。実際、Apply は次のような場合にマルチスレッド化される。
In[11]:= Apply[Log, {{2, x}, {3, x}, {4, x}}, 1]
Out[11]= {Log[x]/Log[2], Log[x]/Log[3], Log[x]/Log[4]}
第三引数 1 により、Apply によって置換するのがリストの最初のレベルであることが指定され、これは前述の例と等価である。