generate_all_trees: no duplicate elements

parent b4324d3c
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
Given n, the program return an array a of size n+1 such that Given n, the program return an array a of size n+1 such that
a[i] contains the list of all binary trees of size i. a[i] contains the list of all binary trees of size i.
TODO: - show that there is no duplicate in a[i] TODO: tail-recursive version of combine
- tail-recursive version of combine
*) *)
module GenerateAllTrees module GenerateAllTrees
...@@ -15,6 +14,7 @@ module GenerateAllTrees ...@@ -15,6 +14,7 @@ module GenerateAllTrees
use import list.List use import list.List
use import list.Mem use import list.Mem
use import list.Append use import list.Append
use import list.Distinct
use import module array.Array use import module array.Array
type tree = Empty | Node tree tree type tree = Empty | Node tree tree
...@@ -31,35 +31,43 @@ module GenerateAllTrees ...@@ -31,35 +31,43 @@ module GenerateAllTrees
exists l r: tree. t = Node l r /\ size l < size t exists l r: tree. t = Node l r /\ size l < size t
predicate all_trees (n: int) (l: list tree) = predicate all_trees (n: int) (l: list tree) =
distinct l /\
forall t: tree. size t = n <-> mem t l forall t: tree. size t = n <-> mem t l
lemma all_trees_0: all_trees 0 (Cons Empty Nil) lemma all_trees_0: all_trees 0 (Cons Empty Nil)
lemma tree_diff:
forall l1 l2: tree. size l1 <> size l2 ->
forall r1 r2: tree. Node l1 r1 <> Node l2 r2
(* combines two lists of trees l1 and l2 into the list of trees (* combines two lists of trees l1 and l2 into the list of trees
with a left sub-tree from l1 and a right sub-tree from l2 *) with a left sub-tree from l1 and a right sub-tree from l2 *)
let combine (i1: int) (l1: list tree) (i2: int) (l2: list tree) = let combine (i1: int) (l1: list tree) (i2: int) (l2: list tree) =
{ 0 <= i1 /\ all_trees i1 l1 /\ 0 <= i2 /\ all_trees i2 l2 } { 0 <= i1 /\ all_trees i1 l1 /\ 0 <= i2 /\ all_trees i2 l2 }
let rec loop1 (l1: list tree) : list tree = let rec loop1 (l1: list tree) : list tree =
{ } { distinct l1 }
match l1 with match l1 with
| Nil -> Nil | Nil -> Nil
| Cons t1 l1 -> | Cons t1 l1 ->
let rec loop2 (l2: list tree) : list tree = let rec loop2 (l2: list tree) : list tree =
{} { distinct l2 }
match l2 with match l2 with
| Nil -> Nil | Nil -> Nil
| Cons t2 l2 -> Cons (Node t1 t2) (loop2 l2) | Cons t2 l2 -> Cons (Node t1 t2) (loop2 l2)
end end
{ forall t:tree. mem t result <-> { distinct result /\
forall t:tree. mem t result <->
(exists r: tree. t = Node t1 r /\ mem r l2) } (exists r: tree. t = Node t1 r /\ mem r l2) }
in in
loop2 l2 ++ loop1 l1 loop2 l2 ++ loop1 l1
end end
{ forall t:tree. mem t result <-> { distinct result /\
forall t:tree. mem t result <->
(exists l r: tree. t = Node l r /\ mem l l1 /\ mem r l2) } (exists l r: tree. t = Node l r /\ mem l l1 /\ mem r l2) }
in in
loop1 l1 loop1 l1
{ forall t:tree. mem t result <-> { distinct result /\
forall t:tree. mem t result <->
(exists l r: tree. t = Node l r /\ size l = i1 /\ size r = i2) } (exists l r: tree. t = Node l r /\ size l = i1 /\ size r = i2) }
let all_trees (n: int) = let all_trees (n: int) =
...@@ -72,6 +80,7 @@ module GenerateAllTrees ...@@ -72,6 +80,7 @@ module GenerateAllTrees
for j = 0 to i-1 do for j = 0 to i-1 do
invariant { invariant {
(forall k: int. 0 <= k < i -> all_trees k a[k]) /\ (forall k: int. 0 <= k < i -> all_trees k a[k]) /\
distinct a[i] /\
(forall t: tree. mem t a[i] <-> (forall t: tree. mem t a[i] <->
exists l r: tree. t = Node l r /\ size t = i /\ size l < j) } exists l r: tree. t = Node l r /\ size t = i /\ size l < j) }
a[i] <- (combine j a[j] (i-1-j) a[i-1-j]) ++ a[i] a[i] <- (combine j a[j] (i-1-j) a[i-1-j]) ++ a[i]
......
(* This file is generated by Why3's Coq driver *)
(* Beware! Only edit allowed sections below *)
Require Import ZArith.
Require Import Rbase.
Definition unit := unit.
Parameter qtmark : Type.
Parameter at1: forall (a:Type), a -> qtmark -> a.
Implicit Arguments at1.
Parameter old: forall (a:Type), a -> a.
Implicit Arguments old.
Inductive list (a:Type) :=
| Nil : list a
| Cons : a -> (list a) -> list a.
Set Contextual Implicit.
Implicit Arguments Nil.
Unset Contextual Implicit.
Implicit Arguments Cons.
Set Implicit Arguments.
Fixpoint mem (a:Type)(x:a) (l:(list a)) {struct l}: Prop :=
match l with
| Nil => False
| (Cons y r) => (x = y) \/ (mem x r)
end.
Unset Implicit Arguments.
Set Implicit Arguments.
Fixpoint infix_plpl (a:Type)(l1:(list a)) (l2:(list a)) {struct l1}: (list
a) :=
match l1 with
| Nil => l2
| (Cons x1 r1) => (Cons x1 (infix_plpl r1 l2))
end.
Unset Implicit Arguments.
Axiom Append_assoc : forall (a:Type), forall (l1:(list a)) (l2:(list a))
(l3:(list a)), ((infix_plpl l1 (infix_plpl l2
l3)) = (infix_plpl (infix_plpl l1 l2) l3)).
Axiom Append_l_nil : forall (a:Type), forall (l:(list a)), ((infix_plpl l
(Nil:(list a))) = l).
Set Implicit Arguments.
Fixpoint length (a:Type)(l:(list a)) {struct l}: Z :=
match l with
| Nil => 0%Z
| (Cons _ r) => (1%Z + (length r))%Z
end.
Unset Implicit Arguments.
Axiom Length_nonnegative : forall (a:Type), forall (l:(list a)),
(0%Z <= (length l))%Z.
Axiom Length_nil : forall (a:Type), forall (l:(list a)),
((length l) = 0%Z) <-> (l = (Nil:(list a))).
Axiom Append_length : forall (a:Type), forall (l1:(list a)) (l2:(list a)),
((length (infix_plpl l1 l2)) = ((length l1) + (length l2))%Z).
Axiom mem_append : forall (a:Type), forall (x:a) (l1:(list a)) (l2:(list a)),
(mem x (infix_plpl l1 l2)) <-> ((mem x l1) \/ (mem x l2)).
Axiom mem_decomp : forall (a:Type), forall (x:a) (l:(list a)), (mem x l) ->
exists l1:(list a), exists l2:(list a), (l = (infix_plpl l1 (Cons x l2))).
Inductive distinct{a:Type} : (list a) -> Prop :=
| distinct_zero : (distinct (Nil:(list a)))
| distinct_one : forall (x:a), (distinct (Cons x (Nil:(list a))))
| distinct_many : forall (x:a) (l:(list a)), (~ (mem x l)) ->
((distinct l) -> (distinct (Cons x l))).
Implicit Arguments distinct.
Axiom distinct_append : forall (a:Type), forall (l1:(list a)) (l2:(list a)),
(distinct l1) -> ((distinct l2) -> ((forall (x:a), (mem x l1) -> ~ (mem x
l2)) -> (distinct (infix_plpl l1 l2)))).
Parameter map : forall (a:Type) (b:Type), Type.
Parameter get: forall (a:Type) (b:Type), (map a b) -> a -> b.
Implicit Arguments get.
Parameter set: forall (a:Type) (b:Type), (map a b) -> a -> b -> (map a b).
Implicit Arguments set.
Axiom Select_eq : forall (a:Type) (b:Type), forall (m:(map a b)),
forall (a1:a) (a2:a), forall (b1:b), (a1 = a2) -> ((get (set m a1 b1)
a2) = b1).
Axiom Select_neq : forall (a:Type) (b:Type), forall (m:(map a b)),
forall (a1:a) (a2:a), forall (b1:b), (~ (a1 = a2)) -> ((get (set m a1 b1)
a2) = (get m a2)).
Parameter const: forall (b:Type) (a:Type), b -> (map a b).
Set Contextual Implicit.
Implicit Arguments const.
Unset Contextual Implicit.
Axiom Const : forall (b:Type) (a:Type), forall (b1:b) (a1:a), ((get (const(
b1):(map a b)) a1) = b1).
Inductive array (a:Type) :=
| mk_array : Z -> (map Z a) -> array a.
Implicit Arguments mk_array.
Definition elts (a:Type)(u:(array a)): (map Z a) :=
match u with
| (mk_array _ elts1) => elts1
end.
Implicit Arguments elts.
Definition length1 (a:Type)(u:(array a)): Z :=
match u with
| (mk_array length2 _) => length2
end.
Implicit Arguments length1.
Definition get1 (a:Type)(a1:(array a)) (i:Z): a := (get (elts a1) i).
Implicit Arguments get1.
Definition set1 (a:Type)(a1:(array a)) (i:Z) (v:a): (array a) :=
match a1 with
| (mk_array xcl0 _) => (mk_array xcl0 (set (elts a1) i v))
end.
Implicit Arguments set1.
Inductive tree :=
| Empty : tree
| Node : tree -> tree -> tree .
Set Implicit Arguments.
Fixpoint size(t:tree) {struct t}: Z :=
match t with
| Empty => 0%Z
| (Node l r) => ((1%Z + (size l))%Z + (size r))%Z
end.
Unset Implicit Arguments.
Axiom size_nonneg : forall (t:tree), (0%Z <= (size t))%Z.
Axiom size_left : forall (t:tree), (0%Z < (size t))%Z -> exists l:tree,
exists r:tree, (t = (Node l r)) /\ ((size l) < (size t))%Z.
Definition all_trees(n:Z) (l:(list tree)): Prop := (distinct l) /\
forall (t:tree), ((size t) = n) <-> (mem t l).
Axiom all_trees_0 : (all_trees 0%Z (Cons Empty (Nil:(list tree)))).
Axiom tree_diff : forall (l1:tree) (l2:tree), (~ ((size l1) = (size l2))) ->
forall (r1:tree) (r2:tree), ~ ((Node l1 r1) = (Node l2 r2)).
(* YOU MAY EDIT THE CONTEXT BELOW *)
(* DO NOT EDIT BELOW *)
Theorem WP_parameter_combine : forall (i1:Z), forall (l1:(list tree)),
forall (i2:Z), forall (l2:(list tree)), ((0%Z <= i1)%Z /\ ((all_trees i1
l1) /\ ((0%Z <= i2)%Z /\ (all_trees i2 l2)))) -> forall (l11:(list tree)),
(distinct l11) ->
match l11 with
| Nil => True
| (Cons t1 l12) => forall (l21:(list tree)), (distinct l21) ->
match l21 with
| Nil => True
| (Cons t2 l22) => (distinct l22) -> forall (result:(list tree)),
((distinct result) /\ forall (t:tree), (mem t result) <->
exists r:tree, (t = (Node t1 r)) /\ (mem r l22)) ->
forall (t:tree), (mem t (Cons (Node t1 t2) result)) ->
exists r:tree, (t = (Node t1 r)) /\ (mem r l21)
end
end.
(* YOU MAY EDIT THE PROOF BELOW *)
intuition.
destruct l11; intuition.
destruct l21; intuition.
unfold mem in H6; fold mem in H6.
destruct H6.
exists t0; intuition.
red; intuition.
generalize (H8 t1); clear H8. intuition.
destruct H8 as (r,h); exists r; intuition.
red; intuition.
Qed.
(* DO NOT EDIT BELOW *)
...@@ -69,6 +69,17 @@ Axiom mem_append : forall (a:Type), forall (x:a) (l1:(list a)) (l2:(list a)), ...@@ -69,6 +69,17 @@ Axiom mem_append : forall (a:Type), forall (x:a) (l1:(list a)) (l2:(list a)),
Axiom mem_decomp : forall (a:Type), forall (x:a) (l:(list a)), (mem x l) -> Axiom mem_decomp : forall (a:Type), forall (x:a) (l:(list a)), (mem x l) ->
exists l1:(list a), exists l2:(list a), (l = (infix_plpl l1 (Cons x l2))). exists l1:(list a), exists l2:(list a), (l = (infix_plpl l1 (Cons x l2))).
Inductive distinct{a:Type} : (list a) -> Prop :=
| distinct_zero : (distinct (Nil:(list a)))
| distinct_one : forall (x:a), (distinct (Cons x (Nil:(list a))))
| distinct_many : forall (x:a) (l:(list a)), (~ (mem x l)) ->
((distinct l) -> (distinct (Cons x l))).
Implicit Arguments distinct.
Axiom distinct_append : forall (a:Type), forall (l1:(list a)) (l2:(list a)),
(distinct l1) -> ((distinct l2) -> ((forall (x:a), (mem x l1) -> ~ (mem x
l2)) -> (distinct (infix_plpl l1 l2)))).
Parameter map : forall (a:Type) (b:Type), Type. Parameter map : forall (a:Type) (b:Type), Type.
Parameter get: forall (a:Type) (b:Type), (map a b) -> a -> b. Parameter get: forall (a:Type) (b:Type), (map a b) -> a -> b.
...@@ -135,8 +146,11 @@ Unset Implicit Arguments. ...@@ -135,8 +146,11 @@ Unset Implicit Arguments.
Axiom size_nonneg : forall (t:tree), (0%Z <= (size t))%Z. Axiom size_nonneg : forall (t:tree), (0%Z <= (size t))%Z.
Definition all_trees(n:Z) (l:(list tree)): Prop := forall (t:tree), Axiom size_left : forall (t:tree), (0%Z < (size t))%Z -> exists l:tree,
((size t) = n) <-> (mem t l). exists r:tree, (t = (Node l r)) /\ ((size l) < (size t))%Z.
Definition all_trees(n:Z) (l:(list tree)): Prop := (distinct l) /\
forall (t:tree), ((size t) = n) <-> (mem t l).
(* YOU MAY EDIT THE CONTEXT BELOW *) (* YOU MAY EDIT THE CONTEXT BELOW *)
...@@ -145,6 +159,7 @@ Definition all_trees(n:Z) (l:(list tree)): Prop := forall (t:tree), ...@@ -145,6 +159,7 @@ Definition all_trees(n:Z) (l:(list tree)): Prop := forall (t:tree),
Theorem all_trees_0 : (all_trees 0%Z (Cons Empty (Nil:(list tree)))). Theorem all_trees_0 : (all_trees 0%Z (Cons Empty (Nil:(list tree)))).
(* YOU MAY EDIT THE PROOF BELOW *) (* YOU MAY EDIT THE PROOF BELOW *)
red; intuition. red; intuition.
apply distinct_one.
destruct t; simpl; auto. destruct t; simpl; auto.
unfold size in H; fold size in H. unfold size in H; fold size in H.
right; generalize (size_nonneg t1); generalize (size_nonneg t2); omega. right; generalize (size_nonneg t1); generalize (size_nonneg t2); omega.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment