#include "treebuffer.h" #include // bounded number of new nodes that will be added $input int N; $assume(0 < N && N <= 5); $input int HISTORY_SIZE; $assume(0 < HISTORY_SIZE && HISTORY_SIZE < N); $input int Data[N]; // the non-deterministic pick of an existing tree as a parent $input int TreePicks[N + 1]; $assume($forall (int i : 0 .. N) 0 <= TreePicks[i] && TreePicks[i] <= i); // all possible results: N iterations * trace-size $output int Traces[N][HISTORY_SIZE]; void write_to_output(int iter, Node * history[]) { // read trace: int h = 0; for (; h < HISTORY_SIZE; h++) if (history[h] != 0) Traces[iter][h] = get_data(history[h]); else break; // make all unused elements -1 in Traces: for (; h < HISTORY_SIZE; h++) Traces[iter][h] = -1; } int main() { Tree * tree = empty(HISTORY_SIZE); Tree * forest[N + 1]; // N new tree + the empty tree int num_trees = 0; $elaborate(N); forest[num_trees++] = tree; while (num_trees <= N) { tree = forest[TreePicks[num_trees-1]]; $elaborate(TreePicks[num_trees-1]); $atomic{ Tree * new_tree = add(tree, Data[num_trees-1]); forest[num_trees++] = new_tree; tree = new_tree; } $atomic{ Node * history[HISTORY_SIZE + 1]; // 0-terminated array (i.e. extra element at the end as 0) int h = 0; take(tree, history); write_to_output(num_trees - 2, history); } } // delete forest for (int i = 0; i < num_trees; i++) delete(forest[i]); return 0; }