From 7c60aa45d5f4486768b6338e2e5aa411dbec8ad9 Mon Sep 17 00:00:00 2001 From: acondolu Date: Wed, 30 May 2018 16:31:24 +0200 Subject: [PATCH] Simple strong separation implemented! - Two phases for eat - Moved code - Reduction does not diverge (replaces DD with B) --- ocaml/andrea.ml | 115 +++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 45 deletions(-) diff --git a/ocaml/andrea.ml b/ocaml/andrea.ml index 7493905..dcc954e 100644 --- a/ocaml/andrea.ml +++ b/ocaml/andrea.ml @@ -14,6 +14,8 @@ type t = | B (* bottom *) ;; +let delta = L(A(V 0, V 0));; + let eta_eq = let rec aux l1 l2 t1 t2 = match t1, t2 with | L t1, L t2 -> aux l1 l2 t1 t2 @@ -55,6 +57,7 @@ type problem = { ; conv : t ; sigma : (var * t) list (* substitutions *) ; stepped : var list + ; phase : [`One | `Two] (* :'( *) } let string_of_problem p = @@ -109,7 +112,7 @@ let rec subst level delift sub = let t2 = subst level delift sub t2 in mk_app t1 t2 | B -> B -and mk_app t1 t2 = match t1 with +and mk_app t1 t2 = if t1 = delta && t2 = delta then B else match t1 with | B | _ when t2 = B -> B | L t1 -> subst 0 true (0, t2) t1 | t1 -> A (t1, t2) @@ -168,19 +171,74 @@ let check p sigma = let sanity p = print_endline (string_of_problem p); (* non cancellare *) if p.conv = B then problem_fail p "p.conv diverged"; - if p.div = B then raise (Done p.sigma); + (* if p.div = B then raise (Done p.sigma); *) + if p.phase = `Two && p.div = delta then raise (Done p.sigma); if not (is_inert p.div) then problem_fail p "p.div converged" ;; +(* drops the arguments of t after the n-th *) +let inert_cut_at n t = + let rec aux t = + match t with + | V _ as t -> 0, t + | A(t1,_) as t -> + let k', t' = aux t1 in + if k' = n then n, t' + else k'+1, t + | _ -> assert false + in snd (aux t) +;; + +let find_eta_difference p t n_args = + let t = inert_cut_at n_args t in + let rec aux t u k = match t, u with + | V _, V _ -> assert false (* div subterm of conv *) + | A(t1,t2), A(u1,u2) -> + if not (eta_eq t2 u2) then (print_endline((string_of_t t2) ^ " <> " ^ (string_of_t u2)); k) + else aux t1 u1 (k-1) + | _, _ -> assert false + in aux p.div t n_args +;; + +let compute_max_lambdas_at hd_var j = + let rec aux hd = function + | A(t1,t2) -> + (if get_inert t1 = (hd, j) + then max ( (*FIXME*) + if is_inert t2 && let hd', j' = get_inert t2 in hd' = hd + then let hd', j' = get_inert t2 in j - j' + else no_leading_lambdas t2) + else id) (max (aux hd t1) (aux hd t2)) + | L t -> aux (hd+1) t + | V _ -> 0 + | _ -> assert false + in aux hd_var +;; + 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, n = get_inert p.div in - let subst = var, mk_lams B n in + let var, k = get_inert p.div in + let phase = p.phase in + let p, t = + match phase with + | `One -> + let n = 1 + max + (compute_max_lambdas_at var k p.div) + (compute_max_lambdas_at var k p.conv) in + (* apply fresh vars *) + let p, t = fold_nat (fun (p, t) _ -> + let p, v = freshvar p in + p, A(t, V (v + k)) + ) (p, V 0) n in + let p = {p with phase=`Two} in p, A(t, delta) + | `Two -> p, delta in + let subst = var, mk_lams t k in let p = subst_in_problem subst p in + let p = if phase = `One then {p with div = (match p.div with A(t,_) -> t | _ -> assert false)} else p in sanity p; p ;; @@ -216,7 +274,7 @@ let problem_of div conv = print_hline (); let [@warning "-8"] [div; conv], var_names = parse ([div; conv]) in let varno = List.length var_names in - let p = {orig_freshno=varno; freshno=1+varno; div; conv; sigma=[]; stepped=[]} in + let p = {orig_freshno=varno; freshno=1+varno; div; conv; sigma=[]; stepped=[]; phase=`One} in (* initial sanity check *) sanity p; p ;; @@ -229,50 +287,17 @@ let exec div conv cmds = | Done _ -> () ;; -(* drops the arguments of t after the n-th *) -let inert_cut_at n t = - let rec aux t = - match t with - | V _ as t -> 0, t - | A(t1,_) as t -> - let k', t' = aux t1 in - if k' = n then n, t' - else k'+1, t - | _ -> assert false - in snd (aux t) -;; - -let find_eta_difference p t n_args = - let t = inert_cut_at n_args t in - let rec aux t u k = match t, u with - | V _, V _ -> assert false (* div subterm of conv *) - | A(t1,t2), A(u1,u2) -> - if not (eta_eq t2 u2) then (print_endline((string_of_t t2) ^ " <> " ^ (string_of_t u2)); k) - else aux t1 u1 (k-1) - | _, _ -> assert false - in aux p.div t n_args -;; - -let compute_max_lambdas_at hd_var j = - let rec aux hd = function - | A(t1,t2) -> - (if get_inert t1 = (hd, j) - then max ( (*FIXME*) - if is_inert t2 && let hd', j' = get_inert t2 in hd' = hd - then let hd', j' = get_inert t2 in j - j' - else no_leading_lambdas t2) - else id) (max (aux hd t1) (aux hd t2)) - | L t -> aux (hd+1) t - | V _ -> 0 - | _ -> assert false - in aux hd_var -;; - 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 (eat p) "Auto did not complete the problem" with Done sigma -> sigma) + (try + let phase = p.phase in + let p = eat p in + if phase = `Two + 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 - 1 in let k = 1 + max -- 2.39.2