Курс№2. Таблицы истинности0%
Теория · номер 2 из 27

Таблицы истинности

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

7 разделов~35 минут1 первичный балл
  1. 1Что проверяет номер
  2. 2Знаки логики на Python
  3. 3Шаблон: F одинаковая во всех строках
  4. 4Разные значения F и две функции
  5. 5Как это решают руками
  6. 6Ловушки перед экзаменом
  7. 7Домашка
Раздел 1 из 7

Что проверяет номер

Дана функция F от переменных x, y, z, w и несколько строк её таблицы истинности. Столбцы переменных не подписаны, часть клеток пустая. Нужно понять, какой столбец какой переменной соответствует. Ответ это буквы в порядке столбцов, например zxwy.

Вид задачи легко определить по последнему столбцу:

F везде одинаковая

В столбце F только нули или только единицы. Самый частый вид.

Строки: 1 0 _ 0 | 0, _ 1 0 _ | 0, 0 _ 0 0 | 0.

F разная или функций две

В столбце F есть и 0, и 1, либо справа сразу два столбца значений: F1 и F2.

Строки: 0 0 _ 1 | 1, 1 _ 1 1 | 0, 1 0 _ 1 | 1.

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

Все виды решаются одним кодом. Компьютер пробует все способы заполнить пустые клетки и все порядки столбцов и печатает тот порядок, который подошёл.

Раздел 2 из 7

Знаки логики на Python

Сначала условие надо перевести на Python. Таблица короткая, и её стоит выучить.

В условииНа PythonСмысл
¬anot aотрицание
a ∧ ba and bоба истинны
a ∨ ba or bхотя бы один истинен
a → ba <= bложно только при 1 → 0
a ≡ ba == bзначения совпадают
a ⊕ b, a ≢ ba != bзначения разные

Запусти и убедись, что <= ведёт себя как импликация. Ноль получается только в строке 1 0:

python
print('a b  a→b')
for a in 0, 1:
    for b in 0, 1:
        print(a, b, ' ', int(a <= b))

Как записать функцию без ошибок

  1. Скопируй выражение из условия к себе в код, чтобы не перепечатывать.
  2. Замени знаки на Python, не трогая скобки.
  3. Сверь скобки с условием один в один.
  4. Перед каждой скобкой с отрицанием оставь not: not (y == z).

Например, F = ((x → y) ∧ ¬z) ∨ (w ≡ x) превращается в такую функцию:

python
def f(x, y, z, w):
    return ((x <= y) and (not z)) or (w == x)
Главная ловушка номера

Запись x <= y == z Python понимает как (x <= y) and (y == z), а совсем не как (x <= y) == z. Такая цепочка сравнений молча даёт неверный ответ. Каждую импликацию и эквивалентность бери в свои скобки.

Посмотри на это сам. Две записи ниже выглядят похоже, но на трёх наборах из восьми расходятся:

python
from itertools import product

for x, y, z in product([0, 1], repeat=3):
    wrong = x <= y == z         # цепочка: (x <= y) and (y == z)
    right = (x <= y) == z       # то, что написано в условии
    print(x, y, z, int(wrong), int(right), '' if wrong == right else '<- разные')
Попробуй самучебная задача

Дана функция F = (x → y) ≡ z. На скольких наборах из восьми F равна 1? Напиши её со скобками и посчитай.

Раздел 3 из 7

Шаблон: F одинаковая во всех строках

Разберём шаблон на примере. Функция F = ((x → y) ∧ ¬z) ∨ (w ≡ x), дан фрагмент из трёх различных строк. Пустая клетка это значение, которое мы не знаем.

F
1000
100
0000

План такой:

  1. Пишем функцию f(x, y, z, w).
  2. Переписываем таблицу в код. Каждая пустая клетка становится своей переменной: a, b, c, d. Последнее число в строке это значение F.
  3. product перебирает, чем заполнить пустые клетки.
  4. Проверяем, что строки получились разные. В условии сказано, что строки различны.
  5. permutations('xyzw') перебирает, какой столбец какая переменная.
  6. Если на всех строках F совпала со значением в таблице, печатаем порядок.
python
from itertools import product, permutations

def f(x, y, z, w):
    return ((x <= y) and (not z)) or (w == x)

for a, b, c, d in product([0, 1], repeat=4):      # 4 пустые клетки
    t = (
        (1, 0, a, 0, 0),      # последнее число — значение F
        (b, 1, 0, c, 0),
        (0, d, 0, 0, 0),
    )
    if len(t) == len(set(t)):                     # строки должны быть разными
        for p in permutations('xyzw'):            # p — порядок столбцов, например ('z','x','w','y')
            if all(f(**dict(zip(p, line))) == line[-1] for line in t):
                print(''.join(p))

