Metamath: введение в язык

Ниже идёт конспективное изложение языка Metamath из документа metamath.pdf. На сайте metamath.org собрано большое количество доказательств различных теорем формальной логики, теории множеств и т.п. математических дисциплин. Предполагается, что подобные доказательства, записанные на языке Metamath, являются формально безупречными и могут быть проверены многочисленными парсерами, понимающими синтаксис этого языка.


Языки и исчисления

Любая формальная теория является некоторым языком со своим алфавитом, словами и способами получения (вывода) новых слов (см. книгу). Символом может быть что угодно, лишь бы мы могли однозначно отличать один символ от другого.
Слово -- конечная, произвольная цепочка (упорядоченная последовательность) символов.

Язык -- это некоторое подмножество всех слов. Обычно существуют правила, позволяющие понять принадлежит данное слово языку или нет. Часто слово языка называется правильно построенной формулой (wff - well formed formula).

Исчислением - это язык в котором задано множество слов (формул), называемых аксиомами и правила вывода (получения) новых формул. Правило вывода -- это предписание, при помощи которого из формул определённого вида получается новая формула.


Базовый синтаксис Metamath

Документ Metamath (текстовый файл с расширением *.mm) начинается с определения констант и переменных.
Константы - это все символы языка которые нельзя менять (например, в арифметике: 0 1 + ( )).
Переменные - это слова, на место которых можно подставлять другие слова. Константы и переменные могут состоять из нескольких ASСII символов и всегда разделяются пробелом:
$c константы_через_пробел $. - все константы и символы языка (const),
$v переменные_через_пробел $. - перечень всех переменных (var),
$d var var $. - эти переменные должны быть различны (disjoint)
(запрет присутствия общих переменных при подстановках).

Переменные обязаны иметь фиксированный тип (логическая формула, терм, целое число и т.п). Тип - это произвольная константа, задаваемая внутри $c ... $.. Объявление типа сопровождается уникальным именем, меткой (label), которая ставится перед командой $f ... $. Для объявления слова аксиомой служит $a, а для теоремы с доказательством - $p. Некоторые аксиомы или теоремы могут требовать посылок или гипотез $e ... $.
label $f const var $. - объявление типа переменной (“floating” hypothesis),
label $e const symb ... symb $. - гипотеза перед $a или $p (“essential” hypothesis), symb = const | var
label $a const symb ... symb $. - аксиома,
label $p const symb ... symb $= proof $. - утверждение, доказательство которого содержится в блоке proof.

Кроме этого существуют комментарии, команды подключения дополнительных файлов и блоки директив языка:

$( comments $), $[ include_file_name $], ${ block of commands $}.

На этом описание базового синтаксиси Metamath окончено.


Исчисление высказываний

Рассмотрим пример исчисления высказываний с импликацией P -> Q и отрицанием !Q. В этом исчислении выводятся все правильно построенные логические формулы вида P -> Q, P -> ( Q -> R ), !!P -> P и т.п. Ниже, слева приведено описание такого исчисления с двумя аксиомами wn, wi. Эти аксиомы рекурсивно определяют что такое правильно построенная формула. Теорема th1 предъявляет пример такой формулы и доказательство.

$c -> ! ( ) |- wff $.    $( Declare the consts $)
$v P Q R S $.            $( Declare the vars   $)
 
wP  $f wff P $.          $( P is wff and so on $)
wQ  $f wff Q $.
wR  $f wff R $.
wS  $f wff S $.
 
wn  $a wff ! P $.        $( define formulae    $)
wi  $a wff ( P -> Q ) $.
 
th1 $p wff ( ! S -> ( R -> P ) ) $=
    wS wn
    wR wP wi wi
    $.
Сохраняем в файле demo1.mm Запускаем программу metamath.exe и в консоли набираем:
MM> read demo1.mm           (загрузка)
MM> verify proof *          (проверка доказательств)
Вывод описания доказательства теоремы th1 делаем командой "MM> show proof th1 /lemmon / all":
1 wS             $f wff S
2 1 wn           $a wff ! S
3 wR             $f wff R
4 wP             $f wff P
5 3,4 wi         $a wff ( R -> P )
6 2,5 wi         $a wff ( ! S -> ( R -> P ) )

