let pre_choice_xor std_xor_uncertain (xor_eqns : term list list)
  : int list * int list * (int * int) list =

  let rec  pre_choice_xor_rec (std, xor, uncertain as sxu) = function
    | ls::lss ->
        (match get_onlyvar std ls with
        | Some n ->
            (* n is the only variable in ls, so n has to be xor *)
            (try
              let (m, uncertain_without_nm) = lookup_bidir_remove n uncertain in
              (* n has to be xor, so m has to be std *)
              (* Add n to xor and m to std.
               * Start from the beginning (xor_eqns), because adding m to std
               * can effect equations that were already visited.
               *
               * TODO: check if it is better to run through all eqns first and
               * check at the end if there were any changes and if yes then run
               * again over all eqns, or if this is not necessary and proceed
               * with lss, although we could possibly eliminate more choices, if
               * we start from beginning again. *)

              pre_choice_xor_rec (m::std, n::xor, uncertain_without_nm) xor_eqns
            with
              Not_found ->
                (* n is not in uncertain *)
                if List.mem n std then
                  (* n is in std, but it has to be in xor as well *)
                  raise No_Solution
                else
                  (* n is not in uncertain and not in std, so n is already in
                   * xor or n is not a shared variable. *)

                  pre_choice_xor_rec sxu lss
            )
        | None ->
            (* There are more than one variable in ls or ls is [], so we cannot
             * easily derive information from this *)

            pre_choice_xor_rec sxu lss
        )
    | [] -> sxu
  in
  pre_choice_xor_rec std_xor_uncertain xor_eqns