BRAGA

02 Writing02-02 Notes02-02-062

Tautology (t)

Published 16 Apr 20268 min read
Contents
  1. 01Deep Breakdown
  2. 02Flowchart
  3. 03Real-world use
  4. 04The formula, piece by piece
  5. 05The formula in words
  6. 06Critical Concepts
  7. 07Step-by-step calculation (tiny example)
  8. 08Code examples

True for all truth values of its components.

Deep Breakdown

What it tells me (Situation Awareness): A tautology is a logical statement (compound proposition) that is true regardless of the truth values of its component variables. No matter how you assign True/False to each variable, the whole expression evaluates to True. Tautologies represent logical truths — statements that are necessarily true by their structure alone, not by the facts of the world. In DA/DS, understanding tautologies matters for: verifying SQL/pandas filter logic, writing correct boolean conditions, and designing assertions that are always true (sanity checks that can never fail).

Flowchart

YesNo (at least one False)CompoundlogicalstatementBuild truth tableEvaluate for ALLcombinations ofvariable valuesAll rows = True?TAUTOLOGY:always true bystructureNOT a tautologyExample: p ∨ ¬p(Law ofExcludedMiddle)

Real-world use

Where it is used

Verifying logical conditions: a tautological condition like (age >= 0) is always true for valid data (if age is stored as unsigned), but explicitly writing (x OR NOT x) is a tautological SQL filter that acts as a no-op (WHERE TRUE). Data validation: assert not (df.empty and not df.empty) is a tautology (can never trigger). Proof verification: mathematical proofs by contradiction establish tautologies.

Problem it solves

In formal logic and database query optimization, recognizing tautologies lets you simplify expressions. SQL engines recognize and eliminate tautological conditions (e.g., WHERE 1=1 or WHERE col IS NOT NULL OR col IS NULL) that always evaluate to True, avoiding unnecessary filtering operations.

How it solves the problem

A tautology evaluates to True for every row of its truth table. Once identified, it can be replaced with TRUE (the constant), eliminating a potentially expensive evaluation. SQL query planners perform this optimization automatically when the tautology is recognizable.

Example in a business

In data validation: assert (predicted_class in [0, 1]) or (predicted_class not in [0, 1]) — this is p OR NOT p, a tautology. It can never fail. Useful in checking that your assertion framework is wired up correctly, or as a structural placeholder. In SQL: SELECT * FROM users WHERE is_active = TRUE OR is_active = FALSE — this is a tautology returning all rows (equivalent to WHERE 1=1).

The formula, piece by piece

Breaking the notation:

  • tt: the notation for a tautology in formal logic. The symbol tt or ⊤\top (top element) denotes "always true."
  • "True for all truth values of its components": a compound proposition where no assignment of True/False to its variables makes it False.

Classic tautologies:

  • p∨¬pp \lor \lnot p (Law of Excluded Middle): "A thing is either true or not true."
  • p⇒pp \Rightarrow p (Reflexivity): "If p, then p."
  • (p⇒q)⇔(¬q⇒¬p)(p \Rightarrow q) \Leftrightarrow (\lnot q \Rightarrow \lnot p) (Contrapositive equivalence).
  • ¬(p∧¬p)\lnot(p \land \lnot p) (Law of Non-Contradiction).
  • (p∧q)⇒p(p \land q) \Rightarrow p (Conjunction elimination).

Truth table for p∨¬pp \lor \lnot p (a simple tautology):

pp ¬p\lnot p p∨¬pp \lor \lnot p
T F T
F T T

Both rows are True → tautology.

The formula in words

"A tautology is a logical statement that is always true, no matter what. It's not true because of the facts — it's true because of how it's built. 'It will either rain or not rain today' is a tautology: true regardless of the weather. In code: x == x is always True for any x (floating-point NaN aside)."

Critical Concepts

  1. Tautology vs. contingency vs. contradiction: a tautology is always True; a contradiction is always False; a contingency is sometimes True and sometimes False.
  2. SQL WHERE 1=1: a common tautological filter used to simplify dynamic query building. It is recognized by all query planners and has no performance cost.
  3. NaN exception in Python: float('nan') == float('nan') is False in Python. So x == x is NOT a universal tautology for floats — NaN breaks it. Use pd.isna(x) to check for NaN.
  4. Tautological assertions (never triggered): writing assert True or assert a or not a (for booleans) creates an assertion that can never fail.

This is useless as a test but sometimes appears as a structural placeholder or proof artifact.

Step-by-step calculation (tiny example)

Task: verify that (p⇒q)∨¬p(p \Rightarrow q) \lor \lnot p is a tautology.

Step 1: Build truth table All combinations of p∈{T,F}p \in \{T, F\} and q∈{T,F}q \in \{T, F\}:

Step 2: Compute p⇒qp \Rightarrow q (False only when pp = T and qq = F)

pp qq p⇒qp \Rightarrow q ¬p\lnot p (p⇒q)∨¬p(p \Rightarrow q) \lor \lnot p
T T T F T
T F F F F
F T T T T
F F T T T

Step 3: Conclusion Not all rows are True (row 2 is False). This is NOT a tautology — it's a contingency. Compare to p∨¬pp \lor \lnot p: both rows are True → that IS a tautology.

Code examples

Beginner example (Python)

