let identify_variables unif_std tas (std_subs : t_subst list)
  (var_identif : t_partition) (vi_ctrs : t_vi_ctrs)
  : (t_subst list * t_partition * (int * int) list) list =

  (* adds the constraint, that n must not be equal to m to the vi constraints.
   *)

  let add_vi_ctr ((equations, vis) : t_vi_ctrs) (n : int) (m : int) =
    ((n,m)::equations, vis)
  in

  let rec help n tas (vi_ctrs : t_vi_ctrs) = function
    | (m::_)::tail ->
        (* identify n and m, if it is allowed by vi_ctrs *)
        (* test, if n equal m is allowed by the negative ctrs *)
        (if is_allowed var_identif n m vi_ctrs then
          (* combine the classes of n and m *)
          let var_identif = combine_classes var_identif m n
          in
          (* test, if var_identif is allowed by the layer ctrs *)
          (if is_allowed_vi var_identif vi_ctrs then
            (* all requirements are fulfilled, var_identif is a variable
             * identification, that is not forbidden by vi_ctrs *)

            let std_subs2 = unif_std false (Var(m)) (Var(n)) std_subs
            in
            (if std_subs2 = [] then
              (* identifing m and n failed in the std theory *)
              help n tas (add_vi_ctr vi_ctrs n m) tail
            else
              let std_subs2_vi = (std_subs2, var_identif, fst vi_ctrs)
              in
              (* Add n <> m to the identification constraints,
               * because we do not want to test the same var identifications
               * twice. *)

              help n (std_subs2_vi::tas) (add_vi_ctr vi_ctrs n m) tail
            )
          else
            (* n must not be equal to m, proceed with tail *)
            help n tas vi_ctrs tail
          )
        else
          (* n must not be equal to m, proceed with tail *)
          help n tas vi_ctrs tail
        )
    | [] -> (tas, vi_ctrs)
    | _  -> failwith ("identify_variables: var_identif is not a valid "^
                      "partition, it contains an empty class")
  in

  let rec help2 tas vi_ctrs = function
    | (n::_)::tail ->
        let (tas,vi_ctrs2) = help n tas vi_ctrs tail in
        help2 tas vi_ctrs2 tail
    | [] -> tas
    | _  -> failwith ("identify_variables: var_identif is not a valid "^
                      "partition, it contains an empty class")
  in

  help2 tas vi_ctrs var_identif