Skip to main content

Задание 2

Рассмотрим несколько примеров

Пример 1

Задание

Логическая функция FF задаётся выражением

F=¬xy(¬zw)F=\lnot x \lor y\lor(\lnot z \land w)

На рисунке приведён фрагмент таблицы истинности функции FF, содержащий все наборы аргументов, при которых функция FF ложна. Определите, какому столбцу таблицы истинности функции F соответствует каждая из переменных xx, yy, zz, ww.

????F
00010
01010
01110

В ответе напишите буквы xx, yy, zz, ww в том порядке, в котором идут соответствующие им столбцы. Буквы в ответе пишите подряд, никаких разделителей между буквами ставить не нужно.

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

public class Example1 {
// список перебираемых значений переменной boolean
static boolean[] booleanValues = new boolean[]{false, true};

// логическая функция, аргументы которой мы подбираем
static boolean f(boolean x, boolean y, boolean z) {
return impl(x, y) && impl(y, z);
}

// операция импликации(следования)
static boolean impl(boolean a, boolean b) {
return !a || b;
}

// главный метод программы
public static void main(String[] args) {
// выводим заголовок
System.out.println("x y z");
// перебираем все наборы значений
for (boolean xV0 : booleanValues)
for (boolean yV0 : booleanValues)
for (boolean zV0 : booleanValues)
// если функция даёт ложь
if (!f(xV0, yV0, zV0))
// выводим этот набор аргументов
System.out.println(
(xV0 ? 1 : 0) + " " + (yV0 ? 1 : 0) + " " + (zV0 ? 1 : 0)
);

}
}

На выходе получим

x y z
0 1 0
1 0 0
1 0 1
1 1 0

В Java для перевода boolean в цифры 0 и 1 я использовал тернарное выражение условие?результат_если_да:результат_если нет. Его можно заменить обычным условием if. Для перебора я создал массив из двух элементов и для каждой переменной написал свой вложенный цикл, который перебирает значения из этого массива.

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

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

Подбирая такие столбцы, получим ответ: yy, zz, ww, xx.

Если значения функции различны, то так просто задачу не получится решить. Однако для начала попробуйте просто вывести все наборы, но добавьте в вывод ещё и значение функции FF:

        ...
// перебираем все наборы значений
for (boolean xV0 : booleanValues)
for (boolean yV0 : booleanValues)
for (boolean zV0 : booleanValues)
// выводим этот набор аргументов
System.out.println(
(xV0 ? 1 : 0) + " " + (yV0 ? 1 : 0) + " " + (zV0 ? 1 : 0) + " " + (f(xV0, yV0, zV0) ? 1 : 0))
);
...

И попробуйте найти соответствие.

Пример 2

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

Решим такую задачу:

Задание

Логическая функция FF задаётся выражением

F=(xy)¬(yz)¬wF=(x\lor y)\land\lnot(y\equiv z)\land\lnot w

На рисунке приведён частично заполненный фрагмент таблицы истинности функции FF, содержащий неповторяющиеся строки. Определите, какому столбцу таблицы истинности функции FF соответствует каждая из переменных xx, yy, zz, ww.

????F
111
0101
1101

В ответе напишите буквы xx, yy, zz, ww в том порядке, в котором идут соответствующие им столбцы. Буквы в ответе пишите подряд, никаких разделителей между буквами ставить не нужно.

import java.util.Arrays;

