/- 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 open tactic monad namespace super private meta def try_subsume_core : list clause.literal → list clause.literal → tactic unit | [] _ := skip | small large := first $ do i ← small^.zip_with_index, j ← large^.zip_with_index, return $ do unify_lit i.1 j.1, try_subsume_core (small^.remove_nth i.2) (large^.remove_nth j.2) -- FIXME: this is incorrect if a quantifier is unused meta def try_subsume (small large : clause) : tactic unit := do small_open ← clause.open_metan small (clause.num_quants small), large_open ← clause.open_constn large (clause.num_quants large), guard $ small^.num_lits ≤ large^.num_lits, try_subsume_core small_open.1^.get_lits large_open.1^.get_lits meta def does_subsume (small large : clause) : tactic bool := (try_subsume small large >> return tt) <|> return ff meta def does_subsume_with_assertions (small large : derived_clause) : prover bool := do if small^.assertions^.subset_of large^.assertions then do does_subsume small^.c large^.c else return ff meta def any_tt {m : Type → Type} [monad m] (active : rb_map clause_id derived_clause) (pred : derived_clause → m bool) : m bool := active^.fold (return ff) $ λk a cont, do v ← pred a, if v then return tt else cont meta def any_tt_list {m : Type → Type} [monad m] {A} (pred : A → m bool) : list A → m bool | [] := return ff | (x::xs) := do v ← pred x, if v then return tt else any_tt_list xs @[super.inf] meta def forward_subsumption : inf_decl := inf_decl.mk 20 $ take given, do active ← get_active, sequence' $ do a ← active^.values, guard $ a^.id ≠ given^.id, return $ do ss ← does_subsume a^.c given^.c, if ss then remove_redundant given^.id [a] else return () meta def forward_subsumption_pre : prover unit := preprocessing_rule $ λnew, do active ← get_active, filter (λn, do do ss ← any_tt active (λa, if a^.assertions^.subset_of n^.assertions then do does_subsume a^.c n^.c else -- TODO: move to locked return ff), return (bnot ss)) new meta def subsumption_interreduction : list derived_clause → prover (list derived_clause) | (c::cs) := do -- TODO: move to locked cs_that_subsume_c ← filter (λd, does_subsume_with_assertions d c) cs, if ¬cs_that_subsume_c^.empty then -- TODO: update score subsumption_interreduction cs else do cs_not_subsumed_by_c ← filter (λd, lift bnot (does_subsume_with_assertions c d)) cs, cs' ← subsumption_interreduction cs_not_subsumed_by_c, return (c::cs') | [] := return [] meta def subsumption_interreduction_pre : prover unit := preprocessing_rule $ λnew, let new' := list.sort_on (λc : derived_clause, c^.c^.num_lits) new in subsumption_interreduction new' meta def keys_where_tt {m} {K V : Type} [monad m] (active : rb_map K V) (pred : V → m bool) : m (list K) := @rb_map.fold _ _ (m (list K)) active (return []) $ λk a cont, do v ← pred a, rest ← cont, return $ if v then k::rest else rest @[super.inf] meta def backward_subsumption : inf_decl := inf_decl.mk 20 $ λgiven, do active ← get_active, ss ← keys_where_tt active (λa, does_subsume given^.c a^.c), sequence' $ do id ← ss, guard (id ≠ given^.id), [remove_redundant id [given]] end super