Problem: quick_sort

Your task is to implement a deterministic variant of Quick Sort and verify its correctness in Verus. The pivot must always be chosen as the first element of the slice (or sub-slice) being sorted. You need to implement: (1) partition: Reorders the slice such that all elements less than the pivot come before it, and all elements greater than or equal to the pivot come after it. It returns the final index of the pivot. (2) quick_sort: Recursive calls using the partition index, which is the function to be verified. There are several verification challenges: (1) Partitioning: Proving that the partition function permutes the array such that [< pivot, pivot, >= pivot] holds. (2) Termination: Proving that the recursive calls are strictly smaller. With pivot = first, if you aren't careful, a sorted array might result in a recursive call of size n-1 and 0. You must prove the pivot index is strictly bounded to ensure the recursion measure decreases. Note that you are not allowed to write new axioms (for example, writing seemingly correct property for multisets), and maybe directly using permutation is a better option.

use vstd::prelude::*;

verus! {
    // Following is the block for necessary definitions
    // <preamble>
    spec fn is_sorted(s: Seq<i32>) -> bool {
        forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j]
    }

    spec fn is_valid_index_permutation(p: Seq<int>, n: int) -> bool {
        &&& p.len() == n
        &&& (forall|i: int| 0 <= i < n ==> 0 <= #[trigger] p[i] < n)
        &&& (forall|i: int, j: int| 0 <= i < j < n ==> #[trigger] p[i] != #[trigger] p[j])
    }

    spec fn is_permutation(v1: Seq<i32>, v2: Seq<i32>) -> bool {
        exists|p: Seq<int>| 
            is_valid_index_permutation(p, v1.len() as int) 
            && v1.len() == v2.len()
            && (forall|i: int| 0 <= i < v1.len() ==> v2[i] == v1[#[trigger] p[i]])
    }
    // </preamble>

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

    // </helpers>

    // Following is the block for proofs of lemmas, or functions that help the implementation or verification of the main specification
    // <proofs>

    // </proofs>

    // Following is the block for the main specification
    // <spec>
    fn quick_sort(v: &mut Vec<i32>)
        ensures
            is_sorted(v@),
            is_permutation(old(v)@, v@),
    // </spec>
    // <code>
    {

    }
    // </code>

    fn main() {}
}