Многозначная логика своими руками

+7 926 604 54 63 address
 Существуют ли логики, действительно альтернативные формальной?
Существуют ли логики, действительно альтернативные формальной?

Существует заблуждение, будто бы «когда-то давно существовала только одна логика — формальная, но с тех пор учёные уже придумали ей массу альтернатив».

Если попросить назвать эти альтернативы, то вполне вероятно, что в пример будет приведена какая-то бессодержательная и размытая конструкция вроде «диалектической логики», однако возможен и вариант приведения содержательной: «нечёткая логика», «многозначная логика» и т. п.

В большинстве случаев, правда, отвечающий не в курсе устройства того, про что он говорит, и реальное его знание о приводимом им в пример заканчивается чем-то вроде «в нечёткой логике всё нечётко».

Это, впрочем, не умаляет реальной содержательности того, что он упомянул — пусть даже он и не понимает его устройства. Заблуждение тут не в том, что «он думает, будто существует нечёткая логика, но на самом деле такой нет», а в том, что «он думает, будто бы нечёткая логика — альтернатива формальной, но на самом деле…».

Что же должно в данном случае следовать за «но на самом деле…»? Если это не «альтернатива», то что? Дополнение? Развитие? Усовершенствование?

Ни то, ни другое и ни третье. Подобно тому, как определив f(x) = 10x + 1, мы не создали альтернативу математике и не дополнили её основы, любая из этих логик — «нечёткая», «многозначная» и т. п. — представляет собой лишь «определение специфического языка на базе другого языка, позволяющего в некоторой предметной области — на некотором классе задач — вести рассуждения быстрее и понятнее».

Мы заводим f(x), чтобы короче записывать 10x + 1, поскольку, например, именно такое выражение в нашей задаче особенно часто встречается. Мы вводим дополнительное прилагательное «неформальный», чтобы короче говорить «не принадлежащий к множеству формализованных видов деятельности». И ровно так же мы вводим «логику в логике» — «логику второго порядка» — чтобы было проще вести рассуждения определённого типа. Логика же первого порядка не только остаётся в деле, но и является обязательной для введения логики второго порядка, подобно тому, как для f(x) для нас обязательны были понятия «сложение», «умножение», «число» и «переменная».

Чтобы лучше представить себе, как это бывает, рассмотрим, например, такую ситуацию.

  • Дима приглашает к себе на День Рождения группу друзей.
  • Все Димины друзья говорят только правду.
  • Вася говорит, что он придёт.
  • Петя говорит, что он не придёт.
  • Коля говорит, что он, возможно, придёт.

Эта система утверждений вполне может выступать в качестве набора предпосылок — базовых утверждений, и к ней мы вполне можем задавать вопросы.

Например,

  • Придёт ли Вася или Петя на День Рождения Димы?
  • Придут ли Коля и Петя?
  • Придут ли Коля и Вася или Петя?

Разумеется, у слов естественного языка всегда есть некоторая произвольность трактовки. Тут, в частности, неясно…

  • Что означает «Вася или Петя»? Когда надо ответить «да» — когда пришёл ровно один из них, или если оба пришли, то это тоже «да»?
  • Каков приоритет у «и» и «или»: в третьем вопросе имеется в виду «(Коля и Вася) или Петя» или же «Коля и (Вася или Петя)»?
  • Что означает «возможно» в ответе Коли?

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

Давайте так и сделаем.

  1. Ответ «да» означает, что человек Икс точно придёт на День Рождения.
  2. Ответ «нет» означает, что человек Икс точно не придёт.
  3. Ответ «возможно» означает, что человек точно в курсе Дня Рождения, но пока ещё точно не знает, сможет ли он прийти.

Здесь уже начинает просматриваться «многозначная логика». И велик соблазн сказать что-то вроде:

«Вот видите, такая логика гораздо ближе к реальности, чем формальная — ведь в реальности правда бывает, что кто-то не может ответить сразу».

Или же:

