|
2.3.1 パターンとは
Mathematicaでは,「パターン」がクラスを表すためによく使われる.簡単なパターンの例としてはf[x_]がある.このパターンは,f[anything]の形を持った式のクラスを表している.(anythingは,任意の引数を表す.)
Mathematicaの多くの操作は,単一式だけでなく,式のクラスを表したパターンでも行うことができる.このため,パターンは大きな威力を持っているといえる.
変換規則にパターンを使うこともできる.こうすると,特定の式をどのように変換するか指定できる.
In[1]:= f[a] + f[b] /. f[x_] -> x^2
Out[1]= 
パターンを使い,特定クラスに属するすべての式に対してそれらの位置を検索させることもできる.
In[2]:= Position[{f[a], g[b], f[c]}, f[x_]]
Out[2]= 
ほとんどのパターンにおいて基本となるオブジェクトは,_(ブランクと呼ぶ)である._は任意の式を表すものとされ,これは基本的な規定になっている.
したがって,例えば,パターン f[_]は,形をf[anything]とした,任意の引数anythingが備わった式なら何でも表す.これに対して,パターンf[x_]は,f[anything]形の式なら何でも表すという点で同じだが,式anythingに参照名xを与えるという点で違う.名前が付くので,変換規則の右辺においてその引数を参照することができるようになる.
ブランクは式のどこにでもおくことができる.ブランクを使うことで,「ブランク(空の穴)を埋めることができる」式であれば何でもマッチするパターンを作ることができる.

パターンの例
どんな構成の式であってもパターンは構築できる.
In[3]:= f[{a, b}] + f[c] /. f[{x_, y_}] -> p[x + y]
Out[3]= 
よくあるパターンの使い方に「式の構成の簡素化」がある.どういうことかを説明しよう.例えば,リストの特定要素2つを引数とする関数を検索するためのパターンを作るとする.まず,パターンをf[list_]としたとすると,リストの要素を抽出するにはPartのような関数を使う必要がある.しかし,この場合,引数は2つと判明しているので,代りにf[{x_, y_}]に対して定義を与えた方が通常より簡単で便利である.そうすれば,リストの要素をxとyの名前で直接参照することができる.さらに,引数はリスト形式で与えるので,Mathematicaはlistの頭部を持ったオブジェクトしか受け付けず,入力間違いを起こすこともなくなる.
これは,2要素からなるリストを使う関数を定義し,第1要素を第2要素を指数としたベキとして評価するための方法である.
In[4]:= g[list_] := Part[list, 1] ^ Part[list, 2]
パターンを使い同じ定義を作る.この方が分かりやすくなる.
In[5]:= h[{x_, y_}] := x ^ y
ここで理解してほしい重要な点は,Mathematicaのパターンは任意構造を持った式のクラスを表す,ということにある.もしもパターンの構造が特定の式の構造と同じであるならば,パターンに現れるブランクを適当なオブジェクトで充填することで同じ式を得ることができる.したがって,パターンは式にマッチする.数学的に同じ値の式が2つあったとしても,式の構造が違えば,それらは同じパターンで表すことができない.
このため,例えば,パターン(1 + x_)^2は,(1 + a)^2と(1 + b^3)^2等の式を表すことができるが,1 + 2 a + a^2は表せない.後者は,数学的に(1 + a)^2に等しいが,パターン(1 + x_)^2と同じ構造を持ち合わせていない.
パターンが式の構造を特定するという事実は,ある式に対してその数学的同値性を維持したまま,その構造だけを変えることができる変換規則を設定する上で重要な意味を持つ.
一般論として,Mathematicaで,構造的ではないが数学的に等価なパターンマッチングを行うことはほとんど不可能である.(1 + a)^2や1 + 2 a + a^2のような式であれば,ExpandやFactor等の関数を使い,式が数学的に等しいかどうかを決定することができる.しかし,2.6.2で触れるように,任意な2つの数式が等しいかどうかを判定することができる一般的な方法は存在しない.
もう1つの例を見てみよう.パターンx^_はx^2にマッチする.しかし,1にはマッチしないが,1は,x^0ととらえることができる.(2.3.9で説明するが,この問題に限り特別にマッチするパターンを記述することは可能である.)どのようなケースであっても,基本的に,Mathematicaのパターンマッチングは構造的な等価性を判定するためにある.
x^n_はx^2とx^3だけにマッチする.数学的には1とxはともに の形で表せるが,式の構造が違う.
In[6]:= {1, x, x^2, x^3} /. x^n_ -> r[n]
Out[6]= 
認識してほしいもう1つの点として,Mathematicaがパターンマッチングに使う構造は,FullFormにより記述された式の完全形による,ということがある.これがどういう意味を持つかというと,例えば,1/xは完全形でPower[x, -1]と書けるので,x_^n_のパターンにマッチする.しかし,x_/y_のパターンにはマッチしない.なぜなら,x_/y_は完全形ではTimes[x_, Power[y_, -1]]であるからである.この不一致の問題は,前述の1とx_^n_の場合と同じで,2.3.9で説明するパターン記述を使えば解消することが可能である.
完全形で見ると,この式は,すべてbの 累乗項からなっている.このために,パターンb_^n_を使った変換規則を適用することができる.
In[7]:= {a/b, 1/b^2, 2/b^2} /. b^n_ -> d[n]
Out[7]= 
これが,リストの完全形である.
In[8]:= FullForm[{a/b, 1/b^2, 2/b^2}]
Out[8]//FullForm= 
Mathematicaのパターンマッチングでは, の関係に代表されるような数学的に等しいかどうかの関係は調べられない.特定の構造的な性質に関した同値であるかが調べられる.例えば,可換則や結合則等の性質はパターンマッチングの考慮に入れられる.
変換規則の適用において,加法で有効な可換則と結合則が使われる.
In[9]:= f[a + b] + f[a + c] + f[b + d] /. f[a + x_] + f[c + y_] -> p[x, y]
Out[9]= 
これまでは,任意の式を表すことができるx_等のパターンオブジェクトを見てきた.続く節では,Mathematicaで使われる,パターンで表された式のクラスを拡張したり,限定したりするための構造体を見ていく.
|