From c804d105b6e73440c85c79786b477bf840308fa0 Mon Sep 17 00:00:00 2001 From: Theofrastos Mantadelis Date: Wed, 3 Nov 2010 19:22:11 +0100 Subject: [PATCH] Some ProbLog improvements related with tabling efficiency, more to come soon --- packages/ProbLog/problog.yap | 804 ++++++++++---------- packages/ProbLog/problog/logger.yap | 56 +- packages/ProbLog/problog/nestedtries.yap | 423 ++++++++++ packages/ProbLog/problog/tabling.yap | 5 +- packages/ProbLog/problog/timer.yap | 30 +- packages/ProbLog/problog/tptree.yap | 221 +++--- packages/ProbLog/problog/utils_learning.yap | 47 +- packages/ProbLog/problog_learning.yap | 28 +- 8 files changed, 1025 insertions(+), 589 deletions(-) create mode 100644 packages/ProbLog/problog/nestedtries.yap diff --git a/packages/ProbLog/problog.yap b/packages/ProbLog/problog.yap index fe47bad99..b7083adcf 100644 --- a/packages/ProbLog/problog.yap +++ b/packages/ProbLog/problog.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-10-06 12:56:13 +0200 (Wed, 06 Oct 2010) $ -% $Revision: 4877 $ +% $Date: 2010-10-21 10:47:36 +0200 (Thu, 21 Oct 2010) $ +% $Revision: 4970 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -14,7 +14,7 @@ % Katholieke Universiteit Leuven % % Main authors of this file: -% Angelika Kimmig, Vitor Santos Costa,Bernd Gutmann, +% Angelika Kimmig, Vitor Santos Costa, Bernd Gutmann, % Theofrastos Mantadelis, Guy Van den Broeck % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -300,21 +300,17 @@ :- style_check(all). :- yap_flag(unknown,error). -:- set_prolog_flag(to_chars_mode,quintus). - % general yap modules -:- use_module(library(charsio)). -:- use_module(library(lists)). -:- use_module(library(terms)). -:- use_module(library(random)). % PM doesn't seem to be used! -:- use_module(library(system)). -:- use_module(library(rbtrees)). % PM doesn't seem to be used! +:- use_module(library(lists), [append/3,member/2,memberchk/2,reverse/2,select/3,nth1/3,nth1/4,nth0/4]). +:- use_module(library(terms), [variable_in_term/2] ). +:- use_module(library(random), [random/1]). +:- use_module(library(system), [tmpnam/1,shell/2,delete_file/1,delete_file/2]). :- use_module(library(ordsets), [list_to_ord_set/2, ord_insert/3, ord_union/3]). % problog related modules :- use_module('problog/variables'). :- use_module('problog/extlists'). -:- use_module('problog/gflags', [flag_store/2]). +:- use_module('problog/gflags'). :- use_module('problog/flags'). :- use_module('problog/print'). :- use_module('problog/os'). @@ -323,6 +319,8 @@ :- use_module('problog/sampling'). :- use_module('problog/intervals'). :- use_module('problog/mc_DNF_sampling'). +:- use_module('problog/timer'). +:- use_module('problog/utils'). :- catch(use_module('problog/ad_converter'),_,true). :- catch(use_module('problog/variable_elimination'),_,true). @@ -344,7 +342,6 @@ :- dynamic(tunable_fact/2). :- dynamic(non_ground_fact/1). :- dynamic(continuous_fact/1). -%:- dynamic(problog_dir/1). % global, manipulated via problog_control/2 :- dynamic(up/0). :- dynamic(limit/0). @@ -368,14 +365,11 @@ :- dynamic(answer/1). % to keep track of the groundings for non-ground facts :- dynamic(grounding_is_known/2). - % for decisions :- dynamic(decision_fact/2). - % for fact where the proabability is a variable :- dynamic(dynamic_probability_fact/1). :- dynamic(dynamic_probability_fact_extract/2). - % for storing continuous parts of proofs (Hybrid ProbLog) :- dynamic([hybrid_proof/3, hybrid_proof/4]). :- dynamic(hybrid_proof_disjoint/4). @@ -384,6 +378,8 @@ % and this module provides the predicate X::Y to iterate over them :- multifile('::'/2). +:- multifile(user:term_expansion/1). + % directory where problogbdd executable is located % automatically set during loading -- assumes it is in same place as this file (problog.yap) :- getcwd(PD), set_problog_path(PD). @@ -566,6 +562,7 @@ generate_atoms(N, A):- % dynamic predicate problog_predicate(Name,Arity) keeps track of predicates that already have wrapper clause %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% converts annotated disjunctions - if loaded term_expansion_intern(A, B, C):- catch(term_expansion_intern_ad(A, B, C), _, false). @@ -617,12 +614,69 @@ term_expansion_intern((Annotation :: Head :- Body), Module, problog:ExpandedClau ). -/* this can slow down prolog time by several orders if there's lots of them -user:term_expansion(P::Goal,Goal) :- - P \= t(_), - P =:= 1, - !. -*/ + + +% handles continuous facts +term_expansion_intern(Head :: Goal,Module,problog:ProbFact) :- + nonvar(Head), + Head=(X,Distribution), + !, + ( + Distribution=gaussian(Mu,Sigma) + -> + true; + ( throw(unknown_distribution) + ) + ), + + ( + variable_in_term_exactly_once(Goal,X) + -> + true; + ( + throw(variable) + ) + ), + + copy_term(((X,Distribution) :: Goal), ((X2,Distribution2) :: Goal2)), + % bind_the_variable + X2=Distribution2, + + % find position in term + Goal2=..[Name|Args], + once(nth1(Pos,Args,Distribution2)), + + length(Args,Arity), + atomic_concat([problogcontinuous_,Name],ProblogName), + probclause_id(ID), + + % is it a tunable fact? + ( + (number(Mu),number(Sigma)) + -> + NewArgs=Args; + ( + Mu_Random is 0.1, % random*4-2, + Sigma_Random is 0.4, % random*2+0.5, + nth1(Pos,Args,_,KeepArgs), + nth1(Pos,NewArgs,gaussian(Mu_Random,Sigma_Random),KeepArgs), + assertz(tunable_fact(ID,gaussian(Mu,Sigma))) + ) + ), + ProbFact =.. [ProblogName,ID|NewArgs], + + ( + ground(Goal) + -> + true; + assertz(non_ground_fact(ID)) + ), + assertz(continuous_fact(ID)), + problog_continuous_predicate(Name, Arity, Pos,ProblogName,Module). + + + + % handles probabilistic facts term_expansion_intern(P :: Goal,Module,problog:ProbFact) :- @@ -704,71 +758,11 @@ sample_initial_value_for_tunable_fact(LogP) :- -% Hybrid ProbLog stuff - -is_valid_gaussian(X) :- - compound(X), - X=gaussian(Mu,Sigma), - ( - ((number(Mu),number(Sigma));(Mu=t(_),Sigma=t(_))) - -> - true; - throw(invalid_gaussian(X)) - ). - -:- multifile(user:term_expansion/1). - -user:term_expansion(Goal, problog:ProbFact) :- - compound(Goal), - Goal=..[Name|Args], - once( (nth(Pos,Args,GaussianArg),is_valid_gaussian(GaussianArg)) ), - - %Goal contains a Gaussian, there is some work to do - - ( % check for a second Gaussian - (nth(Pos2,Args,GaussianArg2),Pos2\=Pos,is_valid_gaussian(GaussianArg2)) - -> - ( - format(user_error,'We only support continous atoms with at most one Gaussian inside.~n',[]), - format(user_error,'Your program contains the atom ~w with more than one.~n',[]), - throw(unsupported_multivariate_gaussian(Goal)) - ); - true - ), - - functor(Goal, Name, Arity), - atomic_concat([problogcontinuous_,Name],ProblogName), - probclause_id(ID), - - GaussianArg=gaussian(Mu_Arg,Sigma_Arg), - - % is it a tunable fact? - ( - (number(Mu_Arg),number(Sigma_Arg)) - -> - NewArgs=Args; - ( - Mu_Random is 0.1, % random*4-2, - Sigma_Random is 0.4, % random*2+0.5, - nth(Pos,Args,_,KeepArgs), - nth(Pos,NewArgs,gaussian(Mu_Random,Sigma_Random),KeepArgs), - assertz(tunable_fact(ID,gaussian(Mu_Arg,Sigma_Arg))) - ) - ), - ProbFact =.. [ProblogName,ID|NewArgs], - - ( - ground(Goal) - -> - true; - assertz(non_ground_fact(ID)) - ), - assertz(continuous_fact(ID)), - problog_continuous_predicate(Name, Arity, Pos,ProblogName). +% % introduce wrapper clause if predicate seen first time -problog_continuous_predicate(Name, Arity,ContinuousArgumentPosition,_) :- +problog_continuous_predicate(Name, Arity,ContinuousArgumentPosition,_,_) :- problog_continuous_predicate(Name, Arity,OldContinuousArgumentPosition), !, ( @@ -784,7 +778,7 @@ problog_continuous_predicate(Name, Arity,ContinuousArgumentPosition,_) :- throw(continuous_argument(not_unique_position)) ) ). -problog_continuous_predicate(Name, Arity, ContinuousArgumentPosition, ProblogName) :- +problog_continuous_predicate(Name, Arity, ContinuousArgumentPosition, ProblogName,Module) :- LBefore is ContinuousArgumentPosition-1, LAfter is Arity-ContinuousArgumentPosition, @@ -798,9 +792,8 @@ problog_continuous_predicate(Name, Arity, ContinuousArgumentPosition, ProblogNam ProbFact =.. [ProblogName,ID|ProbArgs], - prolog_load_context(module,Mod), - assertz( (Mod:OriginalGoal :- ProbFact, + assertz( (Module:OriginalGoal :- ProbFact, % continuous facts always get a grounding ID, even when they are actually ground % this simplifies the BDD script generation non_ground_fact_grounding_id(ProbFact,Ground_ID), @@ -812,6 +805,9 @@ problog_continuous_predicate(Name, Arity, ContinuousArgumentPosition, ProblogNam ArityPlus1 is Arity+1, dynamic(problog:ProblogName/ArityPlus1). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% predicates for the user to manipulate continuous facts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% in_interval(ID,Low,High) :- number(Low), @@ -834,7 +830,9 @@ interval_merge((_ID,GroundID,_Type),Interval) :- b_setval(Key,NewInterval). - +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% assert/retract for probabilistic facts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% problog_assert(P::Goal) :- problog_assert(user,P::Goal). @@ -849,6 +847,10 @@ problog_retractall(Goal) :- ProbLogGoal=..[F2|Args2], retractall(problog:ProbLogGoal). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % introduce wrapper clause if predicate seen first time problog_predicate(Name, Arity, _,_) :- @@ -874,6 +876,39 @@ problog_predicate(Name, Arity, ProblogName,Mod) :- ArityPlus2 is Arity+2, dynamic(problog:ProblogName/ArityPlus2). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Generating and storing the grounding IDs for +% non-ground probabilistic facts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +non_ground_fact_grounding_id(Goal,ID) :- + ground(Goal), + !, + ( + grounding_is_known(Goal,ID) + -> + true; + ( + nb_getval(non_ground_fact_grounding_id_counter,ID), + ID2 is ID+1, + nb_setval(non_ground_fact_grounding_id_counter,ID2), + assertz(grounding_is_known(Goal,ID)) + ) + ). +non_ground_fact_grounding_id(Goal,_) :- + format(user_error,'The current program uses non-ground facts.~n', []), + format(user_error,'If you query those, you may only query fully-grounded versions of the fact.~n',[]), + format(user_error,'Within the current proof, you queried for ~q which is not ground.~2n', [Goal]), + throw(error(non_ground_fact(Goal))). + +reset_non_ground_facts :- + required(keep_ground_ids), + !. +reset_non_ground_facts :- + nb_setval(non_ground_fact_grounding_id_counter,0), + retractall(grounding_is_known(_,_)). + +:- initialization(reset_non_ground_facts). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Getting the ID for any kind of ground fact @@ -947,78 +982,40 @@ probclause_id(ID) :- C1 is ID+1, nb_setval(probclause_counter,C1), !. -non_ground_fact_grounding_id(Goal,ID) :- - ( - ground(Goal) - -> - true; - ( - format(user_error,'The current program uses non-ground facts.~n', []), - format(user_error,'If you query those, you may only query fully-grounded versions of the fact.~n',[]), - format(user_error,'Within the current proof, you queried for ~q which is not ground.~n~n', [Goal]), - throw(error(non_ground_fact(Goal))) - ) - ), - ( - grounding_is_known(Goal,ID) - -> - true; - ( - nb_getval(non_ground_fact_grounding_id_counter,ID), - ID2 is ID+1, - nb_setval(non_ground_fact_grounding_id_counter,ID2), - assertz(grounding_is_known(Goal,ID)) - ) - ). -reset_non_ground_facts :- - (required(keep_ground_ids) -> - true - ; - nb_setval(non_ground_fact_grounding_id_counter,0), - retractall(grounding_is_known(_,_)) - ). - -:- initialization(reset_non_ground_facts). % backtrack over all probabilistic facts % must come before term_expansion -P::Goal :- - probabilistic_fact(P,Goal,_). +Prob::Goal :- + probabilistic_fact(Prob,Goal,_). % backtrack over all probabilistic facts -probabilistic_fact(P2,Goal,ID) :- +probabilistic_fact(Prob,Goal,ID) :- + ground(Goal), + !, + Goal =.. [F|Args], + atomic_concat('problog_',F,F2), + append([ID|Args],[LProb],Args2), + Goal2 =..[F2|Args2], + length(Args2,N), + current_predicate(F2/N), + Goal2, + number(LProb), + Prob is exp(LProb). +probabilistic_fact(Prob,Goal,ID) :- + get_internal_fact(ID,ProblogTerm,_ProblogName,_ProblogArity), + ProblogTerm =.. [F,_ID|Args], + append(Args2,[LProb],Args), + name(F,[_p,_r,_o,_b,_l,_o,_g,_|F2Chars]), + name(F2,F2Chars), + Goal =.. [F2|Args2], ( - ground(Goal) + dynamic_probability_fact(ID) -> - ( - Goal =.. [F|Args], - atomic_concat('problog_',F,F2), - append([ID|Args],[P],Args2), - Goal2 =..[F2|Args2], - length(Args2,N), - current_predicate(F2/N), - call(Goal2), - number(P), - P2 is exp(P) - ); - ( - get_internal_fact(ID,ProblogTerm,_ProblogName,_ProblogArity), - ProblogTerm =.. [F,_ID|Args], - append(Args2,[P],Args), - name(F,[_p,_r,_o,_b,_l,_o,_g,_|F2Chars]), - name(F2,F2Chars), - Goal =.. [F2|Args2], - ( - dynamic_probability_fact(ID) - -> - P2=p; - P2 is exp(P) - ) - ) + Prob=p; + Prob is exp(LProb) ). - % generates unique IDs for proofs proof_id(ID) :- nb_getval(problog_proof_id,ID), @@ -1044,17 +1041,17 @@ get_fact_probability(A, Prob) :- once(append(Part1, [95|Part2], A_Codes)), % 95 = '_' number_codes(ID, Part1), !, % let's check whether Part2 contains an 'l' (l=low) - (member(108, Part2) -> - fail + \+ memberchk(108,Part2), + number_codes(Grounding_ID, Part2), + ( + dynamic_probability_fact(ID) + -> + grounding_is_known(Goal, Grounding_ID), + dynamic_probability_fact_extract(Goal, Prob) ; - number_codes(Grounding_ID, Part2), - (dynamic_probability_fact(ID) -> - grounding_is_known(Goal, Grounding_ID), - dynamic_probability_fact_extract(Goal, Prob) - ; - get_fact_probability(ID, Prob) - ) - ). + get_fact_probability(ID, Prob) + ), + !. get_fact_probability(ID,Prob) :- ground(ID), prob_for_id(ID,Prob,_), @@ -1093,9 +1090,9 @@ set_fact_probability(ID,Prob) :- get_internal_fact(ID,ProblogTerm,ProblogName,ProblogArity), retract(ProblogTerm), ProblogTerm =.. [ProblogName|ProblogTermArgs], - nth(ProblogArity,ProblogTermArgs,_,KeepArgs), + nth1(ProblogArity,ProblogTermArgs,_,KeepArgs), NewLogProb is log(Prob), - nth(ProblogArity,NewProblogTermArgs,NewLogProb,KeepArgs), + nth1(ProblogArity,NewProblogTermArgs,NewLogProb,KeepArgs), NewProblogTerm =.. [ProblogName|NewProblogTermArgs], assertz(NewProblogTerm). @@ -1176,7 +1173,7 @@ get_fact(ID,OutsideTerm) :- ProblogTerm =.. [_Functor,ID|Args], atomic_concat('problog_',OutsideFunctor,ProblogName), Last is ProblogArity-1, - nth(Last,Args,_LogProb,OutsideArgs), + nth1(Last,Args,_LogProb,OutsideArgs), OutsideTerm =.. [OutsideFunctor|OutsideArgs]. % ID of instance of non-ground fact: get fact from grounding table get_fact(ID,OutsideTerm) :- @@ -1216,73 +1213,82 @@ get_fact_list([ID|IDs],[Fact|Facts]) :- % else update state and succeed % % do not maintain gloabl variables in montecarlo mode -add_to_proof(ID, Prob) :- - (problog_control(check, mc) -> - montecarlo_check(ID) - ; - b_getval(problog_steps,MaxSteps), - b_getval(problog_probability, CurrentP), - nb_getval(problog_threshold, CurrentThreshold), - b_getval(problog_current_proof, IDs), - %%%% Bernd, changes for negated ground facts - \+ open_end_memberchk(not(ID),IDs), - %%%% Bernd, changes for negated ground facts - (MaxSteps =< 0 -> - fail - ; - (open_end_memberchk(ID, IDs) -> %Theo - true - ; - open_end_add(ID, IDs, NIDs), %Theo - % \+ prune_check(NIDs, Trie_Completed_Proofs), - multiply_probabilities(CurrentP, Prob, NProb), - (NProb < CurrentThreshold -> - upper_bound(NIDs), - fail - ; - b_setval(problog_probability, NProb), - b_setval(problog_current_proof, NIDs) - ) - ), - Steps is MaxSteps - 1, - b_setval(problog_steps, Steps) - ) - ). +add_to_proof(ID, _LogProb) :- + problog_control(check, mc), + !, + montecarlo_check(ID). +add_to_proof(ID, LogProb) :- + b_getval(problog_steps,MaxSteps), + MaxSteps>0, + b_getval(problog_probability, CurrentLogProb), + nb_getval(problog_threshold, CurrentThreshold), + b_getval(problog_current_proof, IDs), + + % check whether negation of this fact is already used in proof + \+ open_end_memberchk(not(ID),IDs), + + ( % check whether this fact is already used in proof + open_end_memberchk(ID, IDs) + -> + true; + ( + open_end_add(ID, IDs, NIDs), + NewLogProb is CurrentLogProb+LogProb, + ( + NewLogProb < CurrentThreshold + -> + ( + upper_bound(NIDs), + fail + ); + ( + b_setval(problog_probability, NewLogProb), + b_setval(problog_current_proof, NIDs) + ) + ) + ) + ), + Steps is MaxSteps - 1, + b_setval(problog_steps, Steps). -%%%% Bernd, changes for negated ground facts -add_to_proof_negated(ID, Prob) :- - (problog_control(check, mc) -> - % the sample has to fail if the fact is negated - \+ montecarlo_check(ID) - ; - b_getval(problog_steps, MaxSteps), - b_getval(problog_probability, CurrentP), - nb_getval(problog_threshold, CurrentThreshold), - b_getval(problog_current_proof, IDs), - \+ open_end_memberchk(ID, IDs), - (MaxSteps =< 0 -> - fail - ; - (open_end_memberchk(not(ID), IDs) -> - true - ; - open_end_add(not(ID), IDs, NIDs), %Theo - % \+ prune_check(NIDs, Trie_Completed_Proofs), - InverseProb is log(1 - exp(Prob)), - multiply_probabilities(CurrentP, InverseProb, NProb), - (NProb < CurrentThreshold -> - upper_bound(NIDs), %% checkme - fail - ; - b_setval(problog_probability, NProb), - b_setval(problog_current_proof, NIDs) - ) - ), - Steps is MaxSteps - 1, - b_setval(problog_steps, Steps) - ) - ). -%%%% Bernd, changes for negated ground facts +add_to_proof_negated(ID, _) :- + problog_control(check, mc), + !, + % the sample has to fail if the fact is negated + \+ montecarlo_check(ID). +add_to_proof_negated(ID, LogProb) :- + b_getval(problog_steps, MaxSteps), + MaxSteps>0, + b_getval(problog_probability, CurrentLogProb), + nb_getval(problog_threshold, CurrentThreshold), + b_getval(problog_current_proof, IDs), + + % check whether unnegated fact is already used in proof + \+ open_end_memberchk(ID, IDs), + + ( % check wether negation of this fact is already used in proof + open_end_memberchk(not(ID), IDs) + -> + true; + ( + open_end_add(not(ID), IDs, NIDs), + NewLogProb is CurrentLogProb + log(1-exp(LogProb)), + ( + NewLogProb < CurrentThreshold + -> + ( + upper_bound(NIDs), + fail + ); + ( + b_setval(problog_probability, NewLogProb), + b_setval(problog_current_proof, NIDs) + ) + ) + ) + ), + Steps is MaxSteps - 1, + b_setval(problog_steps, Steps). %Hybrid add_continuous_to_proof(ID,GroundID) :- @@ -1376,15 +1382,12 @@ split_g_id([A|B],[A|FactID],GroundingID) :- % % List always length>=1 -> don't need []=true-case for tries upper_bound(List) :- - problog_control(on, limit), - problog_control(check, up), - nb_getval(problog_stopped_proofs, Trie_Stopped_Proofs), - open_end_close_end(List, R), -% (prune_check(R, Trie_Stopped_Proofs) -> true; insert_ptree(R, Trie_Stopped_Proofs)). - insert_ptree(R, Trie_Stopped_Proofs). - -multiply_probabilities(CurrentLogP, LogProb, NLogProb) :- - NLogProb is CurrentLogP + LogProb. + problog_control(on, limit), + problog_control(check, up), + nb_getval(problog_stopped_proofs, Trie_Stopped_Proofs), + open_end_close_end(List, R), + % (prune_check(R, Trie_Stopped_Proofs) -> true; insert_ptree(R, Trie_Stopped_Proofs)). + insert_ptree(R, Trie_Stopped_Proofs). % this is called by all inference methods before the actual ProbLog goal % to set up environment for proving @@ -1404,7 +1407,20 @@ init_problog(Threshold) :- b_setval(problog_continuous_facts_used,[]), retractall(hybrid_proof(_,_,_)), retractall(hybrid_proof(_,_,_,_)), - retractall(hybrid_proof_disjoint(_,_,_,_)). + retractall(hybrid_proof_disjoint(_,_,_,_)), + + % reset all timers in case a query failed before + timer_reset(variable_elimination_time), + timer_reset(bdd_script_time), + timer_reset(bdd_generation_time), + timer_reset(script_gen_time_naive), + timer_reset(bdd_gen_time_naive), + timer_reset(script_gen_time_builtin), + timer_reset(bdd_gen_time_builtin), + timer_reset(script_gen_time_dec), + timer_reset(bdd_gen_time_dec), + timer_reset(sld_time), + timer_reset(build_tree_low). % idea: proofs that are refinements of known proof can be pruned as they don't add probability mass % note that current ptree implementation doesn't provide the check as there's no efficient method known so far... @@ -1471,14 +1487,12 @@ problog_statistics(Stat, Result):- problog_var_get(Stat, Result). generate_order_by_prob_fact_appearance(Order, FileName):- - open(FileName, 'write', Stream), - forall(member(PF, Order), ( - ptree:get_var_name(PF, Name), - format(Stream, "@~w~n", [Name]))), -/* findall(_, (recorded(variable_elimination, prob_fact(PF, _), _), - ptree:get_var_name(PF, Name), - format(Stream, "@~w~n", [Name])), _),*/ - close(Stream). + open(FileName, 'write', Stream), + forall(member(PF, Order), ( + ptree:get_var_name(PF, Name), + format(Stream, "@~w~n", [Name]) + )), + close(Stream). get_order(Trie, Order):- findall(List, ptree:traverse_ptree(Trie, List), Proofs), @@ -1528,11 +1542,11 @@ eval_dnf(OriTrie1, Prob, Status) :- ((problog_flag(variable_elimination, true), nb_getval(problog_nested_tries, false)) -> - statistics(walltime, _), + timer_start(variable_elimination_time), trie_check_for_and_cluster(OriTrie), - statistics(walltime, [_, VariableEliminationTime]), + timer_stop(variable_elimination_time,Variable_Elimination_Time), + problog_var_set(variable_elimination_time, Variable_Elimination_Time), trie_replace_and_cluster(OriTrie, Trie), - problog_var_set(variable_elimination_time, VariableEliminationTime), variable_elimination_stats(Clusters, OrigPF, CompPF), problog_var_set(variable_elimination_stats, compress(Clusters, OrigPF, CompPF)), clean_up @@ -1576,7 +1590,7 @@ eval_dnf(OriTrie1, Prob, Status) :- convert_filename_to_working_path(BDDParFileFlag, BDDParFile), % old reduction method doesn't support nested tries ((problog_flag(use_old_trie, true), nb_getval(problog_nested_tries, false)) -> - statistics(walltime, _), + timer_start(bdd_script_time), (problog_control(check, remember) -> bdd_ptree_map(Trie, BDDFile, BDDParFile, Mapping), convert_filename_to_working_path(save_map, MapFile), @@ -1587,14 +1601,14 @@ eval_dnf(OriTrie1, Prob, Status) :- ; bdd_ptree(Trie, BDDFile, BDDParFile) ), - statistics(walltime, [_, ScriptGenerationTime]), - problog_var_set(bdd_script_time, ScriptGenerationTime), + timer_stop(bdd_script_time,BDD_Script_Time), + problog_var_set(bdd_script_time, BDD_Script_Time), - statistics(walltime, _), + timer_start(bdd_generation_time), execute_bdd_tool(BDDFile, BDDParFile, Prob_old, Status_old), - statistics(walltime,[_, BDDGenerationTime]), - (Status_old = ok -> - problog_var_set(bdd_generation_time, BDDGenerationTime), + timer_stop(bdd_generation_time,BDD_Generation_Time), + (Status_old == ok -> + problog_var_set(bdd_generation_time, BDD_Generation_Time), problog_var_set(probability, Prob_old) ; problog_var_set(bdd_generation_time, fail), @@ -1605,18 +1619,17 @@ eval_dnf(OriTrie1, Prob, Status) :- ), % naive method with nested trie support but not loops ((problog_flag(use_naive_trie, true); (problog_flag(use_old_trie, true), nb_getval(problog_nested_tries, true))) -> - statistics(walltime, _), -% atomic_concat([BDDFile, '_naive'], BDDFile_naive), + timer_start(script_gen_time_naive), BDDFile = BDDFile_naive, nested_ptree_to_BDD_script(Trie, BDDFile_naive, BDDParFile), - statistics(walltime, [_, ScriptGenerationTime_naive]), - problog_var_set(bdd_script_time(naive), ScriptGenerationTime_naive), + timer_stop(script_gen_time_naive,Script_Gen_Time_Naive), + problog_var_set(bdd_script_time(naive), Script_Gen_Time_Naive), - statistics(walltime, _), + timer_start(bdd_gen_time_naive), execute_bdd_tool(BDDFile_naive, BDDParFile, Prob_naive, Status_naive), - statistics(walltime,[_, BDDGenerationTime_naive]), - (Status_naive = ok -> - problog_var_set(bdd_generation_time(naive), BDDGenerationTime_naive), + timer_stop(bdd_gen_time_naive,BDD_Gen_Time_Naive), + (Status_naive == ok -> + problog_var_set(bdd_generation_time(naive),BDD_Gen_Time_Naive), problog_var_set(probability(naive), Prob_naive) ; problog_var_set(bdd_generation_time(naive), fail), @@ -1625,9 +1638,6 @@ eval_dnf(OriTrie1, Prob, Status) :- ; true ), -% problog_statistics, -% print_nested_ptree(Trie), -% findall(_,(problog_chktabled(_ID, _T), writeln(problog_chktabled(_ID, _T))),_), % reduction method with depth_breadth trie support problog_flag(db_trie_opt_lvl, ROptLevel), problog_flag(db_min_prefix, MinPrefix), @@ -1640,8 +1650,7 @@ eval_dnf(OriTrie1, Prob, Status) :- forall(member(OptLevel, Levels), ( (problog_flag(use_db_trie, true) -> tries:trie_db_opt_min_prefix(MinPrefix), - statistics(walltime, _), -% atomic_concat([BDDFile, '_builtin_', OptLevel], BDDFile_builtin), + timer_start(script_gen_time_builtin), BDDFile = BDDFile_builtin, (nb_getval(problog_nested_tries, false) -> trie_to_bdd_trie(Trie, DBTrie, BDDFile_builtin, OptLevel, BDDParFile) @@ -1657,16 +1666,17 @@ eval_dnf(OriTrie1, Prob, Status) :- problog_var_set(dbtrie_statistics(Builtin), tries(memory(FM), tries(FT), entries(FE), nodes(FN))), delete_ptree(DBTrie), - statistics(walltime, [_, ScriptGenerationTime_builtin]), - problog_var_set(bdd_script_time(Builtin), ScriptGenerationTime_builtin), + timer_stop(script_gen_time_builtin,Script_Gen_Time_Builtin), + + problog_var_set(bdd_script_time(Builtin), Script_Gen_Time_Builtin), - statistics(walltime, _), + timer_start(bdd_gen_time_builtin), execute_bdd_tool(BDDFile_builtin, BDDParFile, Prob_builtin, Status_builtin), - statistics(walltime,[_, BDDGenerationTime_builtin]), + timer_stop(bdd_gen_time_builtin,BDD_Gen_Time_Builtin), ptree_db_trie_opt_performed(LVL1, LVL2, LV3), problog_var_set(db_trie_opts_performed(Builtin), opt_perform(LVL1, LVL2, LV3)), - (Status_builtin = ok -> - problog_var_set(bdd_generation_time(Builtin), BDDGenerationTime_builtin), + (Status_builtin == ok -> + problog_var_set(bdd_generation_time(Builtin), BDD_Gen_Time_Builtin), problog_var_set(probability(Builtin), Prob_builtin) ; problog_var_set(bdd_generation_time(Builtin), fail), @@ -1679,18 +1689,17 @@ eval_dnf(OriTrie1, Prob, Status) :- % decomposition method (problog_flag(use_dec_trie, true) -> - statistics(walltime, _), -% atomic_concat([BDDFile, '_dec'], BDDFile_dec), BDDFile = BDDFile_dec, + timer_start(script_gen_time_dec), ptree_decomposition(Trie, BDDFile_dec, BDDParFile), - statistics(walltime, [_, ScriptGenerationTime_dec]), - problog_var_set(bdd_script_time(dec), ScriptGenerationTime_dec), + timer_stop(script_gen_time_dec,Script_Gen_Time_Dec), + problog_var_set(bdd_script_time(dec), Script_Gen_Time_Dec), - statistics(walltime, _), + timer_start(bdd_gen_time_dec), execute_bdd_tool(BDDFile_dec, BDDParFile, Prob_dec, Status_dec), - statistics(walltime,[_, BDDGenerationTime_dec]), - (Status_dec = ok -> - problog_var_set(bdd_generation_time(dec), BDDGenerationTime_dec), + timer_stop(bdd_gen_time_dec,BDD_Gen_Time_Dec), + (Status_dec == ok -> + problog_var_set(bdd_generation_time(dec), BDD_Gen_Time_Dec), problog_var_set(probability(dec), Prob_dec) ; problog_var_set(bdd_generation_time(dec), fail), @@ -1948,13 +1957,13 @@ compute_bounds(LP, UP, Status) :- problog_low(Goal, Threshold, _, _) :- init_problog_low(Threshold), problog_control(off, up), - statistics(walltime, _), + timer_start(sld_time), problog_call(Goal), add_solution, fail. problog_low(_, _, LP, Status) :- - statistics(walltime, [_,E]), %theo - problog_var_set(sld_time, E), + timer_stop(sld_time,SLD_Time), + problog_var_set(sld_time, SLD_Time), nb_getval(problog_completed_proofs, Trie_Completed_Proofs), eval_dnf(Trie_Completed_Proofs, LP, Status), (problog_flag(verbose, true)-> @@ -2046,13 +2055,7 @@ evalStep(Ans,Status) :- nb_getval(problog_stopped_proofs, Trie_Stopped_Proofs), count_ptree(Trie_Completed_Proofs, NProofs), count_ptree(Trie_Stopped_Proofs, NCands), - ( - problog_flag(verbose,true) - -> - format(user,'~w proofs, ~w stopped derivations~n',[NProofs,NCands]); - true - ), - flush_output(user), + format_if_verbose(user,'~w proofs, ~w stopped derivations~n',[NProofs,NCands]), eval_lower(NProofs,Low,StatusLow), ( StatusLow \== ok @@ -2073,8 +2076,7 @@ evalStep(Ans,Status) :- Status = StatusUp ; Diff is Up-Low, - (problog_flag(verbose,true) -> format(user,'difference: ~6f~n',[Diff]);true), - flush_output(user), + format_if_verbose(user,'difference: ~6f~n',[Diff]), ((Diff < Delta; Diff =:= 0) -> Ans = 1; Ans = 0), Status = ok ) @@ -2088,13 +2090,12 @@ eval_lower(N,P,Status) :- N > 0, low(OldN,_), N \= OldN, - nb_getval(problog_completed_proofs, Trie_Completed_Proofs), + nb_getval(problog_completed_proofs, Trie_Completed_Proofs), eval_dnf(Trie_Completed_Proofs,P,Status), - (Status = ok -> + (Status == ok -> retract(low(_,_)), assertz(low(N,P)), - (problog_flag(verbose,true) -> format(user,'lower bound: ~6f~n',[P]);true), - flush_output(user) + format_if_verbose(user,'lower bound: ~6f~n',[P]) ; true). @@ -2113,12 +2114,11 @@ eval_upper(N,UpP,ok) :- nb_setval(problog_all_proofs, Trie_All_Proofs), eval_dnf(Trie_All_Proofs,UpP,StatusUp), delete_ptree(Trie_All_Proofs), - (StatusUp = ok -> + (StatusUp == ok -> retract(up(_,_)), assertz(up(N,UpP)) ; - (problog_flag(verbose,true) -> format(user,'~w - continue using old up~n',[StatusUp]);true), - flush_output(user), + format_if_verbose(user,'~w - continue using old up~n',[StatusUp]), up(_,UpP) ). @@ -2150,17 +2150,14 @@ init_problog_max(Threshold) :- update_max :- b_getval(problog_probability, CurrP), max_probability(MaxP), - (CurrP =< MaxP -> - fail - ; - b_getval(problog_current_proof, IDs), - open_end_close_end(IDs, R), - retractall(max_proof(_)), - assertz(max_proof(R)), - nb_setval(problog_threshold, CurrP), - retractall(max_probability(_)), - assertz(max_probability(CurrP)) - ). + CurrP>MaxP, + b_getval(problog_current_proof, IDs), + open_end_close_end(IDs, R), + retractall(max_proof(_)), + assertz(max_proof(R)), + nb_setval(problog_threshold, CurrP), + retractall(max_probability(_)), + assertz(max_probability(CurrP)). problog_max_id(Goal, _Prob, _Clauses) :- problog_call(Goal), @@ -2276,12 +2273,10 @@ problog_kbest_id(Goal, K) :- update_kbest(K) :- b_getval(problog_probability,NewLogProb), current_kbest(LogThreshold,_,_), - (NewLogProb>=LogThreshold -> - b_getval(problog_current_proof,RevProof), - open_end_close_end(RevProof,Proof), - update_current_kbest(K,NewLogProb,Proof) - ; - fail). + NewLogProb>=LogThreshold, + b_getval(problog_current_proof,RevProof), + open_end_close_end(RevProof,Proof), + update_current_kbest(K,NewLogProb,Proof). update_current_kbest(_,NewLogProb,Cl) :- current_kbest(_,List,_), @@ -2312,7 +2307,7 @@ sorted_insert(A-LA,[B1-LB1|B], [B1-LB1|C] ) :- % keeps all entries with lowest probability, even if implying a total of more than k cutoff(List,Len,1,List,Len) :- !. cutoff([P-L|List],Length,First,[P-L|List],Length) :- - nth(First,[P-L|List],PF-_), + nth1(First,[P-L|List],PF-_), PF=:=P, !. cutoff([_|List],Length,First,NewList,NewLength) :- @@ -2442,69 +2437,48 @@ problog_montecarlo(Goal,Delta,Prob) :- close_static_array(mc_sample). montecarlo(Goal,Delta,K,File) :- -% reset_static_array(mc_sample), clean_sample, problog_control(on,mc), open(File,write,Log), format(Log,'# goal: ~q~n#delta: ~w~n',[Goal,Delta]), format(Log,'# num_programs prob low high diff time~2n',[]), close(Log), - statistics(walltime,[T1,_]), - (problog_flag(verbose,true) -> format('search for ~q~n',[Goal]);true), - montecarlo(Goal,Delta,K,0,File,0,T1), + timer_start(monte_carlo), + format_if_verbose(user,'search for ~q~n',[Goal]), + montecarlo(Goal,Delta,K,0,File,0), + timer_stop(monte_carlo,_Monte_Carlo_Time), problog_control(off,mc). % calculate values after K samples -montecarlo(Goal,Delta,K,SamplesSoFar,File,PositiveSoFar,InitialTime) :- - SamplesNew is SamplesSoFar+1, - SamplesNew mod K =:= 0, - !, - copy_term(Goal,GoalC), - (mc_prove(GoalC) -> Next is PositiveSoFar+1; Next=PositiveSoFar), - Prob is Next/SamplesNew, - statistics(walltime,[T2,_]), - Time is (T2-InitialTime),%/1000, - - problog_convergence_check(Time, Prob, SamplesNew, Delta, _Epsilon, Converged), - ((Converged = true; Converged = terminate) -> - (problog_flag(verbose,true) -> - format('Runtime ~w ms~2n',[Time]) - ; - true - ), - assertz(mc_prob(Prob)) - ; - montecarlo(Goal,Delta,K,SamplesNew,File,Next,InitialTime) - ). - - -% Epsilon is 2*sqrt(Prob*(1-Prob)/SamplesNew), -% Low is Prob-Epsilon, -% High is Prob+Epsilon, -% Diff is 2*Epsilon, -% (problog_flag(verbose,true) -> format('~n~w samples~nestimated probability ~w~n95 percent confidence interval [~w,~w]~n',[SamplesNew,Prob,Low,High]);true), -% open(File,append,Log), -% format(Log,'~w ~8f ~8f ~8f ~8f ~3f~n',[SamplesNew,Prob,Low,High,Diff,Time]), -% close(Log), - - -% ((Diff -% (problog_flag(verbose,true) -> -% format('Runtime ~w sec~2n',[Time]) -% ; -% true -% ), -% assertz(mc_prob(Prob)) -% ; -% montecarlo(Goal,Delta,K,SamplesNew,File,Next,InitialTime) -% ). +montecarlo(Goal,Delta,K,SamplesSoFar,File,PositiveSoFar) :- + SamplesNew is SamplesSoFar+1, + SamplesNew mod K =:= 0, + !, + copy_term(Goal,GoalC), + ( + mc_prove(GoalC) + -> + Next is PositiveSoFar+1; + Next=PositiveSoFar + ), + Prob is Next/SamplesNew, + timer_elapsed(monte_carlo,Time), + problog_convergence_check(Time, Prob, SamplesNew, Delta, _Epsilon, Converged), + ( + (Converged == true; Converged == terminate) + -> + format_if_verbose(user,'Runtime ~w ms~2n',[Time]), + assertz(mc_prob(Prob)) + ; + montecarlo(Goal,Delta,K,SamplesNew,File,Next) + ). % continue until next K samples done -montecarlo(Goal,Delta,K,SamplesSoFar,File,PositiveSoFar,InitialTime) :- +montecarlo(Goal,Delta,K,SamplesSoFar,File,PositiveSoFar) :- SamplesNew is SamplesSoFar+1, copy_term(Goal,GoalC), (mc_prove(GoalC) -> Next is PositiveSoFar+1; Next=PositiveSoFar), - montecarlo(Goal,Delta,K,SamplesNew,File,Next,InitialTime). + montecarlo(Goal,Delta,K,SamplesNew,File,Next). mc_prove(A) :- !, (get_some_proof(A) -> @@ -2586,10 +2560,8 @@ problog_kbest_answers_id(Goal, K) :- update_kbest_answers(Goal,K) :- b_getval(problog_probability,NewLogProb), current_kbest(LogThreshold,_,_), - (NewLogProb>=LogThreshold -> - update_current_kbest_answers(K,NewLogProb,Goal) - ; - fail). + NewLogProb>=LogThreshold, + update_current_kbest_answers(K,NewLogProb,Goal). update_current_kbest_answers(_,NewLogProb,Goal) :- current_kbest(_,List,_), @@ -2700,7 +2672,7 @@ eval_bdd_forest(N,Probs,Status) :- Status = timeout ; statistics(walltime,[_,E3]), - (problog_flag(verbose,true) -> format(user,'~w ms BDD processing~n',[E3]);true), + format_if_verbose(user,'~w ms BDD processing~n',[E3]), see(ResultFile), read_probs(N,Probs), seen, @@ -2763,14 +2735,14 @@ build_trie(low(Threshold), Goal, _) :- number(Threshold), init_problog_low(Threshold), problog_control(off, up), - statistics(walltime, _), + timer_start(build_tree_low), problog_call(Goal), add_solution, fail. build_trie(low(Threshold), _, Trie) :- number(Threshold), - statistics(walltime, [_,E]), - problog_var_set(sld_time, E), + timer_stop(build_tree_low,Build_Tree_Low), + problog_var_set(sld_time, Build_Tree_Low), nb_getval(problog_completed_proofs, Trie). % don't clear tabling; tables can be reused by other query @@ -2957,11 +2929,11 @@ write_bdd_struct_script(Trie,BDDFile,Variables) :- % decomposition method (problog_flag(use_dec_trie, true) -> - statistics(walltime, _), atomic_concat([BDDFile, '_dec'], BDDFile_dec), + timer_start(script_gen_time_dec), ptree_decomposition_struct(Trie, BDDFile_dec, Variables), - statistics(walltime, [_, ScriptGenerationTime_dec]), - problog_var_set(bdd_script_time(dec), ScriptGenerationTime_dec) + timer_stop(script_gen_time_dec,Script_Gen_Time_Dec), + problog_var_set(bdd_script_time(dec), Script_Gen_Time_Dec) % omitted call to execute_bdd_tool ; true @@ -3018,37 +2990,33 @@ write_bdd_forest([Goal|Rest],VarsAcc,VarsTot,N):- % Write files write_nth_bdd_struct_script(N,Trie,Vars) :- - bdd_forest_file(N,BDDFile), - write_bdd_struct_script(Trie,BDDFile,Vars). + bdd_forest_file(N,BDDFile), + write_bdd_struct_script(Trie,BDDFile,Vars). write_global_bdd_file(NbVars,L) :- - bdd_file(BDDFile), - open(BDDFile,'write',BDDFileStream), - tell(BDDFileStream), - format('@BDD2~n~w~n~w~n~w~n',[NbVars,0,L]), - write_global_bdd_file_line(1,L), - write_global_bdd_file_query(1,L), - flush_output, - told. + bdd_file(BDDFile), + open(BDDFile,'write',BDDFileStream), + format(BDDFileStream,'@BDD2~n~w~n~w~n~w~n',[NbVars,0,L]), + write_global_bdd_file_line(1,L,BDDFileStream), + write_global_bdd_file_query(1,L,BDDFileStream), + close(BDDFileStream). -write_global_bdd_file_line(I,Max) :- - (I>Max -> - true - ; - bdd_forest_file(I,BDDFile), - format("L~q = <~w>~n",[I,BDDFile]), - I2 is I+1, - write_global_bdd_file_line(I2,Max) - ). +write_global_bdd_file_line(I,Max,_Handle) :- + I>Max, + !. +write_global_bdd_file_line(I,Max,Handle) :- + bdd_forest_file(I,BDDFile), + format(Handle,'L~q = <~w>~n',[I,BDDFile]), + I2 is I+1, + write_global_bdd_file_line(I2,Max,Handle). -write_global_bdd_file_query(I,Max) :- - (I=Max -> - format("L~q~n",[I]) - ; - format("L~q,",[I]), - I2 is I+1, - write_global_bdd_file_query(I2,Max) - ). +write_global_bdd_file_query(Max,Max,Handle) :- + !, + format(Handle,'L~q~n',[Max]). +write_global_bdd_file_query(I,Max,Handle) :- + format(Handle,'L~q,',[I]), + I2 is I+1, + write_global_bdd_file_query(I2,Max,Handle). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Filename specifications @@ -3057,19 +3025,19 @@ write_global_bdd_file_query(I,Max) :- bdd_forest_file(N,BDDFile) :- problog_flag(bdd_file,BDDFileFlag), atomic_concat([BDDFileFlag,'_',N],BDDFileFlagWithN), - convert_filename_to_working_path(BDDFileFlagWithN, BDDFile). + convert_filename_to_working_path(BDDFileFlagWithN, BDDFile). bdd_files(BDDFile,BDDParFile) :- bdd_file(BDDFile), bdd_par_file(BDDParFile). bdd_file(BDDFile) :- - problog_flag(bdd_file, BDDFileFlag), - convert_filename_to_working_path(BDDFileFlag, BDDFile). + problog_flag(bdd_file, BDDFileFlag), + convert_filename_to_working_path(BDDFileFlag, BDDFile). bdd_par_file(BDDParFile) :- - problog_flag(bdd_par_file, BDDParFileFlag), - convert_filename_to_working_path(BDDParFileFlag, BDDParFile). + problog_flag(bdd_par_file, BDDParFileFlag), + convert_filename_to_working_path(BDDParFileFlag, BDDParFile). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Persistent Ground IDs @@ -3109,6 +3077,16 @@ required(Feature) :- catch(b_getval(Feature_Required,Val),error(existence_error(variable,Feature_Required),_),fail), Val == required. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +format_if_verbose(H,T,L) :- + problog_flag(verbose,true), + !, + format(H,T,L). +format_if_verbose(_,_,_). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Should go to dtproblog.yap %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/packages/ProbLog/problog/logger.yap b/packages/ProbLog/problog/logger.yap index 4a1795e80..cfd68feb3 100644 --- a/packages/ProbLog/problog/logger.yap +++ b/packages/ProbLog/problog/logger.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-09-30 13:50:45 +0200 (Thu, 30 Sep 2010) $ -% $Revision: 4857 $ +% $Date: 2010-10-11 14:14:11 +0200 (Mon, 11 Oct 2010) $ +% $Revision: 4892 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -206,7 +206,6 @@ :- module(logger,[logger_define_variable/2, - logger_define_variables/2, logger_set_filename/1, logger_set_delimiter/1, logger_set_variable/2, @@ -238,25 +237,35 @@ %= +Name, +Type %======================================================================== -logger_define_variable(Name,int) :- +logger_define_variable(Name,Type) :- + bb_get(logger_variables,Variables), + member((Name,_),Variables), + !, + throw(error(variable_redefined(logger_define_variable(Name,Type)))). +logger_define_variable(Name,Type) :- + ground(Name), + atomic(Name), + !, + logger_define_variable_intern(Type,Name). +logger_define_variable(Name,Type) :- + throw(error(illegal_variable_name(logger_define_variable(Name,Type)))). + +logger_define_variable_intern(int,Name) :- !, - is_variable_already_defined(Name), bb_delete(logger_variables,OldVariables), append(OldVariables,[(Name,int)],NewVariables), bb_put(logger_variables,NewVariables), atom_concat(logger_data_,Name,Key), bb_put(Key,null). -logger_define_variable(Name,float) :- +logger_define_variable_intern(float,Name) :- !, - is_variable_already_defined(Name), bb_delete(logger_variables,OldVariables), append(OldVariables,[(Name,float)],NewVariables), bb_put(logger_variables,NewVariables), atom_concat(logger_data_,Name,Key), bb_put(Key,null). -logger_define_variable(Name,time) :- +logger_define_variable_intern(time,Name) :- !, - is_variable_already_defined(Name), bb_delete(logger_variables,OldVariables), append(OldVariables,[(Name,time)],NewVariables), bb_put(logger_variables,NewVariables), @@ -264,34 +273,9 @@ logger_define_variable(Name,time) :- atom_concat(logger_start_time_,Name,Key2), bb_put(Key,null), bb_put(Key2,null). -logger_define_variable(Name,Unknown) :- - is_variable_already_defined(Name), - write('logger_define_variable, unknown type '), - write(Unknown), - write(' for variable '), - write(Name), - nl, - fail. +logger_define_variable_intern(Type,Name) :- + throw(error(unknown_variable_type(logger_define_variable(Name,Type)))). -is_variable_already_defined(Name) :- - bb_get(logger_variables,Variables), - member((Name,_),Variables),!, - write('logger_define_variable, Variable '), - write(Name), - write(' is already defined!\n'), - fail; - true. - -%======================================================================== -%= -%= -%= +ListOfNames, +Type -%======================================================================== - -logger_define_variables([],_). -logger_define_variables([H|T],Type) :- - logger_define_variable(H,Type), - logger_define_variables(T,Type). %======================================================================== %= Set the filename, to which the output should be appended diff --git a/packages/ProbLog/problog/nestedtries.yap b/packages/ProbLog/problog/nestedtries.yap new file mode 100644 index 000000000..abeb512d2 --- /dev/null +++ b/packages/ProbLog/problog/nestedtries.yap @@ -0,0 +1,423 @@ +%%% -*- Mode: Prolog; -*- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% $Date: 2010-11-03 19:13:53 +0100 (Wed, 03 Nov 2010) $ +% $Revision: 4986 $ +% +% This file is part of ProbLog +% http://dtai.cs.kuleuven.be/problog +% +% ProbLog was developed at Katholieke Universiteit Leuven +% +% Copyright 2008, 2009, 2010 +% Katholieke Universiteit Leuven +% +% Main authors of this file: +% Theofrastos Mantadelis +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Artistic License 2.0 +% +% Copyright (c) 2000-2006, The Perl Foundation. +% +% Everyone is permitted to copy and distribute verbatim copies of this +% license document, but changing it is not allowed. Preamble +% +% This license establishes the terms under which a given free software +% Package may be copied, modified, distributed, and/or +% redistributed. The intent is that the Copyright Holder maintains some +% artistic control over the development of that Package while still +% keeping the Package available as open source and free software. +% +% You are always permitted to make arrangements wholly outside of this +% license directly with the Copyright Holder of a given Package. If the +% terms of this license do not permit the full use that you propose to +% make of the Package, you should contact the Copyright Holder and seek +% a different licensing arrangement. Definitions +% +% "Copyright Holder" means the individual(s) or organization(s) named in +% the copyright notice for the entire Package. +% +% "Contributor" means any party that has contributed code or other +% material to the Package, in accordance with the Copyright Holder's +% procedures. +% +% "You" and "your" means any person who would like to copy, distribute, +% or modify the Package. +% +% "Package" means the collection of files distributed by the Copyright +% Holder, and derivatives of that collection and/or of those files. A +% given Package may consist of either the Standard Version, or a +% Modified Version. +% +% "Distribute" means providing a copy of the Package or making it +% accessible to anyone else, or in the case of a company or +% organization, to others outside of your company or organization. +% +% "Distributor Fee" means any fee that you charge for Distributing this +% Package or providing support for this Package to another party. It +% does not mean licensing fees. +% +% "Standard Version" refers to the Package if it has not been modified, +% or has been modified only in ways explicitly requested by the +% Copyright Holder. +% +% "Modified Version" means the Package, if it has been changed, and such +% changes were not explicitly requested by the Copyright Holder. +% +% "Original License" means this Artistic License as Distributed with the +% Standard Version of the Package, in its current version or as it may +% be modified by The Perl Foundation in the future. +% +% "Source" form means the source code, documentation source, and +% configuration files for the Package. +% +% "Compiled" form means the compiled bytecode, object code, binary, or +% any other form resulting from mechanical transformation or translation +% of the Source form. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Permission for Use and Modification Without Distribution +% +% (1) You are permitted to use the Standard Version and create and use +% Modified Versions for any purpose without restriction, provided that +% you do not Distribute the Modified Version. +% +% Permissions for Redistribution of the Standard Version +% +% (2) You may Distribute verbatim copies of the Source form of the +% Standard Version of this Package in any medium without restriction, +% either gratis or for a Distributor Fee, provided that you duplicate +% all of the original copyright notices and associated disclaimers. At +% your discretion, such verbatim copies may or may not include a +% Compiled form of the Package. +% +% (3) You may apply any bug fixes, portability changes, and other +% modifications made available from the Copyright Holder. The resulting +% Package will still be considered the Standard Version, and as such +% will be subject to the Original License. +% +% Distribution of Modified Versions of the Package as Source +% +% (4) You may Distribute your Modified Version as Source (either gratis +% or for a Distributor Fee, and with or without a Compiled form of the +% Modified Version) provided that you clearly document how it differs +% from the Standard Version, including, but not limited to, documenting +% any non-standard features, executables, or modules, and provided that +% you do at least ONE of the following: +% +% (a) make the Modified Version available to the Copyright Holder of the +% Standard Version, under the Original License, so that the Copyright +% Holder may include your modifications in the Standard Version. (b) +% ensure that installation of your Modified Version does not prevent the +% user installing or running the Standard Version. In addition, the +% modified Version must bear a name that is different from the name of +% the Standard Version. (c) allow anyone who receives a copy of the +% Modified Version to make the Source form of the Modified Version +% available to others under (i) the Original License or (ii) a license +% that permits the licensee to freely copy, modify and redistribute the +% Modified Version using the same licensing terms that apply to the copy +% that the licensee received, and requires that the Source form of the +% Modified Version, and of any works derived from it, be made freely +% available in that license fees are prohibited but Distributor Fees are +% allowed. +% +% Distribution of Compiled Forms of the Standard Version or +% Modified Versions without the Source +% +% (5) You may Distribute Compiled forms of the Standard Version without +% the Source, provided that you include complete instructions on how to +% get the Source of the Standard Version. Such instructions must be +% valid at the time of your distribution. If these instructions, at any +% time while you are carrying out such distribution, become invalid, you +% must provide new instructions on demand or cease further +% distribution. If you provide valid instructions or cease distribution +% within thirty days after you become aware that the instructions are +% invalid, then you do not forfeit any of your rights under this +% license. +% +% (6) You may Distribute a Modified Version in Compiled form without the +% Source, provided that you comply with Section 4 with respect to the +% Source of the Modified Version. +% +% Aggregating or Linking the Package +% +% (7) You may aggregate the Package (either the Standard Version or +% Modified Version) with other packages and Distribute the resulting +% aggregation provided that you do not charge a licensing fee for the +% Package. Distributor Fees are permitted, and licensing fees for other +% components in the aggregation are permitted. The terms of this license +% apply to the use and Distribution of the Standard or Modified Versions +% as included in the aggregation. +% +% (8) You are permitted to link Modified and Standard Versions with +% other works, to embed the Package in a larger work of your own, or to +% build stand-alone binary or bytecode versions of applications that +% include the Package, and Distribute the result without restriction, +% provided the result does not expose a direct interface to the Package. +% +% Items That are Not Considered Part of a Modified Version +% +% (9) Works (including, but not limited to, modules and scripts) that +% merely extend or make use of the Package, do not, by themselves, cause +% the Package to be a Modified Version. In addition, such works are not +% considered parts of the Package itself, and are not subject to the +% terms of this license. +% +% General Provisions +% +% (10) Any use, modification, and distribution of the Standard or +% Modified Versions is governed by this Artistic License. By using, +% modifying or distributing the Package, you accept this license. Do not +% use, modify, or distribute the Package, if you do not accept this +% license. +% +% (11) If your Modified Version has been derived from a Modified Version +% made by someone other than you, you are nevertheless required to +% ensure that your Modified Version complies with the requirements of +% this license. +% +% (12) This license does not grant you the right to use any trademark, +% service mark, tradename, or logo of the Copyright Holder. +% +% (13) This license includes the non-exclusive, worldwide, +% free-of-charge patent license to make, have made, use, offer to sell, +% sell, import and otherwise transfer the Package with respect to any +% patent claims licensable by the Copyright Holder that are necessarily +% infringed by the Package. If you institute patent litigation +% (including a cross-claim or counterclaim) against any party alleging +% that the Package constitutes direct or contributory patent +% infringement, then this Artistic License to you shall terminate on the +% date that such litigation is filed. +% +% (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT +% HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED +% WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +% PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT +% PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT +% HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, +% INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE +% OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% nested tries handling +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +:- module(nestedtries, [nested_trie_to_depth_breadth_trie/4]). + +:- use_module(library(ordsets), [list_to_ord_set/2, ord_subset/2]). % this two might be better to do a custom fast implementation +:- use_module(library(lists), [memberchk/2, delete/3]). +:- use_module(library(tries), [trie_to_depth_breadth_trie/6, trie_get_depth_breadth_reduction_entry/1, trie_dup/2, trie_close/1, trie_open/1, trie_replace_nested_trie/3, trie_remove_entry/1, trie_get_entry/2, trie_put_entry/3, trie_traverse/2]). + +:- use_module(flags, [problog_define_flag/5, problog_flag/2]). + +:- style_check(all). +:- yap_flag(unknown,error). + +:- initialization(( +% problog_define_flag(subset_check, problog_flag_validate_boolean, 'perform subset check in nested tries', true, nested_tries), + problog_define_flag(loop_refine_ancs, problog_flag_validate_boolean, 'refine ancestors if no loop exists', true, nested_tries) +% problog_define_flag(trie_preprocess, problog_flag_validate_boolean, 'perform a preprocess step to nested tries', false, nested_tries), +% problog_define_flag(refine_anclst, problog_flag_validate_boolean, 'refine the ancestor list with their childs', false, nested_tries), +% problog_define_flag(anclst_represent,problog_flag_validate_in_list([list, integer]), 'represent the ancestor list', list, nested_tries) +)). + + +trie_replace_entry(_Trie, Entry, _E, false):- + !, trie_remove_entry(Entry). +trie_replace_entry(Trie, Entry, E, true):- + !, trie_get_entry(Entry, Proof), + delete(Proof, E, NewProof), + (NewProof == [] -> + trie_delete(Trie), + trie_put_entry(Trie, [true], _) + ; + trie_remove_entry(Entry), + trie_put_entry(Trie, NewProof, _) + ). +trie_replace_entry(Trie, _Entry, t(ID), R):- + trie_replace_nested_trie(Trie, ID, R). + +trie_delete(Trie):- + trie_traverse(Trie, R), + trie_remove_entry(R), + fail. +trie_delete(_Trie). + +is_state(Variable):- + Variable == true, !. +is_state(Variable):- + Variable == false. +is_state(Variable):- + nonvar(Variable), + Variable = not(NestedVariable), + is_state(NestedVariable). + +is_trie(Trie, ID):- + nonvar(Trie), + Trie = t(ID), !. +is_trie(Trie, ID):- + nonvar(Trie), + Trie = not(NestedTrie), + is_trie(NestedTrie, ID). + +is_label(Label, ID):- + atom(Label), !, + atomic_concat('L', ID, Label). +is_label(Label, ID):- + nonvar(Label), + Label = not(NestedLabel), + is_label(NestedLabel, ID). + +% Ancestor related stuff + +initialise_ancestors(0):- + problog_flag(anclst_represent, integer). +initialise_ancestors([]):- + problog_flag(anclst_represent, list). + +add_to_ancestors(ID, Ancestors, NewAncestors):- + integer(Ancestors), !, + NewAncestors is (1 << (ID - 1)) \/ Ancestors. +add_to_ancestors(ID, Ancestors, NewAncestors):- + is_list(Ancestors), + list_to_ord_set([ID|Ancestors], NewAncestors). + +ancestor_subset_check(SubAncestors, Ancestors):- + integer(SubAncestors), !, + SubAncestors is Ancestors /\ SubAncestors. +ancestor_subset_check(SubAncestors, Ancestors):- + is_list(SubAncestors), + ord_subset(SubAncestors, Ancestors). + +ancestor_loop_refine(Loop, Ancestors, 0):- + var(Loop), integer(Ancestors), !. +ancestor_loop_refine(Loop, Ancestors, []):- + var(Loop), is_list(Ancestors), !. +ancestor_loop_refine(true, Ancestors, Ancestors). + +% Cycle check related stuff +% missing synonym check + +cycle_check(ID, Ancestors):- + integer(Ancestors), !, + Bit is 1 << (ID - 1), + Bit is Bit /\ Ancestors. +cycle_check(ID, Ancestors):- + is_list(Ancestors), + memberchk(ID, Ancestors). + +preprocess(Index, DepthBreadthTrie, OptimizationLevel, StartCount, FinalEndCount):- + problog:problog_chktabled(Index, Trie), !, + trie_dup(Trie, CopyTrie), + initialise_ancestors(Ancestors), + make_nested_trie_base_cases(CopyTrie, t(Index), DepthBreadthTrie, OptimizationLevel, StartCount, EndCount, Ancestors), + trie_close(CopyTrie), + Next is Index + 1, + preprocess(Next, DepthBreadthTrie, OptimizationLevel, EndCount, FinalEndCount). +preprocess(_, _, _, FinalEndCount, FinalEndCount). + +make_nested_trie_base_cases(Trie, t(ID), DepthBreadthTrie, OptimizationLevel, StartCount, FinalEndCount, Ancestors):- + trie_to_depth_breadth_trie(Trie, DepthBreadthTrie, Label, OptimizationLevel, StartCount, EndCount), + (is_trie(Label, SID) -> + trie_get_depth_breadth_reduction_entry(NestedEntry), + trie_replace_entry(Trie, NestedEntry, Label, false), + add_to_ancestors(SID, Ancestors, NewAncestors), + make_nested_trie_base_cases(Trie, t(ID), DepthBreadthTrie, OptimizationLevel, EndCount, FinalEndCount, NewAncestors) + ; + FinalEndCount = EndCount, + get_set_trie(ID, Label, Ancestors) + ). + +nested_trie_to_depth_breadth_trie(Trie, DepthBreadthTrie, FinalLabel, OptimizationLevel):- + integer(OptimizationLevel), + trie_open(DepthBreadthTrie), + (problog_flag(trie_preprocess, true) -> + preprocess(1, DepthBreadthTrie, OptimizationLevel, 0, StartCount) + ; + StartCount = 0 + ), + initialise_ancestors(Ancestors), +% initialise_ancestors(Childs), + (problog_flag(loop_refine_ancs, true) -> + trie_2_dbtrie_init(Trie, DepthBreadthTrie, OptimizationLevel, StartCount, _, Ancestors, FinalLabel, _) + ; + trie_2_dbtrie_init(Trie, DepthBreadthTrie, OptimizationLevel, StartCount, _, Ancestors, FinalLabel, true) + ), + eraseall(problog_trie_table). + +trie_2_dbtrie_init(ID, DepthBreadthTrie, OptimizationLevel, StartCount, EndCount, Ancestors, Label, ContainLoop):- + get_trie_pointer(ID, Trie), + trie_dup(Trie, CopyTrie), + trie_2_dbtrie_intern(CopyTrie, DepthBreadthTrie, OptimizationLevel, StartCount, EndCount, Ancestors, Label, ContainLoop), + trie_close(CopyTrie). + +trie_2_dbtrie_intern(Trie, DepthBreadthTrie, OptimizationLevel, StartCount, FinalEndCount, Ancestors, TrieLabel, ContainLoop):- + trie_to_depth_breadth_trie(Trie, DepthBreadthTrie, Label, OptimizationLevel, StartCount, EndCount), + (is_trie(Label, ID) -> % Label might have issues with negation + trie_get_depth_breadth_reduction_entry(NestedEntry), + % check if Trie introduces a loop + (cycle_check(ID, Ancestors) -> + ContainLoop = true, + NewLabel = false, + NewEndCount = EndCount + ; + % check if Trie is resolved and extract it + (get_set_trie(ID, NewLabel, Ancestors) -> + NewEndCount = EndCount + ; + % calculate the nested trie + add_to_ancestors(ID, Ancestors, NewAncestors), % to be able to support 2 representations + trie_2_dbtrie_init(ID, DepthBreadthTrie, OptimizationLevel, EndCount, NewEndCount, NewAncestors, NewLabel, NewContainLoop), + ancestor_loop_refine(NewContainLoop, Ancestors, RefinedAncestors), + get_set_trie(ID, NewLabel, RefinedAncestors), + ContainLoop = NewContainLoop + ) + ), + trie_replace_entry(Trie, NestedEntry, t(ID), NewLabel), % should be careful to verify that it works also with not(t(ID)) + trie_2_dbtrie_intern(Trie, DepthBreadthTrie, OptimizationLevel, NewEndCount, FinalEndCount, Ancestors, TrieLabel, ContainLoop) + ; + % else we can terminate and return + FinalEndCount = EndCount, + TrieLabel = Label + ). + +% predicate to check/remember resolved tries +% no refiment of ancestor list included + +get_trie_pointer(ID, Trie):- + problog:problog_chktabled(ID, Trie), !. +get_trie_pointer(Trie, Trie). + +get_set_trie(Trie, Label, Ancestors):- + recorded(problog_trie_table, store(Trie, StoredAncestors, Label), _), + (problog_flag(subset_check, true) -> + ancestor_subset_check(StoredAncestors, Ancestors) + ; + StoredAncestors == Ancestors + ), !. +get_set_trie(Trie, Label, Ancestors):- + ground(Label), + recordz(problog_trie_table, store(Trie, Ancestors, Label), _). + + +% chk_negated([H|T], ID):- +% simplify(H, not(t(ID))), !. +% chk_negated([_|T], ID):- +% chk_negated(T, ID). + + +/* +chk_negated([], ID, ID). +chk_negated([H|T], ID, not(ID)):- + simplify(H, not(t(ID))), !. +chk_negated([H|T], ID, ID):- + simplify(H, t(ID)), !. +chk_negated([_|T], ID, FID):- + chk_negated(T, ID, FID).*/ diff --git a/packages/ProbLog/problog/tabling.yap b/packages/ProbLog/problog/tabling.yap index 7ba047a96..118bb5f27 100644 --- a/packages/ProbLog/problog/tabling.yap +++ b/packages/ProbLog/problog/tabling.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-10-06 12:56:13 +0200 (Wed, 06 Oct 2010) $ -% $Revision: 4877 $ +% $Date: 2010-11-03 19:08:13 +0100 (Wed, 03 Nov 2010) $ +% $Revision: 4984 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -445,6 +445,7 @@ problog_neg(M:G):- functor(G, Name, Arity), \+ problog_tabled(M:Name/Arity), \+ problog:problog_predicate(Name, Arity), + \+ (Name == problog_neg, Arity == 1), throw(problog_neg_error('Error: goal must be dynamic and tabled', M:G)). problog_neg(M:G):- % exact inference diff --git a/packages/ProbLog/problog/timer.yap b/packages/ProbLog/problog/timer.yap index b0aed892e..d8d6617d6 100644 --- a/packages/ProbLog/problog/timer.yap +++ b/packages/ProbLog/problog/timer.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-09-28 21:04:43 +0200 (Tue, 28 Sep 2010) $ -% $Revision: 4838 $ +% $Date: 2010-10-15 17:09:55 +0200 (Fri, 15 Oct 2010) $ +% $Revision: 4939 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -208,9 +208,10 @@ :- module(timer,[timer_start/1, % +ID timer_stop/2, % +ID,-Duration timer_pause/1, % +ID - timer_pause/2, % +ID - timer_resume/1]). % +ID - + timer_pause/2, % +ID,-Duration + timer_resume/1, % +ID + timer_elapsed/2, % +ID, -Duration + timer_reset/1]). % +ID :- yap_flag(unknown,error). :- style_check(single_var). @@ -228,6 +229,11 @@ timer_start(Name) :- assertz(timer(Name,StartTime)) ). +timer_start_forced(Name) :- + retractall(timer(Name,_)), + statistics(walltime,[StartTime,_]), + assertz(timer(Name,StartTime)). + timer_stop(Name,Duration) :- ( retract(timer(Name,StartTime)) @@ -270,3 +276,17 @@ timer_resume(Name):- throw(timer_not_paused(timer_resume(Name))) ). + +timer_elapsed(Name,Duration) :- + ( + timer(Name,StartTime) + -> + statistics(walltime,[StopTime,_]), + Duration is StopTime-StartTime; + + throw(timer_not_started(timer_elapsed(Name,Duration))) + ). + +timer_reset(Name) :- + retractall(timer(Name,_)), + retractall(timer_paused(Name,_)). \ No newline at end of file diff --git a/packages/ProbLog/problog/tptree.yap b/packages/ProbLog/problog/tptree.yap index c6e4d0740..9ff552589 100644 --- a/packages/ProbLog/problog/tptree.yap +++ b/packages/ProbLog/problog/tptree.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-09-28 21:04:43 +0200 (Tue, 28 Sep 2010) $ -% $Revision: 4838 $ +% $Date: 2010-11-03 19:08:13 +0100 (Wed, 03 Nov 2010) $ +% $Revision: 4984 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -247,11 +247,15 @@ % load library modules :- use_module(library(tries)). :- use_module(library(lists), [append/3, member/2, memberchk/2, delete/3]). -:- use_module(library(system), [delete_file/1, shell/1, tmpnam/1]). +:- use_module(library(system), [tmpnam/1]). :- use_module(library(ordsets), [ord_intersection/3, ord_union/3]). + + % load our own modules :- use_module(flags). +:- use_module(utils). +:- use_module(nestedtries, [nested_trie_to_depth_breadth_trie/4]). % switch on all tests to reduce bug searching time :- style_check(all). @@ -463,30 +467,31 @@ name_vars([A|B]) :- nested_ptree_to_BDD_struct_script(Trie, BDDFileName, Variables):- tmpnam(TmpFile1), - tmpnam(TmpFile2), open(TmpFile1, 'write', BDDS), - (generate_BDD_from_trie(Trie, Inter, BDDS) -> - next_intermediate_step(TMP), InterCNT is TMP - 1, - write(BDDS, Inter), nl(BDDS), + + ( + generate_BDD_from_trie(Trie, Inter, BDDS) + -> + ( + next_intermediate_step(TMP), + InterCNT is TMP - 1, + format(BDDS,'~q~n',[Inter]), close(BDDS), - (get_used_vars(Variables, VarCNT);VarCNT = 0), - open(TmpFile2, 'write', HEADERS), - write(HEADERS, '@BDD1'), nl(HEADERS), - write(HEADERS, VarCNT), nl(HEADERS), - write(HEADERS, 0), nl(HEADERS), - write(HEADERS, InterCNT), nl(HEADERS), - close(HEADERS), - atomic_concat(['cat ', TmpFile2, ' ', TmpFile1, ' > ', BDDFileName], CMD), - shell(CMD), - delete_file(TmpFile1), - delete_file(TmpFile2), + ( + get_used_vars(Variables, VarCNT) + -> + true; + VarCNT = 0 + ), + create_bdd_file_with_header(BDDFileName,VarCNT,InterCNT,TmpFile1), + delete_file_silent(TmpFile1), cleanup_BDD_generation - ; + );( close(BDDS), - (delete_file(TmpFile1);true), - (delete_file(TmpFile2);true), + delete_file_silent(TmpFile1), cleanup_BDD_generation, fail + ) ). trie_to_bdd_struct_trie(A, B, OutputFile, OptimizationLevel, Variables) :- @@ -528,7 +533,8 @@ trie_to_bdd_struct_trie(A, B, OutputFile, OptimizationLevel, Variables) :- ). nested_trie_to_bdd_struct_trie(A, B, OutputFile, OptimizationLevel, Variables):- - trie_nested_to_depth_breadth_trie(A, B, LL, OptimizationLevel, problog:problog_chktabled), + %trie_nested_to_depth_breadth_trie(A, B, LL, OptimizationLevel, problog:problog_chktabled), + nested_trie_to_depth_breadth_trie(A, B, LL, OptimizationLevel), (is_label(LL) -> retractall(deref(_,_)), (problog_flag(deref_terms, true) -> @@ -571,15 +577,20 @@ nested_trie_to_bdd_struct_trie(A, B, OutputFile, OptimizationLevel, Variables):- write(1), nl, write(0), nl, write(1), nl, - get_var_name(LL, NLL), - write('L1 = '),write(NLL),nl, + simplify(LL, FLL), + (FLL = not(_) -> + write('L1 = ~') + ; + write('L1 = ') + ), + get_var_name(FLL, NLL), + write(NLL),nl, write('L1'), nl, told ). ptree_decomposition_struct(Trie, BDDFileName, Variables) :- tmpnam(TmpFile1), - tmpnam(TmpFile2), nb_setval(next_inter_step, 1), variables_in_dbtrie(Trie, Variables), length(Variables, VarCnt), @@ -599,16 +610,8 @@ ptree_decomposition_struct(Trie, BDDFileName, Variables) :- write('L1'), nl ), told, - tell(TmpFile2), - write('@BDD1'),nl, - write(VarCnt),nl, - write('0'),nl, - write(LCnt),nl, - told, - atomic_concat(['cat ', TmpFile2, ' ', TmpFile1, ' > ', BDDFileName], CMD), - shell(CMD), - delete_file(TmpFile1), - delete_file(TmpFile2). + create_bdd_file_with_header(BDDFileName,VarCnt,LCnt,TmpFile1), + delete_file_silent(TmpFile1). %%%%%%%%%%%%%%%%%%%%%%%% % write BDD info for given ptree to file @@ -696,10 +699,10 @@ bdd_vars_script_intern(A) :- ). bdd_vars_script_intern2(A) :- get_var_name(A,NameA), - atom_chars(A,A_Chars), + atom_codes(A,A_Codes), - once(append(Part1,[95|Part2],A_Chars)), % 95 = '_' - number_chars(ID,Part1), + once(append(Part1,[95|Part2],A_Codes)), % 95 = '_' + number_codes(ID,Part1), ( % let's check whether Part2 contains an 'l' (l=low) member(108,Part2) @@ -709,7 +712,7 @@ bdd_vars_script_intern2(A) :- format('@~w~n0~n0~n~12f;~12f~n',[NameA,Mu,Sigma]) ); ( - number_chars(Grounding_ID,Part2), + number_codes(Grounding_ID,Part2), (problog:decision_fact(ID,_) -> % it's a non-ground decision (problog:problog_control(check,internal_strategy) -> @@ -987,8 +990,44 @@ get_next_name(Name) :- % create BDD-var as fact id prefixed by x % learning.yap relies on this format! % when changing, also adapt test_var_name/1 below + + +simplify_list(List, SList):- + findall(NEL, (member(El, List), simplify(El, NEL)), SList). + +simplify(not(false), true):- !. +simplify(not(true), false):- !. +simplify(not(not(A)), B):- + !, simplify(A, B). +simplify(A, A). + + + +simplify(not(false), true):- !. +simplify(not(true), false):- !. +simplify(not(not(A)), B):- + !, simplify(A, B). +simplify(A, A). + +get_var_name(true, 'TRUE'):- !. +get_var_name(false, 'FALSE'):- !. +get_var_name(Variable, Name):- + atomic(Variable), !, + atomic_concat([x, Variable], Name), + (recorded(map, m(Variable, Name), _) -> + true + ; + recorda(map, m(Variable, Name), _) + ). +get_var_name(not(A), NameA):- + get_var_name(A, NameA). + + +/* get_var_name(true, 'TRUE') :-!. get_var_name(false, 'FALSE') :-!. +get_var_name(not(A), NameA):- + !, get_var_name(A, NameA). get_var_name(A, NameA) :- atomic_concat([x, A], NameA), ( @@ -997,7 +1036,7 @@ get_var_name(A, NameA) :- true ; recorda(map, m(A, NameA), _) - ). + ).*/ % test used by base case of compression mapping to detect single-variable tree % has to match above naming scheme @@ -1060,39 +1099,29 @@ spacy_print(Msg, Level, Space):- :- dynamic(generated_trie/2). :- dynamic(next_intermediate_step/1). -% -% This needs to be modified -% Include nasty code of temporary file usage -% also it is OS depended (requires the cat utility) -% nested_ptree_to_BDD_script(Trie, BDDFileName, VarFileName):- tmpnam(TmpFile1), - tmpnam(TmpFile2), open(TmpFile1, 'write', BDDS), (generate_BDD_from_trie(Trie, Inter, BDDS) -> next_intermediate_step(TMP), InterCNT is TMP - 1, write(BDDS, Inter), nl(BDDS), close(BDDS), - (get_used_vars(Vars, VarCNT);VarCNT = 0), - open(TmpFile2, 'write', HEADERS), - write(HEADERS, '@BDD1'), nl(HEADERS), - write(HEADERS, VarCNT), nl(HEADERS), - write(HEADERS, 0), nl(HEADERS), - write(HEADERS, InterCNT), nl(HEADERS), - close(HEADERS), - atomic_concat(['cat ', TmpFile2, ' ', TmpFile1, ' > ', BDDFileName], CMD), - shell(CMD), - delete_file(TmpFile1), - delete_file(TmpFile2), + ( + get_used_vars(Vars, VarCNT) + -> + true; + VarCNT = 0 + ), + create_bdd_file_with_header(BDDFileName,VarCNT,InterCNT,TmpFile1), + delete_file_silent(TmpFile1), open(VarFileName, 'write', VarStream), bddvars_to_script(Vars, VarStream), close(VarStream), cleanup_BDD_generation ; close(BDDS), - (delete_file(TmpFile1);true), - (delete_file(TmpFile2);true), + delete_file_silent(TmpFile1), cleanup_BDD_generation, fail ). @@ -1136,7 +1165,7 @@ write_bdd_lineterm([LineTerm|LineTerms], Operator, Stream):- generate_line([], [], Inter, _Stream):- !, get_next_intermediate_step(Inter). -generate_line([neg(t(Hash))|L], [TrieInter|T] , Inter, Stream):- +generate_line([not(t(Hash))|L], [TrieInter|T] , Inter, Stream):- !, problog:problog_chktabled(Hash, Trie), generate_BDD_from_trie(Trie, TrieInterTmp, Stream), atomic_concat(['~', TrieInterTmp], TrieInter), @@ -1159,11 +1188,11 @@ bddvars_to_script([H|T], Stream):- (number(H) -> CurVar = H ; - atom_chars(H, H_Chars), + atom_codes(H, H_Codes), % 95 = '_' - append(Part1, [95|Part2], H_Chars), - number_chars(CurVar, Part1), - number_chars(Grounding_ID, Part2) + append(Part1, [95|Part2], H_Codes), + number_codes(CurVar, Part1), + number_codes(Grounding_ID, Part2) ), (problog:dynamic_probability_fact(CurVar) -> problog:grounding_is_known(Goal, Grounding_ID), @@ -1198,16 +1227,17 @@ make_bdd_var(V, VName):- get_var_name(V, VName), add_to_vars(V). + add_to_vars(V):- - clause(get_used_vars(Vars, _Cnt), true), - memberchk(V, Vars),!. + clause(get_used_vars(Vars, _Cnt), true), + memberchk(V, Vars),!. add_to_vars(V):- - clause(get_used_vars(Vars, Cnt), true), !, - retract(get_used_vars(Vars, Cnt)), - NewCnt is Cnt + 1, - assertz(get_used_vars([V|Vars], NewCnt)). + clause(get_used_vars(Vars, Cnt), true), !, + retract(get_used_vars(Vars, Cnt)), + NewCnt is Cnt + 1, + assertz(get_used_vars([V|Vars], NewCnt)). add_to_vars(V):- - assertz(get_used_vars([V], 1)). + assertz(get_used_vars([V], 1)). %%%%%%%%%%%%%%% depth breadth builtin support %%%%%%%%%%%%%%%%% @@ -1310,7 +1340,8 @@ is_state(true). is_state(false). nested_trie_to_bdd_trie(A, B, OutputFile, OptimizationLevel, FileParam):- - trie_nested_to_depth_breadth_trie(A, B, LL, OptimizationLevel, problog:problog_chktabled), +% trie_nested_to_depth_breadth_trie(A, B, LL, OptimizationLevel, problog:problog_chktabled), + nested_trie_to_depth_breadth_trie(A, B, LL, OptimizationLevel), (is_label(LL) -> retractall(deref(_,_)), (problog_flag(deref_terms, true) -> @@ -1352,16 +1383,24 @@ nested_trie_to_bdd_trie(A, B, OutputFile, OptimizationLevel, FileParam):- ; Edges = [LL] ), + writeln(Edges), tell(FileParam), - bdd_vars_script(Edges), + simplify_list(Edges, SEdges), + bdd_vars_script(SEdges), told, tell(OutputFile), write('@BDD1'), nl, write(1), nl, write(0), nl, write(1), nl, - get_var_name(LL, NLL), - write('L1 = '),write(NLL),nl, + (LL = not(_) -> + write('L1 = ~') + ; + write('L1 = ') + ), + simplify(LL, FLL), + get_var_name(FLL, NLL), + write(NLL),nl, write('L1'), nl, told ). @@ -1792,7 +1831,6 @@ seperate([H|T], Labels, [H|Vars]):- ptree_decomposition(Trie, BDDFileName, VarFileName) :- tmpnam(TmpFile1), - tmpnam(TmpFile2), nb_setval(next_inter_step, 1), variables_in_dbtrie(Trie, T), length(T, VarCnt), @@ -1815,16 +1853,8 @@ ptree_decomposition(Trie, BDDFileName, VarFileName) :- write('L1'), nl ), told, - tell(TmpFile2), - write('@BDD1'),nl, - write(VarCnt),nl, - write('0'),nl, - write(LCnt),nl, - told, - atomic_concat(['cat ', TmpFile2, ' ', TmpFile1, ' > ', BDDFileName], CMD), - shell(CMD), - delete_file(TmpFile1), - delete_file(TmpFile2). + create_bdd_file_with_header(BDDFileName,VarCnt,LCnt,TmpFile1), + delete_file_silent(TmpFile1). get_next_inter_step(I):- nb_getval(next_inter_step, I), @@ -2012,3 +2042,22 @@ mark_deref(DB_Trie):- mark_deref(_). % end of Theo + +create_bdd_file_with_header(BDD_File_Name,VarCount,IntermediateSteps,TmpFile) :- + open(BDD_File_Name,write,H), + % this is the header of the BDD script for problogbdd + format(H, '@BDD1~n~q~n0~n~q~n',[VarCount,IntermediateSteps]), + + % append the content of the file TmpFile + open(TmpFile,read,H2), + + ( + repeat, + get_byte(H2,C), + put_byte(H,C), + at_end_of_stream(H2), + ! + ), + close(H2), + + close(H). \ No newline at end of file diff --git a/packages/ProbLog/problog/utils_learning.yap b/packages/ProbLog/problog/utils_learning.yap index 697add8b9..85402a6b2 100644 --- a/packages/ProbLog/problog/utils_learning.yap +++ b/packages/ProbLog/problog/utils_learning.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-09-29 13:24:43 +0200 (Wed, 29 Sep 2010) $ -% $Revision: 4845 $ +% $Date: 2010-10-20 18:06:47 +0200 (Wed, 20 Oct 2010) $ +% $Revision: 4969 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -205,9 +205,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :- module(utils_learning, [empty_bdd_directory/0, - empty_output_directory/0, - delete_file_silent/1, - slice_n/4]). + empty_output_directory/0]). % load library modules @@ -217,6 +215,7 @@ % load our own modules :- use_module(os). :- use_module(flags). +:- use_module(utils). %======================================================================== %= @@ -246,19 +245,8 @@ empty_output_directory :- concat_path_with_filename(Path,'log.dat',F1), concat_path_with_filename(Path,'out.dat',F2), - ( - file_exists(F1) - -> - delete_file_silent(F1); - true - ), - - ( - file_exists(F2) - -> - delete_file_silent(F2); - true - ), + delete_file_silent(F1), + delete_file_silent(F2), atom_codes('values_', PF1), % 'values_*_q_*.dat' atom_codes('factprobs_', PF2), % 'factprobs_*.pl' @@ -272,16 +260,7 @@ empty_output_directory :- empty_output_directory :- throw(error(problog_flag_does_not_exist(output_directory))). -%======================================================================== -%= -%= -%======================================================================== -delete_file_silent(File) :- - file_exists(File), - delete_file(File), - !. -delete_file_silent(_). %======================================================================== %= @@ -304,17 +283,3 @@ delete_files_with_matching_prefix([Name|T],Path,Prefixes) :- delete_files_with_matching_prefix(T,Path,Prefixes). -%======================================================================== -%= Split a list into the first n elements and the tail -%= +List +Integer -Prefix -Residuum -%======================================================================== - - -slice_n([],_,[],[]) :- - !. -slice_n([H|T],N,[H|T2],T3) :- - N>0, - !, - N2 is N-1, - slice_n(T,N2,T2,T3). -slice_n(L,_,[],L). diff --git a/packages/ProbLog/problog_learning.yap b/packages/ProbLog/problog_learning.yap index b8c2ff1f0..82a350075 100644 --- a/packages/ProbLog/problog_learning.yap +++ b/packages/ProbLog/problog_learning.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-10-05 16:52:13 +0200 (Tue, 05 Oct 2010) $ -% $Revision: 4869 $ +% $Date: 2010-10-20 18:06:47 +0200 (Wed, 20 Oct 2010) $ +% $Revision: 4969 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -225,6 +225,7 @@ :- use_module('problog/os'). :- use_module('problog/print_learning'). :- use_module('problog/utils_learning'). +:- use_module('problog/utils'). % used to indicate the state of the system :- dynamic(values_correct/0). @@ -549,11 +550,12 @@ init_learning :- !. init_learning :- check_examples, - + + empty_output_directory, logger_write_header, format_learning(1,'Initializing everything~n',[]), - empty_output_directory, + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Delete the BDDs from the previous run if they should @@ -1031,6 +1033,7 @@ mse_testset :- ( format_learning(2,'MSE_Test ',[]), update_values, + bb_put(llh_test_queries,0.0), findall(SquaredError, (user:test_example(QueryID,_Query,QueryProb,Type), once(update_query(QueryID,'+',probability)), @@ -1041,7 +1044,10 @@ mse_testset :- -> SquaredError is (CurrentProb-QueryProb)**2; SquaredError = 0.0 - ) + ), + bb_get(llh_test_queries,Old_LLH_Test_Queries), + New_LLH_Test_Queries is Old_LLH_Test_Queries+log(CurrentProb), + bb_put(llh_test_queries,New_LLH_Test_Queries) ), AllSquaredErrors), @@ -1050,10 +1056,12 @@ mse_testset :- min_list(AllSquaredErrors,MinError), max_list(AllSquaredErrors,MaxError), MSE is SumAllSquaredErrors/Length, + bb_delete(llh_test_queries,LLH_Test_Queries), logger_set_variable(mse_testset,MSE), logger_set_variable(mse_min_testset,MinError), logger_set_variable(mse_max_testset,MaxError), + logger_set_variable(llh_test_queries,LLH_Test_Queries), format_learning(2,' (~8f)~n',[MSE]) ); true ). @@ -1232,6 +1240,7 @@ gradient_descent :- bb_put(mse_train_sum, 0.0), bb_put(mse_train_min, 0.0), bb_put(mse_train_max, 0.0), + bb_put(llh_training_queries, 0.0), problog_flag(alpha,Alpha), logger_set_variable(alpha,Alpha), @@ -1267,12 +1276,15 @@ gradient_descent :- bb_get(mse_train_sum,Old_MSE_Train_Sum), bb_get(mse_train_min,Old_MSE_Train_Min), bb_get(mse_train_max,Old_MSE_Train_Max), + bb_get(llh_training_queries,Old_LLH_Training_Queries), New_MSE_Train_Sum is Old_MSE_Train_Sum+Squared_Error, New_MSE_Train_Min is min(Old_MSE_Train_Min,Squared_Error), New_MSE_Train_Max is max(Old_MSE_Train_Max,Squared_Error), + New_LLH_Training_Queries is Old_LLH_Training_Queries+log(BDDProb), bb_put(mse_train_sum,New_MSE_Train_Sum), bb_put(mse_train_min,New_MSE_Train_Min), bb_put(mse_train_max,New_MSE_Train_Max), + bb_put(llh_training_queries,New_LLH_Training_Queries), @@ -1368,11 +1380,13 @@ gradient_descent :- bb_delete(mse_train_sum,MSE_Train_Sum), bb_delete(mse_train_min,MSE_Train_Min), bb_delete(mse_train_max,MSE_Train_Max), + bb_delete(llh_training_queries,LLH_Training_Queries), MSE is MSE_Train_Sum/Example_Count, logger_set_variable(mse_trainingset,MSE), logger_set_variable(mse_min_trainingset,MSE_Train_Min), logger_set_variable(mse_max_trainingset,MSE_Train_Max), + logger_set_variable(llh_training_queries,LLH_Training_Queries), format_learning(2,'~n',[]), @@ -1670,7 +1684,9 @@ init_logger :- logger_define_variable(ground_truth_mindiff,float), logger_define_variable(ground_truth_maxdiff,float), logger_define_variable(learning_rate,float), - logger_define_variable(alpha,float). + logger_define_variable(alpha,float), + logger_define_variable(llh_training_queries,float), + logger_define_variable(llh_test_queries,float). :- initialization(init_flags). :- initialization(init_logger).