命題は真偽が定まっていますが、数学で扱う文の多くは変数を含み、値を決めるまで真偽が定まりません。その扱い方を定めます。
1 真理集合
定義 1.1 (条件). 変数を含み、それぞれの変数が動く範囲の中で値を与えると真偽が定まる文や式を条件 (condition) という1。
たとえば、が実数の範囲を動くとき、「」は条件です。を代入すれば真、を代入すれば偽になります。
定義 1.2 (真理集合). 変数が動く範囲を集合とし、の各要素について真偽が定まる条件をとする。の要素のうち、を真にするものをすべて集めた集合
を、条件の真理集合 (truth set) という2。に対して、「が条件を満たす」ことと「」とは同じ意味である。
同じ全体集合上の条件、の真理集合を、それぞれ、とします。条件を論理演算で組み合わせたときの真理集合は、次のようになります。
| 条件 | 真理集合 |
|---|---|
| かつ | (共通部分) |
| または | (和集合) |
| でない | (補集合)3 |
また、「ならば」がすべてのについて成り立つことは、のどの要素もの要素であること、すなわちと同じです。
例 1.3. 全体集合をとし、を「は偶数である」、を「はの倍数である」とする。真理集合はそれぞれ、である。条件文が偽になるのは、が真でが偽の場合だけである。したがって、偽になる値の集合はであり、真になる値の集合はである。たとえばでは、前件が偽なので条件文は真である。条件文が真になるのは、が偽であるか、が真である場合である。したがって、その真理集合はとも書くことができる。実際、なので、となる。この真理集合はと一致しないため、「すべてのについてが成り立つ」という主張は偽である。とは、それぞれ反例になっている。
2 例:整数についての条件
例 2.1. 全体集合を整数全体とし、二つの条件を次のように置く。
- :はの倍数である。真理集合をと書く。
- :はの倍数である。真理集合をと書く。
の倍数はすべての倍数なのでが成り立つ。これは条件の言葉では「ならば」がすべての整数について成り立つことにあたる。逆向きの包含は成り立たない。はに属してに属さないからである。
図は、二つの条件がこの包含関係にある場合を1枚描いたものです。包含が成り立つ根拠は、がの倍数であればと書くことができ、よりの倍数である、という議論のほうにあります。
同じ全体集合のもとで、共通部分と和集合も読み替えることができます。であり、これは「の倍数かつの倍数」が「の倍数」と同じ条件であることに対応します。であり、これは「の倍数またはの倍数」が「の倍数」と同じ条件であることに対応します。
3 補集合は全体集合の取り方で変わる
条件の否定を補集合として読み替えるときは、全体集合が何であるかを先に決めておきます。同じ条件であっても、全体集合を変えると補集合が変わるからです。
例 3.1. 条件:を考える。
- 全体集合を整数全体とすると、なので、はとを除く整数全体である。、、などがに属する。
- 全体集合を正の整数全体とすると、なので、は以上の整数全体である。はそもそも全体集合に属さないため、の要素にならない。
- 全体集合をとすると、なので、である。このとき「」を満たす要素は一つも無い。
三つの場合で、条件そのものは変わっていません。変わったのは、が動く範囲としてどの集合を取るかだけです。「この条件を満たさないもの」と言うときは、何の中で満たさないのかを指定しなければ、集合が定まりません。
閑話休題:論理の、もう一つの対応先 本記事では、論理を集合へ対応させました。「かつ」は共通部分、「または」は和集合、「ならば」は包含です。では、対応先は集合だけでしょうか。実は、もう一つの対応先があります。型です。
プログラミングでは、値に「整数型」「文字列型」といった型というラベルを付けます(型は、その型が取りうる値の集合のようなものだと考えてください)。驚くべきことに、論理と型のあいだにも、集合のときと同じ対応表を引くことができます。本記事の表に、右の1列を加えます。
| 論理 | 集合(本記事) | 型 |
|---|---|---|
| かつ | 直積型(ペア) | |
| または | 直和型 | |
| ならば | 関数型 |
決定的なのは、命題を証明することができることが、その型のプログラムを書くことができることに対応するという点です。証明とプログラムが同じものの別の姿であるというこの対応を、カリー・ハワード対応と呼びます。
ここから先が興味深いところです。私たちが論理と聞いて思い浮かべるのは、一度正しいと分かった事実を何度でも使い回すことができる論理です。ところが、事実は高々一度しか使うことができない(捨てるのは自由であるが、複製はできない)という、一見すると何の役に立つのか分からない論理を考えることができます。アフィン論理です。カリー・ハワード対応によってこの論理を型の世界へ移すと、値を高々一度しか使うことができない型システム、すなわち Affine 型が現れます。
この「一度きり」という制約が、現実の場面で決定的に効きます。メモリの一区画に持ち主が一人しかいなければ、解放済みのメモリを二度使う(use-after-free)という古典的なバグが原理的に起こりません。プログラミング言語 Rust は、この考え方をもとに所有権システムを設計し4、メモリ安全性をガベージコレクタではなく型のレベルで保証します。型検査が通れば、その時点でメモリ安全が確保されているということです5。
型のレベルでメモリ安全性を保証することがどれほどのことかを考えてみます。サイバー攻撃に悪用される脆弱性のうち約7割はメモリ安全性のバグが原因であると報告されています。コンパイル時にそれを根絶することができれば、従来は取り切ることができなかった脆弱性の大半を原理的に排除することができます。使い回すことのできない事実の論理という、役に立つのかどうかも怪しい抽象理論が、世界のソフトウェアの安全性を支える土台になっています。本記事で扱った論理と集合の対応から、一続きにたどることのできる話です。