«Вот видите, как важно отказаться от „закона исключённого третьего“: мы ввели вариант „возможно“ и нам сразу стало гораздо легче описывать реальность».

И действительно, вот это вот «возможно» вроде бы означает одновременно «да» или «нет». Мы даже именно так и собрались трактовать этот ответ: «он в курсе, но пока точно не знает, да или нет».

Однако это — иллюзия.

«Исключённое третье» никуда не делось, оно всё ещё тут. Иллюзия же его исчезновения возникла благодаря тому, что вы мысленно отождествили «да», сказанное кем-то в ответ, с «истиной», как значением данного высказывания.

Смотрите в чём штука. В нашей «логике-2» («логике второго порядка») есть утверждение

Вася сказал «да».

Однако оно есть именно что в «логике-2». В «логике-1» же полная форма утверждения иная:

«Вася сказал „да“» = истина.

Или, если его записать более подробно, то

Утверждение «Вася сказал „да“» является истинным.

Отличие между «да» и «истина» было бы ещё более рельефным, если бы мы обратили внимание на другие варианты.

Утверждение «Петя сказал „нет“» является истинным.

Из этого ведь не следует, что «нет» и «истина» — одно и то же?

Но самое главное, верно и вот это:

«Коля сказал „возможно“» = истина.

Исключённое третье действует не для «возможно», «да» и «нет». Оно действует для «Вася сказал „да“», «Петя сказал „нет“», «Коля сказал „возможно“».

Либо «Вася сказал „да“» — истинно, либо «Вася сказал „да“» — ложно.

Может казаться, будто бы формальная логика требует считать, что, если «Вася сказал „да“» — ложно, то из этого должно следовать «Вася сказал „нет“».

Это, однако, не так. Из этого следует только то, что «Вася не сказал „да“». Для иных же выводов нам нужны дополнительные данные.

Например, мы можем ввести дополнительные базовые утверждения:

  • Друзья Димы могут отвечать только «да», «нет» и «возможно».
  • Они не могут не ответить.
  • Их всех уже опросили.

Тогда из того, что

«Вася сказал „да“» = ложно

будет следовать, что Вася сказал «нет» или Вася сказал «возможно».

Повторюсь: ответы «да», «нет» и «возможно» — не то же самое, что «истинно» или «ложно» в отношении утверждений вида «Вася дал такой-то ответ». Однако явное лингвистическое сходство между ними заставляет нас ошибочно отождествлять одно с другим.

Причём иллюзия была бы ещё сильнее, если бы я — по примеру многих «типа альтернативных логик» — использовал бы вместо «да» и «нет» совсем те же самые слова: «истина» и «ложь».

На деле мы вовсе не вводим «альтернативную логику», а строим внутри формальной логики некий DSL («Domain Specific Language» — локальный предметно-ориентированный язык внутри другого языка). Именно на нём мы задаём соотношения между ответами друзей Димы и ответами на те вопросы, которые можно дополнительно задать к этим ответам.

И вот уже для этих их ответов — «да», «нет», «возможно» (а вовсе не для самих утверждений об их ответах) может не действовать правило исключённого третьего и т. п.

Давайте, кстати, попробуем проделать это для наглядности.

Однако чтобы не попасть в плен иллюзий, с самого начала разграничим операции логики-1 и логики-2 не только по смыслу, но и по именам.

«Истина» или «ложь» будут называться «логическим значением высказывания» в логике-1.

«Да», «нет» и «возможно» будут называться «статусами» в логике-2.

Так,

Вася ответил «да»

имеет смысл: «статус Васиного прихода = да».

При этом

«На вопрос о своём приходе Вася ответил „да“» = истина

означает, что мы ввели предпосылку, что считаем истинным утверждение

Вася ответил «да».

Вот эти символы у нас используются в логике первого порядка.

Логическое «или»
Логическое «и»
¬ Отрицание

В логике второго порядка мы будем по-другому называть некие аналоги этих операций, чтобы подчеркнуть их смысловое отличие от оных в логике первого порядка.

