Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

Mastering Heap Tree Verification with Isabelle: A Step-by-Step Guide for COMP4161 Assignment 3

Learn how to tackle COMP4161 Assignment 3 on heap tree verification using Isabelle and AutoCorres. This guide covers tree-sorted invariants, heap-tree-push proofs, and C verification with real-world analogies from AI and gaming.

COMP4161 assignment 3 heap tree verification Isabelle proof assistant AutoCorres tutorial software verification priority queue correctness heap-tree-sorted invariant C code verification Hoare logic in Isabelle functional programming proofs induction in Isabelle sledgehammer tips AI priority queue gaming leaderboard heap Isabelle2024 assignment help

Introduction to Heap Tree Verification in Isabelle

Welcome to this comprehensive tutorial on advanced topics in software verification, specifically focused on COMP4161 Assignment 3. This assignment, set in May 2026, challenges you to prove correctness properties of a tree heap (priority queue) using Isabelle2024 and AutoCorres 1.11. Whether you're verifying a functional implementation or a C version, this guide will help you understand the key concepts and proof strategies.

Heap trees are everywhere in modern computing—from AI scheduling algorithms to gaming leaderboards. For instance, an AI chatbot like ChatGPT might use a priority queue to manage conversation contexts, where the highest-priority context is always served first. Similarly, in esports, a tournament bracket can be seen as a heap where the top seed is the root. Understanding how to verify such structures is crucial for building reliable software.

Understanding the Tree Heap Data Structure

A tree heap (or simply a heap) is a binary tree where each node satisfies the heap property: the value at any node is greater than or equal to (according to some ordering) the values in its children. This makes the root the highest-priority element. The heap-tree-sorted predicate in Isabelle captures this invariant:

fun heap-tree-sorted :: (\'a\ \ \'a\ \ bool) \ \'a tree\ \ bool where
  heap-tree-sorted ord Empty = True |
  heap-tree-sorted ord (Node x left right) =
    ((\y \ set (tree-elements left). ord x y) \
     (\y \ set (tree-elements right). ord x y) \
     heap-tree-sorted ord left \ heap-tree-sorted ord right)

Notice that unlike a binary search tree, there is no ordering between left and right children. This property is what makes heap operations efficient—O(log n) for push and pop in a balanced tree.

Functional Implementation: heap-tree-push

The core operation in this assignment is heap-tree-push, which replaces the root value and then pushes it down to restore the heap property. Here's the functional implementation from the provided theory file:

fun heap-tree-push :: (\'a\'a\bool) \ \'a\'a tree\'a tree\ where
  heap-tree-push ord x Empty = Empty |
  heap-tree-push ord x (Node _ left right) =
    (if left \ Empty \ ord (tree-top left) x \ (right = Empty \ ord (tree-top left) (tree-top right))
     then Node (tree-top left) (heap-tree-push ord x left) right
     else if right \ Empty \ ord (tree-top right) x
     then Node (tree-top right) left (heap-tree-push ord x right)
     else Node x left right)

This function recursively swaps the new value x with the highest-priority child until the heap property is restored. Proving that heap-tree-push maintains heap-tree-sorted is a key task in Question 1.

Proof Strategy for Question 1: Maintaining Sortedness

To prove that heap-tree-push preserves heap-tree-sorted, you'll need to use induction on the tree structure. The lemma you need to prove is:

lemma heap_tree_push_sorted:
  assumes "heap-tree-sorted ord t"
  shows "heap-tree-sorted ord (heap-tree-push ord x t)"

Here's a step-by-step approach:

  1. Case analysis on the tree t: either Empty or Node.
  2. For Empty, the result is Empty, which is trivially sorted.
  3. For Node, consider the two conditional branches in heap-tree-push.
  4. Use the induction hypothesis on the recursive calls to heap-tree-push in the subtrees.
  5. Leverage the assumption that the original tree was sorted to relate the root value to the children.

You may find Isabelle's auto and simp methods helpful, but be prepared to use blast or force for more complex goals. Remember to use find_theorems to explore automatically generated facts like rel_tree.

Connecting to the C Implementation and AutoCorres

Part 2 of the assignment shifts to verifying the C implementation using AutoCorres. The C code (provided in heap.c) implements the same push operation but with explicit pointer manipulation. AutoCorres lifts this to a monadic abstraction, making verification more manageable.

The key types are tree-heap-C (the C struct) and the memory model with th-dom and th-vals. Your task in Q2.1 is to prove that two tree-heap-C values are equal if each of their four fields are equal. This is a straightforward lemma using auto:

lemma tree_heap_c_eqI:
  assumes "val_C a = val_C b" and "left_C a = left_C b"
      and "right_C a = right_C b" and "parent_C a = parent_C b"
  shows "a = b"
  by (simp add: tree_heap_c_ext_def)

For Q2.2, you'll need to prove that the C function maintains the heap invariant. The inductive predicate tree-in-C defines which pointers are valid and what tree structure they represent. You'll use Hoare logic (via AutoCorres) to specify pre- and post-conditions.

Practical Tips for Using Isabelle and AutoCorres

Here are some tips to streamline your verification:

  • Use sledgehammer wisely: It can suggest proofs, but always verify they terminate. If a proof fails, try breaking the goal into smaller subgoals.
  • Explore the environment: Use find_theorems to discover facts about tree-heap-C, th_dom, and th_vals. The automatic definitions are your friends.
  • Leverage existing lemmas: The theory files likely contain helper lemmas. Don't reinvent the wheel.
  • Use the right proof method: For structural induction, induct is your go-to. For properties of sets, auto often suffices.

Real-World Inspiration: AI and Gaming

Heap trees are not just academic—they power the priority queues in AI systems like recommendation engines and game matchmaking. For example, in a battle royale game, a heap can manage player rankings, where the top player is always at the root. When a player's score changes, a push operation updates their position efficiently. Verifying such operations ensures that the game's leaderboard remains correct.

In the context of AI, consider a chatbot that prioritizes user queries. A heap can ensure urgent queries are handled first. The verification techniques you learn here apply directly to building trustworthy AI systems.

Conclusion

This tutorial covered the essential steps for completing COMP4161 Assignment 3, from understanding the heap tree invariant to proving functional correctness and verifying C code with AutoCorres. By following the proof strategies and tips provided, you'll be well-equipped to tackle the assignment. Remember to use Isabelle's powerful automation tools and the wealth of automatically generated facts. Good luck!