introduce CLPBN in system
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1094 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
parent
08b9f55f9c
commit
ab1cd9bb60
404
CLPBN/clpbn.yap
Normal file
404
CLPBN/clpbn.yap
Normal file
@ -0,0 +1,404 @@
|
||||
|
||||
|
||||
:- module(clpbn, [{}/1,
|
||||
clpbn_findall/3,
|
||||
clpbn_setof/3]).
|
||||
|
||||
:- use_module(library(atts)).
|
||||
:- use_module(library(lists)).
|
||||
:- use_module(library(terms)).
|
||||
|
||||
:- op(1200, xfx, '<--').
|
||||
:- op(1200, fx, '<--').
|
||||
:- op( 500, xfx, '=>').
|
||||
:- op( 500, xfy, with).
|
||||
|
||||
%
|
||||
% avoid the overhead of using goal_expansion/2.
|
||||
%
|
||||
:- multifile
|
||||
user:term_expansion/2.
|
||||
|
||||
:- dynamic
|
||||
user:term_expansion/2.
|
||||
|
||||
:- multifile
|
||||
user:term_expansion/2.
|
||||
|
||||
:- attribute key/1, dist/1, evidence/1, done/1, starter/0.
|
||||
|
||||
|
||||
:- use_module('clpbn/bnt', [dump_as_bnt/2,
|
||||
check_if_bnt_done/1
|
||||
]).
|
||||
|
||||
:- use_module('clpn/vel', [vel/3,
|
||||
check_if_vel_done/1
|
||||
]).
|
||||
|
||||
:- use_module('clpbn/evidence', [add_to_evidence/1,
|
||||
execute_pre_evidence/0
|
||||
]).
|
||||
|
||||
:- include('clpbn/aggs').
|
||||
|
||||
use(vel).
|
||||
|
||||
{Var = Key with Dist} :-
|
||||
% key_entry(Key,Indx),
|
||||
% array_element(clpbn,Indx,El),
|
||||
% attributes:put_att(El,3,indx(Indx)),
|
||||
clpbn:put_atts(El,[key(Key),dist(E=>Domain)]),
|
||||
extract_dist(Dist, E, Domain),
|
||||
add_evidence(Var,El).
|
||||
|
||||
extract_dist(V, (Tab.Inps), Domain) :- var(V), !,
|
||||
V = p(Domain, Tab, Inps).
|
||||
extract_dist(p(Domain, Tab, []), Tab, Domain) :- !.
|
||||
extract_dist(p(Domain, Tab, Inps), (Tab.Inps), Domain).
|
||||
extract_dist(p(Domain, Tab), Tab, Domain).
|
||||
|
||||
key_entry(Key, I) :-
|
||||
hash_table_size(Size),
|
||||
term_hash(Key, -1, Size, Hash),
|
||||
collision(Hash, Size, I),
|
||||
( array_element(keys, I, El) ->
|
||||
update_array(keys, I, Key)
|
||||
;
|
||||
El = Key),
|
||||
!.
|
||||
|
||||
% go from beginning
|
||||
collision(Size, Size, I) :- !,
|
||||
collision(0, Size, I).
|
||||
collision(Hash, _, Hash).
|
||||
collision(Hash, Size, I) :-
|
||||
Hash1 is Hash+1,
|
||||
collision(Hash1, Size, I).
|
||||
|
||||
%
|
||||
% just fetch skolems so that we can process them carefully.
|
||||
%
|
||||
fetch_skolems(A, A) --> { var(A) }, !. %meta-calls
|
||||
fetch_skolems((A,B), (NA,NB)) --> !,
|
||||
fetch_skolems(A, NA),
|
||||
fetch_skolems(B, NB).
|
||||
% do not allow disjunctive clauses, at least for now.
|
||||
fetch_skolems((A;B), (A;B)) --> !.
|
||||
fetch_skolems((A|B), (A|B)) --> !.
|
||||
fetch_skolems((A->B), (NA->NB)) --> !,
|
||||
fetch_skolems(A, NA),
|
||||
fetch_skolems(B, NB).
|
||||
fetch_skolems(M:A, M:NA) --> !,
|
||||
fetch_skolems(A, NA).
|
||||
fetch_skolems(X = { Constraints }, true) --> !,
|
||||
[ [X|Constraints] ].
|
||||
fetch_skolems(G, G) --> [].
|
||||
|
||||
%
|
||||
% just fetch skolems so that we can process them carefully.
|
||||
%
|
||||
handle_body_goals((A,B), (NA,NB)) :- !,
|
||||
handle_body_goals(A, NA),
|
||||
handle_body_goals(B, NB).
|
||||
% do not allow disjunctive clauses, at least for now.
|
||||
handle_body_goals((A;B), (A;B)) :- !.
|
||||
handle_body_goals((A|B), (A|B)) :- !.
|
||||
handle_body_goals((A->B), (NA->NB)) :- !,
|
||||
handle_body_goals(A, NA),
|
||||
handle_body_goals(B, NB).
|
||||
handle_body_goals(M:A, M:NA) :- !,
|
||||
handle_body_goals(A, NA).
|
||||
handle_body_goals(findall(V,G,L), (findall(V,G,L), aggs:fix_vars(L))) :- !.
|
||||
handle_body_goals(setof(V,G,L), (setof(V,G,L),aggs:fix_vars(L))) :- !.
|
||||
handle_body_goals(bagof(V,G,L), (bagof(V,G,L),aggs:fix_vars(L))) :- !.
|
||||
handle_body_goals(G, G).
|
||||
|
||||
|
||||
compile_skolems([[X|Constraints]], Vars, NVars, A, Code) :- !,
|
||||
compile_skolem(X, Vars, NVars, A, Code, Constraints).
|
||||
compile_skolems([[X|Constraints]|Cs], Vars, NVars, A, (Code, RCode)) :-
|
||||
compile_skolem(X, Vars, NVars, A, Code, Constraints),
|
||||
compile_skolems(Cs, Vars, NVars, A, RCode).
|
||||
|
||||
compile_skolem(EVar, Vars, NVars, Head, Code, Constraints) :-
|
||||
compile_constraints(Constraints, Vars, NVars, Head, Code, EVar).
|
||||
|
||||
compile_constraints((A : B), Vars, NVars, Head, (CA , CB), EVar) :- !,
|
||||
compile_first_constraint(A, Head, CA, EVar),
|
||||
compile_second_constraint(B, Vars, NVars, CB, EVar).
|
||||
|
||||
compile_first_constraint(SkKey, Head, (KeyGoal, /* cycle(Key,EVar), */ array_element(clpbn, Id, EVar), clpbn:put_atts(EVar,[key(KeyDesc),indx(Id)])), EVar) :-
|
||||
functor(SkKey, Name, _),!,
|
||||
SkKey =.. [_|Key],
|
||||
generate_key_goal(Head, Name, Key, KeyGoal, KeyDesc, Id).
|
||||
|
||||
compile_second_constraint(Constraint, Vars, NVars, clpbn:put_atts(EVar,[dist(NC)]), EVar) :-
|
||||
check_constraint(Constraint, Vars, NVars, NC).
|
||||
|
||||
check_constraint(Constraint, _, _, Constraint) :- var(Constraint), !.
|
||||
check_constraint((A=>D), _, _, (A=>D)) :- var(A), !.
|
||||
check_constraint((([A|B].L)=>D), Vars, NVars, (([A|B].NL)=>D)) :- !,
|
||||
check_cpt_input_vars(L, Vars, NVars, NL).
|
||||
check_constraint(Dist, _, _, Dist).
|
||||
|
||||
check_cpt_input_vars([], _, _, []).
|
||||
check_cpt_input_vars([V|L], Vars, NVars, [NV|NL]) :-
|
||||
replace_var(Vars, V, NVars, NV),
|
||||
check_cpt_input_vars(L, Vars, NVars, NL).
|
||||
|
||||
replace_var([], V, [], V).
|
||||
replace_var([V|_], V0, [NV|_], NV) :- V == V0, !.
|
||||
replace_var([_|Vars], V, [_|NVars], NV) :-
|
||||
replace_var(Vars, V, NVars, NV).
|
||||
|
||||
generate_key_goal(Head, Name, Key, clpbn_aux:KeyGoal, KeyDesc, Id) :-
|
||||
functor(Head, _, Ar),
|
||||
atom_chars(Name, NaS),
|
||||
number_codes(Ar, ArS),
|
||||
append("/", ArS, S1),
|
||||
append(NaS, S1, S2),
|
||||
append("key_", S2, SNNa),
|
||||
atom_chars(NNa, SNNa),
|
||||
append(Key,[Id],LArgs),
|
||||
KeyGoal =.. [NNa|LArgs],
|
||||
KeyDesc =.. [Name|Key],
|
||||
length(Key, N),
|
||||
NAr is N+1,
|
||||
abolish(clpbn_aux:(NNa/NAr)),
|
||||
reset_clpbn,
|
||||
dynamic_predicate(clpbn_aux:(NNa/NAr), logical),
|
||||
assert((clpbn_aux:KeyGoal :- new_key(Id), asserta(clpbn_aux:(KeyGoal :- !)))).
|
||||
|
||||
new_key(Key) :-
|
||||
get_value(clpbn_key, Key),
|
||||
X is Key+1,
|
||||
set_value(clpbn_key, X).
|
||||
|
||||
skolem_vars([], []).
|
||||
skolem_vars([[V|_]|LV], [V|NLV]) :-
|
||||
skolem_vars(LV, NLV).
|
||||
|
||||
|
||||
skolem_new_vars([], [], []).
|
||||
skolem_new_vars([[_|B]|Sks], [NV|Vs], [[NV|B]|NSks]) :-
|
||||
skolem_new_vars(Sks, Vs, NSks).
|
||||
|
||||
|
||||
fresh_vars([], [], B, B).
|
||||
fresh_vars([V|LV], [NV|NLV], (clpbn:add_evidence(V,NV),B), B0) :-
|
||||
fresh_vars(LV, NLV, B, B0).
|
||||
|
||||
|
||||
add_evidence(V,NV) :-
|
||||
nonvar(V), !,
|
||||
clpbn:put_atts(NV,evidence(V)).
|
||||
add_evidence(V,V).
|
||||
|
||||
%
|
||||
% called by top-level
|
||||
%
|
||||
project_attributes(GVars, AVars) :-
|
||||
AVars = [_|_], !,
|
||||
execute_pre_evidence,
|
||||
sort_vars_by_key(AVars,SortedAVars,DiffVars),
|
||||
get_clpbn_vars(GVars,CLPBNGVars),
|
||||
write_out(CLPBNGVars, SortedAVars,DiffVars).
|
||||
project_attributes(_, _).
|
||||
|
||||
get_clpbn_vars([],[]).
|
||||
get_clpbn_vars([V|GVars],[V|CLPBNGVars]) :-
|
||||
get_atts(V, [key(_)]), !,
|
||||
get_clpbn_vars(GVars,CLPBNGVars).
|
||||
get_clpbn_vars([_|GVars],CLPBNGVars) :-
|
||||
get_clpbn_vars(GVars,CLPBNGVars).
|
||||
|
||||
sort_vars_by_key(AVars,SortedAVars, UnifiableVars) :-
|
||||
get_keys(AVars, KeysVars),
|
||||
keysort(KeysVars, KVars),
|
||||
merge_same_key(KVars, SortedAVars, [], UnifiableVars).
|
||||
|
||||
get_keys([], []).
|
||||
get_keys([V|AVars], [K-V|KeysVars]) :-
|
||||
get_atts(V, [key(K)]),
|
||||
get_keys(AVars, KeysVars).
|
||||
|
||||
merge_same_key([], [], _, []).
|
||||
merge_same_key([K1-V1,K2-V2|Vs], SortedAVars, Ks, UnifiableVars) :-
|
||||
K1 == K2, !, V1 = V2,
|
||||
merge_same_key([K1-V1|Vs], SortedAVars, Ks, UnifiableVars).
|
||||
merge_same_key([K1-V1,K2-V2|Vs], [V1|SortedAVars], Ks, [K1|UnifiableVars]) :-
|
||||
(in_keys(K1, Ks) ; \+ \+ K1 = K2), !,
|
||||
add_to_keys(K1, Ks, NKs),
|
||||
merge_same_key([K2-V2|Vs], SortedAVars, NKs, UnifiableVars).
|
||||
merge_same_key([K-V|Vs], [V|SortedAVars], Ks, UnifiableVars) :-
|
||||
add_to_keys(K, Ks, NKs),
|
||||
merge_same_key(Vs, SortedAVars, NKs, UnifiableVars).
|
||||
|
||||
in_keys(K1,[K|_]) :- \+ \+ K1 = K, !.
|
||||
in_keys(K1,[_|Ks]) :-
|
||||
in_keys(K1,Ks).
|
||||
|
||||
add_to_keys(K1, Ks, Ks) :- ground(K1), !.
|
||||
add_to_keys(K1, Ks, [K1|Ks]).
|
||||
|
||||
write_out(GVars, AVars, DiffVars) :-
|
||||
use(vel),
|
||||
vel(GVars, AVars, DiffVars).
|
||||
write_out(GVars, AVars, _) :-
|
||||
use(bnt),
|
||||
dump_as_bnt(GVars, AVars).
|
||||
% starter_vars(GVars).
|
||||
|
||||
starter_vars([]).
|
||||
starter_vars([Var|Vs]) :-
|
||||
get_atts(Var, [key(_)]),
|
||||
put_atts(Var, [starter]),
|
||||
starter_vars(Vs).
|
||||
|
||||
|
||||
/* attribute_goal(Var, Goal) :-
|
||||
get_atts(Var, [key(_)]),
|
||||
get_bnode(Var, Goal).
|
||||
|
||||
get_value(clpbn_key, Max),
|
||||
Max1 is Max-1,
|
||||
run_through_array(0, Max1, Goal).
|
||||
|
||||
|
||||
run_through_array(Max,Max,Goal) :- !,
|
||||
array_element(clpbn, Max, V),
|
||||
get_bnode(V, Goal).
|
||||
run_through_array(I,Max,(G,Goal)) :- !,
|
||||
array_element(clpbn, I, V),
|
||||
get_bnode(V, G),
|
||||
I1 is I+1,
|
||||
run_through_array(I1,Max,Goal).
|
||||
*/
|
||||
|
||||
get_bnode(Var, Goal) :-
|
||||
get_atts(Var, [key(Key),dist(X)]),
|
||||
dist_goal(X, Key, Goal0),
|
||||
include_evidence(Var, Goal0, Key, Goali),
|
||||
include_starter(Var, Goali, Key, Goal).
|
||||
|
||||
include_evidence(Var, Goal0, Key, ((Key<--Ev),Goal0)) :-
|
||||
get_atts(Var, [evidence(Ev)]), !.
|
||||
include_evidence(_, Goal0, _, Goal0).
|
||||
|
||||
include_starter(Var, Goal0, Key, ((<--Key),Goal0)) :-
|
||||
get_atts(Var, [starter]), !.
|
||||
include_starter(_, Goal0, _, Goal0).
|
||||
|
||||
dist_goal(norm(M,V), Key, (Key=norm(M,V))) :- !.
|
||||
dist_goal(avg(L), Key, (Key=avg(L))) :- !.
|
||||
dist_goal(Dist, Key, (Key=NDist)) :-
|
||||
term_variables(Dist, DVars),
|
||||
process_vars(DVars, DKeys),
|
||||
my_copy_term(Dist,DVars, NDist,DKeys).
|
||||
|
||||
my_copy_term(V, DVars, Key, DKeys) :-
|
||||
find_var(DVars, V, Key, DKeys).
|
||||
my_copy_term(A, _, A, _) :- atomic(A), !.
|
||||
my_copy_term(T, Vs, NT, Ks) :-
|
||||
T =.. [Na|As],
|
||||
my_copy_terms(As, Vs, NAs, Ks),
|
||||
NT =.. [Na|NAs].
|
||||
|
||||
my_copy_terms([], _, [], _).
|
||||
my_copy_terms([A|As], Vs, [NA|NAs], Ks) :-
|
||||
my_copy_term(A, Vs, NA, Ks),
|
||||
my_copy_terms(As, Vs, NAs, Ks).
|
||||
|
||||
find_var([V1|_], V, Key, [Key|_]) :- V1 == V, !.
|
||||
find_var([_|DVars], V, Key, [_|DKeys]) :-
|
||||
find_var(DVars, V, Key, DKeys).
|
||||
|
||||
process_vars([], []).
|
||||
process_vars([V|Vs], [K|Ks]) :-
|
||||
process_var(V, K),
|
||||
process_vars(Vs, Ks).
|
||||
|
||||
process_var(V, K) :- get_atts(V, [key(K)]), !.
|
||||
% oops: this variable has no attributes.
|
||||
process_var(V, _) :- throw(error(instantiation_error,clpbn(attribute_goal(V)))).
|
||||
|
||||
%
|
||||
% unify a CLPBN variable with something.
|
||||
%
|
||||
verify_attributes(Var, T, Goals) :-
|
||||
get_atts(Var, [key(Key),dist(Dist)]), !,
|
||||
/* oops, someone trying to bind a clpbn constrained variable */
|
||||
Goals = [],
|
||||
bind_clpbn(T, Var, Key, Dist).
|
||||
verify_attributes(_, _, []).
|
||||
|
||||
|
||||
bind_clpbn(T, _, Key, Dist) :- var(T),
|
||||
get_atts(T, [key(Key1),dist(Dist1)]), !,
|
||||
bind_clpbns(Key, Dist, Key1, Dist1).
|
||||
bind_clpbn(_, Var, _, _) :-
|
||||
use(bnt),
|
||||
check_if_bnt_done(Var), !.
|
||||
bind_clpbn(_, Var, _, _) :-
|
||||
use(vel),
|
||||
check_if_vel_done(Var), !.
|
||||
bind_clpbn(T, Var, Key0, _) :-
|
||||
get_atts(Var, [key(Key0)]), !,
|
||||
(
|
||||
Key = Key0 -> true
|
||||
;
|
||||
format(user_error, "trying to force evidence ~w through unification with key ~w~n",[T, Key])
|
||||
).
|
||||
|
||||
fresh_attvar(Var, NVar) :-
|
||||
get_atts(Var, LAtts),
|
||||
put_atts(NVar, LAtts).
|
||||
|
||||
bind_clpbns(Key, Dist, Key, Dist1) :- !,
|
||||
( Dist = Dist1 -> true ; throw(error(domain_error(bayesian_domain),bind_clpbns))).
|
||||
bind_clpbns(_, _, _, _, _) :-
|
||||
format(user_error, "unification of two bayesian vars not supported~n").
|
||||
|
||||
:- yap_flag(toplevel_hook,clpbn:init_clpbn).
|
||||
|
||||
hash_table_size(300000).
|
||||
|
||||
init_clpbn :-
|
||||
reset_clpbn,
|
||||
fail.
|
||||
%init_clpbn :-
|
||||
% hash_table_size(HashTableSize),
|
||||
% array(clpbn,HashTableSize),
|
||||
% catch(static_array(keys,HashTableSize,term),_,true).
|
||||
|
||||
|
||||
random_tmp_number(I) :-
|
||||
get_value(clpbn_random_tmp_number,I),
|
||||
I1 is I+1,
|
||||
set_value(clpbn_random_tmp_number,I1).
|
||||
|
||||
reset_clpbn :-
|
||||
current_predicate(_, clpbn_aux:P),
|
||||
retract(clpbn_aux:(P :- !)),
|
||||
fail.
|
||||
reset_clpbn :-
|
||||
set_value(clpbn_key, 0), fail.
|
||||
reset_clpbn :-
|
||||
set_value(clpbn_random_tmp_number, 0), fail.
|
||||
reset_clpbn.
|
||||
|
||||
|
||||
user:term_expansion((A :- {}), ( :- true )) :- !, % evidence
|
||||
prolog_load_context(module, M),
|
||||
add_to_evidence(M:A).
|
||||
user:term_expansion((A :- B), (A :- (LCs,NB))) :- % expands heads
|
||||
fetch_skolems(B, B0, Skolems, []),
|
||||
Skolems \= [],
|
||||
skolem_vars(Skolems, Vars),
|
||||
copy_term(Vars+A, NVars+NA),
|
||||
skolem_new_vars(Skolems, NVars, NSkolems),
|
||||
compile_skolems(NSkolems, Vars, NVars, NA, LCs),
|
||||
handle_body_goals(B0, B1),
|
||||
fresh_vars(Vars, NVars, NB, B1).
|
||||
|
546
CLPBN/clpbn/bnt.yap
Normal file
546
CLPBN/clpbn/bnt.yap
Normal file
@ -0,0 +1,546 @@
|
||||
|
||||
:- module(bnt, [dump_as_bnt/2,
|
||||
check_if_bnt_done/1]).
|
||||
|
||||
:- use_module(library(terms), [term_variables/2
|
||||
]).
|
||||
|
||||
:- use_module(library(ordsets), [ord_subtract/3,
|
||||
ord_add_element/3
|
||||
]).
|
||||
|
||||
:- use_module(library(lists), [reverse/2
|
||||
]).
|
||||
|
||||
:- use_module(library(atts)).
|
||||
|
||||
:- use_module(library(heaps), [empty_heap/1,
|
||||
add_to_heap/4,
|
||||
heap_to_list/2
|
||||
]).
|
||||
|
||||
:- use_module(library(system), [exec/3
|
||||
]).
|
||||
|
||||
:- attribute topord/1, map/1.
|
||||
|
||||
check_if_bnt_done(Var) :-
|
||||
get_atts(Var, [map(_)]).
|
||||
|
||||
dump_as_bnt(GVars, [_|_]) :-
|
||||
exec('matlab -nojvm -nosplash',[pipe(CommandStream),pipe(Answer),pipe(Answer)],_),
|
||||
wait_for_matlab_prompt(Answer),
|
||||
get_value(clpbn_key, Key),
|
||||
send_command(CommandStream, Answer, 'cd /u/vitor/sw/BNT;~n', []),
|
||||
% send_command(CommandStream, Answer, 'cd /home/vitor/Yap/CLPBN/BNT;~n', []),
|
||||
send_command(CommandStream, Answer, 'add_BNT_to_path;~n', []),
|
||||
send_command(CommandStream, Answer, '~w = ~w;~n', ['$VAR'(Key), Key]),
|
||||
send_command(CommandStream, Answer, 'dag = zeros(~w,~w);~n', ['$VAR'(Key), '$VAR'(Key)]),
|
||||
Key1 is Key-1,
|
||||
dump_variable_indices(Key1, Vs, Heap, CommandStream, Answer),
|
||||
write_deps(Heap, CommandStream, Answer),
|
||||
find_observables(GVars, Observables),
|
||||
mknet(Vs, Key, Observables, CommandStream, Answer),
|
||||
dump_cpds(Vs, CommandStream, Answer),
|
||||
inf_engine(Vs, Key, CommandStream, Answer),
|
||||
output_answer(Observables, CommandStream, Answer),
|
||||
close(CommandStream),
|
||||
close(Answer).
|
||||
|
||||
|
||||
dump_variable_indices(I, LF, HF, CommandStream, Answer) :-
|
||||
all_vars_with_deps(I, LDeps, LNoDeps),
|
||||
sort(LNoDeps, S0),
|
||||
empty_heap(H0),
|
||||
topsort(LDeps, S0, LNoDeps, LF, H0, HF),
|
||||
reverse(LF, Vs),
|
||||
dump_vlist(Vs, 0, CommandStream, Answer).
|
||||
|
||||
all_vars_with_deps(0, LDeps, LNoDeps) :- !,
|
||||
var_with_deps(0, LDeps, [], LNoDeps, []).
|
||||
all_vars_with_deps(I, LDeps, LNoDeps) :-
|
||||
var_with_deps(I, LDeps, LDeps0, LNoDeps, LNoDeps0),
|
||||
I1 is I-1,
|
||||
all_vars_with_deps(I1, LDeps0, LNoDeps0).
|
||||
|
||||
var_with_deps(Indx, Deps, Deps0, NoDeps, NoDeps0) :-
|
||||
array_element(clpbn, Indx, V),
|
||||
clpbn:get_atts(V, [dist(D)]), !,
|
||||
term_variables(D, VDeps),
|
||||
(VDeps = [] ->
|
||||
NoDeps = [V|NoDeps0], Deps = Deps0 ;
|
||||
sort(VDeps,SVDeps),
|
||||
Deps = [[V|SVDeps]|Deps0], NoDeps = NoDeps0 ).
|
||||
|
||||
%
|
||||
% this is a silly quadratic algorithm for topological sorting.
|
||||
% it will have to do for now.
|
||||
%
|
||||
% to speedup things a bit I keep a sorted and unsorted version
|
||||
% of the variables sorted so far.
|
||||
%
|
||||
topsort([], _, S, S, H, H) :- !.
|
||||
topsort(LDeps, Sorted0, S0, SF, H, HF) :- !,
|
||||
delete_all(LDeps, Sorted0, S0, LI, SI, Sorted, H, HI),
|
||||
topsort(LI, Sorted, SI, SF, HI, HF).
|
||||
|
||||
delete_all([], SS, S, [], S, SS, H, H).
|
||||
delete_all([[V|VDeps]|LDeps], SS, S, LF, SF, SSF, H0, HF) :-
|
||||
ord_subtract(VDeps, SS, VDepsI),
|
||||
ord_subtract(VDeps, VDepsI, Parents),
|
||||
add_parents_to_heap(Parents, V, H0, HI),
|
||||
( VDepsI = [] ->
|
||||
LF = LI, ord_add_element(SS,V,SSI), SI = [V|S];
|
||||
LF = [[V|VDepsI]|LI], SI = S, SSI = SS),
|
||||
delete_all(LDeps, SSI, SI, LI, SF, SSF, HI, HF).
|
||||
|
||||
add_parents_to_heap([], _, H, H).
|
||||
add_parents_to_heap([P|Parents], V, H0, HF) :-
|
||||
add_to_heap(H0, P, V, HI), % if I put a HF here I get the debugger to loop
|
||||
add_parents_to_heap(Parents, V, HI, HF).
|
||||
|
||||
dump_vlist([], _, _, _).
|
||||
dump_vlist([V|Vs], I, CommandStream, Answer) :-
|
||||
I1 is I+1,
|
||||
clpbn:get_atts(V,[key(_)]),
|
||||
send_command(CommandStream, Answer, '~w = ~w;~n', ['$VAR'(I), I1]),
|
||||
put_atts(V, [topord(I)]),
|
||||
I1 is I+1,
|
||||
dump_vlist(Vs, I1, CommandStream, Answer).
|
||||
|
||||
write_deps(H, CommandStream, Answer) :-
|
||||
heap_to_list(H,L),
|
||||
write_list_deps(L, CommandStream, Answer).
|
||||
|
||||
write_list_deps([], _, _).
|
||||
write_list_deps([V-A|L], CommandStream, Answer) :-
|
||||
fetch_same_key(L, V, SK, LN),
|
||||
write_dep_relation([A|SK], V, CommandStream, Answer),
|
||||
write_list_deps(LN, CommandStream, Answer).
|
||||
|
||||
fetch_same_key([], _, [], []) :- !.
|
||||
fetch_same_key([V1-A|L], V, [A|SK], LN) :- V1 == V, !,
|
||||
fetch_same_key(L, V, SK, LN).
|
||||
fetch_same_key(L, _, [], L).
|
||||
|
||||
write_dep_relation([], _, _) :- !.
|
||||
write_dep_relation([V], D, CommandStream, Answer) :- !,
|
||||
get_atts(V, [topord(IV)]),
|
||||
get_atts(D, [topord(ID)]),
|
||||
send_command(CommandStream, Answer, "dag(~w,~w) = 1;~n", ['$VAR'(ID),'$VAR'(IV)]).
|
||||
write_dep_relation(Vs, D, CommandStream, Answer) :-
|
||||
get_atts(D, [topord(ID)]),
|
||||
my_format(CommandStream, "dag(~w,[",['$VAR'(ID)]),
|
||||
write_anc_list(Vs, start, CommandStream),
|
||||
send_command(CommandStream, Answer, "]) = 1;~n", []).
|
||||
|
||||
write_anc_list([], _, _).
|
||||
write_anc_list([V|Vs], start, CommandStream) :- !,
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "~w",['$VAR'(I)]),
|
||||
write_anc_list(Vs, cont, CommandStream).
|
||||
write_anc_list([V|Vs], cont, CommandStream) :-
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, " ~w",['$VAR'(I)]),
|
||||
write_anc_list(Vs, cont, CommandStream).
|
||||
|
||||
mknet(Vs, Key, Observables, CommandStream, Answer) :-
|
||||
mknet_all_discrete(Vs, Key, Observables, CommandStream, Answer).
|
||||
|
||||
|
||||
mknet_all_discrete(Vs, Key, Observables, CommandStream, Answer) :-
|
||||
send_command(CommandStream, Answer, "discrete_nodes = 1:~w;~n",['$VAR'(Key)]),
|
||||
my_format(CommandStream, "ns = [", []),
|
||||
reverse(Vs, RVs),
|
||||
send_var_sizes(RVs, CommandStream),
|
||||
send_command(CommandStream, Answer, "];~n", []),
|
||||
my_format(CommandStream, "onodes = [", []),
|
||||
dump_observables(Observables, start, CommandStream),
|
||||
send_command(CommandStream, Answer, "];~n", []),
|
||||
send_command(CommandStream, Answer, "bnet = mk_bnet(dag, ns, 'discrete', discrete_nodes, 'observed', onodes);~n", []).
|
||||
|
||||
send_var_sizes([V], CommandStream) :- !,
|
||||
clpbn:get_atts(V, [dist(D)]),
|
||||
dist_size(D, 1, Sz),
|
||||
my_format(CommandStream, "~w", [Sz]).
|
||||
send_var_sizes([V|Vs], CommandStream) :-
|
||||
clpbn:get_atts(V, [dist(D)]),
|
||||
dist_size(D, 1, Sz),
|
||||
my_format(CommandStream, "~w ", [Sz]),
|
||||
send_var_sizes(Vs, CommandStream).
|
||||
|
||||
|
||||
dist_size((_=>Vs), _, L) :- !,
|
||||
length(Vs,L).
|
||||
dist_size((_._=Vs), I0, If) :- !,
|
||||
length(Vs,L),
|
||||
If is I0+(L-1).
|
||||
dist_size((A;B), I0, If) :- !,
|
||||
dist_size(A, I0, I1),
|
||||
I2 is I1+1,
|
||||
dist_size(B, I2, If).
|
||||
dist_size(_, I, I).
|
||||
|
||||
|
||||
dump_observables([], _, _) :- !.
|
||||
dump_observables([Observable|Observables], start, CommandStream) :- !,
|
||||
get_atts(Observable, [topord(I)]),
|
||||
my_format(CommandStream, "~w",['$VAR'(I)]),
|
||||
dump_observables(Observables, mid, CommandStream).
|
||||
dump_observables([Observable|Observables], mid, CommandStream) :-
|
||||
get_atts(Observable, [topord(I)]),
|
||||
my_format(CommandStream, " ~w",['$VAR'(I)]),
|
||||
dump_observables(Observables, mid, CommandStream).
|
||||
|
||||
dump_cpds([], _, _).
|
||||
dump_cpds([V|Vs], CommandStream, Answer) :-
|
||||
clpbn:get_atts(V, [dist(D)]),
|
||||
dump_cpds(Vs, CommandStream, Answer),
|
||||
dump_dist(D, V, CommandStream, Answer).
|
||||
|
||||
%
|
||||
% this is a discrete distribution
|
||||
%
|
||||
dump_dist((average.Ss)=>Vs, V, CommandStream, Answer) :- !,
|
||||
vals_map(Vs, 1, Map),
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "bnet.CPD{~w} = deterministic_CPD(bnet, ~w, inline('round(mean([",['$VAR'(I),'$VAR'(I)]),
|
||||
put_atts(V, [map(Map)]),
|
||||
length(Ss, Len),
|
||||
dump_indices(0,Len,CommandStream),
|
||||
send_command(CommandStream, Answer, "]))'));~n",[]).
|
||||
dump_dist((sum.Ss)=>Vs, V, CommandStream, Answer) :- !,
|
||||
vals_map(Vs, 1, Map),
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "bnet.CPD{~w} = deterministic_CPD(bnet, ~w, inline('sum([",['$VAR'(I),'$VAR'(I)]),
|
||||
put_atts(V, [map(Map)]),
|
||||
length(Ss, Len),
|
||||
dump_indices(0,Len,CommandStream),
|
||||
send_command(CommandStream, Answer, "])'));~n",[]).
|
||||
dump_dist((normalised_average(N).Ss)=>Vs, V, CommandStream, Answer) :- !,
|
||||
vals_map(Vs, 1, Map),
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "bnet.CPD{~w} = deterministic_CPD(bnet, ~w, inline('round((sum([",['$VAR'(I),'$VAR'(I)]),
|
||||
put_atts(V, [map(Map)]),
|
||||
length(Ss, Len),
|
||||
dump_indices(0,Len,CommandStream),
|
||||
N2 is N//2,
|
||||
send_command(CommandStream, Answer, "])+~d)/~d)'));~n",[N2,N]).
|
||||
dump_dist(([H|T].Ss0)=>Vs, V, CommandStream, Answer) :- !,
|
||||
Ds = [H|T],
|
||||
vals_map(Vs, 1, Map),
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "bnet.CPD{~w} = tabular_CPD(bnet, ~w, [ ",['$VAR'(I),'$VAR'(I)]),
|
||||
put_atts(V, [map(Map)]),
|
||||
reverse([V|Ss0], Ss),
|
||||
get_numbers_for_vars(Ss, Ns),
|
||||
calculate_new_numbers(Ds,Ns,0,KDs0),
|
||||
keysort(KDs0,KDs),
|
||||
dump_elements(KDs, CommandStream),
|
||||
send_command(CommandStream, Answer, "]);~n",[]).
|
||||
dump_dist(([H|T]=>Vs), V, CommandStream, Answer) :-
|
||||
vals_map(Vs, 1, Map),
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "bnet.CPD{~w} = tabular_CPD(bnet, ~w, [ ",['$VAR'(I),'$VAR'(I)]),
|
||||
put_atts(V, [map(Map)]),
|
||||
dump_problist([H|T], CommandStream),
|
||||
send_command(CommandStream, Answer, "]);~n",[]).
|
||||
dump_dist((D1;D2), V, CommandStream, Answer) :-
|
||||
get_atts(V, [topord(I)]),
|
||||
my_format(CommandStream, "bnet.CPD{~w} = tabular_CPD(bnet, ~w, [ ",['$VAR'(I),'$VAR'(I)]),
|
||||
find_map((D1;D2), 1, _, Map, []),
|
||||
put_atts(V, [map(Map)]),
|
||||
dump_dlist((D1;D2), start, CommandStream),
|
||||
send_command(CommandStream, Answer, "]);~n",[]).
|
||||
|
||||
vals_map([], _, []).
|
||||
vals_map([V|Vs], I, [[V|I]|Map]) :-
|
||||
I1 is I+1,
|
||||
vals_map(Vs, I1, Map).
|
||||
|
||||
get_numbers_for_vars(Ss, Ns) :-
|
||||
numb_vars(Ss, 0, 1, VPs0),
|
||||
keysort(VPs0, VPs),
|
||||
compute_new_factors(VPs, 1, Int0),
|
||||
keysort(Int0, Int),
|
||||
select_factors(Int, [], Ns).
|
||||
|
||||
|
||||
numb_vars([], _, _, []).
|
||||
numb_vars([V|Vs], I, A0, [T-p(I,A0,L)|VPs]) :-
|
||||
get_atts(V, [map(Map),topord(T)]),
|
||||
length(Map,L),
|
||||
I1 is I+1,
|
||||
Ai is A0*L,
|
||||
numb_vars(Vs, I1, Ai, VPs).
|
||||
|
||||
compute_new_factors([], _, []).
|
||||
compute_new_factors([_-p(I,Siz,L)|VPs], Div, [I-f(Siz,Div)|Os]) :-
|
||||
NDiv is Div*L,
|
||||
compute_new_factors(VPs, NDiv, Os).
|
||||
|
||||
select_factors([], L, L).
|
||||
select_factors([_-Fac|Int], Ns0, Nsf) :-
|
||||
select_factors(Int, [Fac|Ns0], Nsf).
|
||||
|
||||
calculate_new_numbers([],_, _,[]).
|
||||
calculate_new_numbers([P|Ps], Ls, I0, [Pos-P|KDs]) :-
|
||||
compute_new_position(Ls, I0, 0, Pos),
|
||||
I is I0+1,
|
||||
calculate_new_numbers(Ps, Ls, I, KDs).
|
||||
|
||||
compute_new_position([], _, P, P).
|
||||
compute_new_position([f(Siz,Div)|Ls], I0, P0, Pf) :-
|
||||
A is I0 // Siz,
|
||||
I1 is I0 mod Siz,
|
||||
B is A*Div,
|
||||
Pi is P0+B,
|
||||
compute_new_position(Ls, I1, Pi, Pf).
|
||||
|
||||
dump_indices(Len,Len,_) :- !.
|
||||
dump_indices(I0,Len,CommandStream) :-
|
||||
I is I0+1,
|
||||
my_format(CommandStream, "x(~d) ",[I]),
|
||||
dump_indices(I,Len,CommandStream).
|
||||
|
||||
dump_elements([], _).
|
||||
dump_elements([_-P|KDs], CommandStream) :-
|
||||
my_format(CommandStream, "~w~n",[P]),
|
||||
dump_elements(KDs, CommandStream).
|
||||
|
||||
dump_problist([], _).
|
||||
dump_problist([P|KDs], CommandStream) :-
|
||||
my_format(CommandStream, "~w~n",[P]),
|
||||
dump_problist(KDs, CommandStream).
|
||||
|
||||
dump_dlist((D1;D2), Start, CommandStream) :- !,
|
||||
dump_dlist(D1, Start, CommandStream),
|
||||
dump_dlist(D2, mid, CommandStream).
|
||||
dump_dlist((_ = V), Pos, CommandStream) :- !,
|
||||
dump_dlist(V, Pos, CommandStream).
|
||||
dump_dlist((_ -> V), Pos, CommandStream) :- !,
|
||||
dump_dlist(V, Pos, CommandStream).
|
||||
dump_dlist(V, start, CommandStream) :- !,
|
||||
my_format(CommandStream, "~w~n",[V]).
|
||||
dump_dlist(V, mid, CommandStream) :-
|
||||
my_format(CommandStream, "~w~n",[V]).
|
||||
|
||||
find_map((D1;D2), I0, N, LF, L0) :- !,
|
||||
find_map(D1, I0, I, LF, LI),
|
||||
find_map(D2, I, N, LI, L0).
|
||||
find_map((M->_), I, I1, [[M|I]|L0], L0) :-
|
||||
I1 is I+1.
|
||||
|
||||
inf_engine(Vs, Key, CommandStream, Answer) :-
|
||||
send_command(CommandStream, Answer, "engine = jtree_inf_engine(bnet)~n", []),
|
||||
% send_command(CommandStream, Answer, "engine = var_elim_inf_engine(bnet)~n", []),
|
||||
send_command(CommandStream, Answer, "evidence = cell(1,~w)~n", ['$VAR'(Key)]),
|
||||
dump_evidence(Vs, CommandStream, Answer),
|
||||
send_command(CommandStream, Answer, "[engine, loglik] = enter_evidence(engine, evidence)~n",[]).
|
||||
|
||||
dump_evidence([], _, _).
|
||||
dump_evidence([V|Vs], CommandStream, Answer) :-
|
||||
clpbn:get_atts(V, [evidence(Ev)]), !,
|
||||
get_atts(V, [topord(I),map(M)]), !,
|
||||
follow_map(M,Ev,NEv),
|
||||
send_command(CommandStream, Answer, "evidence{~w} = ~w~n", ['$VAR'(I),NEv]),
|
||||
dump_evidence(Vs, CommandStream, Answer).
|
||||
dump_evidence([_|Vs], CommandStream, Answer) :-
|
||||
dump_evidence(Vs, CommandStream, Answer).
|
||||
|
||||
follow_map([[K|V]|_], K, V) :- !.
|
||||
follow_map([_|Map], K, V) :- !,
|
||||
follow_map(Map, K, V).
|
||||
|
||||
find_observables([], []).
|
||||
find_observables([Var|GVars], [Var|Observables]) :-
|
||||
clpbn:get_atts(Var, [dist(_)]), !,
|
||||
find_observables(GVars, Observables).
|
||||
find_observables([_|GVars], Observables) :-
|
||||
find_observables(GVars, Observables).
|
||||
|
||||
output_answer(Observables, CommandStream, Answer) :-
|
||||
split_by_cliques(Observables, Cliques),
|
||||
output_cliques(Cliques, CommandStream, Answer).
|
||||
|
||||
split_by_cliques([], []).
|
||||
split_by_cliques([V|Vs], Cliques) :-
|
||||
split_by_cliques(Vs, Cliques0),
|
||||
add_to_cliques(Cliques0, V, Cliques).
|
||||
|
||||
add_to_cliques([], V, [[V]]).
|
||||
add_to_cliques([Cl|L], V, [[V|Cl]|L]) :-
|
||||
in_clique(Cl,V), !.
|
||||
add_to_cliques([Cl|L], V, [Cl|LN]) :-
|
||||
add_to_cliques(L, V, LN).
|
||||
|
||||
in_clique([], _).
|
||||
in_clique([V1|L], V) :-
|
||||
child(V, V1), !,
|
||||
in_clique(L, V).
|
||||
in_clique([V1|L], V) :-
|
||||
child(V1, V),
|
||||
in_clique(L,V).
|
||||
|
||||
child(V,V1) :-
|
||||
clpbn:get_atts(V, [dist(T)]),
|
||||
term_variables(T,LVs),
|
||||
varmember(LVs, V1).
|
||||
|
||||
varmember([H|_], V1) :- H == V1, !.
|
||||
varmember([_|L], V1) :-
|
||||
varmember(L, V1).
|
||||
|
||||
output_cliques([], _, _).
|
||||
output_cliques([Observables|Cliques], CommandStream, Answer) :-
|
||||
marginal(Observables, CommandStream, Answer),
|
||||
read_answer(Answer, -1, MargDis),
|
||||
parse_observables(Observables, MargDis),
|
||||
output_cliques(Cliques, CommandStream, Answer).
|
||||
|
||||
marginal(Margs, CommandStream, Answer) :-
|
||||
my_format(CommandStream, "marg = marginal_nodes(engine, ", []),
|
||||
write_margs(Margs, CommandStream),
|
||||
send_command(CommandStream, Answer, ")~n", []),
|
||||
my_format(CommandStream, "p = marg.T~n", []).
|
||||
|
||||
|
||||
write_margs([], _) :- !.
|
||||
write_margs([V], CommandStream) :- !,
|
||||
get_atts(V, [topord(IV)]),
|
||||
my_format(CommandStream, "~w", ['$VAR'(IV)]).
|
||||
write_margs(Vs, CommandStream) :-
|
||||
my_format(CommandStream, "[", []),
|
||||
write_anc_list(Vs, start, CommandStream),
|
||||
my_format(CommandStream, "]", []).
|
||||
|
||||
|
||||
|
||||
read_answer(Answer, C0, [C1|L]) :-
|
||||
get0(Answer, C1),
|
||||
put(user_error, C1),
|
||||
( (( C0 = 10 ; C0 = 85) ,C1 = 62) ->
|
||||
L = []
|
||||
;
|
||||
read_answer(Answer, C1, L)
|
||||
).
|
||||
|
||||
wait_for_matlab_prompt(Answer) :-
|
||||
fetch_prompt(Answer, -1).
|
||||
|
||||
fetch_prompt(Answer, C0) :-
|
||||
get0(Answer, C1),
|
||||
put(user_error, C1),
|
||||
( ((C0 = 62 ; C0 = 85) ,C1 = 62) ->
|
||||
true
|
||||
;
|
||||
fetch_prompt(Answer, C1)
|
||||
).
|
||||
|
||||
send_command(OStream, IStream, String, Args) :-
|
||||
my_format(OStream, String, Args),
|
||||
wait_for_matlab_prompt(IStream).
|
||||
|
||||
parse_observables([Obs], MargDis) :- !,
|
||||
get_atts(Obs, [map(Map)]),
|
||||
skip_to_eq(MargDis, L1),
|
||||
fetch_map(Map, L1, Out),
|
||||
clpbn:get_atts(Obs, [key(Key)]),
|
||||
Obs = {Key:Out}.
|
||||
parse_observables(LObs, MargDis) :-
|
||||
joint_map(LObs, Map),
|
||||
skip_to_eq(MargDis, L1),
|
||||
fetch_maps(Map, L1, Out),
|
||||
bind_lobs(LObs, Key, Key, Out).
|
||||
|
||||
fetch_map([[Name|_]], L, (Name -> P)) :- !,
|
||||
get_next_float(L, P, _).
|
||||
fetch_map([[Name|_]|Names], L0, (Name->P ; Rest)) :-
|
||||
get_next_float(L0, P, Lf),
|
||||
fetch_map(Names, Lf, Rest).
|
||||
|
||||
get_next_float(L0, P, Lf) :-
|
||||
skip_spaces(L0, Li),
|
||||
fetch_float(Li,Ls, Lf),
|
||||
number_codes(P, Ls).
|
||||
|
||||
skip_to_eq([61|L], L) :- !.
|
||||
skip_to_eq([_|L], LF) :-
|
||||
skip_to_eq(L, LF).
|
||||
|
||||
skip_spaces([10|L], LF) :- !, skip_spaces(L, LF).
|
||||
skip_spaces([32|L], LF) :- !, skip_spaces(L, LF).
|
||||
skip_spaces(L, L).
|
||||
|
||||
fetch_float([10|L], [], L) :- !.
|
||||
fetch_float([32|L], [], L) :- !.
|
||||
fetch_float([C|Li], [C|Ls], Lf) :-
|
||||
fetch_float(Li, Ls, Lf).
|
||||
|
||||
joint_map(Vars,FMap) :-
|
||||
fetch_maps(Vars,Maps),
|
||||
join_maps(Maps, FMap).
|
||||
|
||||
fetch_maps([], []).
|
||||
fetch_maps([V|Vs], [M|Ms]) :-
|
||||
get_atts(V, [map(M)]),
|
||||
fetch_maps(Vs, Ms).
|
||||
|
||||
join_maps([], [[]]).
|
||||
join_maps([Map|Maps], Rf) :-
|
||||
join_maps(Maps, R1),
|
||||
add(Map, R1, Rf).
|
||||
|
||||
add([], _, []).
|
||||
add([[Name|_]|R], R1, RsF) :-
|
||||
add_head(R1, Name, RsF, Rs0),
|
||||
add(R, R1, Rs0).
|
||||
|
||||
add_head([], _, Rs, Rs).
|
||||
add_head([H|L], A, [[A|H]|Rs], Rs0) :-
|
||||
add_head(L, A, Rs, Rs0).
|
||||
|
||||
|
||||
fetch_maps([Name1], L, (Name2 -> P)) :- !,
|
||||
generate_name(Name1, Name2),
|
||||
get_next_float(L, P, _).
|
||||
fetch_maps([Name1|Names], L0, (Name2->P ; Rest)) :-
|
||||
generate_name(Name1, Name2),
|
||||
get_next_float(L0, P, Lf),
|
||||
fetch_maps(Names, Lf, Rest).
|
||||
|
||||
generate_name([Name], Name) :- !.
|
||||
generate_name([Name|Names], (Name,New)) :-
|
||||
generate_name(Names, New).
|
||||
|
||||
bind_lobs([Obs], Key, FullKey, Out) :- !,
|
||||
clpbn:get_atts(Obs, [key(Key)]),
|
||||
Obs = {FullKey:Out}.
|
||||
bind_lobs([Obs|Lobs], (Key,Rest), FullKey, Out) :-
|
||||
clpbn:get_atts(Obs, [key(Key)]),
|
||||
Obs = {FullKey:Out},
|
||||
bind_lobs(Lobs, Rest, FullKey, Out).
|
||||
|
||||
|
||||
/* cartesian product
|
||||
|
||||
cart([], [[]]).
|
||||
cart([L|R], Rf) :-
|
||||
cart(R, R1),
|
||||
add(L, R1, Rf).
|
||||
|
||||
add([], _, []).
|
||||
add([A|R], R1, RsF) :-
|
||||
add_head(R1, A, RsF, Rs0),
|
||||
add(R, R1, Rs0).
|
||||
|
||||
add_head([], _, Rs, Rs).
|
||||
add_head([H|L], A, [[A|H]|Rs], Rs0) :-
|
||||
add_head(L, A, Rs, Rs0).
|
||||
|
||||
*/
|
||||
|
||||
my_format(Stream, String, Args) :-
|
||||
format(user_error, String, Args),
|
||||
format(Stream, String, Args).
|
||||
|
25
CLPBN/clpbn/evidence.yap
Normal file
25
CLPBN/clpbn/evidence.yap
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
:- module(evidence, [add_to_evidence/1,
|
||||
execute_pre_evidence/0
|
||||
]).
|
||||
|
||||
% declare some new evidence.
|
||||
|
||||
add_to_evidence(G2) :-
|
||||
recordzifnot('$evidence',G2,_),
|
||||
fail.
|
||||
add_to_evidence(_).
|
||||
|
||||
% use it at query evaluation time.
|
||||
|
||||
execute_pre_evidence :-
|
||||
findall(G, recorded('$evidence', G, _), LGs),
|
||||
execute_all(LGs).
|
||||
|
||||
execute_all([]).
|
||||
execute_all([M:G|Gs]) :-
|
||||
call(M:G),
|
||||
execute_all(Gs).
|
||||
|
||||
|
||||
|
495
CLPBN/clpbn/vel.yap
Normal file
495
CLPBN/clpbn/vel.yap
Normal file
@ -0,0 +1,495 @@
|
||||
/***********************************
|
||||
|
||||
Variable Elimination in Prolog
|
||||
|
||||
How to do it
|
||||
|
||||
|
||||
Three steps:
|
||||
build the graph:
|
||||
- for all variables, find out
|
||||
all tables they connect to;
|
||||
multiply their size
|
||||
order by size
|
||||
|
||||
*********************************/
|
||||
|
||||
:- module(vel, [vel/3,
|
||||
check_if_vel_done/1]).
|
||||
|
||||
:- attribute size/1, posterior/4, all_diffs/1.
|
||||
|
||||
:- use_module(library(ordsets), [ord_union/3
|
||||
]).
|
||||
|
||||
:- use_module(library(lists),
|
||||
[
|
||||
append/3,
|
||||
member/2
|
||||
]).
|
||||
|
||||
check_if_vel_done(Var) :-
|
||||
get_atts(Var, [size(_)]), !.
|
||||
|
||||
vel(LVs,Vs0,AllDiffs) :-
|
||||
check_for_hidden_vars(Vs0, Vs0, Vs1),
|
||||
sort(Vs1,Vs),
|
||||
find_all_clpbn_vars(Vs, LV0, Tables0),
|
||||
find_all_table_deps(Tables0, LV0),
|
||||
process(LV0, LVs, tab(Dist,_,_)),
|
||||
Dist =.. [_|Ps0],
|
||||
normalise(Ps0,Ps),
|
||||
bind_vals(LVs,Ps,AllDiffs).
|
||||
|
||||
%
|
||||
% It may happen that variables from a previous query may still be around.
|
||||
% and be used in the next evaluation, so we cannot trust the list of *new*
|
||||
% variables.
|
||||
%
|
||||
check_for_hidden_vars([], _, []).
|
||||
check_for_hidden_vars([V|Vs], AllVs0, [V|NVs]) :-
|
||||
check_for_extra_variables(V,AllVs0, AllVs, Vs, IVs),
|
||||
check_for_hidden_vars(IVs, AllVs, NVs).
|
||||
|
||||
check_for_extra_variables(V,AllVs0, AllVs, Vs, IVs) :-
|
||||
clpbn:get_atts(V, [dist(([_|_].[V1|LV])=>_)]), !,
|
||||
add_old_variables([V1|LV], AllVs0, AllVs, Vs, IVs).
|
||||
check_for_extra_variables(_,AllVs, AllVs, Vs, Vs).
|
||||
|
||||
add_old_variables([], AllVs, AllVs, Vs, Vs).
|
||||
add_old_variables([V1|LV], AllVs0, AllVs, Vs, IVs) :-
|
||||
not_var_member(AllVs0, V1), !,
|
||||
add_old_variables(LV, [V1|AllVs0], AllVs, [V1|Vs], IVs).
|
||||
add_old_variables([_|LV], AllVs0, AllVs, Vs, IVs) :-
|
||||
add_old_variables(LV, AllVs0, AllVs, Vs, IVs).
|
||||
|
||||
find_all_clpbn_vars([], [], []) :- !.
|
||||
find_all_clpbn_vars([V|Vs], [var(V,I,Sz,Vals,_,_)|LV], [table(I,Table,Deps,Sizes)|Tables]) :-
|
||||
var_with_deps(V, Table, Deps, Sizes, Vals), !,
|
||||
get_dist_els(V,Sz),
|
||||
find_all_clpbn_vars(Vs, LV, Tables).
|
||||
|
||||
var_with_deps(V, Table, Deps, Sizes, Vals) :-
|
||||
clpbn:get_atts(V, [dist(D=>Vals)]),
|
||||
from_dist_get(D,Vals,OTable,VDeps),
|
||||
reorder_table([V|VDeps],Sizes,OTable,Deps,Table).
|
||||
|
||||
from_dist_get(average.Vs0,Vals,Lf,Vs) :- !,
|
||||
handle_average(Vs0,Vals,Lf,Vs).
|
||||
from_dist_get(sum.Vs0,Vals,Lf,Vs) :- !,
|
||||
handle_sum(Vs0, Vals, Lf, Vs).
|
||||
from_dist_get(normalised_average(Max).Vs0,Vals,Lf,Vs) :- !,
|
||||
handle_normalised_average(Max,Vs0,Vals,Lf,Vs).
|
||||
from_dist_get(([A|B].[C|D]),_,[A|B],[C|D]) :- !.
|
||||
from_dist_get([A|B],_,[A|B],[]).
|
||||
|
||||
handle_average(Vs0,Vals,Lf,Vs) :-
|
||||
sort(Vs0,Vs),
|
||||
generate_indices(Vals,Inds,0,Av),
|
||||
combine_all(Vs, Inds, Cs),
|
||||
length(Vs, Max),
|
||||
average_possible_cases(0,Av,Max,Cs,Lf).
|
||||
|
||||
handle_sum(Vs0, Vals, Lf, Vs) :-
|
||||
sort(Vs0,Vs),
|
||||
length(Vals,Sz),
|
||||
combine_all(Vs, Cs),
|
||||
sum_possible_cases(0,Sz,Cs,Lf).
|
||||
|
||||
handle_normalised_average(Max,Vs0,Vals,Lf,Vs) :-
|
||||
sort(Vs0,Vs),
|
||||
generate_indices(Vals,_,0,Sz),
|
||||
combine_all(Vs, Cs),
|
||||
average_possible_cases(0,Sz,Max,Cs,Lf).
|
||||
|
||||
|
||||
generate_indices([],[],Av,Av).
|
||||
generate_indices([_|Ls],[I|Inds],I,Av) :-
|
||||
I1 is I+1,
|
||||
generate_indices(Ls,Inds,I1,Av).
|
||||
|
||||
|
||||
combine_all([], [[]]).
|
||||
combine_all([V|LV], Cs) :-
|
||||
combine_all(LV, Cs0),
|
||||
get_dist_els(V,Sz),
|
||||
generate_indices(0, Sz, Vals),
|
||||
add_vals(Vals, Cs0, Cs).
|
||||
|
||||
combine_all([], _, [[]]).
|
||||
combine_all([_|LV], Vals, Cs) :-
|
||||
combine_all(LV, Vals, Cs0),
|
||||
add_vals(Vals, Cs0, Cs).
|
||||
|
||||
generate_indices(Sz,Sz,[]) :- !.
|
||||
generate_indices(I0,Sz,[I0|Vals]) :-
|
||||
I is I0+1,
|
||||
generate_indices(I,Sz,Vals).
|
||||
|
||||
|
||||
add_vals([], _, []).
|
||||
add_vals([V|Vs], Cs0, Csf) :-
|
||||
add_vals(Vs, Cs0, Cs),
|
||||
add_val_to_cases(Cs0, V, Cs, Csf).
|
||||
|
||||
add_val_to_cases([], _, Cs, Cs).
|
||||
add_val_to_cases([C|Cs], V, Cs0, [[V|C]|Csf]) :-
|
||||
add_val_to_cases(Cs, V, Cs0, Csf).
|
||||
|
||||
sum_all([],N,N).
|
||||
sum_all([C|Cs],N0,N) :-
|
||||
X is C+N0,
|
||||
sum_all(Cs,X,N).
|
||||
|
||||
average_possible_cases(Av,Av,_,_,[]) :- !.
|
||||
average_possible_cases(I,Av,Max,Cs,Lf) :-
|
||||
average_cases2(Cs,I,Max,Lf,L0),
|
||||
I1 is I+1,
|
||||
average_possible_cases(I1,Av,Max,Cs,L0).
|
||||
|
||||
average_cases2([], _, _, L, L).
|
||||
average_cases2([C|Cs], I, Av, [P|Lf], L0) :-
|
||||
calculate_avg_prob(C, I, Av, P),
|
||||
average_cases2(Cs, I, Av, Lf, L0).
|
||||
|
||||
calculate_avg_prob(C, I, Av, 1.0) :-
|
||||
sum_all(C,0,N),
|
||||
I =:= integer(round(N/Av)), !.
|
||||
calculate_avg_prob(_, _, _, 0.0).
|
||||
|
||||
sum_possible_cases(Av,Av,_,[]) :- !.
|
||||
sum_possible_cases(I,Av,Cs,Lf) :-
|
||||
sum_cases2(Cs,I,Lf,L0),
|
||||
I1 is I+1,
|
||||
sum_possible_cases(I1,Av,Cs,L0).
|
||||
|
||||
sum_cases2([], _, L, L).
|
||||
sum_cases2([C|Cs], I, [P|Lf], L0) :-
|
||||
calculate_sum_prob(C, I, P),
|
||||
sum_cases2(Cs, I, Lf, L0).
|
||||
|
||||
calculate_sum_prob(C, I, 1.0) :-
|
||||
sum_all(C,0,N),
|
||||
I =:= N, !.
|
||||
calculate_sum_prob(_, _, 0.0).
|
||||
|
||||
|
||||
get_sizes([], []).
|
||||
get_sizes([V|Deps], [Sz|Sizes]) :-
|
||||
get_dist_els(V,Sz),
|
||||
get_sizes(Deps, Sizes).
|
||||
|
||||
get_dist_els(V,Sz) :-
|
||||
get_atts(V, [size(Sz)]), !.
|
||||
get_dist_els(V,Sz) :-
|
||||
clpbn:get_atts(V, [dist(_=>Vals)]), !,
|
||||
length(Vals,Sz),
|
||||
put_atts(V, [size(Sz)]).
|
||||
|
||||
reorder_table(Vs0, Sizes, T0, Vs, TF) :-
|
||||
get_sizes(Vs0, Szs),
|
||||
numb_vars(Vs0, Szs, _, VPs0, VLs0),
|
||||
keysort(VLs0, VLs),
|
||||
compute_new_factors(VLs, _, Vs, Sizes),
|
||||
get_factors(VLs0,Fs),
|
||||
length(T0,L),
|
||||
functor(TF,t,L),
|
||||
copy_to_new_array(T0, 0, VPs0, Fs, TF).
|
||||
|
||||
numb_vars([], [], 1, [], []).
|
||||
numb_vars([V|Vs], [L|Ls], A0, [Ai|VPs], [V-(L,_)|VLs]) :-
|
||||
numb_vars(Vs, Ls, Ai, VPs, VLs),
|
||||
A0 is Ai*L.
|
||||
|
||||
compute_new_factors([], 1, [], []).
|
||||
compute_new_factors([V-(L,F)|VLs], NF, [V|Vs], [L|Szs]) :-
|
||||
compute_new_factors(VLs, F, Vs, Szs),
|
||||
NF is F*L.
|
||||
|
||||
get_factors([],[]).
|
||||
get_factors([_-(_,F)|VLs0],[F|Fs]) :-
|
||||
get_factors(VLs0,Fs).
|
||||
|
||||
copy_to_new_array([], _, _, _, _).
|
||||
copy_to_new_array([P|Ps], I, F0s, Fs, S) :-
|
||||
convert_factor(F0s, Fs, I, N),
|
||||
I1 is I+1,
|
||||
N1 is N+1,
|
||||
arg(N1,S,P),
|
||||
copy_to_new_array(Ps, I1, F0s, Fs, S).
|
||||
|
||||
convert_factor([], [], _, 0).
|
||||
convert_factor([F0|F0s], [F|Fs], I, OUT) :-
|
||||
X is I//F0,
|
||||
NI is I mod F0,
|
||||
NEXT is F*X,
|
||||
convert_factor(F0s, Fs, NI, OUT1),
|
||||
OUT is OUT1+NEXT.
|
||||
|
||||
|
||||
find_all_table_deps(Tables0, LV) :-
|
||||
find_dep_graph(Tables0, DepGraph0),
|
||||
sort(DepGraph0, DepGraph),
|
||||
add_table_deps_to_variables(LV, DepGraph).
|
||||
|
||||
|
||||
find_dep_graph([], []).
|
||||
find_dep_graph([table(I,Tab,Deps,Sizes)|Tables], DepGraph) :-
|
||||
add_table_deps(Deps, I, Deps, Tab, Sizes, DepGraph0, DepGraph),
|
||||
find_dep_graph(Tables, DepGraph0).
|
||||
|
||||
add_table_deps([], _, _, _, _, DepGraph, DepGraph).
|
||||
add_table_deps([V|Deps], I, Deps0, Table, Sizes, DepGraph0, [V-tab(Table,Deps0,Sizes)|DepGraph]) :-
|
||||
add_table_deps(Deps, I, Deps0, Table, Sizes, DepGraph0, DepGraph).
|
||||
|
||||
add_table_deps_to_variables([], []).
|
||||
add_table_deps_to_variables([var(V,_,_,_,Deps,K)|LV], DepGraph) :-
|
||||
steal_deps_for_variable(DepGraph, V, NDepGraph, Deps),
|
||||
compute_size(Deps,[],K),
|
||||
add_table_deps_to_variables(LV, NDepGraph).
|
||||
|
||||
steal_deps_for_variable([V-Info|DepGraph], V0, NDepGraph, [Info|Deps]) :-
|
||||
V == V0, !,
|
||||
steal_deps_for_variable(DepGraph, V0, NDepGraph, Deps).
|
||||
steal_deps_for_variable(DepGraph, _, DepGraph, []).
|
||||
|
||||
compute_size([],Vs,K) :-
|
||||
% use sizes now
|
||||
length(Vs,K).
|
||||
% multiply_sizes(Vs,1,K).
|
||||
compute_size([tab(_,Vs,_)|Tabs],Vs0,K) :-
|
||||
ord_union(Vs,Vs0,VsI),
|
||||
compute_size(Tabs,VsI,K).
|
||||
|
||||
multiply_sizes([],K,K).
|
||||
multiply_sizes([V|Vs],K0,K) :-
|
||||
get_dist_els(V, Sz),
|
||||
KI is K0*Sz,
|
||||
multiply_sizes(Vs,KI,K).
|
||||
|
||||
process(LV0, InputVs, Out) :-
|
||||
find_best(LV0, V0, 10000, V, WorkTables, LVI, InputVs),
|
||||
V \== V0, !,
|
||||
multiply_tables(WorkTables, Table),
|
||||
propagate_evidence(V, Evs),
|
||||
project(V,Table,NewTable,Evs),
|
||||
include(LVI,NewTable,V,LV2),
|
||||
process(LV2, InputVs, Out).
|
||||
process(LV0, _, Out) :-
|
||||
fetch_tables(LV0, WorkTables),
|
||||
multiply_tables(WorkTables, Out).
|
||||
|
||||
find_best([], V, _, V, _, [], _).
|
||||
find_best([var(V,I,Sz,Vals,Deps,K)|LV], _, Threshold, VF, NWorktables, LVF, Inputs) :-
|
||||
K < Threshold,
|
||||
not_var_member(Inputs, V), !,
|
||||
find_best(LV, V, K, VF, WorkTables,LV0, Inputs),
|
||||
(V == VF ->
|
||||
LVF = LV0, Deps = NWorktables
|
||||
;
|
||||
LVF = [var(V,I,Sz,Vals,Deps,K)|LV0], WorkTables = NWorktables
|
||||
).
|
||||
find_best([V|LV], V0, Threshold, VF, WorkTables, [V|LVF], Inputs) :-
|
||||
find_best(LV, V0, Threshold, VF, WorkTables, LVF, Inputs).
|
||||
|
||||
multiply_tables([Table], Table) :- !.
|
||||
multiply_tables([tab(Tab1,Deps1,Szs1), tab(Tab2,Deps2,Sz2)| Tables], Out) :-
|
||||
multiply_table(Tab1, Deps1, Szs1, Tab2, Deps2, Sz2, NTab, NDeps, NSz),
|
||||
multiply_tables([tab(NTab,NDeps,NSz)| Tables], Out).
|
||||
|
||||
|
||||
propagate_evidence(V, Evs) :-
|
||||
clpbn:get_atts(V, [evidence(Ev),dist(_=>Out)]), !,
|
||||
generate_szs_with_evidence(Out,Ev,Evs).
|
||||
propagate_evidence(_, _).
|
||||
|
||||
generate_szs_with_evidence([],_,[]).
|
||||
generate_szs_with_evidence([Ev|Out],Ev,[ok|Evs]) :- !,
|
||||
generate_szs_with_evidence(Out,Ev,Evs).
|
||||
generate_szs_with_evidence([_|Out],Ev,[not_ok|Evs]) :-
|
||||
generate_szs_with_evidence(Out,Ev,Evs).
|
||||
|
||||
|
||||
fetch_tables([], []).
|
||||
fetch_tables([var(_,_,_,_,Deps,_)|LV0], Tables) :-
|
||||
append(Deps,Tables0,Tables),
|
||||
fetch_tables(LV0, Tables0).
|
||||
|
||||
not_var_member([], _).
|
||||
not_var_member([V1|Vs], V) :- V1 \== V,
|
||||
not_var_member(Vs, V).
|
||||
|
||||
multiply_table(Tab1, Deps1, Szs1, Tab2, Deps2, Szs2, NTab, NDeps, NSzs) :-
|
||||
deps_union(Deps1,Szs1,Fs10,Deps2,Szs2,Fs20,NDeps,NSzs),
|
||||
factors(NSzs, Fs, Total),
|
||||
factors(Fs10, Fs1, _),
|
||||
factors(Fs20, Fs2, _),
|
||||
elements(0, Total, Fs, Fs1, Fs2, Tab1, Tab2, LTab),
|
||||
NTab =.. [t|LTab].
|
||||
|
||||
deps_union([],[],[],[],[],[],[],[]) :- !.
|
||||
deps_union([],[],Fs1,[V2|Deps2],[Sz|Szs2],[Sz|Szs2],[V2|Deps2],[Sz|Szs2]) :- !,
|
||||
mk_zeros([Sz|Szs2],Fs1).
|
||||
deps_union([V1|Deps1],[Sz|Szs1],[Sz|Szs1],[],[],Fs2,[V1|Deps1],[Sz|Szs1]) :- !,
|
||||
mk_zeros([Sz|Szs1],Fs2).
|
||||
deps_union([V1|Deps1],[Sz|Szs1],[Sz|Fs1],[V2|Deps2],[Sz|Szs2],[Sz|Fs2],[V1|NDeps],[Sz|NSzs]) :- V1 == V2, !,
|
||||
deps_union(Deps1,Szs1,Fs1,Deps2,Szs2,Fs2,NDeps,NSzs).
|
||||
deps_union([V1|Deps1],[Sz1|Szs1],[Sz1|Fs1],[V2|Deps2],Szs2,[0|Fs2],[V1|NDeps],[Sz1|NSzs]) :- V1 @< V2, !,
|
||||
deps_union(Deps1,Szs1,Fs1,[V2|Deps2],Szs2,Fs2,NDeps,NSzs).
|
||||
deps_union([V1|Deps1],Szs1,[0|Fs1],[V2|Deps2],[Sz|Szs2],[Sz|Fs2],[V2|NDeps],[Sz|NSzs]) :-
|
||||
deps_union([V1|Deps1],Szs1,Fs1,Deps2,Szs2,Fs2,NDeps,NSzs).
|
||||
|
||||
mk_zeros([],[]).
|
||||
mk_zeros([_|Szs],[0|Fs]) :-
|
||||
mk_zeros(Szs,Fs).
|
||||
|
||||
|
||||
factors([], [], 1).
|
||||
factors([0|Ls], [0|NLs], Prod) :- !,
|
||||
factors(Ls, NLs, Prod).
|
||||
factors([N|Ls], [Prod0|NLs], Prod) :-
|
||||
factors(Ls, NLs, Prod0),
|
||||
Prod is Prod0*N.
|
||||
|
||||
elements(Total, Total, _, _, _, _, _, []) :- !.
|
||||
elements(I, Total, Fs, Fs1, Fs2, Tab1, Tab2, [El|Els]) :-
|
||||
element(Fs, I, 1, Fs1, 1, Fs2, Tab1, Tab2, El),
|
||||
I1 is I+1,
|
||||
elements(I1, Total, Fs, Fs1, Fs2, Tab1, Tab2, Els).
|
||||
|
||||
element([], _, P1, [], P2, [], Tab1, Tab2, El) :-
|
||||
arg(P1, Tab1, El1),
|
||||
arg(P2, Tab2, El2),
|
||||
El is El1*El2.
|
||||
element([F|Fs], I, P1, [F1|Fs1], P2, [F2|Fs2], Tab1, Tab2, El) :-
|
||||
FF is I // F,
|
||||
NP1 is P1+F1*FF,
|
||||
NP2 is P2+F2*FF,
|
||||
NI is I mod F,
|
||||
element(Fs, NI, NP1, Fs1, NP2, Fs2, Tab1, Tab2, El).
|
||||
|
||||
%
|
||||
project(V,tab(Table,Deps,Szs),tab(NewTable,NDeps,NSzs),Evs) :-
|
||||
functor(Table,_,Max),
|
||||
find_projection_factor(Deps, V, NDeps, Szs, NSzs, F, Sz),
|
||||
OLoop is Max//(Sz*F),
|
||||
project_outer_loop(0,OLoop,F,Sz,Table,Evs,NTabl),
|
||||
NewTable =.. [t|NTabl].
|
||||
|
||||
find_projection_factor([V|Deps], V1, Deps, [Sz|Szs], Szs, F, Sz) :-
|
||||
V == V1, !,
|
||||
mult(Szs, 1, F).
|
||||
find_projection_factor([V|Deps], V1, [V|NDeps], [Sz|Szs], [Sz|NSzs], F, NSz) :-
|
||||
find_projection_factor(Deps, V1, NDeps, Szs, NSzs, F, NSz).
|
||||
|
||||
mult([], F, F).
|
||||
mult([Sz|Szs], Sz0, F) :-
|
||||
SzI is Sz0*Sz,
|
||||
mult(Szs, SzI, F).
|
||||
|
||||
project_outer_loop(OLoop,OLoop,_,_,_,_,[]) :- !.
|
||||
project_outer_loop(I,OLoop,F,Sz,Table,Evs,NTabl) :-
|
||||
Base is I*Sz*F,
|
||||
project_mid_loop(0,F,Base,Sz,Table,Evs,NTabl,NTabl0),
|
||||
I1 is I+1,
|
||||
project_outer_loop(I1,OLoop,F,Sz,Table,Evs,NTabl0).
|
||||
|
||||
project_mid_loop(F,F,_,_,_,_,NTabl,NTabl) :- !.
|
||||
project_mid_loop(I,F,Base,Sz,Table,Evs,[Ent|NTablF],NTabl0) :-
|
||||
I1 is I+1,
|
||||
NBase is I+Base,
|
||||
project_inner_loop(0,Sz,Evs,NBase,F,Table,0.0,Ent),
|
||||
project_mid_loop(I1,F,Base,Sz,Table,Evs,NTablF,NTabl0).
|
||||
|
||||
project_inner_loop(Sz,Sz,[],_,_,_,Ent,Ent) :- !.
|
||||
project_inner_loop(I,Sz,[ok|Evs],NBase,F,Table,Ent0,Ent) :- !,
|
||||
I1 is I+1,
|
||||
Pos is NBase+I*F+1,
|
||||
arg(Pos,Table,E1),
|
||||
Ent1 is E1+Ent0,
|
||||
project_inner_loop(I1,Sz,Evs,NBase,F,Table,Ent1,Ent).
|
||||
project_inner_loop(I,Sz,[_|Evs],NBase,F,Table,Ent0,Ent) :- !,
|
||||
I1 is I+1,
|
||||
project_inner_loop(I1,Sz,Evs,NBase,F,Table,Ent0,Ent).
|
||||
|
||||
|
||||
include([],_,_,[]).
|
||||
include([var(V,P,VSz,D,Tabs,Est)|LV],tab(T,Vs,Sz),V1,[var(V,P,VSz,D,Tabs,Est)|NLV]) :-
|
||||
not_var_member(Vs,V), !,
|
||||
include(LV,tab(T,Vs,Sz),V1,NLV).
|
||||
include([var(V,P,VSz,D,Tabs,_)|LV],Table,NV,[var(V,P,VSz,D,NTabs,NEst)|NLV]) :-
|
||||
update_tables(Tabs,NTabs,Table,NV,[],NEst),
|
||||
include(LV,Table,NV,NLV).
|
||||
|
||||
update_tables([],[Table],Table,_,AVs,NS) :-
|
||||
Table = tab(_,Vs,_),
|
||||
ord_union(Vs,AVs,TVs),
|
||||
length(TVs,NS).
|
||||
update_tables([tab(Tab0,Vs,Sz)|Tabs],[tab(Tab0,Vs,Sz)|NTabs],Table,V,AVs0,NS) :-
|
||||
not_var_member(Vs,V), !,
|
||||
ord_union(Vs,AVs0,AVsI),
|
||||
update_tables(Tabs,NTabs,Table,V,AVsI,NS).
|
||||
update_tables([_|Tabs],NTabs,Table,V,AVs0,NS) :-
|
||||
update_tables(Tabs,NTabs,Table,V,AVs0,NS).
|
||||
|
||||
bind_vals([],_,_) :- !.
|
||||
% simple case, we want a distribution on a single variable.
|
||||
%bind_vals([V],Ps) :- !,
|
||||
% clpbn:get_atts(V, [dist(_=>Vals)]),
|
||||
% put_atts(V, posterior([V], Vals, Ps)).
|
||||
% complex case, we want a joint distribution, do it on a leader.
|
||||
% should split on cliques ?
|
||||
bind_vals(Vs,Ps,AllDiffs) :-
|
||||
get_all_combs(Vs, Vals),
|
||||
Vs = [V|_],
|
||||
put_atts(V, posterior(Vs, Vals, Ps,AllDiffs)).
|
||||
|
||||
get_all_combs(Vs, Vals) :-
|
||||
get_all_doms(Vs,Ds),
|
||||
findall(L,ms(Ds,L),Vals).
|
||||
|
||||
get_all_doms([], []).
|
||||
get_all_doms([V|Vs], [D|Ds]) :-
|
||||
clpbn:get_atts(V, [dist(_=>D)]),
|
||||
get_all_doms(Vs, Ds).
|
||||
|
||||
ms([], []).
|
||||
ms([H|L], [El|Els]) :-
|
||||
member(El,H),
|
||||
ms(L, Els).
|
||||
|
||||
normalise(Ps0,Ps) :-
|
||||
add_all(Ps0,0.0,Sum),
|
||||
divide_by_sum(Ps0,Sum,Ps).
|
||||
|
||||
add_all([],Sum,Sum).
|
||||
add_all([P|Ps0],Sum0,Sum) :-
|
||||
SumI is Sum0+P,
|
||||
add_all(Ps0,SumI,Sum).
|
||||
|
||||
divide_by_sum([],_,[]).
|
||||
divide_by_sum([P|Ps0],Sum,[PN|Ps]) :-
|
||||
PN is P/Sum,
|
||||
divide_by_sum(Ps0,Sum,Ps).
|
||||
|
||||
attribute_goal(V, G) :-
|
||||
get_atts(V, [posterior(Vs,Vals,Ps,AllDiffs)]),
|
||||
massage_out(Vs, Vals, Ps, G, AllDiffs).
|
||||
|
||||
massage_out(Vs, [D], [P], p(CEqs)=P, AllDiffs) :- !,
|
||||
gen_eqs(Vs,D,Eqs),
|
||||
add_alldiffs(AllDiffs,Eqs,CEqs).
|
||||
massage_out(Vs, [D|Ds], [P|Ps], (p(CEqs)=P,G) , AllDiffs) :-
|
||||
gen_eqs(Vs,D,Eqs),
|
||||
add_alldiffs(AllDiffs,Eqs,CEqs),
|
||||
massage_out(Vs, Ds, Ps, G, AllDiffs).
|
||||
|
||||
gen_eqs([V], [D], (V=D)) :- !.
|
||||
gen_eqs([V], D, (V=D)) :- !.
|
||||
gen_eqs([V|Vs], [D|Ds], ((V=D),Eqs)) :-
|
||||
gen_eqs(Vs,Ds,Eqs).
|
||||
|
||||
add_alldiffs([],Eqs,Eqs).
|
||||
add_alldiffs(AllDiffs,Eqs,(Eqs/alldiff(AllDiffs))).
|
||||
|
||||
|
Reference in New Issue
Block a user