let select (selection: selection) : selected =

  (* first assert candidates leading immediately to a closing unifier. *)
  if Selection_assert.has_closing_candidate selection.sel_assert then begin
    match Selection_assert.select selection.sel_assert with
      | Some selected ->
          selected
            
      | None ->
          failwith "Selection.select"
  end
    
  else
  (* then unit asserts *)
          begin
            match select_unit_assert selection selection.sel_unit_asserts with
              | Some selected ->
                  selected
                    
              | None ->
                  
                  (* then standard asserts *)
                  begin
                    match Selection_assert.select selection.sel_assert with
                      | Some selected ->
                          selected
                              
                      | None ->
          
  (* then right splits *)
 begin
    match Selection_split.select_right_split selection.sel_split with
      | Some selected ->
          selected
            
      | None ->

                                  (* then left splits *)
                          
                          (* recompute deferred split candidates, if necessary *)
                          if selection.sel_no_splits_yet then begin
                            selection.sel_no_splits_yet <- false;
                            Problem_literals.compute_deferred
                              selection.sel_problem_literals Context_unifier.Split;
                          end;
                            
                          begin
                            (* still a branch to replay? *)
                            let replay =
                              match selection.sel_guiding_path with
                                | [] ->
                                    None
                                      
                                | head :: tail ->
                                    selection.sel_guiding_path <- tail;
                                    Some head
                            in
                              (* finally try to find a split literal *)
                              match Selection_split.select selection.sel_split replay with
                                | Some selected ->
                                    check_replayed_decision selected replay;
                                    selected
                                      
                                | None ->
                                    (* process kept candidates exceeding the depth limit
                                       to check if the branch is incomplete. *)

                                    if
                                      Config.is_horn selection.sel_config
                                      ||
                                      selection.sel_no_splits_yet
                                    then
                                      Selection_assert.check_exceeding selection.sel_assert
                                    else
                                      Selection_split.check_exceeding selection.sel_split;

                                    raise SATISFIABLE
                          end
                  end  
          end
  end