Files
mercury/compiler/mode_robdd.tfeirn.m
Zoltan Somogyi 0d7c8a7654 Specify pred or func for all pragmas.
*/*.m:
    As above.

configure.ac:
    Require the installed compiler to support this capability.
2021-06-16 15:23:58 +10:00

785 lines
24 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2001-2006, 2011 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: mode_robdd.tfeirn.m.
% Main author: dmo
% Stability: low
%
%-----------------------------------------------------------------------------%
:- module mode_robdd.tfeirn.
:- interface.
:- import_module check_hlds.
:- import_module check_hlds.mode_constraint_robdd.
:- import_module bool.
:- import_module robdd.
:- import_module term.
%-----------------------------------------------------------------------------%
:- type tfeirn(T).
:- type tfeirn == tfeirn(generic).
:- inst tfeirn == ground. % XXX
:- inst norm_tfeirn for tfeirn/1
---> mode_robdd(ground, ground, ground, ground, ground, bound(yes)).
:- mode di_tfeirn == in. % XXX
:- mode uo_tfeirn == out. % XXX
:- mode ni_tfeirn == in(norm_tfeirn).
:- mode no_tfeirn == out(norm_tfeirn).
% Constants.
:- func one = (tfeirn(T)::no_tfeirn) is det.
:- pragma type_spec(func(one/0), T = mc_type).
:- func zero = (tfeirn(T)::no_tfeirn) is det.
:- pragma type_spec(func(zero/0), T = mc_type).
% Conjunction.
:- func tfeirn(T) * tfeirn(T) = tfeirn(T).
:- pragma type_spec(func(('*')/2), T = mc_type).
% Disjunction.
:- func tfeirn(T) + tfeirn(T) = tfeirn(T).
:- pragma type_spec(func(('+')/2), T = mc_type).
%-----------------------------------------------------------------------------%
:- func var(var(T)::in, tfeirn(T)::in(tfeirn)) = (tfeirn(T)::out(tfeirn))
is det.
:- pragma type_spec(func(var/2), T = mc_type).
:- func not_var(var(T)::in, tfeirn(T)::in(tfeirn)) = (tfeirn(T)::out(tfeirn))
is det.
:- pragma type_spec(func(not_var/2), T = mc_type).
:- func eq_vars(var(T)::in, var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(eq_vars/3), T = mc_type).
:- func neq_vars(var(T)::in, var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(neq_vars/3), T = mc_type).
:- func imp_vars(var(T)::in, var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(imp_vars/3), T = mc_type).
:- func conj_vars(vars(T)::in, tfeirn(T)::di_tfeirn) = (tfeirn(T)::uo_tfeirn)
is det.
:- pragma type_spec(func(conj_vars/2), T = mc_type).
:- func conj_not_vars(vars(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(conj_not_vars/2), T = mc_type).
:- func disj_vars(vars(T)::in, tfeirn(T)::di_tfeirn) = (tfeirn(T)::uo_tfeirn)
is det.
:- pragma type_spec(func(disj_vars/2), T = mc_type).
:- func at_most_one_of(vars(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(at_most_one_of/2), T = mc_type).
:- func not_both(var(T)::in, var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(not_both/3), T = mc_type).
:- func io_constraint(var(T)::in, var(T)::in, var(T)::in, tfeirn(T)::di_tfeirn)
= (tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(io_constraint/4), T = mc_type).
% disj_vars_eq(Vars, Var) <=> (disj_vars(Vars) =:= Var).
:- func disj_vars_eq(vars(T)::in, var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(disj_vars_eq/3), T = mc_type).
:- func var_restrict_true(var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(var_restrict_true/2), T = mc_type).
:- func var_restrict_false(var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(var_restrict_false/2), T = mc_type).
%-----------------------------------------------------------------------------%
% Succeed iff the var is entailed by the xROBDD.
:- pred var_entailed(tfeirn(T)::ni_tfeirn, var(T)::in) is semidet.
:- pragma type_spec(pred(var_entailed/2), T = mc_type).
% Return the set of vars entailed by the xROBDD.
:- func vars_entailed(tfeirn(T)::ni_tfeirn) =
(vars_entailed_result(T)::out) is det.
:- pragma type_spec(func(vars_entailed/1), T = mc_type).
% Return the set of vars disentailed by the xROBDD.
:- func vars_disentailed(tfeirn(T)::ni_tfeirn) =
(vars_entailed_result(T)::out) is det.
:- pragma type_spec(func(vars_disentailed/1), T = mc_type).
:- pred known_vars(tfeirn(T)::ni_tfeirn, vars(T)::out, vars(T)::out) is det.
:- pragma type_spec(pred(known_vars/3), T = mc_type).
% Existentially quantify away the var in the xROBDD.
:- func restrict(var(T)::in, tfeirn(T)::ni_tfeirn) =
(tfeirn(T)::no_tfeirn) is det.
:- pragma type_spec(func(restrict/2), T = mc_type).
% Existentially quantify away all vars greater than the specified var.
:- func restrict_threshold(var(T)::in, tfeirn(T)::ni_tfeirn) =
(tfeirn(T)::no_tfeirn) is det.
:- pragma type_spec(func(restrict_threshold/2), T = mc_type).
:- func restrict_filter(pred(var(T))::(pred(in) is semidet),
tfeirn(T)::ni_tfeirn) = (tfeirn(T)::no_tfeirn) is det.
:- pragma type_spec(func(restrict_filter/2), T = mc_type).
%-----------------------------------------------------------------------------%
% labelling(Vars, xROBDD, TrueVars, FalseVars)
% Takes a set of Vars and an xROBDD and returns a value assignment
% for those Vars that is a model of the Boolean function
% represented by the xROBDD.
% The value assignment is returned in the two sets TrueVars (set
% of variables assigned the value 1) and FalseVars (set of
% variables assigned the value 0).
%
% XXX should try using sparse_bitset here.
:- pred labelling(vars(T)::in, tfeirn(T)::in, vars(T)::out, vars(T)::out)
is nondet.
% minimal_model(Vars, xROBDD, TrueVars, FalseVars)
% Takes a set of Vars and an xROBDD and returns a value assignment
% for those Vars that is a minimal model of the Boolean function
% represented by the xROBDD.
% The value assignment is returned in the two sets TrueVars (set
% of variables assigned the value 1) and FalseVars (set of
% variables assigned the value 0).
%
% XXX should try using sparse_bitset here.
:- pred minimal_model(vars(T)::in, tfeirn(T)::in, vars(T)::out, vars(T)::out)
is nondet.
%-----------------------------------------------------------------------------%
:- func ensure_normalised(tfeirn(T)::di_tfeirn) = (tfeirn(T)::no_tfeirn)
is det.
:- pragma type_spec(func(ensure_normalised/1), T = mc_type).
%-----------------------------------------------------------------------------%
% XXX
% Extract the ROBDD component of the tfeirn.
:- func robdd(tfeirn(T)) = robdd(T).
% Convert the tfeirn to an ROBDD.
:- func to_robdd(tfeirn(T)) = robdd(T).
%-----------------------------------------------------------------------------%
:- func robdd_to_mode_robdd(robdd(T)) = tfeirn(T).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module mode_robdd.equiv_vars.
:- import_module mode_robdd.implications.
:- import_module int.
:- import_module list.
:- import_module map.
:- import_module sparse_bitset.
% T - true vars, F - False Vars, E - equivalent vars, N -
% non-equivalent vars, I - implications, R - ROBDD.
%
% Combinations to try:
% R (straight ROBDD)
% TFR
% TER (Peter Schachte's extension)
% tfeirn
% TFENIR
:- interface.
% This should be abstract, but needs to be exported for insts.
%
:- type tfeirn(T)
---> mode_robdd(
true_vars :: vars(T),
false_vars :: vars(T),
equiv_vars :: equiv_vars(T),
imp_vars :: imp_vars(T),
robdd :: robdd(T),
normalised :: bool
).
:- implementation.
%-----------------------------------------------------------------------------%
one = mode_robdd(init, init, init_equiv_vars, init_imp_vars, one, yes).
zero = mode_robdd(init, init, init_equiv_vars, init_imp_vars, zero, yes).
mode_robdd(TA, FA, EA, IA, RA, _) * mode_robdd(TB, FB, EB, IB, RB, _) =
mode_robdd(TA1 `union` TB1, FA1 `union` FB1,
EA1 * EB1, IA1 * IB1, RA1 * RB1, no) :-
TU = TA `union` TB,
FU = FA `union` FB,
EU = EA * EB,
IU = IA * IB,
mode_robdd(TA1, FA1, EA1, IA1, RA1, _) =
normalise(mode_robdd(TU, FU, EU, IU, RA, no)),
mode_robdd(TB1, FB1, EB1, IB1, RB1, _) =
normalise(mode_robdd(TU, FU, EU, IU, RB, no)).
mode_robdd(TA0, FA0, EA0, IA0, RA0, NA0)
+ mode_robdd(TB0, FB0, EB0, IB0, RB0, NB0) = X :-
( RA0 = zero ->
X = mode_robdd(TB0, FB0, EB0, IB0, RB0, NB0)
; RB0 = zero ->
X = mode_robdd(TA0, FA0, EA0, IA0, RA0, NA0)
;
X = mode_robdd(T, F, E, I, R, no),
T = TA0 `intersect` TB0,
F = FA0 `intersect` FB0,
E = EA + EB,
I = IA + IB,
R = RA + RB,
TAB = TA0 `difference` TB0,
FAB = FA0 `difference` FB0,
EA = EA0 ^ add_equalities(TAB) ^ add_equalities(FAB),
TBA = TB0 `difference` TA0,
FBA = FB0 `difference` FA0,
EB = EB0 ^ add_equalities(TBA) ^ add_equalities(FBA),
EAB = EA `difference` EB,
IA = IA0 ^ add_equalities_to_imp_vars(EAB),
EBA = EB `difference` EA,
IB = IB0 ^ add_equalities_to_imp_vars(EBA),
RA1 = foldl(
func(V, R0) = R0 * var(E ^ det_leader(V)), TAB, RA0),
RA2 = foldl(
func(V, R0) = R0 *
not_var(E ^ det_leader(V)), FAB, RA1),
EA1 = (EA `difference` EB) + EA0,
RA3 = add_equivalences(EA1, RA2),
IA1 = (IA `difference` IB) + IA0,
RA = add_implications(IA1, RA3),
RB1 = foldl(
func(V, R0) = R0 * var(E ^ det_leader(V)), TBA, RB0),
RB2 = foldl(
func(V, R0) = R0 *
not_var(E ^ det_leader(V)), FBA, RB1),
EB1 = (EB `difference` EA) + EB0,
RB3 = add_equivalences(EB1, RB2),
IB1 = (IB `difference` IA) + IB0,
RB = add_implications(IB1, RB3)
).
var_entailed(X, V) :-
(X ^ robdd = zero ; X ^ true_vars `contains` V).
vars_entailed(X) =
(X ^ robdd = zero ->
all_vars
;
some_vars(X ^ true_vars)
).
vars_disentailed(X) =
(X ^ robdd = zero ->
all_vars
;
some_vars(X ^ false_vars)
).
known_vars(X, TrueVars, FalseVars) :-
( X ^ robdd = zero ->
TrueVars = init,
FalseVars = init
;
TrueVars = X ^ true_vars,
FalseVars = X ^ false_vars
).
restrict(V, mode_robdd(T, F, E, I, R, N)) =
( T `contains` V ->
mode_robdd(T `delete` V, F, E, I, R, N)
; F `contains` V ->
mode_robdd(T, F `delete` V, E, I, R, N)
; L = E ^ leader(V) ->
( L \= V ->
mode_robdd(T, F, E `delete` V, I, R, N)
;
mode_robdd(T, F, E `delete` V, I `delete` V,
restrict(V, R), N)
)
;
mode_robdd(T, F, E, I `delete` V, restrict(V, R), N)
).
restrict_threshold(V, mode_robdd(T, F, E, I, R, N)) =
mode_robdd(remove_gt(T, V), remove_gt(F, V), restrict_threshold(V, E),
restrict_threshold(V, I), restrict_threshold(V, R), N).
var(V, X) =
( T `contains` V ->
X
; F `contains` V ->
zero
;
mode_robdd(T `insert` V, F, E, I, R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
not_var(V, X) =
( F `contains` V ->
X
; T `contains` V ->
zero
;
mode_robdd(T, F `insert` V, E, I, R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
eq_vars(VarA, VarB, X) =
(
( T `contains` VarA, T `contains` VarB
; F `contains` VarA, F `contains` VarB
)
->
X
;
( T `contains` VarA, F `contains` VarB
; F `contains` VarA, T `contains` VarB
)
->
zero
;
mode_robdd(T, F, add_equality(VarA, VarB, E), I, R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
neq_vars(VarA, VarB, X) =
(
( T `contains` VarA, T `contains` VarB
; F `contains` VarA, F `contains` VarB
)
->
zero
;
( T `contains` VarA, F `contains` VarB
; F `contains` VarA, T `contains` VarB
)
->
X
;
mode_robdd(T, F, E, I ^ neq_vars(VarA, VarB), R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
imp_vars(VarA, VarB, X) =
( T `contains` VarA, F `contains` VarB ->
zero
; T `contains` VarB ->
X
; F `contains` VarA ->
X
;
mode_robdd(T, F, E, I ^ imp_vars(VarA, VarB), R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
conj_vars(Vars, X) =
( Vars `subset` T ->
X
; is_non_empty(Vars `intersect` F) ->
zero
;
mode_robdd(T `union` Vars, F, E, I, R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
conj_not_vars(Vars, X) =
( Vars `subset` F ->
X
; is_non_empty(Vars `intersect` T) ->
zero
;
mode_robdd(T, F `union` Vars, E, I, R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
disj_vars(Vars, X0) = X :-
X0 = mode_robdd(T, F, E, I, R, _N),
( is_non_empty(Vars `intersect` T) ->
X = X0
; Vars `subset` F ->
X = zero
;
VarsNF = Vars `difference` F,
( remove_least(Var1, VarsNF, VarsNF1) ->
( remove_least(Var2, VarsNF1, VarsNF2) ->
( is_empty(VarsNF2) ->
X = mode_robdd(T, F, E,
I ^ either(Var1, Var2),
R, no)
;
X = X0 `x` disj_vars(VarsNF)
)
;
X = X0 ^ var(Var1)
)
;
X = zero
)
).
at_most_one_of(Vars, X) =
( count(Vars `difference` F) =< 1 ->
X
; count(Vars `intersect` T) > 1 ->
zero
;
mode_robdd(T, F, E, I ^ at_most_one_of(Vars), R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
not_both(VarA, VarB, X) =
( F `contains` VarA ->
X
; F `contains` VarB ->
X
; T `contains` VarA ->
not_var(VarB, X)
; T `contains` VarB ->
not_var(VarA, X)
;
mode_robdd(T, F, E, I ^ not_both(VarA, VarB), R, no)
) :-
X = mode_robdd(T, F, E, I, R, _).
io_constraint(V_in, V_out, V_, X) =
X ^ not_both(V_in, V_) ^ disj_vars_eq(Vars, V_out) :-
Vars = list_to_set([V_in, V_]).
disj_vars_eq(Vars, Var, X) =
( F `contains` Var ->
( Vars `subset` F ->
X
;
X ^ conj_not_vars(Vars)
)
; T `contains` Var ->
( Vars `subset` F ->
zero
;
X ^ disj_vars(Vars)
)
; is_non_empty(Vars `intersect` T) ->
X ^ var(Var)
; Vars `subset` F ->
X ^ not_var(Var)
; remove_least(Var1, Vars, Vars1) ->
( is_empty(Vars1) ->
X ^ eq_vars(Var, Var1)
;
(X ^ imp_vars_set(Vars, Var)) `x`
(var(Var) =< disj_vars(Vars))
)
;
X ^ not_var(Var)
) :-
X = mode_robdd(T, F, _E, _I, _R, _N).
% imp_vars_set({V1, ..., Vn}, V) <===> (V1 =< V) * ... * (Vn % =< V)
:- func imp_vars_set(vars(T)::in, var(T)::in, tfeirn(T)::di_tfeirn) =
(tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(imp_vars_set/3), T = mc_type).
imp_vars_set(Vars, Var, mode_robdd(T, F, E, I0, R, _)) =
mode_robdd(T, F, E, I, R, no) :-
I = I0 ^ foldl(func(VarA, I1) = I1 ^ imp_vars(VarA, Var), Vars).
var_restrict_true(V, mode_robdd(T, F, E, I, R, N)) = X :-
( F `contains` V ->
X = zero
; T `contains` V ->
X = mode_robdd(T `delete` V, F, E, I, R, N)
;
X0 = normalise(mode_robdd(T `insert` V, F, E, I, R, no)),
X = X0 ^ true_vars := X0 ^ true_vars `delete` V
).
var_restrict_false(V, mode_robdd(T, F, E, I, R, N)) = X :-
( T `contains` V ->
X = zero
; F `contains` V ->
X = mode_robdd(T, F `delete` V, E, I, R, N)
;
X0 = normalise(mode_robdd(T, F `insert` V, E, I, R, no)),
X = X0 ^ false_vars := X0 ^ false_vars `delete` V
).
restrict_filter(P, mode_robdd(T, F, E, I, R, N)) =
mode_robdd(filter(P, T), filter(P, F), filter(P, E), filter(P, I),
restrict_filter(P, R), N).
labelling(Vars0, mode_robdd(T, F, E, I, R, N), TrueVars, FalseVars) :-
TrueVars0 = T `intersect` Vars0,
FalseVars0 = F `intersect` Vars0,
Vars = Vars0 `difference` TrueVars0 `difference` FalseVars0,
( is_empty(Vars) ->
TrueVars = TrueVars0,
FalseVars = FalseVars0
;
labelling_2(Vars, mode_robdd(init, init, E, I, R, N),
TrueVars1, FalseVars1),
TrueVars = TrueVars0 `union` TrueVars1,
FalseVars = FalseVars0 `union` FalseVars1
).
:- pred labelling_2(vars(T)::in, tfeirn(T)::in, vars(T)::out, vars(T)::out)
is nondet.
labelling_2(Vars0, X0, TrueVars, FalseVars) :-
( remove_least(V, Vars0, Vars) ->
(
X = var_restrict_false(V, X0),
X ^ robdd \= zero,
labelling_2(Vars, X, TrueVars, FalseVars0),
FalseVars = FalseVars0 `insert` V
;
X = var_restrict_true(V, X0),
X ^ robdd \= zero,
labelling_2(Vars, X, TrueVars0, FalseVars),
TrueVars = TrueVars0 `insert` V
)
;
TrueVars = init,
FalseVars = init
).
minimal_model(Vars, X0, TrueVars, FalseVars) :-
( is_empty(Vars) ->
TrueVars = init,
FalseVars = init
;
minimal_model_2(Vars, X0, TrueVars0, FalseVars0),
(
TrueVars = TrueVars0,
FalseVars = FalseVars0
;
X = X0 `x` (~conj_vars(TrueVars0)),
minimal_model(Vars, X, TrueVars, FalseVars)
)
).
:- pred minimal_model_2(vars(T)::in, tfeirn(T)::in, vars(T)::out, vars(T)::out)
is semidet.
minimal_model_2(Vars0, X0, TrueVars, FalseVars) :-
( remove_least(V, Vars0, Vars) ->
X1 = var_restrict_false(V, X0),
( X1 ^ robdd \= zero ->
minimal_model_2(Vars, X1, TrueVars, FalseVars0),
FalseVars = FalseVars0 `insert` V
;
X2 = var_restrict_true(V, X0),
X2 ^ robdd \= zero,
minimal_model_2(Vars, X2, TrueVars0, FalseVars),
TrueVars = TrueVars0 `insert` V
)
;
TrueVars = init,
FalseVars = init
).
%-----------------------------------------------------------------------------%
ensure_normalised(X) = normalise(X).
:- func normalise(tfeirn(T)::di_tfeirn) = (tfeirn(T)::no_tfeirn) is det.
:- pragma type_spec(func(normalise/1), T = mc_type).
normalise(X0) = X :-
X0 = mode_robdd(T, F, E, I, R, yes),
X = mode_robdd(T, F, E, I, R, yes).
normalise(mode_robdd(TrueVars0, FalseVars0, EQVars0, ImpVars0, Robdd0, no))
= X :-
% T <-> F
( is_non_empty(TrueVars0 `intersect` FalseVars0) ->
X = zero
;
% TF <-> E
normalise_true_false_equivalent_vars(Changed0,
TrueVars0, TrueVars1, FalseVars0, FalseVars1,
EQVars0, EQVars1),
% TF <-> I
normalise_true_false_implication_vars(Changed1,
TrueVars1, TrueVars2, FalseVars1, FalseVars2,
ImpVars0, ImpVars1),
Changed2 = Changed0 `bool__or` Changed1,
% TF -> R
Robdd1 = restrict_true_false_vars(TrueVars2, FalseVars2,
Robdd0),
Changed3 = Changed2 `bool__or` ( Robdd1 \= Robdd0 -> yes ; no),
(
% TF <- R
definite_vars(Robdd1,
some_vars(NewTrueVars), some_vars(NewFalseVars))
->
(
is_empty(NewTrueVars),
is_empty(NewFalseVars)
->
Changed4 = Changed3,
TrueVars = TrueVars2,
FalseVars = FalseVars2
;
Changed4 = yes,
TrueVars = TrueVars2 `union` NewTrueVars,
FalseVars = FalseVars2 `union` NewFalseVars
),
% E <-> I
(
propagate_equivalences_into_implications(
EQVars1, Changed5, ImpVars1, ImpVars2)
->
propagate_implications_into_equivalences(
Changed6, EQVars1, EQVars2,
ImpVars2, ImpVars3),
Changed7 = Changed4 `bool__or` Changed5
`bool__or` Changed6,
% E <-> R
extract_equivalent_vars_from_robdd(Changed8,
Robdd1, Robdd2, EQVars2, EQVars),
Changed9 = Changed7 `bool__or` Changed8,
% I <-> R
extract_implication_vars_from_robdd(Changed10,
Robdd2, Robdd, ImpVars3, ImpVars),
Changed = Changed9 `bool__or` Changed10,
(
Changed = yes,
X0 = mode_robdd(TrueVars, FalseVars,
EQVars, ImpVars, Robdd, no),
X = normalise(X0)
;
Changed = no,
X = mode_robdd(TrueVars, FalseVars,
EQVars, ImpVars, Robdd, yes)
)
;
X = zero
)
;
X = zero
)
).
:- pred normalise_true_false_equivalent_vars(bool::out, vars(T)::in,
vars(T)::out, vars(T)::in, vars(T)::out,
equiv_vars(T)::in, equiv_vars(T)::out) is det.
:- pragma type_spec(pred(normalise_true_false_equivalent_vars/7), T = mc_type).
normalise_true_false_equivalent_vars(Changed, T0, T, F0, F) -->
normalise_known_equivalent_vars(Changed0, T0, T),
normalise_known_equivalent_vars(Changed1, F0, F),
{ Changed = Changed0 `bool__or` Changed1 }.
:- pred extract_equivalent_vars_from_robdd(bool::out, robdd(T)::in,
robdd(T)::out, equiv_vars(T)::in, equiv_vars(T)::out) is det.
:- pragma type_spec(pred(extract_equivalent_vars_from_robdd/5), T = mc_type).
extract_equivalent_vars_from_robdd(Changed, Robdd0, Robdd, EQVars0, EQVars) :-
( RobddEQVars = equivalent_vars_in_robdd(Robdd0) ->
( empty(RobddEQVars) ->
Changed0 = no,
Robdd1 = Robdd0,
EQVars = EQVars0
;
Changed0 = yes,
% Remove any equalities we have just found from the
% ROBDD.
Robdd1 = squeeze_equiv(RobddEQVars, Robdd0),
EQVars = EQVars0 * RobddEQVars
)
;
EQVars = init_equiv_vars,
Changed0 = ( EQVars = EQVars0 -> no ; yes ),
Robdd1 = Robdd0
),
% Remove any other equalities from the ROBDD.
% Note that we can use EQVars0 here since we have already removed the
% equivalences in RobddEQVars using squeeze_equiv.
Robdd = remove_equiv(EQVars0, Robdd1),
Changed = Changed0 `bool__or` ( Robdd \= Robdd1 -> yes ; no ).
:- func x(tfeirn(T)::di_tfeirn, robdd(T)::in) = (tfeirn(T)::uo_tfeirn) is det.
:- pragma type_spec(func(x/2), T = mc_type).
%/*
x(mode_robdd(TA, FA, EA, IA, RA, _), RB) =
mode_robdd(TA `union` T1, FA `union` F1, EA * E1, IA * I1,
RA * R1, no) :-
mode_robdd(T1, F1, E1, I1, R1, _) =
normalise(mode_robdd(TA, FA, EA, IA, RB, no)).
%*/
/*
x(mode_robdd(TA, FA, EA, IA, RA, _), RB) =
mode_robdd(TA, FA, EA, IA, RA * RB, no).
*/
%---------------------------------------------------------------------------%
robdd_to_mode_robdd(R) =
normalise(mode_robdd(init, init, init_equiv_vars, init_imp_vars,
R, no)).
%---------------------------------------------------------------------------%
to_robdd(X) =
(X ^ robdd * conj_vars(X ^ true_vars) * conj_not_vars(X ^ false_vars))
^ map__foldl(func(A, B, R) = R * eq_vars(A, B),
X ^ equiv_vars ^ leader_map)
^ add_implications(X ^ imp_vars).
% to_robdd(X) =
% (X ^ robdd * conj_vars(X ^ true_vars) * conj_not_vars(X ^ false_vars))
% ^ expand_equiv(X ^ equiv_vars ^ leader_map)
% ^ add_implications(X ^ imp_vars).
%---------------------------------------------------------------------------%
:- end_module mode_robdd.tfeirn.
%-----------------------------------------------------------------------------%