|| Логическое «или»
&& Логическое «и»
! Отрицание

И вот как тогда мы могли бы определить «логическое и» в логике-2.

да && да → да
да && нет → нет
да && возможно → возможно

нет && нет → нет
нет && возможно → нет

возможно && возможно → возможно

По сути дела, тут приведён набор правил «замены выражений». Что-то вроде, «если нам встретится выражение „да && нет“, то мы можем заменить его на „нет“, поскольку они тождественны друг другу».

Кроме того, мы считаем, что от перестановки параметров результат не меняется, поэтому «да && нет» тождественно «нет && да» и, следовательно, второе выражение тоже можно заменить по правилу, введённому для первого.

Как можно видеть, «&&» у нас получилось чем-то вроде «пессимистического объединения»: в каждом случае она выбирает из двух вариантов наиболее печальный для Димы.

Но, кроме того, введём ещё «логическое или» из логики-2.

да || да → да
да || нет → да
да || возможно → да

нет || нет → нет
нет || возможно → возможно

возможно || возможно → возможно

«Логическое или»-2 — напротив, «оптимистическое»: оно из двух вариантов выбирает наилучший для Димы.

Теперь мы можем ввести понятие логической переменной в логике-2 тоже.

Переменная — просто буква, которой обозначается выражение, способное принимать один из трёх статусов «да», «нет» и «возможно».

Логические переменные логики-2 тоже следует отличать от логических переменных логики-1.

В логике-1 переменная будет выглядеть, например, вот так.

Назовём утверждение «Вася сказал “да”» буквой «А».
А = истина

Но в логике-2 уже будет иначе

Назовём ответ Васи буквой «а».
а = да

Дальше мы — тоже через набор утверждений — зададим алгоритм преобразования выражений в логике-2.

  1. На место всех переменных некоторого выражения логики-2 следует подставить их значения — «да», «нет» или «возможно».
  2. Из вышеприведённого списка правил надо по порядку брать каждое правило.
  3. Если в выражении найдено подвыражение, соответствующее тому, что в текущем правиле стоит слева от стрелки, то это подвыражение надо заменить тем, что в этом правиле стоит справа от стрелки.
  4. Следует повторять процесс, пока в текущем варианте выражения всё ещё можно найти то, что в этом правиле стоит слева от стрелки.
  5. Когда такие подвыражения кончились, надо брать следующее правило.
  6. Если мы дошли до конца списка правил, то надо снова перейти на его начало.
  7. Вышеописанный процесс следует повторять, до тех пор, пока выражение не останется неизменным при очередном прохождении с заменой от первого правила списка до последнего.

Этот алгоритм может показаться сложным для понимания, но его суть в том, что «надо применять правила замены, пока от них всё ещё меняется выражение».

На языке Wolfram это выглядело бы гораздо короче.

моёВыражение //. rules

rules — это вышеприведённый список правил замены, а //. — команда «применять их, пока выражение не перестанет изменяться».

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

Если есть правило

да || нет → да,

то надо добавить ещё и правило

нет || да → да

Это можно записать так:

swap[r_ → v_] := Reverse[r] → v
rules = Join[rules, swap /@ rules];

Казалось бы, к чему тут вообще эта отсылка к некому языку программирования?

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

Однако как можно видеть, без каких-либо особых ухищрений на компьютере можно реализовать и эту нашу многозначную логику. Нам не надо для этого менять архитектуру компьютера, вводить, кроме «0» и «1», ещё какое-то третье значение кванта информации — бита и так далее. Вот этой вот «негибкой прямолинейной бинарности», оказывается, вполне достаточно.

Описание того, как в логике-2 преобразуются выражения — чисто техническое. Там нет ничего про конкретные высказывания на ней и способы их анализа. Просто «есть правила — преобразуй выражения по ним — получишь ответ».

Валидность же этих правил и самого алгоритма доказывается исключительно по логике-1 — той самой формальной.