public class Example2 {
// имена колонок
static char[] names = {'x', 'y', 'z', 'w'};
// список перебираемых значений переменной boolean
static boolean[] booleanValues = new boolean[]{false, true};

// логическая функция, аргументы которой мы подбираем
static boolean f(boolean x, boolean y, boolean z, boolean w) {
return (x || y) && (y != z) && !w;
}

// проверка значений в линии на совпадение
static int findLine(boolean xV, boolean yV, boolean zV, boolean wV, boolean f, boolean[][] combinations) {
if (xV && zV && f && combinations[0] == null) {
return 0;
}
// обязательно надо сначала проверить эту строку, потому что она
if (!xV && yV && !wV && f && combinations[1] == null) {
return 1;
}
if (yV && zV && !wV && f && combinations[2] == null) {
return 2;
}
return -1;
}

// обработка перестановки
static void processPermutation(int[] p) {
// найденные комбинации, их три, потому что известных строчек таблицы истинности 3
boolean[][] combinations = new boolean[16][];
// кол-во найденных комбинаций
int foundCombinationCnt = 0;
// перебираем все варианты значений для каждой логической переменной
// из таблицы истинности, значений всего два: true и false
for (boolean xV0 : booleanValues)
for (boolean yV0 : booleanValues)
for (boolean zV0 : booleanValues)
for (boolean wV0 : booleanValues) {
// чтобы использовать перестановку, построим на основе четырёх логических
// переменных массив
boolean[] values = new boolean[]{
xV0, yV0, zV0, wV0
};

// получим значения логических переменных с учётом перестановки
// т.е. мы по сути формируем строку значений, которую потом будем сверять с данной
boolean xV = values[p[0]];
boolean yV = values[p[1]];
boolean zV = values[p[2]];
boolean wV = values[p[3]];
// ищем подходящую строку таблицы
int lineNum = findLine(xV, yV, zV, wV, f(xV0, yV0, zV0, wV0), combinations);
// если строка найдена и ещё не сохранена соответствующая этой строке комбинация
if (lineNum != -1) {
// сохраняем комбинацию
combinations[lineNum] = values;
foundCombinationCnt++;
}
}
// если найдено три комбинации
if (foundCombinationCnt == 3) {
System.out.println("++++++++++++++++++++++++++++++");
System.out.println("перестановка: " + Arrays.toString(p));
// выводим шапку
for (int i = 0; i < 4; i++) {
System.out.print(names[p[i]] + " ");
}
System.out.println();
// выводим сохранённые комбинации
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
System.out.print((combinations[i][p[j]] ? 1 : 0) + " ");
}
System.out.println();
}
}
}


// функция-генератор перестановок
static void permute(int[] p, int pos) {
// Если мы дошли до последнего элемента
if (pos == p.length - 1) {
processPermutation(p);
} else { // иначе
// Перебираем все оставшиеся элементы
for (int i = pos; i < p.length; i++) {
// меняем местами текущий элемент и перебираемый
swap(p, pos, i);
// Вызываем Рекурсию для следующего элемента
permute(p, pos + 1);
// меняем местами обратно
swap(p, pos, i);
}
}
}

// главный метод программы
public static void main(String[] args) {
// создаём массив индексов
int[] arr = new int[]{0, 1, 2, 3};
// запускаем перебор перестановок
permute(arr, 0);
}

// поменять местами элементы массива arr с индексами l и r
public static void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}

}

Получим:

++++++++++++++++++++++++++++++
перестановка: [2, 1, 0, 3]
z y x w
1 0 1 0
0 1 0 0
0 1 1 0

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

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

Сама проверка возвращает, какой линии соответствует этот набор. Если он не удовлетворяет ни одной, возвращается -1. Если набор найден, сохраняем его в соответствующий элемент массива, хранящего все комбинации

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

По сути, обработчик перестановки теперь универсален, при четырёх переменных вам нужно менять только методы findLine() и f().

В метод findLine() специально передаётся массив сохранённых наборов. Это сделано для того, чтобы каждая строка обработалась ровно один раз.

Если у вас в задаче другое кол-во переменных, то в генерации перестановок нужно указать массив из стольких индексов, сколько используется у вас, также необходимо изменить размер списка комбинаций до 2n2^n, где nn - кол-во логических переменных.

Также не забудьте поменять массив заголовков names.

Пример 3

Задание

Логическая функция F задаётся выражением

F=((xy)(wz))(zx))F=((x\land y)\lor(w\Rightarrow z))\equiv(z\equiv x))

На рисунке приведён частично заполненный фрагмент таблицы истинности функции F, содержащий неповторяющиеся строки. Определите, какому столбцу таблицы истинности функции F соответствует каждая из переменных x, y, z, w.

????F
0011
11001
011

В ответе напишите буквы x, y, z, w в том порядке, в котором идут соответствующие им столбцы. Буквы в ответе пишите подряд, никаких разделителей между буквами ставить не нужно.

