Skip to main content
โšก Calmops

Axiomatic Semantics: Proving Program Properties

Introduction

Axiomatic semantics defines the meaning of a program through the properties it satisfies rather than how it executes. Instead of describing execution steps (operational) or assigning mathematical meanings (denotational), axiomatic semantics specifies what can be proven about a program using logical axioms and inference rules. This approach is particularly powerful for program verification and proving correctness properties.

This article explores Hoare logic, proof rules, and practical applications in formal verification.

Historical Context

Axiomatic semantics was pioneered by Tony Hoare in 1969 with his seminal paper “An Axiomatic Basis for Computer Programming.” Hoare logic, as it became known, provided a formal framework for reasoning about program correctness. This work laid the foundation for modern program verification and has influenced the development of formal methods throughout computer science.

Core Concepts

Hoare Triples

The fundamental concept in axiomatic semantics is the Hoare triple:

Notation: {P} s {Q}

Meaning: If precondition P holds before executing statement s, then postcondition Q holds after s terminates.

Components:

  • P (Precondition): A logical assertion about the state before execution
  • s (Statement): The program statement being verified
  • Q (Postcondition): A logical assertion about the state after execution

Example:

{x = 5} y := x + 1 {y = 6}

This says: “If x equals 5 before the assignment, then y equals 6 after.”

Assertions

An assertion is a logical formula describing properties of the program state:

State: ฯƒ: Var โ†’ โ„ค (assignment of values to variables)

Assertion: A predicate P(ฯƒ) that is either true or false for a given state

Examples:

x > 0           "x is positive"
x = y + 1       "x is one more than y"
x > 0 โˆง y > 0   "both x and y are positive"
โˆ€i. 0 โ‰ค i < n โ†’ a[i] > 0  "all array elements are positive"

Validity and Satisfiability

Valid Hoare Triple: {P} s {Q} is valid if:

  • For all states ฯƒ where P(ฯƒ) is true
  • If executing s from ฯƒ terminates in state ฯƒ'
  • Then Q(ฯƒ’) is true

Notation: โŠจ {P} s {Q}

Satisfiable: A Hoare triple is satisfiable if there exist states where it holds.

Proof Rules

Axiomatic semantics provides inference rules for proving Hoare triples.

Axiom: Skip

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{P} skip {P}

Skip does nothing, so the postcondition equals the precondition.

Axiom: Assignment

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{P[x โ†ฆ e]} x := e {P}

Where P[x โ†ฆ e] means “substitute e for x in P”

Intuition: To prove that x := e establishes P, we need P to hold with e substituted for x before the assignment.

Example:

To prove: {?} x := 5 {x = 5}
We need: x = 5 with x replaced by 5, which is 5 = 5 (true)
So: {true} x := 5 {x = 5}

Rule: Sequence

{P} sโ‚ {Q}    {Q} sโ‚‚ {R}
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{P} sโ‚; sโ‚‚ {R}

The postcondition of sโ‚ becomes the precondition of sโ‚‚.

Example:

{x = 5} y := x + 1 {y = 6}    {y = 6} z := y * 2 {z = 12}
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{x = 5} y := x + 1; z := y * 2 {z = 12}

Rule: Conditional

{P โˆง b} sโ‚ {Q}    {P โˆง ยฌb} sโ‚‚ {Q}
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{P} if b then sโ‚ else sโ‚‚ {Q}

Both branches must establish the same postcondition Q.

Example:

{x โ‰ฅ 0} if x > 0 then y := 1 else y := 0 {y โ‰ฅ 0}

Rule: While Loop

{I โˆง b} s {I}
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{I} while b do s {I โˆง ยฌb}

Where I is the loop invariantโ€”a property that holds before and after each iteration.

Intuition:

  • I holds before the loop
  • If I and b hold, executing s maintains I
  • When the loop exits (b is false), I and ยฌb hold

Example: Proving while x > 0 do x := x - 1 terminates with x = 0

Invariant: I = (x โ‰ฅ 0)
Precondition: {x โ‰ฅ 0}
Loop body: {x โ‰ฅ 0 โˆง x > 0} x := x - 1 {x โ‰ฅ 0}
Postcondition: {x โ‰ฅ 0 โˆง ยฌ(x > 0)} = {x = 0}

Rule: Consequence (Weakening)

P' โ†’ P    {P} s {Q}    Q โ†’ Q'
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{P'} s {Q'}

We can strengthen the precondition or weaken the postcondition.

Intuition: If P’ implies P, and we can prove {P} s {Q}, then {P’} s {Q} also holds.

Example:

{x > 5} x := x + 1 {x > 5}
Since x > 10 โ†’ x > 5, we have:
{x > 10} x := x + 1 {x > 5}

Proof Techniques

Forward Reasoning

Start with precondition and derive postcondition:

{x = 5}
y := x + 1
{y = 6}  (from assignment rule)
z := y * 2
{z = 12}  (from assignment rule)

Backward Reasoning

Start with desired postcondition and work backward:

Goal: {?} x := 5; y := x + 1 {y = 6}

Working backward:
{?} x := 5 {?} y := x + 1 {y = 6}

For y := x + 1 to establish y = 6:
Need: x + 1 = 6, so x = 5
Precondition for y := x + 1: {x = 5}

