This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/CLPBN/clpbn/bp.yap
2011-02-23 15:31:56 +00:00

158 lines
4.5 KiB
Prolog

/***********************************
Belief Propagation in CLP(BN)
This should connect to C-code.
*********************************/
:- module(clpbn_bp, [
bp/3,
check_if_bp_done/1,
init_bp_solver/4,
run_bp_solver/3]).
:- use_module(library('clpbn/aggregates'),
[check_for_agg_vars/2]).
:- use_module(library('clpbn/connected'),
[init_influences/3,
influences/5
]).
:- use_module(library('clpbn/dists'),
[dist/4,
get_dist_domain/2,
get_dist_params/2
]).
:- use_module(library('clpbn/display'),
[clpbn_bind_vals/3]).
:-use_module(library(lists),
[append/3,
memberchk/2
]).
:- load_foreign_files(['horus'], [], init_predicates).
:- attribute all_diffs/1.
check_if_bp_done(_Var).
%
% implementation of belief propagation
%
% A1 = +QueryVars -> sets of independent marginalization variables
% A2 = *AllVars -> list of all variables
% A3 = -Output -> output probabilities
%
% Other important variables:
%
% State0 initialized graph, is used to pass data from initialization
% to query solving (eg, State might be the JT and be used to run
% different queries).
%
bp([[]],_,_) :- !.
bp([QueryVars],AllVars,Output) :-
writeln(queryVars:QueryVars),
writeln(allVars:AllVars),
% init_bp_solver([QueryVars], AllVars, Output, State),
run_bp_solver([QueryVars], [AllVars], _State),
% bind probs back to variables so that they can be output.
clpbn_bind_vals([QueryVars],[LPs],Output).
% initialise necessary data for query solver
init_bp_solver(Qs, AllVars, _, graph(LVis)) :-
% replace average, max, min and friends by binary nodes.
check_for_agg_vars(AllVars, UnFoldedVars),
% replace the variables reachable from G
init_influences(UnfoldedVars, G, RG),
init_bp_solver_for_questions(Qs, G, RG, _, LVis).
init_bp_solver_for_questions([], _, _, [], []).
init_bp_solver_for_questions([Vs|MVs], G, RG, [NVs|MNVs0], [NVs|LVis]) :-
% find variables connectd to Vs
influences(Vs, _, NVs0, G, RG),
sort(NVs0, NVs),
init_bp_solver_for_questions(MVs, G, RG, MNVs0, LVis).
% use a findall to recover space without needing for GC
run_bp_solver(LVs, LPs, _) :-
findall(Ps, solve_bp(LVs, LPs, Ps), LPs).
solve_bp([LVs|_], [NVs0|_], Ps) :-
get_vars_info(NVs0, LVi),
get_dists_info(NVs0, Dists),
process(LVi, Dists, LVs, Ps).
solve_bp([_|MoreLVs], [_|MoreLVis], Ps) :-
solve_bp(MoreLVs, MoreLVis, Ps).
get_vars_info([], []).
get_vars_info([V|Vs], [var(V, Id, Parents, NParents, Ev)|LV]) :-
clpbn:get_atts(V, [dist(Id, Parents)]), !,
length(Parents, NParents),
get_evidence(V, Ev),
get_vars_info(Vs, LV).
get_vars_info([_|Vs], LV) :-
get_vars_info(Vs, LV).
get_evidence(V, Ev) :-
clpbn:get_atts(V, [evidence(Ev)]), !.
get_evidence(V, -1). % no evidence !!!
get_dists_info([],[]).
get_dists_info([V|Vs], [dist(Id, Domain, DSize, Params, NParams) | Dists]) :-
clpbn:get_atts(V, [dist(Id, _)]), !,
get_dist_domain(Id, Domain),
length(Domain, DSize),
get_dist_params(Id, Params),
length(Params, NParams),
get_dists_info(Vs, Dists).
get_dists_info([_|Vs], Dists) :-
get_dists_info(Vs, Dists).
% +Vars is a list containing info about every clpbn variables
% +Dists is a list containing info about distributions
% +QVs is a list containing the query variables
% -Out is some output term stating the probabilities
process(Vars, Dists, QVs, Out) :-
write('vars = '), writeln(Vars),
order_vars(Vars, [], OrderedVars),
write('ovars = '), writeln(OrderedVars),
write('dists = '), writeln(Dists),
write('qvs = '), writeln(QVs),
length(OrderedVars, NVars),
length(Dists, NDists),
%create_network(OrderedVars, NVars, Dists, NDists, BNet),
length(QVs, NQVs),
run_solver(BNet, QVs, NQVs, Out),
free_memory(BNet).
order_vars([V], _, [V]) :- !.
order_vars([var(V, Id, Parents, NParents, Ev)|Vs], ParsedVars, [var(V, Id, Parents, NParents, Ev)|OrderedVars]) :-
\+ memberchk(V, ParsedVars),
parents_defined(Parents, ParsedVars), !,
order_vars(Vs, [V|ParsedVars], OrderedVars).
order_vars([var(V, Id, Parents, NParents, Ev)|Vs], ParsedVars, OrderedVars) :-
append(Vs, [var(V, Id, Parents, NParents, Ev)], NVs),
order_vars(NVs, ParsedVars, OrderedVars).
parents_defined([], _) :- !.
parents_defined([Parent|Parents], ParsedVars) :-
memberchk(Parent, ParsedVars),
parents_defined(Parents, ParsedVars).
% f(F), b(B). ----> FAIL