Бинарные отношения и их свойства
Учимся описывать связи между объектами строго — через бинарные отношения и их ключевые свойства.
Бинарное отношение на множестве A — это любое подмножество декартова произведения
A × A, то есть набор упорядоченных пар элементов A.
Зачем нужны отношения
«Меньше», «делится на», «является другом», «ссылается на», «наследуется от» — всё это связи между объектами. В программировании отношения повсюду: граф подписок в соцсети, зависимости между модулями, сравнение элементов при сортировке, связи между таблицами в базе данных (то самое «реляционное» в SQL — от слова relation, отношение). Чтобы рассуждать о таких связях строго, математика вводит понятие бинарного отношения — и набор свойств, по которым отношения классифицируют.
Что такое отношение формально
Раньше мы определили декартово произведение A × A — множество всех пар элементов A. Так вот: отношение — это просто выбор некоторых из этих пар. Если пара (a, b) входит в отношение R, говорят «a связано с b» и пишут a R b или (a, b) ∈ R.
Например, на множестве {1, 2, 3} отношение «меньше» — это набор пар {(1,2), (1,3), (2,3)}. Отношение «равно» — это {(1,1), (2,2), (3,3)}. Любой набор пар — это какое-то отношение, даже если у него нет красивого названия.
Четыре свойства, которые надо знать
Отношения классифицируют по тому, как они себя ведут. Вот главные свойства (пусть R — отношение на A).
| Свойство | Определение словами | Пример |
| Рефлексивность | каждый элемент связан сам с собой: (a, a) ∈ R для всех a | «равно», «делится на» |
| Симметричность | если a R b, то и b R a | «быть другом», «равно» |
| Антисимметричность | если a R b и b R a, то a = b | «меньше или равно», «делится на» |
| Транзитивность | если a R b и b R c, то a R c | «меньше», «предок» |
Разберём интуицию. Рефлексивность — «связь с самим собой есть всегда». Симметричность — «связь работает в обе стороны» (дружба взаимна). Антисимметричность — почти противоположность: «в обе стороны связь работает только у элемента с самим собой» (если a ≤ b и b ≤ a, то a и b просто равны). Транзитивность — «связь передаётся по цепочке» (если a меньше b, а b меньше c, то a меньше c).
Важно не путать «не симметрично» с «антисимметрично»: это разные вещи. Отношение может быть и не симметричным, и не антисимметричным одновременно.
Проверяем свойства на Python
Раз отношение — это просто множество пар, проверить любое свойство можно перебором. Напишем три функции-проверки и натравим их на конкретное отношение.
S = {1, 2, 3}
# Отношение R = {(1,1),(2,2),(3,3),(1,2),(2,1)} — диагональ плюс пара 1~2
R = {(1, 1), (2, 2), (3, 3), (1, 2), (2, 1)}
def reflexive(R, S):
return all((x, x) in R for x in S)
def symmetric(R):
return all((b, a) in R for (a, b) in R)
def transitive(R):
return all((a, c) in R
for (a, b) in R
for (b2, c) in R if b == b2)
print("Рефлексивно: ", reflexive(R, S))
print("Симметрично: ", symmetric(R))
print("Транзитивно: ", transitive(R))
Вывод:
Рефлексивно: True Симметрично: True Транзитивно: True
Разберём функцию transitive: мы перебираем все пары (a, b) и (b2, c), и когда «середина» совпадает (b == b2), требуем, чтобы пара (a, c) тоже была в отношении. Это дословный перевод определения транзитивности на код. Такой приём — «определение из учебника превращаем в перебор по парам» — работает для любого свойства отношений.
Матрица и граф отношения
У отношения есть два полезных наглядных представления:
- Матрица. Таблица из нулей и единиц: в клетке (i, j) стоит 1, если
i R j. Тогда рефлексивность — это единицы по всей главной диагонали; симметричность — матрица равна своей транспонированной (симметрична относительно диагонали). - Граф. Точки-элементы, и стрелка из a в b, если
a R b. Симметричное отношение даёт «двусторонние» рёбра, рефлексивное — петли у каждой вершины. Этот взгляд напрямую ведёт нас к теории графов.
Эти два представления — не просто иллюстрации: с ними удобно вычислять. Например, транзитивное замыкание отношения (достижимость по цепочкам) считают именно через матрицу или граф.
Зачем булеан растёт так быстро: цена перебора подмножеств
Факт «у n-элементного множества 2^n подмножеств» — это не просто красивая формула, а предупреждение для программиста. Многие задачи в лоб требуют перебрать все подмножества: найти оптимальную команду, лучшую комбинацию признаков, подмножество предметов с заданной суммой. Такой перебор делает 2^n шагов — и это быстро становится неподъёмным.
Прикинем масштаб: для 20 элементов это около миллиона вариантов (доли секунды), для 40 — уже триллион (минуты-часы), а для 60 — больше квинтиллиона (годы). Каждый новый элемент удваивает работу. Именно поэтому задачи на подмножества — классический источник «комбинаторного взрыва», и в следующих разделах мы увидим, как комбинаторика и грамотные алгоритмы помогают не перебирать всё подряд. Понимание 2^n — это интуиция о том, где «простой перебор» перестаёт работать.
Матричный взгляд: отношение как таблица нулей и единиц
Закрепим идею матрицы отношения на конкретном примере. Возьмём отношение «меньше или равно» на множестве {1, 2, 3} и выпишем его матрицу: в клетке (i, j) ставим 1, если i ≤ j. По матрице свойства видны глазами: рефлексивность — это единицы по всей диагонали, а транзитивность «меньше-равно» даёт характерную «ступенчатую» картину.
R = {(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)} # отношение «≤»
S = [1, 2, 3]
print("Матрица отношения «≤» (1 = связаны):")
print(" " + " ".join(str(j) for j in S))
for i in S:
row = " ".join("1" if (i, j) in R else "0" for j in S)
print(f"{i} | {row}")
reflexive = all((x, x) in R for x in S)
print("Рефлексивно (вся диагональ из 1):", reflexive)
Вывод:
Матрица отношения «≤» (1 = связаны):
1 2 3
1 | 1 1 1
2 | 0 1 1
3 | 0 0 1
Рефлексивно (вся диагональ из 1): True
Единицы заполнили верхний треугольник вместе с диагональю — это «подпись» отношения порядка. А будь отношение симметричным, матрица была бы зеркальна относительно диагонали. Матричное представление — не просто иллюстрация: на нём строят эффективные алгоритмы (умножение матриц отношений даёт композицию, а возведение в степень — транзитивное замыкание).
Типичные ошибки
- Путать симметричность и антисимметричность. Это не «или одно, или другое». Отношение «меньше» (
<) не симметрично и при этом антисимметрично (вырожденно: пар вида a<b и b<a просто нет). А «дружба» симметрична, но не антисимметрична. - Забывать «для всех» в рефлексивности. Достаточно одного элемента без петли
(a, a)— и отношение уже не рефлексивно. - Проверять транзитивность только на «явных» цепочках. Нужно перебрать все пары с общей серединой, иначе легко пропустить контрпример.
Итог
- Отношение на A — подмножество
A × A, набор связанных пар. - Четыре ключевых свойства: рефлексивность, симметричность, антисимметричность, транзитивность.
- Каждое свойство — это проверяемое перебором условие на парах.
- Отношение можно представить матрицей 0/1 или графом со стрелками.