From be345a03877aa92eba2e0232b851d7afe9ee30ba Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Sun, 26 Jun 2011 23:13:43 +0100 Subject: [PATCH] update to recent ProbLog. --- packages/ProbLog/Makefile.in | 5 + packages/ProbLog/problog.yap | 207 +- packages/ProbLog/problog/ad_converter.yap | 120 +- packages/ProbLog/problog/completion.yap | 1122 ++++++++++ packages/ProbLog/problog/discrete.yap | 417 ++++ packages/ProbLog/problog/flags.yap | 4 +- packages/ProbLog/problog/print_learning.yap | 46 +- packages/ProbLog/problog/ptree.yap | 8 +- packages/ProbLog/problog/tabling.yap | 28 +- packages/ProbLog/problog/termhandling.yap | 454 ++++ packages/ProbLog/problog_examples/alarm.pl | 67 + packages/ProbLog/problog_learning.yap | 26 +- packages/ProbLog/problog_lfi.yap | 1167 +++++++++++ packages/ProbLog/simplecudd/simplecudd.c | 6 +- packages/ProbLog/simplecudd_lfi/Example.c | 345 +++ packages/ProbLog/simplecudd_lfi/Makefile.in | 62 + packages/ProbLog/simplecudd_lfi/adterror.c | 47 + packages/ProbLog/simplecudd_lfi/adterror.h | 75 + packages/ProbLog/simplecudd_lfi/allocate.c | 59 + packages/ProbLog/simplecudd_lfi/allocate.h | 30 + packages/ProbLog/simplecudd_lfi/apt.h | 67 + packages/ProbLog/simplecudd_lfi/cheaders.h | 50 + packages/ProbLog/simplecudd_lfi/general.c | 277 +++ packages/ProbLog/simplecudd_lfi/general.h | 202 ++ packages/ProbLog/simplecudd_lfi/iqueue.c | 275 +++ packages/ProbLog/simplecudd_lfi/iqueue.h | 66 + packages/ProbLog/simplecudd_lfi/pqueue.c | 715 +++++++ packages/ProbLog/simplecudd_lfi/pqueue.h | 94 + .../ProbLog/simplecudd_lfi/problogbdd_lfi.c | 1172 +++++++++++ packages/ProbLog/simplecudd_lfi/problogmath.c | 293 +++ packages/ProbLog/simplecudd_lfi/problogmath.h | 168 ++ packages/ProbLog/simplecudd_lfi/queuetest.c | 52 + packages/ProbLog/simplecudd_lfi/simplecudd.c | 1865 +++++++++++++++++ packages/ProbLog/simplecudd_lfi/simplecudd.h | 339 +++ 34 files changed, 9801 insertions(+), 129 deletions(-) create mode 100644 packages/ProbLog/problog/completion.yap create mode 100644 packages/ProbLog/problog/discrete.yap create mode 100644 packages/ProbLog/problog/termhandling.yap create mode 100644 packages/ProbLog/problog_examples/alarm.pl create mode 100644 packages/ProbLog/problog_lfi.yap create mode 100644 packages/ProbLog/simplecudd_lfi/Example.c create mode 100644 packages/ProbLog/simplecudd_lfi/Makefile.in create mode 100644 packages/ProbLog/simplecudd_lfi/adterror.c create mode 100644 packages/ProbLog/simplecudd_lfi/adterror.h create mode 100644 packages/ProbLog/simplecudd_lfi/allocate.c create mode 100644 packages/ProbLog/simplecudd_lfi/allocate.h create mode 100644 packages/ProbLog/simplecudd_lfi/apt.h create mode 100644 packages/ProbLog/simplecudd_lfi/cheaders.h create mode 100644 packages/ProbLog/simplecudd_lfi/general.c create mode 100644 packages/ProbLog/simplecudd_lfi/general.h create mode 100644 packages/ProbLog/simplecudd_lfi/iqueue.c create mode 100644 packages/ProbLog/simplecudd_lfi/iqueue.h create mode 100644 packages/ProbLog/simplecudd_lfi/pqueue.c create mode 100644 packages/ProbLog/simplecudd_lfi/pqueue.h create mode 100644 packages/ProbLog/simplecudd_lfi/problogbdd_lfi.c create mode 100644 packages/ProbLog/simplecudd_lfi/problogmath.c create mode 100644 packages/ProbLog/simplecudd_lfi/problogmath.h create mode 100644 packages/ProbLog/simplecudd_lfi/queuetest.c create mode 100644 packages/ProbLog/simplecudd_lfi/simplecudd.c create mode 100644 packages/ProbLog/simplecudd_lfi/simplecudd.h diff --git a/packages/ProbLog/Makefile.in b/packages/ProbLog/Makefile.in index 009e0ea99..154eba5f0 100644 --- a/packages/ProbLog/Makefile.in +++ b/packages/ProbLog/Makefile.in @@ -30,6 +30,7 @@ BIBTEX=bibtex PROGRAMS= \ $(srcdir)/problog.yap \ + $(srcdir)/problog_lfi.yap \ $(srcdir)/dtproblog.yap \ $(srcdir)/problog_learning.yap @@ -54,9 +55,13 @@ PROBLOG_PROGRAMS= \ $(srcdir)/problog/nestedtries.yap \ $(srcdir)/problog/utils.yap \ $(srcdir)/problog/ad_converter.yap \ + $(srcdir)/problog/termhandling.yap \ + $(srcdir)/problog/completion.yap \ + $(srcdir)/problog/discrete.yap \ $(srcdir)/problog/variables.yap PROBLOG_EXAMPLES = \ + $(srcdir)/problog_examples/alarm.pl \ $(srcdir)/problog_examples/graph.pl \ $(srcdir)/problog_examples/graph_tabled.pl \ $(srcdir)/problog_examples/learn_graph.pl \ diff --git a/packages/ProbLog/problog.yap b/packages/ProbLog/problog.yap index cb70ad91d..8f6fd06ea 100644 --- a/packages/ProbLog/problog.yap +++ b/packages/ProbLog/problog.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2011-01-16 19:24:10 +0100 (Sun, 16 Jan 2011) $ -% $Revision: 5260 $ +% $Date: 2011-04-08 19:30:08 +0200 (Fri, 08 Apr 2011) $ +% $Revision: 5887 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -284,6 +284,7 @@ reset_non_ground_facts/0, '::'/2, probabilistic_fact/3, + continuous_fact/3, init_problog/1, problog_call/1, problog_infer_forest_supported/0, @@ -302,7 +303,7 @@ % general yap modules :- 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(terms), [variable_in_term/2,variant/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]). @@ -590,8 +591,8 @@ generate_atoms(N, A):- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % converts annotated disjunctions -term_expansion_intern(A, Module, C):- - term_expansion_intern_ad(A, Module, C). +term_expansion_intern((Head<--Body), Module, C):- + term_expansion_intern_ad((Head<--Body), Module,inference, C). % converts ?:: prefix to ? :: infix, as handled by other clause term_expansion_intern((Annotation::Fact), Module, ExpandedClause) :- @@ -836,17 +837,50 @@ problog_continuous_predicate(Name, Arity, ContinuousArgumentPosition, ProblogNam %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% in_interval(ID,Low,High) :- - number(Low), - number(High), + var(ID), + throw(error(instantiation_error,in_interval(ID,Low,High))). +in_interval(ID,Low,High) :- + var(Low), + throw(error(instantiation_error,in_interval(ID,Low,High))). +in_interval(ID,Low,High) :- + var(High), + throw(error(instantiation_error,in_interval(ID,Low,High))). +in_interval(ID,Low,High) :- + \+ number(Low), + throw(error(type_error(number,Low),in_interval(ID,Low,High))). +in_interval(ID,Low,High) :- + \+ number(High), + throw(error(type_error(number,High),in_interval(ID,Low,High))). +in_interval(ID,Low,High) :- Low throw(error('Why do you want to know the probability of a decision?')) %fail - ; + ; ground(Log) -> Prob is exp(Log) + ; + Prob = p ). get_fact_log_probability(ID,Prob) :- @@ -1167,9 +1227,28 @@ set_continuous_fact_parameters(ID,Parameters) :- export_facts(Filename) :- open(Filename,'write',Handle), - forall(P::Goal, - format(Handle,'~10f :: ~q.~n',[P,Goal])), + %compiled ADs + forall((current_predicate(user:ad_intern/3),user:ad_intern(Original,ID,Facts)), + print_ad_intern(Handle,Original,ID,Facts) + ), + nl(Handle), + + % probabilistic facts + % but comment out auxiliary facts stemmig from + % compiled ADs + forall(P::Goal, + ( + is_mvs_aux_fact(Goal) + -> + format(Handle,'% ~10f :: ~q.~n',[P,Goal]); + format(Handle,'~10f :: ~q.~n',[P,Goal]) + ) + ), + + nl(Handle), + + % continuous facts (Hybrid ProbLog) forall(continuous_fact(ID), ( get_continuous_fact_parameters(ID,Param), @@ -1179,6 +1258,30 @@ export_facts(Filename) :- close(Handle). + +is_mvs_aux_fact(A) :- + functor(A,B,_), + atomic_concat(mvs_fact_,_,B). + +% code for printing the compiled ADs +print_ad_intern(Handle,(Head<--Body),_ID,Facts) :- + print_ad_intern(Head,Facts,0.0,Handle), + format(Handle,' <-- ~q.~n',[Body]). +print_ad_intern((A1;B1),[A2|B2],Mass,Handle) :- + once(print_ad_intern_one(A1,A2,Mass,NewMass,Handle)), + format(Handle,'; ',[]), + print_ad_intern(B1,B2,NewMass,Handle). +print_ad_intern(_::Fact,[],Mass,Handle) :- + P2 is 1.0 - Mass, + format(Handle,'~10f :: ~q',[P2,Fact]). +print_ad_intern_one(_::Fact,_::AuxFact,Mass,NewMass,Handle) :- + % ask problog to get the fact_id + once(probabilistic_fact(P,AuxFact,_FactID)), + P2 is P * (1-Mass), + NewMass is Mass+P2, + format(Handle,'~10f :: ~q',[P2,Fact]). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % recover fact for given id % list version not exported (yet?) @@ -1244,7 +1347,7 @@ add_to_proof(ID, LogProb) :- % 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 + ( % check whether this fact is already used in proof open_end_memberchk(ID, IDs) -> true; @@ -1410,7 +1513,7 @@ upper_bound(List) :- % to set up environment for proving % it resets control flags, method specific values to be set afterwards! init_problog(Threshold) :- - reset_problog_proof_id, + reset_proof_id, reset_non_ground_facts, reset_control, LT is log(Threshold), @@ -2795,44 +2898,40 @@ build_trie(K-best, Goal, Trie) :- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% write_bdd_struct_script(Trie,BDDFile,Variables) :- - % Check whether we use Hybrid ProbLog - ( - hybrid_proof(_,_,_) - -> - ( % Yes! run the disjoining stuff - retractall(hybrid_proof_disjoint(_,_,_,_)), - disjoin_hybrid_proofs, + ( + hybrid_proof(_,_,_) % Check whether we use Hybrid ProbLog + -> + ( + % Yes! run the disjoining stuff + retractall(hybrid_proof_disjoint(_,_,_,_)), + disjoin_hybrid_proofs, - init_ptree(OriTrie), % use this as tmp ptree - %%%%%%%%%%%%%%%%%%%%% - ( % go over all stored proofs - enum_member_ptree(List,OriTrie1), - ( - List=[_|_] - -> - Proof=List; - Proof=[List] - ), - ( - select(continuous(ProofID),Proof,Rest) - -> - ( - % this proof is using continuous facts - all_hybrid_subproofs(ProofID,List2), - append(Rest,List2,NewProof), - insert_ptree(NewProof,OriTrie) - ); - insert_ptree(Proof,OriTrie) - ), - - fail; - true - ) - %%%%%%%%%%%%%%%%%%%%% - ) ; - % Nope, just pass on the Trie - OriTrie=OriTrie1 - ), + init_ptree(OriTrie), % use this as tmp ptree + forall(enum_member_ptree(List,OriTrie1), % go over all stored proofs + ( + ( + List=[_|_] + -> + Proof=List; + Proof=[List] + ), + ( + select(continuous(ProofID),Proof,Rest) + -> + ( + % this proof is using continuous facts + all_hybrid_subproofs(ProofID,List2), + append(Rest,List2,NewProof), + insert_ptree(NewProof,OriTrie) + ); + insert_ptree(Proof,OriTrie) + ) + ) + ) + ); + % Nope, just pass on the Trie + OriTrie=OriTrie1 + ), ((problog_flag(variable_elimination, true), nb_getval(problog_nested_tries, false)) -> statistics(walltime, _), diff --git a/packages/ProbLog/problog/ad_converter.yap b/packages/ProbLog/problog/ad_converter.yap index aae4b2fff..6f6fac997 100644 --- a/packages/ProbLog/problog/ad_converter.yap +++ b/packages/ProbLog/problog/ad_converter.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-12-13 18:15:14 +0100 (Mon, 13 Dec 2010) $ -% $Revision: 5125 $ +% $Date: 2011-04-26 15:48:52 +0200 (Tue, 26 Apr 2011) $ +% $Revision: 6371 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -204,24 +204,20 @@ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -:- module(ad_converter,[compile_annotated_disjunction/5, - compile_tunable_annotated_disjunction/5, - proper_annotated_disjunction/1, - proper_tunable_annotated_disjunction/1, - term_expansion_intern_ad/3, +:- module(ad_converter,[term_expansion_intern_ad/4, op(1149, yfx, <-- ), op( 550, yfx, :: ) ]). % general yap modules -:- use_module(library(lists),[reverse/2,member/2,append/3]). +:- use_module(library(lists),[reverse/2,member/2,memberchk/2,append/3]). :- use_module(flags). :- style_check(all). :- yap_flag(unknown,error). -:- discontiguous user:ad_intern/2. +:- discontiguous user:(<--)/2, problog:(<--)/2. :- op( 550, yfx, :: ). @@ -230,29 +226,43 @@ :- initialization(problog_define_flag(show_ad_compilation,problog_flag_validate_boolean,'show compiled code for ADs',false,annotated_disjunctions)). :- initialization(problog_define_flag(ad_cpl_semantics,problog_flag_validate_boolean,'use CP-logics semantics for ADs',true,annotated_disjunctions)). +:- initialization(problog_define_flag(ad_sumto1_learning,problog_flag_validate_boolean,'make p_i sum to 1 for learning',true,annotated_disjunctions)). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -term_expansion_intern_ad( (Head<--Body),Module,ad_intern((Head<--Body),ID)) :- +term_expansion_intern_ad( (Head<--Body),Module,Mode,Result) :- problog_flag(ad_cpl_semantics,AD_CPL_Semantics), ( proper_tunable_annotated_disjunction(Head) -> - compile_tunable_annotated_disjunction(Head,Body,Facts,Bodies,ID,AD_CPL_Semantics); + compile_tunable_annotated_disjunction(Head,Body,Facts,Bodies,ID,AD_CPL_Semantics,Mode); ( - proper_annotated_disjunction(Head), - compile_annotated_disjunction(Head,Body,Facts,Bodies,ID,AD_CPL_Semantics) + proper_annotated_disjunction(Head,Sum_of_P_in_Head) + -> + compile_annotated_disjunction(Head,Body,Facts,Bodies,ID,AD_CPL_Semantics,Mode,Sum_of_P_in_Head); + throw(error(invalid_annotated_disjunction,(Head<--Body))) ) ), - forall(member(F,Facts),(once(problog:term_expansion_intern(F,Module,Atom)), - assertz(problog:Atom))), - forall(member(B,Bodies),assertz(Module:B)), + findall(problog:Atom,( + member(F,Facts), + once(problog:term_expansion_intern(F,Module,Atom)) + ),Result_Atoms), + ( + Mode==lfi_learning + -> + findall(Module:myclause(H,B),member((H:-B),Bodies),Result_Bodies); + findall(Module:B,member(B,Bodies),Result_Bodies) + ), + + append(Result_Atoms,Result_Bodies,Result), + + problog_flag(show_ad_compilation,Show_AD_compilation), - ( Show_AD_compilation==true -> @@ -289,7 +299,7 @@ get_next_unique_id(ID) :- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -proper_annotated_disjunction(AD) :- +proper_annotated_disjunction(AD,Sum) :- proper_annotated_disjunction(AD,0.0,Sum), Sum=<1. @@ -316,7 +326,7 @@ proper_tunable_annotated_disjunction((X;Y)) :- % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compile_tunable_annotated_disjunction(Head,Body,Facts2,Bodies2,Extra_ID,AD_CPL_Semantics) :- +compile_tunable_annotated_disjunction(Head,Body,Facts2,Bodies2,Extra_ID,AD_CPL_Semantics,Mode) :- get_next_unique_id(Extra_ID), ( @@ -325,16 +335,28 @@ compile_tunable_annotated_disjunction(Head,Body,Facts2,Bodies2,Extra_ID,AD_CPL_S term_variables(Body,Body_Vars); Body_Vars=[] ), - - convert_a_tunable(Head,Extra_ID,[],Facts,Body_Vars), - convert_b(Head,Body,_NewBody,Extra_ID,[],Bodies,Body_Vars), - reverse(Facts,Facts2), + + + convert_a_tunable(Head,Extra_ID,[],Facts0,Body_Vars), + + problog_flag(ad_sumto1_learning,AD_SumTo1_Learning), + ( + AD_SumTo1_Learning==true + -> + Facts0=[_|Facts1]; + Facts1=Facts0 + ), + + reverse(Facts1,Facts2), + convert_b(Head,Body,_NewBody,Extra_ID,[],Bodies,Body_Vars,Mode,Facts2), + + reverse(Bodies,Bodies2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compile_annotated_disjunction(Head,Body,Facts2,Bodies2,Extra_ID,AD_CPL_Semantics) :- +compile_annotated_disjunction(Head,Body,Facts2,Bodies2,Extra_ID,AD_CPL_Semantics,Mode,ProbSum) :- get_next_unique_id(Extra_ID), ( @@ -344,10 +366,20 @@ compile_annotated_disjunction(Head,Body,Facts2,Bodies2,Extra_ID,AD_CPL_Semantics Body_Vars=[] ), - convert_a(Head,0.0,_Acc,Extra_ID,[],Facts,Body_Vars), - convert_b(Head,Body,_NewBody,Extra_ID,[],Bodies,Body_Vars), + convert_a(Head,0.0,_Acc,Extra_ID,[],Facts0,Body_Vars), + + ( + abs(ProbSum-1.0) < 0.0000001 + -> + Facts0=[_|Facts1]; + Facts1=Facts0 + ), + + + reverse(Facts1,Facts2), + convert_b(Head,Body,_NewBody,Extra_ID,[],Bodies,Body_Vars,Mode,Facts2), + - reverse(Facts,Facts2), reverse(Bodies,Bodies2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -365,15 +397,10 @@ convert_a(P::Atom,OldAcc,NewAcc,Extra_ID,OldFacts,[P1::ProbFact|OldFacts],Body_V ProbFact =.. [NewAtom|NewAllArguments], ( - P=:=0 + (P=:=0; OldAcc=:=0) -> - P1 is 0.0 ; - ( - OldAcc=:=0 - -> P1 is P; - P1 is P/(1-OldAcc) - ) + P1 is min(P/(1-OldAcc),1.0) ), NewAcc is OldAcc+P. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -382,7 +409,7 @@ convert_a(P::Atom,OldAcc,NewAcc,Extra_ID,OldFacts,[P1::ProbFact|OldFacts],Body_V convert_a_tunable((X;Y),Extra_ID,OldFacts,Facts,Body_Vars) :- convert_a_tunable(X,Extra_ID,OldFacts,NewFacts,Body_Vars), convert_a_tunable(Y,Extra_ID,NewFacts,Facts,Body_Vars). -convert_a_tunable(P::Atom,Extra_ID,OldFacts,[P::ProbFact|OldFacts],Body_Vars) :- +convert_a_tunable(t(_)::Atom,Extra_ID,OldFacts,[t(_)::ProbFact|OldFacts],Body_Vars) :- Atom =.. [Functor|AllArguments], append(AllArguments,Body_Vars,NewAllArguments), length(AllArguments,Arity), @@ -393,10 +420,10 @@ convert_a_tunable(P::Atom,Extra_ID,OldFacts,[P::ProbFact|OldFacts],Body_Vars) :- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -convert_b((X;Y),OldBody,Body,ExtraID,OldBodies,Bodies,Body_Vars) :- - convert_b(X,OldBody,NewBody,ExtraID,OldBodies,NewBodies,Body_Vars), - convert_b(Y,NewBody,Body,ExtraID,NewBodies,Bodies,Body_Vars). -convert_b(_::Atom,OldBody,NewBody,Extra_ID,OldBodies,[(Atom:-ThisBody)|OldBodies],Body_Vars) :- +convert_b((X;Y),OldBody,Body,ExtraID,OldBodies,Bodies,Body_Vars,Mode,Facts) :- + convert_b(X,OldBody,NewBody,ExtraID,OldBodies,NewBodies,Body_Vars,Mode,Facts), + convert_b(Y,NewBody,Body,ExtraID,NewBodies,Bodies,Body_Vars,Mode,Facts). +convert_b(_::Atom,OldBody,NewBody,Extra_ID,OldBodies,[(Atom:-ThisBody)|OldBodies],Body_Vars,Mode,Facts) :- Atom =.. [Functor|AllArguments], append(AllArguments,Body_Vars,NewAllArguments), @@ -404,8 +431,19 @@ convert_b(_::Atom,OldBody,NewBody,Extra_ID,OldBodies,[(Atom:-ThisBody)|OldBodies atomic_concat([mvs_fact_,Functor,'_',Arity,'_',Extra_ID],NewFunctor), ProbFact =.. [NewFunctor|NewAllArguments], - tuple_append(OldBody,ProbFact,ThisBody), - tuple_append(OldBody,problog_not(ProbFact),NewBody). + ( + memberchk(_::ProbFact,Facts) + -> + tuple_append(OldBody,ProbFact,ThisBody); + ThisBody=OldBody + ), + + ( + Mode==lfi_learning + -> + tuple_append(OldBody,\+ProbFact,NewBody); + tuple_append(OldBody,problog_not(ProbFact),NewBody) + ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % diff --git a/packages/ProbLog/problog/completion.yap b/packages/ProbLog/problog/completion.yap new file mode 100644 index 000000000..7a2a46625 --- /dev/null +++ b/packages/ProbLog/problog/completion.yap @@ -0,0 +1,1122 @@ +%%% -*- Mode: Prolog; -*- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% $Date: 2011-04-21 14:18:59 +0200 (Thu, 21 Apr 2011) $ +% $Revision: 6364 $ +% +% Main authors of this file: +% Bernd Gutmann +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% 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. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +:- module(completion, [propagate_evidence/2, + bdd_cluster/2, + split_atom_name/3, + reset_completion/0]). + +:- style_check(all). +:- yap_flag(unknown,error). + +% load library modules +:- use_module(library(lists),[member/2,append/3,reverse/2]). +:- use_module(library(system), [tmpnam/1]). + +% load our own modules +:- use_module('../problog'). +:- use_module(logger). +:- use_module(termhandling). +:- use_module(flags). +:- use_module(print_learning). +:- use_module(utils). +:- use_module(utils_learning). + +:- dynamic seen_atom/4. +:- dynamic bdd_cluster/2. + +:- initialization(problog_define_flag(propagate_known,problog_flag_validate_boolean,'Propagate known atoms',true,learning_bdd_generation)). +:- initialization(problog_define_flag(propagate_det,problog_flag_validate_boolean,'Propagate deterministic atoms',true,learning_bdd_generation)). +:- initialization(problog_define_flag(output_dot_files,problog_flag_validate_boolean,'Output .dot files for BDD scripts',true,learning_bdd_generation)). +:- initialization(problog_define_flag(split_bdds,problog_flag_validate_boolean,'Split BDD scripts when possible',true,learning_bdd_generation)). + +%======================================================================== +%= +%======================================================================== + +user:myclause(_InterpretationID,Head,Body) :- + current_predicate(user:myclause/2), + user:myclause(Head,Body). + +%======================================================================== +%= +%======================================================================== + +reset_completion :- + retractall(seen_atom(_,_,_,_)), + retractall(bdd_cluster(_,_)). + +%======================================================================== +%= +%======================================================================== + +propagate_evidence(_,_) :- + \+ current_predicate(user:known/3), + !, + throw(error(system_error,'The predicate user:known/3 is not defined. If you really have empty interpretations declare the user:known/3 as dynamic and come back.')). + + +propagate_evidence(InterpretationID,Query_Type) :- + atomic(InterpretationID), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Clean up %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + eraseall(rules), + eraseall(unpropagated_rules), + eraseall(known_atoms), + eraseall(reachable), + + ( + Query_Type==test + -> + ( + Key_BDD_script_generation=test_bdd_script_generation, + Key_BDD_script_generation_grounding=test_bdd_script_generation_grounding, + Key_BDD_script_generation_completion=test_bdd_script_generation_completion, + Key_BDD_script_generation_propagation=test_bdd_script_generation_propagation, + Key_BDD_script_generation_splitting=test_bdd_script_generation_splitting, + Key_BDD_script_generation_active_ground_atoms=test_bdd_script_generation_active_ground_atoms, + Key_BDD_script_generation_propagated_ground_atoms=test_bdd_script_generation_propagated_ground_atoms + ); + ( + Key_BDD_script_generation=train_bdd_script_generation, + Key_BDD_script_generation_grounding=train_bdd_script_generation_grounding, + Key_BDD_script_generation_completion=train_bdd_script_generation_completion, + Key_BDD_script_generation_propagation=train_bdd_script_generation_propagation, + Key_BDD_script_generation_splitting=train_bdd_script_generation_splitting, + Key_BDD_script_generation_active_ground_atoms=train_bdd_script_generation_active_ground_atoms, + Key_BDD_script_generation_propagated_ground_atoms=train_bdd_script_generation_propagated_ground_atoms + ) + ), + + + logger_start_timer(Key_BDD_script_generation), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Calc dep() %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + logger_start_timer(Key_BDD_script_generation_grounding), + format_learning(5,'d',[]), + % iterate over all evidence atoms + forall(user:known(InterpretationID,Atom,Value), + ( + (calculate_dep_atom_outer(Atom,InterpretationID);Value==false) + -> + true; + throw(unprovable_evidence(Atom)) + ) + ), + logger_stop_timer(Key_BDD_script_generation_grounding), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Calc completion %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + logger_start_timer(Key_BDD_script_generation_completion), + format_learning(5,'c',[]), + once(completion(InterpretationID)), + logger_stop_timer(Key_BDD_script_generation_completion), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Bring out intermediate garbage %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + eraseall(reachable), + !, + garbage_collect_atoms, + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Calc propagation %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + problog_flag(propagate_known,Propagate_Known), + + ( + Propagate_Known==true + -> + ( + logger_start_timer(Key_BDD_script_generation_propagation), + format_learning(5,'p',[]), + once(propagate), + logger_stop_timer(Key_BDD_script_generation_propagation) + ); + true + ), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Split BDD Script %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + problog_flag(split_bdds,Split_BDDs), + format_learning(5,'S',[]), + ( + Split_BDDs==false + -> + ( + findall(R,(recorded(rules,_,R);recorded(unpropagated_rules,_,R)),All_R), + Cluster=[All_R] + ); + ( + logger_start_timer(Key_BDD_script_generation_splitting), + split_rules(Cluster), + logger_stop_timer(Key_BDD_script_generation_splitting) + ) + ), + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Print BDD script %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + format_learning(5,'s',[]), + print_script_per_cluster(Cluster,InterpretationID,1,0,Seen_Atoms,[],ClusterIDs), + store_known_atoms(InterpretationID,ClusterIDs,Query_Type), + key_statistics(known_atoms,Known_Atoms,_), + logger_add_to_variable(Key_BDD_script_generation_active_ground_atoms,Seen_Atoms), + logger_add_to_variable(Key_BDD_script_generation_propagated_ground_atoms,Known_Atoms), + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Clean up %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + eraseall(rules), + eraseall(unpropagated_rules), + eraseall(known_atoms), + eraseall(reachable), + logger_stop_timer(Key_BDD_script_generation). + + +%======================================================================== +%= +%======================================================================== + +print_script_per_cluster([],_,_,Seen_Atoms,Seen_Atoms,Cluster_IDs,Cluster_IDs). +print_script_per_cluster([Refs|T],InterpretationID,Cluster_ID,Old_Seen_Atoms,Seen_Atoms,Old_Cluster_IDs,Cluster_IDs) :- + create_bdd_file_name(InterpretationID,Cluster_ID,File_Name), + %trace, + once(print_simplecudd_script(Refs,File_Name,This_Seen_Atoms)), + New_Seen_Atoms is Old_Seen_Atoms+This_Seen_Atoms, + Next_Cluster_ID is Cluster_ID+1, + print_script_per_cluster(T,InterpretationID,Next_Cluster_ID,New_Seen_Atoms,Seen_Atoms,[Cluster_ID|Old_Cluster_IDs],Cluster_IDs). + + +%======================================================================== +%= +%======================================================================== + +completion(InterpretationID) :- + % iterate over all reachable atoms where the completion + % can be computed. This will skip reachable probabilistic facts. + forall(( + recorded(reachable,Head,_), + completion_for_atom(Head,Rule,InterpretationID) + ), + ( + once(propagate_interpretation(Rule,InterpretationID,Rule2)), + simplify(Rule2,Rule3,_), + ( + (Rule3\==false,record_constraint_cs_check(Rule3)) + -> + true; + ( + print_theory, + format(user_error,'=============================~n',[]), + format(user_error,'Inconsistency error at building completion for atom ~q (Example ~q)~n',[Head,InterpretationID]), + format(user_error,' Completion was~n ~q~2n',[Rule]), + format(user_error,' After subsituting evidence~n ~q~2n',[Rule2]), + format(user_error,' After simplifying~n ~q~2n',[Rule3]), + format(user_error,'=============================~2n',[]), + throw(theory_is_inconsistent) + ) + ) + ) + ), + + print_theory, + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Store known Atoms %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + forall(user:known(InterpretationID,Atom,Value), + recorda(known_atoms,'$atom'(Atom) <=> Value,_) + ). + + +completion_for_atom(Head,'$atom'(Head)<=>Disjunction,InterpretationID) :- + % find all clauses + findall(Body2,( + user:myclause(InterpretationID,Head,Body), + ground_term_with_known_atoms(Body,Body2) + ),Bodies), + Bodies\==[], + list_to_disjunction(Bodies,Disjunction). + + +%======================================================================== +%= find rule which makes sense to propagate +%======================================================================== + +propagate :- + problog_flag(propagate_det,true), + !, + repeat, + once(propagate_intern_known(Result1)), +% print_theory, + Result1==false, + once(propagate_intern_deterministic(Result2)), + Result2==false, + !. +propagate :- + repeat, + once(propagate_intern_known(Result1)), + Result1==false, + !. + +propagate_intern_known(true) :- + recorded(unpropagated_rules,Atom <=> AtomValue,Key1), + !, + erase(Key1), + recorda(known_atoms,Atom <=> AtomValue,_), + forall( + ( + recorded(rules,Rule,Key2), + once(propagate(Rule,'$atom'(Atom),AtomValue,NewRule,true)) % will succeed only when Atom appears in Rule + ), + ( + erase(Key2), + once(simplify(NewRule,NewRuleSimplified,_)), + ( + (NewRuleSimplified\==false,record_constraint_cs_check(NewRuleSimplified)) + -> + true; + ( + print_theory, + format(user_error,'Propagating ~q=~q for ~q leads to an inconsistency.!!!~2n',[Atom,AtomValue,Rule]), + throw(inconsitent) + ) + ) + ) + ). +propagate_intern_known(false). + +propagate_intern_deterministic(true) :- + recorded(rules,Atom <=> AtomValue,Key1), + !, + erase(Key1), + forall( + ( + recorded(rules,Rule,Key2), + once(propagate(Rule,Atom,AtomValue,NewRule,true)) % will succeed only when Atom appears in Rule + ), + ( + erase(Key2), + once(simplify(NewRule,NewRuleSimplified,_)), + ( + (NewRuleSimplified\=false,record_constraint_cs_check(NewRuleSimplified)) + -> + true; + ( + print_theory, + format(user_error,'Propagating ~q=~q for ~q leads to an inconsistency.!!!~2n',[Atom,AtomValue,Rule]), + throw(inconsitent) + ) + ) + ) + ). +propagate_intern_deterministic(false). + + +%======================================================================== +%= +%======================================================================== + +record_constraint_cs_check( (X <=> Y) ) :- + recorda(rules,(X <=> Y),_). +record_constraint_cs_check((X,Y)) :- + record_constraint_cs_check(X), + record_constraint_cs_check(Y). +record_constraint_cs_check( (X;Y)) :- + recorda(rules,(X;Y),_). +record_constraint_cs_check( \+ '$atom'(X) ) :- + ( + recorded(unpropagated_rules, ('$atom'(X)<=>OldValue),_) + -> + OldValue==false; + recorda(unpropagated_rules, ('$atom'(X) <=> false),_) + ). +record_constraint_cs_check('$atom'(X)) :- + ( + recorded(unpropagated_rules, ('$atom'(X)<=>OldValue),_) + -> + OldValue==true; + recorda(unpropagated_rules, ('$atom'(X) <=> true),_) + ). +record_constraint_cs_check(true). + +%======================================================================== +%= +%======================================================================== + + +split_atom_name(Name,ID,GroundID) :- + atom(Name), + atomic_concat(x,Temp,Name), + atom_codes(Temp,TempC), + + ( + append(Head,[95|Tail],TempC) % 95-_- + -> + ( + number_chars(ID,Head), + number_chars(GroundID,Tail) + ); + ( + number_chars(ID,TempC), + GroundID=0 + ) + ), + !. + +store_known_atoms(ID,ClusterIDs,Query_Type) :- + ( + Query_Type==test + -> + ( + KK_True_Array=known_count_true_test, + KK_False_Array=known_count_false_test + ); + ( + KK_True_Array=known_count_true_training, + KK_False_Array=known_count_false_training + ) + ), + + retractall(bdd_cluster(ID,_)), + + assertz(bdd_cluster(ID,ClusterIDs)), + create_known_values_file_name(ID,File_Name), + open(File_Name,'write',Handle), + format(Handle,'completion:bdd_cluster(~w,~w).~n',[ID,ClusterIDs]), + + forall(( + recorded(known_atoms,'$atom'(Atom) <=> Value,_), + remember(Atom,Name), + split_atom_name(Name,FactID,GroundID) + ), + ( + ( + Value==true + -> + add_to_array_element(KK_True_Array,FactID,1,_); + add_to_array_element(KK_False_Array,FactID,1,_) + ), + know_atom_expected_count(Value,Count), + format(Handle,'completion:known_count(~w,~w,~w,~w). % ~w~n',[ID,FactID,GroundID,Count,Atom]) + ) + ), + + close(Handle). + +know_atom_expected_count(true,1). +know_atom_expected_count(false,0). + + +%======================================================================== +%= +%======================================================================== + +print_theory :- + format_learning(5,'== Unpropagated Rules ==~n',[]), + forall(recorded(unpropagated_rules,Rule,Key), + format_learning(6,'~q. (~q)~n',[Rule,Key]) + ), + forall(recorded(unpropagated_rules,Rule,Key), + format_learning_rule(5,Rule,Key) + ), + + format_learning(6,'== Rules ==~n',[]), + forall(recorded(rules,Rule,Key), + format_learning(6,'~q. (~q)~n',[Rule,Key])), + format_learning(5,'== Prettyprint Rules ==~n',[]), + forall(recorded(rules,Rule,Key), + (format_learning_rule(5,Rule,Key)) + ), + + format_learning(5,'== Known and Propagated Atoms ==~n',[]), + forall(recorded(known_atoms,Head <=> Bodies,Key), + format('~q <=> ~q. (~q)~n',[Head,Bodies,Key]) + ). + + +%======================================================================== +%= split_rules(-Cluster) +%======================================================================== +split_rules(Cluster) :- + eraseall(cluster), + + % add all rules to the clusters + forall(recorded(rules,Expression,Reference), + include_in_clusters(Expression,Reference)), + + % add all unpropagated rules to the clusters + forall(recorded(unpropagated_rules,Expression,Reference), + include_in_clusters(Expression,Reference)), + + garbage_collect_atoms, + + % Merge clusters until + % no more clusters can be merged + ( + repeat, + merge_cluster(Result), + Result==false, + ! + ), + + findall(Keys,recorded(cluster,c(_Facts,Keys),_),Cluster), + eraseall(cluster), + + garbage_collect_atoms. + +%======================================================================== +%= include_in_clusters(+Expression,+Reference) +%======================================================================== + +include_in_clusters(Expression,Reference) :- + ( + setof(F, Expression^term_element(Expression, F), Facts_Sorted) + -> + true; + Facts_Sorted = [] + ), + + bb_put(facts,Facts_Sorted), + bb_put(rule_keys,[Reference]), + + % iterate over all cluster that overlap with Current_Facts + forall(( + recorded(cluster,c(CFacts,Cluster_Rule_Keys),CKey), + bb_get(facts,Current_Facts), + sorted_overlap_test(Current_Facts,CFacts) + ), + ( + erase(CKey), + bb_get(rule_keys,Current_Rule_Keys), + append(Current_Facts,CFacts,Merged_Facts), + append(Current_Rule_Keys,Cluster_Rule_Keys,Merged_Rule_Keys), + sort(Merged_Facts,Sorted_Facts), + bb_put(facts,Sorted_Facts), + bb_put(rule_keys,Merged_Rule_Keys) + ) + ), + + %clean up and store the new (possibly merged) cluster + bb_delete(facts,Final_Facts), + bb_delete(rule_keys,Final_Rule_Keys), + recorda(cluster,c(Final_Facts,Final_Rule_Keys),_). + +%======================================================================== +%= find two clusters that should be merged because they both +%= contain the same fact +%======================================================================== + +merge_cluster(true) :- + recorded(cluster,c(CFacts1,Cluster_Rule_Keys1),CKey1), + recorded(cluster,c(CFacts2,Cluster_Rule_Keys2),CKey2), + CKey1 @< CKey2, + sorted_overlap_test(CFacts1,CFacts2), + !, + erase(CKey1), + erase(CKey2), + + append(CFacts1,CFacts2,Merged_Facts), + sort(Merged_Facts,Sorted_Facts), + + append(Cluster_Rule_Keys1,Cluster_Rule_Keys2,Merged_Rule_Keys), + recorda(cluster,c(Sorted_Facts,Merged_Rule_Keys),_). +merge_cluster(false). + +%======================================================================== +%= +%======================================================================== + +print_simplecudd_script(Refs,BDDFilename,Seen_Atoms) :- + retractall(seen_atom(_,_,_,_)), + retractall(script_hash(_,_)), + + bb_put(counter,0), + bb_put(det_counter,0), + bb_put(grounding_counter,0), + + tmpnam(Temp_File_Name), + open(Temp_File_Name,'write',Handle1), + findall(X,( + member(R,Refs), + recorded(_,Expression,R), + print_expression(Expression,Handle1,X) + ),L), + reverse(L,L_Rev), + list_to_conjunction(L_Rev,Con), + + + print_expression_and_final(Con,Handle1,'',Final), + + ( + (atom_codes(Final,[76|_])) % X='L....' + -> + LastID=Final; + ( + next_counter(LastID), + format(Handle1,'~w=~w~n',[LastID,Final]) + ) + ), + + format(Handle1,'~w~n',[LastID]), + close(Handle1), + + succeeds_n_times(seen_atom(_,_,_,_),Seen_Atoms), + bb_get(counter,IntermediateSteps), + + prefix_bdd_file_with_header(BDDFilename,Seen_Atoms,IntermediateSteps,Temp_File_Name), + + problog_flag(output_dot_files,Output_Dot_Files), + + ( + Output_Dot_Files==true + -> + ( + atomic_concat([BDDFilename,'.dot'],Dot_File_Name), + open(Dot_File_Name,'write',Handle2), + format(Handle2,'digraph d{~n',[]), + + forall(seen_atom(Atom,ID,_FactID,_), + format(Handle2,'~q [label="~q\\n~q", style="filled", color="lightblue"];~n',[ID,Atom,ID]) + ), + + findall(X,(member(R,Refs),recorded(_,Expression,R),print_dot_expression(Expression,Handle2,X)),_L2), + + % switch off printing final line until bugfix + %list_to_conjunction(L2,Con2), +% print_dot_expression(Con2,Handle2,_), + format(Handle2,'}~n',[]), + close(Handle2) + ); + true + ), + + retractall(script_hash(_,_)), + retractall(seen_atom(_,_,_,_)). + + +%======================================================================== +%= +%======================================================================== + +print_expression(Term,_Handle,N) :- + script_hash(Term,N), + !. + +print_expression(X <=> Y, Handle,N3) :- + print_expression(X,Handle,N1), + print_expression(Y,Handle,N2), + next_counter(N3), + assert(script_hash(X <=> Y, N3)), + format(Handle,'~w = ~w ~~# ~w~n',[N3,N1,N2]). +print_expression( (X,Y), Handle,Number) :- + print_expression_and((X,Y),Handle,'',Number), + assert(script_hash((X,Y), Number)). +print_expression( (X;Y), Handle,Number) :- + print_expression_or((X;Y),Handle,'',Number), + assert(script_hash((X;Y), Number)). +print_expression( \+ '$atom'(X), _Handle,ID) :- + remember(X,Name), + atomic_concat(['~',Name],ID). +print_expression( true, _Handle,'TRUE'). +print_expression( false, _Handle,'FALSE'). +print_expression('$atom'(X), _Handle,ID) :- + remember(X,ID). + +print_expression_or((X;Y), Handle,OldAcc,Number) :- + !, + print_expression(X,Handle,NX), + atomic_concat([OldAcc,NX,' + '],NewAcc), + print_expression_or(Y,Handle,NewAcc,Number). +print_expression_or(X, Handle,OldAcc,Number) :- + print_expression(X,Handle,NX), + next_counter(Number), + format(Handle,'~w = ~w~w~n',[Number,OldAcc,NX]). + + +print_expression_and((X,Y), Handle,OldAcc,Number) :- + !, + print_expression(X,Handle,NX), + atomic_concat([OldAcc,NX,' * '],NewAcc), + print_expression_and(Y,Handle,NewAcc,Number). +print_expression_and(X, Handle,OldAcc,Number) :- + print_expression(X,Handle,NX), + next_counter(Number), + format(Handle,'~w = ~w~w~n',[Number,OldAcc,NX]). + + +print_expression_and_final((X,Y), Handle,OldAcc,Number) :- + !, + atomic_concat([OldAcc,X,' * '],NewAcc), + print_expression_and_final(Y,Handle,NewAcc,Number). +print_expression_and_final( true, _Handle,_ACC,'TRUE'). +print_expression_and_final(X, Handle,OldAcc,Number) :- + next_counter(Number), + format(Handle,'~w = ~w~w~n',[Number,OldAcc,X]). + + +%======================================================================== +%= +%======================================================================== + +print_dot_expression_or((X;Y), Handle,Number) :- + !, + print_dot_expression(X,Handle,NX), + print_dot_line(NX,Number,Handle), + print_dot_expression_or(Y,Handle,Number). +print_dot_expression_or(X, Handle,Number) :- + print_dot_expression(X,Handle,NX), + print_dot_line(NX,Number,Handle). + + +print_dot_expression_and((X,Y), Handle,Number) :- + !, + print_dot_expression(X,Handle,NX), + print_dot_line(NX,Number,Handle), + print_dot_expression_and(Y,Handle,Number). +print_dot_expression_and(X, Handle,Number) :- + print_dot_expression(X,Handle,NX), + print_dot_line(NX,Number,Handle). + + + + +print_dot_expression(X <=> Y, Handle,N3) :- + print_dot_expression(X,Handle,N1), + print_dot_expression(Y,Handle,N2), + next_counter(N3), + format(Handle,'~w [label="<=>",shape="diamond", style="filled", color="lightsalmon"];~n',[N3]), + print_dot_line(N1,N3,Handle), + print_dot_line(N2,N3,Handle). +print_dot_expression( (X,Y), Handle,Number) :- + next_counter(Number), + format(Handle,'~w [label="^",shape="triangle", style="filled", color="lightgoldenrod"];~n',[Number]), + print_dot_expression_and((X,Y),Handle,Number). +print_dot_expression( (X;Y), Handle,Number) :- + next_counter(Number), + format(Handle,'~w [label="v",shape="invtriangle", style="filled", color="greenyellow"];~n',[Number]), + print_dot_expression_or((X;Y),Handle,Number). +print_dot_expression( \+ '$atom'(X), _Handle,ID) :- + remember(X,Name), + atomic_concat(['~',Name],ID). +print_dot_expression(true, _Handle,'TRUE'). +print_dot_expression( false, _Handle,'FALSE'). +print_dot_expression( '$atom'(X), _Handle,ID) :- + remember(X,ID). + + +print_dot_line(N1,N2,Handle) :- + ( + atomic_concat('~',ID,N1) + -> + format(Handle,'~w -> ~w [style="dashed, bold"];~n',[ID,N2]); + format(Handle,'~w -> ~w;~n',[N1,N2]) + ). + +%======================================================================== +%= +%======================================================================== + + +remember(X,Name) :- + seen_atom(X,Name,_,_), + !. +remember(X,X) :- + atom(X), + atom_codes(X,[76|_]), % X='L....' + !. +remember(X,Name) :- + probabilistic_fact(P,X,ID), + !, + ( + non_ground_fact(ID) + -> + ( + next_grounding_id(Grounding_ID), + atomic_concat([x,ID,'_',Grounding_ID],Name) + ); + atomic_concat([x,ID],Name) + ), + assertz(seen_atom(X,Name,ID,P)). +remember(X,Name) :- + next_det_counter(Det_ID), + atomic_concat([y,Det_ID],Name), + assertz(seen_atom(X,Name,det,1.0)). + + +next_grounding_id(N) :- + bb_get(grounding_counter,N), + N2 is N+1, + bb_put(grounding_counter,N2). + +next_det_counter(ID) :- + bb_get(det_counter,N), + N2 is N+1, + atomic_concat(['y',N2],ID), + bb_put(det_counter,N2). + +next_counter(ID) :- + bb_get(counter,N), + N2 is N+1, + atomic_concat(['L',N2],ID), + bb_put(counter,N2). + +%======================================================================== +%= calculate_dep_atom(+Atom) +%======================================================================== + + +calculate_dep_atom_outer(Atom,InterpretationID) :- + bb_put(dep_proven,false), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + ( % go over all proofs for atom + calculate_dep_atom(Atom,InterpretationID), + bb_put(dep_proven,true), + + fail; % go to next proof + true + ), + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + bb_delete(dep_proven,Result), + Result==true. + + +calculate_dep_atom(true,_) :- + !. +calculate_dep_atom(false,_) :- + !. +calculate_dep_atom( (X is Y),_ ) :- + !, + call(X is Y). +calculate_dep_atom( (X > Y),_ ) :- + !, + call(X > Y). +calculate_dep_atom( (X < Y),_ ) :- + !, + call(X < Y). +calculate_dep_atom( (X == Y),_ ) :- + !, + call(X == Y). +calculate_dep_atom( (X = Y),_ ) :- + !, + call(X = Y). +calculate_dep_atom( (X > Y),_ ) :- + !, + call(X > Y). +calculate_dep_atom( (X < Y),_ ) :- + !, + call(X < Y). +calculate_dep_atom( (X =< Y),_ ) :- + !, + call(X =< Y). +calculate_dep_atom( (X >= Y),_ ) :- + !, + call(X >= Y). +calculate_dep_atom(call(X),_) :- + !, + call(X). +calculate_dep_atom( Atom,_ ) :- + recorded(reachable,Atom,_), + % FIXME, could this cut prune away too much? what if Atom is non-ground? + !. +calculate_dep_atom( Atom,InterpretationID ) :- + ground(Atom), + !, + recorda(reachable,Atom,_), + if(user:myclause(InterpretationID,Atom,Body),(calculate_dep_atom_intern(Body,InterpretationID)),probabilistic_fact(_,Atom,_)). +calculate_dep_atom( Atom,InterpretationID ) :- + if(user:myclause(InterpretationID,Atom,Body),(calculate_dep_atom_intern(Body,InterpretationID)),probabilistic_fact(_,Atom,_)), + ( + ground(Atom) + -> + ( + recorded(reachable,Atom,_) + -> + true; + recorda(reachable,Atom,_) + ); + ( + format(user_error,'Error at running the meta interpreter.~n',[]), + format(user_error,'The clauses defined by myclause/2 have to be written in a way such that~n',[]), + format(user_error,'each atom in the body of a clause gets fully grounded when it is called.~n',[]), + format(user_error,' This is not the case for the atom ~w~3n',[Atom]), + throw(meta_interpreter_error(Atom)) + ) + ). + + +calculate_dep_atom_intern((X,Y),InterpretationID) :- + !, + calculate_dep_atom_intern(X,InterpretationID), + calculate_dep_atom_intern(Y,InterpretationID). +calculate_dep_atom_intern((X;Y),InterpretationID) :- + !, + ( + calculate_dep_atom_intern(X,InterpretationID); + calculate_dep_atom_intern(Y,InterpretationID) + ). +calculate_dep_atom_intern(\+X,InterpretationID) :- + !, + calculate_dep_atom_intern(X,InterpretationID). +calculate_dep_atom_intern(X,InterpretationID) :- + calculate_dep_atom(X,InterpretationID). + +%======================================================================== +%= +%======================================================================== + + + +ground_term_with_known_atoms( (X,Y), (X2,Y2)) :- + !, + ground_term_with_known_atoms(X,X2), + ground_term_with_known_atoms(Y,Y2). +ground_term_with_known_atoms( (X;Y), (X2;Y2)) :- + !, + ground_term_with_known_atoms(X,X2), + ground_term_with_known_atoms(Y,Y2). + +ground_term_with_known_atoms( \+ X, \+ X2) :- + !, + ground_term_with_known_atoms(X,X2). +ground_term_with_known_atoms( true, true) :- + !. +ground_term_with_known_atoms( false, false) :- + !. +ground_term_with_known_atoms( (X is Y), true) :- + !, + call(X is Y). +ground_term_with_known_atoms( (X < Y), true) :- + !, + call(X < Y). +ground_term_with_known_atoms( (X > Y), true) :- + !, + call(X > Y). +ground_term_with_known_atoms( (X >= Y), true) :- + !, + call(X >= Y). +ground_term_with_known_atoms( (X =< Y), true) :- + !, + call(X =< Y). +ground_term_with_known_atoms( (X = Y), true) :- + !, + call(X = Y). +ground_term_with_known_atoms( (X == Y), true) :- + !, + call(X == Y). +ground_term_with_known_atoms( call(X), '$atom'(X)) :- + !, + call(X). +ground_term_with_known_atoms( X, '$atom'(X)) :- + !, + recorded(reachable,X,_). + diff --git a/packages/ProbLog/problog/discrete.yap b/packages/ProbLog/problog/discrete.yap new file mode 100644 index 000000000..2cd45d11f --- /dev/null +++ b/packages/ProbLog/problog/discrete.yap @@ -0,0 +1,417 @@ +%%% -*- Mode: Prolog; -*- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% $Date: 2010-12-02 15:20:15 +0100 (Thu, 02 Dec 2010) $ +% $Revision: 5043 $ +% +% This file is part of ProbLog +% http://dtai.cs.kuleuven.be/problog +% +% ProbLog was developed at Katholieke Universiteit Leuven +% +% Copyright 2009 +% Angelika Kimmig, Vitor Santos Costa, Bernd Gutmann +% +% Main authors of this file: +% Bernd Gutmann +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% 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. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Discrete probability distributions for ProbLog +% +% this file contains predicates to emulate discrete distributions in ProbLog +% +% uniform(I,N,ID) +% emulates a uniform discrete distribution +% P(I) = 1/N for I in {1,2,...,N} +% If I is a variable, the predicate backtracks over all +% possible values for I +% ID has to be ground, it is an identifier which - if in the same proof - +% reused, will always return the same value +% +% binomial(K,N,P,ID) +% emulates a binomial distribution +% P(K) = (N over K) x P^K x (1-P)^(N-K) for K in {0,1,...,N} +% If K is a variable, the predicate backtracks over all +% possible values for K +% ID has to be ground, it is an identifier which - if in the same proof - +% reused, will always return the same value +% +% poisson(K,Lambda,ID) +% emulates a Poisson distribution +% P(K) = Lamda^K / K! x exp(-Lambda) for K in {0,1,2, ....} +% If K is a variable, the predicate backtracks over all +% possible values for K +% ID has to be ground, it is an identifier which - if in the same proof - +% reused, will always return the same value +% +% +% Author : Bernd Gutmann, bernd.gutmann@cs.kuleuven.be +% Version : January 14, 2009 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +:- module(discrete, [uniform/3,binomial/4,poisson/3]). +:- use_module('../problog'). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% A distribution over 1,2, ..., N +% where P(I) := 1/N +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Prob::p_uniform(_I,_N,_ID,Prob). +uniform(I,N,ID) :- + integer(N), + N>0, + ( var(I) ; integer(I), I>0, I== 0 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Prob::p_binomial(_K,_N,_P,_ID,Prob). +binomial(K,N,P,ID) :- + number(P), + P >= 0, + P =< 1, + integer(N), + N>=0, + ( var(K) ; integer(K),K>=0,K= + K= 0.0, + FactProb =< 1.0, + + ( + ( + call(Old), + p_binomial(K,N,P,ID,FactProb), + KResult=K + ); ( + K= 0 +% ID has to be ground +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +P :: p_poisson(_K,_Lambda,_ID,P). + +poisson(K,Lambda,ID) :- + ( var(K); integer(K),K>=0 ), + number(Lambda), + Lambda>=0, + ground(ID), + poisson(0,K,true,Lambda,0.0,ID). + +poisson(K,K2,Old,Lambda,ProbAcc,ID) :- + % KResult is a number, make sure, not to go over it + % safes some time + ( + integer(K2) + -> + K= 0.0, + FactProb =< 1.0, + + ( + ( + call(Old), + p_poisson(K,Lambda,ID,FactProb), + K2=K + ); ( + NextK is K+1, + NextProbAcc is ProbAcc+Prob, + poisson(NextK,K2,(problog_not(p_poisson(K,Lambda,ID,FactProb)),Old),Lambda,NextProbAcc,ID) + ) + ). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + + +% calculates (Lambda ** N) / N! + +power_over_factorial(N,Lambda,Result) :- + integer(N), + N>=0, + power_over_factorial(N,Lambda,1.0,Result). +power_over_factorial(N,Lambda,Old,Result) :- + ( + N>0 + -> + ( + N2 is N-1, + New is Old * Lambda/N, + power_over_factorial(N2,Lambda,New,Result) + ); Result=Old + ). + + + +% calculates (N \over K) = N!/(K! * (N-K)!) + +binomial_coefficient(N,K,Result) :- + integer(K), + K >= 0, + binomial_coefficient(K,N,1,Result). +binomial_coefficient(I,N,Product,Result) :- + ( + I=0 + -> + Result=Product; + ( + I2 is I-1, + Product2 is Product * (N+1-I)/I, + binomial_coefficient(I2,N,Product2,Result) + ) + ). \ No newline at end of file diff --git a/packages/ProbLog/problog/flags.yap b/packages/ProbLog/problog/flags.yap index 438a8ca07..24239fc88 100644 --- a/packages/ProbLog/problog/flags.yap +++ b/packages/ProbLog/problog/flags.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-12-02 15:20:15 +0100 (Thu, 02 Dec 2010) $ -% $Revision: 5043 $ +% $Date: 2011-02-08 16:00:57 +0100 (Tue, 08 Feb 2011) $ +% $Revision: 5614 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog diff --git a/packages/ProbLog/problog/print_learning.yap b/packages/ProbLog/problog/print_learning.yap index 8389bc570..95a60b7d7 100644 --- a/packages/ProbLog/problog/print_learning.yap +++ b/packages/ProbLog/problog/print_learning.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-12-02 15:20:15 +0100 (Thu, 02 Dec 2010) $ -% $Revision: 5043 $ +% $Date: 2011-04-21 14:18:59 +0200 (Thu, 21 Apr 2011) $ +% $Revision: 6364 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -207,11 +207,12 @@ %%%%%%%% % Collected OS depended instructions %%%%%%%% -:- module(print_learning, [format_learning/3]). +:- module(print_learning, [format_learning/3,format_learning_rule/3]). % load our own modules :- use_module(flags). +:- use_module(termhandling). :- initialization(problog_define_flag(verbosity_learning, problog_flag_validate_0to5,'How much output shall be given (0=nothing,5=all)',5, learning_general)). @@ -230,3 +231,42 @@ format_learning(Level,String,Arguments) :- flush_output(user). format_learning(_,_,_) :- true. + +%======================================================================== +%= +%= +%= +%======================================================================== + + +format_learning_rule(D,'$atom'(A)):- + format_learning(D,'~q',[A]). +format_learning_rule(D,\+A):- + format_learning(D,'\+',[]), + format_learning_rule(D,A). + +format_learning_rule(D,'true'):- + format_learning(D,'true',[]). +format_learning_rule(D,'false'):- + format_learning(D,'false',[]). + +format_learning_rule(D,(First<=>Second)):- + format_learning_rule(D,First), + format_learning(D,'<==>',[]), + format_learning_rule(D,Second) + . +format_learning_rule(D,(First;Second)):- + format_learning(D,'(',[]), + format_learning_rule(D,First), + format_learning(D,';',[]), + format_learning_rule(D,Second), + format_learning(D,')',[]) + . +format_learning_rule(D,(First,Second)):- + format_learning_rule(D,First), + format_learning(D,',',[]), + format_learning_rule(D,Second) + . +format_learning_rule(D,R,Key):- + (format_learning_rule(D,R) ; (format('~q ',[flr(D,R,Key)]),throw(ball))), + format_learning(D,' (~q)~n',[Key]). diff --git a/packages/ProbLog/problog/ptree.yap b/packages/ProbLog/problog/ptree.yap index 2d8afb1d2..ad2ae30cf 100644 --- a/packages/ProbLog/problog/ptree.yap +++ b/packages/ProbLog/problog/ptree.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2011-01-16 19:24:10 +0100 (Sun, 16 Jan 2011) $ -% $Revision: 5260 $ +% $Date: 2011-04-11 17:23:11 +0200 (Mon, 11 Apr 2011) $ +% $Revision: 5920 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -679,6 +679,10 @@ writemap([Name|Names],[Fact|Facts]):- writemap(Names, Facts). bdd_vars_script([], []). +bdd_vars_script([false|T], Names):- + bdd_vars_script(T, Names). +bdd_vars_script([true|T], Names):- + bdd_vars_script(T, Names). bdd_vars_script([not(A)|B], Names) :- !, bdd_vars_script([A|B], Names). bdd_vars_script([A|B], [NameA|Names]) :- diff --git a/packages/ProbLog/problog/tabling.yap b/packages/ProbLog/problog/tabling.yap index 1171fd126..f3911265b 100644 --- a/packages/ProbLog/problog/tabling.yap +++ b/packages/ProbLog/problog/tabling.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-12-13 16:29:18 +0100 (Mon, 13 Dec 2010) $ -% $Revision: 5122 $ +% $Date: 2011-04-11 17:23:11 +0200 (Mon, 11 Apr 2011) $ +% $Revision: 5920 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -305,21 +305,21 @@ problog_table(P) :- problog_table(P, M). problog_table(M:P, _) :- - problog_table(P, M). + problog_table(P, M). problog_table((P1, P2), M) :- - problog_table(P1, M), - problog_table(P2, M). + problog_table(P1, M), + problog_table(P2, M). problog_table(Name/Arity, Module) :- - length(Args,Arity), - Head =.. [Name|Args], - \+ predicate_property(Module:Head, dynamic), !, - throw(error('problog_table: Problog tabling currently requires the predicate to be declared dynamic and compiles it to static.')). + length(Args,Arity), + Head =.. [Name|Args], + \+ predicate_property(Module:Head, dynamic), !, + throw(error('problog_table: Problog tabling currently requires the predicate to be declared dynamic and compiles it to static.')). problog_table(Name/Arity, Module) :- - length(Args,Arity), - Head =.. [Name|Args], - atom_concat(['problog_', Name, '_original'], OriginalName), - atom_concat(['problog_', Name, '_mctabled'], MCName), - atom_concat(['problog_', Name, '_tabled'], ExactName), + length(Args,Arity), + Head =.. [Name|Args], + atom_concat(['problog_', Name, '_original'], OriginalName), + atom_concat(['problog_', Name, '_mctabled'], MCName), + atom_concat(['problog_', Name, '_tabled'], ExactName), % Monte carlo tabling catch((table(Module:MCName/Arity), diff --git a/packages/ProbLog/problog/termhandling.yap b/packages/ProbLog/problog/termhandling.yap new file mode 100644 index 000000000..39addcf0f --- /dev/null +++ b/packages/ProbLog/problog/termhandling.yap @@ -0,0 +1,454 @@ +%%% -*- Mode: Prolog; -*- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% $Date: 2011-04-09 12:00:00 +0200 (Sat, 09 Apr 2011) $ +% $Revision: 5890 $ +% +% Main authors of this file: +% Bernd Gutmann +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% 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. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +:- module(termhandling, [term_element/2, + propagate/5, + propagate_interpretation/3, + simplify/3, + list_to_disjunction/2, + list_to_conjunction/2, + op( 551, yfx, <=> ), + not/2]). + +% propagate( +OldTerm, +AtomToReplace, +ReplacementTermForAtom, -NewTerm, -ReplaceHasHappend). +% simplify(+OldTerm,-NewTerm,-SimplificationHasHappend). +% list_to_disjunction(+list,-Disjunction). +% list_to_conjunction(+list,+Conjunction). + +:- op( 551, yfx, <=> ). + +:- style_check(all). +:- yap_flag(unknown,error). + +%======================================================================== +%= +%= +%= term_element(+GroundTerm, ?Atom) +%======================================================================== + +term_element((X,Y),Z) :- + (term_element(X,Z);term_element(Y,Z)). +term_element((X;Y),Z) :- + (term_element(X,Z);term_element(Y,Z)). +term_element((X <=> Y),Z) :- + (term_element(X,Z);term_element(Y,Z)). +term_element(\+ X,Z) :- + term_element(X,Z). +term_element('$atom'(X),'$atom'(X)) :- + X \== true, + X \== false. + + +% or(+Boolean,+Boolean,-Boolean) + +or(true,_,true). +or(false,X,X). + + +% not(+Boolean,-Boolean) +not(true,false). +not(false,true). + +%======================================================================== +%= +%= +%= propagate_interpretation(+GroundTerm, +ID, -GroundTerm) +%======================================================================== + +propagate_interpretation((X,Y),ID,(X2,Y2)) :- + propagate_interpretation(X,ID,X2), + propagate_interpretation(Y,ID,Y2). +propagate_interpretation((X;Y),ID,(X2;Y2)) :- + propagate_interpretation(X,ID,X2), + propagate_interpretation(Y,ID,Y2). +propagate_interpretation((X <=> Y),ID,(X2 <=> Y2)) :- + propagate_interpretation(X,ID,X2), + propagate_interpretation(Y,ID,Y2). +propagate_interpretation((\+ X), ID,\+ X2) :- + propagate_interpretation(X,ID,X2). +propagate_interpretation('$atom'(X),ID,Value) :- + ( + user:known(ID,X,Value) + -> + true; + Value='$atom'(X) + ). + +%======================================================================== +%= +%= +%= +%======================================================================== + +propagate((X,Y),A,AValue,(X2,Y2),Result) :- + propagate(X,A,AValue,X2,Result1), + propagate(Y,A,AValue,Y2,Result2), + or(Result1,Result2,Result). +propagate((X;Y),A,AValue,(X2;Y2),Result) :- + propagate(X,A,AValue,X2,Result1), + propagate(Y,A,AValue,Y2,Result2), + or(Result1,Result2,Result). +propagate((X <=> Y),A,AValue,(X2 <=> Y2),Result) :- + propagate(X,A,AValue,X2,Result1), + propagate(Y,A,AValue,Y2,Result2), + or(Result1,Result2,Result). +propagate((\+ X), A, AValue,\+ X2,Result) :- + propagate(X,A,AValue,X2,Result). +propagate('$atom'(X),'$atom'(A),AValue,X2,Result) :- + ( + X==A + -> + ( + X2=AValue, + Result=true + ); + ( + X2=X, + Result=false + ) + ). +propagate(true,_,_,true,false). +propagate(false,_,_,false,false). + +%======================================================================== +%= +%= +%= +%======================================================================== + + +negate_atom(\+ '$atom'(X), '$atom'(X)). +negate_atom( '$atom'(X),\+ '$atom'(X)). + +occurs_check_and((X,_), A) :- + occurs_check_and(X,A), + !. +occurs_check_and((_,Y), A) :- + occurs_check_and(Y,A). +occurs_check_and( '$atom'(X), '$atom'(X)). + + +occurs_check_or((X;_), A) :- + occurs_check_or(X,A), + !. +occurs_check_or((_;Y), A) :- + occurs_check_and(Y,A). +occurs_check_or( '$atom'(X), '$atom'(X) ). + + +%======================================================================== +%= +%= Tries to simplify Term. If succeeded Status=true and SimplifiedTerm +%= is bound to the simplified term. If not succeeded Status=false and +%= SimplifiedTerm=Term. +%= +%= Only works for ground terms! If non-ground terms are used, the +%= the result is undefined!!! +%= +%= simplify(+Term, -SimplifiedTerm, -Status) +%= +%======================================================================== + + +simplify(Term,Term3,true) :- + simplify_intern(Term,Term2,Result), + Result==true, + !, + simplify(Term2,Term3,_). +simplify(Term,Term,false). +%----------- + +simplify_intern( (X<=>Y), NewTerm, Result) :- + simplify_intern_implication(X,Y,NewTerm,Result). +simplify_intern((\+ X), NewTerm,Result) :- + simplify_intern_negation(X,NewTerm,Result). +simplify_intern( (X;Y), NewTerm, Result) :- + simplify_intern_or(X,Y,NewTerm,Result). +simplify_intern( (X,Y), NewTerm, Result) :- + simplify_intern_and(X,Y,NewTerm,Result). +simplify_intern('$atom'(X),'$atom'(X),false). +simplify_intern(true,true,false). +simplify_intern(false,false,false). + + +%----------- +simplify_intern_or( true,_,true,true) :- + !. +simplify_intern_or( false,X,X,true) :- + !. +simplify_intern_or(_,true,true,true) :- + !. +simplify_intern_or(X,false,X,true) :- + !. +% quite expensive +% simplify_intern_or(X,Y,true,true) :- +% negate_atom(X,X2), +% occurs_check_or(Y,X2), +% !. +simplify_intern_or(X,Y,(X2;Y2),Result) :- + !, + simplify_intern(X,X2,Result1), + simplify_intern(Y,Y2,Result2), + or(Result1,Result2,Result). +%----------- +simplify_intern_and( true,X,X,true) :- + !. +simplify_intern_and( false,_,false,true) :- + !. +simplify_intern_and(X,true,X,true) :- + !. +simplify_intern_and(_,false,false,true) :- + !. +% quite expensive +% simplify_intern_and(X,Y,false,true) :- +% negate_atom(X,X2), +% occurs_check_and(Y,X2), +% !. +simplify_intern_and(X,Y,(X2,Y2),Result) :- + !, + simplify_intern(X,X2,Result1), + simplify_intern(Y,Y2,Result2), + or(Result1,Result2,Result). + +%----------- +simplify_intern_implication(true,Y,Y,true) :- + !. +simplify_intern_implication(false,Y,(\+ Y),true) :- + !. +simplify_intern_implication(X,true,X,true) :- + !. +simplify_intern_implication(X,false,(\+ X),true) :- + !. +simplify_intern_implication(X,Y,(X <=> Y2), Result) :- + !, + simplify_intern(Y,Y2,Result). + +%----------- + +simplify_intern_negation(true,false,true). +simplify_intern_negation(false,true,true). +simplify_intern_negation((\+ X),X,true). +simplify_intern_negation((A,B),Term,true) :- + simplify_intern_or( (\+ A), (\+ B), Term, _). +simplify_intern_negation((A;B),Term,true) :- + simplify_intern_and( (\+ A), (\+ B), Term, _). +simplify_intern_negation('$atom'(X),(\+ '$atom'(X)),false). + +%======================================================================== +%= +%= +%= list_to_disjunction(+List,-Disjunction) +%======================================================================== +list_to_disjunction([A,B|T],(A;T2)) :- + !, + list_to_disjunction([B|T],T2). +list_to_disjunction([A],A). +list_to_disjunction([],false). + +%======================================================================== +%= +%= +%= list_to_conjunction(+List,(A,T2)-Conjunction) :- +%======================================================================== + +list_to_conjunction([A,B|T],(A,T2)) :- + !, + list_to_conjunction([B|T],T2). +list_to_conjunction([A],A). +list_to_conjunction([],true). diff --git a/packages/ProbLog/problog_examples/alarm.pl b/packages/ProbLog/problog_examples/alarm.pl new file mode 100644 index 000000000..41dfc7c0b --- /dev/null +++ b/packages/ProbLog/problog_examples/alarm.pl @@ -0,0 +1,67 @@ +%%% -*- Mode: Prolog; -*- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% ProbLog program describing modelling a simplified version of the ALARM network +% (running example used in the paper [Gutmann et. al, ECML 2011]) +% $Id: alarm.pl 6416 2011-06-10 14:38:44Z bernd $ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% example for parameter learning with LFI-ProbLog +% +% training examples are included at the end of the file +% query ?- do_learning(20). +% will run 20 iterations of learning with default settings +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + +:- use_module('../problog'). +:- use_module('../problog_lfi'). + +% uncomment to see what is happening +:- set_problog_flag(verbosity_learning,5). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Probabilistic Facts % +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% the t(_) identifies them as tunable, that is, +% the probabilities are to be learned + +t(_) :: burglary. +t(_) :: earthquake. +t(_) :: hears_alarm(_Person). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Background Knowledge % +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% the background knowledge, read as myclause(Head,Body) +% clauses are assumed to be range-restricted + +myclause(person(mary), true). +myclause(person(john), true). +myclause(alarm, burglary). +myclause(alarm, earthquake). +myclause(calls(Person), (person(Person),alarm,hears_alarm(Person))). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Training examples % +%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +example(1). +example(2). + +%%%% Example 1 +known(1,alarm,true). + +%%%% Example 2 +known(2,earthquake,false). +known(2,calls(mary),true). + diff --git a/packages/ProbLog/problog_learning.yap b/packages/ProbLog/problog_learning.yap index 6055a8ef4..4dc88bb1b 100644 --- a/packages/ProbLog/problog_learning.yap +++ b/packages/ProbLog/problog_learning.yap @@ -2,8 +2,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% $Date: 2010-12-15 15:05:44 +0100 (Wed, 15 Dec 2010) $ -% $Revision: 5142 $ +% $Date: 2011-04-21 14:18:59 +0200 (Thu, 21 Apr 2011) $ +% $Revision: 6364 $ % % This file is part of ProbLog % http://dtai.cs.kuleuven.be/problog @@ -529,7 +529,7 @@ init_learning :- ), - succeeds_n_times(user:example(_,_,_,_),TestExampleCount), + succeeds_n_times(user:test_example(_,_,_,_),TestExampleCount), format_learning(3,'~q test examples~n',[TestExampleCount]), succeeds_n_times(user:example(_,_,_,_),TrainingExampleCount), @@ -555,8 +555,8 @@ init_learning :- -> set_problog_flag(alpha,1.0); ( - succeed_n_times((user:example(_,_,P,=),P=:=1.0),Pos_Count), - succeed_n_times((user:example(_,_,P,=),P=:=0.0),Neg_Count), + succeeds_n_times((user:example(_,_,P,=),P=:=1.0),Pos_Count), + succeeds_n_times((user:example(_,_,P,=),P=:=0.0),Neg_Count), Alpha is Pos_Count/Neg_Count, set_problog_flag(alpha,Alpha) ) @@ -671,11 +671,17 @@ update_values :- forall(get_fact_probability(ID,Prob), ( - inv_sigmoid(Prob,Value), - ( - non_ground_fact(ID) - -> - format(Handle,'@x~q_*~n~10f~n',[ID,Value]); + (problog:dynamic_probability_fact(ID) -> + get_fact(ID, Term), + forall(grounding_is_known(Term, GID), ( + problog:dynamic_probability_fact_extract(Term, Prob2), + inv_sigmoid(Prob2,Value), + format(Handle, '@x~q_~q~n~10f~n', [ID,GID, Value]))) + ; non_ground_fact(ID) -> + inv_sigmoid(Prob,Value), + format(Handle,'@x~q_*~n~10f~n',[ID,Value]) + ; + inv_sigmoid(Prob,Value), format(Handle,'@x~q~n~10f~n',[ID,Value]) ) )), diff --git a/packages/ProbLog/problog_lfi.yap b/packages/ProbLog/problog_lfi.yap new file mode 100644 index 000000000..c9f74dadc --- /dev/null +++ b/packages/ProbLog/problog_lfi.yap @@ -0,0 +1,1167 @@ +%%% -*- Mode: Prolog; -*- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% $Date: 2011-04-09 12:00:00 +0200 (Sat, 09 Apr 2011) $ +% $Revision: 5890 $ +% +% This file is part of ProbLog +% http://dtai.cs.kuleuven.be/problog +% +% ProbLog was developed at Katholieke Universiteit Leuven +% +% Copyright 2009 +% Angelika Kimmig, Vitor Santos Costa, Bernd Gutmann +% +% Main authors of this file: +% Bernd Gutmann +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% 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. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +:- module(problog_lfi,[do_learning/1, + do_learning/2, + create_ground_tunable_fact/2, + reset_learning/0 + ]). + + + +% switch on all the checks to reduce bug searching time +:- style_check(all). +:- yap_flag(unknown,error). + +% load modules from the YAP library +:- use_module(library(lists),[member/2,nth1/3,sum_list/2,min_list/2,max_list/2]). +:- use_module(library(system),[file_exists/1,exec/3,wait/2]). + +% load our own modules +:- use_module('problog'). +:- use_module('problog/logger'). +:- use_module('problog/flags'). +:- use_module('problog/os'). +:- use_module('problog/completion'). +:- use_module('problog/print_learning'). +:- use_module('problog/utils_learning'). +:- use_module('problog/utils'). +:- use_module('problog/ad_converter'). + + +% used to indicate the state of the system +:- dynamic(learning_initialized/0). +:- dynamic(current_iteration/1). +:- dynamic(query_all_scripts/2). +:- dynamic(last_llh/1). + +:- discontiguous(user:myclause/1). +:- discontiguous(user:myclause/2). +:- discontiguous(user:known/3). +:- discontiguous(user:example/1). +:- discontiguous(user:test_example/1). + +:- multifile(completion:bdd_cluster/2). +%:- multifile(completion:known_count/4). + +user:term_expansion(myclause((Head<--Body)), C) :- + prolog_load_context(module,Module), + term_expansion_intern_ad((Head<--Body), Module,lfi_learning, C). + +%======================================================================== +%= Hack for Ingo, to allow tunable facts with body +%= +%= e.g. :- create_ground_tunable_fact( t(_) :: f(X), member(X,[a,b,c])). +%= will create +%= t(_) :: f(a). +%= t(_) :: f(b). +%= t(_) :: f(c). +%======================================================================== + +create_ground_tunable_fact(F,B) :- + B, + once(problog_assert(F)), + fail. +create_ground_tunable_fact(_,_). + + +%======================================================================== +%= store the facts with the learned probabilities to a file +%= if F is a variable, a filename based on the current iteration is used +%= +%======================================================================== + +save_model:- + current_iteration(Iteration), + create_factprobs_file_name(Iteration,Filename), + open(Filename,'write',Handle), + forall((current_predicate(user:ad_intern/3),user:ad_intern(Original,ID,Facts)), + print_ad_intern(Handle,Original,ID,Facts) + ), + forall(probabilistic_fact(_,Goal,ID), + ( + array_element(factprob,ID,P), + ( + is_mvs_aux_fact(Goal) + -> + format(Handle,'% ~10f :: ~q. %ID=~q~n',[P,Goal,ID]); + format(Handle ,'~10f :: ~q. %ID=~q~n',[P,Goal,ID]) + ) + ) + ), + close(Handle). + +is_mvs_aux_fact(A) :- + functor(A,B,_), + atomic_concat(mvs_fact_,_,B). + +print_ad_intern(Handle,(Head<--Body),_ID,Facts) :- + format(Handle,'myclause( (',[]), + print_ad_intern(Head,Facts,0.0,Handle), + format(Handle,' <-- ~q) ).~n',[Body]). +print_ad_intern((A1;B1),[A2|B2],Mass,Handle) :- + once(print_ad_intern_one(A1,A2,Mass,NewMass,Handle)), + format(Handle,'; ',[]), + print_ad_intern(B1,B2,NewMass,Handle). +print_ad_intern(_::Fact,[],Mass,Handle) :- + P2 is 1.0 - Mass, + format(Handle,'~f :: ~q',[P2,Fact]). +print_ad_intern_one(_::Fact,_::AuxFact,Mass,NewMass,Handle) :- + % ask problog to get the fact_id + once(probabilistic_fact(_,AuxFact,FactID)), + % look in our table for the probability + array_element(factprob,FactID,P), + P2 is P * (1-Mass), + NewMass is Mass+P2, + format(Handle,'~f :: ~q',[P2,Fact]). +%======================================================================== +%= initialize everything and perform Iterations times EM +%= can be called several times +%======================================================================== + +do_learning(Iterations) :- + do_learning(Iterations,-1). + +do_learning(Iterations,Epsilon) :- + integer(Iterations), + number(Epsilon), + Iterations>0, + init_learning, + !, + do_learning_intern(Iterations,Epsilon), + !, + copy_back_fact_probabilities. + +do_learning_intern(0,_) :- + !. +do_learning_intern(Iterations,Epsilon) :- + Iterations>0, + logger_start_timer(duration), + + current_iteration(CurrentIteration), + !, + retractall(current_iteration(_)), + !, + NextIteration is CurrentIteration+1, + assertz(current_iteration(NextIteration)), + EndIteration is CurrentIteration+Iterations-1, + + format_learning(1,'~nIteration ~d of ~d~n',[CurrentIteration,EndIteration]), + logger_set_variable(iteration,CurrentIteration), + + write_probabilities_file, + + once(llh_testset), + + once(ground_truth_difference), + once(em_one_iteration), + + problog_flag(log_frequency,Log_Frequency), + ( + ( Log_Frequency>0, 0 =:= CurrentIteration mod Log_Frequency) + -> + once(save_model); + true + ), + !, + + ( + last_llh(Last_LLH) + -> + ( + retractall(last_llh(_)), + logger_get_variable(llh_training_set,Current_LLH), + assertz(last_llh(Current_LLH)), + !, + LLH_Diff is abs(Last_LLH-Current_LLH) + ); ( + logger_get_variable(llh_training_set,Current_LLH), + assertz(last_llh(Current_LLH)), + LLH_Diff is Epsilon+1 + ) + ), + + logger_stop_timer(duration), + logger_write_data, + RemainingIterations is Iterations-1, + !, + garbage_collect, + !, + + ( + LLH_Diff>Epsilon + -> + do_learning_intern(RemainingIterations,Epsilon); + true + ). + + +%======================================================================== +%= find proofs and build bdds for all training and test examples +%= +%= +%======================================================================== +init_learning :- + learning_initialized, + !. +init_learning :- + convert_filename_to_problog_path('problogbdd_lfi', Path), + ( + file_exists(Path) + -> + true; + ( + problog_path(PD), + format(user_error, 'WARNING: Can not find file: problogbdd_lfi. Please place file in problog path: ~q~n',[PD]), + fail + ) + ), + + check_theory, + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Delete the stuff from the previous run + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + problog_flag(reuse_initialized_bdds,Re_Use_Flag), + + ( + Re_Use_Flag==false + -> + empty_bdd_directory; + true + ), + empty_output_directory, + + + logger_write_header, + + format_learning(1,'Initializing everything~n',[]), + + ( + current_predicate(user:test_example/1) + -> + ( + succeeds_n_times(user:test_example(_),TestExampleCount), + format_learning(3,'~q test example(s)~n',[TestExampleCount]) + ); + true + ), + + succeeds_n_times(user:example(_),TrainingExampleCount), + format_learning(3,'~q training example(s)~n',[TrainingExampleCount]), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Create arrays for probabilties and counting tables + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + once(initialize_fact_probabilities), + problog:probclause_id(N), + static_array(factprob_temp,N,float), + static_array(factusage,N,int), + static_array(known_count_true_training,N,int), + static_array(known_count_false_training,N,int), + static_array(known_count_true_test,N,int), + static_array(known_count_false_test,N,int), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % build BDD script for every example + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + once(init_queries), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % done + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + assertz(current_iteration(0)), + assertz(learning_initialized), + once(save_model), + + format_learning(1,'~n',[]), + + garbage_collect, + garbage_collect_atoms. + + + + +%======================================================================== +%= This predicate checks some aspects of the data given by the user. +%= You know folks: Garbage in, garbage out. +%= +%======================================================================== +check_theory :- + ( + (user:myclause(Head,Body),P :: Head) + -> + ( + format(user_error,'===============================================================~n',[]), + format(user_error,' The theory contains an atom that appears both as probabilistic~n',[]), + format(user_error,' fact and as head of an rule. This is not allowed.~2n',[]), + format(user_error,' ~q~n',[P :: Head]), + format(user_error,' ~q~2n',[myclause(Head,Body)]), + format(user_error,'===============================================================~2n',[]), + + throw(bad_theory(Head)) + ); + true + ), + + ( + (current_predicate(user:example/1),user:example(_)) + -> + true; + ( + format(user_error,'===============================================================~n',[]), + format(user_error,' No training examples specified.~n',[]), + format(user_error,'===============================================================~2n',[]), + throw(bad_theory(no_training_examples)) + ) + ), + + ( + ( current_predicate(user:test_example/1),user:example(ID), user:test_example(ID) ) + -> + ( + format(user_error,'===============================================================~n',[]), + format(user_error,' The example ~q appears both as test and as training example.~n',[ID]), + format(user_error,' Example IDs from test and training examples must be disjoint.~2n',[]), + format(user_error,' Do NOT bypass this test, since the implementation yields wrong resuls~n',[]), + format(user_error,' when an example ID appears both as test and training example.',[]), + format(user_error,'===============================================================~2n',[]), + + throw(bad_theory(double_id(ID))) + ); + true + ), + + ( + (current_predicate(user:known/3),user:example(ID2),user:known(ID2,_,_)) + -> + true; + ( + format(user_error,'===============================================================~n',[]), + format(user_error,' No evidence specified.~n',[]), + format(user_error,'===============================================================~2n',[]), + throw(bad_theory(no_evidence)) + ) + ), + + + ( + (user:known(ID,Foo,Evidence), (Evidence\=true,Evidence\=false)) + -> + ( + format(user_error,'===============================================================~n',[]), + format(user_error,' Bad evidence for training example ~q: ~q.~n',[ID,known(ID,Foo,Evidence)]), + format(user_error,'===============================================================~2n',[]), + throw(bad_theory(bad_evidence(ID))) + ); + true + ), + + ( + (user:known(ID,Foo,true), user:known(ID,Foo,false)) + -> + ( + format(user_error,'===============================================================~n',[]), + format(user_error,' Bad evidence for training example ~q: ~q and ~q~n',[ID,known(ID,Foo,true),known(ID,Foo,false)]), + format(user_error,'===============================================================~2n',[]), + throw(bad_theory(bad_evidence(ID))) + ); + true + ). + + + +%======================================================================== +%= copy fact probabilities to array for speeding up the update +%= +%= +%======================================================================== + +initialize_fact_probabilities :- + problog:probclause_id(N), + static_array(factprob,N,float), + + forall(get_fact_probability(FactID,P), + update_array(factprob,FactID,P)). + +copy_back_fact_probabilities :- + forall(tunable_fact(FactID,_), + ( + array_element(factprob,FactID,P), + set_fact_probability(FactID,P) + ) + ). + + + +%======================================================================== +%= This predicate goes over all training and test examples, +%= calls the inference method of ProbLog and stores the resulting +%= BDDs +%======================================================================== + + +init_queries :- + problog_flag(cluster_bdds,Cluster_BDDs), + format_learning(2,'Build BDDs for examples~n',[]), + forall(user:example(Training_ID), + ( + format_learning(3,'training example ~q: ',[Training_ID]), + init_one_query(Training_ID,training) + ) + ), + + forall( + ( + current_predicate(user:test_example/1), + user:test_example(Test_ID) + ), + ( + format_learning(3,'test example ~q: ',[Test_ID]), + init_one_query(Test_ID,test) + ) + ), + + ( + Cluster_BDDs==true + -> + ( + format_learning(2,'Calculate MD5s for training example BDD scripts~n',[]), + create_training_query_cluster_list(Training_Set_Cluster_List), + format_learning(2,'Calculate MD5s for test example BDD scripts~n',[]), + create_test_query_cluster_list(Test_Set_Cluster_List) + ); + ( + findall( a(QueryID,ClusterID,1), ( + current_predicate(user:test_example/1), + user:test_example(QueryID), + bdd_cluster(QueryID,ClusterIDs), + member(ClusterID,ClusterIDs) + ), Test_Set_Cluster_List), + + findall( a(QueryID,ClusterID,1), ( + user:example(QueryID), + bdd_cluster(QueryID,ClusterIDs), + member(ClusterID,ClusterIDs) + ), Training_Set_Cluster_List) + ) + ), + + assertz(training_set_cluster_list(Training_Set_Cluster_List)), + assertz(test_set_cluster_list(Test_Set_Cluster_List)). + +%======================================================================== +%= +%======================================================================== + +init_one_query(QueryID,_Query_Type) :- + create_known_values_file_name(QueryID,File_Name), + file_exists(File_Name), + !, + format_learning(3,'Will reuse existing BDD script ~q for example ~q.~n',[File_Name,QueryID]), + consult(File_Name). + + %FIXME + + % check whether we can read the BDD script for each cluster + +init_one_query(QueryID,Query_Type) :- + once(propagate_evidence(QueryID,Query_Type)), + format_learning(3,'~n',[]), + garbage_collect_atoms, + garbage_collect. + + +create_test_query_cluster_list(L2) :- + findall( a(QueryID,ClusterID), ( + current_predicate(user:test_example/1), + user:test_example(QueryID), + bdd_cluster(QueryID,ClusterIDs), + member(ClusterID,ClusterIDs) + ), AllCluster), + calc_all_md5(AllCluster,AllCluster2), + findall(a(QueryID1,ClusterID1,Len),(bagof(a(QueryID,ClusterID),member(a(QueryID,ClusterID,_MD5),AllCluster2),L),nth1(1,L,a(QueryID1,ClusterID1)),length(L,Len)),L2), + !, + + length(AllCluster,Len1), + length(L2,Len2), + + ( + Len1>0 + -> + ( + Reduction is Len2/Len1, + format_learning(3,' ~d cluster after splitting, ~d unique cluster ==> reduction factor of ~4f~n',[Len1,Len2,Reduction]) + ); + true + ). + +calc_all_md5([],[]). +calc_all_md5([a(QueryID,ClusterID)|T],[a(QueryID,ClusterID,MD5)|T2]) :- + create_bdd_file_name(QueryID,ClusterID,File_Name), + calc_md5(File_Name,MD5), + calc_all_md5(T,T2). + +create_training_query_cluster_list(L2) :- + findall( a(QueryID,ClusterID), ( + user:example(QueryID), + bdd_cluster(QueryID,ClusterIDs), + member(ClusterID,ClusterIDs) + ), AllCluster), + + calc_all_md5(AllCluster,AllCluster2), + + + findall(a(QueryID1,ClusterID1,Len), + ( + bagof(a(QueryID,ClusterID),member(a(QueryID,ClusterID,_MD5),AllCluster2),L), + nth1(1,L,a(QueryID1,ClusterID1)), + length(L,Len) + ),L2), + + length(AllCluster,Len1), + length(L2,Len2), + + Reduction is Len2/Len1, + + format_learning(3,' ~d cluster after splitting, ~d unique cluster ==> reduction factor of ~4f~n',[Len1,Len2,Reduction]). + + +%======================================================================== +%= +%======================================================================== + +reset_learning :- + ( + learning_initialized + -> + ( + retractall(current_iteration(_)), + retractall(learning_initialized), + + retractall(training_set_cluster_list(_)), + retractall(test_set_cluster_list(_)), + close_static_array(factprob), + close_static_array(factprob_temp), + close_static_array(factusage), + + close_static_array(known_count_true_training), + close_static_array(known_count_false_training), + close_static_array(known_count_true_test), + close_static_array(known_count_false_test), + + reset_completion, + empty_bdd_directory, + empty_output_directory, + + logger_reset_all_variables + ); + true + ). + +%======================================================================== +%= calculate the LLH on the test set and set the variable +%= in the logger module +%======================================================================== + +llh_testset :- + current_predicate(user:test_example/1), + !, + current_iteration(Iteration), + create_test_predictions_file_name(Iteration,F), + + open(F,'write',Handle), + + catch( + sum_forall(LProb, + ( + probabilistic_fact(_,_,FactID), + array_element(factprob,FactID,PFact), + array_element(known_count_true_test,FactID,KK_True), + array_element(known_count_false_test,FactID,KK_False), + + ( + KK_True>0 + -> + Part1 is KK_True*log(PFact); + Part1 is 0.0 + ), + ( + KK_False>0 + -> + LProb is Part1+KK_False*log(1-PFact); + LProb is Part1 + ) + ), + PropagatedLLH + ),_,PropagatedLLH is 0.0/0.0), + format(Handle,'prob_known_atoms(~15e).~n',[PropagatedLLH]), + + test_set_cluster_list(AllCluster), + % deal with test examples where BDD needs to be evaluated + problog_flag(parallel_processes,Parallel_Processes), + once(evaluate_bdds(AllCluster,Handle,Parallel_Processes,'d',':',PropagatedLLH,LLH)), + logger_set_variable(llh_test_set,LLH), + close(Handle). +llh_testset :- + true. + + + + + +%======================================================================== +%= +%= +%= +%======================================================================== + +% FIXME +ground_truth_difference :- + findall(Diff,(tunable_fact(FactID,GroundTruth), + \+continuous_fact(FactID), + \+ var(GroundTruth), + array_element(factprob,FactID,Prob), + Diff is abs(GroundTruth-Prob)),AllDiffs), + ( + AllDiffs==[] + -> + ( + MinDiff=0.0, + MaxDiff=0.0, + DiffMean=0.0 + ) ; + ( + length(AllDiffs,Len), + sum_list(AllDiffs,AllDiffsSum), + min_list(AllDiffs,MinDiff), + max_list(AllDiffs,MaxDiff), + DiffMean is AllDiffsSum/Len + ) + ), + + logger_set_variable(ground_truth_diff,DiffMean), + logger_set_variable(ground_truth_mindiff,MinDiff), + logger_set_variable(ground_truth_maxdiff,MaxDiff). + +%======================================================================== +%= +%= +%======================================================================== + +write_probabilities_file :- + current_iteration(Iteration), + create_bdd_input_file_name(Iteration,Probabilities_File), + open(Probabilities_File,'write',Handle), + forall(get_fact_probability(ID,_), + ( + array_element(factprob,ID,Prob), + + ( + non_ground_fact(ID) + -> + format(Handle,'@x~q_*~n~15e~n1~nx~q~N',[ID,Prob,ID]); + format(Handle,'@x~q~n~15e~n1~nx~q~N',[ID,Prob,ID]) + ) + ) + ), + close(Handle). + + + + +%======================================================================== +%= +%= +%= +%======================================================================== + +update_query(QueryID,ClusterID ,Method,Command,PID,Output_File_Name) :- + current_iteration(Iteration), + + create_bdd_input_file_name(Iteration,Input_File_Name), + create_bdd_output_file_name(QueryID,ClusterID,Iteration,Output_File_Name), + create_bdd_file_name(QueryID,ClusterID,BDD_File_Name), + + problog_dir(PD), + concat_path_with_filename(PD,'problogbdd_lfi',Absolute_Name), + + atomic_concat([Absolute_Name, + ' -i "', Input_File_Name, '"', + ' -l "', BDD_File_Name, '"', + ' -m ',Method, + ' -id ', QueryID, + ' > "', + Output_File_Name, + '"'],Command), + + exec(Command,[std,std,std],PID). + +update_query_wait(QueryID,_ClusterID,Count,Symbol,Command,PID,OutputFilename,BDD_Probability) :- + wait(PID,Error), + format_learning(4,'~w',[Symbol]), + ( + Error \= 0 + -> + ( + format(user_error,'SimpleCUDD stopped with error code ~q.~n', [Error]), + format(user_error,'The command was~n ~q~n',[Command]), + throw(bdd_error(QueryID,Error)) + ); + true + ), + + once(my_load_allinone(OutputFilename,QueryID,Count,BDD_Probability)), + + problog_flag(retain_bdd_output,Retain_BDD_Output), + + ( + Retain_BDD_Output==true + -> + true; + delete_file_silently(OutputFilename) + ). + + +%======================================================================== +%= +%= +%= +%======================================================================== + + +my_load_allinone(File,QueryID,Count,BDD_Probability) :- + open(File,'read',Handle), + read(Handle,Atom), + once(my_load_intern_allinone(Atom,Handle,QueryID,Count,error,BDD_Probability)), + !, + close(Handle). + +my_load_allinone(File,QueryID,_,_,_,_) :- + format(user_error,'Error at ~q.~2n',[my_load(File,QueryID)]), + throw(error(my_load(File,QueryID))). + +my_load_intern_allinone(end_of_file,_,_,_,BDD_Probability,BDD_Probability) :- + !. +my_load_intern_allinone(query_probability(QueryID,Prob),Handle,QueryID,Count,Old_BDD_Probability,BDD_Probability) :- + !, + ( + Old_BDD_Probability==error + -> + true; + throw(error(bdd_output_contains_prob_twice(query_probability(QueryID,Prob)))) + ), + Prob2 is Prob, % this is will throw an exception if simplecudd delivers non-number garbage + read(Handle,X), + my_load_intern_allinone(X,Handle,QueryID,Count,Prob2,BDD_Probability). +my_load_intern_allinone(ec(QueryID,VarName,Value),Handle,QueryID,Count,Old_BDD_Probability,BDD_Probability) :- + !, + split_atom_name(VarName,FactID,_GroundID), + MultValue is Value*Count, + add_to_array_element(factprob_temp,FactID,MultValue,_NewEC), + add_to_array_element(factusage,FactID,Count,_NewDiv), + read(Handle,X), + my_load_intern_allinone(X,Handle,QueryID,Count,Old_BDD_Probability,BDD_Probability). +my_load_intern_allinone(X,Handle,QueryID,Count,Old_BDD_Probability,BDD_Probability) :- + format(user_error,'Unknown atom ~q in results file.~n',[X]), + read(Handle,X2), + my_load_intern_allinone(X2,Handle,QueryID,Count,Old_BDD_Probability,BDD_Probability). + +%======================================================================== +%= Perform one iteration of EM +%======================================================================== + +em_one_iteration :- + write_probabilities_file, + reset_static_array(factprob_temp), + reset_static_array(factusage), + + current_iteration(Iteration), + create_training_predictions_file_name(Iteration,Name), + + open(Name,'write',Handle), + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % start calculate new values + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + % process known_count information + bb_put(dummy,0.0), + ( + % go over all tunable facts and get their current probability + tunable_fact(FactID,_), + array_element(factprob,FactID,P), + % get known counts + + array_element(known_count_true_training,FactID,KK_True), + array_element(known_count_false_training,FactID,KK_False), + KK_Sum is KK_True+KK_False, + + KK_Sum>0, + + % add counts + add_to_array_element(factprob_temp,FactID,KK_True,_NewValue), + add_to_array_element(factusage,FactID,KK_Sum,_NewCount), + + % for LLH training set + + ( + KK_True>0 + -> + Part1 is KK_True*log(P); + Part1 is 0.0 + ), + ( + KK_False>0 + -> + LProb is Part1 + KK_False*log(1-P); + LProb is Part1 + ), + + bb_get(dummy,Old), + New is Old+LProb, + bb_put(dummy,New), + + fail; + true + ), + bb_delete(dummy,LLH_From_True_BDDs), + + format(Handle,'propagatedprob(~15e).~n',[LLH_From_True_BDDs]), + + training_set_cluster_list(AllCluster), + + problog_flag(parallel_processes,Parallel_Processes), + evaluate_bdds(AllCluster,Handle,Parallel_Processes,'e','.',LLH_From_True_BDDs,LLH), + + logger_set_variable(llh_training_set,LLH), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % stop calculate new values + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + format_learning(2,'~n',[]), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % start copy new values + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + problog_flag(pc_numerator,Pseudo_Counts_Numerator), + problog_flag(pc_denominator,Pseudo_Counts_Denominator), + + forall( + ( + tunable_fact(FactID,_), + array_element(factusage,FactID,Used), + Used>0 % only update relevant facts + ), + ( + array_element(factprob_temp,FactID,NewValue), + NewP is (NewValue+ Pseudo_Counts_Numerator) / (Used+Pseudo_Counts_Denominator), + update_array(factprob,FactID,NewP) + ) + ), + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % stop copy new values + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + close(Handle). + + +%======================================================================== +%= Call SimpleCUDD for each BDD Cluster script +%= L : a list containing 3-tuples a(QueryID,ClusterID,Count) +%= H : file handle for the log file +%= P : number of parallel SimpleCUDD processes +%= T : type of evaluation, either 'd' or 'e' +%= S : symbol to print after a process finished +%= OldLLH : accumulator for LLH +%= LLH : resulting LLH +%= +%= evaluate_bdds(+L,+H,+P,+T,+S,+OldLLH,-LLH) +%======================================================================== + +evaluate_bdds([],_,_,_,_,LLH,LLH). +evaluate_bdds([H|T],Handle,Parallel_Processes,Type,Symbol,OldLLH,LLH) :- + once(slice_n([H|T],Parallel_Processes,ForNow,Later)), + logger_start_timer(bdd_evaluation), + once(evaluate_bdds_start(ForNow,Type,ForNow_Jobs)), + once(evaluate_bdds_stop(ForNow_Jobs,Handle,Symbol,OldLLH,NewLLH)), + logger_stop_timer(bdd_evaluation), + evaluate_bdds(Later,Handle,Parallel_Processes,Type,Symbol,NewLLH,LLH). + +evaluate_bdds_start([],_,[]). +evaluate_bdds_start([a(QueryID,ClusterID,Count)|T],Type,[job(QueryID,ClusterID,Count,Command,PID,OutputFilename)|T2]) :- + once(update_query(QueryID,ClusterID,Type,Command,PID,OutputFilename)), + evaluate_bdds_start(T,Type,T2). +evaluate_bdds_stop([],_,_,LLH,LLH). +evaluate_bdds_stop([job(ID,ClusterID,Count,Command,PID,OutputFilename)|T],Handle,Symbol,OldLLH,LLH) :- + once(update_query_wait(ID,ClusterID,Count,Symbol,Command,PID,OutputFilename,BDD_Prob)), + format(Handle,'bdd_prob(~w,~w,~15e). % Count=~w~n',[ID,ClusterID,BDD_Prob,Count]), + catch(NewLLH is OldLLH + Count*log(BDD_Prob),_Exception,NewLLH is 0.0/0.0), + evaluate_bdds_stop(T,Handle,Symbol,NewLLH,LLH). + + +%======================================================================== +%= +%= +%======================================================================== + + + +%======================================================================== +%= initialize the logger module and set the flags for learning +%= don't change anything here! use set_learning_flag/2 instead +%======================================================================== + +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' + 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(retain_bdd_output,problog_flag_validate_boolean,'Keep output files from BDD tool',false,learning_general), + problog_define_flag(log_frequency, problog_flag_validate_posint, 'log results every nth iteration', 1, learning_general), + problog_define_flag(reuse_initialized_bdds,problog_flag_validate_boolean, 'Reuse BDDs from previous runs',false, learning_general), + problog_define_flag(pc_numerator,problog_flag_validate_in_interval_right_open([0.0,+inf]),'Add X to numerator (Pseudocounts)',0.0,learning_general), + problog_define_flag(pc_denominator,problog_flag_validate_in_interval_right_open([0.0,+inf]),'Add X to denominator (Pseudocounts)',0.0,learning_general), + problog_define_flag(parallel_processes,problog_flag_validate_posint,'Number of parallel BDD processes',8,learning_general), + + problog_define_flag(cluster_bdds,problog_flag_validate_boolean,'Cluster similar BDDs',true,learning_general). + + +init_logger :- + logger_define_variable(iteration, int), + logger_define_variable(duration,time), + + logger_define_variable(llh_training_set,float), + logger_define_variable(llh_test_set,float), + + logger_define_variable(bdd_evaluation,time), + + logger_define_variable(ground_truth_diff,float), + logger_define_variable(ground_truth_mindiff,float), + logger_define_variable(ground_truth_maxdiff,float), + + logger_define_variable(train_bdd_script_generation,time), + logger_define_variable(train_bdd_script_generation_grounding,time), + logger_define_variable(train_bdd_script_generation_completion,time), + logger_define_variable(train_bdd_script_generation_propagation,time), + logger_define_variable(train_bdd_script_generation_splitting,time), + logger_define_variable(train_bdd_script_generation_active_ground_atoms,int), + logger_define_variable(train_bdd_script_generation_propagated_ground_atoms,int), + + logger_define_variable(test_bdd_script_generation,time), + logger_define_variable(test_bdd_script_generation_grounding,time), + logger_define_variable(test_bdd_script_generation_completion,time), + logger_define_variable(test_bdd_script_generation_propagation,time), + logger_define_variable(test_bdd_script_generation_splitting,time), + logger_define_variable(test_bdd_script_generation_active_ground_atoms,int), + logger_define_variable(test_bdd_script_generation_propagated_ground_atoms,int). + +:- initialization(init_flags). +:- initialization(init_logger). diff --git a/packages/ProbLog/simplecudd/simplecudd.c b/packages/ProbLog/simplecudd/simplecudd.c index 56a76807c..33f20ae78 100644 --- a/packages/ProbLog/simplecudd/simplecudd.c +++ b/packages/ProbLog/simplecudd/simplecudd.c @@ -7,8 +7,8 @@ * * * Author: Theofrastos Mantadelis * * File: simplecudd.c * -* $Date:: 2010-12-17 12:21:58 +0100 (Fri, 17 Dec 2010) $ * -* $Revision:: 5159 $ * +* $Date:: 2011-04-11 17:23:11 +0200 (Mon, 11 Apr 2011) $ * +* $Revision:: 5920 $ * * * ******************************************************************************** * * @@ -1240,7 +1240,7 @@ DdNode* LineParser(DdManager *manager, namedvars varmap, DdNode **inter, int max iconst = 1; } else if (strcmp(term + inegvar, "FALSE") == 0) { iconst = 1; - inegvar = 1; + inegvar = !inegvar; } else { iconst = 0; ivar = AddNamedVar(varmap, term + inegvar); diff --git a/packages/ProbLog/simplecudd_lfi/Example.c b/packages/ProbLog/simplecudd_lfi/Example.c new file mode 100644 index 000000000..ad0708636 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/Example.c @@ -0,0 +1,345 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright Katholieke Universiteit Leuven 2008 * +* * +* Author: Theofrastos Mantadelis * +* File: Example.c * +* * +******************************************************************************** +* * +* 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. * +* * +* The End * +* * +\******************************************************************************/ + + +#include "simplecudd.h" + +typedef struct _extmanager { + DdManager *manager; + DdNode *t, *f; + hisqueue *his; + namedvars varmap; +} extmanager; + +void DFS(extmanager MyManager, DdNode *Current); +int compexpand(extmanager MyManager, DdNode *Current, extmanager MyManager2, DdNode *Current2); +int bufstrcat(char *targetstr, int targetmem, const char *srcstr); +void getalltruepaths(extmanager MyManager, DdNode *Current, const char *startpath, const char *prevvar); + +int main(int argc, char **arg) { + extmanager MyManager; + DdNode *bdd, **forest; + bddfileheader fileheader; + int code; + char yn; + code = -1; + if (argc != 2) { + fprintf(stderr, "\nUsage: %s [filename]\nGenerates and traverses a BDD from file\n", arg[0]); + fprintf(stderr, "\nUsage: %s -online\nGenerates and traverses a BDD online mode\n", arg[0]); + return code; + } + RAPIDLOADON; + if (strcmp("-online", arg[1]) == 0) { + MyManager.manager = simpleBDDinit(0); + MyManager.t = HIGH(MyManager.manager); + MyManager.f = LOW(MyManager.manager); + MyManager.varmap = InitNamedVars(1, 0); + bdd = OnlineGenerateBDD(MyManager.manager, &MyManager.varmap); + } else { + fileheader = ReadFileHeader(arg[1]); + switch(fileheader.filetype) { + case BDDFILE_SCRIPT: + MyManager.manager = simpleBDDinit(fileheader.varcnt); + MyManager.t = HIGH(MyManager.manager); + MyManager.f = LOW(MyManager.manager); + MyManager.varmap = InitNamedVars(fileheader.varcnt, fileheader.varstart); + if (fileheader.version > 1) { + forest = FileGenerateBDDForest(MyManager.manager, MyManager.varmap, fileheader); + bdd = forest[0]; + } else { + forest = NULL; + bdd = FileGenerateBDD(MyManager.manager, MyManager.varmap, fileheader); + } + break; + case BDDFILE_NODEDUMP: + MyManager.manager = simpleBDDinit(fileheader.varcnt); + MyManager.t = HIGH(MyManager.manager); + MyManager.f = LOW(MyManager.manager); + MyManager.varmap = InitNamedVars(fileheader.varcnt, fileheader.varstart); + bdd = LoadNodeDump(MyManager.manager, MyManager.varmap, fileheader.inputfile); + break; + default: + fprintf(stderr, "Error: not a valid file format to load.\n"); + return code; + break; + } + } + int nextbdd = 0; + while (bdd != NULL) { + printf("Do you want to load parameter values from testdata.txt [y]? "); yn = getchar(); getchar(); + if (yn == 'y') { + printf("yo\n"); + LoadVariableData(MyManager.varmap, "testdata.txt"); + printf("yo\n"); + char **a; + a = GetVariableOrder("testdata.txt", MyManager.varmap.varcnt); + int aa; + for (aa = 0; aa < MyManager.varmap.varcnt; aa++) + printf("%s\n", a[aa]); + ImposeOrder(MyManager.manager, MyManager.varmap, a); + } + + + code = 0; + MyManager.his = InitHistory(GetVarCount(MyManager.manager)); + if (strcmp("-online", arg[1]) != 0) { + DFS(MyManager, bdd); + printf("Do you need an export [y]? "); yn = getchar(); getchar(); + if (yn == 'y') simpleNamedBDDtoDot(MyManager.manager, MyManager.varmap, bdd, "SimpleCUDDExport.dot"); + printf("Do you want a save [y]? "); yn = getchar(); getchar(); + if (yn == 'y') SaveNodeDump(MyManager.manager, MyManager.varmap, bdd, "SimpleCUDDSave.sav"); + printf("Do you want to see all true paths [y]? "); yn = getchar(); getchar(); + if (yn == 'y') { + ReInitHistory(MyManager.his, GetVarCount(MyManager.manager)); + getalltruepaths(MyManager, bdd, "", ""); + } + } else { + onlinetraverse(MyManager.manager, MyManager.varmap, MyManager.his, bdd); + } + nextbdd++; + if (forest != NULL) bdd = forest[nextbdd]; else bdd = NULL; + } + if (MyManager.manager != NULL) KillBDD(MyManager.manager); + return code; +} + +void DFS(extmanager MyManager, DdNode *Current) { + DdNode *h, *l; + hisnode *Found; + char *curnode; + curnode = GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, Current); + if (GetIndex(Current) < MyManager.varmap.varcnt) { + printf("%s(%f,%i,%s)\n", curnode, MyManager.varmap.dvalue[GetIndex(Current)], MyManager.varmap.ivalue[GetIndex(Current)], (char *) MyManager.varmap.dynvalue[GetIndex(Current)]); + } else { + printf("%s\n", curnode); + } + if ((Current != MyManager.t) && (Current != MyManager.f) && + ((Found = GetNode(MyManager.his, MyManager.varmap.varstart, Current)) == NULL)) { + l = LowNodeOf(MyManager.manager, Current); + h = HighNodeOf(MyManager.manager, Current); + printf("l(%s)->", curnode); + DFS(MyManager, l); + printf("h(%s)->", curnode); + DFS(MyManager, h); + AddNode(MyManager.his, MyManager.varmap.varstart, Current, 0.0, 0, NULL); + } +} + +void getalltruepaths(extmanager MyManager, DdNode *Current, const char *startpath, const char *prevvar) { + DdNode *h, *l; + char *curnode, *curpath; + int pathmaxsize = 1024; + curpath = (char *) malloc(sizeof(char) * pathmaxsize); + curpath[0] = '\0'; + pathmaxsize = bufstrcat(curpath, pathmaxsize, startpath); + pathmaxsize = bufstrcat(curpath, pathmaxsize, prevvar); + pathmaxsize = bufstrcat(curpath, pathmaxsize, "*"); + curnode = GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, Current); + if (Current == MyManager.t) { + printf("%s\n", curpath); + } else if (Current != MyManager.f) { + h = HighNodeOf(MyManager.manager, Current); + if (h != MyManager.f) { + getalltruepaths(MyManager, h, curpath, curnode); + } + l = LowNodeOf(MyManager.manager, Current); + if (l != MyManager.f) { + pathmaxsize = bufstrcat(curpath, pathmaxsize, "~"); + getalltruepaths(MyManager, l, curpath, curnode); + } + } + free(curpath); +} + +int bufstrcat(char *targetstr, int targetmem, const char *srcstr) { + int strinc = strlen(srcstr), strsize = strlen(targetstr); + while ((strsize + strinc) > (targetmem - 1)) { + targetmem *= 2; + targetstr = (char *) realloc(targetstr, sizeof(char) * targetmem); + } + strcat(targetstr, srcstr); + return targetmem; +} diff --git a/packages/ProbLog/simplecudd_lfi/Makefile.in b/packages/ProbLog/simplecudd_lfi/Makefile.in new file mode 100644 index 000000000..9d530645a --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/Makefile.in @@ -0,0 +1,62 @@ +# +# default base directory for YAP installation +# (EROOT for architecture-dependent files) +# +prefix = @prefix@ +exec_prefix = @exec_prefix@ +ROOTDIR = $(prefix) +EROOTDIR = @exec_prefix@ +abs_top_builddir = @abs_top_builddir@ +# +# where the binary should be +# +BINDIR = $(EROOTDIR)/bin +# +# where YAP should look for libraries +# +LIBDIR=@libdir@ +YAPLIBDIR=@libdir@/Yap +# +# where YAP should look for architecture-independent Prolog libraries +# +SHAREDIR=$(ROOTDIR)/share +# +# +CC=@CC@ +# +# +# You shouldn't need to change what follows. +# +INSTALL=@INSTALL@ +INSTALL_DATA=@INSTALL_DATA@ +INSTALL_PROGRAM=@INSTALL_PROGRAM@ +SHELL=/bin/sh +RANLIB=@RANLIB@ +srcdir=@srcdir@ +SO=@SO@ +#4.1VPATH=@srcdir@:@srcdir@/OPTYap +CWD=$(PWD) +# + +DYNAMIC = +CFLAGS = @CFLAGS@ +INCLUDE = @CUDD_CPPFLAGS@ +LINKFLAGS = -lm +LINKLIBS = @CUDD_LDFLAGS@ + +default: problogbdd_lfi + +problogbdd_lfi: problogbdd_lfi.o simplecudd.o general.o problogmath.o pqueue.o allocate.o iqueue.o adterror.o allocate.o + @echo Making problogbdd_lfi... + @echo Copyright Katholieke Universiteit Leuven 2008 + @echo Authors: T. Mantadelis, A. Kimmig, B. Gutmann, I. Thon, G. Van den Broeck + $(CC) problogbdd_lfi.o simplecudd.o general.o problogmath.o pqueue.o iqueue.o adterror.o allocate.o $(LINKLIBS) $(LINKFLAGS) -o problogbdd_lfi + +%.o : $(srcdir)/%.c + $(CC) $(CFLAGS) $(INCLUDE) $(DYNAMIC) -c $< + +clean: + rm -f *.o problogbdd_lfi + +install: default + $(INSTALL_PROGRAM) problogbdd_lfi $(DESTDIR)$(SHAREDIR)/Yap diff --git a/packages/ProbLog/simplecudd_lfi/adterror.c b/packages/ProbLog/simplecudd_lfi/adterror.c new file mode 100644 index 000000000..0dbde6162 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/adterror.c @@ -0,0 +1,47 @@ +/****************************************************************** +** +** ADTERROR.C: +** +** ADT Error Handler +** +** This file is part of Apt Abstrct Data Types (ADT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +******************************************************************/ + +#include "adterror.h" +//#include "gprintf.h" + +//PUBLIC +//#ifdef __ANSI_C__ +void ADTError(char *name, ADTErrorCodes error, char *proc) +//#else +//void ADTError(name,error,proc) + //char *name; + //ADTErrorCodes error; + //char *proc; +//#endif +{ + fprintf(stderr,"ADT Error: "); + fprintf(stderr," Module: %s\n",name); + fprintf(stderr," Procedure: %s\n",proc); + fprintf(stderr," Error Code: %s\n",error); + exit(1); +} + +//PUBLIC +//#ifdef __ANSI_C__ +void ADTWarning(char *name, ADTWarningCodes warning, char *proc) +//#else +//void ADTWarning(name,warning,proc) + //char *name; + //ADTWarningCodes warning; + //char *proc; + //#endif +{ + + fprintf(stderr,"ADT Warning: "); + fprintf(stderr," Module: %s\n",name); + fprintf(stderr," Procedure: %s\n",proc); + fprintf(stderr," Warning Code: %s\n",warning); +} diff --git a/packages/ProbLog/simplecudd_lfi/adterror.h b/packages/ProbLog/simplecudd_lfi/adterror.h new file mode 100644 index 000000000..852f34326 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/adterror.h @@ -0,0 +1,75 @@ +/****************************************************************** +** +** ADTERROR.H: +** +** ADT Error Handler +** +** This file is part of Apt Abstrct Data Types (ADT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +******************************************************************/ +#ifndef ADTERROR_H +#define ADTERROR_H + +//#include "cheaders.h" +#include +#include +#include + +/* ADT Names */ + +#define ADT_AStack "Array Stack" +#define ADT_AStackIter "Array Stack Iterator" +#define ADT_Buffer "Buffer" +#define ADT_BufferIO "Buffered I/O" +#define ADT_Deque "Deque" +#define ADT_DequeIter "Deque Iterator" +#define ADT_HashTable "Hash Table" +#define ADT_HashTableIter "Hash Table Iterator" +#define ADT_Queue "Queue" +#define ADT_QueueIter "Queue Iterator" +#define ADT_Stack "Stack" +#define ADT_StackIter "Stack Iterator" +#define ADT_Table "AVL Table" +#define ADT_TableIter "AVL Table Iterator" +#define ADT_Tree "AVL Tree" +#define ADT_TreeIter "AVL Tree Iterator" + +/* ADT Error Codes */ + +typedef enum _ADTErrorCodes { + E_Allocation, + E_NullQueue, + E_NullQueueIter, + E_Seek, + E_SeekOverflow, + E_SeekUnderflow, + /* Added HashTable errors 03/22/2005 pma */ + E_NullHashTable, + E_NullHashTableIter, + /* Added AVLTable errors 04/04/2005 pma */ + E_NullAVLTable, + E_NullAVLTableIter, + + E_Undefined +} ADTErrorCodes; + +typedef enum _ADTWarningCodes { + W_Undefined +} ADTWarningCodes; + +/* ADT Error Handler */ + +#ifdef __ANSI_C__ + +void ADTError(char *name, ADTErrorCodes error, char *proc); +void ADTWarning(char *name, ADTWarningCodes warning, char *proc); + +#else + +void ADTError(); +void ADTWarning(); + +#endif + +#endif diff --git a/packages/ProbLog/simplecudd_lfi/allocate.c b/packages/ProbLog/simplecudd_lfi/allocate.c new file mode 100644 index 000000000..64d052855 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/allocate.c @@ -0,0 +1,59 @@ +/****************************************************************** +** +** ALLOCATE.C: +** +** Allocation Routines +** +** This file is part of Apt Computing Tools (ACT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +******************************************************************/ + +/* ---------- C Headers */ + +//#include "cheaders.h" + +/* ---------- Headers */ + +#include "apt.h" +#include "allocate.h" + +/* ---------- Private Globals */ + +PRIVATE int bytesAllocated = 0; + +/* ---------- Functions */ + +/* +** +** Allocate +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *Allocate(int bytes) +#else +void *Allocate(bytes) +int bytes; +#endif +{ + bytesAllocated += bytes; + return (void *)calloc(1,bytes); +} + +/* +** +** Free +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void Free(void *memory) +#else +void Free(memory) +void *memory; +#endif +{ + free(memory); +} diff --git a/packages/ProbLog/simplecudd_lfi/allocate.h b/packages/ProbLog/simplecudd_lfi/allocate.h new file mode 100644 index 000000000..56a0c7b88 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/allocate.h @@ -0,0 +1,30 @@ +/****************************************************************** +** +** ALLOCATE.H: +** +** Allocation Routines +** +** This file is part of Apt Computing Tools (ACT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +******************************************************************/ + +#ifndef ALLOCATE_H +#define ALLOCATE_H + +/* ----------- Headers */ + +#include "apt.h" + +/* ----------- Exported Function Prototypes */ + +#ifdef __ANSI_C__ +void *Allocate(int); +void Free(void*); +#else +void *Allocate(); +void Free(); +#endif /* __ANSI_C__ */ + +#endif /* ALLOCATE_H */ diff --git a/packages/ProbLog/simplecudd_lfi/apt.h b/packages/ProbLog/simplecudd_lfi/apt.h new file mode 100644 index 000000000..dfda5a561 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/apt.h @@ -0,0 +1,67 @@ +/****************************************************************** +** +** APT.H: +** +** Definitions and Types for all APT modules +** +** This file is part of Apt Computing Tools (ACT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +******************************************************************/ + +#ifndef APT_H +#define APT_H + +/* ---------- Defines */ + +#ifndef ERROR +#define ERROR -1 +#endif + +#ifndef EXTERN +#define EXTERN extern +#endif + +#ifndef FAILURE +#define FAILURE -1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef INFINITY +#define INFINITY 32768L +#endif + +#ifndef PRIVATE +#define PRIVATE static +#endif + +#ifndef PUBLIC +#define PUBLIC +#endif + +#ifndef SUCCESS +#define SUCCESS 1 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* ---------- Types */ + +#define __ANSI_C__ + +typedef void (*ApplyFunction)(void*); +typedef void (*ApplyFunction1)(void*,void*); +typedef void (*ApplyFunction2)(void*,void*,void*); +typedef void (*ApplyFunction3)(void*,void*,void*,void*); +typedef int (*ComparisonFunction)(void*, void*); +typedef void (*DisposeFunction)(void*); + +typedef void (*ApplyFunctionGeneric)(void* target, void* args[]); + +#endif /* APT_H */ diff --git a/packages/ProbLog/simplecudd_lfi/cheaders.h b/packages/ProbLog/simplecudd_lfi/cheaders.h new file mode 100644 index 000000000..e3a93e1d4 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/cheaders.h @@ -0,0 +1,50 @@ +/* + * cheaders.h : A unified headers file for APT. It does slow down compile + * time somewhat, but this allows us to ensure consistent usage + * of header files and replace missing ones easily. + */ + +#ifndef APT_CHEADERS_H +#define APT_CHEADERS_H + +#include "apt_config.h" + +#ifdef HAVE_CTYPE_H + #include +#else + #error Your C compiler is very old (ctype.h missing). Time to upgrade. Sorry +#endif + +#ifdef HAVE_STRING_H + #include +#else + #error Your C compiler is very old (string.h missing). Time to upgrade. Sorry +#endif + +#ifdef HAVE_STDIO_H + #include +#else + #error Your C compiler is very old (stdio.h missing). Time to upgrade. Sorry +#endif + +#ifdef HAVE_STDLIB_H + #include +#else + #error Your C compiler is not ANSI C (stdlib.h missing). Time to upgrade. Sorry +#endif + +#if HAVE_STDARG_H +# include +# define VA_START(a, f) va_start(a, f) +#else +# if HAVE_VARARGS_H +# include +# define VA_START(a, f) va_start(a) +# endif +#endif + +#ifndef VA_START + #error Your C compiler has no support for variable argument functions. Time to upgrade. Sorry. +#endif + +#endif diff --git a/packages/ProbLog/simplecudd_lfi/general.c b/packages/ProbLog/simplecudd_lfi/general.c new file mode 100644 index 000000000..658ad6d2c --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/general.c @@ -0,0 +1,277 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright Katholieke Universiteit Leuven 2008 * +* * +* Author: Theofrastos Mantadelis * +* File: general.c * +* * +******************************************************************************** +* * +* 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. * +* * +* The End * +* * +\******************************************************************************/ + + +#include "general.h" + +/* Number Handling */ + +int IsRealNumber(char *c) { + int i, l; + l = strlen(c); + if (l <= 0) return 0; + if (l == 1) return IsNumberDigit(c[0]); + for(i = 1; i < strlen(c); i++) { + if (c[i] == '.') return IsPosNumber(&c[i + 1]); + if (!IsNumberDigit(c[i])) return 0; + } + return (IsNumberDigit(c[0]) || IsSignDigit(c[0])); +} + +int IsPosNumber(const char *c) { + int i, l; + l = strlen(c); + if (l <= 0) return 0; + for(i = 0; i < strlen(c); i++) { + if (!IsNumberDigit(c[i])) return 0; + } + return 1; +} + +int IsNumber(const char *c) { + int i, l; + l = strlen(c); + if (l <= 0) return 0; + if (l == 1) return IsNumberDigit(c[0]); + for(i = 1; i < strlen(c); i++) { + if (!IsNumberDigit(c[i])) return 0; + } + return (IsNumberDigit(c[0]) || IsSignDigit(c[0])); +} + +/* File Handling */ + +char * freadstr(FILE *fd, const char *separators) { + char *str; + int buf, icur = 0, max = 10; + str = (char *) malloc(sizeof(char) * max); + str[0] = '\0'; + do { + if ((buf = fgetc(fd)) != EOF) { + if (icur == (max - 1)) { + max = max * 2; + str = (char *) realloc(str, sizeof(char) * max); + } + if (!CharIn((char) buf, separators)) { + str[icur] = (char) buf; + icur++; + str[icur] = '\0'; + } + } + } while(!CharIn(buf, separators) && !feof(fd)); + return str; +} + +int CharIn(const char c, const char *in) { + int i; + for (i = 0; i < strlen(in); i++) + if (c == in[i]) return 1; + return 0; +} + +/* string handling */ + +int patternmatch(char *pattern, char *thestr) { + int i, j = -1, pl = strlen(pattern), sl = strlen(thestr); + for(i = 0; i < pl; i++) { + if (pattern[i] == '*') { + do { + i++; + if (i == pl) return 1; + } while(pattern[i] == '*'); + do { + j++; + if (j >= sl) return 0; + if ((thestr[j] == pattern[i]) && patternmatch(pattern + i, thestr + j)) return 1; + } while(1); + } else { + j++; + if (j >= sl) return 0; + if (pattern[i] != thestr[j]) return 0; + } + } + return (pl == sl); +} diff --git a/packages/ProbLog/simplecudd_lfi/general.h b/packages/ProbLog/simplecudd_lfi/general.h new file mode 100644 index 000000000..618c9a92e --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/general.h @@ -0,0 +1,202 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright Katholieke Universiteit Leuven 2008 * +* * +* Author: Theofrastos Mantadelis * +* File: general.h * +* * +******************************************************************************** +* * +* 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. * +* * +* The End * +* * +\******************************************************************************/ + + +#include +#include +#include + +#define IsNumberDigit(c) ('0' <= c && c <= '9') +#define IsSignDigit(c) (c == '+' || c == '-') +#define isOperator(x) (x == '+' || x == '*' || x == '#' || x == '=') +#define freadline(fd) freadstr(fd, "\n"); + +int IsRealNumber(char *c); +int IsPosNumber(const char *c); +int IsNumber(const char *c); +char * freadstr(FILE *fd, const char *separators); +int CharIn(const char c, const char *in); +int patternmatch(char *pattern, char *thestr); diff --git a/packages/ProbLog/simplecudd_lfi/iqueue.c b/packages/ProbLog/simplecudd_lfi/iqueue.c new file mode 100644 index 000000000..e2e948c09 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/iqueue.c @@ -0,0 +1,275 @@ +/****************************************************************** +** +** IQUEUE.C: +** +** ADT Queue Iterator Implementation +** +** This file is part of Apt Abstrct Data Types (ADT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +** The concept of an iterator for an Abstract Data Type is derived +** from research on Smalltalk. +******************************************************************/ + +/* ---------- C Headers */ + +//#include "cheaders.h" + +/* ---------- Headers */ + +#include "adterror.h" +#include "allocate.h" +#include "iqueue.h" + +/* ---------- Private Function Prototypes */ + +#ifdef __ANSI_C__ +#else +#endif + +/* ---------- Functions */ + +/* +** +** QueueIteratorDispose +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueIteratorDispose(QueueIterator qi) +#else +void QueueIteratorDispose(qi) +QueueIterator qi; +#endif +{ + free(qi); +} + +/* +** +** QueueIteratorNew +** +*/ +PUBLIC +#ifdef __ANSI_C__ +QueueIterator QueueIteratorNew(Queue q, int start) +#else +QueueIterator QueueIteratorNew(q,start) +Queue q; +int start; +#endif +{ + QueueIterator qi; + + if (q) + qi = ((QueueIterator)Allocate(sizeof(_QueueIterator))); + else + ADTError(ADT_QueueIter, E_NullQueue, "QueueIteratorNew"); + if (qi) { + qi->queue = q; + QueueIteratorAbsoluteSeek(qi, start); + } else + ADTError(ADT_QueueIter, E_Allocation, "QueueIteratorNew"); + return (qi); +} + +/* +** +** QueueIteratorAtTop +** +*/ +PUBLIC +#ifdef __ANSI_C__ +int QueueIteratorAtTop(QueueIterator qi) +#else +int QueueIteratorAtTop(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorAtTop"); + return QueueIteratorAtPosition(qi,1); +} + +/* +** +** QueueIteratorAtBottom +** +*/ +PUBLIC +#ifdef __ANSI_C__ +int QueueIteratorAtBottom(QueueIterator qi) +#else +int QueueIteratorAtBottom(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorAtBottom"); + return QueueIteratorAtPosition(qi,0); +} + +/* +** +** QueueIteratorAtPosition +** +*/ +PUBLIC +#ifdef __ANSI_C__ +int QueueIteratorAtPosition(QueueIterator qi, int position) +#else +int QueueIteratorAtPosition(qi,position) +QueueIterator qi; +int position; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorAtPosition"); + if (position <= 0) + position += (QueueSize(qi->queue) + 1); + return qi->position == position; +} + +/* +** +** QueueIteratorPosition +** +*/ +PUBLIC +#ifdef __ANSI_C__ +int QueueIteratorPosition(QueueIterator qi) +#else +int QueueIteratorPosition(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorPosition"); + return qi->position; +} + +/* +** +** QueueIteratorCurrentData +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueIteratorCurrentData(QueueIterator qi) +#else +void *QueueIteratorCurrentData(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorCurrentData"); + return QueueItemElement(qi->currentItem); +} + +/* +** +** QueueIteratorPreviousData +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueIteratorPreviousData(QueueIterator qi) +#else +void *QueueIteratorPreviousData(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorPreviousData"); + return QueueItemElement(qi->previousItem); +} + +/* +** +** QueueIteratorAdvance +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueIteratorAdvance(QueueIterator qi) +#else +void QueueIteratorAdvance(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorAdvance"); + qi->previousItem = qi->currentItem; + qi->currentItem = QueueNext(qi->previousItem); + if (qi->previousItem) qi->position++; +} + +/* +** +** QueueIteratorBackup +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueIteratorBackup(QueueIterator qi) +#else +void QueueIteratorBackup(qi) +QueueIterator qi; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorBackup"); + QueueIteratorRelativeSeek(qi, -1); +} + +/* +** +** QueueIteratorAbsoluteSeek +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueIteratorAbsoluteSeek(QueueIterator qi, int position) +#else +void QueueIteratorAbsoluteSeek(qi,position) +QueueIterator qi; +int position; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorAbsoluteSeek"); + if (position <= 0) + position += (QueueSize(qi->queue) + 1); + if (position <= 0) + ADTError(ADT_QueueIter, E_Seek, "QueueIteratorAbsoluteSeek"); + /* Here, we know position is positive */ + if (position > QueueSize(qi->queue) + 1) + qi->position = QueueSize(qi->queue) + 1; + else + qi->position = position; + qi->previousItem = QueueSeek(qi->queue,position-1); + if (qi->previousItem) + qi->currentItem = QueueNext(qi->previousItem); + else + qi->currentItem = QueueSeek(qi->queue,position); +} + +/* +** +** QueueIteratorRelativeSeek +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueIteratorRelativeSeek(QueueIterator qi,int disp) +#else +void QueueIteratorRelativeSeek(qi,disp) +QueueIterator qi; +int disp; +#endif +{ + if (!qi) + ADTError(ADT_QueueIter, E_NullQueueIter, "QueueIteratorRelativeSeek"); + QueueIteratorAbsoluteSeek(qi,qi->position+disp); +} diff --git a/packages/ProbLog/simplecudd_lfi/iqueue.h b/packages/ProbLog/simplecudd_lfi/iqueue.h new file mode 100644 index 000000000..abee025ce --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/iqueue.h @@ -0,0 +1,66 @@ +/****************************************************************** +** +** IQUEUE.H: +** +** ADT Queue Iterator Implementation +** +** This file is part of Apt Abstract Data Types (ADT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +******************************************************************/ + +#ifndef IQUEUE_H +#define IQUEUE_H + +/* ---------- Headers */ + +#include "pqueue.h" + +/* ---------- Types */ + +typedef struct _QueueIterator { + int position; + Queue queue; + QueueItem currentItem, previousItem; +} _QueueIterator, *QueueIterator; + +/* ---------- Exported Function Prototypes */ + +#ifdef __ANSI_C__ +QueueIterator QueueIteratorNew(Queue,int); +void QueueIteratorDispose(QueueIterator); + +int QueueIteratorAtTop(QueueIterator); +int QueueIteratorAtBottom(QueueIterator); +int QueueIteratorAtPosition(QueueIterator,int); + +int QueueIteratorPosition(QueueIterator); +void *QueueIteratorCurrentData(QueueIterator); +void *QueueIteratorPreviousData(QueueIterator); + +void QueueIteratorAdvance(QueueIterator); +void QueueIteratorBackup(QueueIterator); +void QueueIteratorAbsoluteSeek(QueueIterator,int); +void QueueIteratorRelativeSeek(QueueIterator,int); + +#else +QueueIterator QueueIteratorNew(); +void QueueIteratorDispose(); + +int QueueIteratorAtTop(); +int QueueIteratorAtBottom(); +int QueueIteratorAtPosition(); + +int QueueIteratorPosition(); +void *QueueIteratorCurrentData(); +void *QueueIteratorPreviousData(); + +void QueueIteratorAdvance(); +void QueueIteratorBackup(); +void QueueIteratorAbsoluteSeek(); +void QueueIteratorRelativeSeek(); + +#endif /* __ANSI_C__ */ + +#endif /* QUEUE_H */ diff --git a/packages/ProbLog/simplecudd_lfi/pqueue.c b/packages/ProbLog/simplecudd_lfi/pqueue.c new file mode 100644 index 000000000..72f480c23 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/pqueue.c @@ -0,0 +1,715 @@ +/****************************************************************** +** +** QUEUE.C: +** +** ADT Queue Implementation +** +** This file is part of Apt Abstrct Data Types (ADT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +******************************************************************/ + +/* ---------- C Headers */ + +//#include "cheaders.h" + +/* ---------- Headers */ + +#include "apt.h" + +#include "allocate.h" +#include "pqueue.h" +#include +#include +#include + +/* ---------- Private Function Prototypes */ + +#ifdef __ANSI_C__ +PRIVATE void QueueDisposeItem(QueueItem, DisposeFunction); +PRIVATE QueueItem QueueGetItem(Queue); +PRIVATE QueueItem QueueNewItem(void*, int); +PRIVATE void QueuePutItem(Queue, QueueItem); +PRIVATE QueueItem QueueRemoveItem(Queue, QueueItem); +PRIVATE int QueueCompareEqual(void *, void *); +#else +PRIVATE void QueueDisposeItem(); +PRIVATE QueueItem QueueGetItem(); +PRIVATE QueueItem QueueNewItem(); +PRIVATE void QueuePutItem(); +PRIVATE QueueItem QueueRemoveItem(); +PRIVATE int QueueCompareEqual(); +#endif + +/* ---------- Functions */ + +/* +** +** QueueApply +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueApply(Queue q, ApplyFunction f) +#else +void QueueApply(q,f) +Queue q; +ApplyFunction f; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + (*f)(item->element); + } +} + +/* +** +** QueueApply1 +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueApply1(Queue q, void *p1, ApplyFunction1 f) +#else +void QueueApply1(q,p1,f) +Queue q; +void *p1; +ApplyFunction1 f; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + (*f)(item->element,p1); + } +} + +/* +** +** QueueApply2 +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueApply2(Queue q, void *p1, void *p2, ApplyFunction2 f) +#else +void QueueApply2(q,p1,p2,f) +Queue q; +void *p1; +void *p2; +ApplyFunction2 f; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + (*f)(item->element,p1,p2); + } +} + +/* +** +** QueueApply3 +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueApply3(Queue q, void *p1, void* p2, void *p3, ApplyFunction3 f) +#else +void QueueApply3(q,p1,p2,p3,f) +Queue q; +void *p1; +void *p2; +void *p3; +ApplyFunction3 f; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + (*f)(item->element,p1,p2,p3); + } +} + +/* +** +** QueueCAR +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueCAR(Queue q) +#else +void *QueueCAR(q) +Queue q; +#endif +{ + if (q != NULL && q->head != NULL) + return QueueItemElement(q->head); + return NULL; +} + +/* +** +** QueueCDR +** +*/ +PUBLIC +#ifdef __ANSI_C__ +Queue QueueCDR(Queue q) +#else +Queue QueueCDR(q) +Queue q; +#endif +{ + if (q != NULL && q->head != NULL) { + Queue new = QueueNew(); + new->head = q->head->next; + new->tail = new->head != NULL ? q->tail : NULL; + new->size = q->size-1; + return new; + } else + return NULL; +} + +/* +** +** QueueDispose +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueueDispose(Queue q, DisposeFunction f) +#else +void QueueDispose(q,f) +Queue q; +DisposeFunction f; +#endif +{ + QueueItem item; + QueueItem next = NULL; + + for (item = q->head; item != NULL; item = next) { + next = item->next; + QueueDisposeItem(item,f); + } + free(q); +} + +/* +** +** QueueDisposeItem +** +*/ +PRIVATE +#ifdef __ANSI_C__ +void QueueDisposeItem(QueueItem item, DisposeFunction f) +#else +void QueueDisposeItem(item,f) +QueueItem item; +DisposeFunction f; +#endif +{ + if (f) (*f)(item->element); + free(item); +} + +/* +** +** QueueFind +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueFind(Queue q, void *element, ComparisonFunction f) +#else +void *QueueFind(q,element,f) +Queue q; +void *element; +ComparisonFunction f; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + if ((*f)(element,item->element) == 0) break; + } + return (item != NULL ? item->element : NULL); +} + +/* +** +** QueueFindAndRemove +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueFindAndRemove(Queue q, void *element, + ComparisonFunction f) +#else +void *QueueFindAndRemove(q, element, f) +Queue q; +void *element; +ComparisonFunction f; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + if ((*f)(element,item->element) == 0) break; + } + item = QueueRemoveItem(q,item); + return (item != NULL ? item->element : NULL); +} +/* +** +** QueueFindAndRemoveType +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueFindAndRemoveType(Queue q, void *element, + ComparisonFunction f, int type) +#else +void *QueueFindAndRemoveType(q, element, f, type) +Queue q; +void *element; +ComparisonFunction f; +int type; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + if ((*f)(element,item->element) == 0 && item->type == type) break; + } + item = QueueRemoveItem(q,item); + return (item != NULL ? item->element : NULL); +} + +/* +** +** QueueFindType +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueFindType(Queue q, int type) +#else +void *QueueFindType(q,type) +Queue q; +int type; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + if (item->type == type) break; + } + return (item != NULL ? item->element : NULL); +} + +/* +** +** QueueFindTypeAndRemove +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueFindTypeAndRemove(Queue q, int type) +#else +void *QueueFindTypeAndRemove(q,type) +Queue q; +int type; +#endif +{ + QueueItem item; + + for (item = q->head; item != NULL; item = item->next) { + if (item->type == type) break; + } + return (QueueRemoveItem(q,item)); +} + +/* +** +** QueueGet +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueGet(Queue q) +#else +void *QueueGet(q) +Queue q; +#endif +{ + void *element; + QueueItem item; + + item = QueueGetItem(q); + if (item) { + element = item->element; + QueueDisposeItem(item,NULL); + } + else element = NULL; + return (element); +} + +/* +** +** QueueGetItem +** +*/ +PRIVATE +#ifdef __ANSI_C__ +QueueItem QueueGetItem(Queue q) +#else +QueueItem QueueGetItem(q) +Queue q; +#endif +{ + QueueItem item; + + if (q->head) { + item = q->head; + q->head = q->head->next; + q->size--; + } + else item = NULL; + return (item); +} + +/* +** +** QueueHead +** +*/ +PUBLIC +#ifdef __ANSI_C__ +QueueItem QueueHead(Queue q) +#else +QueueItem QueueHead(q) +Queue q; +#endif +{ + return q != NULL ? q->head : NULL; +} + +/* +** +** QueueItemElement +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueItemElement(QueueItem item) +#else +void *QueueItemElement(item) +QueueItem item; +#endif +{ + return (item->element); +} + +/* +** +** QueueItemType +** +*/ +PUBLIC +#ifdef __ANSI_C__ +int QueueItemType(QueueItem item) +#else +int QueueItemType(item) +QueueItem item; +#endif +{ + return (item->type); +} + +/* +** +** QueueLook +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void *QueueLook(Queue q) +#else +void *QueueLook(q) +Queue q; +#endif +{ + QueueItem item; + + item = q->head; + return (item != NULL ? item->element : NULL); +} + +/* +** +** QueueNew +** +*/ +PUBLIC +#ifdef __ANSI_C__ +Queue QueueNew(void) +#else +Queue QueueNew() +#endif +{ + Queue q; + + q = ((Queue)Allocate(sizeof(_Queue))); + if (q) { + q->head = q->tail = NULL; + q->size = 0; + } + return (q); +} + +/* +** +** QueueNewItem +** +*/ +PRIVATE +#ifdef __ANSI_C__ +QueueItem QueueNewItem(void *element, int type) +#else +QueueItem QueueNewItem(element,type) +void *element; +int type; +#endif +{ + QueueItem item; + + item = ((QueueItem)Allocate(sizeof(_QueueItem))); + if (item) { + item->element = element; + item->type = type; + item->next = NULL; + } + return (item); +} + +/* +** +** QueueNext +** +*/ +PUBLIC +#ifdef __ANSI_C__ +QueueItem QueueNext(QueueItem item) +#else +QueueItem QueueNext(item) +QueueItem item; +#endif +{ + return item != NULL ? item->next : NULL; +} + +/* +** +** QueuePut +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueuePut(Queue q, void *element, int type) +#else +void QueuePut(q,element,type) +Queue q; +void *element; +int type; +#endif +{ + QueueItem item; + + item = QueueNewItem(element,type); + QueuePutItem(q,item); +} + +/* +** +** QueuePutItem +** +*/ +PRIVATE +#ifdef __ANSI_C__ +void QueuePutItem(Queue q, QueueItem item) +#else +void QueuePutItem(q,item) +Queue q; +QueueItem item; +#endif +{ + if (q->head == NULL) { + q->head = q->tail = item; + } else { + q->tail->next = item; + q->tail = q->tail->next; + } + q->size++; +} + +/* +** +** QueuePutOnPriority +** +*/ +PUBLIC +#ifdef __ANSI_C__ +void QueuePutOnPriority(Queue q, void *element, int type, + ComparisonFunction f) +#else +void QueuePutOnPriority(q,element,type,f) +Queue q; +void *element; +int type; +ComparisonFunction f; +#endif +{ + QueueItem item; + item = QueueNewItem(element,type); + //fprintf(stderr,"searching for location using %p.\n",f); + if (f == NULL){ + //fprintf(stderr,"comparing function is null %f \n",f); + exit(1); + QueuePutItem(q,item); + + }else { + if (q->head == NULL) QueuePutItem(q,item); + else { + QueueItem p, lastp = NULL; + for (p = q->head; p != NULL; p = p->next) { + int cval =(*f)(element,p->element); + if (cval<0){ + // fprintf(stderr,"%i <=> %i == %i\n",*((int *) element),*((int *)(p->element)), + // cval); + break; + } + lastp = p; + } + if (p == q->head) { + item->next = q->head; + q->head = item; + } else if (p == NULL) { + q->tail->next = item; + q->tail = q->tail->next; + } else { + item->next = p; + lastp->next = item; + } + q->size++; + } + } +} + +/* +** +** QueueRemoveItem +** +*/ +PRIVATE +#ifdef __ANSI_C__ +QueueItem QueueRemoveItem(Queue q, QueueItem item) +#else +QueueItem QueueRemoveItem(q,item) +Queue q; +QueueItem item; +#endif +{ + QueueItem this, prev = NULL; + + if (q == NULL) return (NULL); + if (item == NULL) return (NULL); + this = q->head; + while (this && this != item) { + prev = this; this = this->next; + } + if (this == NULL) return (NULL); + if (this == q->head) q->head = item->next; + if (this == q->tail) q->tail = prev; + if (prev) prev->next = this->next; + q->size--; + return (item); +} + +/* +** +** QueueSeek +** +*/ +PUBLIC +#ifdef __ANSI_C__ +QueueItem QueueSeek(Queue q, int position) +#else +QueueItem QueueSeek(q,position) +Queue q; +int position; +#endif +{ + QueueItem item; +#if 0 + /* Allow single-level negative addressing of queue items */ + if (position <= 0) + position += QueueSize(q); +#endif + /* Seeks which fail will result in NULL, not error conditions */ + if (position <= 0 || position > QueueSize(q)) + return NULL; + item = QueueHead(q); + while (--position > 0) + item = QueueNext(item); + return item; +} + +/* +** +** QueueSize +** +*/ +PUBLIC +#ifdef __ANSI_C__ +int QueueSize(Queue q) +#else +int QueueSize(q) +Queue q; +#endif +{ + return q != NULL ? q->size : 0; +} + +/* +** +** QueueTail +** +*/ +PUBLIC +#ifdef __ANSI_C__ +QueueItem QueueTail(Queue q) +#else +QueueItem QueueTail(q) +Queue q; +#endif +{ + return q != NULL ? q->tail : NULL; +} + +PRIVATE +#ifdef __ANSI_C__ +int QueueCompareEqual(void *x, void *y) +#else +int QueueCompareEqual(x,y) +void *x, *y; +#endif +{ + return 0; +} + + diff --git a/packages/ProbLog/simplecudd_lfi/pqueue.h b/packages/ProbLog/simplecudd_lfi/pqueue.h new file mode 100644 index 000000000..2bda94fbe --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/pqueue.h @@ -0,0 +1,94 @@ +/****************************************************************** +** +** QUEUE.H: +** +** ADT Queue Implementation +** +** This file is part of Apt Abstract Data Types (ADT) +** Copyright (c) 1991 -- Apt Technologies +** All rights reserved +** +******************************************************************/ +//http://www.koders.com/c/fid7B82D8DDECE4EDC672F17D970458033C4079A615.aspx?s=queue + +/* +** This ADT, originally written in 1989, provides a general queue +** implementation--in C--which is the equivalent of the Java Vector. +*/ + +#ifndef QUEUE_H +#define QUEUE_H + +/* ---------- Headers */ + +#include "apt.h" + +/* ---------- Types */ + +typedef struct _QueueItem { + void *element; + int type; + struct _QueueItem *next; +} _QueueItem, *QueueItem; + +typedef struct _Queue { + struct _QueueItem *head; + struct _QueueItem *tail; + int size; +} _Queue, *Queue; + +/* ---------- Exported Function Prototypes */ + +#ifdef __ANSI_C__ +void QueueApply(Queue, ApplyFunction); +void QueueApply1(Queue, void*, ApplyFunction1); +void QueueApply2(Queue, void*, void*, ApplyFunction2); +void QueueApply3(Queue, void*, void*, void*, ApplyFunction3); +void *QueueCAR(Queue); +Queue QueueCDR(Queue); +void QueueDispose(Queue, DisposeFunction); +void *QueueFind(Queue, void*, ComparisonFunction); +void *QueueFindAndRemove(Queue, void*, ComparisonFunction); +void *QueueFindAndRemoveType(Queue, void*, ComparisonFunction, int); +void *QueueFindType(Queue, int); +void *QueueFindTypeAndRemove(Queue, int); +void *QueueGet(Queue); +QueueItem QueueHead(Queue); +void *QueueItemElement(QueueItem); +int QueueItemType(QueueItem); +void *QueueLook(Queue); +Queue QueueNew(void); +QueueItem QueueNext(QueueItem); +void QueuePut(Queue, void*, int); +void QueuePutOnPriority(Queue, void*, int, ComparisonFunction); +QueueItem QueueSeek(Queue,int); +int QueueSize(Queue); +QueueItem QueueTail(Queue); +#else +void QueueApply(); +void QueueApply1(); +void QueueApply2(); +void QueueApply3(); +void *QueueCAR(); +Queue QueueCDR(); +void QueueDispose(); +void *QueueFind(); +void *QueueFindAndRemove(); +void *QueueFindAndRemoveType(); +void *QueueFindType(); +void *QueueFindTypeAndRemove(); +void *QueueGet(); +QueueItem QueueHead(); +void *QueueItemElement(); +int QueueItemType(); +void *QueueLook(); +Queue QueueNew(); +QueueItem QueueNext(); +void QueuePut(); +void QueuePutOnPriority(); +QueueItem QueueSeek(); +int QueueSize(); +QueueItem QueueTail(); +#endif /* __ANSI_C__ */ + +#endif /* QUEUE_H */ diff --git a/packages/ProbLog/simplecudd_lfi/problogbdd_lfi.c b/packages/ProbLog/simplecudd_lfi/problogbdd_lfi.c new file mode 100644 index 000000000..a7fdd83e1 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/problogbdd_lfi.c @@ -0,0 +1,1172 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright Katholieke Universiteit Leuven 2008 * +* * +* Author: Theofrastos Mantadelis, Angelika Kimmig, Bernd Gutmann * +* File: ProblogBDD.c * +* * +******************************************************************************** +* * +* 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. * +* * +* The End * +* * +\******************************************************************************/ + +#include "simplecudd.h" +#include "problogmath.h" +#include "pqueue.h" +#include "iqueue.h" +#include +#include +#define VERSION "2.0.0" + +typedef struct _parameters { + int loadfile; + int savedfile; + int exportfile; + int inputfile; + int debug; + int errorcnt; + int *error; + int method; + int queryid; + int timeout; + double sigmoid_slope; + int online; + int maxbufsize; + char *ppid; + int orderfile; +} parameters; + +typedef struct _gradientpair { + double probability; + double gradient; +} gradientpair; + +typedef struct _extmanager { + DdManager *manager; + DdNode *t, *f; + hisqueue *his; + namedvars varmap; +} extmanager; + +int argtype(const char *arg); +void printhelp(int argc, char **arg); +parameters loadparam(int argc, char **arg); +parameters params; + +void handler(int num); +void pidhandler(int num); +void termhandler(int num); + +void myexpand(extmanager MyManager, DdNode *Current); +double CalcProbability(extmanager MyManager, DdNode *Current); +double CalcProbabilitySigmoid(extmanager MyManager, DdNode *Current); +gradientpair CalcGradient(extmanager MyManager, DdNode *Current, int TargetVar, char *TargetPattern, int type); +double CalcExpectedCountsUp(extmanager * MyManager, DdNode *Current, char *query_id) ; +double CalcExpectedCountsDown(extmanager * MyManager, DdNode *Current, char *query_id); +double CalcExpectedCounts(extmanager * MyManager, DdNode *Current, char *query_id, int calcdown_needed); +int patterncalculated(char *pattern, extmanager MyManager, int loc); +char * extractpattern(char *thestr); + +int main(int argc, char **arg) { + extmanager MyManager; + DdNode *bdd, **forest, *bakbdd; + bddfileheader fileheader; + int i, ivarcnt, code, curbdd; + gradientpair tvalue; + double probability = -1.0; + char *varpattern; + varpattern = NULL; + code = -1; + params = loadparam(argc, arg); + + if (params.errorcnt > 0) { + printhelp(argc, arg); + for (i = 0; i < params.errorcnt; i++) { + fprintf(stderr, "Error: not known or error at parameter %s.\n", arg[params.error[i]]); + } + return -1; + } + + if (params.online == 0 && params.loadfile == -1) { + printhelp(argc, arg); + fprintf(stderr, "Error: you must specify a loading file.\n"); + return -1; + } + + if (params.method != 0 && arg[params.method][0] != 'g' && arg[params.method][0] != 'p' && arg[params.method][0] != 'o' && arg[params.method][0] != 'l' && arg[params.method][0] != 'e' && arg[params.method][0] != 'd') { + printhelp(argc, arg); + fprintf(stderr, "Error: you must choose a calculation method beetween [p]robability, [g]radient, [l]ine search, [o]nline, [e]xpected counts, probability with [d]eterministic nodes.\n"); + return -1; + } + + if (params.method != 0 && (arg[params.method][0] == 'g' || arg[params.method][0] == 'p' || arg[params.method][0] == 'l'|| arg[params.method][0] == 'e'|| arg[params.method][0] == 'd') && params.inputfile == -1) { + printhelp(argc, arg); + fprintf(stderr, "Error: an input file is necessary for probability, gradient, line search calculation or expected counts methods.\n"); + return -1; + } + + if (params.debug) DEBUGON; + RAPIDLOADON; + SETMAXBUFSIZE(params.maxbufsize); + + signal(SIGINT, termhandler); + if (params.ppid != NULL) { + signal(SIGALRM, pidhandler); + alarm(5); + } else { + signal(SIGALRM, handler); + alarm(params.timeout); + } + + if (params.online) { + MyManager.manager = simpleBDDinit(0); + MyManager.t = HIGH(MyManager.manager); + MyManager.f = LOW(MyManager.manager); + MyManager.varmap = InitNamedVars(1, 0); + bdd = OnlineGenerateBDD(MyManager.manager, &MyManager.varmap); + ivarcnt = GetVarCount(MyManager.manager); + } else { + //fprintf(stderr,"reading file \n"); + fileheader = ReadFileHeader(arg[params.loadfile]); + switch(fileheader.filetype) { + case BDDFILE_SCRIPT: + // fprintf(stderr," ..... %i \n",fileheader.varcnt); + MyManager.manager = simpleBDDinit(fileheader.varcnt); + MyManager.t = HIGH(MyManager.manager); + MyManager.f = LOW(MyManager.manager); + MyManager.varmap = InitNamedVars(fileheader.varcnt, fileheader.varstart); + if (fileheader.version > 1) { + forest = FileGenerateBDDForest(MyManager.manager, MyManager.varmap, fileheader); + bdd = forest[0]; + bakbdd = bdd; + } else { + forest = NULL; + bdd = FileGenerateBDD(MyManager.manager, MyManager.varmap, fileheader); + bakbdd = bdd; + } + ivarcnt = fileheader.varcnt; + break; + case BDDFILE_NODEDUMP: + MyManager.manager = simpleBDDinit(fileheader.varcnt); + MyManager.t = HIGH(MyManager.manager); + MyManager.f = LOW(MyManager.manager); + MyManager.varmap = InitNamedVars(fileheader.varcnt, fileheader.varstart); + bdd = LoadNodeDump(MyManager.manager, MyManager.varmap, fileheader.inputfile); + ivarcnt = fileheader.varcnt; + break; + default: + fprintf(stderr, "Error: not a valid file format to load.\n"); + return -1; + break; + } + // fprintf(stderr,"bdd built\n"); + } + + + alarm(0); + + // problem specifics + + if (bdd != NULL) { + ivarcnt = RepairVarcnt(&MyManager.varmap); + code = 0; + if (params.inputfile != -1) { + if (LoadVariableData(MyManager.varmap, arg[params.inputfile]) == -1) return -1; + // if (!all_loaded(MyManager.varmap, 1)) return -1; + all_loaded_for_deterministic_variables(MyManager.varmap, 1); + } + // impose a predifined order good for debugging + // can be used with a partial number of variables to impose ordering at beggining of BDD + if (params.orderfile != -1) { + ImposeOrder(MyManager.manager, MyManager.varmap, GetVariableOrder(arg[params.orderfile], MyManager.varmap.varcnt)); + } + curbdd = 0; + do { + MyManager.his = InitHistory(ivarcnt); + if (params.method != 0) { + switch(arg[params.method][0]) { + case 'g': + for (i = 0; i < MyManager.varmap.varcnt; i++) { + if (MyManager.varmap.vars[i] != NULL) { + + // check whether this is a continues fact + if (MyManager.varmap.dynvalue[i] == NULL) { // nope, regular fact + varpattern = extractpattern(MyManager.varmap.vars[i]); + if ((varpattern == NULL) || (!patterncalculated(varpattern, MyManager, i))) { + tvalue = CalcGradient(MyManager, bdd, i + MyManager.varmap.varstart, varpattern, 0); + probability = tvalue.probability; + if (varpattern == NULL) { + printf("query_gradient(%s,%s,p,%e).\n", arg[params.queryid], MyManager.varmap.vars[i], tvalue.gradient); + } else { + varpattern[strlen(varpattern) - 2] = '\0'; + printf("query_gradient(%s,%s,p,%e).\n", arg[params.queryid], varpattern, tvalue.gradient); + } + ReInitHistory(MyManager.his, MyManager.varmap.varcnt); + if (varpattern != NULL) free(varpattern); + } + } else { // it is! let's do the Hybrid Problog Magic + // first for mu + varpattern = extractpattern(MyManager.varmap.vars[i]); + if ((varpattern == NULL) || (!patterncalculated(varpattern, MyManager, i))) { + tvalue = CalcGradient(MyManager, bdd, i + MyManager.varmap.varstart, varpattern, 1); + probability = tvalue.probability; + if (varpattern == NULL) { + printf("query_gradient(%s,%s,mu,%e).\n", arg[params.queryid], MyManager.varmap.vars[i], tvalue.gradient); + } else { + varpattern[strlen(varpattern) - 2] = '\0'; + printf("query_gradient(%s,%s,mu,%e).\n", arg[params.queryid], varpattern, tvalue.gradient); + } + } + ReInitHistory(MyManager.his, MyManager.varmap.varcnt); + if (varpattern != NULL) free(varpattern); + + // then for sigma + varpattern = extractpattern(MyManager.varmap.vars[i]); + if ((varpattern == NULL) || (!patterncalculated(varpattern, MyManager, i))) { + tvalue = CalcGradient(MyManager, bdd, i + MyManager.varmap.varstart, varpattern, 2); + probability = tvalue.probability; + if (varpattern == NULL) { + printf("query_gradient(%s,%s,sigma,%e).\n", arg[params.queryid], MyManager.varmap.vars[i], tvalue.gradient); + } else { + varpattern[strlen(varpattern) - 2] = '\0'; + printf("query_gradient(%s,%s,sigma,%e).\n", arg[params.queryid], varpattern, tvalue.gradient); + } + } + ReInitHistory(MyManager.his, MyManager.varmap.varcnt); + if (varpattern != NULL) free(varpattern); + } + + } else { + fprintf(stderr, "Error: no variable name given for parameter.\n"); + } + } + if (probability < 0.0) { + // no nodes, so we have to calculate probability ourself + tvalue = CalcGradient(MyManager, bdd, 0 + MyManager.varmap.varstart, NULL, 0); + probability = tvalue.probability; + } + printf("query_probability(%s,%e).\n", arg[params.queryid], probability); + break; + case 'l': + tvalue = CalcGradient(MyManager, bdd, 0 + MyManager.varmap.varstart, NULL, 0); + probability = tvalue.probability; + printf("query_probability(%s,%e).\n", arg[params.queryid], probability); + break; + case 'e': + //fprintf(stderr,"start calc exp count\n"); + printf("query_probability(%s,%30.30e).\n", arg[params.queryid],CalcExpectedCounts(&MyManager, bdd,arg[params.queryid],1)); + break; + case 'd': + //fprintf(stderr,"start calc exp count\n"); + printf("query_probability(%s,%30.30e).\n", arg[params.queryid],CalcExpectedCounts(&MyManager, bdd,arg[params.queryid],0)); + break; + case 'p': + printf("query_probability(%s,%e).\n", arg[params.queryid], CalcProbability(MyManager, bdd)); + break; + case 'o': + onlinetraverse(MyManager.manager, MyManager.varmap, MyManager.his, bdd); + break; + default: + myexpand(MyManager, bdd); + break; + } + } else { + myexpand(MyManager, bdd); + } + if (forest != NULL) { + curbdd++; + bdd = forest[curbdd]; + } else { + bdd = NULL; + } + ReInitHistory(MyManager.his, MyManager.varmap.varcnt); + } while(bdd != NULL); + bdd = bakbdd; + if (params.savedfile > -1) SaveNodeDump(MyManager.manager, MyManager.varmap, bdd, arg[params.savedfile]); + if (params.exportfile > -1) simpleNamedBDDtoDot(MyManager.manager, MyManager.varmap, bdd, arg[params.exportfile]); + free(MyManager.his); + } + if (MyManager.manager != NULL) { + KillBDD(MyManager.manager); + free(MyManager.varmap.dvalue); + free(MyManager.varmap.ivalue); + if (MyManager.varmap.dynvalue != NULL) { + for(i = 0; i < MyManager.varmap.varcnt; i++) + if (MyManager.varmap.dynvalue[i] != NULL) { + free(MyManager.varmap.dynvalue[i]); + } + free(MyManager.varmap.dynvalue); + } + for (i = 0; i < MyManager.varmap.varcnt; i++) + free(MyManager.varmap.vars[i]); + free(MyManager.varmap.vars); + } + if (params.error != NULL) free(params.error); + + return code; + +} + +/* Shell Parameters handling */ + +int argtype(const char *arg) { + if (strcmp(arg, "-l") == 0 || strcmp(arg, "--load") == 0) return 0; + if (strcmp(arg, "-e") == 0 || strcmp(arg, "--export") == 0) return 2; + if (strcmp(arg, "-m") == 0 || strcmp(arg, "--method") == 0) return 3; + if (strcmp(arg, "-i") == 0 || strcmp(arg, "--input") == 0) return 4; + if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) return 5; + if (strcmp(arg, "-d") == 0 || strcmp(arg, "--debug") == 0) return 6; + if (strcmp(arg, "-id") == 0 || strcmp(arg, "--queryid") == 0) return 7; + if (strcmp(arg, "-t") == 0 || strcmp(arg, "--timeout") == 0) return 8; + if (strcmp(arg, "-sd") == 0 || strcmp(arg, "--savedump") == 0) return 9; + if (strcmp(arg, "-sl") == 0 || strcmp(arg, "--slope") == 0) return 10; + if (strcmp(arg, "-o") == 0 || strcmp(arg, "--online") == 0) return 11; + if (strcmp(arg, "-bs") == 0 || strcmp(arg, "--bufsize") == 0) return 12; + if (strcmp(arg, "-pid") == 0 || strcmp(arg, "--pid") == 0) return 13; + if (strcmp(arg, "-ord") == 0 || strcmp(arg, "--order") == 0) return 14; + + return -1; +} + +void printhelp(int argc, char **arg) { + fprintf(stderr, "\n\nProbLogBDD Tool Version: %s\n\n", VERSION); + fprintf(stderr, "SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html)\n"); + fprintf(stderr, "SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be)\n"); + fprintf(stderr, "Copyright Katholieke Universiteit Leuven 2008\n"); + fprintf(stderr, "Authors: Theofrastos Mantadelis, Angelika Kimmig, Bernd Gutmann\n"); + fprintf(stderr, "This package falls under the: Artistic License 2.0\n"); + fprintf(stderr, "\nUsage: %s -l [filename] -i [filename] -o (-s(d) [filename] -e [filename] -m [method] -id [queryid] -sl [double]) (-t [seconds] -d -h)\n", arg[0]); + fprintf(stderr, "Generates and traverses a BDD\nMandatory parameters:\n"); + fprintf(stderr, "\t-l [filename]\t->\tfilename to load supports two formats:\n\t\t\t\t\t\t1. script with generation instructions\n\t\t\t\t\t\t2. node dump saved file\n"); + fprintf(stderr, "\t-i [filename]\t->\tfilename to input problem specifics (mandatory with file formats 1, 2)\n"); + fprintf(stderr, "\t-o\t\t->\tgenerates the BDD in online mode instead from a file can be used instead of -l\n"); + fprintf(stderr, "Optional parameters:\n"); + fprintf(stderr, "\t-sd [filename]\t->\tfilename to save generated BDD in node dump format (fast loading, traverse valid only)\n"); + fprintf(stderr, "\t-e [filename]\t->\tfilename to export generated BDD in dot format\n"); + fprintf(stderr, "\t-m [method]\t->\tthe calculation method to be used: none(default), [p]robability, [g]radient, [l]ine search, [o]nline, [e]xpexted counts, prob. with [d]eterministic nodes\n"); + fprintf(stderr, "\t-id [queryid]\t->\tthe queries identity name (used by gradient) default: %s\n", arg[0]); + fprintf(stderr, "\t-sl [double]\t->\tthe sigmoid slope (used by gradient) default: 1.0\n"); + fprintf(stderr, "Extra parameters:\n"); + fprintf(stderr, "\t-t [seconds]\t->\tthe seconds (int) for BDD generation timeout default 0 = no timeout\n"); + fprintf(stderr, "\t-pid [pid]\t->\ta process id (int) to check for termination default 0 = no process to check\n"); + fprintf(stderr, "\t-bs [bytes]\t->\tthe bytes (int) to use as a maximum buffer size to read files default 0 = no max\n"); + fprintf(stderr, "\t-ord [filename]\t->\tUse the [filename] to define a specific BDD variable order\n"); + fprintf(stderr, "\t-d\t\t->\tRun in debug mode (gives extra messages in stderr)\n"); + fprintf(stderr, "\t-h\t\t->\tHelp (displays this message)\n"); + fprintf(stderr, "Extra notes:\nSupports a forest of BDDs in one shared BDD.\nSelected computational methods will be applied to each BDD seperately.\nFile operations will be applied only to the first BDD.\n"); + fprintf(stderr, "\nExample: %s -l testbdd -i input.txt -m g -id testbdd\n", arg[0]); +} + +parameters loadparam(int argc, char **arg) { + int i; + parameters params; + params.loadfile = -1; + params.savedfile = -1; + params.exportfile = -1; + params.method = 0; + params.inputfile = -1; + params.debug = 0; + params.errorcnt = 0; + params.queryid = 0; + params.timeout = 0; + params.sigmoid_slope = 1.0; + params.online = 0; + params.maxbufsize = 0; + params.ppid = NULL; + params.orderfile = -1; + params.error = (int *) malloc(argc * sizeof(int)); + for (i = 1; i < argc; i++) { + switch(argtype(arg[i])) { + case 0: + if (argc > i + 1) { + i++; + params.loadfile = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 2: + if (argc > i + 1) { + i++; + params.exportfile = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 3: + if (argc > i + 1) { + i++; + params.method = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 4: + if (argc > i + 1) { + i++; + params.inputfile = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 5: + printhelp(argc, arg); + break; + case 6: + params.debug = 1; + break; + case 7: + if (argc > i + 1) { + i++; + params.queryid = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 8: + if ((argc > i + 1) && (IsPosNumber(arg[i + 1]))) { + i++; + params.timeout = atoi(arg[i]); + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 9: + if (argc > i + 1) { + i++; + params.savedfile = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 10: + if ((argc > i + 1) && (IsRealNumber(arg[i + 1]))) { + i++; + params.sigmoid_slope = atof(arg[i]); + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 11: + params.online = 1; + break; + case 12: + if ((argc > i + 1) && (IsPosNumber(arg[i + 1]))) { + i++; + params.maxbufsize = atoi(arg[i]); + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 13: + if ((argc > i + 1) && (IsPosNumber(arg[i + 1]))) { + i++; + params.ppid = (char *) malloc(sizeof(char) * (strlen(arg[i]) + 1)); + strcpy(params.ppid, arg[i]); + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + case 14: + if (argc > i + 1) { + i++; + params.orderfile = i; + } else { + params.error[params.errorcnt] = i; + params.errorcnt++; + } + break; + default: + params.error[params.errorcnt] = i; + params.errorcnt++; + break; + } + } + return params; +} + +/* Error Handlers */ + +void handler(int num) { + fprintf(stderr, "Error: Timeout %i exceeded.\n", params.timeout); + exit(-1); +} + +void pidhandler(int num) { + char *s; + if (params.timeout > 0) { + params.timeout -= 5; + if (params.timeout <= 0) { + fprintf(stderr, "Error: Timeout exceeded.\n"); + exit(-1); + } + } + s = (char *) malloc(sizeof(char) * (19 + strlen(params.ppid))); + strcpy(s, "ps "); strcat(s, params.ppid); strcat(s, " >/dev/null"); + if (system(s) != 0) exit(4); + signal(SIGALRM, pidhandler); + alarm(5); + free(s); +} + +void termhandler(int num) { + exit(3); +} + +/* Debugging traverse function */ + +void myexpand(extmanager MyManager, DdNode *Current) { + DdNode *h, *l; + hisnode *Found; + char *curnode; + curnode = GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, Current); + printf("%s\n", curnode); + if ((Current != MyManager.t) && (Current != MyManager.f) && + ((Found = GetNode(MyManager.his, MyManager.varmap.varstart, Current)) == NULL)) { + l = LowNodeOf(MyManager.manager, Current); + h = HighNodeOf(MyManager.manager, Current); + printf("l(%s)->", curnode); + myexpand(MyManager, l); + printf("h(%s)->", curnode); + myexpand(MyManager, h); + AddNode(MyManager.his, MyManager.varmap.varstart, Current, 0.0, 0, NULL); + } +} + +/* Angelicas Algorithm */ + +double CalcProbability(extmanager MyManager, DdNode *Current) { + DdNode *h, *l; + hisnode *Found; + char *curnode, *dynvalue; + double lvalue, hvalue, tvalue; + density_integral dynvalue_parsed; + if (params.debug) { + curnode = GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, Current); + fprintf(stderr, "%s\n", curnode); + } + if (Current == MyManager.t) return 1.0; + if (Current == MyManager.f) return 0.0; + + if ((Found = GetNode(MyManager.his, MyManager.varmap.varstart, Current)) != NULL) return Found->dvalue; + l = LowNodeOf(MyManager.manager, Current); + h = HighNodeOf(MyManager.manager, Current); + if (params.debug) fprintf(stderr, "l(%s)->", curnode); + lvalue = CalcProbability(MyManager, l); + if (params.debug) fprintf(stderr, "h(%s)->", curnode); + hvalue = CalcProbability(MyManager, h); + + + tvalue = MyManager.varmap.dvalue[GetIndex(Current) - MyManager.varmap.varstart]; + + tvalue = tvalue * hvalue + lvalue * (1.0 - tvalue); + AddNode(MyManager.his, MyManager.varmap.varstart, Current, tvalue, 0, NULL); + return tvalue; +} + + +double CalcExpectedCounts(extmanager * MyManager, DdNode *Current, char *query_id, int calcdown_needed) { + + // fprintf(stderr,"%%calcing up\n"); + double ret = CalcExpectedCountsUp(MyManager, Current, query_id); + // fprintf(stderr,"%%result is %e\n",ret); + // fprintf(stderr,"%%calcing down\n"); + + if (calcdown_needed != 0) { + double retd=CalcExpectedCountsDown(MyManager,Current, query_id); + } +/* if(1 != retd){ */ +/* fprintf(stderr,"down %e != up %e/%e\n",ret,retd,ret); */ +/* exit(1); */ +/* } */ + return ret; +} + + +/* ComparisonFunction compare_nodes ( extmanager MyManager) */ +/* { */ +/* //fprintf(stderr,"creating comparator for %p\n",MyManager); */ + +/* int comparator(void *av, void *bv){ */ +/* fprintf(stderr,"========================> %p \n",MyManager); */ +/* fprintf(stderr,"xxxxx \n"); */ +/* DdNode* a = (DdNode*)av; */ +/* DdNode* b = (DdNode*)bv; */ +/* extmanager MyManager; */ +/* int aindex,bindex, aperm, bperm; */ +/* aindex=GetIndex(a); */ +/* bindex=GetIndex(b); */ +/* aperm=Cudd_IsConstant(a) ? CUDD_CONST_INDEX : Cudd_ReadPerm(MyManager.manager,aindex); */ +/* Cudd_ReadPerm(MyManager.manager,bindex); */ +/* bperm=Cudd_IsConstant(b) ? CUDD_CONST_INDEX : Cudd_ReadPerm(MyManager.manager,bindex); */ +/* int temp = aperm-bperm; */ +/* //-Cudd_ReadPerm(MyManager.manager,(*b).index);//-Cudd_ReadPerm(MyManager,b);// - Cudd_ReadPerm(b); */ +/* //fprintf(stderr,"comparing3 %p %p %p\n",a,b,MyManager); */ +/* // return -1; */ +/* if (temp < 0) */ +/* return 1; */ +/* else if (temp > 0) */ +/* return -1; */ +/* // else //never return zero otherwise one is pruned away, or(?) */ +/* // return 0; */ +/* } */ + +/* // return (acurrentItem != NULL) { + DdNode* val = (DdNode*) qiter->currentItem->element; + QueueIteratorAdvance(qiter); + fprintf(stderr," %s %s", GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, val), + (qiter->currentItem !=NULL)?",":"]\n"); + } + +} + /** also nesting in CalcExpected seems to not work (must be here nested only valid within function frame)*/ +/* will be changed at later stage */ +static extmanager * ineedtostorethatsomehow; +int comparator(void *av, void *bv){ + int ret; + DdNode* a = (DdNode*)av; + DdNode* b = (DdNode*)bv; + int aindex,bindex, aperm, bperm; + aindex=GetIndex(a); + bindex=GetIndex(b); + aperm=Cudd_IsConstant(a) ? CUDD_CONST_INDEX : Cudd_ReadPerm(ineedtostorethatsomehow->manager,aindex); + Cudd_ReadPerm(ineedtostorethatsomehow->manager,bindex); + bperm=Cudd_IsConstant(b) ? CUDD_CONST_INDEX : Cudd_ReadPerm(ineedtostorethatsomehow->manager,bindex); + int temp = -aperm+bperm; + if (temp < 0) + ret= 1; + else if (temp > 0) + ret= -1; + // else //never return zero otherwise one is pruned away, or(?) + // return 0; + if(LOG_EXPECTED){ + fprintf(stderr,"perm(%s,%i)=%i perm(%s,%i)=%i => %i\n",GetNodeVarNameDisp(ineedtostorethatsomehow->manager, ineedtostorethatsomehow->varmap, a), + aindex, + aperm, + GetNodeVarNameDisp(ineedtostorethatsomehow->manager, ineedtostorethatsomehow->varmap, b), + bindex,bperm, + ret);} + + return ret; +} + +/** output information for skipped nodes **/ +skip_nodes(extmanager * MyManager, double (*counts)[] , DdNode* node, DdNode* l,double dprob, char *query_id){ + int skipcnt; + skipcnt = Cudd_ReadPerm(MyManager->manager,GetIndex(node))+1; + if(LOG_EXPECTED){fprintf(stderr,">> skipper >> %s=%i@%i of %i -> %i@%i %i\n", + MyManager->varmap.dynvalue[GetIndex(node) - MyManager->varmap.varstart], + GetIndex(node), + Cudd_ReadPerm(MyManager->manager,GetIndex(node)), + Cudd_ReadSize( MyManager->manager), + GetIndex(l), + Cudd_ReadPerm(MyManager->manager,GetIndex(l)), + Cudd_IsConstant(l) + ); + } + return skip_nodes_cnt( MyManager, counts, skipcnt, l, dprob, query_id); + +} +skip_nodes_cnt(extmanager * MyManager, double (*counts)[] , int skipcnt, DdNode* l,double dprob, char *query_id){ + if(LOG_EXPECTED) fprintf(stderr,"====================\n"); + double p; + int ivalue; + // fprintf(stderr, " skip (:%i) \n",__LINE__); + while(Cudd_IsConstant(l) ? + skipcnt < Cudd_ReadSize( MyManager->manager) // the terminals/leafs/constants will be ignored + : + skipcnt < Cudd_ReadPerm(MyManager->manager,GetIndex(l) ) + ){ + skipcnt++; + if(LOG_EXPECTED){ fprintf(stderr,"skipcnt %i\n",skipcnt-1);} + int idx=Cudd_ReadInvPerm(MyManager->manager,skipcnt-1); + if(LOG_EXPECTED){fprintf(stderr,"index %i %i\n",idx,MyManager->varmap.varstart);} + //fprintf(stdout,"%i %s.\n",skipcnt,MyManager->varmap.dynvalue[GetIndex(node) - MyManager->varmap.varstart]); + if(LOG_EXPECTED){fprintf(stderr,"Node skipped level %i index: %i name: %s (dprob is %e)\n", + skipcnt,idx, + MyManager->varmap.vars[idx - MyManager->varmap.varstart], + dprob);} + //notiz + ivalue = MyManager->varmap.ivalue[idx - MyManager->varmap.varstart]; + //+ new{ + //double tvalue; // probability of prob fact corresp to node + //tvalue = MyManager->varmap.dvalue[idx - MyManager->varmap.varstart]; + //} + if(ivalue==1){ + p=dprob*MyManager->varmap.dvalue[idx - MyManager->varmap.varstart]; + //+ new{ + //p=dprob*MyManager->varmap.dvalue[idx - MyManager->varmap.varstart] *tvalue; + //} + if(p>0){// probability is zero, don't follow this branch + (*counts)[idx - MyManager->varmap.varstart]+=p; + // fprintf(stdout,"oec(%s,%s,%e). %%2\n",query_id,MyManager->varmap.vars[idx - MyManager->varmap.varstart],p); + if(LOG_EXPECTED) fprintf(stderr,"ec -> %s,%s,%e . %%2_1\n",query_id,MyManager->varmap.vars[idx - MyManager->varmap.varstart],p); + }else{ + if(LOG_EXPECTED){fprintf(stdout,"%% ec(%s,%s,%30.30e). %%2_2\n",query_id,MyManager->varmap.vars[idx - MyManager->varmap.varstart],p);} + } + } + } + // fprintf(stderr, " skip %i \n",__LINE__); + if(LOG_EXPECTED){fprintf(stderr,"skipped\n");} +} + + +double CalcExpectedCountsDown(extmanager * MyManager, DdNode *Current, char *query_id) { + ineedtostorethatsomehow=MyManager; + Queue q = QueueNew(); + //fprintf(stderr", =====> queue is: %p \n",q); + int i; + char *curnode, *curh, *curl,*dynvalue; + DdNode *h, *l, *node; + ComparisonFunction fun; + hisnode *Found,*lfound, *hfound; + double dprob; //downward probability of current node + double tvalue; // probability of prob fact corresp to node + int ivalue; + double retval; //last value of true + + double counts[MyManager->varmap.varcnt] ; + double (*pcnt)[MyManager->varmap.varcnt]; + pcnt = &counts; + for( i = 0 ;i< MyManager->varmap.varcnt ; i++){ + (*pcnt)[i]=0; + } + // skip everything before the first node: + skip_nodes_cnt(MyManager,pcnt,0,Current,1,query_id); + + + fun = *comparator; + if(LOG_EXPECTED){fprintf(stderr," ##############################\n");} + if(LOG_EXPECTED){ fprintf(stderr," ##############################\n fun is %p\n",fun);} + if(!Cudd_IsConstant(Current)){ + QueuePutOnPriority(q, Current, NODE_VALUE,fun); + Found = GetNode(MyManager->his, MyManager->varmap.varstart, Current); + (*Found).dvalue2=1.0/((*Found).dvalue); + dynvalue = (*Found).dynvalue; + } + Current= NULL; // not used anymore or should not be + retval=0; + + while(QueueSize(q)>0){ + if(LOG_EXPECTED){fprintf(stderr,"\n");} + if(LOG_EXPECTED){PrintNodeQueue(q,*MyManager);} + node=QueueGet(q); + curnode = GetNodeVarNameDisp(MyManager->manager, MyManager->varmap, node); + int level = Cudd_ReadPerm(MyManager->manager,GetIndex(node)); + if(!Cudd_IsConstant(node)){ + tvalue = MyManager->varmap.dvalue[GetIndex(node) - MyManager->varmap.varstart]; + ivalue = MyManager->varmap.ivalue[GetIndex(node) - MyManager->varmap.varstart]; + dynvalue = MyManager->varmap.vars[GetIndex(node) - MyManager->varmap.varstart]; + Found = GetNode(MyManager->his, MyManager->varmap.varstart, node); + dprob=(*Found).dvalue2; + l = LowNodeOf(MyManager->manager, node); + h = HighNodeOf(MyManager->manager, node); + lfound = GetNode(MyManager->his, MyManager->varmap.varstart, l); + hfound = GetNode(MyManager->his, MyManager->varmap.varstart, h) ; + curh = GetNodeVarNameDisp(MyManager->manager, MyManager->varmap, h); + curl = GetNodeVarNameDisp(MyManager->manager, MyManager->varmap, l); + + if(LOG_EXPECTED){fprintf(stderr, "%s (%i)--> %s %s\n", curnode,(*node).index,curh,curl);} + /** low node */ + if((*lfound).dvalue2<-0.1){ //only if not seen before == dvalue2=0 (almost) otherwise requing does not harm + if(LOG_EXPECTED){fprintf(stderr,"queueing l(%s)=%s \n",curnode,curl);} + QueuePutOnPriority(q, l, NODE_VALUE,fun); + (*lfound).dvalue2=0; + } + ((*lfound).dvalue2)=((*lfound).dvalue2)+(ivalue==0? dprob : dprob*(1-tvalue)); + if(LOG_EXPECTED){fprintf(stderr, "l(%s)=%s %e \n", curnode,curl,(*lfound).dvalue2);} + if(LOG_EXPECTED){fprintf(stderr, "l(%s)=%s %e %e %e\n", curnode,curl,(*lfound).dvalue2,tvalue,dprob);} + + /** high node */ + if((*hfound).dvalue2<-0.1){ //only if not seen before == dvalue2=0 (almost) otherwise requing does not harm + fun = *comparator; + (*fun)(l,l); + if(LOG_EXPECTED){ + PrintNodeQueue(q,*MyManager); + fprintf(stderr,"-> %p\n",h); + } + QueuePutOnPriority(q, h, NODE_VALUE,fun); + (*hfound).dvalue2=0; + } + (*hfound).dvalue2=(*hfound).dvalue2+(ivalue==0? dprob : (dprob*(tvalue))); + if(LOG_EXPECTED){fprintf(stderr, "h(%s)=%s %e %e %e\n", curnode,curh,(*hfound).dvalue2,tvalue,dprob);} + /** output expected counts current node */ + if(ivalue==1){ + (*pcnt)[GetIndex(node) - MyManager->varmap.varstart]+=dprob * tvalue * (*hfound).dvalue; + //fprintf(stdout,"oec(%s,%s,%e). %% 1_1\n",query_id,dynvalue,dprob * tvalue * (*hfound).dvalue); + if(LOG_EXPECTED) fprintf(stderr,"ec -> %s,%s,%e . %% 1_1\n",query_id,dynvalue,dprob * tvalue * (*hfound).dvalue); + }else{ + (*pcnt)[GetIndex(node) - MyManager->varmap.varstart]+=dprob * tvalue * (*hfound).dvalue; + if(LOG_EXPECTED) fprintf(stderr,"ec -> %s,%s,%e . %% 1_2\n",query_id,dynvalue,dprob * tvalue * (*hfound).dvalue); + } + /** output expected counts of skipped nodes for low branch*/ + skip_nodes(MyManager,pcnt,node,l,dprob*((ivalue==0)?1:(1-tvalue))*(*lfound).dvalue,query_id); + skip_nodes(MyManager,pcnt,node,h,dprob*((ivalue==0)?1:(tvalue))*(*hfound).dvalue,query_id); + }else{ + if(LOG_EXPECTED){fprintf(stderr,"here: retval %s %e=>%e\n",curnode,retval,(*Found).dvalue2);} + if(node==(MyManager->t)){ + if(LOG_EXPECTED){fprintf(stderr,"updating retval %e=>%e\n",retval,(*Found).dvalue2);} + retval=(*Found).dvalue2; + } + + } + } + for( i = 0 ;i< MyManager->varmap.varcnt ; i++){ + ivalue = MyManager->varmap.ivalue[i]; + /* fprintf(stderr,"Node level %i index: %i name: %s (dprob is %e)\n", */ + /* i,idx, */ + /* MyManager->varmap.vars[idx - MyManager->varmap.varstart], */ + /* dprob); */ + //fprintf(stderr,"Node idx: %i level: %i \n",i,Cudd_ReadPerm(MyManager->manager,i)); + if(ivalue==0){ + fprintf(stdout,"%% det: ec(%s,%s,%30.30e).\n",query_id,MyManager->varmap.vars[i],(counts)[i]); + }else{ + fprintf(stdout,"ec(%s,%s,%30.30e).\n",query_id,MyManager->varmap.vars[i],(counts)[i]); + + } + } + // free(counts); + if(LOG_EXPECTED){ +fprintf(stderr,"retval is %e\n",retval); +} + return retval; +} + +double CalcExpectedCountsUp(extmanager * MyManager, DdNode *Current, char *query_id) { + // fprintf(stderr,"--------------------- the manager 2 %p \n",&MyManager); + + DdNode *h, *l; + hisnode *Found; + char *curnode; + double lvalue, hvalue, tvalue; + // tvalue=0.0; + int ivalue; + if (params.debug) { + curnode = GetNodeVarNameDisp(MyManager->manager, MyManager->varmap, Current); + fprintf(stderr, "%s\n", curnode); + } + + if (Current == MyManager->t){ + // if ((Found = GetNode(MyManager->his, MyManager->varmap.varstart, Current)) == NULL) { + // fprintf(stderr,"adding true \n"); + AddNode(MyManager->his, MyManager->varmap.varstart, MyManager->t, 1, 0, NULL);//}//needed in down + return 1.0; + } + if (Current == MyManager->f){ + // fprintf(stderr,"adding false \n"); + // if ((Found = GetNode(MyManager->his, MyManager->varmap.varstart, Current)) == NULL) { + AddNode(MyManager->his, MyManager->varmap.varstart, MyManager->f, 0, 0, NULL);//}//needed in down + return 0.0; + } + + if ((Found = GetNode(MyManager->his, MyManager->varmap.varstart, Current)) != NULL) return Found->dvalue; + l = LowNodeOf(MyManager->manager, Current); + h = HighNodeOf(MyManager->manager, Current); + if (params.debug) fprintf(stderr, "l(%s)->", curnode); + lvalue = CalcExpectedCountsUp(MyManager, l,query_id); + if (params.debug) fprintf(stderr, "h(%s)->", curnode); + hvalue = CalcExpectedCountsUp(MyManager, h,query_id); + + + tvalue = MyManager->varmap.dvalue[GetIndex(Current) - MyManager->varmap.varstart]; + //notiz + ivalue = MyManager->varmap.ivalue[GetIndex(Current) - MyManager->varmap.varstart]; + + if(ivalue == 1){ + tvalue = tvalue * hvalue + lvalue * (1.0 - tvalue); + }else if (ivalue == 0){ + tvalue = hvalue + lvalue ; + } + // fprintf(stderr," ---> %e \n",tvalue); + AddNode(MyManager->his, MyManager->varmap.varstart, Current, tvalue, 0, NULL); + return tvalue; +} + + +/* Bernds Algorithm */ +// type=0 regular probabilistic fact +// type=1 derive gradient for mu +// type=2 derive gradient for sigma +gradientpair CalcGradient(extmanager MyManager, DdNode *Current, int TargetVar, char *TargetPattern, int type) { + DdNode *h, *l; + hisnode *Found; + char *curnode, *dynvalue; + gradientpair lowvalue, highvalue, tvalue; + double this_probability; + double *gradient; + density_integral dynvalue_parsed; + + if (params.debug) { + curnode = GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, Current); + fprintf(stderr, "%s\n", curnode); + } + // base cases + if (Current == MyManager.t) { + tvalue.probability = 1.0; + tvalue.gradient = 0.0; + return tvalue; + } + if (Current == MyManager.f) { + tvalue.probability = 0.0; + tvalue.gradient = 0.0; + return tvalue; + } + //node is in cache + if ((Found = GetNode(MyManager.his, MyManager.varmap.varstart, Current)) != NULL) { + tvalue.probability = Found->dvalue; + tvalue.gradient = *((double *) Found->dynvalue); + return tvalue; + } + + //inductive case + l = LowNodeOf(MyManager.manager, Current); + h = HighNodeOf(MyManager.manager, Current); + if (params.debug) fprintf(stderr, "l(%s)->", curnode); + lowvalue = CalcGradient(MyManager, l, TargetVar, TargetPattern,type); + if (params.debug) fprintf(stderr, "h(%s)->", curnode); + highvalue = CalcGradient(MyManager, h, TargetVar, TargetPattern,type); + dynvalue = (char*) MyManager.varmap.dynvalue[GetIndex(Current) - MyManager.varmap.varstart]; + if (dynvalue == NULL) { // no dynvalue, it's a regular probabilistic fact + this_probability = sigmoid(MyManager.varmap.dvalue[GetIndex(Current) - MyManager.varmap.varstart], params.sigmoid_slope); + } else { // there is a dynvalue, it's a continuous fact! let's do the hybrid ProbLog magic here + curnode = GetNodeVarNameDisp(MyManager.manager, MyManager.varmap, Current); + dynvalue_parsed = parse_density_integral_string(dynvalue, curnode); + this_probability=cumulative_normal(dynvalue_parsed.low,dynvalue_parsed.high,dynvalue_parsed.mu,dynvalue_parsed.sigma); + } + + tvalue.probability = this_probability * highvalue.probability + (1 - this_probability) * lowvalue.probability; + tvalue.gradient = this_probability * highvalue.gradient + (1 - this_probability) * lowvalue.gradient; + if ((GetIndex(Current) == TargetVar) || + ((TargetPattern != NULL) && patternmatch(TargetPattern, MyManager.varmap.vars[GetIndex(Current)]))) { + if (type == 0) { // current node is normal probabilistic fact + tvalue.gradient += (highvalue.probability - lowvalue.probability) * this_probability * (1 - this_probability) * params.sigmoid_slope; + } else if (type == 1) { // it's a continues fact and we need d/dmu + tvalue.gradient += cumulative_normal_dmu(dynvalue_parsed.low, dynvalue_parsed.high, dynvalue_parsed.mu, dynvalue_parsed.sigma) * (highvalue.probability + lowvalue.probability); + } else if (type == 2) { // it's a continues fact and we need d/dsigma + tvalue.gradient += cumulative_normal_dsigma(dynvalue_parsed.low, dynvalue_parsed.high, dynvalue_parsed.mu, dynvalue_parsed.sigma) * (highvalue.probability + lowvalue.probability); + } + } + gradient = (double *) malloc(sizeof(double)); + *gradient = tvalue.gradient; + AddNode(MyManager.his, MyManager.varmap.varstart, Current, tvalue.probability, 0, gradient); + return tvalue; +} + +char * extractpattern(char *thestr) { + char *p; + int i = 0, sl = strlen(thestr); + while((thestr[i] != '_') && (i < sl)) i++; + if (i == sl) return NULL; + i++; + p = (char *) malloc(sizeof(char) * (i + 2)); + strncpy(p, thestr, i); + p[i] = '*'; + p[i + 1] = '\0'; + return p; +} + +int patterncalculated(char *pattern, extmanager MyManager, int loc) { + int i; + if (pattern == NULL) return 0; + for (i = loc - 1; i > -1; i--) + if (patternmatch(pattern, MyManager.varmap.vars[i])) return 1; + return 0; +} diff --git a/packages/ProbLog/simplecudd_lfi/problogmath.c b/packages/ProbLog/simplecudd_lfi/problogmath.c new file mode 100644 index 000000000..e903e7bbb --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/problogmath.c @@ -0,0 +1,293 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright T. Mantadelis, A. Kimmig, B. Gutmann * +* and Katholieke Universiteit Leuven 2008 * +* * +* Author: Bernd Gutmann * +* File: problogmath.c * +* $Date:: 2009-12-06 00:55:33 +0100 (Sun, 06 Dec 2009) $ * +* $Revision:: 2919 $ * +* * +* * +******************************************************************************** +* * +* The "Artistic License" * +* * +* Preamble * +* * +* The intent of this document is to state the conditions under which a * +* Package may be copied, such that the Copyright Holder maintains some * +* semblance of artistic control over the development of the package, * +* while giving the users of the package the right to use and distribute * +* the Package in a more-or-less customary fashion, plus the right to make * +* reasonable modifications. * +* * +* Definitions: * +* * +* "Package" refers to the collection of files distributed by the * +* Copyright Holder, and derivatives of that collection of files * +* created through textual modification. * +* * +* "Standard Version" refers to such a Package if it has not been * +* modified, or has been modified in accordance with the wishes * +* of the Copyright Holder as specified below. * +* * +* "Copyright Holder" is whoever is named in the copyright or * +* copyrights for the package. * +* * +* "You" is you, if you're thinking about copying or distributing * +* this Package. * +* * +* "Reasonable copying fee" is whatever you can justify on the * +* basis of media cost, duplication charges, time of people involved, * +* and so on. (You will not be required to justify it to the * +* Copyright Holder, but only to the computing community at large * +* as a market that must bear the fee.) * +* * +* "Freely Available" means that no fee is charged for the item * +* itself, though there may be fees involved in handling the item. * +* It also means that recipients of the item may redistribute it * +* under the same conditions they received it. * +* * +* 1. You may make and give away verbatim copies of the source form of the * +* Standard Version of this Package without restriction, provided that you * +* duplicate all of the original copyright notices and associated disclaimers. * +* * +* 2. You may apply bug fixes, portability fixes and other modifications * +* derived from the Public Domain or from the Copyright Holder. A Package * +* modified in such a way shall still be considered the Standard Version. * +* * +* 3. You may otherwise modify your copy of this Package in any way, provided * +* that you insert a prominent notice in each changed file stating how and * +* when you changed that file, and provided that you do at least ONE of the * +* following: * +* * +* a) place your modifications in the Public Domain or otherwise make them * +* Freely Available, such as by posting said modifications to Usenet or * +* an equivalent medium, or placing the modifications on a major archive * +* site such as uunet.uu.net, or by allowing the Copyright Holder to include * +* your modifications in the Standard Version of the Package. * +* * +* b) use the modified Package only within your corporation or organization. * +* * +* c) rename any non-standard executables so the names do not conflict * +* with standard executables, which must also be provided, and provide * +* a separate manual page for each non-standard executable that clearly * +* documents how it differs from the Standard Version. * +* * +* d) make other distribution arrangements with the Copyright Holder. * +* * +* 4. You may distribute the programs of this Package in object code or * +* executable form, provided that you do at least ONE of the following: * +* * +* a) distribute a Standard Version of the executables and library files, * +* together with instructions (in the manual page or equivalent) on where * +* to get the Standard Version. * +* * +* b) accompany the distribution with the machine-readable source of * +* the Package with your modifications. * +* * +* c) give non-standard executables non-standard names, and clearly * +* document the differences in manual pages (or equivalent), together * +* with instructions on where to get the Standard Version. * +* * +* d) make other distribution arrangements with the Copyright Holder. * +* * +* 5. You may charge a reasonable copying fee for any distribution of this * +* Package. You may charge any fee you choose for support of this * +* Package. You may not charge a fee for this Package itself. However, * +* you may distribute this Package in aggregate with other (possibly * +* commercial) programs as part of a larger (possibly commercial) software * +* distribution provided that you do not advertise this Package as a * +* product of your own. You may embed this Package's interpreter within * +* an executable of yours (by linking); this shall be construed as a mere * +* form of aggregation, provided that the complete Standard Version of the * +* interpreter is so embedded. * +* * +* 6. The scripts and library files supplied as input to or produced as * +* output from the programs of this Package do not automatically fall * +* under the copyright of this Package, but belong to whoever generated * +* them, and may be sold commercially, and may be aggregated with this * +* Package. If such scripts or library files are aggregated with this * +* Package via the so-called "undump" or "unexec" methods of producing a * +* binary executable image, then distribution of such an image shall * +* neither be construed as a distribution of this Package nor shall it * +* fall under the restrictions of Paragraphs 3 and 4, provided that you do * +* not represent such an executable image as a Standard Version of this * +* Package. * +* * +* 7. C subroutines (or comparably compiled subroutines in other * +* languages) supplied by you and linked into this Package in order to * +* emulate subroutines and variables of the language defined by this * +* Package shall not be considered part of this Package, but are the * +* equivalent of input as in Paragraph 6, provided these subroutines do * +* not change the language in any way that would cause it to fail the * +* regression tests for the language. * +* * +* 8. Aggregation of this Package with a commercial distribution is always * +* permitted provided that the use of this Package is embedded; that is, * +* when no overt attempt is made to make this Package's interfaces visible * +* to the end user of the commercial distribution. Such use shall not be * +* construed as a distribution of this Package. * +* * +* 9. The name of the Copyright Holder may not be used to endorse or promote * +* products derived from this software without specific prior written * +* permission. * +* * +* 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * +* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * +* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * +* * +* The End * +* * +\******************************************************************************/ + +#include "problogmath.h" + + +double sigmoid(double x, double slope) { + return 1.0 / (1.0 + exp(-x * slope)); +} + +// This function calculates the accumulated density of the normal distribution +// For details see G. Marsaglia, Evaluating the Normal Distribution, Journal of Statistical Software, 2004:11(4). +double Phi(double x) { + double s=x; + double t=0.0; + double b=x; + double q=x*x; + double i=1; + + // if the value is too small or too big, return + // 0/1 to avoid long computations + if (x < -10.0) { + return 0.0; + } + + if (x > 10.0) { + return 1.0; + } + + // t is the value from last iteration + // s is the value from the current iteration + // iterate until they are equal + while(fabs(s-t) >= DBL_MIN) { + t=s; + i+=2; + b*=q/i; + s+=b; + } + + return 0.5+s*exp(-0.5*q-0.91893853320467274178); +} + +// integrates the normal distribution over [low,high] +double cumulative_normal(double low, double high, double mu, double sigma) { + return Phi((high-mu)/sigma) - Phi((low-mu)/sigma); +} + +// evaluates the density of the normal distribution +double normal(double x, double mu,double sigma) { + double inner=(x-mu)/sigma; + double denom=sigma*sqrt(2*3.14159265358979323846); + return exp(-inner*inner/2)/denom; +} + +double cumulative_normal_dmu(double low, double high,double mu,double sigma) { + return normal(low,mu,sigma) - normal(high,mu,sigma); +} + +double cumulative_normal_dsigma(double low, double high,double mu,double sigma) { + return ((mu-high)*normal(high,mu,sigma) - (mu-low)*normal(low,mu,sigma))/sigma; +} + + +// this function parses two strings "$a;$b" and "???_???l$ch$d" where $a-$d are (real) numbers +// it is used to parse in the parameters of continues variables from the input file +density_integral parse_density_integral_string(char *input, char *variablename) { + density_integral result; + int i; + char garbage[64], s1[64],s2[64],s3[64],s4[64]; + + if(sscanf(input, "%64[^;];%64[^;]", s1,s2) != 2) { + fprintf(stderr, "Error at parsing the string %s in the function parse_density_integral_string\n",input); + fprintf(stderr, "The string should contain 2 fields seperated by ; characters.\n"); + exit(EXIT_FAILURE); + } + + if (IsRealNumber(s1)) { + result.mu=atof(s1); + } else { + fprintf(stderr, "Error at parsing the string %s in the function parse_density_integral_string\n",input); + fprintf(stderr, "%s is not a number\n",s1); + exit(EXIT_FAILURE); + } + + if (IsRealNumber(s2)) { + result.sigma=atof(s2); + } else { + fprintf(stderr, "Error at parsing the string %s in the function parse_density_integral_string\n",input); + fprintf(stderr, "%s is not a number\n",s2); + exit(EXIT_FAILURE); + } + + if (result.sigma<=0) { + fprintf(stderr, "Error at parsing the string %s in the function parse_density_integral_string",input); + fprintf(stderr, "The value for sigma has to be larger than 0.\n"); + + exit(EXIT_FAILURE); + } + + if (sscanf(variablename,"%64[^lh]l%64[^lh]h%64[^lh]",garbage,s3,s4) != 3) { + fprintf(stderr, "Error at parsing the string %s in the function parse_density_integral_string\n",variablename); + fprintf(stderr, "The string should contain 2 fields seperated by ; characters.\n"); + exit(EXIT_FAILURE); + } + + // replace the d by . in s1 and s2 + for(i=0; s3[i]!='\0' ; i++) { + if (s3[i]=='d') { + s3[i]='.'; + } + if (s3[i]=='m') { + s3[i]='-'; + } + } + for(i=0; s4[i]!='\0' ; i++) { + if (s4[i]=='d') { + s4[i]='.'; + } + if (s4[i]=='m') { + s4[i]='-'; + } + } + + if (IsRealNumber(s3)) { + result.low=atof(s3); + } else { + fprintf(stderr, "Error at parsing the string %s in the function parse_density_integral_string\n",input); + fprintf(stderr, "%s is not a number\n",s1); + exit(EXIT_FAILURE); + } + + if (IsRealNumber(s4)) { + result.high=atof(s4); + } else { + fprintf(stderr, "Error ar parsing the string %s in the function parse_density_integral_string\n",input); + fprintf(stderr, "%s is not a number\n",s1); + exit(EXIT_FAILURE); + } + + + if (result.low>result.high) { + fprintf(stderr, "Error ar parsing the string %s in the function parse_density_integral_string\n",input); + fprintf(stderr, "The value for low has to be larger than then value for high.\n"); + exit(EXIT_FAILURE); + } + + + return result; +} diff --git a/packages/ProbLog/simplecudd_lfi/problogmath.h b/packages/ProbLog/simplecudd_lfi/problogmath.h new file mode 100644 index 000000000..a547e145b --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/problogmath.h @@ -0,0 +1,168 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright T. Mantadelis, A. Kimmig, B. Gutmann * +* and Katholieke Universiteit Leuven 2008 * +* * +* Author: Bernd Gutmann * +* File: problogmath.h * +* $Date:: 2009-08-17 17:45:21 +0200 (Mon, 17 Aug 2009) $ * +* $Revision:: 1900 $ * +* * +* * +******************************************************************************** +* * +* The "Artistic License" * +* * +* Preamble * +* * +* The intent of this document is to state the conditions under which a * +* Package may be copied, such that the Copyright Holder maintains some * +* semblance of artistic control over the development of the package, * +* while giving the users of the package the right to use and distribute * +* the Package in a more-or-less customary fashion, plus the right to make * +* reasonable modifications. * +* * +* Definitions: * +* * +* "Package" refers to the collection of files distributed by the * +* Copyright Holder, and derivatives of that collection of files * +* created through textual modification. * +* * +* "Standard Version" refers to such a Package if it has not been * +* modified, or has been modified in accordance with the wishes * +* of the Copyright Holder as specified below. * +* * +* "Copyright Holder" is whoever is named in the copyright or * +* copyrights for the package. * +* * +* "You" is you, if you're thinking about copying or distributing * +* this Package. * +* * +* "Reasonable copying fee" is whatever you can justify on the * +* basis of media cost, duplication charges, time of people involved, * +* and so on. (You will not be required to justify it to the * +* Copyright Holder, but only to the computing community at large * +* as a market that must bear the fee.) * +* * +* "Freely Available" means that no fee is charged for the item * +* itself, though there may be fees involved in handling the item. * +* It also means that recipients of the item may redistribute it * +* under the same conditions they received it. * +* * +* 1. You may make and give away verbatim copies of the source form of the * +* Standard Version of this Package without restriction, provided that you * +* duplicate all of the original copyright notices and associated disclaimers. * +* * +* 2. You may apply bug fixes, portability fixes and other modifications * +* derived from the Public Domain or from the Copyright Holder. A Package * +* modified in such a way shall still be considered the Standard Version. * +* * +* 3. You may otherwise modify your copy of this Package in any way, provided * +* that you insert a prominent notice in each changed file stating how and * +* when you changed that file, and provided that you do at least ONE of the * +* following: * +* * +* a) place your modifications in the Public Domain or otherwise make them * +* Freely Available, such as by posting said modifications to Usenet or * +* an equivalent medium, or placing the modifications on a major archive * +* site such as uunet.uu.net, or by allowing the Copyright Holder to include * +* your modifications in the Standard Version of the Package. * +* * +* b) use the modified Package only within your corporation or organization. * +* * +* c) rename any non-standard executables so the names do not conflict * +* with standard executables, which must also be provided, and provide * +* a separate manual page for each non-standard executable that clearly * +* documents how it differs from the Standard Version. * +* * +* d) make other distribution arrangements with the Copyright Holder. * +* * +* 4. You may distribute the programs of this Package in object code or * +* executable form, provided that you do at least ONE of the following: * +* * +* a) distribute a Standard Version of the executables and library files, * +* together with instructions (in the manual page or equivalent) on where * +* to get the Standard Version. * +* * +* b) accompany the distribution with the machine-readable source of * +* the Package with your modifications. * +* * +* c) give non-standard executables non-standard names, and clearly * +* document the differences in manual pages (or equivalent), together * +* with instructions on where to get the Standard Version. * +* * +* d) make other distribution arrangements with the Copyright Holder. * +* * +* 5. You may charge a reasonable copying fee for any distribution of this * +* Package. You may charge any fee you choose for support of this * +* Package. You may not charge a fee for this Package itself. However, * +* you may distribute this Package in aggregate with other (possibly * +* commercial) programs as part of a larger (possibly commercial) software * +* distribution provided that you do not advertise this Package as a * +* product of your own. You may embed this Package's interpreter within * +* an executable of yours (by linking); this shall be construed as a mere * +* form of aggregation, provided that the complete Standard Version of the * +* interpreter is so embedded. * +* * +* 6. The scripts and library files supplied as input to or produced as * +* output from the programs of this Package do not automatically fall * +* under the copyright of this Package, but belong to whoever generated * +* them, and may be sold commercially, and may be aggregated with this * +* Package. If such scripts or library files are aggregated with this * +* Package via the so-called "undump" or "unexec" methods of producing a * +* binary executable image, then distribution of such an image shall * +* neither be construed as a distribution of this Package nor shall it * +* fall under the restrictions of Paragraphs 3 and 4, provided that you do * +* not represent such an executable image as a Standard Version of this * +* Package. * +* * +* 7. C subroutines (or comparably compiled subroutines in other * +* languages) supplied by you and linked into this Package in order to * +* emulate subroutines and variables of the language defined by this * +* Package shall not be considered part of this Package, but are the * +* equivalent of input as in Paragraph 6, provided these subroutines do * +* not change the language in any way that would cause it to fail the * +* regression tests for the language. * +* * +* 8. Aggregation of this Package with a commercial distribution is always * +* permitted provided that the use of this Package is embedded; that is, * +* when no overt attempt is made to make this Package's interfaces visible * +* to the end user of the commercial distribution. Such use shall not be * +* construed as a distribution of this Package. * +* * +* 9. The name of the Copyright Holder may not be used to endorse or promote * +* products derived from this software without specific prior written * +* permission. * +* * +* 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR * +* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * +* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * +* * +* The End * +* * +\******************************************************************************/ + +#include +#include +#include +#include +#include + +typedef struct _density_integral { + double low; + double high; + double mu; + double sigma; +} density_integral; + + + +double sigmoid(double x, double slope); +double Phi(double x); +double cumulative_normal(double low, double high, double sigma, double mu); +double cumulative_normal_dmu(double low, double high,double mu,double sigma); +double cumulative_normal_dsigma(double low, double high,double mu,double sigma); +density_integral parse_density_integral_string(char *input, char *variablename); diff --git a/packages/ProbLog/simplecudd_lfi/queuetest.c b/packages/ProbLog/simplecudd_lfi/queuetest.c new file mode 100644 index 000000000..27484ed25 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/queuetest.c @@ -0,0 +1,52 @@ +#include + +#include "pqueue.h" +#include "iqueue.h" +//http://www.koders.com/c/fid7B82D8DDECE4EDC672F17D970458033C4079A615.aspx?s=queue +#define INT_VALUE 1000 + +//typedef int (*ComparisonFunction)(void*, void*); +int compare_int (const int *a, const int *b) +{ + fprintf(stderr,"comparing %i %i \n",*a,*b); + int temp = *a - *b; + // return (a 0) + return -1; + else + return 0; +} + + +int main (int argc, char* argv[]) { + int val1 = 1; + int val2 = 2; + int val3 = 3; + int val4 = 4; + + Queue q = QueueNew(); + + QueuePutOnPriority(q, &val1, INT_VALUE,(ComparisonFunction)compare_int); + QueuePutOnPriority(q, &val3, INT_VALUE,(ComparisonFunction)compare_int); + QueuePutOnPriority(q, &val2, INT_VALUE,(ComparisonFunction)compare_int); + QueuePutOnPriority(q, &val4, INT_VALUE,(ComparisonFunction)compare_int); + + QueueItem qptr = q->head; + while (qptr != NULL) { + int* val = (int*) qptr->element; + printf("value: %d\n", *val); + qptr = qptr->next; + } + + QueueIterator qiter = QueueIteratorNew(q, 1); + + while (qiter->currentItem != NULL) { + int* val = (int*) qiter->currentItem->element; + printf("iterator value: %d\n", *val); + QueueIteratorAdvance(qiter); + } +} diff --git a/packages/ProbLog/simplecudd_lfi/simplecudd.c b/packages/ProbLog/simplecudd_lfi/simplecudd.c new file mode 100644 index 000000000..4c27369ec --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/simplecudd.c @@ -0,0 +1,1865 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright Katholieke Universiteit Leuven 2008 * +* * +* Author: Theofrastos Mantadelis, Bernd Gutmann * +* File: simplecudd.c * +* * +******************************************************************************** +* * +* 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. * +* * +* The End * +* * +\******************************************************************************/ + +#include +#include +#include "simplecudd.h" + +/* BDD manager initialization */ + +int _debug = 0; +int _RapidLoad = 0; +int _maxbufsize = 0; + +DdManager* simpleBDDinit(int varcnt) { + DdManager *temp; + // fprintf(stderr,"varcnt is %i \n",varcnt); + temp = Cudd_Init(varcnt, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); + Cudd_AutodynEnable(temp, CUDD_REORDER_GROUP_SIFT); + //Cudd_AutodynEnable(temp, CUDD_REORDER_RANDOM); + //Cudd_AutodynDisable(temp); + Cudd_SetMaxCacheHard(temp, 1024*1024*1024); + Cudd_SetLooseUpTo(temp, 1024*1024*512); + if (_debug) Cudd_EnableReorderingReporting(temp); + return temp; +} + +/* BDD tree travesrsing */ + +DdNode* HighNodeOf(DdManager *manager, DdNode *node) { + DdNode *tmp; + if (IsHigh(manager, node)) return HIGH(manager); + if (IsLow(manager, node)) return LOW(manager); + tmp = Cudd_Regular(node); + if (Cudd_IsComplement(node)) return NOT(tmp->type.kids.T); + return tmp->type.kids.T; +} + +DdNode* LowNodeOf(DdManager *manager, DdNode *node) { + DdNode *tmp; + if (IsHigh(manager, node)) return HIGH(manager); + if (IsLow(manager, node)) return LOW(manager); + tmp = Cudd_Regular(node); + if (Cudd_IsComplement(node)) return NOT(tmp->type.kids.E); + return tmp->type.kids.E; +} + +/* BDD tree generation */ + +DdNode* D_BDDAnd(DdManager *manager, DdNode *bdd1, DdNode *bdd2) { + DdNode *tmp; + Cudd_Ref(bdd1); + tmp = Cudd_bddAnd(manager, bdd1, bdd2); + Cudd_Ref(tmp); + //Cudd_RecursiveDeref(manager, bdd2); + return tmp; +} + +DdNode* D_BDDNand(DdManager *manager, DdNode *bdd1, DdNode *bdd2) { + DdNode *tmp; + Cudd_Ref(bdd1); + tmp = Cudd_bddNand(manager, bdd1, bdd2); + Cudd_Ref(tmp); + //Cudd_RecursiveDeref(manager, bdd2); + return tmp; +} + +DdNode* D_BDDOr(DdManager *manager, DdNode *bdd1, DdNode *bdd2) { + DdNode *tmp; + Cudd_Ref(bdd1); + tmp = Cudd_bddOr(manager, bdd1, bdd2); + Cudd_Ref(tmp); + //Cudd_RecursiveDeref(manager, bdd2); + return tmp; +} + +DdNode* D_BDDNor(DdManager *manager, DdNode *bdd1, DdNode *bdd2) { + DdNode *tmp; + Cudd_Ref(bdd1); + tmp = Cudd_bddNor(manager, bdd1, bdd2); + Cudd_Ref(tmp); + //Cudd_RecursiveDeref(manager, bdd2); + return tmp; +} + +DdNode* D_BDDXor(DdManager *manager, DdNode *bdd1, DdNode *bdd2) { + DdNode *tmp; + Cudd_Ref(bdd1); + tmp = Cudd_bddXor(manager, bdd1, bdd2); + Cudd_Ref(tmp); + //Cudd_RecursiveDeref(manager, bdd2); + return tmp; +} + +DdNode* D_BDDXnor(DdManager *manager, DdNode *bdd1, DdNode *bdd2) { + DdNode *tmp; + Cudd_Ref(bdd1); + tmp = Cudd_bddXnor(manager, bdd1, bdd2); + Cudd_Ref(tmp); + //Cudd_RecursiveDeref(manager, bdd2); + return tmp; +} + +/* file manipulation */ + +bddfileheader ReadFileHeader(char *filename) { + bddfileheader temp; + char *header; + temp.inputfile = NULL; + temp.version = 0; + temp.varcnt = 0; + temp.varstart = 0; + temp.intercnt = 0; + temp.filetype = BDDFILE_OTHER; + if ((temp.inputfile = fopen(filename, "r")) == NULL) { + perror(filename); + temp.filetype = BDDFILE_ERROR; + return temp; + } + // Read file header + if (!feof(temp.inputfile)) { + header = freadline(temp.inputfile); + temp.version = CheckFileVersion(header); + if (temp.version > -1) temp.filetype = (strlen(header) == 5) * BDDFILE_SCRIPT + (strlen(header) == 7) * BDDFILE_NODEDUMP; + free(header); + switch (temp.filetype) { + case BDDFILE_SCRIPT: + switch (temp.version) { + case 1: + case 2: + fscanf(temp.inputfile, "%i\n", &temp.varcnt); + fscanf(temp.inputfile, "%i\n", &temp.varstart); + fscanf(temp.inputfile, "%i\n", &temp.intercnt); + break; + default: + fclose(temp.inputfile); + temp.inputfile = NULL; + break; + } + break; + case BDDFILE_NODEDUMP: + switch (temp.version) { + case 1: + fscanf(temp.inputfile, "%i\n", &temp.varcnt); + fscanf(temp.inputfile, "%i\n", &temp.varstart); + break; + default: + fclose(temp.inputfile); + temp.inputfile = NULL; + break; + } + break; + case BDDFILE_OTHER: + fclose(temp.inputfile); + temp.inputfile = NULL; + break; + default: + fclose(temp.inputfile); + temp.inputfile = NULL; + break; + } + } + return temp; +} + +int CheckFileVersion(const char *version) { + if (strlen(version) < 5) return -1; + if (strlen(version) == 5 && version[0] == '@' && version[1] == 'B' && version[2] == 'D' && version[3] == 'D') return atoi(version + 4); + if (strlen(version) == 7 && version[0] == '@' && version[1] == 'N' && version[2] == 'O' && version[3] == 'D' + && version[4] == 'E' && version[5] == 'S') return atoi(version + 6); + return -1; +} + +int simpleBDDtoDot(DdManager *manager, DdNode *bdd, char *filename) { + DdNode *f[1]; + int ret; + FILE *fd; + f[0] = Cudd_BddToAdd(manager, bdd); + fd = fopen(filename, "w"); + if (fd == NULL) { + perror(filename); + return -1; + } + ret = Cudd_DumpDot(manager, 1, f, NULL, NULL, fd); + fclose(fd); + return ret; +} + +int simpleNamedBDDtoDot(DdManager *manager, namedvars varmap, DdNode *bdd, char *filename) { + DdNode *f[1]; + int ret; + FILE *fd; + Cudd_ReduceHeap(manager, CUDD_REORDER_SIFT_CONVERGE, 1); + f[0] = Cudd_BddToAdd(manager, bdd); + fd = fopen(filename, "w"); + if (fd == NULL) { + perror(filename); + return -1; + } + // Cudd_AutodynEnable(mana, CUDD_REORDER_EXACT); + // Cudd_ReduceHeap(manager, CUDD_REORDER_SIFT, 1); + + ret = Cudd_DumpDot(manager, 1, f, varmap.vars, NULL, fd); + fclose(fd); + return ret; +} + +int SaveNodeDump(DdManager *manager, namedvars varmap, DdNode *bdd, char *filename) { + hisqueue *Nodes; + FILE *outputfile; + int i; + if ((outputfile = fopen(filename, "w")) == NULL) { + perror(filename); + return -1; + } + fprintf(outputfile, "%s\n%i\n%i\n", "@NODES1", varmap.varcnt, varmap.varstart); + Nodes = InitHistory(varmap.varcnt); + for (i = 0; i < varmap.varcnt; i++) + fprintf(outputfile, "%s\t%i\n", varmap.vars[i], Cudd_ReadPerm(manager, i)); + if (bdd == HIGH(manager)) fprintf(outputfile, "TRUE\t0\tTRUE\t0\tTRUE\t0\n"); + else if (bdd == LOW(manager)) fprintf(outputfile, "FALSE\t0\tFALSE\t0\tFALSE\t0\n"); + else SaveExpand(manager, varmap, Nodes, bdd, outputfile); + ReInitHistory(Nodes, varmap.varcnt); + free(Nodes); + fclose(outputfile); + return 0; +} + +void SaveExpand(DdManager *manager, namedvars varmap, hisqueue *Nodes, DdNode *Current, FILE *outputfile) { + DdNode *h, *l; + hisnode *Found; + char *curnode; + int inode; + if (Current != HIGH(manager) && Current != LOW(manager)) { + if ((Found = GetNode(Nodes, varmap.varstart, Current)) == NULL) { + AddNode(Nodes, varmap.varstart, Current, 0.0, 0, NULL); + Found = GetNode(Nodes, varmap.varstart, Current); + } + if (!(Found->ivalue)) { + Found->ivalue = 1; + curnode = GetNodeVarNameDisp(manager, varmap, Current); + inode = GetNodeIndex(Nodes, varmap.varstart, Current); + fprintf(outputfile, "%s\t%i\t", curnode, inode); + h = HighNodeOf(manager, Current); + if (h == HIGH(manager)) { + fprintf(outputfile, "TRUE\t0\t"); + } else if (h == LOW(manager)) { + fprintf(outputfile, "FALSE\t0\t"); + } else { + if (GetNode(Nodes, varmap.varstart, h) == NULL) AddNode(Nodes, varmap.varstart, h, 0.0, 0, NULL); + curnode = GetNodeVarNameDisp(manager, varmap, h); + inode = GetNodeIndex(Nodes, varmap.varstart, h); + fprintf(outputfile, "%s\t%i\t", curnode, inode); + } + l = LowNodeOf(manager, Current); + if (l == HIGH(manager)) { + fprintf(outputfile, "TRUE\t0\n"); + } else if (l == LOW(manager)) { + fprintf(outputfile, "FALSE\t0\n"); + } else { + if (GetNode(Nodes, varmap.varstart, l) == NULL) AddNode(Nodes, varmap.varstart, l, 0.0, 0, NULL); + curnode = GetNodeVarNameDisp(manager, varmap, l); + inode = GetNodeIndex(Nodes, varmap.varstart, l); + fprintf(outputfile, "%s\t%i\n", curnode, inode); + } + SaveExpand(manager, varmap, Nodes, l, outputfile); + SaveExpand(manager, varmap, Nodes, h, outputfile); + } + } +} + +DdNode * LoadNodeDump(DdManager *manager, namedvars varmap, FILE *inputfile) { + hisqueue *Nodes; + nodeline temp; + DdNode *ret; + int i, pos, *perm; + char *varnam; + perm = (int *) malloc(sizeof(int) * varmap.varcnt); + Nodes = InitHistory(varmap.varcnt); + for (i = 0; i < varmap.varcnt; i++) { + varnam = freadstr(inputfile, "\t"); + pos = atoi(freadstr(inputfile, "\n")); + AddNamedVarAt(varmap, varnam, pos); + perm[pos] = pos; + } + temp.varname = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\t", &temp.nodenum); + temp.truevar = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\t", &temp.truenode); + temp.falsevar = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\n", &temp.falsenode); + ret = LoadNodeRec(manager, varmap, Nodes, inputfile, temp); + free(temp.varname); + free(temp.truevar); + free(temp.falsevar); + fclose(inputfile); + ReInitHistory(Nodes, varmap.varcnt); + free(Nodes); + Cudd_Ref(ret); + Cudd_ShuffleHeap(manager, perm); + for (i = 0; i < varmap.varcnt; i++) varmap.ivalue[i] = 0; + return ret; +} + +DdNode * LoadNodeRec(DdManager *manager, namedvars varmap, hisqueue *Nodes, FILE *inputfile, nodeline current) { + nodeline temp; + DdNode *newnode, *truenode, *falsenode; + int index; + newnode = GetIfExists(manager, varmap, Nodes, current.varname, current.nodenum); + if (newnode != NULL) return newnode; + falsenode = GetIfExists(manager, varmap, Nodes, current.falsevar, current.falsenode); + if (falsenode == NULL) { + temp.varname = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\t", &temp.nodenum); + temp.truevar = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\t", &temp.truenode); + temp.falsevar = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\n", &temp.falsenode); + falsenode = LoadNodeRec(manager, varmap, Nodes, inputfile, temp); + free(temp.varname); + free(temp.truevar); + free(temp.falsevar); + } + truenode = GetIfExists(manager, varmap, Nodes, current.truevar, current.truenode); + if (truenode == NULL) { + temp.varname = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\t", &temp.nodenum); + temp.truevar = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\t", &temp.truenode); + temp.falsevar = freadstr(inputfile, "\t"); + fscanf(inputfile, "%i\n", &temp.falsenode); + truenode = LoadNodeRec(manager, varmap, Nodes, inputfile, temp); + free(temp.varname); + free(temp.truevar); + free(temp.falsevar); + } + index = GetNamedVarIndex(varmap, current.varname); + if (!varmap.ivalue[index]) { + varmap.ivalue[index] = 1; + newnode = GetVar(manager, varmap.varstart + index); + //Cudd_RecursiveDeref(manager, newnode->type.kids.T); + //Cudd_RecursiveDeref(manager, newnode->type.kids.E); + newnode->type.kids.T = Cudd_NotCond(truenode, Cudd_IsComplement(truenode)); + newnode->type.kids.E = Cudd_NotCond(falsenode, Cudd_IsComplement(truenode)); + Cudd_Ref(newnode->type.kids.T); + Cudd_Ref(newnode->type.kids.E); + Cudd_Ref(newnode); + } else { + if (_RapidLoad == 1) { + newnode = cuddAllocNode(manager); + if (newnode != NULL) { + newnode->index = varmap.varstart + index; + newnode->type.kids.T = Cudd_NotCond(truenode, Cudd_IsComplement(truenode)); + newnode->type.kids.E = Cudd_NotCond(falsenode, Cudd_IsComplement(truenode)); + Cudd_Ref(newnode->type.kids.T); + Cudd_Ref(newnode->type.kids.E); + Cudd_Ref(newnode); + } + } else { + newnode = cuddUniqueInter(manager, varmap.varstart + index, Cudd_NotCond(truenode, Cudd_IsComplement(truenode)), Cudd_NotCond(falsenode, Cudd_IsComplement(truenode))); + if (newnode != NULL) { + Cudd_Ref(newnode); + } else { + newnode = cuddAllocNode(manager); + if (newnode != NULL) { + newnode->index = varmap.varstart + index; + newnode->type.kids.T = Cudd_NotCond(truenode, Cudd_IsComplement(truenode)); + newnode->type.kids.E = Cudd_NotCond(falsenode, Cudd_IsComplement(truenode)); + Cudd_Ref(newnode->type.kids.T); + Cudd_Ref(newnode->type.kids.E); + Cudd_Ref(newnode); + } + } + } + } + if (newnode != NULL) { + Nodes[index].thenode[current.nodenum].key = Cudd_NotCond(newnode, Cudd_IsComplement(truenode)); + return Cudd_NotCond(newnode, Cudd_IsComplement(truenode)); + } + return NULL; +} + +DdNode * GetIfExists(DdManager *manager, namedvars varmap, hisqueue *Nodes, char *varname, int nodenum) { + int index; + if (strcmp(varname, "TRUE") == 0) return HIGH(manager); + if (strcmp(varname, "FALSE") == 0) return LOW(manager); + index = GetNamedVarIndex(varmap, varname); + if (index == -1 * varmap.varcnt) { + fprintf(stderr, "Error: more variables requested than initialized.\n"); + exit(-1); + } + if ((index < 0) || (index == 0 && varmap.vars[0] == NULL)) { + index = AddNamedVar(varmap, varname); + } + ExpandNodes(Nodes, index, nodenum); + if (Nodes[index].thenode[nodenum].key != NULL) return Nodes[index].thenode[nodenum].key; + return NULL; +} + +void ExpandNodes(hisqueue *Nodes, int index, int nodenum) { + int i; + if (Nodes[index].cnt > nodenum) return; + Nodes[index].thenode = (hisnode *) realloc(Nodes[index].thenode, (nodenum + 1) * sizeof(hisnode)); + for (i = Nodes[index].cnt; i < nodenum + 1; i++) { + Nodes[index].thenode[i].key = NULL; + Nodes[index].thenode[i].ivalue = 0; + Nodes[index].thenode[i].dvalue = 0.0; + Nodes[index].thenode[i].dynvalue = NULL; + } + Nodes[index].cnt = nodenum + 1; +} + +char** GetVariableOrder(char *filename, int varcnt) { + FILE *data; + char *dataread, buf, **varname; + int icur = 0, maxbufsize = 10, index = -1; + if ((data = fopen(filename, "r")) == NULL) { + perror(filename); + return NULL; + } + varname = (char **) malloc(sizeof(char *) * varcnt); + dataread = (char *) malloc(sizeof(char) * maxbufsize); + while(!feof(data)) { + fread(&buf, 1, 1, data); + if (buf == '\n') { + dataread[icur] = '\0'; + icur = 0; + buf = ' '; + if (dataread[0] == '@') { + index++; + varname[index] = (char *) malloc(sizeof(char) * strlen(dataread)); + strcpy(varname[index], dataread + 1); + } + } else { + dataread[icur] = buf; + icur++; + if (icur == _maxbufsize) { + fprintf(stderr, "Error: Maximum buffer size(%i) exceeded.\n", _maxbufsize); + fclose(data); + free(varname); + free(dataread); + return NULL; + } + while (icur > maxbufsize - 1) { + maxbufsize *= 2; + dataread = (char *) realloc(dataread, sizeof(char) * maxbufsize); + } + } + } + fclose(data); + free(dataread); + for(icur=index+1; icur < varcnt; icur++) + varname[icur] = NULL; + return varname; +} + +int LoadVariableData(namedvars varmap, char *filename) { + FILE *data; + char *dataread, buf, *varname, *dynvalue; + char * unparsed_string; + double dvalue = 0.0; + int icur = 0, maxbufsize = 10, hasvar = 0, index = -1, idat = 0, ivalue = 0; + dynvalue = NULL; + if ((data = fopen(filename, "r")) == NULL) { + perror(filename); + return -1; + } + dataread = (char *) malloc(sizeof(char) * maxbufsize); + while(!feof(data)) { + fread(&buf, 1, 1, data); + if ((buf == '\n') && icur == 0) { + // ignore empty lines + } else if (buf == '\n') { + dataread[icur] = '\0'; + icur = 0; + buf = ' '; + if (dataread[0] == '@') { + if (hasvar) { + for (index = 0; index < varmap.varcnt; index++) { + if ((varmap.vars[index] != NULL) && (patternmatch(varname, varmap.vars[index]))) { + varmap.loaded[index] = 1; + varmap.dvalue[index] = dvalue; + varmap.ivalue[index] = ivalue; + if (varmap.dynvalue[index] != NULL) { + free(varmap.dynvalue[index]); + varmap.dynvalue[index] = NULL; + } + if (dynvalue != NULL) { + varmap.dynvalue[index] = (void *) malloc(sizeof(char) * (strlen(dynvalue) + 1)); + strcpy(varmap.dynvalue[index], dynvalue); + } + } + } + dvalue = 0.0; + ivalue = 0; + if (dynvalue != NULL) { + free(dynvalue); + dynvalue = NULL; + } + free(varname); + } + varname = (char *) malloc(sizeof(char) * strlen(dataread)); + strcpy(varname, dataread + 1); + hasvar = 1; + idat = 0; + } else { + if (hasvar >= 0) { + switch(idat) { + case 0: + // http://www.cplusplus.com/reference/clibrary/cstdlib/strtod/ + + errno=0; // reset global error indicator + dvalue = strtod(dataread, &unparsed_string); + + // check for errors + if (errno == ERANGE || unparsed_string == dataread) { + fprintf(stderr, "Error at file: %s. Variable: %s does not have a valid real value: %s.\n", filename, varname, dataread); + fclose(data); + free(varname); + free(dataread); + return -2; + } + idat++; + break; + case 1: + if (IsNumber(dataread)) ivalue = atoi(dataread); + else { + fprintf(stderr, "Error at file: %s. Variable: %s can't have non integer value: %s.\n", filename, varname, dataread); + fclose(data); + free(varname); + free(dataread); + return -2; + } + idat++; + break; + case 2: + dynvalue = malloc(sizeof(char) * (strlen(dataread) + 1)); + strcpy(dynvalue, dataread); + break; + } + } + } + } else { + dataread[icur] = buf; + icur++; + if (icur == _maxbufsize) { + fprintf(stderr, "Error: Maximum buffer size(%i) exceeded.\n", _maxbufsize); + fclose(data); + free(varname); + free(dataread); + return -2; + } + while (icur > maxbufsize - 1) { + maxbufsize *= 2; + dataread = (char *) realloc(dataread, sizeof(char) * maxbufsize); + } + } + } + if (hasvar) { + for (index = 0; index < varmap.varcnt; index++) { + if ((varmap.vars[index] != NULL) && (patternmatch(varname, varmap.vars[index]))) { + varmap.loaded[index] = 1; + varmap.dvalue[index] = dvalue; + varmap.ivalue[index] = ivalue; + if (dynvalue != NULL) { + varmap.dynvalue[index] = (void *) malloc(sizeof(char) * (strlen(dynvalue) + 1)); + strcpy(varmap.dynvalue[index], dynvalue); + } + } + } + if (dynvalue != NULL) { + free(dynvalue); + dynvalue = NULL; + } + free(varname); + } + fclose(data); + free(dataread); + return 0; +} + +/* Queue for node storing to avoid loops */ + +hisqueue* InitHistory(int varcnt) { + int i; + hisqueue *HisQueue; + // fprintf(stderr,"init hisotry %i %i\n",__LINE__,varcnt+2); + HisQueue = (hisqueue *) malloc(sizeof(hisqueue) * (varcnt+2)); + for (i = 0; i < varcnt+2; i++) { + HisQueue[i].thenode = NULL; + HisQueue[i].cnt = 0; + } + return HisQueue; +} + +void ReInitHistory(hisqueue *HisQueue, int varcnt) { + int i, j; + for (i = 0; i < varcnt +2; i++) { + if (HisQueue[i].thenode != NULL && !Cudd_IsConstant(HisQueue[i].thenode)) { + for (j = 0; j < HisQueue[i].cnt; j++) + if (HisQueue[i].thenode[j].dynvalue != NULL) free(HisQueue[i].thenode[j].dynvalue); + free(HisQueue[i].thenode); + HisQueue[i].thenode = NULL; + } + HisQueue[i].cnt = 0; + } +} + +int my_index_calc(int varstart, DdNode *node){ + if(Cudd_IsConstant(node)){ + return Cudd_V(node); + }else{ + int index = GetIndex(node) - varstart+2; + return index; + } +} +void AddNode(hisqueue *HisQueue, int varstart, DdNode *node, double dvalue, int ivalue, void *dynvalue) { + // int index = GetIndex(node) - varstart; + // fprintf(stderr,"----- node added: %p <-> %i <-> %e\n",node,GetIndex(node),dvalue); + int index= my_index_calc(varstart,node); + HisQueue[index].thenode = (hisnode *) realloc(HisQueue[index].thenode, (HisQueue[index].cnt + 1+2/*account for t+f*/) * sizeof(hisnode)); + HisQueue[index].thenode[HisQueue[index].cnt].key = node; + HisQueue[index].thenode[HisQueue[index].cnt].dvalue = dvalue; + HisQueue[index].thenode[HisQueue[index].cnt].dvalue2 = -1; //keep backward compatibility + HisQueue[index].thenode[HisQueue[index].cnt].ivalue = ivalue; + HisQueue[index].thenode[HisQueue[index].cnt].dynvalue = dynvalue; + HisQueue[index].cnt += 1; +} + +hisnode* GetNode(hisqueue *HisQueue, int varstart, DdNode *node) { + // int index = GetIndex(node) - varstart; + int index= -1; + index=my_index_calc(varstart,node); + // fprintf(stderr,"----- node retuned: %p <-> %i <-> %i \n",node,GetIndex(node),index); + //TODO: this must be check think not initialzied. Null check fails? + // if (Cudd_IsConstant(node) ){ + // fprintf(stderr,"----- node retuned: %p <-> %i \n",node,GetIndex(node)); + // fprintf(stderr,"returning %p ,,,,, %e\n", &(HisQueue[index].thenode[index])); + // return &(HisQueue[index].thenode[0]);} + int i;//to bug check + for(i = 0; i < HisQueue[index].cnt; i++) { + if (HisQueue[index].thenode[i].key == node){ + // fprintf(stderr,"returning %p ....%e \n", &(HisQueue[index].thenode[i]),&(HisQueue[index].thenode[i]).dvalue); + return &(HisQueue[index].thenode[i]); + } + } + // fprintf(stderr,"returning null\n"); + return NULL; +} + +int GetNodeIndex(hisqueue *HisQueue, int varstart, DdNode *node) { + int i; + // int index = GetIndex(node) - varstart; + int index= my_index_calc(varstart,node); + if (Cudd_IsConstant(node) ){ return index;} + for(i = 0; i < HisQueue[index].cnt; i++) { + if (HisQueue[index].thenode[i].key == node) return i; + } + return -1; +} + +/* Named variables */ + +namedvars InitNamedVars(int varcnt, int varstart) { + namedvars temp; + int i; + temp.varcnt = varcnt; + temp.varstart = varstart; + temp.vars = (char **) malloc(sizeof(char *) * varcnt); + temp.loaded = (int *) malloc(sizeof(int) * varcnt); + temp.dvalue = (double *) malloc(sizeof(double) * varcnt); + temp.ivalue = (int *) malloc(sizeof(int) * varcnt); + temp.dynvalue = (void **) malloc(sizeof(void *) * varcnt); + for (i = 0; i < varcnt; i++) { + temp.vars[i] = NULL; + temp.loaded[i] = 0; + temp.dvalue[i] = 0.0; + temp.ivalue[i] = 0; + temp.dynvalue[i] = NULL; + } + return temp; +} + +void EnlargeNamedVars(namedvars *varmap, int newvarcnt) { + int i; + varmap->vars = (char **) realloc(varmap->vars, sizeof(char *) * newvarcnt); + varmap->loaded = (int *) realloc(varmap->loaded, sizeof(int) * newvarcnt); + varmap->dvalue = (double *) realloc(varmap->dvalue, sizeof(double) * newvarcnt); + varmap->ivalue = (int *) realloc(varmap->ivalue, sizeof(int) * newvarcnt); + varmap->dynvalue = (void **) realloc(varmap->dynvalue, sizeof(void *) * newvarcnt); + for (i = varmap->varcnt; i < newvarcnt; i++) { + varmap->vars[i] = NULL; + varmap->loaded[i] = 0; + varmap->dvalue[i] = 0.0; + varmap->ivalue[i] = 0; + varmap->dynvalue[i] = NULL; + } + varmap->varcnt = newvarcnt; +} + +int AddNamedVarAt(namedvars varmap, const char *varname, int index) { + if (varmap.varcnt > index) { + varmap.vars[index] = (char *) malloc(sizeof(char) * (strlen(varname) + 1)); + strcpy(varmap.vars[index], varname); + return index; + } + return -1; +} + +int AddNamedVar(namedvars varmap, const char *varname) { + int index = GetNamedVarIndex(varmap, varname); + if (index == -1 * varmap.varcnt) { + return -1; + } else if ((index < 0) || (index == 0 && varmap.vars[0] == NULL)) { + index *= -1; + varmap.vars[index] = (char *) malloc(sizeof(char) * (strlen(varname) + 1)); + strcpy(varmap.vars[index], varname); + } + return index; +} + +void SetNamedVarValuesAt(namedvars varmap, int index, double dvalue, int ivalue, void *dynvalue) { + varmap.dvalue[index] = dvalue; + varmap.ivalue[index] = ivalue; + varmap.dynvalue[index] = dynvalue; +} + +int SetNamedVarValues(namedvars varmap, const char *varname, double dvalue, int ivalue, void *dynvalue) { + int index = GetNamedVarIndex(varmap, varname); + if (index == -1 * varmap.varcnt) { + return -1; + } else if ((index < 0) || (index == 0 && varmap.vars[0] == NULL)) { + index *= -1; + varmap.vars[index] = (char *) malloc(sizeof(char) * (strlen(varname) + 1)); + strcpy(varmap.vars[index], varname); + varmap.dvalue[index] = dvalue; + varmap.ivalue[index] = ivalue; + varmap.dynvalue[index] = dynvalue; + } else { + varmap.dvalue[index] = dvalue; + varmap.ivalue[index] = ivalue; + varmap.dynvalue[index] = dynvalue; + } + return index; +} + +int GetNamedVarIndex(const namedvars varmap, const char *varname) { + int i; + for (i = 0; i < varmap.varcnt; i++) { + if (varmap.vars[i] == NULL) return -1 * i; + if (strcmp(varmap.vars[i], varname) == 0) return i; + } + return -1 * varmap.varcnt; +} + +char* GetNodeVarName(DdManager *manager, namedvars varmap, DdNode *node) { + if (node == NULL) return NULL; + if (node == HIGH(manager)) return "true"; + if (node == LOW(manager)) return "false"; + return varmap.vars[GetIndex(node) - varmap.varstart]; +} + +char* GetNodeVarNameDisp(DdManager *manager, namedvars varmap, DdNode *node) { + if (HIGH(manager) == node) return "TRUE"; + if (LOW(manager) == node) return "FALSE"; + if (NULL == node) return "(null)"; + return varmap.vars[GetIndex(node) - varmap.varstart]; +} + +int RepairVarcnt(namedvars *varmap) { + while (varmap->vars[varmap->varcnt - 1] == NULL && varmap->varcnt>0){ + varmap->varcnt--; + } + return varmap->varcnt; +} + +int all_loaded(namedvars varmap, int disp) { + int i, res = 1; + for (i = 0; i < varmap.varcnt; i++) { + if (varmap.loaded[i] == 0) { + res = 0; + if (disp) fprintf(stderr, "The variable: %s was not loaded with values.\n", varmap.vars[i]); else return 0; + } + } + return res; +} + +int all_loaded_for_deterministic_variables(namedvars varmap, int disp) { + int i; + char * dummy; + for (i = 0; i < varmap.varcnt; i++) { + if (varmap.loaded[i] == 0) { + // no value specified, make it a deterministic variable + varmap.loaded[i]=1; + varmap.dvalue[i]=1.0; + varmap.ivalue[i]=0; + dummy = malloc(0); + varmap.dynvalue[i]=dummy; + // if (disp) fprintf(stderr, "The variable: %s was not loaded with values.\n", varmap.vars[i]); else return 0; + } + } + return 1; +} + +int ImposeOrder(DdManager *manager, const namedvars varmap, char **map) { + int order[varmap.varcnt], i, mappos, index = -1, ivar; + for (i = 0; i < varmap.varcnt; i++) { + if (map[i] != NULL) { + order[i] = GetNamedVarIndex(varmap, map[i]); + index = i; + } else { + order[i] = -1; + } + } + index++; + for (i = 0; i < varmap.varcnt; i++) { + ivar = Cudd_ReadPerm(manager, i); + mappos = get_var_pos_in_map(map, varmap.vars[ivar], varmap.varcnt); + if (mappos == -1) { + order[index] = ivar; + index++; + } + } + if (index != varmap.varcnt) + fprintf(stderr, "Warning possible error in: Impose Order...\n"); + return Cudd_ShuffleHeap(manager, order); +} + +int get_var_pos_in_map(char **map, const char *var, int varcnt) { + int i; + for (i = 0; i < varcnt; i++) { + if (map[i] == NULL) return -1; + if (strcmp(map[i], var) == 0) return i; + } + return -1; +} + +/* Parser */ + +DdNode* FileGenerateBDD(DdManager *manager, namedvars varmap, bddfileheader fileheader) { + return (FileGenerateBDDForest(manager, varmap, fileheader))[0]; +} + +DdNode** FileGenerateBDDForest(DdManager *manager, namedvars varmap, bddfileheader fileheader) { + int icomment, maxlinesize, icur, iline, curinter, iequal; + DdNode *Line, **inter, **result; + char buf, *inputline, *filename, *subl; + bddfileheader interfileheader; + // Initialization of intermediate steps + inter = (DdNode **) malloc(sizeof(DdNode *) * fileheader.intercnt); + for (icur = 0; icur < fileheader.intercnt; icur++) inter[icur] = NULL; + // Read file data + interfileheader.inputfile = NULL; + filename = NULL; // For nested files + iequal = 0; // Flag for encountered = sign + icur = 0; // Pointer for inputline buffer location + iline = 5; // Current file line (first after header) + icomment = 0; // Flag for comments + maxlinesize = 80; // inputline starting buffer size + inputline = (char *) malloc(sizeof(char) * maxlinesize); + while(!feof(fileheader.inputfile)) { + fread(&buf, 1, 1, fileheader.inputfile); + if (buf == ';' || buf == '%' || buf == '$') icomment = 1; + if (buf == '\n') { + if (icomment) icomment = 0; + if (iequal > 1) { + fprintf(stderr, "Error at line: %i. Line contains more than 1 equal(=) signs.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } else iequal = 0; + if (icur > 0) { + inputline[icur] = '\0'; + if (inputline[0] != 'L') { + fprintf(stderr, "Error at line: %i. Intermediate results should start with L.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } + curinter = getInterBDD(inputline); + if (curinter == -1) { + if (fileheader.version < 2) { + if (inputline[0] == 'L' && IsPosNumber(inputline + 1)) { + curinter = atoi(inputline + 1) - 1; + if (curinter > -1 && curinter < fileheader.intercnt && inter[curinter] != NULL) { + if (_debug) fprintf(stderr, "Returned: %s\n", inputline); + fclose(fileheader.inputfile); + result = (DdNode **) malloc(sizeof(DdNode *) * 1); + result[0] = inter[curinter]; + free(inter); + free(inputline); + return result; + } else { + fprintf(stderr, "Error at line: %i. Return result asked doesn't exist.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } + } else { + fprintf(stderr, "Error at line: %i. Invalid intermediate result format.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } + } else { + // Support for forest + result = (DdNode **) malloc(sizeof(DdNode *) * 10); + maxlinesize = 10; + iline = -1; + for (subl = strtok(inputline, ","); subl != NULL; subl = strtok(NULL, ",")) { + if (subl[0] == 'L' && IsPosNumber(subl + 1)) { + curinter = atoi(subl + 1) - 1; + if (curinter > -1 && curinter < fileheader.intercnt && inter[curinter] != NULL) { + iline++; + if (iline >= (maxlinesize - 1)) { + maxlinesize *= 2; + result = (DdNode **) realloc(result, sizeof(DdNode *) * maxlinesize); + } + result[iline] = inter[curinter]; + } else { + fprintf(stderr, "Error at line: %i. Return result asked(%s) doesn't exist.\n", iline, subl); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + free(subl); + return NULL; + } + } else { + fprintf(stderr, "Error at line: %i. Invalid intermediate result format.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + free(subl); + return NULL; + } + } + if (_debug) fprintf(stderr, "Returned: %s\n", inputline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + free(subl); + iline++; + result[iline] = NULL; + return result; + } + } else if (curinter > -1 && curinter < fileheader.intercnt && inter[curinter] == NULL) { + if (_debug) fprintf(stderr, "%i %s\n", curinter, inputline); + filename = getFileName(inputline); + if (filename == NULL) { + Line = LineParser(manager, varmap, inter, fileheader.intercnt, inputline, iline); + } else { + interfileheader = ReadFileHeader(filename); + if (interfileheader.inputfile == NULL) { + //Line = simpleBDDload(manager, &varmap, filename); + Line = NULL; + } else { + Line = FileGenerateBDD(manager, varmap, interfileheader); + } + if (Line == NULL) fprintf(stderr, "Error at line: %i. Error in nested BDD file: %s.\n", iline, filename); + free(filename); + filename = NULL; + interfileheader.inputfile = NULL; + } + if (Line == NULL) { + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } + inter[curinter] = Line; + icur = 0; + } else if (curinter > -1 && curinter < fileheader.intercnt && inter[curinter] != NULL) { + fprintf(stderr, "Error at line: %i. Intermediate results can't be overwritten.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } else { + fprintf(stderr, "Error at line: %i. Intermediate result asked doesn't exist.\n", iline); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } + } + iline++; + } else if (buf != ' ' && buf != '\t' && !icomment) { + if (buf == '=') iequal++; + inputline[icur] = buf; + icur += 1; + if (icur == _maxbufsize) { + fprintf(stderr, "Error: Maximum buffer size(%i) exceeded.\n", _maxbufsize); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; + } + while (icur > maxlinesize - 1) { + maxlinesize *= 2; + inputline = (char *) realloc(inputline, sizeof(char) * maxlinesize); + } + } + } + fprintf(stderr, "Error, file either doesn't end with a blank line or no return result was asked.\n"); + fclose(fileheader.inputfile); + free(inter); + free(inputline); + return NULL; +} + +int getInterBDD(char *function) { + int i, ret; + char *inter; + for (i = 0; i < strlen(function); i++) { + if (function[i] == '=') { + inter = (char *) malloc(sizeof(char) * i); + strncpy(inter, function + 1, i - 1); + inter[i - 1] = '\0'; + if (IsPosNumber(inter)) { + ret = atoi(inter) - 1; + free(inter); + return ret; + } else { + free(inter); + return -1; + } + } + } + return -1; +} + +char* getFileName(const char *function) { + int i = 0; + char *filename; + while(function[i] != '=' && (i + 1) < strlen(function)) i++; + if ((i + 1) < strlen(function)) { + i++; + if (function[i] == '<' && function[strlen(function) - 1] == '>') { + filename = (char *) malloc(sizeof(char) * strlen(function) - i); + strcpy(filename, function + i + 1); + filename[strlen(function) - i - 2] = '\0'; + return filename; + } + } + return NULL; +} + +DdNode* LineParser(DdManager *manager, namedvars varmap, DdNode **inter, int maxinter, char *function, int iline) { + int istart, iend, ilength, i, symbol, ivar, inegvar, inegoper, iconst; + long startAt, endAt; + double secs; + DdNode *bdd; + char *term, curoper; + bdd = HIGH(manager); + Cudd_Ref(bdd); + term = NULL; + ivar = -1; + curoper = '*'; + istart = -1; + iend = strlen(function) - 1; + ilength = -1; + symbol = -1; + inegvar = 0; + inegoper = 0; + iconst = 0; + for (i = strlen(function) - 1; i > -1; i--) { + if (symbol == -1 && isOperator(function[i])) { + symbol = i; + istart = i + 1; + ilength = iend - i; + iend = i - 1; + if (ilength > 0 && !(ilength == 1 && function[istart] == '~')) { + term = (char *) malloc(sizeof(char) * (ilength + 1)); + strncpy(term, function + istart, ilength); + term[ilength] = '\0'; + } else { + fprintf(stderr, "Line Parser Error at line: %i. An operator was encounter with no term at its right side.\n", iline); + free(term); + return NULL; + } + } + if (symbol != -1) { + if (term[0] == '~') inegvar = 1; else inegvar = 0; + if (term[0 + inegvar] != 'L') { + // Term is a variable + if (strcmp(term + inegvar, "TRUE") == 0) { + iconst = 1; + } else if (strcmp(term + inegvar, "FALSE") == 0) { + iconst = 1; + inegvar = 1; + } else { + iconst = 0; + ivar = AddNamedVar(varmap, term + inegvar); + if (ivar == -1) { + fprintf(stderr, "Line Parser Error at line: %i. More BDD variables than the reserved term: %s.\n", iline, term); + free(term); + return NULL; + } + } + if (_debug) fprintf(stderr, "%s\n", term); + if (_debug && !iconst) fprintf(stderr, "PNZ1:%.0f P1:%.0f S1:%i PNZ2:%.0f P2:%.0f S2:%i\n", + Cudd_CountPathsToNonZero(bdd), + Cudd_CountPath(bdd), + Cudd_DagSize(bdd), + Cudd_CountPathsToNonZero(GetVar(manager, ivar + varmap.varstart)), + Cudd_CountPath(GetVar(manager, ivar + varmap.varstart)), + Cudd_DagSize(GetVar(manager, ivar + varmap.varstart)) ); + startAt = clock(); + if (!iconst) { + if (inegvar) bdd = BDD_Operator(manager, NOT(GetVar(manager, ivar + varmap.varstart)), bdd, curoper, inegoper); + else bdd = BDD_Operator(manager, GetVar(manager, ivar + varmap.varstart), bdd, curoper, inegoper); + } else { + switch(curoper) { + case '+': + if (inegvar ^ inegoper) ; else { + bdd = HIGH(manager); + Cudd_Ref(bdd); + } + break; + case '*': + if (inegvar ^ inegoper) { + bdd = LOW(manager); + Cudd_Ref(bdd); + } + break; + case '#': + if (inegvar ^ inegoper) ; else bdd = NOT(bdd); + break; + } + } + endAt = clock(); + secs = ((double) (endAt - startAt)) / ((double) CLOCKS_PER_SEC); + if (_debug) fprintf(stderr, "term: %s of line: %i took: %ld\n", term, iline, endAt - startAt); + //if ((endAt - startAt) > 10000000) Cudd_AutodynDisable(manager); + if (bdd == NULL) { + fprintf(stderr, "Line Parser Error at line: %i. Error using operator %c on term: %s.\n", iline, curoper, term); + free(term); + return NULL; + } + } else { + // Term is an intermediate result + if (IsPosNumber(term + inegvar + 1)) ivar = atoi(term + inegvar + 1) - 1; else { + fprintf(stderr, "Line Parser Error at line: %i. Invalid intermediate result format term: %s.\n", iline, term); + free(term); + return NULL; + } + if (ivar < 0 || ivar > maxinter || inter[ivar] == NULL) { + fprintf(stderr, "Line Parser Error at line: %i. Usage of undeclared intermediate result term: %s.\n", iline, term); + free(term); + return NULL; + } + if (_debug) fprintf(stderr, "%s\n", term); + if (_debug) fprintf(stderr, "PNZ1:%.0f P1:%.0f S1:%i PNZ2:%.0f P2:%.0f S2:%i\n", + Cudd_CountPathsToNonZero(bdd), + Cudd_CountPath(bdd), + Cudd_DagSize(bdd), + Cudd_CountPathsToNonZero(inter[ivar]), + Cudd_CountPath(inter[ivar]), + Cudd_DagSize(inter[ivar]) ); + startAt = clock(); + if (inegvar) bdd = BDD_Operator(manager, NOT(inter[ivar]), bdd, curoper, inegoper); + else bdd = BDD_Operator(manager, inter[ivar], bdd, curoper, inegoper); + endAt = clock(); + secs = ((double) (endAt - startAt)) / ((double) CLOCKS_PER_SEC); + if (_debug) fprintf(stderr, "term: %s of line: %i took: %ld\n", term, iline, endAt - startAt); + //if ((endAt - startAt) > 10000000) Cudd_AutodynDisable(manager); + if (bdd == NULL) { + fprintf(stderr, "Line Parser Error at line: %i. Error using operator %c on term: %s.\n", iline, curoper, term); + free(term); + return NULL; + } + } + free(term); + term = NULL; + curoper = function[symbol]; + if (curoper == '=') return bdd; + if (function[symbol - 1] == '~') { + inegoper = 1; + i--; + iend--; + } else { + inegoper = 0; + } + symbol = -1; + } + } + return NULL; +} + +DdNode* BDD_Operator(DdManager *manager, DdNode *bdd1, DdNode *bdd2, char Operator, int inegoper) { + switch (Operator) { + case '+': + if (inegoper) return D_BDDNor(manager, bdd1, bdd2); + else return D_BDDOr(manager, bdd1, bdd2); + break; + case '*': + if (inegoper) return D_BDDNand(manager, bdd1, bdd2); + else return D_BDDAnd(manager, bdd1, bdd2); + break; + case '#': + if (inegoper) return D_BDDXnor(manager, bdd1, bdd2); + else return D_BDDXor(manager, bdd1, bdd2); + break; + default: + return NULL; + break; + } +} + +DdNode* OnlineGenerateBDD(DdManager *manager, namedvars *varmap) { + int icomment, maxlinesize, icur, iline, curinter, iequal, iinters, itmp, i; + DdNode *Line, **inter; + char buf, *inputline, *filename; + bddfileheader interfileheader; + // Initialization of intermediate steps + iinters = 1; + inter = (DdNode **) malloc(sizeof(DdNode *) * iinters); + for (icur = 0; icur < iinters; icur++) inter[icur] = NULL; + // Read file data + interfileheader.inputfile = NULL; + filename = NULL; // For nested files + iequal = 0; // Flag for encountered = sign + icur = 0; // Pointer for inputline buffer location + iline = 1; // Current file line (first after header) + icomment = 0; // Flag for comments + maxlinesize = 80; // inputline starting buffer size + inputline = (char *) malloc(sizeof(char) * maxlinesize); + + do { + buf = fgetc(stdin); + if (buf == ';' || buf == '%' || buf == '$') icomment = 1; + if (buf == '\n') { + if (icomment) icomment = 0; + if (iequal > 1) { + fprintf(stderr, "Error at line: %i. Line contains more than 1 equal(=) signs.\n", iline); + free(inter); + free(inputline); + return NULL; + } else iequal = 0; + if (icur > 0) { + inputline[icur] = '\0'; + if (inputline[0] == '@') { + if (inputline[1] == 'e') { + free(inter); + free(inputline); + exit(0); + } else { + itmp = GetParam(inputline, 1); + if (itmp > varmap->varcnt) + EnlargeNamedVars(varmap, itmp); + itmp = GetParam(inputline, 2); + if (itmp > iinters) { + inter = (DdNode **) realloc(inter, sizeof(DdNode *) * itmp); + for (i = iinters; i < itmp; i++) inter[i] = NULL; + iinters = itmp; + } + } + icur = 0; + } else { + if (inputline[0] != 'L') { + fprintf(stderr, "Error at line: %i. Intermediate results should start with L.\n", iline); + free(inter); + free(inputline); + return NULL; + } + curinter = getInterBDD(inputline); + if (curinter == -1) { + if (inputline[0] == 'L' && IsPosNumber(inputline + 1)) { + curinter = atoi(inputline + 1) - 1; + if (curinter > -1 && curinter < iinters && inter[curinter] != NULL) { + if (_debug) fprintf(stderr, "Returned: %s\n", inputline); + Line = inter[curinter]; + free(inter); + free(inputline); + return Line; + } else { + fprintf(stderr, "Error at line: %i. Return result asked doesn't exist.\n", iline); + free(inter); + free(inputline); + return NULL; + } + } else { + fprintf(stderr, "Error at line: %i. Invalid intermediate result format.\n", iline); + free(inter); + free(inputline); + return NULL; + } + } else if (curinter > -1) { + if (curinter >= iinters) { + inter = (DdNode **) realloc(inter, sizeof(DdNode *) * (curinter + 1)); + for (i = iinters; i < curinter + 1; i++) inter[i] = NULL; + iinters = curinter + 1; + } + if (inter[curinter] == NULL) { + if (_debug) fprintf(stderr, "%i %s\n", curinter, inputline); + filename = getFileName(inputline); + if (filename == NULL) { + Line = OnlineLineParser(manager, varmap, inter, iinters, inputline, iline); + } else { + interfileheader = ReadFileHeader(filename); + if (interfileheader.inputfile == NULL) { + //Line = simpleBDDload(manager, varmap, filename); + Line = NULL; + } else { + Line = FileGenerateBDD(manager, *varmap, interfileheader); + } + if (Line == NULL) fprintf(stderr, "Error at line: %i. Error in nested BDD file: %s.\n", iline, filename); + free(filename); + filename = NULL; + interfileheader.inputfile = NULL; + } + if (Line == NULL) { + free(inter); + free(inputline); + return NULL; + } + inter[curinter] = Line; + icur = 0; + } else if (inter[curinter] != NULL) { + fprintf(stderr, "Error at line: %i. Intermediate results can't be overwritten.\n", iline); + free(inter); + free(inputline); + return NULL; + } + } else { + fprintf(stderr, "Error at line: %i. Intermediate result asked doesn't exist.\n", iline); + free(inter); + free(inputline); + return NULL; + } + } + } + iline++; + } else if (buf != ' ' && buf != '\t' && !icomment) { + if (buf == '=') iequal++; + inputline[icur] = buf; + icur += 1; + if (icur == _maxbufsize) { + fprintf(stderr, "Error: Maximum buffer size(%i) exceeded.\n", _maxbufsize); + free(inter); + free(inputline); + return NULL; + } + while (icur > maxlinesize - 1) { + maxlinesize *= 2; + inputline = (char *) realloc(inputline, sizeof(char) * maxlinesize); + } + } + } while(1); + fprintf(stderr, "Error, file either doesn't end with a blank line or no return result was asked.\n"); + free(inter); + free(inputline); + return NULL; +} + +DdNode* OnlineLineParser(DdManager *manager, namedvars *varmap, DdNode **inter, int maxinter, char *function, int iline) { + int istart, iend, ilength, i, symbol, ivar, inegvar, inegoper, iconst; + long startAt, endAt; + double secs; + DdNode *bdd; + char *term, curoper; + bdd = HIGH(manager); + Cudd_Ref(bdd); + term = NULL; + ivar = -1; + curoper = '*'; + istart = -1; + iend = strlen(function) - 1; + ilength = -1; + symbol = -1; + inegvar = 0; + inegoper = 0; + iconst = 0; + for (i = strlen(function) - 1; i > -1; i--) { + if (symbol == -1 && isOperator(function[i])) { + symbol = i; + istart = i + 1; + ilength = iend - i; + iend = i - 1; + if (ilength > 0 && !(ilength == 1 && function[istart] == '~')) { + term = (char *) malloc(sizeof(char) * (ilength + 1)); + strncpy(term, function + istart, ilength); + term[ilength] = '\0'; + } else { + fprintf(stderr, "Line Parser Error at line: %i. An operator was encounter with no term at its right side.\n", iline); + free(term); + return NULL; + } + } + if (symbol != -1) { + if (term[0] == '~') inegvar = 1; else inegvar = 0; + if (term[0 + inegvar] != 'L') { + // Term is a variable + if (strcmp(term + inegvar, "TRUE") == 0) { + iconst = 1; + } else if (strcmp(term + inegvar, "FALSE") == 0) { + iconst = 1; + inegvar = 1; + } else { + iconst = 0; + ivar = AddNamedVar(*varmap, term + inegvar); + if (ivar == -1) { + EnlargeNamedVars(varmap, varmap->varcnt + 1); + ivar = AddNamedVar(*varmap, term + inegvar); + } + if (ivar == -1) { + fprintf(stderr, "Line Parser Error at line: %i. More BDD variables than the reserved term: %s.\n", iline, term); + free(term); + return NULL; + } + } + if (_debug) fprintf(stderr, "%s\n", term); + if (_debug && !iconst) fprintf(stderr, "PNZ1:%.0f P1:%.0f S1:%i PNZ2:%.0f P2:%.0f S2:%i\n", + Cudd_CountPathsToNonZero(bdd), + Cudd_CountPath(bdd), + Cudd_DagSize(bdd), + Cudd_CountPathsToNonZero(GetVar(manager, ivar + varmap->varstart)), + Cudd_CountPath(GetVar(manager, ivar + varmap->varstart)), + Cudd_DagSize(GetVar(manager, ivar + varmap->varstart)) ); + startAt = clock(); + if (!iconst) { + if (inegvar) bdd = BDD_Operator(manager, NOT(GetVar(manager, ivar + varmap->varstart)), bdd, curoper, inegoper); + else bdd = BDD_Operator(manager, GetVar(manager, ivar + varmap->varstart), bdd, curoper, inegoper); + } else { + switch(curoper) { + case '+': + if (inegvar ^ inegoper) ; else { + bdd = HIGH(manager); + Cudd_Ref(bdd); + } + break; + case '*': + if (inegvar ^ inegoper) { + bdd = LOW(manager); + Cudd_Ref(bdd); + } + break; + case '#': + if (inegvar ^ inegoper) ; else bdd = NOT(bdd); + break; + } + } + endAt = clock(); + secs = ((double) (endAt - startAt)) / ((double) CLOCKS_PER_SEC); + if (_debug) fprintf(stderr, "term: %s of line: %i took: %ld\n", term, iline, endAt - startAt); + //if ((endAt - startAt) > 10000000) Cudd_AutodynDisable(manager); + if (bdd == NULL) { + fprintf(stderr, "Line Parser Error at line: %i. Error using operator %c on term: %s.\n", iline, curoper, term); + free(term); + return NULL; + } + } else { + // Term is an intermediate result + if (IsPosNumber(term + inegvar + 1)) ivar = atoi(term + inegvar + 1) - 1; else { + fprintf(stderr, "Line Parser Error at line: %i. Invalid intermediate result format term: %s.\n", iline, term); + free(term); + return NULL; + } + if (ivar < 0 || ivar > maxinter || inter[ivar] == NULL) { + fprintf(stderr, "Line Parser Error at line: %i. Usage of undeclared intermediate result term: %s.\n", iline, term); + free(term); + return NULL; + } + if (_debug) fprintf(stderr, "%s\n", term); + if (_debug) fprintf(stderr, "PNZ1:%.0f P1:%.0f S1:%i PNZ2:%.0f P2:%.0f S2:%i\n", + Cudd_CountPathsToNonZero(bdd), + Cudd_CountPath(bdd), + Cudd_DagSize(bdd), + Cudd_CountPathsToNonZero(inter[ivar]), + Cudd_CountPath(inter[ivar]), + Cudd_DagSize(inter[ivar]) ); + startAt = clock(); + if (inegvar) bdd = BDD_Operator(manager, NOT(inter[ivar]), bdd, curoper, inegoper); + else bdd = BDD_Operator(manager, inter[ivar], bdd, curoper, inegoper); + endAt = clock(); + secs = ((double) (endAt - startAt)) / ((double) CLOCKS_PER_SEC); + if (_debug) fprintf(stderr, "term: %s of line: %i took: %ld\n", term, iline, endAt - startAt); + //if ((endAt - startAt) > 10000000) Cudd_AutodynDisable(manager); + if (bdd == NULL) { + fprintf(stderr, "Line Parser Error at line: %i. Error using operator %c on term: %s.\n", iline, curoper, term); + free(term); + return NULL; + } + } + free(term); + term = NULL; + curoper = function[symbol]; + if (curoper == '=') return bdd; + if (function[symbol - 1] == '~') { + inegoper = 1; + i--; + iend--; + } else { + inegoper = 0; + } + symbol = -1; + } + } + return NULL; +} + +int GetParam(char *inputline, int iParam) { + int icoma, istart, iend, ret; + char *numb; + istart = 1; + icoma = istart; + iend = strlen(inputline); + while((inputline[icoma] != ',') && (icoma < iend)) + icoma++; + if (iParam == 1) { + numb = (char *) malloc(sizeof(char) * icoma); + strncpy(numb, inputline + 1, icoma - 1); + numb[icoma - 1] = '\0'; + if (IsPosNumber(numb)) { + ret = atoi(numb); + free(numb); + return ret; + } + } else if(iParam == 2) { + numb = (char *) malloc(sizeof(char) * (iend - icoma + 1)); + strncpy(numb, inputline + icoma + 1, iend - icoma); + numb[iend - icoma] = '\0'; + if (IsPosNumber(numb)) { + ret = atoi(numb); + free(numb); + return ret; + } + } + return 0; +} + +void onlinetraverse(DdManager *manager, namedvars varmap, hisqueue *HisQueue, DdNode *bdd) { + char buf, *inputline; + int icur, maxlinesize, iline, index, iloop, ivalue, iQsize, i, inQ, iRoot; + double dvalue; + DdNode **Q, **Q2, *h_node, *l_node, *curnode; + hisqueue *his; + hisnode *hnode; + iloop = 1; + icur = 0; // Pointer for inputline buffer location + iline = 1; // Current file line (first after header) + maxlinesize = 80; // inputline starting buffer size + inputline = (char *) malloc(sizeof(char) * maxlinesize); + curnode = bdd; + iQsize = 0; + iRoot = 1; + Q = (DdNode **) malloc(sizeof(DdNode *) * iQsize); + Q2 = NULL; + his = InitHistory(varmap.varcnt); + do { + buf = fgetc(stdin); + if (buf == '\n') { + inputline[icur] = '\0'; + if ((icur > 0) && (inputline[0] == '@') && (inputline[2] == ',' || inputline[2] == '\0')) { + switch(inputline[1]) { + case 'c': + if (iRoot) { + iRoot = 0; + printf("bdd_temp_value('%s', %i).\n", GetNodeVarNameDisp(manager, varmap, curnode), 1); + } else { + printf("bdd_temp_value('%s', %i).\n", GetNodeVarNameDisp(manager, varmap, curnode), iQsize); + } + fflush(stdout); + break; + case 'n': + if (curnode != HIGH(manager) && curnode != LOW(manager) && (hnode = GetNode(his, varmap.varstart, curnode)) == NULL) { + //AddNode(his, varmap.varstart, curnode, 0.0, 0, NULL); + l_node = LowNodeOf(manager, curnode); + h_node = HighNodeOf(manager, curnode); + inQ = 0; + for(i = 0; (i < iQsize / 2) && (inQ < 3); i++) + inQ = (Q[i] == l_node) || (Q[iQsize - i] == l_node) + 2 * (Q[i] == h_node) || (Q[iQsize - i] == h_node); + if (inQ & 1 == 0) inQ = inQ + (GetNode(his, varmap.varstart, l_node) != NULL); + if (inQ & 2 == 0) inQ = inQ + 2 * (GetNode(his, varmap.varstart, h_node) != NULL); + if (inQ & 1 == 1) inQ = inQ - (l_node == HIGH(manager) || l_node == LOW(manager)); + if (inQ & 2 == 2) inQ = inQ - 2 * (h_node == HIGH(manager) || h_node == LOW(manager)); + inQ = 0; + switch(inQ) { + case 0: + iQsize += 2; + Q = (DdNode **) realloc(Q, sizeof(DdNode *) * iQsize); + Q[iQsize - 2] = l_node; + Q[iQsize - 1] = h_node; + break; + case 1: + iQsize++; + Q = (DdNode **) realloc(Q, sizeof(DdNode *) * iQsize); + Q[iQsize - 1] = h_node; + break; + case 2: + iQsize++; + Q = (DdNode **) realloc(Q, sizeof(DdNode *) * iQsize); + Q[iQsize - 1] = l_node; + break; + case 3: + break; + default: + break; + } + } + if (inputline[2] == '\0' || strcmp(inputline + 3, "DFS") == 0) { + if (iQsize > 0) { + iQsize--; + curnode = Q[iQsize]; + Q = (DdNode **) realloc(Q, sizeof(DdNode *) * iQsize); + } + } else if (strcmp(inputline + 3, "BFS") == 0) { + if (iQsize > 0) { + iQsize--; + curnode = Q[0]; + Q2 = (DdNode **) malloc(sizeof(DdNode *) * iQsize); + for(i = 0; i < iQsize; i++) + Q2[i] = Q[i + 1]; + free(Q); + Q = Q2; + } + } else { + fprintf(stderr, "Error: Could not find method: %s, Correct syntax @n,[DFS, BFS].\n", inputline + 3); + free(Q); + free(inputline); + exit(-1); + } + break; + case 'h': + printf("bdd_temp_value('%s').\n", GetNodeVarNameDisp(manager, varmap, HighNodeOf(manager, curnode))); + fflush(stdout); + break; + case 'l': + printf("bdd_temp_value('%s').\n", GetNodeVarNameDisp(manager, varmap, LowNodeOf(manager, curnode))); + fflush(stdout); + break; + case 'v': + index = GetNamedVarIndex(varmap, inputline + 3); + if (index >= 0) { + printf("bdd_temp_value([%f,%i,%s]).\n", varmap.dvalue[index], varmap.ivalue[index], (char *) varmap.dynvalue[index]); + fflush(stdout); + } else { + fprintf(stderr, "Error: Could not find variable: %s, Correct syntax @v,[variable name].\n", inputline + 3); + free(Q); + free(inputline); + exit(-1); + } + break; + case 'e': + iloop = 0; + break; + default: + fprintf(stderr, "Error: Not recognizable instruction: %s.\n", inputline); + free(Q); + free(inputline); + exit(-1); + break; + } + icur = 0; + } else { + fprintf(stderr, "Error: Not recognizable instruction: %s.\n", inputline); + free(Q); + free(inputline); + exit(-1); + } + iline++; + } else if (buf != ' ' && buf != '\t') { + inputline[icur] = buf; + icur += 1; + if (icur == _maxbufsize) { + fprintf(stderr, "Error: Maximum buffer size(%i) exceeded.\n", _maxbufsize); + free(Q); + free(inputline); + exit(-1); + } + while (icur > maxlinesize - 1) { + maxlinesize *= 2; + inputline = (char *) realloc(inputline, sizeof(char) * maxlinesize); + } + } + } while(iloop); + free(Q); + free(inputline); +} diff --git a/packages/ProbLog/simplecudd_lfi/simplecudd.h b/packages/ProbLog/simplecudd_lfi/simplecudd.h new file mode 100644 index 000000000..3ba29f3d9 --- /dev/null +++ b/packages/ProbLog/simplecudd_lfi/simplecudd.h @@ -0,0 +1,339 @@ +/******************************************************************************\ +* * +* SimpleCUDD library (www.cs.kuleuven.be/~theo/tools/simplecudd.html) * +* SimpleCUDD was developed at Katholieke Universiteit Leuven(www.kuleuven.be) * +* * +* Copyright Katholieke Universiteit Leuven 2008 * +* * +* Author: Theofrastos Mantadelis * +* File: simplecudd.h * +* * +******************************************************************************** +* * +* 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. * +* * +* The End * +* * +\******************************************************************************/ + + +#include +#include +#include +#include +#include +#include "pqueue.h" +#include "util.h" +#include "cudd.h" +#include "cuddInt.h" +#include "general.h" + +#define IsHigh(manager, node) HIGH(manager) == node +#define IsLow(manager, node) LOW(manager) == node +#define HIGH(manager) Cudd_ReadOne(manager) +#define LOW(manager) Cudd_Not(Cudd_ReadOne(manager)) +#define NOT(node) Cudd_Not(node) +#define GetIndex(node) Cudd_NodeReadIndex(node) +#define GetOrder(manager, node) Cudd_ReadPerm(manager, GetIndex(node)) +#define GetVar(manager, index) Cudd_bddIthVar(manager, index) +#define NewVar(manager) Cudd_bddNewVar(manager) +#define KillBDD(manager) Cudd_Quit(manager) +#define GetVarCount(manager) Cudd_ReadSize(manager) +#define DEBUGON _debug = 1 +#define DEBUGOFF _debug = 0 +#define RAPIDLOADON _RapidLoad = 1 +#define RAPIDLOADOFF _RapidLoad = 0 +#define SETMAXBUFSIZE(size) _maxbufsize = size +#define BDDFILE_ERROR -1 +#define BDDFILE_OTHER 0 +#define BDDFILE_SCRIPT 1 +#define BDDFILE_NODEDUMP 2 + +extern int _RapidLoad; +extern int _debug; +extern int _maxbufsize; + +typedef struct _bddfileheader { + FILE *inputfile; + int version; + int varcnt; + int varstart; + int intercnt; + int filetype; +} bddfileheader; + +typedef struct _namedvars { + int varcnt; + int varstart; + char **vars; + int *loaded; + double *dvalue; + int *ivalue; + void **dynvalue; +} namedvars; + +/** Custom struct to store a DdNode with assigned values */ +/** semantics of values depends on algorithm used */ +typedef struct _hisnode { + DdNode *key; + double dvalue; + double dvalue2;// =0; //needed for expected counts + int ivalue; + void *dynvalue; +} hisnode; + +typedef struct _hisqueue { + int cnt; + hisnode *thenode; +} hisqueue; + +typedef struct _nodeline { + char *varname; + char *truevar; + char *falsevar; + int nodenum; + int truenode; + int falsenode; +} nodeline; + +/* Initialization */ + +DdManager* simpleBDDinit(int varcnt); + +/* BDD Generation */ + +DdNode* D_BDDAnd(DdManager *manager, DdNode *bdd1, DdNode *bdd2); +DdNode* D_BDDNand(DdManager *manager, DdNode *bdd1, DdNode *bdd2); +DdNode* D_BDDOr(DdManager *manager, DdNode *bdd1, DdNode *bdd2); +DdNode* D_BDDNor(DdManager *manager, DdNode *bdd1, DdNode *bdd2); +DdNode* D_BDDXor(DdManager *manager, DdNode *bdd1, DdNode *bdd2); +DdNode* D_BDDXnor(DdManager *manager, DdNode *bdd1, DdNode *bdd2); + +DdNode* FileGenerateBDD(DdManager *manager, namedvars varmap, bddfileheader fileheader); +DdNode** FileGenerateBDDForest(DdManager *manager, namedvars varmap, bddfileheader fileheader); +DdNode* OnlineGenerateBDD(DdManager *manager, namedvars *varmap); +DdNode* LineParser(DdManager *manager, namedvars varmap, DdNode **inter, int maxinter, char *function, int iline); +DdNode* OnlineLineParser(DdManager *manager, namedvars *varmap, DdNode **inter, int maxinter, char *function, int iline); +DdNode* BDD_Operator(DdManager *manager, DdNode *bdd1, DdNode *bdd2, char Operator, int inegoper); +int getInterBDD(char *function); +char* getFileName(const char *function); +int GetParam(char *inputline, int iParam); +char** GetVariableOrder(char *filename, int varcnt); +int LoadVariableData(namedvars varmap, char *filename); + +/* Named variables */ + +int ImposeOrder(DdManager *manager, const namedvars varmap, char **map); +int get_var_pos_in_map(char **map, const char *var, int varcnt); +namedvars InitNamedVars(int varcnt, int varstart); +void EnlargeNamedVars(namedvars *varmap, int newvarcnt); +int AddNamedVarAt(namedvars varmap, const char *varname, int index); +int AddNamedVar(namedvars varmap, const char *varname); +void SetNamedVarValuesAt(namedvars varmap, int index, double dvalue, int ivalue, void *dynvalue); +int SetNamedVarValues(namedvars varmap, const char *varname, double dvalue, int ivalue, void *dynvalue); +int GetNamedVarIndex(const namedvars varmap, const char *varname); +int RepairVarcnt(namedvars *varmap); +char* GetNodeVarName(DdManager *manager, namedvars varmap, DdNode *node); +char* GetNodeVarNameDisp(DdManager *manager, namedvars varmap, DdNode *node); +int all_loaded(namedvars varmap, int disp); + +/* Traversal */ + +DdNode* HighNodeOf(DdManager *manager, DdNode *node); +DdNode* LowNodeOf(DdManager *manager, DdNode *node); + +/* Traversal - History */ + +hisqueue* InitHistory(int varcnt); +void ReInitHistory(hisqueue *HisQueue, int varcnt); +void AddNode(hisqueue *HisQueue, int varstart, DdNode *node, double dvalue, int ivalue, void *dynvalue); +hisnode* GetNode(hisqueue *HisQueue, int varstart, DdNode *node); +int GetNodeIndex(hisqueue *HisQueue, int varstart, DdNode *node); +void onlinetraverse(DdManager *manager, namedvars varmap, hisqueue *HisQueue, DdNode *bdd); + +/* Save-load */ + +bddfileheader ReadFileHeader(char *filename); +int CheckFileVersion(const char *version); + +DdNode * LoadNodeDump(DdManager *manager, namedvars varmap, FILE *inputfile); +DdNode * LoadNodeRec(DdManager *manager, namedvars varmap, hisqueue *Nodes, FILE *inputfile, nodeline current); +DdNode * GetIfExists(DdManager *manager, namedvars varmap, hisqueue *Nodes, char *varname, int nodenum); + +int SaveNodeDump(DdManager *manager, namedvars varmap, DdNode *bdd, char *filename); +void SaveExpand(DdManager *manager, namedvars varmap, hisqueue *Nodes, DdNode *Current, FILE *outputfile); +void ExpandNodes(hisqueue *Nodes, int index, int nodenum); + +/* Export */ + +int simpleBDDtoDot(DdManager *manager, DdNode *bdd, char *filename); +int simpleNamedBDDtoDot(DdManager *manager, namedvars varmap, DdNode *bdd, char *filename); +