:- module(bdd, [bdd_new/2, bdd_new/3, bdd_from_list/3, mtbdd_new/2, mtbdd_new/3, bdd_eval/2, mtbdd_eval/2, bdd_tree/2, bdd_size/2, bdd_print/2, bdd_to_probability_sum_product/2, bdd_to_probability_sum_product/3, bdd_close/1, mtbdd_close/1]). :- use_module(library(lists)). :- use_module(library(maplist)). :- use_module(library(rbtrees)). :- use_module(library(simpbool)). tell_warning :- print_message(warning,functionality(cudd)). :- catch(load_foreign_files([cudd], [], init_cudd),_,fail) -> true ; tell_warning. % create a new BDD from a tree. bdd_new(T, Bdd) :- term_variables(T, Vars), bdd_new(T, Vars, Bdd). bdd_new(T, Vars, cudd(M,X,VS,TrueVars)) :- term_variables(Vars, TrueVars), VS =.. [vs|TrueVars], findall(Manager-Cudd, set_bdd(T, VS, Manager, Cudd), [M-X]). % create a new BDD from a list. bdd_from_list(List, Vars, cudd(M,X,VS,TrueVars)) :- term_variables(Vars, TrueVars), VS =.. [vs|TrueVars], findall(Manager-Cudd, set_bdd_from_list(List, VS, Manager, Cudd), [M-X]). set_bdd(T, VS, Manager, Cudd) :- numbervars(VS,0,_), ( ground(T) -> term_to_cudd(T,Manager,Cudd) ; writeln(throw(error(instantiation_error,T))) ). set_bdd_from_list(T0, VS, Manager, Cudd) :- numbervars(VS,0,_), generate_releases(T0, Manager, T), % T0 = T, % writeln_list(T0), list_to_cudd(T,Manager,_Cudd0,Cudd). generate_releases(T0, Manager, T) :- rb_empty(RB0), reverse(T0, [H|R]), add_releases(R, RB0, [H], Manager, T). add_releases([], _, RR, _M, RR). add_releases([(X = Ts)|R], RB0, RR0, M, RR) :- term_variables(Ts, Vs), !, add_variables(Vs, RB0, RR0, M, RBF, RRI), add_releases(R, RBF, [(X=Ts)|RRI], M, RR). add_variables([], RB, RR, _M, RB, RR). add_variables([V|Vs], RB0, RR0, M, RBF, RRF) :- rb_lookup(V, _, RB0), !, add_variables(Vs, RB0, RR0, M, RBF, RRF). add_variables([V|Vs], RB0, RR0, M, RBF, RRF) :- rb_insert(RB0, V, _, RB1), add_variables(Vs, RB1, [release_node(M,V)|RR0], M, RBF, RRF). writeln_list([]). writeln_list([B|Bindings]) :- writeln(B), writeln_list(Bindings). %list_to_cudd(H._List,_Manager,_Cudd0,_CuddF) :- writeln(l:H), fail. list_to_cudd([],_Manager,Cudd,Cudd) :- writeln('X'). list_to_cudd([release_node(M,cudd(V))|T], Manager, Cudd0, CuddF) :- !, write('-'), flush_output, cudd_release_node(M,V), list_to_cudd(T, Manager, Cudd0, CuddF). list_to_cudd([(V=0*_Par)|T], Manager, _Cudd0, CuddF) :- !, write('0'), flush_output, term_to_cudd(0, Manager, Cudd), V = cudd(Cudd), list_to_cudd(T, Manager, Cudd, CuddF). list_to_cudd([(V=0)|T], Manager, _Cudd0, CuddF) :- !, write('0'), flush_output, term_to_cudd(0, Manager, Cudd), V = cudd(Cudd), list_to_cudd(T, Manager, Cudd, CuddF). list_to_cudd([(V=_Tree*0)|T], Manager, _Cudd0, CuddF) :- !, write('0'), flush_output, term_to_cudd(0, Manager, Cudd), V = cudd(Cudd), list_to_cudd(T, Manager, Cudd, CuddF). list_to_cudd([(V=Tree*1)|T], Manager, _Cudd0, CuddF) :- !, write('.'), flush_output, term_to_cudd(Tree, Manager, Cudd), V = cudd(Cudd), list_to_cudd(T, Manager, Cudd, CuddF). list_to_cudd([(V=Tree)|T], Manager, _Cudd0, CuddF) :- write('.'), flush_output, ( ground(Tree) -> true ; throw(error(instantiation_error(Tree))) ), term_to_cudd(Tree, Manager, Cudd), V = cudd(Cudd), list_to_cudd(T, Manager, Cudd, CuddF). mtbdd_new(T, Mtbdd) :- term_variables(T, Vars), mtbdd_new(T, Vars, Mtbdd). mtbdd_new(T, Vars, add(M,X,VS,Vars)) :- VS =.. [vs|Vars], functor(VS,vs,Sz), findall(Manager-Cudd, (numbervars(VS,0,_),term_to_add(T,Sz,Manager,Cudd)), [M-X]). bdd_eval(cudd(M, X, Vars, _), Val) :- cudd_eval(M, X, Vars, Val). bdd_eval(add(M, X, Vars, _), Val) :- add_eval(M, X, Vars, Val). mtbdd_eval(add(M,X, Vars, _), Val) :- add_eval(M, X, Vars, Val). % get the BDD as a Prolog list from the CUDD C object bdd_tree(cudd(M, X, Vars, _Vs), bdd(Dir, List, Vars)) :- cudd_to_term(M, X, Vars, Dir, List). bdd_tree(add(M, X, Vars, _), mtbdd(Tree, Vars)) :- add_to_term(M, X, Vars, Tree). bdd_to_probability_sum_product(cudd(M,X,_,Probs), Prob) :- cudd_to_probability_sum_product(M, X, Probs, Prob). bdd_to_probability_sum_product(cudd(M,X,_,_Probs), Probs, Prob) :- cudd_to_probability_sum_product(M, X, Probs, Prob). bdd_close(cudd(M,_,_Vars, _)) :- cudd_die(M). bdd_close(add(M,_,_Vars, _)) :- cudd_die(M). bdd_size(cudd(M,Top,_Vars, _), Sz) :- cudd_size(M,Top,Sz). bdd_size(add(M,Top,_Vars, _), Sz) :- cudd_size(M,Top,Sz). bdd_print(cudd(M,Top,_Vars, _), File) :- cudd_print(M, Top, File). bdd_print(add(M,Top,_Vars, _), File) :- cudd_print(M, Top, File). mtbdd_close(add(M,_,_Vars,_)) :- cudd_die(M). /* algorithm to compute probabilitie in Prolog */ bdd_to_sp(bdd(Dir, Tree, _Vars, IVars), Binds, Prob) :- findall(P, sp(Dir, Tree, IVars, Binds, P), [Prob]). sp(Dir, Tree, Vars, Vars, P) :- run_sp(Tree), fetch(Tree, Dir, P). run_sp([]). run_sp(pp(P,X,L,R).Tree) :- run_sp(Tree), P is X*L+(1-X)*R. run_sp(pn(P,X,L,R).Tree) :- run_sp(Tree), P is X*L+(1-X)*(1-R). fetch(pp(P,_,_,_)._Tree, 1, P). fetch(pp(P,_,_,_)._Tree, -1, N) :- N is 1-P. fetch(pn(P,_,_,_)._Tree, 1, P). fetch(pn(P,_,_,_)._Tree, -1, N) :- N is 1-P.