From f6d8304fcf0ba297afb5a5f3b3babec54190d8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Fri, 31 Aug 2018 20:03:00 +0100 Subject: [PATCH] Problog --- library/lists.yap | 11 --- library/tries/base_tries.h | 14 +-- library/tries/core_tries.h | 50 +++++----- packages/ProbLog/problog/logger.yap | 2 +- packages/ProbLog/problog/ptree.yap | 2 +- packages/ProbLog/problog_learning_lbdd.yap | 101 +++++++++++---------- pl/bootlists.yap | 11 +++ pl/consult.yap | 8 +- pl/preds.yap | 2 +- 9 files changed, 103 insertions(+), 98 deletions(-) diff --git a/library/lists.yap b/library/lists.yap index 52e38df66..0343d6005 100644 --- a/library/lists.yap +++ b/library/lists.yap @@ -358,17 +358,6 @@ remove_duplicates([Elem|L], [Elem|NL]) :- delete(L, Elem, Temp), remove_duplicates(Temp, NL). -% reverse(List, Reversed) -% is true when List and Reversed are lists with the same elements -% but in opposite orders. rev/2 is a synonym for reverse/2. - -reverse(List, Reversed) :- - reverse(List, [], Reversed). - -reverse([], Reversed, Reversed). -reverse([Head|Tail], Sofar, Reversed) :- - reverse(Tail, [Head|Sofar], Reversed). - % same_length(?List1, ?List2) % is true when List1 and List2 are both lists and have the same number diff --git a/library/tries/base_tries.h b/library/tries/base_tries.h index 01c070daa..87ff12f04 100644 --- a/library/tries/base_tries.h +++ b/library/tries/base_tries.h @@ -135,13 +135,13 @@ void trie_max_stats(YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_I void trie_usage(TrEntry trie, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes); void trie_print(TrEntry trie); -void trie_data_construct(TrNode node); -void trie_set_traverse_mode(YAP_Int mode); -YAP_Int trie_get_traverse_mode(void); -TrData trie_traverse_first(TrEntry trie); -TrData trie_traverse_next(TrData data); -void trie_disable_hash_table(void); -void trie_enable_hash_table(void); +extern void trie_data_construct(TrNode node); +extern void trie_set_traverse_mode(YAP_Int mode); +extern YAP_Int trie_get_traverse_mode(void); +extern TrData trie_traverse_first(TrEntry trie); +extern TrData trie_traverse_next(TrData data); +extern void trie_disable_hash_table(void); +extern void trie_enable_hash_table(void); YAP_Term trie_to_list(TrEntry trie); diff --git a/library/tries/core_tries.h b/library/tries/core_tries.h index 4bfaf47f8..7cbef73be 100644 --- a/library/tries/core_tries.h +++ b/library/tries/core_tries.h @@ -287,32 +287,32 @@ typedef struct trie_hash { /* API */ /* --------------------------- */ -TrEngine core_trie_init_module(void); -TrNode core_trie_open(TrEngine engine); -void core_trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); -void core_trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)); -void core_trie_set_mode(YAP_Int mode); -YAP_Int core_trie_get_mode(void); -TrNode core_trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth); -TrNode core_trie_check_entry(TrNode node, YAP_Term entry); -YAP_Term core_trie_get_entry(TrNode node); -void core_trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); -void core_trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); -void core_trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)); -void core_trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*copy_function)(TrNode, TrNode)); -void core_trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)); -YAP_Int core_trie_count_join(TrNode node1, TrNode node2); -YAP_Int core_trie_count_intersect(TrNode node1, TrNode node2); -void core_trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)); -TrNode core_trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)); -void core_trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); -void core_trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); -void core_trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes); -void core_trie_print(TrNode node, void (*print_function)(TrNode)); +extern TrEngine core_trie_init_module(void); +extern TrNode core_trie_open(TrEngine engine); +extern void core_trie_close(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); +extern void core_trie_close_all(TrEngine engine, void (*destruct_function)(TrNode)); +extern void core_trie_set_mode(YAP_Int mode); +extern YAP_Int core_trie_get_mode(void); +extern TrNode core_trie_put_entry(TrEngine engine, TrNode node, YAP_Term entry, YAP_Int *depth); +extern TrNode core_trie_check_entry(TrNode node, YAP_Term entry); +extern YAP_Term core_trie_get_entry(TrNode node); +extern void core_trie_remove_entry(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); +extern void core_trie_remove_subtree(TrEngine engine, TrNode node, void (*destruct_function)(TrNode)); +extern void core_trie_add(TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode)); +extern void core_trie_join(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*copy_function)(TrNode, TrNode)); +extern void core_trie_intersect(TrEngine engine, TrNode node_dest, TrNode node_source, void (*add_function)(TrNode, TrNode), void (*destruct_function)(TrNode)); +extern YAP_Int core_trie_count_join(TrNode node1, TrNode node2); +extern YAP_Int core_trie_count_intersect(TrNode node1, TrNode node2); +extern void core_trie_save(TrNode node, FILE *file, void (*save_function)(TrNode, FILE *)); +extern TrNode core_trie_load(TrEngine engine, FILE *file, void (*load_function)(TrNode, YAP_Int, FILE *)); +extern void core_trie_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); +extern void core_trie_max_stats(TrEngine engine, YAP_Int *memory, YAP_Int *tries, YAP_Int *entries, YAP_Int *nodes); +extern void core_trie_usage(TrNode node, YAP_Int *entries, YAP_Int *nodes, YAP_Int *virtual_nodes); +extern void core_trie_print(TrNode node, void (*print_function)(TrNode)); -void core_disable_hash_table(void); -void core_enable_hash_table(void); +extern void core_disable_hash_table(void); +extern void core_enable_hash_table(void); -YAP_Term core_trie_to_list(TrNode node); +extern YAP_Term core_trie_to_list(TrNode node); #include "core_dbtries.h" diff --git a/packages/ProbLog/problog/logger.yap b/packages/ProbLog/problog/logger.yap index 295e3fb3d..2311d46b3 100644 --- a/packages/ProbLog/problog/logger.yap +++ b/packages/ProbLog/problog/logger.yap @@ -244,7 +244,7 @@ logger_define_variable(Name,Type) :- -> write('redefining logger variable '),write(Name),write(' of type '), write(Type0), nl ; - throw(error(variable_redefined(logger_define_variable(Name,Type))) + throw(error(variable_redefined(logger_define_variable(Name,Type)))) ). logger_define_variable(Name,Type) :- ground(Type), diff --git a/packages/ProbLog/problog/ptree.yap b/packages/ProbLog/problog/ptree.yap index aff2080a8..4fddabef7 100644 --- a/packages/ProbLog/problog/ptree.yap +++ b/packages/ProbLog/problog/ptree.yap @@ -263,7 +263,7 @@ % this is a test to determine whether YAP provides the needed trie library :- initialization( - ( predicate_property(trie_disable_hash, imported_from(tries)) -> + ( predicate_property(trie_disable_hash, imported_from(M)) -> trie_disable_hash ; print_message(warning,'The predicate tries:trie_disable_hash/0 does not exist. Please update trie library.') ) diff --git a/packages/ProbLog/problog_learning_lbdd.yap b/packages/ProbLog/problog_learning_lbdd.yap index 7f61a3fb0..a248d242d 100644 --- a/packages/ProbLog/problog_learning_lbdd.yap +++ b/packages/ProbLog/problog_learning_lbdd.yap @@ -389,8 +389,6 @@ reset_learning :- do_learning(Iterations) :- do_learning(Iterations,-1). -:- spy do_learning/2. - do_learning(Iterations,Epsilon) :- current_predicate(user:example/4), !, @@ -514,32 +512,7 @@ init_learning :- % if yes, switch to problog_exact % continuous facts are not supported yet. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - problog_flag(continuous_facts, true), - !, - problog_flag(init_method,(_,_,_,_,OldCall)), - ( - ( - continuous_fact(_), - OldCall\=problog_exact_save(_,_,_,_,_) - ) - -> - ( - format_learning(2,'Theory uses continuous facts.~nWill use problog_exact/3 as initalization method.~2n',[]), - set_problog_flag(init_method,(Query,Probability,BDDFile,ProbFile,problog_exact_save(Query,Probability,_Status,BDDFile,ProbFile))) - ); - true - ), - - ( - problog_tabled(_) - -> - ( - format_learning(2,'Theory uses tabling.~nWill use problog_exact/3 as initalization method.~2n',[]), - set_problog_flag(init_method,(Query,Probability,BDDFile,ProbFile,problog_exact_save(Query,Probability,_Status,BDDFile,ProbFile))) - ); - true - ), - + set_default_gradient_method, succeeds_n_times(user:test_example(_,_,_,_),TestExampleCount), format_learning(3,'~q test examples~n',[TestExampleCount]), @@ -597,6 +570,21 @@ init_learning :- empty_bdd_directory. +set_default_gradient_method :- + problog_flag(continuous_facts, true), + !, + problog_flag(init_method,OldMethod), + format_learning(2,'Theory uses continuous facts.~nWill use problog_exact/3 as initalization method.~2n',[]), + set_problog_flag(init_method,(Query,Probability,BDDFile,ProbFile,problog_exact_save(Query,Probability,_Status,BDDFile,ProbFile))). +set_default_gradient_method :- + problog_tabled(_), problog_flag(fast_proofs,false), + !, + format_learning(2,'Theory uses tabling.~nWill use problog_exact/3 as initalization method.~2n',[]), + set_problog_flag(init_method,(Query,Probability,BDDFile,ProbFile,problog_exact_save(Query,Probability,_Status,BDDFile,ProbFile))). +set_default_gradient_method :- + set_problog_flag(init_method,(Query,1,BDD, + problog_kbest_as_bdd(user:Query,1,BDD))). + %======================================================================== %= This predicate goes over all training and test examples, %= calls the inference method of ProbLog and stores the resulting @@ -625,29 +613,23 @@ init_one_query(QueryID,Query,Type) :- format_learning(3,' Reuse existing BDD ~q~n~n',[QueryID]); ( b_setval(problog_required_keep_ground_ids,false), - problog_flag(libbdd_init_method,(Query,Bdd,Call)), + rb_new(H0), + problog_flag(init_method,(Query,NOf,Bdd,problog_kbest_as_bdd(Call,1,Bdd))), + strip_module(Call,_,gene(X,Y)), + !, Bdd = bdd(Dir, Tree, MapList), % trace, - once(Call), - rb_new(H0), + problog:problog_kbest_as_bdd(user:gene(X,Y),1,Bdd), maplist_to_hash(MapList, H0, Hash), Tree \= [], + %put_code(0'.), writeln(QueryID), tree_to_grad(Tree, Hash, [], Grad), recordz(QueryID,bdd(Dir, Grad, MapList),_) ) - ), - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % check wether this BDD is similar to another BDD - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - ( - problog_flag(check_duplicate_bdds,true) - -> - true /* ignore this flag for now */ - ; - true - ),!. -init_one_query(_QueryID,_Query,_Type). + ). +init_one_query(_QueryID,_Query,_Type) :- + throw(unsupported_init_method). @@ -1006,6 +988,7 @@ inv_sigmoid(T,InvSig) :- save_old_probabilities :- problog_flag(continous_facts, true), + !, forall(tunable_fact(FactID,_), ( continuous_fact(FactID) @@ -1024,6 +1007,14 @@ save_old_probabilities :- ) ) ). +save_old_probabilities :- + forall(tunable_fact(FactID,_), + ( + get_fact_probability(FactID,OldProbability), + atomic_concat(['old_prob_',FactID],Key), + bb_put(Key,OldProbability) + ) + ). @@ -1106,7 +1097,8 @@ gradient_descent :- save_old_probabilities, update_values, - reset_gradients. + reset_gradients, + compute_gradients(Handle). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % start set gradient to zero @@ -1130,7 +1122,14 @@ gradient_descent :- bb_put(Key,0.0) ) ) - ), + ). + reset_gradients :- + forall(tunable_fact(FactID,_), + ( + atomic_concat(['grad_',FactID],Key), + bb_put(Key,0.0) + ) + ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % stop gradient to zero %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1138,6 +1137,7 @@ gradient_descent :- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % start calculate gradient %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +compute_gradients(Handle) :- bb_put(mse_train_sum, 0.0), bb_put(mse_train_min, 0.0), bb_put(mse_train_max, 0.0), @@ -1485,18 +1485,18 @@ my_5_min(V1,V2,V3,V4,V5,F1,F2,F3,F4,F5,VMin,FMin) :- %======================================================================== init_flags :- - prolog_file_name('queries',Queries_Folder), % get absolute file name for './queries' - prolog_file_name('output',Output_Folder), % get absolute file name for './output' + prolog_file_name(queries,Queries_Folder), % get absolute file name for './queries' + prolog_file_name(output,Output_Folder), % get absolute file name for './output' problog_define_flag(bdd_directory, problog_flag_validate_directory, 'directory for BDD scripts', Queries_Folder,learning_general), problog_define_flag(output_directory, problog_flag_validate_directory, 'directory for logfiles etc', Output_Folder,learning_general,flags:learning_output_dir_handler), problog_define_flag(log_frequency, problog_flag_validate_posint, 'log results every nth iteration', 1, learning_general), problog_define_flag(rebuild_bdds, problog_flag_validate_nonegint, 'rebuild BDDs every nth iteration', 0, learning_general), problog_define_flag(reuse_initialized_bdds,problog_flag_validate_boolean, 'Reuse BDDs from previous runs',false, learning_general), problog_define_flag(check_duplicate_bdds,problog_flag_validate_boolean,'Store intermediate results in hash table',true,learning_general), - problog_define_flag(libbdd_init_method,problog_flag_validate_dummy,'ProbLog predicate to search proofs',(Query,Tree,problog:problog_kbest_as_bdd(Query,100,Tree)),learning_general,flags:learning_libdd_init_handler), + problog_define_flag(init_method,problog_flag_validate_dummy,'ProbLog predicate to search proofs',(Query,Tree,problog:problog_kbest_as_bdd(Query,100,Tree)),learning_general,flags:learning_libdd_init_handler), problog_define_flag(alpha,problog_flag_validate_number,'weight of negative examples (auto=n_p/n_n)',auto,learning_general,flags:auto_handler), problog_define_flag(sigmoid_slope,problog_flag_validate_posnumber,'slope of sigmoid function',1.0,learning_general), - problog_define_flag(continuous_facts,problog_flag_validate_boolean,'support parameter learning of continuous distributions',1.0,learning_general), + problog_define_flag(continuous_facts,problog_flag_validate_boolean,'support parameter learning of continuous distributions',true,learning_general), problog_define_flag(learning_rate,problog_flag_validate_posnumber,'Default learning rate (If line_search=false)',examples,learning_line_search,flags:examples_handler), problog_define_flag(line_search, problog_flag_validate_boolean,'estimate learning rate by line search',false,learning_line_search), @@ -1504,7 +1504,6 @@ init_flags :- problog_define_flag(line_search_tau, problog_flag_validate_indomain_0_1_open,'tau value for line search',0.618033988749,learning_line_search), problog_define_flag(line_search_tolerance,problog_flag_validate_posnumber,'tolerance value for line search',0.05,learning_line_search), problog_define_flag(line_search_interval, problog_flag_validate_dummy,'interval for line search',(0,100),learning_line_search,flags:linesearch_interval_handler). - init_logger :- logger_define_variable(iteration, int), @@ -1527,5 +1526,7 @@ init_logger :- logger_define_variable(llh_test_queries,float). :- initialization(init_flags). + :- initialization(init_logger). + diff --git a/pl/bootlists.yap b/pl/bootlists.yap index 69beade81..c944d9fe6 100644 --- a/pl/bootlists.yap +++ b/pl/bootlists.yap @@ -136,3 +136,14 @@ prolog:length(L, M) :- %% @} +% reverse(List, Reversed) +% is true when List and Reversed are lists with the same elements +% but in opposite orders. rev/2 is a synonym for reverse/2. + +lists:reverse(List, Reversed) :- + lists:reverse(List, [], Reversed). + +lists:reverse([], Reversed, Reversed). +lists:reversae([Head|Tail], Sofar, Reversed) :- + lists:reverse(Tail, [Head|Sofar], Reversed). + diff --git a/pl/consult.yap b/pl/consult.yap index f4afdb88e..7975791f6 100644 --- a/pl/consult.yap +++ b/pl/consult.yap @@ -855,7 +855,10 @@ nb_setval('$if_le1vel',0). '__NB_getval__'('$lf_status', TOpts, fail), '$lf_opt'( initialization, TOpts, Ref), nb:nb_queue_close(Ref, Answers, []), - lists:member(G, Answers), + '$process_init_goal'(Answers). +'$exec_initialization_goals'. + +'$process_init_goal'([G|_]) :- '$yap_strip_module'( G, M0, G0), ( catch(M0:G0, Error, user:'$LoopError'(Error, top)) @@ -865,7 +868,8 @@ nb_setval('$if_le1vel',0). format(user_error,':- ~w:~w failed.~n',[M0,G0]) ), fail. -'$exec_initialization_goals'. +'$process_init_goal'([_|Gs]) :- + '$process_init_goal'(Gs). /** @pred include(+ _F_) is directive diff --git a/pl/preds.yap b/pl/preds.yap index 127fe10ed..f273db11a 100644 --- a/pl/preds.yap +++ b/pl/preds.yap @@ -535,7 +535,7 @@ predicate_property(Pred,Prop) :- functor(P,N,A), once(recorded('$module','$module'(_TFN,M,_S,Publics,_L),_)), lists:memberchk(N/A,Publics). -'$predicate_property'(P,M,M0,imported_from(M0)) :- +'$predicate_property'(P,M,M0,imported_from(M)) :- M \= M0. '$predicate_property'(P,Mod,_,number_of_clauses(NCl)) :- '$number_of_clauses'(P,Mod,NCl).