source: CIVL/examples/verifyThis/binaryTreeTraversal.cvl@ 397ae5f

main test-branch
Last change on this file since 397ae5f was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/* VerifyThis 2016 - Challenge 2: Binary Tree Traversal
2 * https://docs.google.com/document/d/1TvvoRovDQtmuXth6vcWtUNCQCNmzZO9X_DdcxM9aXbQ/edit
3 *
4 * We are given a binary tree with the following properties:
5 * - It is well formed, in the sense that following a child pointer (left or
6 * right) and then following a parent pointer brings us to the original
7 * node. Moreover, the parent pointer of the root is null.
8 * - It has at least one node, and each node has 0 or 2 children.
9 * We do not know the initial value of the mark fields.
10 * Our goal is to set all mark fields to true. The algorithm below (Morris
11 * 1979) works in time linear in the number of nodes, as usual, but uses
12 * only a constant amount of extra space.
13 *
14 * Tasks. Prove that:
15 * (1) upon termination of the algorithm, all mark fields are set
16 * (2) the tree shape does not change
17 * (3) the code does not crash, and
18 * (4) the code terminates.
19 * (bonus) the nodes are visited in depth-first order
20 *
21 * This solution verifies tasks (1) to (4).
22 *
23 * Author: Stephen Siegel
24 */
25#include <civlc.cvh>
26#include <stdbool.h>
27#include <stdlib.h>
28#include <stdio.h>
29
30$input int DB = 5; // depth bound
31
32typedef struct _tree {
33 struct _tree *left;
34 struct _tree *right;
35 struct _tree *parent;
36 _Bool mark;
37} *Tree;
38
39// algorithm to mark every node in tree...
40void markTree(Tree root) {
41 Tree x, y;
42
43 x = root;
44 while (true) {
45 x->mark = $true;
46 if (x->left == NULL && x->right == NULL) {
47 y = x->parent;
48 } else {
49 y = x->left;
50 x->left = x->right;
51 x->right = x->parent;
52 x->parent = y;
53 }
54 x = y;
55 if (x==NULL)
56 break;
57 }
58}
59
60// make a new Tree from given children, allocating on heap
61Tree makeTree(Tree left, Tree right, _Bool mark) {
62 Tree result = (Tree)malloc(sizeof(struct _tree));
63
64 result->left = left;
65 result->right = right;
66 result->mark = mark;
67 result->parent = NULL;
68 if (left != NULL)
69 left->parent = result;
70 if (right != NULL)
71 right->parent = result;
72 return result;
73}
74
75// construct an arbitrary tree of depth at most "depth"
76Tree makeArbitrary(int depth) {
77 if (depth == 0)
78 return NULL;
79
80 // nondeterministic choice between two things:
81 // 0: return tree with 0 nodes
82 // 1: return tree with 2 nodes
83 if ($choose_int(2) == 0)
84 return makeTree(NULL, NULL, false);
85
86 Tree t1 = makeArbitrary(depth - 1);
87 Tree t2 = makeArbitrary(depth - 1);
88 Tree result = makeTree(t1, t2, false);
89
90 return result;
91}
92
93// print tree, for debugging only...
94void printTree(Tree tree) {
95 if (tree == NULL)
96 printf("NULL\n");
97 else {
98 printf("Begin Tree: %p\n", tree);
99 printf("Mark: ");
100 if (tree->mark)
101 printf("true\n");
102 else
103 printf("false\n");
104 printf("Parent: %p\n", tree->parent);
105 printf("Left:\n");
106 printTree(tree->left);
107 printf("Right:\n");
108 printTree(tree->right);
109 printf("End Tree\n");
110 }
111}
112
113// deep copy a tree, ignoring marks...
114Tree copyTree(Tree root) {
115 if (root == NULL)
116 return NULL;
117
118 Tree t1 = copyTree(root->left);
119 Tree t2 = copyTree(root->right);
120
121 return makeTree(t1, t2, false);
122}
123
124// free all nodes in the tree rooted at root...
125void freeTree(Tree root) {
126 if (root != NULL) {
127 freeTree(root->left);
128 freeTree(root->right);
129 free(root);
130 }
131}
132
133// example for debuggin only...
134Tree makeExample1() {
135 Tree n1 = makeTree(NULL, NULL, false);
136 Tree n2 = makeTree(NULL, NULL, true);
137 Tree n3 = makeTree(n1, n2, false);
138
139 return n3;
140}
141
142// example for debuggin only...
143Tree makeExample2() {
144 Tree n1 = makeTree(NULL, NULL, false);
145 Tree n2 = makeTree(NULL, n1, false);
146 Tree n3 = makeTree(NULL, n2, false);
147
148 return n3;
149}
150
151// checks every node in Tree t is marked...
152_Bool checkAllMarked(Tree t) {
153 if (t != NULL) {
154 if (!(t->mark)) return false;
155 if (!checkAllMarked(t->left)) return false;
156 if (!checkAllMarked(t->right)) return false;
157 }
158 return true;
159}
160
161// checks two trees have same "shape"
162void checkIso(Tree t1, Tree t2) {
163 if (t1 == NULL)
164 $assert(t2 == NULL);
165 if (t2 == NULL)
166 $assert(t1 == NULL);
167 if (t1 != NULL) {
168 checkIso(t1->left, t2->left);
169 checkIso(t1->right, t2->right);
170 }
171}
172
173// generate arbitrary tree up to depth bound
174// and check all marked, termination, no invalid
175// pointer operations, and resulting tree has unchanged
176// shape...
177int main() {
178 Tree t1 = makeArbitrary(DB);
179 Tree t2 = copyTree(t1);
180
181 $assume(t1 != NULL);
182 markTree(t1);
183 $assert(checkAllMarked(t1));
184 checkIso(t1, t2);
185 freeTree(t1);
186 freeTree(t2);
187}
Note: See TracBrowser for help on using the repository browser.