パターン適用範囲の制限
Mathematica は,パターンに制約条件を指定するための一般化された機構を提供している.単に,パターン記述の後に書式
/;condition の条件を加えればよい.そうすると,制約条件が
Trueになる場合に限り,パターンを適用する.ここで,記号
/;はスラッシュ・セミと読み,その意味は「何々の,場合に限り」と解釈する.
| pattern/;condition | 条件が満たされたときのみマッチするパターン |
| lhs:>rhs/;condition | 条件が満たされたときのみ適用する変換規則 |
| lhs:=rhs/;condition | 条件が満たされたときのみ適用する定義 |
パターンと変換規則の適用範囲の限定
引数 nが0より大のときだけ適用する定義を関数 facに与える. |
| Out[2]= |  |
|
| Out[3]= |  |
|
/;は,個々のパターンだけでなく,
:=の関数定義式や
:>の変換規則にも使える.そのときも,式や規則の末尾に書式
/;conditionを使い制約条件を加えることで,特定の条件が満たされるときだけに定義や変換規則が適用されるようにすることができる.ただし,注意点として,この
/;条件は,通常,
=の定義や,
->の変換規則に使ってはならない.
「即時的な定義と遅延的な定義」で述べるように,これらの式は直ちに評価されてしまうからである.
この方法でも,引数 nが正の値を取るときだけに適用される定義を与えることができる. |
| Out[5]= |  |
|
演算子
/;を使い,規則の適用範囲を任意な数学的条件で制限することも可能である.通常の場合,広範な式と構造的にマッチするパターンを使い,数学的な制約条件で式の範囲をずっと小さな集合にできる.
この規則は, v[x_, 1-x_]の構造を持つ式にだけ適用される. |
この式は規則と同じ形なので規則が適用されることになる.
| Out[7]= |  |
|
この式は,数学的に同じ形を取っているが,構造が違う.このため規則は適用されない.
| Out[8]= |  |
|
この規則は,条件 y 1-xが付いているので, w[x_, y_]の形の式ならばどれにでも適用される. |
| Out[10]= |  |
|
パターンと変換規則を組み合せて設定する際,式によっては,
/;の制約条件を加える位置を選択することができる.例えば,
lhs:>rhs/;condition とすれば,規則の右辺に条件を加えることができるし,
lhs/;condition->rhs とすれば,左辺に条件を加えることができる.さらに,左辺
lhs の内部に条件を挿入することも可能である.ただし,制限事項が1つある.それは,制約条件が付加されたパターンの記述において,すべてのパターンの参照名が明記されている必要がある,という事項である.これがないと,実際に制約条件を評価する際に,必要な参照名がまだパターンマッチングのプロセスに組み込まれていないという状況に陥ってしまい,制約条件の評価が続けられなくなってしまう.そうなると,パターンマッチングから参照したはずのオブジェクトは使えなくなるので,代りに,変数には大域的な値が適用されることになる.
例を見てみよう.
f[x_, y_]/;(x+y<2)で示される制約条件は,
f[x_, y_]のパターンマッチングから得られる変数
x,
yを必要とする.この式を
f[x_/;x+y<2, y_]と書き換えたとすると,条件の評価に必要な
yはパターンマッチングから取得できなくなってしまう.このため,代りに
yには大域的な値が適用される.
適切な参照名がパターンに与えられていれば,なるべく小さいパターンを選び,そこに
/;の制約条件を適用するようにしておくと検索効率を向上させることができる.その理由は,パターンマッチングはパターン式の先頭から末尾に向かって要素の1つずつに対して行われるので,
/;の制約条件が早く見付かれば見付かるほど候補を早く絞り込めるからである.
パターン全部に制約条件 /;を適用させるより, x_にだけ適用した方がわずかではあるが,効率が上がる.
| Out[11]= |  |
|
複文型の従属部に制約条件 /;を使う場合は丸カッコでくくっておかなければならない.
| Out[12]= |  |
|
/;を使いパターンと変換規則を設けるときは,特定の性質や型を持つ数や式に限って適用可能になるようにするのが普通である.
Mathematica には式の性質を識別するための組込み関数が用意されているので,それらを使い判定作業を行うとよい.組込み関数には,英語の「質問」を意味する単語「Question」から取ったローマ字
Qで終る名前が付いているので分かりやすいだろう.
| IntegerQ[expr] | 整数 |
| EvenQ[expr] | 偶数 |
| OddQ[expr] | 奇数 |
| PrimeQ[expr] | 素数 |
| NumberQ[expr] | 数 |
| NumericQ[expr] | 数値 |
| PolynomialQ[expr,{x1,x2,...}] |
| x1, x2, ...の多項式判定 |
| VectorQ[expr] | ベクトル判定 |
| MatrixQ[expr] | 行列判定 |
| VectorQ[expr,NumericQ], MatrixQ[expr,NumericQ] |
| 数判定付きベクトル判定(数判定付き数行列判定) |
| VectorQ[expr,test], MatrixQ[expr,test] |
| 関数 test がすべての要素にTrueを与える行列 |
| ArrayQ[expr,d] | 深度が d と同じである完全配列 |
数の型や数学的な性質を調べるための判定関数
この規則は,数の型を持つリスト要素だけに適用される.
| Out[13]= |  |
|
この定義は,要素を整数とするベクトルについてだけ適用される. |
この定義は,この場合,最初のケースにだけ適用される.
| Out[15]= |  |
|
上記の判定関数を使う際の注意点として,判定する式の型や式の性質が確定していない場合,判定関数は
Falseを返す,ということがある.
| Out[16]= |  |
|
xは未知数なので型は未定である.このため, Falseが返される.
| Out[17]= |  |
|
IntegerQ[x]のような関数は,
x が明示的な整数かどうかを判定する.
x
Integersのような推定の場合,
Refine,
Simplifyあるいは関連関数を使って,記号変数
x についての推測をすることができる.
SameQ[x,y] または x y | x とy は等しい |
UnsameQ[x,y] または x y | x とy は等しくない |
| OrderedQ[{a,b,...}] | 標準的な並び順でリスト要素 a, b, ... が配置されているかどうかを判定する |
| MemberQ[expr,form] | 式expr の要素にform にマッチするものがあるかどうか |
| FreeQ[expr,form] | 式expr の要素にform がないかどうか |
| MatchQ[expr,form] | 式expr がパターンform にマッチするかどうか |
| ValueQ[expr] | 式expr に特定値が定義されているかどうか |
| AtomQ[expr] | 式expr が部分式を持たない最小単位のものかどうか |
式の構成上の性質を調べるための判定関数
2重イコール(  )の式は,シンボル的な形のまま維持される.3重イコール(  )は,両辺の式が明らかに等しくなければ Falseを返す.
| Out[18]= |  |
|
式 nは,リスト {x, x^n}の「メンバー」ではない.
| Out[19]= |  |
|
| Out[20]= |  |
|
FreeQを使い, hに関する「線形性」規則を定義することができる. |
| Out[22]= |  |
|
| pattern?test | 判定 test の判定結果をTrueとする式だけにパターンを適用する |
パターン適用範囲のもうひとつの限定法
条件構築
pattern/;condition を使うことで,パターン名を含む条件を評価させ,適合するものがあるかどうかを判定させることができる.これに対して,条件構築
pattern?test を使うと,任意関数
test がパターンマッチングされた式全体に適用され,適合するものがあるかどうかが判定される.場合によっては,
/;の代りに
?を使った方がよりコンパクトな形の定義にすることができる.
この定義では, x_により抽出される前に NumberQで型が数かどうかを判定される. |
この定義は, pが数的な引数を持つときだけに適用される.
| Out[24]= |  |
|
さらに複雑な定義を使う.純関数を丸カッコでくくることを忘れないように注意. |
| Out[26]= |  |
|
| Except[c] | c 以外のすべての式にマッチするパターン |
| Except[c,patt] | patt にはマッチするがc にはマッチしないパターン |
例外を含むパターン
| Out[27]= |  |
|
| Out[28]= |  |
|
| Out[29]= |  |
|
Except[c]は,
c 以外の「あらゆるもの」にマッチする,ある意味できわめて一般的なパターンである.場合によっては,
patt にマッチする式から始めて,次に
c にマッチする式を除外する
Except[c, patt]を使わなければならないこともあるだろう.