В первой строчке файла объявлено 6 констант, среди которых зарезервирован также символ |- (выводимость). Во второй строке объявлено 4 переменных P, Q, R, S. Следующие 4 строки определяют тип этих переменных как правильно построенных формул (wff - константа исчисления).

Аксиома wn описывает как к произвольной формуле можно "присоединить" отрицание, а wi задаёт правило построения формулы с импликацией. Эти аксиомы подразумевают описание переменных, которые в них участвуют (в порядке появления в строке). Подобные описания называются гипотезами. Для аксиомы wn такая гипотеза одна (что подставлять вместо P), а для wi - гипотез должно быть 2 (для P и Q).

Наконец, последняя команда с меткой th1 и 11-ю символами между $p ... $=, является теоремой. Она утверждает, что строка "wff ( ! S -> ( R -> P ) )" - это правильно построенная формула. Доказательство теоремы находится между символами $= и $. Подчеркнём, что Metamath ни чего не знает о смысле wff. Это просто константа языка, как и все другие.

Metamath проверяет доказательство слева на право при помощи стека. Первоначально стек пустой. На первом шаге Metamath видит гипотезу wS и помещает её в стек:

[ 1: wff S ].
Следующая директива wn является аксиомой ($a), поэтому запускается процесс обработки. Аксиома имеет единственную переменную P типа wff (чтобы это не означало). Эта переменная объявлена ранее в строке wP $f wff P $. Metamath извлекает из стека один элемент (который там есть). Так как он начинается с wff, его можно использовать для подстановки и в аксиоме, вместо P пишется S. Результат снова помещается в стек:
[ 1: wff ! S ].
Далее идущие wR, wP не являются аксиомами и просто отправляются в стек:
[ 3: wff P, 2: wff R, 1: wff ! S ].
На 5-м шаге Metamath встречает команду wi, которая является аксиомой ($a) с двумя переменными P, Q типа wff. Поэтому из стека извлекаются 2 последние команды, wP, wR и проверяется, что они содержат в начале константу wff. Это так и Metamath делает подстановки (вместо P пишет R, а вместо Q пишет P). Результат wff ( R -> P ) снова заталкивается в стек:
[ 2: wff ( R -> P ), 1: wff ! S ].
На последнем шаге Metamath снова видит аксиому, требующую двух wff переменных. Извлечение их из стека и подстановка даёт доказываемую формулу:
[ 1: wff ( S -> ( R -> P ) ) ].  
Так как строка описания доказательства окончилась и в стеке находится единственный элемент, проверка доказательства теоремы th1 оканчивается успехом.


Обратная польская нотация

Использование стека приводит к тому, что все доказательства формируются по принципу обратной польской нотации (придуманной Лукашевичем). Например wP wQ wi это P->Q (бинарная операция -> ставится после её аргументов P и Q).

Разберём более сложный пример для формулы: (P->(Q->R))->((P->Q)->(P->R)).
Будем последовательно записывать каждую связку в обратной польской нотации:

(P->( wQ wR wi))->((wP wQ wi)->(wP wR wi)),
(wP (wQ wR wi) wi)->((wP wQ wi) (wP wR wi) wi),
(wP (wQ wR wi) wi) ((wP wQ wi) (wP wR wi) wi) wi
wP wQ wR wi wi wP wQ wi wP wR wi wi wi.
На последнем шаге скобки опущены, так как это выражение однозначно представимо в исходном виде. Для этого проходим по строке слева-направо. Как только встречаем символ операции (в нашем случае это wi), окружаем его и предыдущие его два аргумента скобками. Далее считаем содержание таких скобок "одним символом":
wP wQ wR wi wi wP wQ wi wP wR wi wi wi,
wP (wQ wR wi) wi wP wQ wi wP wR wi wi wi,
(wP (wQ wR wi) wi) wP wQ wi wP wR wi wi wi,
(wP (wQ wR wi) wi) (wP wQ wi) wP wR wi wi wi,
(wP (wQ wR wi) wi) (wP wQ wi) (wP wR wi) wi wi,
(wP (wQ wR wi) wi) ((wP wQ wi) (wP wR wi) wi) wi.