Я привёл только методы, у которых реализация отличается от реализации в предыдущем задании

Отдельно написана функция impl() для вычисления импликации

    // логическая функция, аргументы которой мы подбираем
static boolean f(boolean x, boolean y, boolean z, boolean w) {
return ((x && !y) || impl(w, z)) == (z == x);
}

// операция импликации(следования)
static boolean impl(boolean a, boolean b) {
return !a || b;
}

// проверка значений в линии на совпадение
static int findLine(boolean xV, boolean yV, boolean zV, boolean wV, boolean f, boolean[][] combinations) {
if (!yV && !zV && wV && f && combinations[0] == null) {
return 0;
}
if (!xV && yV && !zV && !wV && f && combinations[1] == null) {
return 1;
}
if (!xV && wV && f && combinations[2] == null) {
return 2;
}
return -1;
}

Получим:

++++++++++++++++++++++++++++++
перестановка: [2, 1, 3, 0]
z y w x
1 0 0 1
0 1 0 0
0 1 1 1

Пример 4

Задание
F=((xy)(yz))(xw)(wz))F=((x\land y)\lor(y\land z))\equiv(x\Rightarrow w)\land(w\Rightarrow z))

Логическая функция F задаётся выражением

На рисунке приведён частично заполненный фрагмент таблицы истинности функции F, содержащий неповторяющиеся строки. Определите, какому столбцу таблицы истинности функции F соответствует каждая из переменных x, y, z, w.

????F
01111
0101
0101

В ответе напишите буквы x, y, z, w в том порядке, в котором идут соответствующие им столбцы. Буквы в ответе пишите подряд, никаких разделителей между буквами ставить не нужно.

    // логическая функция, аргументы которой мы подбираем
static boolean f(boolean x, boolean y, boolean z, boolean w) {
return ((x && y) || (y && z)) == (impl(x, w) && impl(w, z));
}

// проверка значений в линии на совпадение
static int findLine(boolean xV, boolean yV, boolean zV, boolean wV, boolean f, boolean[][] combinations) {
if (!xV && yV && zV && wV && f && combinations[0] == null) {
return 0;
}
if (!xV && yV && !zV && f && combinations[1] == null) {
return 1;
}
if (!xV && yV && !zV && f && combinations[2] == null) {
return 2;
}
return -1;
}

Получим:

++++++++++++++++++++++++++++++
перестановка: [0, 3, 2, 1]
x w z y
0 1 1 1
0 1 0 0
0 1 0 1

Пример 5

Задание

Логическая функция F задаётся выражением

F=((wy)x)((wz)(yw))F=((w\lor y)\equiv x)\lor((w\Rightarrow z)\land(y\Rightarrow w))

На рисунке приведён частично заполненный фрагмент таблицы истинности функции F, содержащий неповторяющиеся строки. Определите, какому столбцу таблицы истинности функции F соответствует каждая из переменных x, y, z, w.

????F
110
10
111

В ответе напишите буквы x, y, z, w в том порядке, в котором идут соответствующие им столбцы. Буквы в ответе пишите подряд, никаких разделителей между буквами ставить не нужно.

В этом задании очень важно соблюсти порядок строк, иначе строка, подходящая под более конкретное требование может быть сохранена как строка с более общим требование(меньше значений в таблице), тогда строка, которая удовлетворяет только более общим требованиям уже не сохранится

    // логическая функция, аргументы которой мы подбираем
static boolean f(boolean x, boolean y, boolean z, boolean w) {
return (((w || y) == x)) || (impl(w, z) && impl(y, w));
}

// операция импликации(следования)
static boolean impl(boolean a, boolean b) {
return !a || b;
}

// проверка значений в линии на совпадение
static int findLine(boolean xV, boolean yV, boolean zV, boolean wV, boolean f, boolean[][] combinations) {
// сначала проверяем вторую строку, т.к. она - частный случай первой
if (xV && wV && !f && combinations[0] == null) {
return 0;
}
if (wV && !f && combinations[1] == null) {
return 1;
}
if (xV && zV && !f && combinations[2] == null) {
return 2;
}
return -1;
}

