Software Abstraction Cheat Sheet

How Formal Methods Compress Programs into Essential Structure

Abstraction here means: forget some implementation detail (mutation, allocation, scheduling, evaluation order, pointer layout…) while preserving the structure you need to reason about a property (correctness, safety, liveness, equivalence).
Many examples are intentionally simplified to highlight the math. When a model is a toy (e.g., email regex), it's labeled as such.

Part I

Foundational Models of Computation

1 Lambda Calculus

Core Idea
Everything is a function. Data, control flow, recursion: all encoded as function application.
Notation
λx.body defines function, (f a) applies function
Example 1 Factorial
Py Code (Python)
python
def factorial(n):
    result = 1
    for i in range(1, n + 1):
        result *= i
    return result
λ Lambda Calculus
lambda
fact = Y (λf. λn. if (iszero n) 1 (mult n (f (pred n))))

where:
  Y    = λf.(λx.f(x x))(λx.f(x x))  -- fixed-point combinator
  mult = λm.λn.λf.m(n f)            -- Church numerals
  pred = λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u)
Example 2 Boolean Logic (AND)
Py Code (Python)
def and_gate(a, b):
    if a == True:
        if b == True:
            return True
        else:
            return False
    else:
        return False
λ Lambda Calculus
TRUE  = λx.λy.x
FALSE = λx.λy.y
AND   = λp.λq.p q p

2 Turing Machines

Core Idea
Computation as mechanical state transitions over tape symbols.
Notation
δ(state, symbol) → (new_state, write_symbol, direction)
Example 1 Increment Binary Number
Py Code (Python)
def increment_binary(bits):
    carry = 1
    result = []
    for bit in reversed(bits):
        if carry:
            if bit == '0':
                result.append('1')
                carry = 0
            else:
                result.append('0')
                carry = 1
        else:
            result.append(bit)
    if carry:
        result.append('1')
    return ''.join(reversed(result))
TM Turing Machine
States: {qcarry, halt}
Alphabet: {0, 1, □}

Transitions (add 1 with carry):
  δ(qcarry, 0) = (halt,   1, L)  -- flip 0→1, done
  δ(qcarry, 1) = (qcarry, 0, L)  -- flip 1→0, carry
  δ(qcarry, □) = (halt,   1, L)  -- overflow: new 1

3 Finite State Machines / Automata

Core Idea
Computation with finite memory. Captures "modes" and "transitions."
Notation
(States, Alphabet, δ, start, accept)
Vending Machine (click states to step)

3.5 Regular Expressions & Context-Free Structure

Core Idea
Regex/FA: finite "mode memory". CFG/PDA: finite control + unbounded stack (nesting).
Notation
Regex ⇄ NFA ⇄ DFA, CFG ⇄ PDA
Example Balanced Parentheses
Py Code (Python)
def balanced(s):
    count = 0
    for c in s:
        if c == '(': count += 1
        elif c == ')': count -= 1
        if count < 0: return False
    return count == 0
G CFG / PDA
CFG:  S → SS | "(" S ")" | ε

PDA:
  read '(' → push
  read ')' → pop (reject if empty)
  accept if stack empty at end

4 Recursive Function Theory

Core Idea
Build functions from zero, successor, projection, composition, and primitive recursion.
Notation
Z = 0, S(n) = n+1, h = Pr[f, g]
Example Addition
Py Code
def add(m, n):
    result = m
    for _ in range(n):
        result += 1
    return result
PR Primitive Recursion
add(m, 0)    = m           -- base
add(m, S(n)) = S(add(m, n)) -- step

Formally: add = Pr[π₁, Cn[S, π₃]]

Part II

Semantic Frameworks

5 Denotational Semantics

Core Idea
Programs denote mathematical objects (functions). Meaning is compositional.
Notation
⟦program⟧ : Environment → Value
Example While Loop
Py Code
x = 5
while x > 0:
    x = x - 1
# x is now 0
⟦⟧ Denotational
⟦while b do c⟧ = fix(F)

F = λφ.λσ. if ⟦b⟧σ = true 
            then φ(⟦c⟧σ) 
            else σ

6 Operational Semantics (Small-Step)

Core Idea
Meaning defined by reduction rules. How does the program step?
Notation
⟨config⟩ → ⟨config'⟩
Example Arithmetic Reduction
Py Execution Trace
(2 + 3) * 4
= 5 * 4      # addition first
= 20         # then multiplication
Small-Step SOS
⟨(2+3)*4, σ⟩ → ⟨5*4, σ⟩
             → ⟨20, σ⟩

Rule: ⟨n₁+n₂, σ⟩ → ⟨n, σ⟩

7 Axiomatic Semantics (Hoare Logic)

Core Idea
Meaning = what you can prove. Specify pre/post conditions.
Notation
{P} C {Q} means "If P holds before C, then Q holds after"
Example Loop with Invariant
Py Code
# Sum 1 to n
s = 0; i = 0
while i < n:
    i = i + 1
    s = s + i
# s = n(n+1)/2
{} Hoare Logic
{n ≥ 0}
{INV: s = i(i+1)/2 ∧ i ≤ n}
while i < n do body
{s = n(n+1)/2}

8 Separation Logic

Core Idea
Extend Hoare logic for heap/pointers with "separating conjunction."
Notation
P * Q means "P and Q hold on disjoint memory regions"
Example Linked List Node
C Code (C)
Node* n = malloc(sizeof(Node));
n->value = val;
n->next = NULL;
return n;
* Separation Logic
{emp}
  n := alloc(2);
{n ↦ _, _}
  [n] := val; [n+1] := NULL;
{n ↦ val, NULL}

Part III

Type Theory and Logic

9 Type Systems