Ответ zxwy. Он напечатается два раза, потому что подходит при двух разных заполнениях пустых клеток. Это нормально. Вот если напечатались разные порядки, то ошибка в функции или таблице.

Что происходит в длинной строке

Строка с all выглядит страшно, но разбирается по кускам:

Если так понятнее, ту же проверку можно написать длиннее, без ** и all. Ответ будет тот же:

python
for p in permutations('xyzw'):
    ok = True
    for line in t:
        v = dict(zip(p, line))                    # {'z': 1, 'x': 0, ...}
        if f(v['x'], v['y'], v['z'], v['w']) != line[-1]:
            ok = False
    if ok:
        print(''.join(p))
Ловушка: строки должны быть разными

Проверку len(t) == len(set(t)) легко забыть. Убери её в примере выше и запусти: появится лишний ответ wxzy, и непонятно, какой вписывать. Пишем эту проверку всегда.

Сколько переменных в product, столько и пустых клеток. Если пустых клеток нет, product и проверка различия не нужны, остаётся только цикл по permutations.

Раздел 4 из 7

Разные значения F и две функции

В столбце F и 0, и 1

Код менять не надо. Мы и так сравниваем F со значением своей строки, line[-1], а не с константой. Поэтому шаблон работает сразу. Попробуй на задаче.

Попробуй самучебная задача

F = (x ∨ ¬y) ∧ (z → w) ∧ (¬w ∨ x). Фрагмент из трёх различных строк, значения F разные. Какой столбец какая переменная?

F
0011
1110
1011

Две функции в одной таблице

Справа два столбца значений, F1 и F2. Пишем две функции и проверяем обе. Значение F1 теперь предпоследнее в строке, line[-2], а F2 последнее, line[-1]. Лишние числа zip опять отбросит сам.

python
from itertools import product, permutations

def f1(x, y, z, w):
    return (x <= y) or (z and (not w))

def f2(x, y, z, w):
    return (y == w) <= (x or z)

for a, b, c, d in product([0, 1], repeat=4):
    t = (
        (1, a, 0, b, 1, 0),   # два последних числа — F1 и F2
        (0, 0, c, 0, 1, 0),
        (1, 1, 0, d, 0, 1),
    )
    if len(t) == len(set(t)):
        for p in permutations('xyzw'):
            if all(f1(**dict(zip(p, line))) == line[-2] and
                   f2(**dict(zip(p, line))) == line[-1] for line in t):
                print(''.join(p))

Ответ wxzy.

Раздел 5 из 7

Как это решают руками

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

Руками ищут вынужденные значения:

Из этого получаются условия вида «x и w в каждой строке разные» или «z везде равна 1». Дальше ищем столбцы, которые подходят под эти условия во всех строках, и начинаем со строк, где пустых клеток меньше всего.

Пример из раздела 3 начинается так. F = 0, значит, (w ≡ x) = 0, и в каждой строке x и w противоположны. В третьей строке нули стоят в первом, третьем и четвёртом столбцах. Значит, одна из букв x и w точно во втором столбце.

Можно ещё вывести все строки, где F = 0, и сравнить их с фрагментом глазами:

python
from itertools import product

print('x y z w')
for x, y, z, w in product([0, 1], repeat=4):
    if not (((x <= y) and (not z)) or (w == x)):
        print(x, y, z, w)
Раздел 6 из 7

Ловушки перед экзаменом

ЛовушкаКак не попасться
Цепочка x <= y == zКаждую импликацию и эквивалентность в свои скобки
→ записали как >=a → b это a <= b
Нет проверки на разные строкиВсегда пиши len(t) == len(set(t))
Сравнили F с константойСравнивай с line[-1], тогда код подойдёт для любых значений
Две функции: перепутали столбцыЕсли F1 левее, то F1 это line[-2], а F2 это line[-1]
Буквы в permutationsТе же, что в def f(...), порядок внутри строки неважен
Ответ напечатался несколько разЭто нормально, если порядок один и тот же. Разные порядки означают ошибку
Ответ с пробеламиБуквы подряд: zxwy
Раздел 7 из 7

Домашка

Шесть задач с настоящих экзаменов и из банка ФИПИ. Решай прямо здесь: кнопка «Решать здесь» открывает редактор, а код каждой задачи сохраняется.

Перед тем как писать код, сделай три вещи:

Где теряют балл в этих задачах

В первой задаче внутри функции и эквивалентность, и импликация, скобки тут особенно важны. В пятой значение F равно 1, а не 0, но код от этого не меняется. Ответ везде это четыре маленькие буквы подряд.

Ещё задачи этого вида лежат в разделе «Задания», №2.

Задачи «Попробуй сам» учебные, в домашке задачи с настоящих экзаменов и из банка ФИПИ. Код в блоках можно менять и запускать, он выполняется прямо в браузере.