Из подобных, достаточно длинных последовательностей состоят доказательства Metamath.


Аксиомы Лукашевича

Рассмотрим теперь несколько более содержательных теорем. Для этого добавим три аксиомы Лукашевича и правило вывода modus ponens (из формул P и P->Q выводится формула Q):

ax-1 $a |- ( P -> ( Q -> P ) ) $.
ax-2 $a |- ( ( P -> ( Q -> R ) )  -> ( ( P -> Q ) -> ( P -> R ) ) )  $.
ax-3 $a |- ( ( ! P -> ! Q ) -> ( Q -> P ) ) $.
 
${                                $( the modus ponens rule $)
   min   $e |- P          $.
   maj   $e |- ( P -> Q ) $.
   mp    $a |- Q          $.
$}

В аксиомах и правиле вывода стоит константа "|-", интерпретируемая как "выводится". Первая аксиома требует описания двух переменных (что подставлять вместо P и Q), вторая - трёх, а третья - снова двух. Правило вывода mp, фактически, также является аксиомой. Однако она, кроме обязательных заданий двух переменных P и Q, содержит две посылки min и maj, которые также должны находится в стеке, чтобы правило сработало. Таким образом, если wi требует перед собой в стеке 2-х элементов, то для mp их должно быть 4.

Опишем вывод производного правила P->(Q->R) |- (P->Q)->(P->R) с именем a2i. Это теорема исчисления ($p), зависящая от трёх переменных P, Q, R типа wff (они таковыми сделаны раньше при помощи директивы $f). Последовательность имён переменных соответствует тому, как они появлялись в описании теоремы (первые две строки a2i.1 и a2i) Четвёртым аргументом теоремы выступает гипотеза a2i.1, между $e и $.:

${
   a2i.1 $e |- ( P -> ( Q -> R ) ) $.             $( hypotheses                                   $)
   a2i   $p |- ( ( P -> Q ) -> ( P -> R ) ) $=
         wP wQ wR wi wi                           $( P  :  wff ( P->(Q->R) )                      $)
         wP wQ wi wP wR wi wi                     $( Q  :  wff ( (P->Q)->(P->R) )                 $)
         a2i.1                                    $( min: |-  (P->(Q->R))                         $)
         wP wQ wR ax-2                            $( maj: |-  ( (P->(Q->R)) -> ((P->Q)->(P->R)) ) $)
         mp                                       $(      |-  ( ((P->Q)->(P->R)) )                $)
         $.
$}
Отметим, что гипотеза a2i.1 (в отличии от аксиом и теорем) не требует подстановки в неё переменных. Более того, в соответствии с общепринятой в логике практикой, гипотеза является неизменным (данным свыше) утверждением.

Каждая строка доказательства (после $=) формирует последовательность символов, приведенную после двоеточия в комментариях (пробелы для краткости опущены). Первые 4 последовательности находятся в стеке перед применением правила mp. Первые две - это выражения (wff), которые будут подставлены в переменные P, Q правила. Вторые две (min, maj) - посылки ($e) правила mp. В них, в соответствии с правилом mp, должен уже стоять символ "|-", а не "wff" как ранее.

Производное правило вывода a2i можно использовать в последующих доказательствах.
Получим, например, правило P->Q, P->(Q->R) |- P->R с тремя переменными и двумя посылками mpd.1 и mpd.2:

${
   mpd.1 $e |- ( P -> Q ) $.          $( hypotheses 1                                 $)
   mpd.2 $e |- ( P -> ( Q -> R ) ) $. $( hypotheses 2                                 $)
   mpd   $p |- ( P -> R ) $=
         wP wQ wi                     $( P       :  wff ( P -> Q )                    $)
         wP wR wi                     $( Q       :  wff ( P -> R )                    $)
         mpd.1                        $( min     :  |- ( P -> Q )                     $)
 
         wP wQ wR                     $( P,Q,R   : wff P, wff Q, wff R                $)
         mpd.2                        $( a2i.1   :  |- ( P -> ( Q -> R ) )            $)
         a2i                          $( maj     :  |- ( ( P -> Q ) -> ( P -> R ) )   $)
 
         mp                           $(         :  |- ( P -> R )                     $)
         $.
$}
Выше пустыми строками отделено применение правила a2i, в результате которого возникает вторая посылка maj правила mp из последней строчки. Правило a2i требует наличия в стеке 4-х элементов. Первые три из них подстановки wff, а четвёртая - утверждение о выводимости (|-).

