File: same_fringe.mlw

package info (click to toggle)
why3 1.8.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 45,028 kB
  • sloc: xml: 185,443; ml: 111,224; ansic: 3,998; sh: 2,578; makefile: 2,568; java: 865; python: 720; javascript: 290; lisp: 205; pascal: 173
file content (101 lines) | stat: -rw-r--r-- 2,419 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

(*
  ``Same fringe'' is a famous problem.
  Given two binary search trees, you must decide whether they contain the
  same elements. See for instance http://www.c2.com/cgi/wiki?SameFringeProblem
*)

module SameFringe

  use int.Int
  use list.List
  use list.Length
  use list.Append

  (* binary trees with elements at the nodes *)

  type elt

  val eq (x y: elt) : bool ensures { result <-> x=y }

  type tree =
    | Empty
    | Node tree elt tree

  function elements (t : tree) : list elt = match t with
    | Empty -> Nil
    | Node l x r -> elements l ++ Cons x (elements r)
  end

  (* the left spine of a tree, as a bottom-up list *)

  type enum =
    | Done
    | Next elt tree enum

  function enum_elements (e : enum) : list elt = match e with
    | Done -> Nil
    | Next x r e -> Cons x (elements r ++ enum_elements e)
  end

  (* the enum of a tree [t], prepended to a given enum [e] *)

  let rec enum t e variant { t }
    ensures { enum_elements result = elements t ++ enum_elements e }
  = match t with
    | Empty -> e
    | Node l x r -> enum l (Next x r e)
    end

  let rec eq_enum e1 e2 variant { length (enum_elements e1) }
    ensures { result=True <-> enum_elements e1 = enum_elements e2 }
  = match e1, e2 with
    | Done, Done ->
        True
    | Next x1 r1 e1, Next x2 r2 e2 ->
        eq x1 x2 && eq_enum (enum r1 e1) (enum r2 e2)
    | _ ->
        False
    end

  let same_fringe t1 t2
    ensures { result=True <-> elements t1 = elements t2 }
  = eq_enum (enum t1 Done) (enum t2 Done)

  let test1 () = enum Empty Done
  let test2 () = eq_enum Done Done
  let test3 () = same_fringe Empty Empty

  val constant a : elt
  val constant b : elt

  let leaf x = Node Empty x Empty

  let test4 () = same_fringe (Node (leaf a) b Empty) (Node Empty a (leaf b))
  let test5 () = same_fringe (Node (leaf a) b Empty) (Node Empty b (leaf a))

  exception BenchFailure

  let bench () raises { BenchFailure -> true } =
    if not (test4 ()) then raise BenchFailure

end

module Test

  use int.Int
  clone SameFringe with type elt = int

  let test1 () = enum Empty Done
  let test2 () = eq_enum Done Done
  let test3 () = same_fringe Empty Empty

  constant a : int = 1
  constant b : int = 2

  let leaf x = Node Empty x Empty

  let test4 () = same_fringe (Node (leaf a) b Empty) (Node Empty a (leaf b))
  let test5 () = same_fringe (Node (leaf a) b Empty) (Node Empty b (leaf a))

end