python
# Tautology: True for ALL truth values of its components
from itertools import product

def truth_table(func, n_vars: int, var_names: list[str]) -> None:
    """Print a truth table for a logical function."""
    combos = list(product([True, False], repeat=n_vars))
    header = " " + " ".join(f"{v:>6}" for v in var_names) + " | result[["
    print(header)
    print("]] " + "-" * (len(header) - 2))
    all_true = True
    for combo in combos:
        result = func(*combo)
    if not result:
        all_true = False
    row = " " + " ".join(f"{'T' if v else 'F':>6}" for v in combo)
    print(f"{row} | {'T' if result else 'F'}")
    print(f" → {'TAUTOLOGY' if all_true else 'NOT a tautology'}")
    print("Law of Excluded Middle: p OR NOT p")
truth_table(lambda p: p or not p, 1, ["p"])
print("\nContingency: p AND q")
truth_table(lambda p, q: p and q, 2, ["p", "q"])
print("\nContrapositive equivalence: (p→q) ↔ (¬q→¬p)")
implication = lambda p, q: (not p) or q   # p→q = NOT p OR q
contra = lambda p, q: q or (not p)   # ¬q→¬p = NOT(NOT q) OR NOT p
truth_table(lambda p, q: implication(p, q) == contra(p, q), 2, ["p", "q"])   # Practical: tautological SQL-style filter
data = [{"age": 25, "active": True}, {"age": 30, "active": False}, {"age": 0, "active": True}]
tautological_filter = [row for row in data if row["active"] or not row["active"]]   # always True
print(f"\nTautological filter returns all rows: {len(tautological_filter)} of {len(data)}")

Beginner example (R)

r
# Tautology: True for ALL truth values
truth_table <- function(func, var_names) { n <- length(var_names)
  combos <- expand.grid(rep(list(c(TRUE, FALSE)), n)) names(combos) <- var_names
  results <- apply(combos, 1, function(row) do.call(func, as.list(row)))
  combos$result <- results
  print(combos)
  cat(sprintf("→ %s\n\n", if (all(results)) "TAUTOLOGY" else "NOT a tautology"))
}
cat("Law of Excluded Middle: p OR NOT p\n")
truth_table(function(p) p | !p, c("p"))
cat("Contingency: p AND q\n")
truth_table(function(p, q) p & q, c("p", "q"))

Professional example (Python)

python
from itertools import product
import pandas as pd   # Scenario: verify logical conditions in data validation rules
# Check if a compound validation is a tautology (always passes)
# or a contingency (can fail)

def classify_proposition(func, n_vars: int) -> dict:
    """Classify a proposition as tautology, contradiction, or contingency."""
    results = [func(*combo) for combo in product([True, False], repeat=n_vars)]
    return { "all_true": all(results), "all_false": not any(results), "type": ("TAUTOLOGY" if all(results) else "CONTRADICTION" if not any(results) else "CONTINGENCY"), "true_count": sum(results), "false_count": len(results) - sum(results), "total": len(results), }   # Example validation rules (pretend they operate on two boolean fields)
#
is_valid = "record passes validation"
#
is_flagged = "record is flagged for review"
rules = { "is_valid OR NOT is_valid": lambda v, f: v or not v, "is_flagged AND NOT is_flagged": lambda v, f: f and not f, "is_valid OR is_flagged": lambda v, f: v or f, "is_valid AND is_flagged": lambda v, f: v and f, "NOT(is_valid AND NOT is_valid)": lambda v, f: not (v and not v), "(v→f) IFF (¬f→¬v)": lambda v, f: ((not v or f) == (not (not f) or not v)),
}
print("Logical Classification of Validation Rules")
print("=" * 56)
print(f" {'Rule':>42} {'Type':>14} {'T/F'}")
for rule_name, func in rules.items():
    info = classify_proposition(func, n_vars=2)
print(f" {rule_name:>42} {info['type']:>14} {info['true_count']}/{info['total']}")
print()
print(" Tautologies → always-pass assertions (structurally safe)")
print(" Contradictions → always-fail assertions (structural bug!)")
print(" Contingencies → real validation logic (can pass or fail)")

Professional example (R)

r
# Classify proposition by truth count: tautology / contradiction / contingency
truth_table <- expand.grid(A = c(TRUE, FALSE), B = c(TRUE, FALSE))
rules <- list( tautology = with(truth_table, A | !A), contradiction = with(truth_table, A & !A), contingency = with(truth_table, A & B)
)
for (rule_name in names(rules)) { vals <- rulesrule_name
  true_count <- sum(vals)
  total <- length(vals)
  type <- if (true_count == 0) "contradiction"
  else
  if (true_count == total) "tautology"
  else "contingency"
  cat(sprintf(" %15s %s %d/%d\n", rule_name, type, true_count, total))
}
cat(" Tautologies → always pass; contingencies → real validation.\n")

Source: domain knowledge

#foundations#number-sets-and-logic#mathematical-reasoning

Keyboard shortcuts

Single keys, ignored while typing in a field or with Cmd, Ctrl or Alt held.

0
Home
1 2 3 4
Work, Writing, Tools, About
j / k
Next / previous section on this page
n / p
Next / previous project or essay
u
Up one level
l
Deutsch
t
Light or dark theme
?
This list
Esc
Close