Не будь программы, можно было бы заподозрить, что тут, в рассуждениях «на словах» просто где-то сокрыта ошибка (и, возможно, не одна), а на самом деле ничего работать не будет. Чтобы же оно заработало, необходима «альтернативная логика».

Но вот наличие работающей программы исключает такой вариант. Действительно мы можем строить выражение и, преобразуя его по этому алгоритму, получать однозначно трактуемый ответ.

По этой причине и приведён код на Wolfram.

Вот как это на нём записывается.

Задание значений переменных (статусов ответов).

(* a — ответ Васи *)
a = да; 

(* b — ответ Пети *)
b = нет;

(* с — ответ Коли*)
c = возможно; 

Зададим интересующие нас вопросы.

(*Придёт ли Вася или Петя на День Рождения Димы?*)
a || b //. rules
да

(* Придут ли Коля и Петя? *)
a && b //. rules
нет

(* Придут ли (Коля и Вася) или Петя? *)
((c && a) || b) //. rules
возможно

На примере последнего выражения посмотрим, что, по сути, делает наш алгоритм/программа.

Есть выражение

(c && a) || b

Сначала на место переменных подставляются их значения.

(возможно && да) || нет

Теперь для каждого правила из списка мы пробуем найти подвыражение, соответствующее тому, что у этого правила слева от стрелки.

Первое, что будет найдено «возможно && да → возможно». Соответствующее подвыражение следует заменить правой от стрелки частью правила.

возможно || нет

Теперь уже следующим подходящим правилом замены будет «возможно || нет → возможно». После замены у нас останется

возможно

Дальше, сколько ни проходи по списку, изменить выражение уже не удастся, поэтому оно — окончательный ответ.

При этом видно, что наша система под кодовым названием «логика-2» уже столь формализована и абстрактна, что не зависит от того, что именно скрывается под именами переменных «a», «b» и «c». Мы можем применять её для любых других высказываний, которые тоже могут иметь статус «да», «нет» и «возможно».

Однако трактовать результаты мы должны строго в том же смысле, в котором трактовались ответы друзей Димы.

Например, «возможно» тут означает не вообще всё, что можно назвать словом «возможно», а именно то самое «возможно», которое соотносится с теми самыми «да» и «нет» по описанному нами списку правил.

Вот в этом уже проявляется логика-1 — формальная логика: всё это имеет хоть какой-то содержательный смысл только в том случае, если мы следуем правилам формальной логики, и тот смысл, который оно имеет, — тот и только тот, который косвенно описан в списке правил замены.

Причём список замены нами построен тоже исключительно по правилам формальной логики: по сути, из некоторого набора утверждений мы логикой-1 выводили то, как должно выглядеть правило преобразования.

Так, мы для начала воспользовались тем, что друзья Димы на все вопросы отвечают только правду, а потому приравняли их ответ на приглашение к статусам их прихода, названным аналогично: «да», «нет», «возможно».

Потом мы для каждой пары статусов и для каждой операции — «||» и «&&» — задали преобразование, соответствующее тому смыслу, который мы него вкладываем.

Нам, в частности, хотелось, чтобы «&&» было подобно «логическому и» из логики-1: мы говорим «да, все перечисленные придут», если все перечисленные сказали «да», и мы говорим «все перечисленные возможно придут», если никто из них не сказал «нет». И к этому желаемому поведению операции мы тоже подобрали правило преобразования при помощи формальной логики.

Мы могли бы на этом не останавливаться и ввести ещё какие-то операции — чтобы расширить множество систем базовых утверждений, которые могут анализироваться таким образом.

Предположим, мы бы хотели ещё рассматривать те ситуации, когда кого-то из друзей Димы ещё не успели спросить (или он ответил что-то неразборчивое, а потом связь прервалась).

ОК. Введём для этого ещё один статус ответа в рамках логики-2: «неизвестно».

Для него нам тоже надо задать правила преобразования.

неизвестно && неизвестно → неизвестно
неизвестно && да → неизвестно
неизвестно && нет → неизвестно
неизвестно && возможно → неизвестно