Получим:

++++++++++++++++++++++++++++++
перестановка: [1, 0, 2, 3]
y x z w
1 0 0 1
0 0 0 1
1 0 1 0

Пример 6

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

Рассмотрим задачу:

Задание

Каждое логическое выражение AA и BB зависит от одного и того же набора из 5 переменных. В таблицах истинности каждого из этих выражений в столбце значений стоит ровно по 4 единицы. Каково минимально возможное число единиц в столбце значений таблицы истинности выражения A¬BA \lor\lnot B?

Решение:

полная таблица истинности каждого выражения с пятью переменными содержит 25 = 32 строки

в каждой таблице по 4 единицы и по 28 (= 32 – 4) нуля

выражение A¬BA \lor\lnot B равно нулю тогда и только тогда, когда A=0A = 0 и B=1B = 1

минимальное количество единиц в таблице истинности выражения A¬BA \lor\lnot B будет тогда, когда там будет наибольшее число нулей, то есть в наибольшем количество строк одновременно A=0A = 0 и B=1B = 1

по условию A=0A = 0 в 28 строках, и B=1B = 1 в 4 строках, поэтому выражение A¬BA \lor\lnot B может быть равно нулю не более чем в 4 строках, оставшиеся 324=2832 – 4 = 28 могут быть равны 1

Ответ: 28.

Пример 7

Задание

Дан фрагмент таблицы истинности для выражения FF:

x1x2x3x4x5F
001001
101011
011101

Укажите максимально возможное число различных строк полной таблицы истинности этого выражения, в которых значение x1x_1 не совпадает с FF

полная таблица истинности выражения с пятью переменными содержит 25 = 32 строки

в приведённой части таблицы в двух строках значение x1x_1 совпадает с FF, а в одной – не совпадает

во всех оставшихся (неизвестных) 323=2932 – 3 = 29 строках значения x1x_1 и FF могут не совпадать

всего несовпадающих строк может быть 1+29=301 + 29 = 30.

Ответ: 30

Пример 8

Задание

Александра заполняла таблицу истинности для выражения F. Она успела заполнить лишь небольшой фрагмент таблицы:

x1x2x3x4x5x6x7x8F
010
101
111

Каким выражением может быть F?

  1. x1¬x2x3¬x4x5x6¬x7¬x8x_1 \land \lnot x_2 \land x_3 \land \lnot x_4 \land x_5 \land x_6 \land\lnot x_7 \land\lnot x_8
  2. x1x2x3¬x4¬x5¬x6¬x7¬x8x_1 \lor x_2 \lor x_3 \lor \lnot x_4 \lor\lnot x_5 \lor\lnot x_6 \lor\lnot x_7 \lor\lnot x_8
  3. ¬x1x2¬x3x4x5¬x6¬x7¬x8\lnot x_1 \land x_2 \land \lnot x_3 \land x_4 \land x_5 \land \lnot x_6 \land\lnot x_7 \land\lnot x_8
  4. x1¬x2x3¬x4¬x5¬x6¬x7¬x8x_1 \lor \lnot x_2 \lor x_3 \lor \lnot x_4 \lor\lnot x_5 \lor\lnot x_6 \lor\lnot x_7 \lor\lnot x_8

Решение

В последнем столбце таблицы истинности видим две единицы, откуда сразу следует, что это не может быть цепочка операций «И» (конъюнкций), которая даёт только одну единицу; поэтому ответы 1 и 3 заведомо неверные

Анализируем первую строку таблицы истинности; мы знаем в ней только два значения - x2=0x_2=0 и x8=1x_8=1.

Чтобы в результате в первой строке получить 0, необходимо, чтобы переменная x8x_8 входила в сумму с инверсией (тогда из 1 получится 0!), это условие выполняется для обоих оставшихся вариантов, 2 и 4

кроме того, переменная x2x_2 должна входить в выражение без инверсии (иначе соответствующее слагаемое в первой строке равно 1, и это даст в результате 1); этому условию не удовлетворяет выражение 4; остается один возможный вариант – выражение 2

Ответ: 2

Задания для самостоятельного выполнения