Производное правило mpd в базовом файле set.mm системы Metamath используются для вывода теоремы P -> P ("идентичность высказывания"). Эта теорема, в отличии от правил, не содержит гипотез:

id   $p |- ( P -> P ) $=
     wP                               $( P       :  wff  P                            $)
     wP wP wi                         $( Q       :  wff  ( P->P )                     $)
     wP                               $( R       :  wff  P                            $)
     wP wP ax-1                       $( mpd.1   :  |- ( P -> ( P->P ) )              $)
     wP wP wP wi ax-1                 $( mpd.2   :  |- ( P -> ( ( P -> P ) -> P ) )   $)
     mpd                              $(         :  |- ( P -> P )                     $)
     $.

Компактная запись трёх приведенных доказательств может быть получена командой MM> show proof *:

a2i:
13   min=a2i.1     $e |-  P→(Q→R )
17   maj=ax-2      $a |-  (P→(Q→R))→((P→Q)→(P→R))
18   a2i=mp        $a |-  (P→Q)→(P→R)
mpd:
 7   min=mpd.1     $e |-  P→Q
11   a2i.1=mpd.2   $e |-  P→(Q→R)
12   maj=a2i       $p |-  (P→Q)→(P→R)
13   mpd=mp        $a |-  P→R
id:
 8   mpd.1=ax-1    $a |-  P→(P→P)
13   mpd.2=ax-1    $a |-  P→((P→P)→P)
14   id=mpd        $p |-  P→P

Приведём также вывод теоремы ( P -> P ) без использования производных правил:

id1 $p |- ( P -> P ) $=
    wP wP wP wi wi                    $( P:   wff  P->(P->P)                                 $)
    wP wP wi                          $( Q:   wff (P->P)                                     $)
    wP wP ax-1                        $( min: |-  P->(P->P)                                  $)
 
    wP wP wP wi wP wi wi              $( P:   wff P->((P->P)->P)                             $)
    wP wP wP wi wi wP wP wi wi        $( Q:   wff (P->(P->P)) -> (P->P)                      $)
    wP wP wP wi    ax-1               $( min: |-  P->((P->P)->P)                             $)
    wP wP wP wi wP ax-2               $( maj: |-  (P->((P->P)->P)) -> ((P->(P->P))->(P->P))  $)
    mp                                $( maj: |-  (P->(P->P)) -> (P->P)                      $)
 
    mp                                $(      |-  ( P-> P )                                  $)
  $.

Обратим внимание, что в первой строке нельзя использовать более компактную запись "wP wP ax-1", так как она приведёт к строке "|- P->(P->P)", тогда как для применения правила mp там должна стоять подстановка для переменной P, т.е. правильно построенная формула "wff P->(P->P)".

Пустыми строками отделено первое применение правила mp в результате которого формируется вторая посылка maj финального применения mp. В результате этого возникает последовательность ( P->P ), совпадающая с содержанием теоремы id1, поэтому она считается доказанной.


Теория с термами

Рассмотрим теперь пример из арифметики, которая имеет переменные двух типов - термы и wff.
Пусть в этой теории есть две аксиомы:

(A1) (t = r → (t = s → r = s))           транзитивность равенства
(A2) (t + 0) = t                         прибавление нуля
и правило вывода modus ponens (mp). Выведем из аксиом формулу t=t:
1. (t + 0) = t                           (по аксиоме A2)
2. (t + 0) = t                           (по аксиоме A2)
3. ((t + 0) = t → ((t + 0) = t → t = t)) (по аксиоме A1)
4. ((t + 0) = t → t = t)                 (правило mp применяется к шагу 2 и 3)
5. t = t                                 (правило mp применяется к шагу 1 и 4)

Опишем этот же вывод на языке Metamath. Для этого создадим файл в котором определим константы и 5 переменных. Переменные t,r,s будут типа term, а переменные P,Q - формулами wff:

$c 0 + = -> ( ) term wff |- $.        $( Declare the consts  $)
$v t r s P Q $.                       $( Declare the vars    $)
 