неизвестно || неизвестно → неизвестно
неизвестно || да → да
неизвестно || нет → нет
неизвестно || возможно → возможно

Логика-2 из трёхзначной превращается в четырёхзначную, но она по-прежнему является лишь локальным специфическим языком в рамках логики-1. Алгоритм преобразования высказываний остаётся всё тем же и всё так же в пару строк реализуется на этом вашем «бинарном» компьютере и с его бинарной логикой.

Дальше дело доходит и до «отрицания», которое пока ещё не реализовано.

Как уже говорилось выше, отрицание из логики-1 — это не то же самое, что мы могли бы назвать «отрицанием» в рамках логики-2.

В логике-1 из того, что

«Вася сказал „да“» — ложно

следует лишь то, что

Вася не сказал «да»

… то есть, как максимум, просто перефразировка его же самого́.

Если мы хотим, чтобы полный аналог такой операции в логике-2 обладал свойством исключённого третьего, то мы, исходя из того, что статусов у нас сейчас четыре — «да», «нет», «возможно» и «неизвестно» — должны заключить следующее: «отрицанием» каждого из статусов является список из трёх других.

У нас — это тоже следует из формальной логики — просто нет иного выхода: ведь у нас нет специальных имён для статусов вида «всё, кроме „да“».

Но при этом правило исключённого третьего для системы с четырьмя статусами однозначно утверждает: если

«Вася сказал „да“» — ложно,

то либо Вася сказал «нет», либо Вася сказал «возможно», либо ответ Васи неизвестен.

Однако вариант реализации со списком нам вполне доступен — мы вполне можем определить «отрицание» в логике-2 следующим образом:

! да → {нет, возможно, неизвестно}
! нет → {да, возможно, неизвестно}
! возможно → {да, нет, неизвестно}
! неизвестно → {да, нет, возможно}

…и трактовать ответы со списком, как возможные и равноправные альтернативы нашего выражения.

Правда, для этого ещё надо дополнить сам алгоритм преобразования, чтобы он позволял проделывать логические операции не только с двумя статусами, но и со статусом и списком статусов или с двумя списками статусов.

По смыслу — примерно вот так:

a && {b1, b2, …} → {a && b1, a && b2, …}
{a1, a2, …} && {b1, b2, …} → { a1 && {b1, b2, …}, a2 && {b1, b2, …}, … }
и т. д.

Если вам вдруг интересно, то на Wolfram это будет записываться вот так:

op_[l_List, x_] :> (op[x, #] & /@ l)
op_[l_List] :> (op[#] & /@ l)
Разбор того, что тут написано, потребовал бы ещё одной статьи сравнимого размера, поэтому я просто оставлю это здесь.

Однако это не единственный вариант того, что мы могли бы назвать «отрицанием» — благо, теперь мы разграничиваем отрицание в логике-1 и нечто, названное «отрицанием», в логике-2.

Например, мы могли бы считать, что

«Вася не сказал „да“»

с точки зрения практических интересов Димы означает «я по-прежнему не знаю, придёт ли он».

Кроме того, быть может, мы рассматриваем ситуацию, как ещё развивающуюся, а потому из «сейчас он не сказал “да”» не следует, что он этого не скажет в дальнейшем.

В этом же смысле можно трактовать «Васе не неизвестно»: Вася как бы уже в курсе Дня Рождения, просто Дима не знает его ответ, а потому считает, что из этого следует, что Вася, возможно, придёт.

Поэтому мы можем добавить ещё одно «вроде как отрицание».

не@да → неизвестно
не@нет → неизвестно
не@возможно → неизвестно
не@неизвестно → возможно

Такая операция, даже если мы назовём её «отрицанием», уже не подобна отрицанию из логики-1: во-первых, для неё не выполняется закон исключённого третьего, а, во-вторых, она ещё и не взаимно однозначна — в частности, двойное её применение не всегда приводит к возврату к исходному статусу.

Тем не менее, мы ей вполне можем пользоваться, полностью оставаясь в рамках формальной логики, поскольку используем мы её лишь как набор правил преобразования выражений в рамках логики-1. Как статус ответа в рамках логики-2, но не как значение выражения в рамках логики-1.

Причём мы можем её использовать даже вместе с операцией «!» — с аналогом полного отрицания.

И даже можем завести третий вариант «отрицания».

наоборот@да → нет
наоборот@нет → да
наоборот@возможно → неизвестно
наоборот@неизвестно → возможно

Здесь есть взаимная однозначность и одновременно с тем выполняется нечто, вроде «исключённого третьего», но четыре статуса при этом как бы распадаются на две пары.

Однако мы всё равно можем использовать эту операцию и даже приписать некий практический смысл её трактовке.

Например, она может относиться к случаям вида:

Известно, что Вася не ответил и не ответит «да».

Для Димы в практическом смысле это знание аналогично тому, что Вася ответил «нет».

Если бы было известно, что Вася не ответил и не ответит «нет», то в практическом смысле для Димы это — аналог ответа «да».

Если известно, что Вася не ответил «возможно», то Дима считает, что ответ Васи ему неизвестен.
Если известно, что Вася ответил хоть как-то (его ответ не неизвестен), то для Димы это означает, что Вася, возможно, придёт.

Однако неверно было бы считать, что операции «наоборот», «не» и «!» означают одно и то же — раз уж мы все их в процессе рассуждений называли «отрицанием». Нет, формальная логика требует трактовать их именно так, как они были введены, не подменяя одну другой.

И тем более ни одну из них нельзя отождествить с отрицанием из формальной логики — даже «!», которая вроде бы выглядит, как полный аналог.

Аналог или не аналог, но эти операции находятся в разных смысловых пространствах.

Собственно, те «парадоксы», которые подводят людей к мыслям: «формальная логика ограничена», «есть вещи, с которыми она не справляется» и т. п., — как раз и возникают из-за незаметного смешения смысловых пространств:

  • Логического значения высказывания и высказывания о логическом значении («А = истина» и «где-то утверждается, что А — истина»)
  • Вывода о значении высказывания и чьих-то слов о значении высказывания («следовательно, А — истина» и «Вася говорит, что „А — истина“).
  • Логического значения высказывания и высказывания о степени уверенности кого-то в значении отрицания этого высказывания («А — истина» и «Вася не совсем уверен, что А — ложно»)

Это далеко не полный перечень вариантов, однако все они сводятся к отождествлению разных смысловых пространств, из-за чего и возникают ошибочные суждения о логическом выводе из некоторого набора утверждений и о логике в целом. Но стоит перестать это делать, как все такие «парадоксы» исчезнут.

Наконец, можно было бы задаться вопросом: а действительно ли надо вводить логику-2 исключительно как DSL в рамках логики-1? Ведь можно просто повторить некий (возможно, адаптированный) набор правил из неё в логике-2, после чего считать логику-2 — отдельным вариантом логики?
Да, так действительно можно было бы сделать. Однако в этом случае вполне можно было бы ровно так же математику, для которой мы локально ввели некую удобную нам функцию назвать «альтернативной математикой».

Таким образом, слово «альтернативный» перестаёт значить то, что под ним обычно понимается.

Формальная логика — это минимальный набор правил, требуемых для построения любой другой «логики» более высокого порядка в виде системы высказываний в рамках формальной логики.

От того, что мы назвали такую систему «тоже логикой», ничего не изменилось — она от этого не стала неким образом отличаться от любого другого набора высказываний в рамках формальной логики.

Всё, что можно проанализировать при помощи любой содержательной логики-2, можно проанализировать и при помощи логики-1 — просто это будет более многословно и менее удобно.

Поэтому любая логика-2 является лишь «альтернативным (более кратким и наглядным) способом записи рассуждений», но не «альтернативным способом ведения рассуждений».

.
Комментарии