Problem: merge_sort

Your task is to implement Merge Sort and verify its correctness in Dafny. Merge Sort is a divide-and-conquer algorithm that divides the input array into two halves, calls itself for the two halves, and then merges the two sorted halves. You might implement two functions: (1) merge: Takes two sorted vectors and combines them into one sorted vector. (2) merge_sort: The recursive driver, which is the function to be verified. There are several verification challenges: (1) Proving that merge maintains the permutation property (the sum of counts in inputs equals counts in output). (2) Proving merge produces a sorted output. (3) Proving termination of the recursion (using a decrement on length). 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.

// Following is the block for necessary definitions
// <preamble>
ghost predicate is_sorted(s: seq<int>) {
    forall i, j :: 0 <= i < j < |s| ==> s[i] <= s[j]
}

ghost predicate is_valid_index_permutation(p: seq<int>, n: int) {
    && |p| == n
    && (forall i {:trigger p[i]} :: 0 <= i < n ==> 0 <= p[i] < n)
    && (forall i, j {:trigger p[i], p[j]} :: 0 <= i < j < n ==> p[i] != p[j])
}

ghost predicate is_permutation(v1: seq<int>, v2: seq<int>) {
    exists p: seq<int> :: 
        is_valid_index_permutation(p, |v1|) 
        && |v1| == |v2|
        && (forall i {:trigger p[i]} :: 0 <= i < |v1| ==> v2[i] == v1[p[i]])
}
// </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 merge_sort(v: seq<int>) returns (v_new: seq<int>)
    ensures is_sorted(v_new)
    ensures is_permutation(v, v_new)
// </spec>
// <code>
{
    // Implement and verify the Merge Sort algorithm here.
}
// </code>

method main() {}