Core Idea
Classify expressions by "what kind of thing" they compute. Prevent errors statically.
Notation
Γ ⊢ e : τ means "in context Γ, expression e has type τ"
Example Function Application
Py Code
def double(x: int) -> int:
    return x * 2

result = double(5)  # OK
# double("hi")  # Type error!
Type Judgment
Γ ⊢ double : Int → Int
Γ ⊢ 5 : Int
────────────────────────
Γ ⊢ double(5) : Int

9.5 Refinement Types & Dependent Types

Core Idea
Types + predicates. Types can depend on values.
Notation
x : Int { x ≥ 0 }, Vec A n (vector of n elements)

10 Curry-Howard Correspondence

Core Idea
Types are propositions, programs are proofs. Logic and computation unified.
Notation
A → B = function, A × B = pair, A + B = Either
Correspondence Programs = Proofs
λ Types (Programs)
A → B     (function)
A × B     (pair/tuple)
A + B     (Either/union)
⊥         (Void/Never)
Logic (Proofs)
A ⟹ B    (implication)
A ∧ B     (conjunction)
A ∨ B     (disjunction)
⊥         (false)

11 Category Theory for Programming

Core Idea
Abstract over structure-preserving transformations. Functors, natural transformations, monads.
Notation
Functor F : C → D, Monad M with return and bind

Part IV

Concurrency and Process Algebras

12 Process Algebra (CSP / CCS / π-calculus)

Core Idea
Concurrent processes as algebraic terms. Composition, synchronization as operators.
Notation
P = a → Q, P □ Q (choice), P ∥ Q (parallel)

12.5 Behavioral Equivalence

Core Idea
Compare systems by observable behavior: trace equivalence, bisimulation.

13 Petri Nets

Core Idea
Concurrent systems as bipartite graphs. Places hold tokens, transitions fire.
Notation
(P, T, F, M₀) where P=places, T=transitions, F=flow, M₀=initial marking

14 Temporal Logic (LTL / CTL)

Core Idea
Specify properties about time: what must/may eventually/always happen.
Notation
(always), (eventually), (next), U (until)
Example Safety & Liveness
En Natural Language
"The mutex is never held
by two processes at once"

"Every request eventually
gets a response"
Temporal Logic
□(¬(holds₁ ∧ holds₂))
  [SAFETY]

□(request → ◇response)
  [LIVENESS]

Part V

Abstract Interpretation & Verification

15 Abstract Interpretation

Core Idea
Sound approximation via Galois connections. Trade precision for decidability.
Notation
(C, α, γ, A) where α abstracts, γ concretizes
Example Sign Analysis
Py Concrete
x = 5      # x ∈ {5}
y = -3     # y ∈ {-3}
z = x * y  # z ∈ {-15}
α Abstract (Signs)
x = +   # positive
y = -   # negative
z = + × - = -  # negative

16 Model Checking

Core Idea
Exhaustively verify temporal properties on finite-state models.
Notation
M ⊨ φ means "model M satisfies formula φ"

16.5 SAT/SMT Solving

Core Idea
Reduce program questions to constraint solving.
Notation
sat(φ), SMT, path constraints

Part VI

Data Abstraction

17 Abstract Data Types (ADTs)

Core Idea
Data = signature + axioms. Hide representation.
Notation
Operations + Laws (e.g., pop(push(s, x)) = s)
Example Stack ADT
Py Implementation
class Stack:
    def __init__(self):
        self._data = []
    def push(self, x):
        self._data.append(x)
    def pop(self):
        return self._data.pop()
Σ ADT Specification
Stack[T]
  empty : Stack[T]
  push  : Stack[T] × T → Stack[T]
  pop   : Stack[T] → Stack[T] × T

pop(push(s, x)) = (s, x)

18 Relational Algebra

Core Idea
Data as mathematical relations. Query = algebraic expression.
Notation
σ (select), π (project), (join), (union)
Example Database Query
SQL SQL
SELECT name, dept
FROM employees
WHERE salary > 50000
π Relational Algebra
π_{name,dept}(
  σ_{salary>50000}(employees)
)

Part VII

The Limits of Abstraction

19 Fundamental Limits

Core Idea
Rice's Theorem, Gödel's Incompleteness, and the Abstraction-Precision tradeoff.
Rice's Theorem: ANY non-trivial semantic property of programs is undecidable. "Does this program halt?", "Is this program equivalent to that?" - all undecidable.
Implication: Perfect analysis is impossible. All useful abstractions approximate. This is why we need abstract interpretation, model checking, and other sound-but-incomplete methods.

Quick Reference Card

Abstraction Key Insight Notation
Lambda Calculus Everything is a function λx.e, (f x)
Turing Machine Mechanical state changes δ(q,a)=(q′,b,D)
FSM Modes + transitions (Q, Σ, δ, q₀, F)
Denotational Programs = math objects ⟦P⟧ρ
Operational Step-by-step reduction ⟨e,σ⟩ → ⟨e′,σ′⟩
Hoare Logic Pre/post contracts {P} C {Q}
Separation Logic Disjoint heap regions P * Q
Type Systems Classify by kind Γ ⊢ e : τ
Curry-Howard Proofs = programs Types = propositions
Category Theory Structure preservation Functor, Monad
Process Algebra Concurrent composition P ∥ Q, P □ Q
Petri Nets Token flow Places, transitions
Temporal Logic Properties over time □, ◇, U, AG, EF
Abstract Interp. Sound approximation (C, α, γ, A)
Model Checking Exhaustive verification M ⊨ φ
ADT Signature + axioms ops + laws
Relational Algebra Data as relations σ, π, ⋈, ∪

"The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise." Edsger W. Dijkstra
Quick Reference