let pre_choice_std (shared_vars : int list) (std_ls : t_equal)
: int list * int list * (int * int) list =
(* A help function which will collect std, xor, uncertain and not_visited as
* tas.
* not_visited contains all the variables of shared_vars, that are not already
* put into std, xor or uncertain. So, they four build a partition of
* shared_vars
*)
let rec pre_choice_std_rec (std, xor, uncertain, not_visited as tas) =
function
| (n,t)::tail ->
(* Test if n is in not_visited. In fact it cannot happen that n is not
* in not_visited and it is in std, xor or uncertain. This is due to the
* fact that std_ls must not contain two values for a variable.
* What is acctually tested here is, if n is a shared variable. *)
let (n_is_shared, not_visited_without_n) =
remove_from_list n not_visited
in
if n_is_shared then
match t with
| Var(_) ->
(* A binding x -> y can happen because of variable identification.
* Act as if n is free. *)
pre_choice_std_rec tas tail
| PInv(Var(mm)) ->
(* mm is not neccesarily free *)
(match valeur_elem mm std_ls with
| Var(m) ->
(* m is free in std_ls *)
(* Test if m is a shared variable *)
let (m_is_shared, not_visited_without_nm) =
remove_from_list m not_visited_without_n
in
if m_is_shared then
(* Only if n and m are shared we add them to uncertain.
* It is possible to remove m from not_visited, because, due
* to assumptions, it is not allowed, that there is another
* rule n2 -> PInv(m) in std_ls with n2 in shared_vars. *)
pre_choice_std_rec
(std, xor, (n,m)::uncertain, not_visited_without_nm) tail
else
(* m is not shared *)
(* Test, if it is possible that m and n change the sides. *)
if acceptable_value ([],FreeVar 0,[]) m (PInv(Var(n))) then
(* It is possible that n and m change sides, so we can say
* that n is xor, because m is not shared and therefore
* std. *)
pre_choice_std_rec
(std, n::xor, uncertain, not_visited_without_n) tail
else
(* It is not possible that n and m change sides, because
* of their types. So, n has to be std. *)
pre_choice_std_rec
(n::std, xor, uncertain, not_visited_without_n) tail
| _ ->
(* m is not free in std_ls and cannot be PInv(_), due to
* normalisation, so n has to be standard. *)
pre_choice_std_rec
(n::std, xor, uncertain, not_visited_without_n) tail
)
| _ ->
(* t is a standard term with a top symbol that cannot vanish,
* i.e. n has to be standard *)
pre_choice_std_rec
(n::std, xor, uncertain, not_visited_without_n) tail
else
(* n is not in not_visited, i.e. it is not in shared_vars,
* i.e. ignore it *)
pre_choice_std_rec tas tail
| [] -> tas
in
(* distributes variables with type 0 to xor and the others to std
*)
let rec distribute std xor = function
| n::ns -> if var_type n = 0 then
distribute std (n::xor) ns
else
distribute (n::std) xor ns
| [] -> (std, xor)
in
(* apply pre_choice_std_rec with an initial tas, where not_visited is
* shared_vars. *)
let (std, xor, uncertain, not_visited) =
pre_choice_std_rec ([],[],[],shared_vars) std_ls
in
(* All variables that are not_visited are free in std_ls and do not appear in
* equations like x -> PInv(y) or if they do appear in such equations they
* cannot change the side because of their types.
* We can say that all variables in not_visited that have type 0 belong to
* xor, because this will not change the std solution. *)
let (std, xor) = distribute std xor not_visited
in
(std, xor, uncertain)