tt $f term t $.                       $( terms: $)
tr $f term r $.
ts $f term s $.
 
wP $f wff  P $.                       $( wff: $)
wQ $f wff  Q $.
Определим теперь что такое терм (term) и правильно построенная формула (wff):
tze $a term 0 $.
tpl $a term ( t + r )  $.
 
weq $a wff  t = r      $.
wi  $a wff  ( P -> Q ) $.
Опишем две аксиомы теории и правило вывода modus ponens:
ax1 $a |- ( t = r -> ( t = s -> r = s ) ) $.     $( axioms $)
ax2 $a |- ( t + 0 ) = t                   $.
 
${                                               $( modus ponens $)
   min $e |- P          $.
   maj $e |- ( P -> Q ) $.
   mp  $a |- Q          $.
$}
Теперь можно сформулировать и доказать теорему t=t:
   th1 $p |- t = t $=                              $( Prove a theorem:                             $)
 
      tt tze tpl tt weq                            $( P  :   wff (t+0)=t                           $)
      tt tt weq                                    $( Q  :   wff t=t                               $)
      tt ax2                                       $( min:   |-  ( t+0)=t                          $)
 
      tt tze tpl tt weq                            $( P  :   wff (t+0)=t                           $)
      tt tze tpl tt weq tt tt weq wi               $( Q  :   wff ( (t+0)=t -> t=t )                $)
      tt ax2                                       $( min:   |-  (t+0) = t                         $)
      tt tze tpl tt tt ax1                         $( maj:   |-  ( (t+0)=t -> ((t+0)=t -> t=t) )   $)
      mp                                           $( maj:   |-  ( (t+0)=t -> t=t )                $)
 
      mp                                           $(        |-  ( t=t )                           $)
$.

Сохраняем этот вывод в текстовом файле demo.mm. Запускаем программу metamath.exe и в консоли набираем:

MM> read demo.mm
MM> verify proof *
Команда "show proof th1" выводит компактное описание доказательства:
10   min=ax2   $a |- ( t + 0 ) = t
26     min=ax2 $a |- ( t + 0 ) = t
32     maj=ax1 $a |- ( ( t + 0 ) = t -> ( ( t + 0 ) = t -> t = t ) )
33   maj=mp   $a |- ( ( t + 0 ) = t -> t = t )
34 th1=mp     $a |- t = t
Полное описание каждой директивы доказательства делается командой "show proof th1 /lemmon / all":
1  tt             $f term t
2  tze            $a term 0
3  1,2 tpl        $a term ( t + 0 )
4  tt             $f term t
5  3,4 weq        $a wff ( t + 0 ) = t                                    | P
 
6  tt             $f term t
7  tt             $f term t
8  6,7 weq        $a wff t = t                                            | Q
 
9  tt             $f term t
10 9 ax2          $a |- ( t + 0 ) = t                                     | min: P
-----------------------------------------------------------------------------------------
11 tt             $f term t
12 tze            $a term 0
13 11,12 tpl      $a term ( t + 0 )
14 tt             $f term t
15 13,14 weq      $a wff ( t + 0 ) = t                                    | P
 
16 tt             $f term t
17 tze            $a term 0
18 16,17 tpl      $a term ( t + 0 )
19 tt             $f term t
20 18,19 weq      $a wff ( t + 0 ) = t
21 tt             $f term t
22 tt             $f term t
23 21,22 weq      $a wff t = t
24 20,23 wi       $a wff ( ( t + 0 ) = t -> t = t )                       | Q
 
25 tt             $f term t
26 25 ax2         $a |- ( t + 0 ) = t                                     | min: P
 
27 tt             $f term t
28 tze            $a term 0
29 27,28 tpl      $a term ( t + 0 )
30 tt             $f term t
31 tt             $f term t
32 29,30,31 ax1   $a |- ( ( t + 0 ) = t -> ( ( t + 0 ) = t -> t = t ) )  | maj: P->Q
 
33 15,24,26,32 mp $a |- ( ( t + 0 ) = t -> t = t )                       | maj: P->Q
-----------------------------------------------------------------------------------------
34 5,8,10,33 mp   $a |- t = t