For x := 5 to establish x = 5:
Precondition: {true}

Result: {true} x := 5; y := x + 1 {y = 6}

Loop Invariant Discovery

Finding the right loop invariant is crucial:

Strategy:

  1. Identify what should be true throughout
  2. Verify it holds initially
  3. Verify it’s maintained by loop body
  4. Verify it implies the desired postcondition

Example: Summing array elements

Program: sum := 0; i := 0; while i < n do (sum := sum + a[i]; i := i + 1)

Invariant: I = (sum = ฮฃโฑผโ‚Œโ‚€^(i-1) a[j] โˆง 0 โ‰ค i โ‰ค n)

Initially: sum = 0, i = 0, so I holds
Maintained: If I holds and i < n, after loop body:
  sum' = sum + a[i] = ฮฃโฑผโ‚Œโ‚€^i a[j]
  i' = i + 1
  So I still holds
Exit: When i โ‰ฅ n, we have sum = ฮฃโฑผโ‚Œโ‚€^(n-1) a[j]

Practical Example: Proving Correctness

Program: Compute factorial

n := input
result := 1
i := 1
while i โ‰ค n do (
  result := result * i
  i := i + 1
)

Specification: {n โ‰ฅ 0} program {result = n!}

Proof:

{n โ‰ฅ 0}
result := 1
{result = 1 โˆง n โ‰ฅ 0}
i := 1
{result = 1 โˆง i = 1 โˆง n โ‰ฅ 0}

Loop invariant: I = (result = (i-1)! โˆง 1 โ‰ค i โ‰ค n+1)

{I}
while i โ‰ค n do (
  {I โˆง i โ‰ค n}
  result := result * i
  {result = i! โˆง i โ‰ค n}
  i := i + 1
  {result = (i-1)! โˆง i โ‰ค n+1}  (I maintained)
)
{I โˆง ยฌ(i โ‰ค n)}
{result = n! โˆง i = n+1}
{result = n!}

Advanced Topics

Partial vs Total Correctness

Partial Correctness: {P} s {Q}

  • If s terminates, Q holds
  • Doesn’t guarantee termination

Total Correctness: [P] s [Q]

  • s terminates and Q holds
  • Requires proving termination

Termination Proof: Use variant function (decreasing measure)

Concurrency

For concurrent programs, extend Hoare logic:

{Pโ‚} sโ‚ {Qโ‚}    {Pโ‚‚} sโ‚‚ {Qโ‚‚}
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
{Pโ‚ โˆง Pโ‚‚} sโ‚ โˆฅ sโ‚‚ {Qโ‚ โˆง Qโ‚‚}

Requires non-interference: sโ‚ and sโ‚‚ don’t interfere with each other’s variables.

Separation Logic

Extends Hoare logic for reasoning about heap-allocated data:

{P * R} s {Q * R}

Where * is the separating conjunction (P and Q hold on disjoint heap regions).

Glossary

Assertion: A logical formula describing program state properties

Axiomatic Semantics: Defining meaning through provable properties

Hoare Logic: Formal system for proving program correctness

Hoare Triple: {P} s {Q} - precondition, statement, postcondition

Invariant: A property that holds throughout execution

Loop Invariant: A property maintained by each loop iteration

Postcondition: Assertion that should hold after execution

Precondition: Assertion that should hold before execution

Proof Rule: Inference rule for deriving Hoare triples

Variant Function: Decreasing measure proving termination

Practice Problems

Problem 1: Prove {x = 5} y := x + 1; z := y * 2 {z = 12}

Solution:

{x = 5}
y := x + 1
{y = 6}  (assignment rule: x + 1 = 6 when x = 5)
z := y * 2
{z = 12}  (assignment rule: y * 2 = 12 when y = 6)

Problem 2: Find a loop invariant for while x > 0 do x := x - 1 starting with x = n.

Solution:

Invariant: I = (x โ‰ฅ 0)
Initially: x = n โ‰ฅ 0, so I holds
Maintained: If x โ‰ฅ 0 and x > 0, then x - 1 โ‰ฅ 0, so I maintained
Exit: When x โ‰ค 0, we have x = 0 (since x โ‰ฅ 0 from invariant)

Problem 3: Prove {true} x := 5 {x = 5}

Solution:

By assignment rule: {P[x โ†ฆ 5]} x := 5 {P}
We want: {true} x := 5 {x = 5}
So P = (x = 5)
P[x โ†ฆ 5] = (5 = 5) = true
Therefore: {true} x := 5 {x = 5}

Conclusion

Axiomatic semantics provides a powerful framework for proving program correctness through logical reasoning. By specifying what can be proven about a program rather than how it executes, axiomatic semantics enables rigorous verification of critical properties.

Hoare logic, with its elegant proof rules and intuitive reasoning about preconditions, postconditions, and invariants, has become the foundation for modern program verification tools and techniques. From simple sequential programs to concurrent systems and heap-allocated data, axiomatic semantics continues to evolve and provide essential tools for ensuring software correctness.

Understanding axiomatic semantics is essential for anyone involved in formal verification, program analysis, or the development of reliable software systems. It bridges the gap between informal correctness arguments and rigorous mathematical proofs, enabling the development of provably correct software.

Comments