let solve_triangular a b ro vars atms po =
let rec help po subst row =
let no_ones_found = ref true in
for col = row to (Array.length vars)-1 do
(* if we found a one we test if it
* is possible to choose this variable according
* to the partial order *)
if lookup ro a row col = 1 then
begin
(if is_possible po (get_row ro b row) atms vars.(col) then
begin
(* extend substitution *)
let ll = array_to_list (fun i -> Var vars.(i))
(get_row ro a row) [] col
in
(* add the variables in atms to ll *)
let ll = array_to_list (fun i -> Var atms.(i))
(get_row ro b row) ll (-1)
in
(* do a small normalisation *)
let term = match ll with
| [] -> Atm(0)
| [x] -> x
| _ -> Xor ll
in
let subst = (vars.(col), term)::subst
in
(* try to solve system with the next row *)
if row = 0 then
(* we found a solution and can stop iterating *)
raise (Substitution_found subst)
else
(* try to solve system with the next row *)
(* update the partial order *)
let po = it_list
(fun po t ->
match t with
| Var(m) -> add_to_po po m vars.(col)
| _ -> failwith "solve_triangular: only Var(_) allowed"
) po ll
in
(* apply substitution to the other equations *)
for row2 = 0 to row-1 do
if lookup ro a row2 col = 1 then
add_lines ro a b row2 row
done;
help po subst (row-1)
end
else
()
);
no_ones_found := false
end
else
()
done;
(* if there are no variables in this row we can find a solution
* iff there are also no constants in this row, i.e. if it is
* a 0 = 0 equation *)
if !no_ones_found then
begin
for i = 0 to (Array.length atms)-1 do
if lookup ro b row i = 1 then
raise No_Solution
done;
if row = 0 then
raise (Substitution_found subst)
else
help po subst (row-1)
end
in
try
help po [] ((Array.length a)-1);
raise No_Solution
with
Substitution_found subst -> subst