X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=ocaml%2Fsimple.ml;h=d600d30f6347a07697628181248d0c13856aff65;hb=73c253890a1f287278327aa49db613941ebf9527;hp=27d0119e58c505ba6918f43a02bf3bad879d8015;hpb=26ff6df470edda1ce022f1ba88e3769fe6323a4a;p=fireball-separation.git diff --git a/ocaml/simple.ml b/ocaml/simple.ml index 27d0119..d600d30 100644 --- a/ocaml/simple.ml +++ b/ocaml/simple.ml @@ -9,14 +9,42 @@ open Pure type var = int;; type t = | V of var - | A of bool * t * t + | A of (bool ref) * t * t | L of (bool * t) ;; -let rec measure_of_t = function - | V _ -> 0 - | A(b,t1,t2) -> (if b then 1 else 0) + measure_of_t t1 + measure_of_t t2 - | L(b,t) -> if b then measure_of_t t else 0 +let measure_of_t = + let rec aux acc = function + | V _ -> acc, 0 + | A(b,t1,t2) -> + let acc, m1 = aux acc t1 in + let acc, m2 = aux acc t2 in + if not (List.memq b acc) && !b then b::acc, 1 + m1 + m2 else acc, m1 + m2 + | L(b,t) -> if b then aux acc t else acc, 0 + in snd ++ (aux []) +;; + +let index_of x = + let rec aux n = + function + [] -> None + | x'::_ when x == x' -> Some n + | _::xs -> aux (n+1) xs + in aux 1 +;; + +let sep_of_app = + let apps = ref [] in + function + r when not !r -> " " + | r -> + let i = + match index_of r !apps with + Some i -> i + | None -> + apps := !apps @ [r]; + List.length !apps + in " " ^ string_of_int i ^ ":" ;; let string_of_t = @@ -30,7 +58,7 @@ let string_of_t = | A _ | L _ as t -> "(" ^ string_of_term_no_pars level t ^ ")" and string_of_term_no_pars_app level = function - | A(b,t1,t2) -> string_of_term_no_pars_app level t1 ^ (if b then "," else " ") ^ string_of_term_w_pars level t2 + | A(b,t1,t2) -> string_of_term_no_pars_app level t1 ^ sep_of_app b ^ string_of_term_w_pars level t2 | _ as t -> string_of_term_w_pars level t and string_of_term_no_pars level = function | L(_,t) -> "λ" ^ string_of_bvar level ^ ". " ^ string_of_term_no_pars (level+1) t @@ -39,7 +67,7 @@ let string_of_t = ;; -let delta = L(true,A(true,V 0, V 0));; +let delta = L(true,A(ref true,V 0, V 0));; (* does NOT lift the argument *) let mk_lams = fold_nat (fun x _ -> L(false,x)) ;; @@ -100,18 +128,26 @@ let rec no_leading_lambdas v n = function | V v' -> if v = v' then n else 0 ;; -(* b' defaults to false *) +(* b' is true iff we are substituting the argument of a step + and the application of the redex was true. Therefore we need to + set the new app to true. *) let rec subst b' level delift sub = function | V v -> if v = level + fst sub then lift level (snd sub) else V (if delift && v > level then v-1 else v) | L(b,t) -> L(b, subst b' (level + 1) delift sub t) | A(_,t1,(V v as t2)) when b' && v = level + fst sub -> - mk_app b' (subst b' level delift sub t1) (subst b' level delift sub t2) + mk_app (ref true) (subst b' level delift sub t1) (subst b' level delift sub t2) | A(b,t1,t2) -> mk_app b (subst b' level delift sub t1) (subst b' level delift sub t2) +(* b is + - a fresh ref true if we want to create a real application from scratch + - a shared ref true if we substituting in the head of a real application *) and mk_app b' t1 t2 = if t1 = delta && t2 = delta then raise B else match t1 with - | L(b,t1) -> subst (b' && not b) 0 true (0, t2) t1 + | L(b,t1) -> + let last_lam = match t1 with L _ -> false | _ -> true in + if not b && last_lam then b' := false ; + subst (!b' && not b && not last_lam) 0 true (0, t2) t1 | _ -> A (b', t1, t2) and lift n = let rec aux lev = @@ -122,13 +158,13 @@ and lift n = in aux 0 ;; let subst = subst false 0 false;; -let mk_app = mk_app true;; +let mk_app t1 = mk_app (ref true) t1;; let eta_eq = let rec aux t1 t2 = match t1, t2 with | L(_,t1), L(_,t2) -> aux t1 t2 - | L(_,t1), t2 -> aux t1 (A(true,lift 1 t2,V 0)) - | t1, L(_,t2) -> aux (A(true,lift 1 t1,V 0)) t2 + | L(_,t1), t2 -> aux t1 (A(ref true,lift 1 t2,V 0)) + | t1, L(_,t2) -> aux (A(ref true,lift 1 t1,V 0)) t2 | V a, V b -> a = b | A(_,t1,t2), A(_,u1,u2) -> aux t1 u1 && aux t2 u2 | _, _ -> false @@ -244,36 +280,6 @@ let compute_max_lambdas_at hd_var j = let print_cmd s1 s2 = print_endline (">> " ^ s1 ^ " " ^ s2);; -(* eat the arguments of the divergent and explode. - It does NOT perform any check, may fail if done unsafely *) -let eat p = -print_cmd "EAT" ""; - let var, k = get_inert p.div in - let phase = p.phase in - let p = - match phase with - | `One -> - let n = 1 + max - (compute_max_lambdas_at var (k-1) p.div) - (compute_max_lambdas_at var (k-1) p.conv) in - (* apply fresh vars *) - let p, t = fold_nat (fun (p, t) _ -> - let p, v = freshvar p in - p, A(false, t, V (v + k)) - ) (p, V 0) n in - let p = {p with phase=`Two} in - let t = A(false, t, delta) in - let t = fold_nat (fun t m -> A(false, t, V (k-m))) t (k-1) in - let subst = var, mk_lams t k in - let p = subst_in_problem subst p in - let _, args = get_inert p.div in - {p with div = inert_cut_at (args-k) p.div} - | `Two -> - let subst = var, mk_lams delta k in - subst_in_problem subst p in - sanity p -;; - (* step on the head of div, on the k-th argument, with n fresh vars *) let step k n p = let var, _ = get_inert p.div in @@ -281,20 +287,52 @@ print_cmd "STEP" ("on " ^ string_of_t (V var) ^ " (of:" ^ string_of_int n ^ ")") let p, t = (* apply fresh vars *) fold_nat (fun (p, t) _ -> let p, v = freshvar p in - p, A(false, t, V (v + k + 1)) + p, A(ref false, t, V (v + k + 1)) ) (p, V 0) n in let t = (* apply bound variables V_k..V_0 *) - fold_nat (fun t m -> A(false, t, V (k-m+1))) t (k+1) in + fold_nat (fun t m -> A(ref false, t, V (k-m+1))) t (k+1) in let t = mk_lams t (k+1) in (* make leading lambdas *) let subst = var, t in let p = subst_in_problem subst p in sanity p ;; +let finish p = + let compute_max_arity = + let rec aux n = function + | A(_,t1,t2) -> max (aux (n+1) t1) (aux 0 t2) + | L(_,t) -> max n (aux 0 t) + | V _ -> n + in aux 0 in +print_cmd "FINISH" ""; + let div_hd, div_nargs = get_inert p.div in + let j = div_nargs - 1 in + let arity = compute_max_arity p.conv in + let n = 1 + arity + max + (compute_max_lambdas_at div_hd j p.div) + (compute_max_lambdas_at div_hd j p.conv) in + let p = step j n p in + let div_hd, div_nargs = get_inert p.div in + let rec aux m = function + A(_,t1,t2) -> if is_var t2 then + (let delta_var, _ = get_inert t2 in + if delta_var <> div_hd && get_subterm_with_head_and_args delta_var 1 p.conv = None + then m, delta_var + else aux (m-1) t1) else aux (m-1) t1 + | _ -> assert false in + let m, delta_var = aux div_nargs p.div in + let p = subst_in_problem (delta_var, delta) p in + let p = subst_in_problem (div_hd, mk_lams delta (m-1)) p in + sanity p +;; + let rec auto p = let hd_var, n_args = get_inert p.div in match get_subterm_with_head_and_args hd_var n_args p.conv with | None -> + (try problem_fail (finish p) "Auto.2 did not complete the problem" + with Done sigma -> sigma) + (* (try let phase = p.phase in let p = eat p in @@ -302,6 +340,7 @@ let rec auto p = then problem_fail p "Auto.2 did not complete the problem" else auto p with Done sigma -> sigma) + *) | Some t -> let j = find_eta_difference p t n_args in let k = 1 + max @@ -311,7 +350,7 @@ let rec auto p = let p = step j k p in let m2 = measure_of_t p.div in (if m2 >= m1 then - (print_string "WARNING! Measure did not decrease (press )"; + (print_string ("WARNING! Measure did not decrease : " ^ string_of_int m2 ^ " >= " ^ string_of_int m1 ^ " (press )"); ignore(read_line()))); auto p ;; @@ -325,7 +364,7 @@ let problem_of (label, div, convs, ps, var_names) = | `N _ | `Match _ -> assert false in assert (List.length ps = 0); let convs = List.rev convs in - let conv = List.fold_left (fun x y -> mk_app x (aux (y :> Num.nf))) (V (List.length var_names)) convs in + let conv = if List.length convs = 1 then aux (List.hd convs :> Num.nf) else List.fold_left (fun x y -> mk_app x (aux (y :> Num.nf))) (V (List.length var_names)) convs in let var_names = "@" :: var_names in let div = match div with | Some div -> aux (div :> Num.nf)