\r
let delta = L(A(V 0, V 0));;\r
\r
+let rec is_stuck = function\r
+ | C -> true\r
+ | A(t,_) -> is_stuck t\r
+ | _ -> false\r
+;;\r
+\r
let eta_eq' =\r
let rec aux l1 l2 t1 t2 = match t1, t2 with\r
+ | _, _ when is_stuck t1 || is_stuck t2 -> true\r
| L t1, L t2 -> aux l1 l2 t1 t2\r
| L t1, t2 -> aux l1 (l2+1) t1 t2\r
| t1, L t2 -> aux (l1+1) l2 t1 t2\r
\r
(* is arg1 eta-subterm of arg2 ? *)\r
let eta_subterm u =\r
- let rec aux lev t = eta_eq' lev 0 u t || match t with\r
+ let rec aux lev t = if t = C then false else (eta_eq' lev 0 u t || match t with\r
| L t -> aux (lev+1) t\r
| A(t1, t2) -> aux lev t1 || aux lev t2\r
- | _ -> false\r
- in aux 0\r
+ | _ -> false) in\r
+ aux 0\r
;;\r
\r
(* does NOT lift the argument *)\r
{p with freshno=freshno+1}, freshno+1\r
;;\r
\r
+(* CSC: rename? is an applied C an inert?\r
+ is_inert and get_inert work inconsistently *)\r
let rec is_inert =\r
function\r
| A(t,_) -> is_inert t\r
| L _ | B -> false\r
;;\r
\r
+let rec is_constant =\r
+ function\r
+ C -> true\r
+ | V _ -> false\r
+ | B -> assert false\r
+ | A(t,_)\r
+ | L t -> is_constant t\r
+;;\r
+\r
let rec get_inert = function\r
- | V n -> (n,0)\r
+ | V _ | C as t -> (t,0)\r
| A(t, _) -> let hd,args = get_inert t in hd,args+1\r
| _ -> assert false\r
;;\r
\r
+let args_of_inert =\r
+ let rec aux acc =\r
+ function\r
+ | V _ | C -> acc\r
+ | A(t, a) -> aux (a::acc) t\r
+ | _ -> assert false\r
+ in\r
+ aux []\r
+;;\r
+\r
(* precomputes the number of leading lambdas in a term,\r
after replacing _v_ w/ a term starting with n lambdas *)\r
let rec no_leading_lambdas v n = function\r
| L t -> 1 + no_leading_lambdas (v+1) n t\r
- | A _ as t -> let v', m = get_inert t in if v = v' then max 0 (n - m) else 0\r
+ | A _ as t -> let v', m = get_inert t in if V v = v' then max 0 (n - m) else 0\r
| V v' -> if v = v' then n else 0\r
| B | C -> 0\r
;;\r
sigma=sub::p.sigma}\r
;;\r
\r
-let get_subterm_with_head_and_args hd_var n_args =\r
- let rec aux lev = function\r
- | C | V _ | B -> None\r
- | L t -> aux (lev+1) t\r
+let get_subterms_with_head hd_var =\r
+ let rec aux lev inert_done = function\r
+ | C | V _ | B -> []\r
+ | L t -> aux (lev+1) false t\r
| A(t1,t2) as t ->\r
let hd_var', n_args' = get_inert t1 in\r
- if hd_var' = hd_var + lev && n_args <= 1 + n_args'\r
- (* the `+1` above is because of t2 *)\r
- then Some (lift ~-lev t)\r
- else match aux lev t2 with\r
- | None -> aux lev t1\r
- | Some _ as res -> res\r
- in aux 0\r
+ if not inert_done && hd_var' = V (hd_var + lev)\r
+ then lift ~-lev t :: aux lev true t1 @ aux lev false t2\r
+ else aux lev true t1 @ aux lev false t2\r
+ in aux 0 false\r
;;\r
\r
let rec purify = function\r
;;\r
\r
(* drops the arguments of t after the n-th *)\r
-(* FIXME! E' usato in modo improprio contando sul fatto\r
- errato che ritorna un inerte lungo esattamente n *)\r
let inert_cut_at n t =\r
let rec aux t =\r
match t with\r
;;\r
\r
(* return the index of the first argument with a difference\r
- (the first argument is 0)\r
- precondition: p.div and t have n+1 arguments\r
- *)\r
-let find_eta_difference p t argsno =\r
- let t = inert_cut_at argsno t in\r
- let rec aux t u k = match t, u with\r
- | V _, V _ -> problem_fail p "no eta difference found (div subterm of conv?)"\r
- | A(t1,t2), A(u1,u2) ->\r
- if not (eta_eq t2 u2) then (k-1)\r
- else aux t1 u1 (k-1)\r
- | _, _ -> assert false\r
- in aux p.div t argsno\r
+ (the first argument is 0) *)\r
+let find_eta_difference p t =\r
+ let divargs = args_of_inert p.div in\r
+ let conargs = args_of_inert t in\r
+ let rec aux k divargs conargs =\r
+ match divargs,conargs with\r
+ [],_ -> []\r
+ | _::_,[] -> [k]\r
+ | t1::divargs,t2::conargs ->\r
+ (if not (eta_eq t1 t2) then [k] else []) @ aux (k+1) divargs conargs\r
+ in\r
+ aux 0 divargs conargs\r
;;\r
\r
let compute_max_lambdas_at hd_var j =\r
let rec aux hd = function\r
| A(t1,t2) ->\r
- (if get_inert t1 = (hd, j)\r
+ (if get_inert t1 = (V hd, j)\r
then max ( (*FIXME*)\r
- if is_inert t2 && let hd', j' = get_inert t2 in hd' = hd\r
+ if is_inert t2 && let hd', j' = get_inert t2 in hd' = V hd\r
then let hd', j' = get_inert t2 in j - j'\r
else no_leading_lambdas hd_var j t2)\r
else id) (max (aux hd t1) (aux hd t2))\r
\r
let print_cmd s1 s2 = print_endline (">> " ^ s1 ^ " " ^ s2);;\r
\r
+(* returns Some i if i is the smallest integer s.t. p holds for the i-th\r
+ element of the list in input *)\r
+let smallest_such_that p =\r
+ let rec aux i =\r
+ function\r
+ [] -> None\r
+ | hd::_ when (print_endline (string_of_t hd) ; p hd) -> Some i\r
+ | _::tl -> aux (i+1) tl\r
+ in\r
+ aux 0\r
+;;\r
+\r
(* eat the arguments of the divergent and explode.\r
It does NOT perform any check, may fail if done unsafely *)\r
let eat p =\r
let p =\r
match phase with\r
| `One ->\r
+ let i =\r
+ match smallest_such_that (fun x -> not (is_constant x)) (args_of_inert p.div) with\r
+ Some i -> i\r
+ | None -> assert false (*CSC: backtrack? *) in\r
let n = 1 + max\r
- (compute_max_lambdas_at var (k-1) p.div)\r
- (compute_max_lambdas_at var (k-1) p.conv) in\r
+ (compute_max_lambdas_at var (k-i-1) p.div)\r
+ (compute_max_lambdas_at var (k-i-1) p.conv) in\r
(* apply fresh vars *)\r
let p, t = fold_nat (fun (p, t) _ ->\r
let p, v = freshvar p in\r
p, A(t, V (v + k))\r
- ) (p, V 0) n in\r
+ ) (p, V (k-1-i)) n in\r
let p = {p with phase=`Two} in\r
let t = A(t, delta) in\r
- let t = fold_nat (fun t m -> A(t, V (k-m))) t (k-1) in\r
+ let t = fold_nat (fun t m -> if k-m = i then t else A(t, V (k-m))) t k in\r
let subst = var, mk_lams t k in\r
let p = subst_in_problem subst p in\r
let _, args = get_inert p.div in\r
\r
(* step on the head of div, on the k-th argument, with n fresh vars *)\r
let step k n p =\r
- let var, _ = get_inert p.div in\r
-print_cmd "STEP" ("on " ^ string_of_t (V var) ^ " (of:" ^ string_of_int n ^ ")");\r
+ let hd, _ = get_inert p.div in\r
+ match hd with\r
+ | C | L _ | B | A _ -> assert false\r
+ | V var ->\r
+print_cmd "STEP" ("on " ^ string_of_t (V var) ^ " (on " ^ string_of_int (k+1) ^ "th)");\r
let p, t = (* apply fresh vars *)\r
fold_nat (fun (p, t) _ ->\r
let p, v = freshvar p in\r
sanity p\r
;;\r
\r
-let rec auto p =\r
- let hd_var, n_args = get_inert p.div in\r
- match get_subterm_with_head_and_args hd_var n_args p.conv with\r
- | None ->\r
- (try\r
- let phase = p.phase in\r
+let auto p =\r
+ let rec aux p =\r
+ let hd, n_args = get_inert p.div in\r
+ match hd with\r
+ | C | L _ | B | A _ -> assert false\r
+ | V hd_var ->\r
+ let tms = get_subterms_with_head hd_var p.conv in\r
+ if List.exists (fun t -> snd (get_inert t) >= n_args) tms\r
+ then (\r
+ (* let tms = List.sort (fun t1 t2 -> - compare (snd (get_inert t1)) (snd (get_inert t2))) tms in *)\r
+ List.iter (fun t -> try\r
+ let js = find_eta_difference p t in\r
+ (* print_endline (String.concat ", " (List.map string_of_int js)); *)\r
+ if js = [] then problem_fail p "no eta difference found (div subterm of conv?)";\r
+ let js = List.rev js in\r
+ List.iter\r
+ (fun j ->\r
+ try\r
+ let k = 1 + max\r
+ (compute_max_lambdas_at hd_var j p.div)\r
+ (compute_max_lambdas_at hd_var j p.conv) in\r
+ ignore (aux (step j k p))\r
+ with Fail(_, s) ->\r
+ print_endline ("Backtracking (eta_diff) because: " ^ s)) js;\r
+ raise (Fail(-1, "no eta difference"))\r
+ with Fail(_, s) ->\r
+ print_endline ("Backtracking (get_subterms) because: " ^ s)) tms;\r
+ raise (Fail(-1, "no similar terms"))\r
+ )\r
+ else\r
+ (let phase = p.phase in\r
let p = eat p in\r
if phase = `Two\r
then problem_fail p "Auto.2 did not complete the problem"\r
- else auto p\r
- with Done sigma -> sigma)\r
- | Some t ->\r
- let j = find_eta_difference p t n_args in\r
- let k = 1 + max\r
- (compute_max_lambdas_at hd_var j p.div)\r
- (compute_max_lambdas_at hd_var j p.conv) in\r
- let p = step j k p in\r
- auto p\r
+ else aux p)\r
+ in\r
+ try\r
+ aux p\r
+ with Done sigma -> sigma\r
;;\r
\r
let problem_of (label, div, convs, ps, var_names) =\r
;;\r
\r
let solve p =\r
- if eta_subterm p.div p.conv\r
+ if is_stuck p.div then print_endline "!!! div is stuck. Problem was not run !!!"\r
+ else if eta_subterm p.div p.conv\r
then print_endline "!!! div is subterm of conv. Problem was not run !!!"\r
else check p (auto p)\r
;;\r