Problem: trie_delete

Your task is to implement the Delete operation for a Byte-based Trie data structure (Prefix Tree) and verify its correctness in Dafny. This operation removes a key (seq<int>, representing bytes) from the tree. Crucially, this implementation must perform "Eager Pruning" (or Trimming). If deleting a key leaves a node with no children and is_end set to false (making it a "useless" node), that node must be removed entirely from the tree. This pruning process must propagate upwards to ensure the tree remains minimal. Specifically, you must prove the following: (1) Set Update: The abstract view of the resulting tree must be exactly the difference between the original view and the key. If the key was not present, the view remains unchanged. (2) Invariant Preservation (Pruning): The result must satisfy opt_well_formed. In this specification, well_formed strictly forbids "empty" nodes (nodes that are not endpoints and have no children). Therefore, proving this invariant formally verifies that your implementation correctly pruned all dead branches created by the deletion.

// Following is the block for necessary definitions
// <preamble>
datatype Option<T> = Some(value: T) | None

datatype Node = Node(
    is_end: bool,
    // A sequence of children, representing bytes 0..255
    children: seq<Option<Node>>
) {
    // A node is "empty" (useless) if it marks no key and leads to no keys.
    // Requirement: children sequence must be size 256 for the quantifier index to be valid.
    predicate is_empty() 
        requires |this.children| == 256
    {
        !this.is_end && (forall i: int {:trigger this.children[i]} :: 0 <= i < 256 ==> this.children[i].None?)
    }

    // Standard structural integrity + The Pruning Invariant
    predicate well_formed() 
        decreases this
    {
        // 1. Must have exactly 256 slots (for u8)
        && |this.children| == 256
        // 2. Recursive check for all children
        && (forall i: int {:trigger this.children[i]} :: 0 <= i < 256 ==> 
            match this.children[i] {
                case Some(child) => 
                    // The child must be structurally valid
                    && child.well_formed()
                    // CRITICAL: The child must not be useless.
                    // child.well_formed() ensures |child.children| == 256, satisfying is_empty's precondition.
                    && !child.is_empty()
                case None => true
            }
        )
    }

    // Recursive definition of containment
    function contains(key: seq<int>): bool
        decreases |key|
    {
        if |key| == 0 then
            this.is_end
        else
            var char_idx := key[0];
            if 0 <= char_idx < |this.children| then
                match this.children[char_idx] {
                    case Some(child) => child.contains(key[1..])
                    case None => false
                }
            else
                false
    }

    // View as a Set of byte sequences
    ghost function view(): iset<seq<int>> {
        iset key: seq<int> | this.contains(key)
    }
}

ghost function opt_view(node: Option<Node>): iset<seq<int>> {
    match node {
        case Some(n) => n.view()
        case None => iset{}
    }
}

predicate opt_well_formed(node: Option<Node>) {
    match node {
        case Some(n) => 
            // The node structure is valid
            && n.well_formed() 
            // The root itself must not be useless (if it is, the tree should be None)
            && !n.is_empty()
        case None => true
    }
}
// </preamble>

// Following is the block for potential helper specifications
// <helpers>

// </helpers>

// Following is the block for proofs of lemmas
// <proofs>

// </proofs>

// Following is the block for the main specification
// <spec>
method delete(tree: Option<Node>, key: seq<int>) returns (res: Option<Node>)
    requires opt_well_formed(tree)
    // Constraint: Input key elements must represent bytes (u8)
    requires forall k :: k in key ==> 0 <= k < 256
    ensures 
        // Crucial: The implementation must prune dead branches to satisfy this
        && opt_well_formed(res)
        // Set difference: existing view minus the key
        && opt_view(res) == opt_view(tree) - iset{key}
// </spec>
// <code>
{
    // Implement and verify the delete function for Trie data structure
}
// </code>

method main() {}