133 lines
4.8 KiB
Text
133 lines
4.8 KiB
Text
/-
|
||
Copyright (c) 2016 Gabriel Ebner. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Gabriel Ebner
|
||
-/
|
||
import .clause .prover_state .utils
|
||
open tactic monad expr
|
||
|
||
namespace super
|
||
|
||
def position := list ℕ
|
||
|
||
meta def get_rwr_positions : expr → list position
|
||
| (app a b) := [[]] ++
|
||
do arg ← list.zip_with_index (get_app_args (app a b)),
|
||
pos ← get_rwr_positions arg.1,
|
||
[arg.2 :: pos]
|
||
| (var _) := []
|
||
| e := [[]]
|
||
|
||
meta def get_position : expr → position → expr
|
||
| (app a b) (p::ps) :=
|
||
match list.nth (get_app_args (app a b)) p with
|
||
| some arg := get_position arg ps
|
||
| none := (app a b)
|
||
end
|
||
| e _ := e
|
||
|
||
meta def replace_position (v : expr) : expr → position → expr
|
||
| (app a b) (p::ps) :=
|
||
let args := get_app_args (app a b) in
|
||
match args^.nth p with
|
||
| some arg := app_of_list a^.get_app_fn $ args^.update_nth p $ replace_position arg ps
|
||
| none := app a b
|
||
end
|
||
| e [] := v
|
||
| e _ := e
|
||
|
||
variable gt : expr → expr → bool
|
||
variables (c1 c2 : clause)
|
||
variables (ac1 ac2 : derived_clause)
|
||
variables (i1 i2 : nat)
|
||
variable pos : list ℕ
|
||
variable ltr : bool
|
||
variable lt_in_termorder : bool
|
||
variable congr_ax : name
|
||
|
||
lemma {u v w} sup_ltr (F : Sort u) (A : Sort v) (a1 a2) (f : A → Sort w) : (f a1 → F) → f a2 → a1 = a2 → F :=
|
||
take hnfa1 hfa2 heq, hnfa1 (@eq.rec A a2 f hfa2 a1 heq^.symm)
|
||
lemma {u v w} sup_rtl (F : Sort u) (A : Sort v) (a1 a2) (f : A → Sort w) : (f a1 → F) → f a2 → a2 = a1 → F :=
|
||
take hnfa1 hfa2 heq, hnfa1 (@eq.rec A a2 f hfa2 a1 heq)
|
||
|
||
meta def is_eq_dir (e : expr) (ltr : bool) : option (expr × expr) :=
|
||
match is_eq e with
|
||
| some (lhs, rhs) := if ltr then some (lhs, rhs) else some (rhs, lhs)
|
||
| none := none
|
||
end
|
||
|
||
meta def try_sup : tactic clause := do
|
||
guard $ (c1^.get_lit i1)^.is_pos,
|
||
qf1 ← c1^.open_metan c1^.num_quants,
|
||
qf2 ← c2^.open_metan c2^.num_quants,
|
||
(rwr_from, rwr_to) ← (is_eq_dir (qf1.1^.get_lit i1)^.formula ltr)^.to_monad,
|
||
atom ← return (qf2.1^.get_lit i2)^.formula,
|
||
eq_type ← infer_type rwr_from,
|
||
atom_at_pos ← return $ get_position atom pos,
|
||
atom_at_pos_type ← infer_type atom_at_pos,
|
||
unify eq_type atom_at_pos_type,
|
||
unify rwr_from atom_at_pos transparency.none,
|
||
rwr_from' ← instantiate_mvars atom_at_pos,
|
||
rwr_to' ← instantiate_mvars rwr_to,
|
||
if lt_in_termorder
|
||
then guard (gt rwr_from' rwr_to')
|
||
else guard (¬gt rwr_to' rwr_from'),
|
||
rwr_ctx_varn ← mk_fresh_name,
|
||
abs_rwr_ctx ← return $
|
||
lam rwr_ctx_varn binder_info.default eq_type
|
||
(if (qf2.1^.get_lit i2)^.is_neg
|
||
then replace_position (mk_var 0) atom pos
|
||
else imp (replace_position (mk_var 0) atom pos) c2^.local_false),
|
||
lf_univ ← infer_univ c1^.local_false,
|
||
univ ← infer_univ eq_type,
|
||
atom_univ ← infer_univ atom,
|
||
op1 ← qf1.1^.open_constn i1,
|
||
op2 ← qf2.1^.open_constn c2^.num_lits,
|
||
hi2 ← (op2.2^.nth i2)^.to_monad,
|
||
new_atom ← whnf_no_delta $ app abs_rwr_ctx rwr_to',
|
||
new_hi2 ← return $ local_const hi2^.local_uniq_name `H binder_info.default new_atom,
|
||
new_fin_prf ←
|
||
return $ app_of_list (const congr_ax [lf_univ, univ, atom_univ]) [c1^.local_false, eq_type, rwr_from, rwr_to,
|
||
abs_rwr_ctx, (op2.1^.close_const hi2)^.proof, new_hi2],
|
||
clause.meta_closure (qf1.2 ++ qf2.2) $ (op1.1^.inst new_fin_prf)^.close_constn (op1.2 ++ op2.2^.update_nth i2 new_hi2)
|
||
|
||
meta def rwr_positions (c : clause) (i : nat) : list (list ℕ) :=
|
||
get_rwr_positions (c^.get_lit i)^.formula
|
||
|
||
meta def try_add_sup : prover unit :=
|
||
(do c' ← try_sup gt ac1^.c ac2^.c i1 i2 pos ltr ff congr_ax,
|
||
inf_score 2 [ac1^.sc, ac2^.sc] >>= mk_derived c' >>= add_inferred)
|
||
<|> return ()
|
||
|
||
meta def superposition_back_inf : inference :=
|
||
take given, do active ← get_active, sequence' $ do
|
||
given_i ← given^.selected,
|
||
guard (given^.c^.get_lit given_i)^.is_pos,
|
||
option.to_monad $ is_eq (given^.c^.get_lit given_i)^.formula,
|
||
other ← rb_map.values active,
|
||
guard $ ¬given^.sc^.in_sos ∨ ¬other^.sc^.in_sos,
|
||
other_i ← other^.selected,
|
||
pos ← rwr_positions other^.c other_i,
|
||
-- FIXME(gabriel): ``sup_ltr fails to resolve at runtime
|
||
[do try_add_sup gt given other given_i other_i pos tt ``super.sup_ltr,
|
||
try_add_sup gt given other given_i other_i pos ff ``super.sup_rtl]
|
||
|
||
meta def superposition_fwd_inf : inference :=
|
||
take given, do active ← get_active, sequence' $ do
|
||
given_i ← given^.selected,
|
||
other ← rb_map.values active,
|
||
guard $ ¬given^.sc^.in_sos ∨ ¬other^.sc^.in_sos,
|
||
other_i ← other^.selected,
|
||
guard (other^.c^.get_lit other_i)^.is_pos,
|
||
option.to_monad $ is_eq (other^.c^.get_lit other_i)^.formula,
|
||
pos ← rwr_positions given^.c given_i,
|
||
[do try_add_sup gt other given other_i given_i pos tt ``super.sup_ltr,
|
||
try_add_sup gt other given other_i given_i pos ff ``super.sup_rtl]
|
||
|
||
@[super.inf]
|
||
meta def superposition_inf : inf_decl := inf_decl.mk 40 $
|
||
take given, do gt ← get_term_order,
|
||
superposition_fwd_inf gt given,
|
||
superposition_back_inf gt given
|
||
|
||
end super
|