let check_assert
  (config: config)
  (bound: bound)
  (context: Context.context)
  (subst: subst)
  (context_unifier_space: context_unifier_space)
  (context_partners: context_partners)
  (is_element_incomplete: bool) :
  raw_context_unifier option =
  
  (* is the assert literal parameter free? *)
  let is_assert_valid_at (i : int) : bool =
    let assert_vars =
      Subst.get_bound_vars
        subst
        context_unifier_space.Context_unifier.cus_input_partners.(i).Context_unifier.ip_vars
    in
      List.for_all 
        (fun var ->
           Var.is_universal var.Subst.sv_var
        )
        assert_vars
  in
  
  (* has the unifier an empty remainder
     and leaves the assert literal parameter free?
     returns also the index of the assert literal. *)

  (* precheck in context_unifier_check assures that
     check_close is only called with an empty remainder,
     so check only that assert literal instance is universal. *)

  let rec is_valid_at (i: int) (assert_index: int option) : bool * int option =
    if i >= Array.length context_partners then begin
(*      not (Context_unifier.is_remainder' subst), assert_index*)
(*      true, assert_index*)
      failwith "Context_unifier_check.is_valid_at: no assert literal"
    end

    else begin
      let input_index =
        context_unifier_space.Context_unifier.cus_input_partners.(i).Context_unifier.ip_index
      in
      let context_partner =
        context_partners.(input_index)
      in
        (* no parameter in the assert literal? *)
        if context_partner.Context_unifier.cp_element == Context.assert_element then begin
          (* the is_assert_valid_at check can be really expensive, so we want to avoid it if possible *)
          if
            (* parametric propagation on lemmas *)
            (
              Config.lemma_parametric_assert config > 0
              &&
              context_unifier_space.Context_unifier.cus_lemma_learned >= Config.lemma_parametric_assert config
            )
            ||
            (* if all context literals are universal the instance must be universal *)
            Context.is_universal context
            ||
            (* if all used context literals are universal the instance must be universal *)
            (Tools.array_for_all (fun cp -> cp.Context_unifier.cp_element.Context.el_pars == []) context_partners)
            ||
            (* ok, we have to do the expensive (yes, it is) check *)
            is_assert_valid_at i
          then
            (*is_valid_at (i + 1) (Some i)*)
            trueSome i
          else begin
            false, assert_index
          end
        end

        (* empty remainder? *)
        else begin
            (*
          if
            Context_unifier.is_remainder 
              subst
              context_partner.Context_unifier.cp_element(*.Context.el_pars*)
              input_index
          then begin
            false, assert_index
          end
        
          (* yes, so continue *)
          else*)

            is_valid_at (i + 1) assert_index
        end
    end
  in
(*    if (not (Config.is_horn config)) && Context_unifier.is_remainder' subst then
      None

    else*)

    match is_valid_at 0 None with
      | false, _ ->
          None

      | trueNone ->
          failwith "Context_unifier_check.check_assert"

      | trueSome assert_index ->
          let assert_clause_literal =
            context_unifier_space.Context_unifier.cus_input_partners.(assert_index).Context_unifier.ip_literal
          in
            (* this should be filtered in context_unifier_searach *)
            if
              Const.debug
              &&
              (Config.neg_assert_candidates config = Flags.NAC_Ignore)
              &&
              (not assert_clause_literal.Term.sign)
            then begin
              failwith "Context_unifier_check.check_assert: neg_assert";
            end;

            (* - within bound -> keep
               - exceeding bound and not delayed restarting -> register
               - exceeding bound and delayed restarting -> keep
               - exceeding bound and lookahead -> keep
               - otherwise: drop
            *)

            let complexity =
              bound#get_complexity_subst
                assert_clause_literal
                subst
                Subst.input_literal_offset
            in
            let keep, exceeding =
              (* exceeding bound *)
              if bound#exceeds complexity then begin
                (* exceeding bound, horn, positive, not delayed restarting -> register *)
                if Config.is_horn config && assert_clause_literal.Term.sign then begin
                  match Config.restart config with
                    | Flags.RS_Eager
                    | Flags.RS_Lazy ->
                        ignore (bound#register complexity
                                (Context_unifier.get_creation_choice_point context_partners)
                                : bool);
                    | Flags.RS_Delayed ->
                        ()
                end;
                
                (* this context element is already incomplete,
                   so all its context unifiers will be recomputed anyway if needed. *)

                if is_element_incomplete then
                  falsetrue

                (* keep for Delayed *)
                else if Config.restart config = Flags.RS_Delayed then
                  truetrue

                (* keep for exceeding lookeahead *)
                else if Config.lookahead_exceeding config then
                  truetrue

                (* otherwise drop for the time being *)
                else
                  falsetrue
              end

              (* within bound -> keep *)
              else
                truefalse
            in
              if keep then
                (* this candidate is obeying the bound
                   or needed for the lookahead check *)

                let raw_context_unifier = 
                  Context_unifier.create_context_unifier
                    context_unifier_space
                    (Array.copy context_partners)
                    exceeding
                in
                  Some raw_context_unifier
              else
                None