prism logical probabilistic system.

This commit is contained in:
Vítor Santos Costa 2011-11-10 12:24:47 +00:00
parent d971219b7e
commit e865248dce
127 changed files with 22788 additions and 0 deletions

93
packages/prism/LICENSE Normal file
View File

@ -0,0 +1,93 @@
LICENSE AGREEMENT OF THE PRISM SYSTEM
Copyright (c) 2009,
Taisuke Sato, Neng-Fa Zhou, Yoshitaka Kameya, Yusuke Izumi
All rights reserved.
The PRISM system ("the Software") is built on top of B-Prolog
(http://www.probp.com/), which is provided by Afany Software.
The Software is developed subject to the C source code license
of B-Prolog (http://www.probp.com/license.htm) and distributed
with the permission from Afany Software.
The PRISM development team, which consists of the members from
Tokyo Institute of Technology and from Afany Software, hereby
grants a non-exclusive and non-transferable license to the
person who uses the Software ("the User"), subject to this
agreement.
1. RELATION WITH B-PROLOG. The Software consists of the
standard routines of B-Prolog ("the B-Prolog part") and the
extensional routines by the PRISM development team ("the PRISM
part"). The User must agree that the use of the B-Prolog part
is also restricted by the license agreement of B-Prolog with
the exception stated in Paragraphs 3 and 4.
2. RIGHT TO USE. The User may use the Software provided
that the User has right to use B-Prolog according to the User's
license agreement of B-Prolog. Given the license agreement of
B-Prolog as of the release date of the Software, the User may
use the Software free of charge for academic and non-commercial
purposes, and must purchase a license for other use.
3. DISTRIBUTION. The User may distribute the Software, only
for non-commercial purposes, provided that the Software is
distributed along with this agreement.
4. SOURCE CODE AND DERIVED SOFTWARE. The PRISM development
team may make the source code of the PRISM part ("the Public
Source Code") publicly available under a separate license ("the
Additional License"), along with a minimal set of source and
binary files coming from the B-Prolog part and required to build
the Software ("the Build Kit"). The User may use and distribute
the Public Source Code and the Build Kit subject to the
following subparagraphs.
4.1. SOURCE CODE. The User may use and distribute the
Public Source Code, entirely or in part, subject to the
Additional License.
4.2. BUILD KIT. The User may use and distribute the Build
Kit according to the remaining subparagraphs, provided that
the User has right to use B-Prolog the User's license agreement
of B-Prolog. The Additional License shall not apply to the
Build Kit.
4.3. DERIVED SOFTWARE. The User may build software ("the
Derived Software") from the Public Source Code, modified or
unmodified, along with the Build Kit provided that (a) the User
has right to use the Build Kit as stated in Subparagraph 4.2,
and that (b) the Derived Software presents the following
message in the same way as the Software.
This edition of B-Prolog is for evaluation, learning, and
non-profit research purposes only, and a license is needed for
any other uses. Please visit http://www.probp.com/license.htm
for the detail.
4.4. DISTRIBUTION OF DERIVED SOFTWARE. The User may distribute
the Derived Software built according to Subparagraph 4.3, only
for non-commercial purposes, provided that the Derived Software
is distributed (a) along with this agreement and (b) under the
license consistent with this agreement.
5. COPYRIGHT. The B-Prolog part is copyrighted by Afany
Software and the PRISM part is copyrighted by the PRISM
development team. The Software contains several public domain
modules as listed in the B-Prolog's manual and the implementation
of Mersenne Twister copyrighted by its authors
(http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html), and
some portion of code in the PRISM part is based on the SPECFUN
library available in the NETLIB repository (http://www.netlib.org/).
The User shall own the copyright for the modified part of the
Software according to Subparagraph 3.3.
6. NO WARRANTY. The Software is provided "as-is", without
any warranties express or implied. The User may report any
defects of the Software to the PRISM development team, but
there is no guarantee for those defects to be fixed. The User
who purchased a license from Afany Software might receive a
warranty according to the license agreement of B-Prolog, only
when the defects obviously originate from the B-Prolog part.
Neither Afany Software nor the PRISM development team is
responsible for any damages caused by the use of the Software.

View File

@ -0,0 +1,39 @@
The following license agreement is referred to as the "Additional
License" in Paragraph 4 of a license agreement on the use of the
software, which is titled "LICENSE AGREEMENT OF THE PRISM SYSTEM."
--------------------------------------------------------------------
SOURCE CODE LICENSE AGREEMENT OF THE PRISM SYSTEM
Copyright (c) 2009,
Taisuke Sato, Neng-Fa Zhou, Yoshitaka Kameya, Yusuke Izumi
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* None of the name of Tokyo Institute of Technology, the name of
City University of New York, nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

24
packages/prism/README Normal file
View File

@ -0,0 +1,24 @@
========================== README (top) ==========================
This is a software package of PRISM version 2.0, a logic-based
programming system for statistical modeling, which is built
on top of B-Prolog (http://www.probp.com/). Since version 2.0,
the source code of the PRISM part is included in the released
package. Please use PRISM based on the agreement described in
LICENSE and LICENSE.src.
LICENSE ... license agreement of PRISM
LICENSE.src ... additional license agreement on the source
code of PRISM
bin/ ... executables
doc/ ... documents
src/ ... source code
exs/ ... example programs
exs_fail/ ... example programs for generative modeling
with failure
exs_foc/ ... additional examples that demonstrate the
First Order Compiler
For the files under each directory, please read the README file
in the directory. For the papers or additional information
on PRISM, please visit http://sato-www.cs.titech.ac.jp/prism/ .

65
packages/prism/exs/README Normal file
View File

@ -0,0 +1,65 @@
========================== README (exs) ==========================
Files/Directories:
README ... this file
direction.psm ... the first example in the user's manual
dcoin.psm ... simple program modeling two Bernoulli trial processes
bloodABO.psm ... ABO blood type program (ABO gene model)
bloodAaBb.psm ... ABO blood type program (AaBb gene model)
bloodtype.dat ... data file for bloodABO.psm and bloodAaBb.psm
alarm.psm ... Bayesian network program
sbn.psm ... Singly connected Bayesian network program
hmm.psm ... discrete hidden Markov model
phmm.psm ... profile hmm for the alignment of amino-acid sequences
phmm.dat ... data file for phmm.psm
pdcg.psm ... PCFG program for top-down parsing
pdcg_c.psm ... PCFG program for Charniak's example
plc.psm ... probabilistic left-corner parsing
votes.psm ... cross-validation of naive Bayes with the `votes' data
jtree/ ... Bayesian network program in a junction-tree form
noisy_or/ ... Bayesian network program using noisy OR
How to use:
All programs are self-contained, hopefully. Try first a sample
session in each program to get familiar with a model.
Comment:
The above programs contain no negation. When a program contains
negation, you have to compile away negation by FOC (first order
compiler). For PRISM programs with negation, see ../exs_fail.
References:
(PRISM)
Parameter Learning of Logic Programs for Symbolic-statistical Modeling,
Sato,T. and Kameya,Y.,
Journal of Artificial Intelligence Research 15, pp.391-454, 2001.
New advances in logic-based probabilistic modeling by PRISM,
Sato,T. and Kameya,Y.,
Probabilistic Inductive Logic Programming, LNCS 4911, Springer,
pp.118-155, 2008.
(PCFGs)
Foundations of Statistical Natural Language Processing,
Manning,C.D. and Schutze,H.,
The MIT Press, 1999.
A Separate-and-Learn Approach to EM Learning of PCFGs
Sato,T., Abe,S., Kameya,Y. and Shirai,K.,
Proc. of the 6th Natural Language Processing Pacific Rim Symposium
(NLRPS-2001), pp.255-262, 2001.
(BNs)
Probabilistic Reasoning in Intelligent Systems,
Pearl,J.,
Morgan Kaufmann, 1988.
Expert Systems and Probabilistic Network Models,
Castillo,E., Gutierrez,J.M. and Hadi,A.S.,
Springer-Verlag, 1997.
(HMMs)
Foundations of Speech Recognition,
Rabiner,L.R. and Juang,B.,
Prentice-Hall, 1993.

View File

@ -0,0 +1,122 @@
%%%%
%%%% Bayesian networks (1) -- alarm.psm
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example is borrowed from:
%% Poole, D., Probabilistic Horn abduction and Bayesian networks,
%% In Proc. of Artificial Intelligence 64, pp.81-129, 1993.
%%
%% (Fire) (Tampering)
%% / \ /
%% ((Smoke)) (Alarm)
%% |
%% (Leaving) (( )) -- observable node
%% | ( ) -- hidden node
%% ((Report))
%%
%% In this network, we assume that all rvs (random variables)
%% take on {yes,no} and also assume that only two nodes, `Smoke'
%% and `Report', are observable.
%%-------------------------------------
%% Quick start : sample session
%%
%% ?- prism(alarm),go. % Learn parameters from randomly generated
%% % 100 samples
%%
%% Get the probability and the explanation graph:
%% ?- prob(world(yes,no)).
%% ?- probf(world(yes,no)).
%%
%% Get the most likely explanation and its probability:
%% ?- viterbif(world(yes,no)).
%% ?- viterbi(world(yes,no)).
%%
%% Compute conditional hindsight probabilities:
%% ?- chindsight(world(yes,no)).
%% ?- chindsight_agg(world(yes,no),world(_,_,query,yes,_,no)).
go:- alarm_learn(100).
%%-------------------------------------
%% Declarations:
:- set_prism_flag(data_source,file('world.dat')).
% When we run learn/0, the data are supplied
% from `world.dat'.
values(_,[yes,no]). % We declare multiary random switch msw(.,V)
% used in this program such that V (outcome)
% is one of {yes,no}. Note that '_' is
% an anonymous logical variable in Prolog.
% The distribution of V is specified by
% set_params below.
%%------------------------------------
%% Modeling part:
%%
%% The above BN defines a joint distribution
%% P(Fire,Tapering,Smoke,Alarm,Leaving,Report).
%% We assume `Smoke' and `Report' are observable while others are not.
%% Our modeling simulates random sampling of the BN from top nodes
%% using msws. For each rv, say `Fire', we introduce a corresponding
%% msw, say msw(fi,Fi) such that
%% msw(fi,Fi) <=> sampling msw named fi yields the outcome Fi.
%% Here fi is a constant intended for the name of rv `Fire.'
%%
world(Fi,Ta,Al,Sm,Le,Re) :-
%% Define a distribution for world/5 such that e.g.
%% P(Fire=yes,Tapering=yes,Smoke=no,Alarm=no,Leaving=no,Report=no)
%% = P(world(yes,yes,no,no,no,no))
msw(fi,Fi), % P(Fire)
msw(ta,Ta), % P(Tampering)
msw(sm(Fi),Sm), % CPT P(Smoke | Fire)
msw(al(Fi,Ta),Al), % CPT P(Alarm | Fire,Tampering)
msw(le(Al),Le), % CPT P(Leaving | Alarm)
msw(re(Le),Re). % CPT P(Report | Leaving)
world(Sm,Re):-
%% Define marginal distribution for `Smoke' and `Report'
world(_,_,_,Sm,_,Re).
%%------------------------------------
%% Utility part:
alarm_learn(N) :-
unfix_sw(_), % Make all parameters changeable
set_params, % Set parameters as you specified
get_samples(N,world(_,_),Gs), % Get N samples
fix_sw(fi), % Preserve the parameter values
learn(Gs). % for {msw(fi,yes), msw(fi,no)}
% alarm_learn(N) :-
% %% generate teacher data and write them to `world.dat'
% %% before learn/0 is called.
% write_world(N,'world.dat'),
% learn.
set_params :-
set_sw(fi,[0.1,0.9]),
set_sw(ta,[0.15,0.85]),
set_sw(sm(yes),[0.95,0.05]),
set_sw(sm(no),[0.05,0.95]),
set_sw(al(yes,yes),[0.50,0.50]),
set_sw(al(yes,no),[0.90,0.10]),
set_sw(al(no,yes),[0.85,0.15]),
set_sw(al(no,no),[0.05,0.95]),
set_sw(le(yes),[0.88,0.12]),
set_sw(le(no),[0.01,0.99]),
set_sw(re(yes),[0.75,0.25]),
set_sw(re(no),[0.10,0.90]).
write_world(N,File) :-
get_samples(N,world(_,_),Gs),tell(File),write_world(Gs),told.
write_world([world(Sm,Re)|Gs]) :-
write(world(Sm,Re)),write('.'),nl,write_world(Gs).
write_world([]).

View File

@ -0,0 +1,111 @@
%%%%
%%%% ABO blood type --- bloodABO.psm
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% ABO blood type consists of A, B, O and AB. They are observable
%% (phenotypes) and determined by a pair of blood type genes (geneotypes).
%% There are three ABO genes, namely a, b and o located on the 9th
%% chromosome of a human being. There are 6 geneotypes ({a,a},{a,b},{a,o},
%% {b,b},{b,o},{o,o}) and each determines a blood type. For example {a,b}
%% gives blood type AB etc. Our task is to estimate frequencies of ABO
%% genes from a random sample of ABO blood type, assuming random mate.
%%-------------------------------------
%% Quick start : sample session
%%
%% ?- prism(bloodABO),go,print_blood.
%% % Learn parameters from randomly generated
%% % 100 samples with A:B:O:AB = 38:22:31:9
%%
%% ?- sample(bloodtype(X)).
%% % Pick up a person with blood type X randomly
%% % acccording to the currrent parameter settings
%%
%% ?- get_samples(100,bloodtype(X),_Gs),countlist(_Gs,Cs).
%% % Pick up 100 persons and get the frequencies
%% % of their blood types
%%
%% ?- probf(bloodtype(ab),E),print_graph(E).
%% % Print all explanations for blooodtype(ab) in
%% % a compressed form
%%
%% ?- prob(bloodtype(ab),P).
%% % P is the probability of bloodtype(ab) being true
%%
%% ?- viterbif(bloodtype(ab)).
%% ?- viterbif(bloodtype(ab),P,E),print_graph(E).
%% ?- viterbi(bloodtype(ab),P).
%% % P is the probability of a most likely
%% % explanation E for bloodtype(ab).
%%
%% ?- viterbit(bloodtype(ab)).
%% % Print the most likely explanation for
%% % bloodtype(ab) in a tree form.
go:- learn_bloodtype(100).
%%-------------------------------------
%% Declarations:
:- set_prism_flag(data_source,file('bloodtype.dat')).
% When we run learn/0, the data are supplied
% by `bloodtype.dat'.
values(gene,[a,b,o],[0.5,0.2,0.3]).
% We declare msw(gene,V) s.t. V takes on
% one of the genes {a,b,o} when executed,
% with the freq.: a 50%, b 20%, o 30%.
%%------------------------------------
%% Modeling part:
bloodtype(P) :-
genotype(X,Y),
( X=Y -> P=X
; X=o -> P=Y
; Y=o -> P=X
; P=ab
).
genotype(X,Y) :- msw(gene,X),msw(gene,Y).
% We assume random mate. Note that msw(gene,X)
% and msw(gene,Y) are i.i.d. (independent and
% identically distributed) random variables
% in Prism because they have the same id but
% different subgoals.
%%------------------------------------
%% Utility part:
learn_bloodtype(N) :- % Learn parameters from N observations
random_set_seed(214857), % Set seed of the random number generator
gen_bloodtype(N,Gs),!, % Sample bloodtype/1 of size N
learn(Gs). % Perform search and graphical EM learning
% learn. % <= when using the file `bloodtype.dat'
gen_bloodtype(N,Gs) :-
N > 0,
random_select([a,b,o,ab],[0.38,0.22,0.31,0.09],X),
Gs = [bloodtype(X)|Gs1], % Sample a blood type with an empirical
N1 is N-1,!, % ratio for Japanese people.
gen_bloodtype(N1,Gs1).
gen_bloodtype(0,[]).
print_blood :-
prob(bloodtype(a),PA),prob(bloodtype(b),PB),
prob(bloodtype(o),PO),prob(bloodtype(ab),PAB),
nl,
format("P(A) = ~6f~n",[PA]),
format("P(B) = ~6f~n",[PB]),
format("P(O) = ~6f~n",[PO]),
format("P(AB) = ~6f~n",[PAB]).
print_gene :-
get_sw(gene,[_,[a,b,o],[GA,GB,GO]]),
nl,
format("P(a) = ~6f~n",[GA]),
format("P(b) = ~6f~n",[GB]),
format("P(o) = ~6f~n",[GO]).

View File

@ -0,0 +1,114 @@
%%%%
%%%% Another hypothesis on ABO blood type inheritance --- bloodAaBb.psm
%%%%
%%%% Copyright (C) 2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% ABO blood type consists of A, B, O and AB. They are observable
%% (phenotypes) and determined by a pair of blood type genes (geneotypes).
%% At present, it is known that there are three ABO genes, namely a, b and
%% o located on the 9th chromosome of a human being, but in early 20th
%% century, there was another hypothesis that we have two loci for ABO
%% blood type with dominant alleles A/a and B/b. That is, genotypes aabb,
%% A*bb, aaB* and A*B* correspond to the blood types (phenotypes) O, A, B
%% and AB, respectively, where * stands for a don't care symbol. We call
%% this hypothesis the AaBb gene model, and assume random mating.
%%-------------------------------------
%% Quick start : sample session -- the same as that of bloodABO.psm
%%
%% ?- prism(bloodAaBb),go,print_blood.
%% % Learn parameters from randomly generated
%% % 100 samples with A:B:O:AB = 38:22:31:9
%%
%% ?- probf(bloodtype(ab),E),print_graph(E).
%% ?- prob(bloodtype(ab),P).
%%
%% ?- viterbif(bloodtype(ab),P,E),print_graph(E).
%% ?- viterbi(bloodtype(ab),P).
%% % P is the probability of a most likely
%% % explanation E for bloodtype(ab).
go:- learn_bloodtype(100).
%%-------------------------------------
%% Session for model selection:
%%
%% -- we try to evaluate the plausibilities of the correct model (ABO
%% gene model) and this AaBb gene model according to the data in
%% `bloodtype.dat'. The data file `bloodtype.dat' contains 38
%% persons of blood type A, 22 persons of blood type B, 31 persons
%% of blood type O, and 9 persons of blood type AB (the ratio is
%% almost the same as that in Japanese people).
%%
%% 1. Modify bloodABO.psm and bloodAaBb.psm:
%% - Use learn/0 instead of learn/1.
%%
%% 2. Get the BIC value for the ABO gene model (bloodABO.psm)
%% ?- prism(bloodABO).
%% ?- learn.
%% ?- learn_statistics(bic,BIC).
%%
%% 3. Get the BIC value for the AaBb gene model (this file)
%% ?- prism(bloodAaBb).
%% ?- learn.
%% ?- learn_statistics(bic,BIC).
%%
:- set_prism_flag(data_source,file('bloodtype.dat')).
% When we run learn/0, the data are supplied
% by `bloodtype.dat'.
values(locus1,['A',a]).
values(locus2,['B',b]).
%%------------------------------------
%% Modeling part:
bloodtype(P) :-
genotype(locus1,X1,Y1),
genotype(locus2,X2,Y2),
( X1=a, Y1=a, X2=b, Y2=b -> P=o
; ( X1='A' ; Y1='A' ), X2=b, Y2=b -> P=a
; X1=a, Y1=a, ( X2='B' ; Y2='B') -> P=b
; P=ab
).
genotype(L,X,Y) :- msw(L,X),msw(L,Y).
%%------------------------------------
%% Utility part:
%% (the same as that in bloodABO.psm)
learn_bloodtype(N) :- % Learn parameters from N observations
random_set_seed(214857), % Set seed of the random number generator
gen_bloodtype(N,Gs),!, % Sample bloodtype/1 of size N
learn(Gs). % Perform search and graphical EM learning
% learn. % <= when using the file `bloodtype.dat'
gen_bloodtype(N,Gs) :-
N > 0,
random_select([a,b,o,ab],[0.38,0.22,0.31,0.09],X),
Gs = [bloodtype(X)|Gs1], % Sample a blood type with an empirical
N1 is N-1,!, % ratio for Japanese people.
gen_bloodtype(N1,Gs1).
gen_bloodtype(0,[]).
print_blood :-
prob(bloodtype(a),PA),prob(bloodtype(b),PB),
prob(bloodtype(o),PO),prob(bloodtype(ab),PAB),
nl,
format("P(A) = ~6f~n",[PA]),
format("P(B) = ~6f~n",[PB]),
format("P(O) = ~6f~n",[PO]),
format("P(AB) = ~6f~n",[PAB]).
print_gene :-
get_sw(locus1,[_,['A',a],[GA,Ga]]),
get_sw(locus2,[_,['B',b],[GB,Gb]]),
nl,
format("P(A) = ~6f~n",[GA]),
format("P(a) = ~6f~n",[Ga]),
format("P(B) = ~6f~n",[GB]),
format("P(b) = ~6f~n",[Gb]).

View File

@ -0,0 +1,100 @@
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(a).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(b).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(o).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).
bloodtype(ab).

View File

@ -0,0 +1,72 @@
%%%%
%%%% Double coin tossing --- dcoin.psm
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% A sequential mixture of two Bernoulli trials processes.
%% We have two coins, coin(1) and coin(2).
%% Start with coin(1), we keep flipping a coin and observe the outcome.
%% We change coins according to the rule in the process.
%% If the outcome is "head", the next coin to flip is coin(2).
%% If the outcome is "tail", the next coin to flip is coin(1).
%% The learning task is to estimate parameters for coin(1) and coin(2),
%% observing a sequence of outcomes.
%% As there is no hidden variable in this model, EM learning is just
%% ML estimation from complete data.
%%-------------------------------------
%% Quick start : sample session
%%
%% (1) load this program
%% ?- prism(dcoin).
%%
%% (2) sampling and probability computations
%% ?- sample(dcoin(10,X)),prob(dcoin(10,X)).
%% ?- sample(dcoin(10,X)),probf(dcoin(10,X)).
%%
%% (3) EM learning
%% ?- go.
go:- dcoin_learn(500).
%%------------------------------------
%% Declarations:
values(coin(1),[head,tail],[0.5,0.5]).
% Declare msw(coin(1),V) s.t. V = head or
% V = tail, where P(msw(coin(1),head)) = 0.5
% and P(msw(coin(1),tail)) = 0.5.
values(coin(2),[head,tail],[0.7,0.3]).
% Declare msw(coin(2),V) s.t. V = head or
% V = tail, where P(msw(coin(2),head)) = 0.7
% and P(msw(coin(2),tail)) = 0.3.
%%------------------------------------
%% Modeling part:
dcoin(N,Rs) :- % Rs is a list with length N of outcomes
dcoin(N,coin(1),Rs). % from two Bernoulli trials processes.
dcoin(N,Coin,[R|Rs]) :-
N > 0,
msw(Coin,R),
( R == head, NextCoin = coin(2)
; R == tail, NextCoin = coin(1) ),
N1 is N-1,
dcoin(N1,NextCoin,Rs).
dcoin(0,_,[]).
%%------------------------------------
%% Utility part:
dcoin_learn(N) :-
set_params, % Set parameters.
sample(dcoin(N,Rs)), % Get a sample Rs of size N.
Goals = [dcoin(N,Rs)], % Estimate the parameters from Rs.
learn(Goals).
set_params :-
set_sw(coin(1),[0.5,0.5]),
set_sw(coin(2),[0.7,0.3]).

View File

@ -0,0 +1,46 @@
%%%%
%%%% Decision of the direction by a coin tossing -- direction.psm
%%%%
%%%% This program has just one random switch named `coin'.
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%%-------------------------------------
%% Sample session
%%
%% (1) Load this program:
%% ?- prism(direction).
%%
%% (2) Get a sample:
%% ?- sample(direction(D)).
%%
%% (3) Display the information about the switch `coin':
%% ?- show_sw.
%%
%% (4) Set the probability distribution to the switch `coin':
%% ?- set_sw(coin,[0.7,0.3]).
%%
%% (5) Display the switch information again with the distribution set
%% at step 4:
%% ?- show_sw.
%%
%% (6) Get a sample again with the distribution set at step 4:
%% ?- sample(direction(D)).
%%
%% [Note1]
%% Since 1.9, without any extra settings, the probability distribution
%% of every switch is set to a uniform distribution.
%%
%% [Note2]
%% If you go (3) with skipping (2), nothing should be displayed. This
%% is because any random switch will not be registered by the system until
%% it is explicitly used or referred to.
values(coin,[head,tail]). % The switch `coin' takes `head' or `tail' as its value
direction(D):-
msw(coin,Face), % Make a coin tossing
( Face==head -> D=left ; D=right). % Decide the direction according to
% the result of coin tossing

View File

@ -0,0 +1,99 @@
%%%%
%%%% Hidden Markov model --- hmm.psm
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% [state diagram:] (2 states and 2 output symbols)
%%
%% +--------+ +--------+
%% | | | |
%% | +------+ +------+ |
%% | | |------->| | |
%% +---->| s0 | | s1 |<----+
%% | |<-------| |
%% +------+ +------+
%%
%% - In each state, possible output symbols are `a' and `b'.
%%-------------------------------------
%% Quick start : sample session
%%
%% ?- prism(hmm),hmm_learn(100). % Learn parameters from 100 randomly
%% % generated samples
%%
%% ?- show_sw. % Confirm the learned parameter
%%
%% ?- prob(hmm([a,a,a,a,a,b,b,b,b,b])). % Calculate the probability
%% ?- probf(hmm([a,a,a,a,a,b,b,b,b,b])). % Get the explanation graph
%%
%% ?- viterbi(hmm([a,a,a,a,a,b,b,b,b,b])). % Run the Viterbi computation
%% ?- viterbif(hmm([a,a,a,a,a,b,b,b,b,b])). % Get the Viterbi explanation
%%
%% ?- hindsight(hmm([a,a,a,a,a,b,b,b,b,b])). % Get hindsight probabilities
%%------------------------------------
%% Declarations:
values(init,[s0,s1]). % state initialization
values(out(_),[a,b]). % symbol emission
values(tr(_),[s0,s1]). % state transition
% :- set_prism_flag(default_sw_d,1.0).
% :- set_prism_flag(epsilon,1.0e-2).
% :- set_prism_flag(restart,10).
% :- set_prism_flag(log_scale,on).
%%------------------------------------
%% Modeling part:
hmm(L):- % To observe a string L:
str_length(N), % Get the string length as N
msw(init,S), % Choose an initial state randomly
hmm(1,N,S,L). % Start stochastic transition (loop)
hmm(T,N,_,[]):- T>N,!. % Stop the loop
hmm(T,N,S,[Ob|Y]) :- % Loop: current state is S, current time is T
msw(out(S),Ob), % Output Ob at the state S
msw(tr(S),Next), % Transit from S to Next.
T1 is T+1, % Count up time
hmm(T1,N,Next,Y). % Go next (recursion)
str_length(10). % String length is 10
%%------------------------------------
%% Utility part:
hmm_learn(N):-
set_params,!, % Set parameters manually
get_samples(N,hmm(_),Gs),!, % Get N samples
learn(Gs). % Learn with the samples
set_params:-
set_sw(init, [0.9,0.1]),
set_sw(tr(s0), [0.2,0.8]),
set_sw(tr(s1), [0.8,0.2]),
set_sw(out(s0),[0.5,0.5]),
set_sw(out(s1),[0.6,0.4]).
%% prism_main/1 is a special predicate for batch execution.
%% The following command conducts learning from 50 randomly
%% generated samples:
%% > upprism hmm 50
prism_main([Arg]):-
parse_atom(Arg,N), % Convert an atom ('50') to a number (50)
hmm_learn(N). % Learn with N samples
%% viterbi_states(Os,Ss) returns the most probable sequence Ss
%% of state transitions for an output sequence Os.
%%
%% | ?- viterbi_states([a,a,a,a,a,b,b,b,b,b],States).
%%
%% States = [s0,s1,s0,s1,s0,s1,s0,s1,s0,s1,s0] ?
viterbi_states(Outputs,States):-
viterbif(hmm(Outputs),_,E),
viterbi_subgoals(E,E1),
maplist(hmm(_,_,S,_),S,true,E1,States).

View File

@ -0,0 +1,8 @@
================== README (exs/jtree) ==========================
Files:
README ... This file
asia.psm ... BN for Asia network (naive)
jasia.psm ... BN for Asia network (junction-tree; evidences kept in D-list)
jasia_a.psm ... BN for Asia network (junction-tree; evidences asserted first)
bn2prism/ ... Java translator from BNs to join-tree PRISM programs

View File

@ -0,0 +1,84 @@
%%%%
%%%% Bayesian networks for Asia network -- asia.psm
%%%%
%%%% Copyright (C) 2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example is known as the Asia network, and was borrowed from:
%% S. L. Lauritzen and D. J. Spiegelhalter (1988).
%% Local computations with probabilities on graphical structures
%% and their application to expert systems.
%% Journal of Royal Statistical Society, Vol.B50, No.2, pp.157-194.
%%
%% ((Smoking[S]))
%% ((Visit to Asia[A])) / \
%% | / \
%% v v \
%% (Tuberculosis[T]) (Lang cancer[L]) \
%% \ / \
%% \ / v
%% v v (Bronchinitis[B])
%% (Tuberculosis or lang cancer[TL]) /
%% / \ /
%% / \ /
%% v \ /
%% ((X-ray[X])) v v
%% ((Dyspnea[D]))
%%
%% We assume that the nodes A, S, X and D are observable. This
%% program provides a naive representation of the Asia network, as
%% shown in ../alarm.psm. The junction-tree version of the Asia
%% network program is given in jasia.psm
%%-------------------------------------
%% Quick start:
%%
%% ?- prism(asia),go.
go:- chindsight_agg(world(f,_,_,t),world(f,query,_,_,_,_,_,t)).
% we compute a conditional distribution P(T | A=false, D=true)
%%-------------------------------------
%% Declarations:
values(bn(_,_),[t,f]). % each switch takes on true or false
%%-------------------------------------
%% Modeling part:
world(A,S,X,D):- world(A,_,S,_,_,X,_,D).
world(A,T,S,L,TL,X,B,D) :-
msw(bn(a,[]),A),msw(bn(t,[A]),T),
msw(bn(s,[]),S),msw(bn(l,[S]),L),
incl_or(T,L,TL),
msw(bn(x,[TL]),X),msw(bn(b,[S]),B),
msw(bn(d,[TL,B]),D).
% inclusive OR
incl_or(t,t,t).
incl_or(t,f,t).
incl_or(f,t,t).
incl_or(f,f,f).
%%-------------------------------------
%% Utility part:
:- set_params.
set_params:-
set_sw(bn(a,[]),[0.01,0.99]),
set_sw(bn(t,[t]),[0.05,0.95]),
set_sw(bn(t,[f]),[0.01,0.99]),
set_sw(bn(s,[]),[0.5,0.5]),
set_sw(bn(l,[t]),[0.1,0.9]),
set_sw(bn(l,[f]),[0.01,0.99]),
set_sw(bn(x,[t]),[0.98,0.02]),
set_sw(bn(x,[f]),[0.05,0.95]),
set_sw(bn(b,[t]),[0.60,0.40]),
set_sw(bn(b,[f]),[0.30,0.70]),
set_sw(bn(d,[t,t]),[0.90,0.10]),
set_sw(bn(d,[t,f]),[0.70,0.30]),
set_sw(bn(d,[f,t]),[0.80,0.20]),
set_sw(bn(d,[f,f]),[0.10,0.90]).

View File

@ -0,0 +1,153 @@
%%%%
%%%% Join-tree PRISM program for Asia network -- jasia.psm
%%%%
%%%% Copyright (C) 2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example is known as the Asia network, and was borrowed from:
%% S. L. Lauritzen and D. J. Spiegelhalter (1988).
%% Local computations with probabilities on graphical structures
%% and their application to expert systems.
%% Journal of Royal Statistical Society, Vol.B50, No.2, pp.157-194.
%%
%% ((Smoking[S]))
%% ((Visit to Asia[A])) / \
%% | / \
%% v v \
%% (Tuberculosis[T]) (Lang cancer[L]) \
%% \ / \
%% \ / v
%% v v (Bronchinitis[B])
%% (Tuberculosis or lang cancer[TL]) /
%% / \ /
%% / \ /
%% v \ /
%% ((X-ray[X])) v v
%% ((Dyspnea[D]))
%%
%% We assume that the nodes A, S, X and D are observable. One may
%% notice that this network is multiply-connected (there are undirected
%% loop: S-L-TL-D-B-S). To perform efficient probabilistic inferences,
%% one popular method is the join-tree (JT) algorithm. In the JT
%% algorithm, we first convert the original network (DAG) into a tree-
%% structured undirected graph, called join tree (junction tree), in
%% which a node corresponds to a set of nodes in the original network.
%% Then we compute the conditional probabilities based on the join
%% tree. For example, the above network is converted into the
%% following join tree:
%%
%% node4(A,T) node2(S,L,B)
%% \ \
%% [T] [L,B]
%% \ \ node1
%% node3(T,L,TL)--[L,TL]--(L,TL,B)
%% /
%% [TL,B]
%% node6 /
%% (TL,X)--[TL]--(TL,B,D)
%% node5
%%
%% where (...) corresponds to a node and [...] corresponds to a
%% separator. In this join tree, node2 corresponds to a set {S,L,B} of
%% the original nodes. We consider that node1 is the root of this join
%% tree.
%%
%% Here we write a PRISM program that represents the above join tree.
%% The predicate named msg_i_j corresponds to the edge from node i to
%% node j in the join tree. The predicate named node_i corresponds to
%% node i.
%%
%% The directory `bn2prism' in the same directory contains BN2Prism, a
%% Java translator from a Bayesian network to a PRISM program in join-
%% tree style, like the one shown here.
%%-------------------------------------
%% Quick start:
%%
%% ?- prism(jasia),go.
go:- chindsight_agg(world([(a,f),(d,t)]),node_4(_,query,_)).
% we compute a conditional distribution P(T | A=false, D=true)
go2:- prob(world([(a,f),(d,t)])).
% we compute a marginal probability P(A=false, D=true)
%%-------------------------------------
%% Declarations:
values(bn(_,_),[t,f]). % each switch takes on true or false
%%-------------------------------------
%% Modeling part:
%%
%% [Note]
%% Evidences are kept in a difference list in the last argument of
%% the msg_i_j and the node_i predicates. For simplicity, it is
%% assumed that the evidences are given in the same order as that
%% of appearances of msw/2 in the top-down execution of world/1.
world(E):- msg_1_0(E-[]).
msg_1_0(E0-E1) :- node_1(_L,_TL,_B,E0-E1).
msg_2_1(L,B,E0-E1 ):- node_2(_S,L,B,E0-E1).
msg_3_1(L,TL,E0-E1):- node_3(_T,L,TL,E0-E1).
msg_4_3(T,E0-E1) :- node_4(_A,T,E0-E1).
msg_5_1(TL,B,E0-E1):- node_5(TL,B,_D,E0-E1).
msg_6_5(TL,E0-E1) :- node_6(TL,_X,E0-E1).
node_1(L,TL,B,E0-E1):-
msg_2_1(L,B,E0-E2),
msg_3_1(L,TL,E2-E3),
msg_5_1(TL,B,E3-E1).
node_2(S,L,B,E0-E1):-
cpt(s,[],S,E0-E2),
cpt(l,[S],L,E2-E3),
cpt(b,[S],B,E3-E1).
node_3(T,L,TL,E0-E1):-
incl_or(L,T,TL),
msg_4_3(T,E0-E1).
node_4(A,T,E0-E1):-
cpt(a,[],A,E0-E2),
cpt(t,[A],T,E2-E1).
node_5(TL,B,D,E0-E1):-
cpt(d,[TL,B],D,E0-E2),
msg_6_5(TL,E2-E1).
node_6(TL,X,E0-E1):-
cpt(x,[TL],X,E0-E1).
cpt(X,Par,V,E0-E1):-
( E0=[(X,V)|E1] -> true ; E0=E1 ),
msw(bn(X,Par),V).
% inclusive OR
incl_or(t,t,t).
incl_or(t,f,t).
incl_or(f,t,t).
incl_or(f,f,f).
%%-------------------------------------
%% Utility part:
:- set_params.
set_params:-
set_sw(bn(a,[]),[0.01,0.99]),
set_sw(bn(t,[t]),[0.05,0.95]),
set_sw(bn(t,[f]),[0.01,0.99]),
set_sw(bn(s,[]),[0.5,0.5]),
set_sw(bn(l,[t]),[0.1,0.9]),
set_sw(bn(l,[f]),[0.01,0.99]),
set_sw(bn(x,[t]),[0.98,0.02]),
set_sw(bn(x,[f]),[0.05,0.95]),
set_sw(bn(b,[t]),[0.60,0.40]),
set_sw(bn(b,[f]),[0.30,0.70]),
set_sw(bn(d,[t,t]),[0.90,0.10]),
set_sw(bn(d,[t,f]),[0.70,0.30]),
set_sw(bn(d,[f,t]),[0.80,0.20]),
set_sw(bn(d,[f,f]),[0.10,0.90]).

View File

@ -0,0 +1,167 @@
%%%%
%%%% Join-tree PRISM program for Asia network -- jasia.psm
%%%%
%%%% Copyright (C) 2009
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example is known as the Asia network, and was borrowed from:
%% S. L. Lauritzen and D. J. Spiegelhalter (1988).
%% Local computations with probabilities on graphical structures
%% and their application to expert systems.
%% Journal of Royal Statistical Society, Vol.B50, No.2, pp.157-194.
%%
%% ((Smoking[S]))
%% ((Visit to Asia[A])) / \
%% | / \
%% v v \
%% (Tuberculosis[T]) (Lang cancer[L]) \
%% \ / \
%% \ / v
%% v v (Bronchinitis[B])
%% (Tuberculosis or lang cancer[TL]) /
%% / \ /
%% / \ /
%% v \ /
%% ((X-ray[X])) v v
%% ((Dyspnea[D]))
%%
%% We assume that the nodes A, S, X and D are observable. One may
%% notice that this network is multiply-connected (there are undirected
%% loop: S-L-TL-D-B-S). To perform efficient probabilistic inferences,
%% one popular method is the join-tree (JT) algorithm. In the JT
%% algorithm, we first convert the original network (DAG) into a tree-
%% structured undirected graph, called join tree (junction tree), in
%% which a node corresponds to a set of nodes in the original network.
%% Then we compute the conditional probabilities based on the join
%% tree. For example, the above network is converted into the
%% following join tree:
%%
%% node4(A,T) node2(S,L,B)
%% \ \
%% [T] [L,B]
%% \ \ node1
%% node3(T,L,TL)--[L,TL]--(L,TL,B)
%% /
%% [TL,B]
%% node6 /
%% (TL,X)--[TL]--(TL,B,D)
%% node5
%%
%% where (...) corresponds to a node and [...] corresponds to a
%% separator. In this join tree, node2 corresponds to a set {S,L,B} of
%% the original nodes. We consider that node1 is the root of this join
%% tree.
%%
%% Here we write a PRISM program that represents the above join tree.
%% The predicate named msg_i_j corresponds to the edge from node i to
%% node j in the join tree. The predicate named node_i corresponds to
%% node i.
%%
%% The directory `bn2prism' in the same directory contains BN2Prism, a
%% Java translator from a Bayesian network to a PRISM program in join-
%% tree style, like the one shown here.
%%-------------------------------------
%% Quick start:
%%
%% ?- prism(jasia_a),go.
go:- chindsight_agg(world([(a,f),(d,t)]),node_4(_,query)).
% we compute a conditional distribution P(T | A=false, D=true)
go2:- prob(world([(a,f),(d,t)])).
% we compute a marginal probability P(A=false, D=true)
%%-------------------------------------
%% Declarations:
values(bn(_,_),[t,f]). % each switch takes on true or false
%%-------------------------------------
%% Modeling part:
%%
%% [Note]
%% Evidences are added first into the Prolog database. This is a
%% simpler method than keeping the evidences in difference list
%% (as done in jasia.psm). However, in learning, the subgoals are
%% inappropriately shared among the observed goals, each of which
%% is associated with a different set of evidences (This optimization
%% is called inter-goal sharing, and unconditionally enabled in the
%% current PRISM system). An ad-hoc workaround is to introduce an
%% ID for each set of evidences and keep the ID through the arguments
%% (e.g. we define world(ID,E), msg_2_1(ID,L,B), and so on).
world(E):- assert_evid(E),msg_1_0.
msg_1_0 :- node_1(_L,_TL,_B).
msg_2_1(L,B) :- node_2(_S,L,B).
msg_3_1(L,TL):- node_3(_T,L,TL).
msg_4_3(T) :- node_4(_A,T).
msg_5_1(TL,B):- node_5(TL,B,_D).
msg_6_5(TL) :- node_6(TL,_X).
node_1(L,TL,B):-
msg_2_1(L,B),
msg_3_1(L,TL),
msg_5_1(TL,B).
node_2(S,L,B):-
cpt(s,[],S),
cpt(l,[S],L),
cpt(b,[S],B).
node_3(T,L,TL):-
incl_or(L,T,TL),
msg_4_3(T).
node_4(A,T):-
cpt(a,[],A),
cpt(t,[A],T).
node_5(TL,B,D):-
cpt(d,[TL,B],D),
msg_6_5(TL).
node_6(TL,X):-
cpt(x,[TL],X).
cpt(X,Par,V):-
( evid(X,V) -> true ; true ),
msw(bn(X,Par),V).
% inclusive OR
incl_or(t,t,t).
incl_or(t,f,t).
incl_or(f,t,t).
incl_or(f,f,f).
% adding evidences to Prolog database
assert_evid(Es):-
retractall(evid(_,_)),
assert_evid0(Es).
assert_evid0([]).
assert_evid0([(X,V)|Es]):-
assert(evid(X,V)),!,
assert_evid0(Es).
%%-------------------------------------
%% Utility part:
:- set_params.
set_params:-
set_sw(bn(a,[]),[0.01,0.99]),
set_sw(bn(t,[t]),[0.05,0.95]),
set_sw(bn(t,[f]),[0.01,0.99]),
set_sw(bn(s,[]),[0.5,0.5]),
set_sw(bn(l,[t]),[0.1,0.9]),
set_sw(bn(l,[f]),[0.01,0.99]),
set_sw(bn(x,[t]),[0.98,0.02]),
set_sw(bn(x,[f]),[0.05,0.95]),
set_sw(bn(b,[t]),[0.60,0.40]),
set_sw(bn(b,[f]),[0.30,0.70]),
set_sw(bn(d,[t,t]),[0.90,0.10]),
set_sw(bn(d,[t,f]),[0.70,0.30]),
set_sw(bn(d,[f,t]),[0.80,0.20]),
set_sw(bn(d,[f,f]),[0.10,0.90]).

View File

@ -0,0 +1,7 @@
================== README (exs/noisy_or) ==========================
Files:
README ... this file
alarm_nor_basic.psm ... BN program using noisy OR (network-specific)
alarm_nor_generic.psm ... BN program using noisy OR (network-independent)
noisy_or.psm ... library for noisy OR

View File

@ -0,0 +1,160 @@
%%%%
%%%% Bayesian networks using noisy OR (1) -- alarm_nor_basic.psm
%%%%
%%%% Copyright (C) 2004,2006,2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example is borrowed from:
%% Poole, D., Probabilistic Horn abduction and Bayesian networks,
%% In Proc. of Artificial Intelligence 64, pp.81-129, 1993.
%%
%% (Fire) (Tampering)
%% / \ /
%% ((Smoke)) (Alarm)
%% |
%% (Leaving) (( )) -- observable node
%% | ( ) -- hidden node
%% ((Report))
%%
%% In this network, we assume that all rvs (random variables) take on
%% {yes,no} and also assume that only two nodes, `Smoke' and `Report', are
%% observable.
%%
%% Furthermore, in this program, we consider that the Alarm variable's CPT
%% (conditional probability table) given through the noisy-OR rule. That is,
%% let us assume that we have the following inhibition probabilities:
%%
%% P(Alarm=no | Fire=yes, Tampering=no) = 0.3
%% P(Alarm=no | Fire=no, Tampering=yes) = 0.2
%%
%% The CPT for the Alarm variable is then constructed from these inhibition
%% probabilities and the noisy-OR rule:
%%
%% +------+-----------+--------------------+----------------+
%% | Fire | Tampering | P(Alarm=yes) | P(Alarm=no) |
%% +------+-----------+--------------------+----------------+
%% | yes | yes | 0.94 = 1 - 0.3*0.2 | 0.06 = 0.3*0.2 |
%% | yes | no | 0.7 = 1 - 0.3 | 0.3 |
%% | no | yes | 0.8 = 1 - 0.2 | 0.2 |
%% | no | no | 0 | 1.0 |
%% +------+-----------+--------------------+----------------+
%%
%% cpt_al/3 in this program implements the above CPT with random switches.
%% The key step is to consider the generation process underlying the noisy-OR
%% rule. One may notice that this program is written in a network-specific
%% form, but a more generic, network-independent program is given in
%% alarm_nor_generic.psm.
%%
%% Please note that this program shares a considerably large part with
%% ../alarm.psm, so some comments are omitted for simplicity.
%%-------------------------------------
%% Quick start:
%%
%% ?- prism(alarm_nor_basic).
%%
%% Print the CPT of the Alarm variable constructed from the noisy OR rule:
%% ?- print_dist_al.
%%
%% Print logical formulas that express the probabilistic behavior of
%% the noisy OR rule for Alarm:
%% ?- print_expl_al.
%%
%% Get the probability and the explanation graph:
%% ?- prob(world(yes,no)).
%% ?- probf(world(yes,no)).
%%
%% Get the most likely explanation and its probability:
%% ?- viterbif(world(yes,no)).
%% ?- viterbi(world(yes,no)).
%%
%% Compute conditional hindsight probabilities:
%% ?- chindsight(world(yes,no),world(_,_,_,_,_,_)).
%% ?- chindsight_agg(world(yes,no),world(_,_,query,yes,_,no)).
%%
%% Learn parameters from randomly generated 100 samples
%% ?- alarm_learn(100).
go:- alarm_learn(100).
%%-------------------------------------
%% Declarations:
values(_,[yes,no]).
%%------------------------------------
%% Modeling part:
world(Sm,Re):- world(_,_,_,Sm,_,Re).
world(Fi,Ta,Al,Sm,Le,Re) :-
cpt_fi(Fi), % P(Fire)
cpt_ta(Ta), % P(Tampering)
cpt_sm(Fi,Sm), % CPT P(Smoke | Fire)
cpt_al(Fi,Ta,Al), % CPT P(Alarm | Fire,Tampering)
cpt_le(Al,Le), % CPT P(Leaving | Alarm)
cpt_re(Le,Re). % CPT P(Report | Leaving)
cpt_fi(Fi):- msw(fi,Fi).
cpt_ta(Ta):- msw(ta,Ta).
cpt_sm(Fi,Sm):- msw(sm(Fi),Sm).
cpt_al(Fi,Ta,Al):- % implementation of noisy OR:
( Fi = yes, Ta = yes ->
msw(cause_al_fi,N_Al_Fi),
msw(cause_al_ta,N_Al_Ta),
( N_Al_Fi = no, N_Al_Ta = no -> Al = no
; Al = yes
)
; Fi = yes, Ta = no -> msw(cause_al_fi,Al)
; Fi = no, Ta = yes -> msw(cause_al_ta,Al)
; Fi = no, Ta = no -> Al = no
).
cpt_le(Al,Le):- msw(le(Al),Le).
cpt_re(Le,Re):- msw(re(Le),Re).
%%------------------------------------
%% Utility part:
alarm_learn(N) :-
unfix_sw(_), % Make all parameters changeable
set_params, % Set parameters as you specified
get_samples(N,world(_,_),Gs), % Get N samples
fix_sw(fi), % Preserve the parameter values
learn(Gs). % for {msw(fi,yes), msw(fi,no)}
set_params :-
set_sw(fi,[0.1,0.9]),
set_sw(ta,[0.15,0.85]),
set_sw(sm(yes),[0.95,0.05]),
set_sw(sm(no),[0.05,0.95]),
set_sw(le(yes),[0.88,0.12]),
set_sw(le(no),[0.01,0.99]),
set_sw(re(yes),[0.75,0.25]),
set_sw(re(no),[0.10,0.90]),
set_sw(cause_al_fi,[0.7,0.3]), % switch for an inhibition prob
set_sw(cause_al_ta,[0.8,0.2]). % switch for an inhibition prob
:- set_params.
%% Check routine for Noisy-OR
print_dist_al:-
set_params,
( member(Fi,[yes,no]),
member(Ta,[yes,no]),
member(Al,[yes,no]),
prob(cpt_al(Fi,Ta,Al),P),
format("P(al=~w | fi=~w, ta=~w):~t~6f~n",[Al,Fi,Ta,P]),
fail
; true
).
print_expl_al:-
set_params,
( member(Fi,[yes,no]),
member(Ta,[yes,no]),
member(Al,[yes,no]),
probf(cpt_al(Fi,Ta,Al)),
fail
; true
).

View File

@ -0,0 +1,174 @@
%%%%
%%%% Bayesian networks using noisy OR (2) -- alarm_nor_generic.psm
%%%%
%%%% Copyright (C) 2004,2006,2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example is borrowed from:
%% Poole, D., Probabilistic Horn abduction and Bayesian networks,
%% In Proc. of Artificial Intelligence 64, pp.81-129, 1993.
%%
%% (Fire) (Tampering)
%% / \ /
%% ((Smoke)) (Alarm)
%% |
%% (Leaving) (( )) -- observable node
%% | ( ) -- hidden node
%% ((Report))
%%
%% In this network, we assume that all rvs (random variables) take on
%% {yes,no} and also assume that only two nodes, `Smoke' and `Report', are
%% observable.
%%
%% Furthermore, as did in alarm_nor_basic.psm, we consider that the Alarm
%% variable's CPT given through the noisy-OR rule. That is, we have the
%% following inhibition probabilities:
%%
%% P(Alarm=no | Fire=yes, Tampering=no) = 0.3
%% P(Alarm=no | Fire=no, Tampering=yes) = 0.2
%%
%% The CPT for the Alarm variable is then constructed from these inhibition
%% probabilities and the noisy-OR rule:
%%
%% +------+-----------+--------------------+----------------+
%% | Fire | Tampering | P(Alarm=yes) | P(Alarm=no) |
%% +------+-----------+--------------------+----------------+
%% | yes | yes | 0.94 = 1 - 0.3*0.2 | 0.06 = 0.3*0.2 |
%% | yes | no | 0.7 = 1 - 0.3 | 0.3 |
%% | no | yes | 0.8 = 1 - 0.2 | 0.2 |
%% | no | no | 0 | 1.0 |
%% +------+-----------+--------------------+----------------+
%%
%% While alarm_nor_basic.psm uses network-specific implementation, in this
%% program, we attempt to introduce a more generic routine that can handle
%% noisy OR. To be more concrete:
%%
%% - We specify noisy OR nodes in a declarative form (with noisy_or/3).
%% - We introduce generic probabilistic predicates that make probabilistic
%% choices, following the specifications of noisy OR nodes.
%%
%% The definition of these generic probabilistic predicates are given in
%% noisy_or.psm, and we will include noisy_or.psm into this program.
%%
%%-------------------------------------
%% Quick start (the same as those listed in alarm_nor_basic.psm):
%%
%% ?- prism(alarm_nor_generic).
%%
%% Print the CPT of the Alarm variable constructed from the noisy OR rule:
%% ?- print_dist_al.
%%
%% Print logical formulas that express the probabilistic behavior of
%% the noisy OR rule for Alarm:
%% ?- print_expl_al.
%%
%% Get the probability and the explanation graph:
%% ?- prob(world(yes,no)).
%% ?- probf(world(yes,no)).
%%
%% Get the most likely explanation and its probability:
%% ?- viterbif(world(yes,no)).
%% ?- viterbi(world(yes,no)).
%%
%% Compute conditional hindsight probabilities:
%% ?- chindsight(world(yes,no),world(_,_,_,_,_,_)).
%% ?- chindsight_agg(world(yes,no),world(_,_,query,yes,_,no)).
%%
%% Learn parameters from randomly generated 100 samples
%% ?- alarm_learn(100).
%%-------------------------------------
%% Declarations:
values(_,[yes,no]).
:- include('noisy_or.psm').
% We include generic probabilistic predicates that can handle
% noisy-OR. The following predicates will be available:
%
% - cpt(X,PaVs,V) represents a probabilistic choice where a
% random variable X given instantiations PaVs of parents
% takes a value V. If X is an ordinary node, a random
% switch bn(X,PaVs) will be used. On the other hand, if
% X is a noisy-OR node, switch cause(X,Y) will be used,
% where Y is one of parents of X.
%
% - set_nor_params/0 sets inhibition probabilisties (i.e.
% the parameters of switches cause(X,Y)) according to
% the specifications for noisy-OR nodes with noisy_or/3.
%%------------------------------------
%% Modeling part:
world(Sm,Re):- world(_,_,_,Sm,_,Re).
world(Fi,Ta,Al,Sm,Le,Re) :-
cpt(fi,[],Fi), % P(Fire)
cpt(ta,[],Ta), % P(Tampering)
cpt(sm,[Fi],Sm), % CPT P(Smoke | Fire)
cpt(al,[Fi,Ta],Al), % CPT P(Alarm | Fire,Tampering)
cpt(le,[Al],Le), % CPT P(Leaving | Alarm)
cpt(re,[Le],Re). % CPT P(Report | Leaving)
% declarations for noisy OR nodes:
noisy_or(al,[fi,ta],[[0.7,0.3],[0.8,0.2]]).
%%------------------------------------
%% Utility part:
alarm_learn(N) :-
unfix_sw(_), % Make all parameters changeable
set_params, % Set ordinary parameters
set_nor_params, % Set inhibition parameters
get_samples(N,world(_,_),Gs), % Get N samples
fix_sw(bn(fi,[])), % Preserve the parameter values
learn(Gs). % for {msw(bn(fi,[]),yes), msw(bn(fi,[]),no)}
:- set_params.
:- set_nor_params.
set_params:-
set_sw(bn(fi,[]),[0.1,0.9]),
set_sw(bn(ta,[]),[0.15,0.85]),
set_sw(bn(sm,[yes]),[0.95,0.05]),
set_sw(bn(sm,[no]),[0.05,0.95]),
set_sw(bn(le,[yes]),[0.88,0.12]),
set_sw(bn(le,[no]),[0.01,0.99]),
set_sw(bn(re,[yes]),[0.75,0.25]),
set_sw(bn(re,[no]),[0.10,0.90]).
%% Check routine for Noisy-OR
print_dist_al:-
( member(Fi,[yes,no]),
member(Ta,[yes,no]),
member(Al,[yes,no]),
get_cpt_prob(al,[Fi,Ta],Al,P),
format("P(al=~w | fi=~w, ta=~w):~t~6f~n",[Al,Fi,Ta,P]),
fail
; true
).
print_expl_al:-
( member(Fi,[yes,no]),
member(Ta,[yes,no]),
member(Al,[yes,no]),
get_cpt_probf(al,[Fi,Ta],Al),
fail
; true
).
%% [Note] prob/1 and probf/1 will fail if its argument fails
get_cpt_prob(X,PaVs,V,P):-
( prob(cpt(X,PaVs,V),P)
; P = 0.0
),!.
get_cpt_probf(X,PaVs,V):-
( probf(cpt(X,PaVs,V))
; format("cpt(~w,~w,~w): always false~n",[X,PaVs,V])
),!.

View File

@ -0,0 +1,65 @@
%%%%
%%%% Library for generic noisy OR predicates --- noisy_or.psm
%%%%
%%%% Copyright (C) 2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% When this file included, the following predicates will be available:
%%
%% - cpt(X,PaVs,V) represents a probabilistic choice where a
%% random variable X given instantiations PaVs of parents
%% takes a value V. If X is an ordinary node, a random
%% switch bn(X,PaVs) will be used. On the other hand, if
%% X is a noisy-OR node, switch cause(X,Y) will be used,
%% where Y is one of parents of X.
%%
%% - set_nor_params/0 sets inhibition probabilisties (i.e.
%% the parameters of switches cause(X,Y)) according to
%% the specifications for noisy-OR nodes with noisy_or/3.
%%---------------------------------------
%% Declarations:
% added just for making the results of probabilistic inference
% simple and readable:
:- p_not_table choose_noisy_or/4, choose_noisy_or/6.
%%---------------------------------------
%% Modeling part:
cpt(X,PaVs,V):-
( noisy_or(X,Pa,_) -> choose_noisy_or(X,Pa,PaVs,V) % for noisy OR nodes
; msw(bn(X,PaVs),V) % for ordinary nodes
).
choose_noisy_or(X,Pa,PaVs,V):- choose_noisy_or(X,Pa,PaVs,no,no,V).
choose_noisy_or(_,[],[],yes,V,V).
choose_noisy_or(_,[],[],no,_,no).
choose_noisy_or(X,[Y|Pa],[PaV|PaVs],PaHasYes0,ValHasYes0,V):-
( PaV=yes ->
msw(cause(X,Y),V0),
PaHasYes=yes,
( ValHasYes0=no, V0=no -> ValHasYes=no
; ValHasYes=yes
)
; PaHasYes=PaHasYes0,
ValHasYes=ValHasYes0
), % do not insert the cut symbol here
choose_noisy_or(X,Pa,PaVs,PaHasYes,ValHasYes,V).
%%---------------------------------------
%% Utility part:
set_nor_params:-
( noisy_or(X,Pa,DistList), % spec for a noisy OR node
set_nor_params(X,Pa,DistList),
fail
; true
).
set_nor_params(_,[],[]).
set_nor_params(X,[Y|Pa],[Dist|DistList]):-
set_sw(cause(X,Y),Dist),!,
set_nor_params(X,Pa,DistList).

View File

@ -0,0 +1,89 @@
%%%%
%%%% Probabilistic DCG --- pdcg.psm
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% PCFGs (probabilistic contex free grammars) are a stochastic extension
%% of CFG grammar such that in a (leftmost) derivation, each production
%% rule is selected probabilistically and applied. Look at the following
%% sample PCFG in which S is a start symbol and {a,b} are terminals.
%%
%% Rule 1: S -> SS (0.4)
%% Rule 2: S -> a (0.5)
%% Rule 3: S -> b (0.1)
%%
%% When S is expanded, three rules, Rule 1, 2 and 3 are applicable.
%% To determine a rule to apply, probabilistic selection is made in
%% such a way that Rule 1 is selected with probability 0.4, Rule 2
%% with probability 0.5 and Rule 3 with probability 0.1, respectively.
%% The probability of a derivation tree is defined to be the product
%% of probabilities associated with rules used in the derivation,
%% and that of a sentence is defined to be the sum of proabibities of
%% derivations for the sentence.
%%
%% When modeling PCFGs, we follow DCG (definite clause grammar)
%% formalism. So we write down a top-down parser using difference
%% list which represents the rest of the sentence to parse. Note that
%% the grammar is left-recursive, and hence running the program below
%% without a tabling mechanism goes into an infinite loop.
%%-------------------------------------
%% Quick start : learning experiment with the sample grammar
%%
%% ?- prism(pdcg),go. % Learn parameters of the PCFG above from
%% % randomly generated 100 samples
%%
%% ?- prob(pdcg([a,b,b])).
%% ?- prob(pdcg([a,b,b]),P).
%% ?- probf(pdcg([a,b,b])).
%% ?- probf(pdcg([a,b,b]),E),print_graph(E).
%% ?- sample(pdcg(X)).
%%
%% ?- viterbi(pdcg([a,b,b]),P). % P is the prob. of the most likely
%% ?- viterbif(pdcg([a,b,b]),P,E). % explanation E for pdcg([a,b,b])
%% ?- viterbif(pdcg([a,b,b]),P,E),print_graph(E).
go:- pdcg_learn(100).
max_str_len(20). % Maximum string length is 20.
%%------------------------------------
%% Declarations:
values('S',[['S','S'],a,b],[0.4,0.5,0.1]).
% We use a msw of the form msw('S',V) such
% that V is one of { ['S','S'], a, b },
% and when msw('S',V) is executed, the prob.
% of V=['S','S'] is 0.4, that of V=a is 0.5
% and that of V=b is 0.1.
%%------------------------------------
%% Modeling part:
start_symbol('S'). % Start symbol is S
pdcg(L):-
start_symbol(I),
pdcg2(I,L-[]).
% I is a category to expand.
pdcg2(I,L0-L2):- % L0-L2 is a list for I to span.
msw(I,RHS), % Choose a rule I -> RHS probabilistically.
( RHS == ['S','S'],
pdcg2('S',L0-L1),
pdcg2('S',L1-L2)
; RHS == a,
L0 = [RHS | L2]
; RHS == b,
L0 = [RHS | L2] ).
%%------------------------------------
%% Utility part:
pdcg_learn(N):-
max_str_len(MaxStrL),
get_samples_c(N,pdcg(X),(length(X,Y),Y =< MaxStrL),Goals,[Ns,_]),
format("#sentences= ~d~n",[Ns]),
unfix_sw('S'), % Make parameters of msw('S',.) changable
learn(Goals). % Conduct ML estimation by graphical EM learning

View File

@ -0,0 +1,121 @@
%%%%
%%%% Probabilistic DCG for Charniak's example --- pdcg_c.psm
%%%%
%%%% Copyright (C) 2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% As described in the comments in pdcg.psm, PCFGs (probabilistic context-
%% free grammars) are a stochastic extension of CFG grammar such that in a
%% (leftmost) derivation, each production rule is selected probabilistically
%% and applied. This program presents an implementation of an example from
%% Charniak's textbook (Statistical Language Learning, The MIT Press, 1993):
%%
%% s --> np vp (0.8) | verb --> swat (0.2)
%% s --> vp (0.2) | verb --> flies (0.4)
%% np --> noun (0.4) | verb --> like (0.4)
%% np --> noun pp (0.4) | noun --> swat (0.05)
%% np --> noun np (0.2) | noun --> flies (0.45)
%% vp --> verb (0.3) | noun --> ants (0.5)
%% vp --> verb np (0.3) | prep --> like (1.0)
%% vp --> verb pp (0.2) |
%% vp --> verb np pp (0.2) |
%% pp --> prep np (1.0) |
%% (`s' is the start symbol)
%%
%% This program has a grammar-independent part (pcfg/1-2 and proj/2),
%% which can work with any underlying CFG which has no epsilon rules
%% and produces no unit cycles.
%%----------------------------------
%% Quick start:
%%
%% ?- prism(pdcg_c).
%%
%% ?- prob(pcfg([swat,flies,like,ants])).
%% % get the generative probability of a sentence
%% % "swat flies like ants"
%%
%% ?- sample(pcfg(_X)),viterbif(pcfg(_X)).
%% % parse a sampled sentence
%%
%% ?- get_samples(50,pcfg(X),_Gs),learn(_Gs),show_sw.
%% % conduct an artificial learning experiments
%%
%% ?- viterbif(pcfg([swat,flies,like,ants])).
%% % get the most probabile parse for "swat flies like ants"
%%
%% ?- n_viterbif(3,pcfg([swat,flies,like,ants])).
%% % get top 3 ranked parses for "swat flies like ants"
%%
%% ?- viterbit(pcfg([swat,flies,like,ants])).
%% % print the most probabile parse for "swat flies like ants" in
%% % a tree form.
%%
%% ?- viterbit(pcfg([swat,flies,like,ants]),P,E), build_tree(E,T).
%% % get the most probabile parse for "swat flies like ants" in a
%% % tree form, and convert it to a more readable Prolog term.
%%
%% ?- probfi(pcfg([swat,flies,like,ants])).
%% % print the parse forest with inside probabilities
%%
%%----------------------------------
%% Declarations:
values(s,[[np,vp],[vp]]).
values(np,[[noun],[noun,pp],[noun,np]]).
values(vp,[[verb],[verb,np],[verb,pp],[verb,np,pp]]).
values(pp,[[prep,np]]).
values(verb,[[swat],[flies],[like]]).
values(noun,[[swat],[flies],[ants]]).
values(prep,[[like]]).
:- p_not_table proj/2. % This declaration is introduced just for
% making the results of probabilistic inferences
% simple and readable.
%%----------------------------------
%% Modeling part:
pcfg(L):- pcfg(s,L-[]).
pcfg(LHS,L0-L1):-
( nonterminal(LHS) -> msw(LHS,RHS),proj(RHS,L0-L1)
; L0 = [LHS|L1]
).
proj([],L-L).
proj([X|Xs],L0-L1):-
pcfg(X,L0-L2),proj(Xs,L2-L1).
nonterminal(s).
nonterminal(np).
nonterminal(vp).
nonterminal(pp).
nonterminal(verb).
nonterminal(noun).
nonterminal(prep).
%%----------------------------------
%% Utility part:
% set the rule probabilities:
:- set_sw(s,[0.8,0.2]).
:- set_sw(np,[0.4,0.4,0.2]).
:- set_sw(vp,[0.3,0.3,0.2,0.2]).
:- set_sw(pp,[1.0]).
:- set_sw(verb,[0.2,0.4,0.4]).
:- set_sw(noun,[0.05,0.45,0.5]).
:- set_sw(prep,[1.0]).
% build_tree(E,T):-
% Build a parse tree T from a tree-formed explanation E.
build_tree([],[]).
build_tree([pcfg(_),Gs],T) :- build_tree(Gs,T).
build_tree([pcfg(Sym,_)|Gs],T) :- build_tree1(Gs,T0),T=..[Sym|T0].
build_tree1([],[]).
build_tree1([pcfg(Sym,_)|Gs],[Sym|T]) :- !,build_tree1(Gs,T).
build_tree1([msw(_,_)|Gs],T) :- !, build_tree1(Gs,T).
build_tree1([G|Gs],[T0|T]) :- build_tree(G,T0),!,build_tree1(Gs,T).

View File

@ -0,0 +1,44 @@
%% This data was created by Rose.
%% see http://bibiserv.techfak.uni-bielefeld.de/rose
%% Rose
%% Copyright (c) 1997-2000 University of Bielefeld, Germany and
%% Deutsches Krebsforschungszentrum (DKFZ) Heidelberg, Germany.
%% All rights reserved.
%%
%% correct alignments
%%
%% HLKIANRKDK----HHNKEFGGHHLA
%% HLKATHRKDQ----HHNREFGGHHLA
%% VLKFANRKSK----HHNKEMGAHHLA
%% HKKGAT---------------PVNVS
%% HKKGATATG-----------NPKHVC
%% QFKVAAAVGK----HQDASRGVHHID
%% SFKGQGAVSK----HQDPEWGVHHID
%% SFKGQGAVSV----PQAPAWGINHID
%% HFKSQAEVNK----HDRPEWGLNQID
%% HFRSQAEVNQRQFNHHRPQWSFNQIG
%% SFNVVKGASK----RENGGMGAEPVD
%% KFKKVDGLGK----KEHPALGVH---
%% KFMVGGKDGK----NRKDAHAHRKVE
%% KYKVPEKDGK----KRTNAHSHRKVE
%% RYKIPESDGK----KRTNSHRHRKVE
%% RYKIASMDGK----KRYAEHKHKKLE
observe( ['H','L','K','I','A','N','R','K','D','K','H','H','N','K','E','F','G','G','H','H','L','A'] ).
observe( ['H','L','K','A','T','H','R','K','D','Q','H','H','N','R','E','F','G','G','H','H','L','A'] ).
observe( ['V','L','K','F','A','N','R','K','S','K','H','H','N','K','E','M','G','A','H','H','L','A'] ).
observe( ['H','K','K','G','A','T','P','V','N','V','S'] ).
observe( ['H','K','K','G','A','T','A','T','G','N','P','K','H','V','C'] ).
observe( ['Q','F','K','V','A','A','A','V','G','K','H','Q','D','A','S','R','G','V','H','H','I','D'] ).
observe( ['S','F','K','G','Q','G','A','V','S','K','H','Q','D','P','E','W','G','V','H','H','I','D'] ).
observe( ['S','F','K','G','Q','G','A','V','S','V','P','Q','A','P','A','W','G','I','N','H','I','D'] ).
observe( ['H','F','K','S','Q','A','E','V','N','K','H','D','R','P','E','W','G','L','N','Q','I','D'] ).
observe( ['H','F','R','S','Q','A','E','V','N','Q','R','Q','F','N','H','H','R','P','Q','W','S','F','N','Q','I','G'] ).
observe( ['S','F','N','V','V','K','G','A','S','K','R','E','N','G','G','M','G','A','E','P','V','D'] ).
observe( ['K','F','K','K','V','D','G','L','G','K','K','E','H','P','A','L','G','V','H'] ).
observe( ['K','F','M','V','G','G','K','D','G','K','N','R','K','D','A','H','A','H','R','K','V','E'] ).
observe( ['K','Y','K','V','P','E','K','D','G','K','K','R','T','N','A','H','S','H','R','K','V','E'] ).
observe( ['R','Y','K','I','P','E','S','D','G','K','K','R','T','N','S','H','R','H','R','K','V','E'] ).
observe( ['R','Y','K','I','A','S','M','D','G','K','K','R','Y','A','E','H','K','H','K','K','L','E'] ).

263
packages/prism/exs/phmm.psm Normal file
View File

@ -0,0 +1,263 @@
%%%%
%%%% Profile HMM --- phmm.psm
%%%%
%%%% Copyright (C) 2004,2006,2007,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% Profile HMMs are a variant of HMMs that have three types of states,
%% i.e. `match state',`insert state' and `delete state.' Match states
%% constitute an HMM that outputs a `true' string. Insertion states
%% emit a symbol additionally to the `true' string whereas delete (skip)
%% states emit no symbol.
%%
%% Profile HMMs are used to align amino-acid sequences by inserting
%% and skipping symbols as well as matching symbols. For example
%% amino-acid sequences below
%%
%% HLKIANRKDKHHNKEFGGHHLA
%% HLKATHRKDQHHNREFGGHHLA
%% VLKFANRKSKHHNKEMGAHHLA
%% ...
%%
%% are aligned by the profile HMM program in this file as follows.
%%
%% -HLKIA-NRKDK-H-H----NKEFGGHH-LA
%% -HLK-A-T-HRK-DQHHN--R-EFGGHH-LA
%% -VLKFA-NRKSK-H-H----NKEMGAHH-LA
%% ...
%%-------------------------------------
%% Quick start : sample session, align the sample data in phmm.dat.
%%
%% To run on an interactive session:
%% ?- prism(phmm),go. (ML/MAP)
%% ?- prism(phmm),go_vb. (variational Bayes)
%%
%% To perform a batch execution:
%% > upprism phmm
go :-
read_goals(Gs,'phmm.dat'), % Read the sequence data from phmm.dat.
learn(Gs), % Learn parameters from the data.
wmag(Gs). % Compute viterbi paths using the learned
% parameters and aligns sequences in Gs.
% To enable variational Bayes, we need some additional flag settings:
go_vb :-
set_prism_flag(learn_mode,both),
set_prism_flag(viterbi_mode,hparams),
set_prism_flag(reset_hparams,on),
go.
prism_main :- go.
%prism_main :- go_vb.
%%%--------------------- model ---------------------
observe(Sequence) :- hmm(Sequence,start).
hmm([],end).
hmm(Sequence,State) :-
State \== end,
msw(move_from(State),NextState),
msw(emit_at(State), Symbol),
( Symbol = epsilon ->
hmm( Sequence, NextState )
; Sequence = [Symbol|TailSeq],
hmm( TailSeq , NextState )
).
amino_acids(['A','C','D','E','F','G','H','I','K','L','M','N','P','Q','R',
'S','T','V','W','X','Y']).
hmm_len(17).
%%%--------------------- values ---------------------
values(move_from(State),Values) :-
hmm_len(Len),
get_index(State,X),
( 0 =< X, X < Len ->
Y is X + 1,
Values = [insert(X),match(Y),delete(Y)]
; Values = [insert(X),end] ).
values(emit_at(State),Vs) :-
((State = insert(_) ; State = match(_)) ->
amino_acids(Vs)
; Vs = [epsilon] ).
%%%--------------------- set_sw ---------------------
:- init_set_sw.
init_set_sw :-
% tell('/dev/null'), % Suppress output (on Linux only)
set_sw( move_from(start) ),
set_sw( move_from(insert(0)) ),
set_sw( emit_at(start) ),
set_sw( emit_at(insert(0)) ),
hmm_len(Len),
% told,
init_set_sw(Len).
init_set_sw(0).
init_set_sw(X) :-
X > 0,
set_sw( move_from(insert(X)) ),
set_sw( move_from(match(X)) ),
set_sw( move_from(delete(X)) ),
set_sw( emit_at(insert(X)) ),
set_sw( emit_at(match(X)) ),
set_sw( emit_at(delete(X)) ),
Y is X - 1,
init_set_sw(Y).
%%%--------------------- estimation ---------------------
%% most likely path
%% mlpath(['A','E'],Path) => Path = [start,match(1),end]
mlpath(Sequence,Path):-
mlpath(Sequence,Path,_).
mlpath(Sequence,Path,Prob):-
viterbif(hmm(Sequence,start),Prob,Nodes),
nodes2path(Nodes,Path).
nodes2path([Node|Nodes],[State|Path]):-
Node = node(hmm(_,State),_),
nodes2path(Nodes,Path).
nodes2path([],[]).
mlpaths([Seq|Seqs],[Path|Paths], X):-
mlpath(Seq,Path),
X= [P|_], writeln(P),
stop_low_level_trace,
mlpaths(Seqs,Paths, X).
mlpaths([],[],_).
%%%--------------------- alignment ---------------------
wmag(Gs):-
seqs2goals(S,Gs),wma(S).
wma(Seqs):-
write_multiple_alignments(Seqs).
write_multiple_alignments(Seqs):-
nl,
write('search Viterbi paths...'),nl,
mlpaths(Seqs,Paths,Paths),
write('done.'),
nl,
write('------------ALIGNMENTS------------'),
nl,
write_multiple_alignments( Seqs, Paths ),
write('----------------------------------'),
nl.
make_max_length_list([Path|Paths],MaxLenList) :-
make_max_length_list(Paths, TmpLenList),
make_length_list(Path,LenList),
marge_len_list(LenList,TmpLenList,MaxLenList).
make_max_length_list([Path],MaxLenList) :-
!,make_length_list(Path,MaxLenList).
marge_len_list([H1|T1],[H2|T2],[MargedH|MargedT]) :-
max(MargedH,[H1,H2]),
marge_len_list(T1,T2,MargedT).
marge_len_list([],[],[]).
%% make_length_list([start,insert(0),match(1),end],LenList)
%% -> LenList = [2,1]
%% make_length_list([start,delete(1),insert(1),insert(1),end],LenList)
%% -> LenList = [1,1]
make_length_list(Path,[Len|LenList]) :-
count_emission(Path,Len,NextIndexPath),
make_length_list(NextIndexPath,LenList).
make_length_list([end],[]).
count_emission(Path,Count,NextIndexPath) :-
Path = [State|_],
get_index(State,Index),
count_emission2(Path,Count,Index,NextIndexPath).
%% count_emission2([start,insert(0),match(1),end],Count,0,NextIndexPath)
%% -> Count = 2, NextIndexPath = [match(1),end]
%% count_emission2([delete(1),insert(1),insert(1),end],Count,1,NextIndexPath)
%% -> Count = 2, NextIndexPath = [end]
count_emission2([State|Path],Count,Index,NextIndexPath) :-
( get_index(State,Index) ->
count_emission2( Path, Count2, Index, NextIndexPath ),
( (State = delete(_); State==start) ->
Count = Count2
; Count is Count2 + 1 )
; Count = 0,
NextIndexPath = [State|Path]
).
write_multiple_alignments(Seqs,Paths) :-
make_max_length_list(Paths,LenList),
write_multiple_alignments(Seqs,Paths,LenList).
write_multiple_alignments([Seq|Seqs],[Path|Paths],LenList) :-
write_alignment(Seq,Path,LenList),
write_multiple_alignments(Seqs,Paths,LenList).
write_multiple_alignments([],[],_).
write_alignment(Seq,Path,LenList) :-
write_alignment(Seq,Path,LenList,0).
write_alignment([],[end],[],_):- !,nl.
write_alignment(Seq,[State|Path],LenList,Index) :-
get_index(State,Index),!,
( (State = delete(_) ; State == start) ->
write_alignment( Seq, Path, LenList, Index )
; Seq = [Symbol|Seq2],
LenList = [Len|LenList2],
write(Symbol),
Len2 is Len - 1,
write_alignment(Seq2,Path,[Len2|LenList2],Index)
).
write_alignment(Seq,[State|Path],LenList,Index) :-
LenList = [Len|LenList2],
Index2 is Index + 1,
pad(Len),
write_alignment(Seq,[State|Path],LenList2,Index2).
pad(Len) :-
Len > 0,
write('-'),
Len2 is Len - 1,!,
pad(Len2).
pad(0).
%%%--------------------- utility ---------------------
get_index(State,Index) :-
(State=match(_),!,State=match(Index));
(State=insert(_),!,State=insert(Index));
(State=delete(_),!,State=delete(Index));
(State=start,!,Index=0);
(State=end,!,hmm_len(X),Index is X+1).
seqs2goals([Seq|Seqs],[Goal|Goals]) :-
Goal = observe(Seq),
seqs2goals(Seqs,Goals).
seqs2goals([],[]).
max(Max,[Head|Tail]) :-
max(Tmp,Tail),!,
( Tmp > Head -> Max = Tmp ; Max = Head ).
max(Max,[Max]).
read_goals(Goals,FileName) :-
see(FileName),
read_goals(Goals),
seen.
read_goals(Goals) :-
read(Term),
( Term = end_of_file ->
Goals = []
; Goals = [Term|Goals1],
read_goals(Goals1)
).

View File

@ -0,0 +1,60 @@
pslc([adv,n,p,v,n,adv,adv,adv,adv,v,n,p,v]).
pslc([v,n,c,v,n,p,v,n,c,n,p,v]).
pslc([adv,n,p,v,n,adv,adv,v,n,p,v,n,c,v,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([n,p,v]).
pslc([adv,adv,v,n,p,v,n,c,adv,adv,v,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([n,p,v]).
pslc([adv,adv,n,c,n,p,v,n,p,v,n,p,v,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([n,p,v]).
pslc([adv,adv,v,n,c,adv,v,n,p,v]).
pslc([n,p,v]).
pslc([v,n,c,adv,v,n,c,n,p,v,n,p,v]).
pslc([v,n,c,n,c,v,n,p,v]).
pslc([adv,adv,v,n,c,adv,v,n,c,adv,n,p,v,n,c,n,p,v,n,v,n,p,v]).
pslc([n,p,v]).
pslc([adv,n,p,v,n,c,v,n,p,v,n,v,n,p,v]).
pslc([v,n,c,n,p,v,n,p,v]).
pslc([n,c,v,n,c,n,c,n,p,v,n,p,v,n,p,v]).
pslc([v,n,c,n,p,v,n,c,adv,adv,v,n,p,v]).
pslc([adv,adv,v,n,c,v,n,p,v]).
pslc([n,p,v,n,c,adv,v,n,v,n,p,v]).
pslc([v,n,c,n,p,v,n,c,v,n,p,v]).
pslc([n,p,v]).
pslc([adv,adv,v,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([v,n,p,v]).
pslc([adv,adv,adv,n,p,v,n,p,v,n,c,v,n,v,n,c,v,n,p,v,n,c,n,p,v,n,c,n,p,v]).
pslc([v,n,p,v,n,p,v]).
pslc([v,n,p,v]).
pslc([n,c,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([adv,adv,v,n,v,n,c,adv,v,n,n,p,v,n,c,n,c,n,p,v,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([n,p,v,n,p,v]).
pslc([adv,n,adv,adv,v]).
pslc([adv,v,n,p,v,n,v,n,c,v,n,c,v,n,c,n,p,v,n,p,v,n,c,v,n,c,v,n,p,v]).
pslc([adv,adv,v,n,p,v,n,c,v,n,c,v,n,c,adv,v,n,p,v,n,p,v,n,p,v]).
pslc([n,p,v,n,p,v,n,p,v]).
pslc([n,p,v,n,c,adv,adv,v,n,p,v,n,v,n,p,v]).
pslc([adv,v,n,p,v,n,p,v]).
pslc([adv,adv,v,n,p,v]).
pslc([adv,adv,v,n,p,v,n,p,v]).
pslc([v,n,p,v]).
pslc([adv,n,p,v,n,c,adv,adv,v,n,v,n,n,p,v]).
pslc([n,p,v]).
pslc([adv,n,p,v,n,p,v]).
pslc([adv,n,p,v,n,adv,adv,v,n,c,n,p,v,n,p,v,n,c,v,n,p,v]).
pslc([n,p,v]).
pslc([n,c,v,n,c,n,p,v,n,c,adv,v,n,v,n,p,v]).
pslc([n,p,v,n,p,v,n,p,v,n,p,v]).
pslc([v,n,p,v,n,p,v]).
pslc([v,n,c,adv,v,n,c,n,p,v,n,p,v,n,c,adv,adv,v,n,p,v,n,p,v]).
pslc([n,p,v]).
pslc([v,n,p,v,n,p,v,n,c,adv,adv,v,n,p,v,n,v,n,p,v,n,p,v,n,p,v,n,p,v]).
pslc([v,n,p,v]).
pslc([n,p,v]).
pslc([n,c,adv,adv,v,n,p,v]).
pslc([n,p,v]).

215
packages/prism/exs/plc.psm Normal file
View File

@ -0,0 +1,215 @@
%%%%
%%%% Probablistic left corner grammar --- plc.psm
%%%%
%%%% Copyright (C) 2004,2006,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This is a PRISM program modeling a probabilistic left-corner
%% parser (stack version) described in
%%
%% "Probabilistic Parsing using left corner language models",
%% C.D.Manning,
%% Proc. of the 5th Int'l Conf. on Parsing Technologies (IWPT-97),
%% MIT Press, pp.147-158.
%%
%% Note that this program defines a distribution over sentences
%% procedurally, i.e. the derivation process is described in terms
%% of stack operations. Also note that we automatically get
%% a correctness-guaranteed EM procedure for probablistic
%% left-corner grammars.
%%-------------------------------------
%% Quick start : sample session with Grammar_1 (attached below)
%%
%% (1) Move to a directory where this program is placed.
%% (2) Start PRISM (no options needed since 1.10)
%%
%% > prism
%%
%% (3) Load this program (by default, every msw is given a uniform
%% distribution)
%%
%% ?- prism(plc).
%%
%% (4) Use uitilities, e.g.
%% (4-1) Computing explanation (support) graphs and probabilities
%%
%% ?- prob(pslc([n,p,v])).
%% ?- probf(pslc([n,p,v])).
%% ?- probf(pslc([n,p,v]),E),print_graph(E).
%% ?- prob(pslc([adv,adv,n,c,n,p,v])).
%% ?- probf(pslc([adv,adv,n,c,n,p,v])).
%% ?- probf(pslc([adv,adv,n,c,n,p,v]),E),print_graph(E).
%%
%% Pv is prob. of a most likely explanation E for pslc([adv,...,v])
%% ?- viterbif(pslc([adv,adv,n,c,n,p,v]),Pv,E).
%% ?- viterbi(pslc([adv,adv,n,c,n,p,v]),Pv).
%%
%% (4-2) Sampling
%%
%% ?- sample(pslc(X)), sample(pslc(Y)), sample(pslc(Z)).
%%
%% (4-3) Graphical EM learning for Grammar_1 (wait for some time)
%%
%% ?- go.
go:- plc_learn(50). % Generate randomly 50 sentences and learn
max_str_len(30). % Sentence length <= 30
%%------------------------------------
%% Modeling part:
pslc(Ws) :-
start_symbol(C), % asserted in Grammar_1
pslc(Ws,[g(C)]). % C is a top-goal category
pslc([],[]).
pslc(L0,Stack0) :-
process(Stack0,Stack,L0,L),
pslc(L,Stack).
%% shift operation
process([g(A)|Rest],Stack,[Wd|L],L):- % g(A) is a goal category
( terminal(A), % Stack given = [g(A),g(F),D...] created
A = Wd, Stack = Rest % by e.g. projection using E -> D,A,F
; \+ terminal(A), % Select probabilistically one of first(A)
( get_values(first(A),[Wd]) % No choice if the first set is a singleton
; get_values(first(A),[_,_|_]), % Select 1st word by msw
msw(first(A),Wd) ),
Stack = [Wd,g(A)|Rest]
).
%% projection and attachment
process([A|Rest],Stack,L,L):- % a subtree with top=A is completed
\+ A = g(_), % A's right neighbor has the form g(_)
Rest = [g(C)|Stack0], % => A is not a terminal
( A == C, % g(A) is waiting for an A-tree
( get_values(lc(A,A),_), % lc(X,Y) means X - left-corner -> Y
msw(attach(A),Op), % A must have a chance of not attaching
( Op == attach, Stack = Stack0 % attachment
; Op == project, next_Stack(A,Rest,Stack) ) % projection
; \+ get_values(lc(A,A),_),
Stack = Stack0 ) % forcible attachment for nonterminal
; A \== C,
next_Stack(A,Rest,Stack) ).
%% projection % subtree A completed, waited for by g(C)
next_Stack(A,[g(C)|Rest2],Stack) :- % rule I -> A J K
( get_values(lc(C,A),[_,_|_]), % => Stack=[g(J),g(K),I,g(C)...]
msw(lc(C,A),rule(LHS,[A|RHS2])) % if C - left-corner -> A
; get_values(lc(C,A),[rule(LHS,[A|RHS2])]) ), % no other rules for projection
predict(RHS2,[LHS,g(C)|Rest2],Stack).
predict([],L,L).
predict([A|Ls],L2,[g(A)|NewLs]):-
predict(Ls,L2,NewLs).
%%------------------------------------
%% Utility part:
plc_learn(N):-
gen_plc(N,Goals),
learn(Goals).
gen_plc(0,[]).
gen_plc(N,Goals):-
N > 0,
N1 is N-1,
sample(pslc(L)),
length(L,K),
max_str_len(StrL),
( K > StrL,
Goals = G2
; Goals=[pslc(L)|G2],
format(" G = ~w~n",[pslc(L)])
),!,
gen_plc(N1,G2).
%%--------------- Grammar_1 -----------------
start_symbol(s).
rule(s,[pp,v]).
rule(s,[ap,vp]).
rule(vp,[pp,v]).
rule(vp,[ap,v]).
rule(np,[vp,n]).
rule(np,[v,n]).
rule(np,[n]).
rule(np,[np,c,np]).
rule(np,[ap,np]).
rule(pp,[np,p]).
rule(pp,[n,p]).
rule(ap,[adv,adv]).
rule(ap,[adv]).
rule(ap,[adv,np]).
terminal(v).
terminal(n).
terminal(c).
terminal(p).
terminal(adv).
%% first set computed from Grammar_1
first(vp,v).
first(np,v).
first(pp,v).
first(s,v).
first(vp,n).
first(np,n).
first(pp,n).
first(s,n).
first(vp,adv).
first(ap,adv).
first(np,adv).
first(pp,adv).
first(s,adv).
%%------------------------------------
%% Declarations:
%%
%% created from Grammar_1
values(lc(s,pp),[rule(s,[pp,v]),rule(vp,[pp,v])]).
values(lc(s,np),[rule(np,[np,c,np]),rule(pp,[np,p])]).
values(lc(s,vp),[rule(np,[vp,n])]).
values(lc(pp,np),[rule(np,[np,c,np]),rule(pp,[np,p])]).
values(lc(pp,vp),[rule(np,[vp,n])]).
values(lc(pp,pp),[rule(vp,[pp,v])]).
values(lc(np,vp),[rule(np,[vp,n])]).
values(lc(np,pp),[rule(vp,[pp,v])]).
values(lc(np,np),[rule(np,[np,c,np]),rule(pp,[np,p])]).
values(lc(vp,pp),[rule(vp,[pp,v])]).
values(lc(vp,np),[rule(np,[np,c,np]),rule(pp,[np,p])]).
values(lc(vp,vp),[rule(np,[vp,n])]).
values(lc(vp,ap),[rule(np,[ap,np]),rule(vp,[ap,v])]).
values(lc(vp,adv),[rule(ap,[adv]),rule(ap,[adv,adv]),rule(ap,[adv,np])]).
values(lc(ap,adv),[rule(ap,[adv]),rule(ap,[adv,adv]),rule(ap,[adv,np])]).
values(lc(vp,v),[rule(np,[v,n])]).
values(lc(vp,n),[rule(np,[n]),rule(pp,[n,p])]).
values(lc(np,v),[rule(np,[v,n])]).
values(lc(np,n),[rule(np,[n]),rule(pp,[n,p])]).
values(lc(np,ap),[rule(np,[ap,np]),rule(vp,[ap,v])]).
values(lc(np,adv),[rule(ap,[adv]),rule(ap,[adv,adv]),rule(ap,[adv,np])]).
values(lc(pp,n),[rule(np,[n]),rule(pp,[n,p])]).
values(lc(pp,ap),[rule(np,[ap,np]),rule(vp,[ap,v])]).
values(lc(pp,adv),[rule(ap,[adv]),rule(ap,[adv,adv]),rule(ap,[adv,np])]).
values(lc(pp,v),[rule(np,[v,n])]).
values(lc(s,ap),[rule(np,[ap,np]),rule(s,[ap,vp]),rule(vp,[ap,v])]).
values(lc(s,adv),[rule(ap,[adv]),rule(ap,[adv,adv]),rule(ap,[adv,np])]).
values(lc(s,v),[rule(np,[v,n])]).
values(lc(s,n),[rule(np,[n]),rule(pp,[n,p])]).
values(first(s),[adv,n,v]).
values(first(vp),[adv,n,v]).
values(first(np),[adv,n,v]).
values(first(pp),[adv,n,v]).
values(first(ap),[adv]).
values(attach(s),[attach,project]).
values(attach(vp),[attach,project]).
values(attach(np),[attach,project]).
values(attach(pp),[attach,project]).
values(attach(ap),[attach,project]).

130
packages/prism/exs/sbn.psm Normal file
View File

@ -0,0 +1,130 @@
%%%%
%%%% Bayesian networks (2) -- sbn.psm
%%%%
%%%% Copyright (C) 2004,2008
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% This example shows how to simulate Pearl's message passing
%% (without normalization) for singly connected BNs (Bayesian networks).
%%
%% Suppose that we have a Bayesian network in Fiugre 1 and that
%% we wish to compute marginal probabilites P(B) of B.
%% The distribution defined by the BN in Figure 1 is expressed
%% by a BN program in Figure 3. We transform it into another
%% program that defines the same marginal distribuion for B.
%%
%% Original graph Transformed graph
%%
%% A B B
%% / \ / |
%% / \ / v
%% C D ==> D
%% / \ / | \
%% / \ / v v
%% E F A E F
%% /
%% v
%% C
%% (Figure 1) (Figure 2)
%%
%% Original BN program for Figure 1
%%
world(VA,VB,VC,VD,VE,VF):-
msw(par('A',[]),VA), msw(par('B',[]),VB),
msw(par('C',[VA]),VC), msw(par('D',[VA,VB]),VD),
msw(par('E',[VD]),VE), msw(par('F',[VD]),VF).
check_B(VB):- world(_,VB,_,_,_,_).
%%
%% (Figure 3)
%%
%% Transformation:
%% [Step 1] Transform the orignal BN in Figure 1 into Figure 2 by letting
%% B be the top node and other nodes dangle from B.
%% [Step 2] Construct a program that calls nodes in Figure 2 from the top
%% node to leaves. For example for D, add clause
%%
%% call_BD(VB):- call_DA(VA),call_DE(VE),call_DF(VF).
%%
%% while inserting an msw expressing the CPT P(D|A,B) in the body. Here,
%%
%% call_XY(V) <=>
%% node Y is called from X with ground term V (=X's realization)
%%
%% It can be proved by unfolding that the transformed program is equivalent
%% in distribution semantics to the original program in Figure 3.
%% => Both programs compute the same marginal distribution for B.
%% Confirm by ?- prob(ask_B(2),X),prob(check_B(2),Y).
%%-------------------------------------
%% Quick start : sample session
%%
%% ?- prism(sbn),go. % Learn parameters from randomly generated
%% % 100 samples while preserving the marginal
%% % disribution P(B)
%%
%% ?- prob(ask_B(2)).
%% ?- prob(ask_B(2),X),prob(check_B(2),Y). % => X=Y
%% ?- probf(ask_B(2)).
%% ?- sample(ask_B(X)).
%%
%% ?- viterbi(ask_B(2)).
%% ?- viterbif(ask_B(2),P,E),print_graph(E).
go:- sbn_learn(100).
%%------------------------------------
%% Declarations:
values(par('A',[]), [0,1]). % Declare msw(par('A',[]),VA) where
values(par('B',[]), [2,3]). % VA is one of {0,1}
values(par('C',[_]), [4,5]).
values(par('D',[_,_]),[6,7]). % Declare msw(par('D',[VA,VB]),VD) where
values(par('E',[_]), [8,9]). % VD is one of {6,7}
values(par('F',[_]), [10,11]).
set_params:- % Call set_sw/2 built-in
set_sw(par('A',[]), [0.3,0.7]),
set_sw(par('B',[]), uniform), % => [0.5,0.5]
set_sw(par('C',[0]), f_geometric(3,asc)), % => [0.25,0.75]
set_sw(par('C',[1]), f_geometric(3,desc)), % => [0.75,0.25]
set_sw(par('D',[0,2]),f_geometric(3)), % => [0.75,0.25]
set_sw(par('D',[1,2]),f_geometric(2)), % => [0.666...,0.333...]
set_sw(par('D',[0,3]),f_geometric), % => [0.666...,0.333...]
set_sw(par('D',[1,3]),[0.3,0.7]),
set_sw(par('E',[6]), [0.3,0.7]),
set_sw(par('E',[7]), [0.1,0.9]),
set_sw(par('F',[6]), [0.3,0.7]),
set_sw(par('F',[7]), [0.1,0.9]).
:- set_params.
%%------------------------------------
%% Modeling part: transformed program defining P(B)
ask_B(VB) :- % ?- prob(ask_B(2),X)
msw(par('B',[]),VB), % => X = P(B=2)
call_BD(VB).
call_BD(VB):- % msw's Id must be ground
call_DA(VA), % => VA must be ground
msw(par('D',[VA,VB]),VD), % => call_DA(VA)
call_DE(VD), % before msw(par('D',[VA,VB]),VD)
call_DF(VD).
call_DA(VA):-
msw(par('A',[]),VA),
call_AC(VA).
call_AC(VA):-
msw(par('C',[VA]),_VC).
call_DE(VD):-
msw(par('E',[VD]),_VE).
call_DF(VD):-
msw(par('F',[VD]),_VF).
%%------------------------------------
%% Utility part:
sbn_learn(N):- % Learn parameters (CPTs) from a list of
random_set_seed(123456), % N randomly generated ask_B(.) atoms
set_params,
get_samples(N,ask_B(_),Goals),
learn(Goals).

View File

@ -0,0 +1,112 @@
%%%%
%%%% Evaluation of a naive Bayes classifier for `votes' dataset
%%%% --- votes.psm
%%%%
%%%% Copyright (C) 2009
%%%% Sato Laboratory, Dept. of Computer Science,
%%%% Tokyo Institute of Technology
%% In this program, we conduct n-fold cross validation of a naive Bayes
%% classifier. This program was created to demonstrate the usefulness of
%% the built-in predicates introduced since version 1.12. The target
%% dataset is the congressional voting records (`votes') dataset, which
%% is available from UCI machine learning repository (http://archive.ics.
%% uci.edu/ml/).
%%
%% From this program, it is seen that, using new built-in predicates such
%% as maplist/5, avglist/2, random_shuffle/2, and so on, we can make the
%% utility part compact, as well as the modeling part. Also one may find
%% that we only combine general-purpose built-ins to implement n-fold cross
%% validation.
%%-------------------------------------
%% Quick start : sample session
%%
%% (Preparation: Download the data file `house-votes-84.data' from UCI ML
%% repository, and put it `as-is' on the current directly)
%%
%% ?- prism(votes),votes_learn. % Learn parameters from the whole dataset
%%
%% ?- prism(votes),votes_cv(10). % Conduct 10-fold cross validation
%%
%%-------------------------------------
%% Declarations
values(class,[democrat,republican]). % class labels
values(attr(_,_),[y,n]). % all attributes have two values: y or n
%%-------------------------------------
%% Modeling part (a naive Bayes model)
%%
%% [Note]
%% According to `house-votes-84.names', a data description file for the
%% `votes' dataset, '?' simply denotes that the value is not "yea" nor
%% "nay". On the other hand, in this program, we consider '?' as a missing
%% value just for demonstration purpose.
nbayes(C,Vals):- msw(class,C),nbayes(1,C,Vals).
nbayes(_,_,[]).
nbayes(J,C,[V|Vals]):-
choose(J,C,V),
J1 is J+1,
nbayes(J1,C,Vals).
choose(J,C,V):-
( V == '?' -> msw(attr(J,C),_) % handling '?' as a missing value
; msw(attr(J,C),V0),
V = V0
).
%%-------------------------------------
%% Utility part:
%% Batch routine for a simple learning
votes_learn:-
load_data_file(Gs),
learn(Gs).
%% Batch routine for N-fold cross validation
votes_cv(N):-
random_set_seed(81729), % Fix the random seed to keep the same splitting
load_data_file(Gs0), % Load the entire data
random_shuffle(Gs0,Gs), % Randomly reorder the data
numlist(1,N,Ks), % Get Ks = [1,...,N] (B-Prolog built-in)
maplist(K,Rate,votes_cv(Gs,K,N,Rate),Ks,Rates),
% Call votes_cv/2 for K=1...N
avglist(Rates,AvgRate), % Get the avg. of the precisions
maplist(K,Rate,format("Test #~d: ~2f%~n",[K,Rate*100]),Ks,Rates),
format("Average: ~2f%~n",[AvgRate*100]).
%% Subroutine for learning and testing for K-th split data (K = 1...N)
votes_cv(Gs,K,N,Rate):-
format("<<<< Test #~d >>>>~n",[K]),
separate_data(Gs,K,N,Gs0,Gs1), % Gs0: training data, Gs1: test data
learn(Gs0), % Learn by PRISM's built-in
maplist(nbayes(C,Vs),R,(viterbig(nbayes(C0,Vs)),(C0==C->R=1;R=0)),Gs1,Rs),
% Predict the class by viterbig/1 for each test example
% and evaluate it with the answer class label
avglist(Rs,Rate), % Get the accuracy for the K-th splitting
format("Done (~2f%).~n~n",[Rate*100]).
%% Split the entire data (Data) into the training data (Train)
%% and the test data (Test) for the K-th evaluation (K=1...N)
separate_data(Data,K,N,Train,Test):-
length(Data,L),
L0 is L*(K-1)//N, % L0: offset of the test data (// - integer division)
L1 is L*(K-0)//N-L0, % L1: size of the test data
splitlist(Train0,Rest,Data,L0), % Length of Train0 = L0
splitlist(Test,Train1,Rest,L1), % Length of Test = L1
append(Train0,Train1,Train).
%% Load the `votes' data in CSV form and convert it to suitable
%% Prolog terms
load_data_file(Gs):-
load_csv('house-votes-84.data',Gs0),
maplist(csvrow([C|Vs]),nbayes(C,Vs),true,Gs0,Gs).

16
packages/prism/src/README Normal file
View File

@ -0,0 +1,16 @@
========================== README (src) ==========================
This directory contains the source files of the PRISM part, along
with a minimal set of source and binary files from B-Prolog,
required to build the PRISM system:
c/ ... C code
prolog/ ... Prolog code
Please use/modify/distribute the source code based on the license
agreements described $(TOP)/LICENSE and $(TOP)/LICENSE.src, where
$(TOP) is the top directory in the unfolded package.
To build the PRISM system, we need to compile both C and Prolog
source files. Please follow the instructions described in READMEs
at the `c' and `prolog' directories.

View File

@ -0,0 +1,91 @@
# -*- Makefile -*-
#
# 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
YAP_EXTRAS=@YAP_EXTRAS@ -D_YAP_NOT_INSTALLED_=1 -D__YAP_PROLOG__=1
#
#
CC=@CC@
CFLAGS= @SHLIB_CFLAGS@ $(YAP_EXTRAS) $(DEFS) -I$(srcdir) -I../../../.. -I$(srcdir)/../../../../include -I$(srcdir)/../../../../H -I$(srcdir)/../../../../library/dialect/bprolog/fli
LDFLAGS=@LDFLAGS@
#
#
# 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)
#
##----------------------------------------------------------------------
ifeq ($(PROCTYPE),mp)
SUBDIRS += $(MP_DIR)
OBJS += $(MP_OBJS)
endif
##----------------------------------------------------------------------
include $(srcdir)/makefiles/Makefile.files
S=/
O=o
SOBJS=prism.@SO@
#in some systems we just create a single object, in others we need to
# create a libray
all: $(SOBJS)
core/%.o: $(srcdir)/core/%.c
$(CC) -c $(CFLAGS) $< -o $@
up/%.o: $(srcdir)/up/%.c
$(CC) -c $(CFLAGS) $< -o $@
mp/%.o: $(srcdir)/mp/%.c
$(CC) -c $(CFLAGS) $< -o $@
@DO_SECOND_LD@prism.@SO@: $(OBJS)
@DO_SECOND_LD@ @SHLIB_LD@ $(LDFLAGS) -o $@ $(OBJS) @EXTRA_LIBS_FOR_DLLS@
all: $(TARGET)
install: $(TARGET)
$(INSTALL_PROGRAM) $(SOBJS) $(DESTDIR)$(YAPLIBDIR)
clean: clean_subdirs
$(RM) $(TARGET)
clean_subdirs:
for i in $(SUBDIRS); do \
($(MAKE) -f $(MAKEFILE) -C $$i clean ) \
done
##----------------------------------------------------------------------
.PHONY: all install clean $(SUBDIRS)
##----------------------------------------------------------------------

View File

@ -0,0 +1,401 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include "core/bpx.h"
#include "core/vector.h"
/*--------------------------------------------------------------------*/
#define REQUIRE_HEAP(n) \
( heap_top + (n) <= local_top ? \
(void)(0) : myquit(STACK_OVERFLOW, "stack + heap") )
/*--------------------------------------------------------------------*/
/* Functions from B-Prolog */
/* cpred.c */
int bp_string_2_term(const char *, TERM, TERM);
char* bp_term_2_string(TERM);
int bp_call_term(TERM);
int bp_mount_query_term(TERM);
int bp_next_solution(void);
/* file.c */
void write_term(TERM);
/* float1.c */
double floatval(TERM);
TERM encodefloat1(double);
/* loader.c */
SYM_REC_PTR insert(const char *, int, int);
/* mic.c */
NORET quit(const char *);
NORET myquit(int, const char *);
/* unify.c */
int unify(TERM, TERM);
int is_UNIFIABLE(TERM, TERM);
int is_IDENTICAL(TERM, TERM);
/* prism.c */
NORET bp4p_quit(int);
/*--------------------------------------------------------------------*/
static NORET bpx_raise(const char *fmt, ...)
{
va_list ap;
fprintf(curr_out, "*** {PRISM BPX ERROR: ");
va_start(ap, fmt);
vfprintf(curr_out, fmt, ap);
va_end(ap);
fprintf(curr_out, "}\n");
bp4p_quit(1);
}
/*--------------------------------------------------------------------*/
bool bpx_is_var(TERM t)
{
XDEREF(t);
return ISREF(t);
}
bool bpx_is_atom(TERM t)
{
XDEREF(t);
return ISATOM(t);
}
bool bpx_is_integer(TERM t)
{
XDEREF(t);
return ISINT(t);
}
bool bpx_is_float(TERM t)
{
XDEREF(t);
return ISNUM(t);
}
bool bpx_is_nil(TERM t)
{
XDEREF(t);
return ISNIL(t);
}
bool bpx_is_list(TERM t)
{
XDEREF(t);
return ISLIST(t);
}
bool bpx_is_structure(TERM t)
{
XDEREF(t);
return ISSTRUCT(t);
}
bool bpx_is_compound(TERM t)
{
XDEREF(t);
return ISCOMPOUND(t);
}
bool bpx_is_unifiable(TERM t1, TERM t2)
{
XDEREF(t1);
XDEREF(t2);
return (bool)(is_UNIFIABLE(t1, t2));
}
bool bpx_is_identical(TERM t1, TERM t2)
{
XDEREF(t1);
XDEREF(t2);
return (bool)(is_IDENTICAL(t1, t2));
}
/*--------------------------------------------------------------------*/
TERM bpx_get_call_arg(BPLONG i, BPLONG arity)
{
if (i < 1 || i > arity) {
bpx_raise("index out of range");
}
return ARG(i, arity);
}
BPLONG bpx_get_integer(TERM t)
{
XDEREF(t);
if (ISINT(t)) {
return INTVAL(t);
}
else {
bpx_raise("integer expected");
}
}
double bpx_get_float(TERM t)
{
XDEREF(t);
if (ISINT(t)) {
return (double)(INTVAL(t));
}
else if (ISFLOAT(t)) {
return floatval(t);
}
else {
bpx_raise("integer or floating number expected");
}
}
const char * bpx_get_name(TERM t)
{
XDEREF(t);
switch (XTAG(t)) {
case STR:
return GET_NAME_STR(GET_STR_SYM_REC(t));
case ATM:
return GET_NAME_ATOM(GET_ATM_SYM_REC(t));
case LST:
return ".";
default:
bpx_raise("callable expected");
}
}
int bpx_get_arity(TERM t)
{
XDEREF(t);
switch (XTAG(t)) {
case STR:
return GET_ARITY_STR(GET_STR_SYM_REC(t));
case ATM:
return GET_ARITY_ATOM(GET_ATM_SYM_REC(t));
case LST:
return 2;
default:
bpx_raise("callable expected");
}
}
TERM bpx_get_arg(BPLONG i, TERM t)
{
BPLONG n, j;
XDEREF(t);
switch (XTAG(t)) {
case STR:
n = GET_ARITY_STR(GET_STR_SYM_REC(t));
j = 0;
break;
case LST:
n = 2;
j = 1;
break;
default:
bpx_raise("compound expected");
}
if (i < 1 || i > n) {
bpx_raise("bad argument index");
}
return GET_ARG(t, i - j);
}
TERM bpx_get_car(TERM t)
{
XDEREF(t);
if (ISLIST(t)) {
return GET_CAR(t);
}
else {
bpx_raise("list expected");
}
}
TERM bpx_get_cdr(TERM t)
{
XDEREF(t);
if (ISLIST(t)) {
return GET_CDR(t);
}
else {
bpx_raise("list expected");
}
}
/*--------------------------------------------------------------------*/
TERM bpx_build_var(void)
{
TERM term;
REQUIRE_HEAP(1);
term = (TERM)(heap_top);
NEW_HEAP_FREE;
return term;
}
TERM bpx_build_integer(BPLONG n)
{
return MAKEINT(n);
}
TERM bpx_build_float(double x)
{
REQUIRE_HEAP(4);
return encodefloat1(x);
}
TERM bpx_build_atom(const char *name)
{
SYM_REC_PTR sym;
sym = insert(name, strlen(name), 0);
return ADDTAG(sym, ATM);
}
TERM bpx_build_list(void)
{
TERM term;
REQUIRE_HEAP(2);
term = ADDTAG(heap_top, LST);
NEW_HEAP_FREE;
NEW_HEAP_FREE;
return term;
}
TERM bpx_build_nil(void)
{
return nil_sym;
}
TERM bpx_build_structure(const char *name, BPLONG arity)
{
SYM_REC_PTR sym;
TERM term;
REQUIRE_HEAP(arity + 1);
term = ADDTAG(heap_top, STR);
sym = insert(name, strlen(name), arity);
NEW_HEAP_NODE((TERM)(sym));
while (--arity >= 0) {
NEW_HEAP_FREE;
}
return term;
}
/*--------------------------------------------------------------------*/
bool bpx_unify(TERM t1, TERM t2)
{
return (bool)(unify(t1, t2));
}
/*--------------------------------------------------------------------*/
TERM bpx_string_2_term(const char *s)
{
TERM term, vars;
int result;
REQUIRE_HEAP(2);
term = (TERM)(heap_top);
NEW_HEAP_FREE;
vars = (TERM)(heap_top);
NEW_HEAP_FREE;
result = bp_string_2_term(s, term, vars);
if (result != BP_TRUE) {
bpx_raise("parsing failed -- %s", s);
}
return term;
}
const char * bpx_term_2_string(TERM t)
{
XDEREF(t);
return bp_term_2_string(t);
}
/*--------------------------------------------------------------------*/
int bpx_call_term(TERM t)
{
XDEREF(t);
return bp_call_term(t);
}
int bpx_call_string(const char *s)
{
return bp_call_term(bpx_string_2_term(s));
}
int bpx_mount_query_term(TERM t)
{
XDEREF(t);
return bp_mount_query_term(t);
}
int bpx_mount_query_string(const char *s)
{
return bp_mount_query_term(bpx_string_2_term(s));
}
int bpx_next_solution(void)
{
if (curr_toam_status == TOAM_NOTSET) {
bpx_raise("no goal mounted");
}
return bp_next_solution();
}
/*--------------------------------------------------------------------*/
void bpx_write(TERM t)
{
XDEREF(t);
write_term(t);
}
/*--------------------------------------------------------------------*/
int bpx_printf(const char *fmt, ...)
{
va_list ap;
int r;
va_start(ap, fmt);
r = vfprintf(curr_out, fmt, ap);
va_end(ap);
return r;
}
/*--------------------------------------------------------------------*/
#ifdef __YAP_PROLOG__
BPLONG toam_signal_vec;
BPLONG illegal_arguments;
BPLONG failure_atom;
BPLONG number_var_exception;
#endif

View File

@ -0,0 +1,323 @@
#ifndef BPX_H
#define BPX_H
#include "bprolog.h"
#include "stuff.h"
#ifdef __YAP_PROLOG__
#include <stdio.h>
#include <stdlib.h>
#include <YapTerm.h>
#include <YapTags.h>
#include <YapRegs.h>
typedef void *SYM_REC_PTR;
#define heap_top H
#define local_top ASP
#define trail_top TR
#define trail_up_addr ((tr_fr_ptr)LCL0)
#define UNDO_TRAILING while (TR > (tr_fr_ptr)trail_top0) { RESET_VARIABLE(VarOfTerm(TrailTerm(TR--))); }
#define NEW_HEAP_NODE(x) (*heap_top++ = (x))
#define STACK_OVERFLOW 1
/*====================================================================*/
#define ARG(X,Y) XREGS[X]
#define XDEREF(T) while (IsVarTerm(T)) { CELL *next = VarOfTerm(T); if (IsUnboundVar(next)) break; (T) = *next; }
#define MAKEINT(I) bp_build_integer(I)
#define INTVAL(T) bp_get_integer(T)
#define MAX_ARITY 256
#define BP_MALLOC(X,Y,Z) ( X = malloc((Y)*sizeof(BPLONG)) )
#define NULL_TERM ((TERM)(0))
#define REF0 0x0L
#define REF1 0x1L
#define SUSP 0x2L
#define LST 0x4L
#define ATM 0x8L
#define INT 0x10L
#define STR 0x20L
#define NVAR (LST|ATM|INT|STR)
#define GET_STR_SYM_REC(p) ((SYM_REC_PTR)*RepAppl(p))
#define GET_ATM_SYM_REC(p) ((SYM_REC_PTR)AtomOfTerm(p))
#define GET_ARITY_STR(s) YAP_ArityOfFunctor((YAP_Functor)(s))
#define GET_ARITY_ATOM(s) 0
#define GET_NAME_STR(f) YAP_AtomName(YAP_NameOfFunctor((YAP_Functor)(f)))
#define GET_NAME_ATOM(a) YAP_AtomName((YAP_Atom)(a))
static inline
long int XTAG(TERM t)
{
switch(YAP_TagOfTerm(t)) {
case YAP_TAG_UNBOUND:
return REF0;
case YAP_TAG_ATT:
return SUSP;
case YAP_TAG_REF:
return REF1;
case YAP_TAG_PAIR:
return LST;
case YAP_TAG_ATOM:
return ATM;
case YAP_TAG_INT:
return INT;
case YAP_TAG_LONG_INT:
return INT;
case YAP_TAG_APPL:
default:
return STR;
}
}
extern inline TERM ADDTAG(void * t,int tag) {
if (tag == ATM)
return MkAtomTerm((Atom)t);
if (tag == LST)
return AbsPair((CELL *)t);
return AbsAppl((CELL *)t);
}
#define ISREF(t) IsVarTerm(t)
#define ISATOM(t) IsAtomTerm(t)
#define ISINT(t) IsIntegerTerm(t)
#define ISNUM(t) YAP_IsNumberTerm(t)
#define ISNIL(t) YAP_IsTermNil(t)
#define ISLIST(t) IsPairTerm(t)
#define ISSTRUCT(t) IsApplTerm(t)
#define ISFLOAT(t) IsFloatTerm(t)
#define ISCOMPOUND(t) YAP_IsCompoundTerm(t)
#define floatval FloatOfTerm
#define encodefloat1 MkFloatTerm
extern inline int is_UNIFIABLE(TERM t1, TERM t2)
{
return YAP_Unifiable(t1, t2);
}
extern inline int is_IDENTICAL(TERM t1, TERM t2)
{
return YAP_ExactlyEqual(t1, t2);
}
#define SWITCH_OP(T,NDEREF,VCODE,ACODE,LCODE,SCODE,SUCODE) \
switch (XTAG((T))) { \
case REF0: \
VCODE \
case LST: \
LCODE \
case SUSP: \
SUCODE \
case STR: \
SCODE \
default: \
ACODE \
}
#define XNDEREF(X,LAB)
#define GET_ARG(A,I) YAP_ArgOfTerm((I),(A))
#define GET_CAR(A) YAP_HeadOfTerm(A)
#define GET_CDR(A) YAP_TailOfTerm(A)
#define MAKE_NVAR(id) ( (YAP_Term)(id) )
#define float_psc ((YAP_Functor)FunctorDouble)
#define NEW_HEAP_FREE (*H = (CELL)H); H++
#define nil_sym YAP_TermNil()
extern BPLONG illegal_arguments;
extern BPLONG failure_atom;
extern BPLONG number_var_exception;
extern BPLONG toam_signal_vec;
#define unify YAP_Unify
extern inline char *
bp_term_2_string(TERM t)
{
char *buf = malloc(256);
if (!buf) return NULL;
YAP_WriteBuffer(t, buf, 256, 0);
return buf;
}
// char *bp_get_name(TERM t)
extern inline int
bp_string_2_term(const char *s, TERM to, TERM tv)
{
TERM t0 = YAP_ReadBuffer(s, NULL);
TERM t1 = YAP_TermNil(); // for now
return unify(t0, to) && unify(t1,tv);
}
extern inline SYM_REC_PTR
insert(const char *name, int size, int arity)
{
if (!arity) {
return (SYM_REC_PTR)YAP_LookupAtom(name);
}
return (SYM_REC_PTR)YAP_MkFunctor(YAP_LookupAtom(name), arity);
}
extern inline int
compare(TERM t1, TERM t2)
{
// compare terms??
return YAP_CompareTerms(t1,t2);
}
extern inline void
write_term(TERM t)
{
YAP_Write(t,NULL,0);
}
static NORET quit(const char *s)
{
fprintf(stderr,"PRISM QUIT: %s\n",s);
exit(0);
}
static NORET myquit(int i, const char *s)
{
fprintf(stderr,"PRISM QUIT: %s\n",s);
exit(i);
}
// vsc: why two arguments?
static inline int
list_length(BPLONG t1, BPLONG t2)
{
return YAP_ListLength((TERM)t1);
}
#define PRE_NUMBER_VAR(X)
static inline void
numberVarTermOpt(TERM t)
{
YAP_NumberVars(t, 0);
}
static inline TERM
unnumberVarTerm(TERM t, BPLONG_PTR pt1, BPLONG_PTR pt2)
{
return YAP_UnNumberVars(t);
}
extern inline int
unifyNumberedTerms(TERM t1, TERM t2)
{
if (YAP_Unify(t1,t2))
return TRUE;
return FALSE;
}
#define IsNumberedVar YAP_IsNumberedVariable
#else
#define GET_ARITY_ATOM GET_ARITY
#define GET_ARITY_STR GET_ARITY
#define GET_NAME_STR GET_NAME
#define GET_NAME_ATOM GET_NAME
/*====================================================================*/
#define NULL_TERM ((TERM)(0))
/*--------------------------------*/
/* These are the safer versions of DEREF and NDEREF macros. */
#define XDEREF(op) \
do { if(TAG(op) || (op) == FOLLOW(op)) { break; } (op) = FOLLOW(op); } while(1)
#define XNDEREF(op, label) \
do { if(TAG(op) || (op) == FOLLOW(op)) { break; } (op) = FOLLOW(op); goto label; } while(1)
/*--------------------------------*/
/* This low-level macro provides more detailed information about the */
/* type of a given term than TAG(op). */
#define XTAG(op) ((op) & TAG_MASK)
#define REF0 0x0L
#define REF1 TOP_BIT
#define INT INT_TAG
#define NVAR TAG_MASK
/*--------------------------------*/
/* The following macros are the same as IsNumberedVar and NumberVar */
/* respectively, provided just for more consistent naming. */
#define IS_NVAR(op) ( ((op) & TAG_MASK) == NVAR )
#define MAKE_NVAR(id) ( (((BPLONG)(id)) << 2) | NVAR )
/*--------------------------------*/
/* This macro is redefined to reduce warnings on GCC 4.x. */
#if defined LINUX && ! defined M64BITS
#undef UNTAGGED_ADDR
#define UNTAGGED_ADDR(op) ( (((BPLONG)(op)) & VAL_MASK0) | addr_top_bit )
#endif
/*====================================================================*/
#endif /* YAP */
bool bpx_is_var(TERM);
bool bpx_is_atom(TERM);
bool bpx_is_integer(TERM);
bool bpx_is_float(TERM);
bool bpx_is_nil(TERM);
bool bpx_is_list(TERM);
bool bpx_is_structure(TERM);
bool bpx_is_compound(TERM);
bool bpx_is_unifiable(TERM, TERM);
bool bpx_is_identical(TERM, TERM);
TERM bpx_get_call_arg(BPLONG, BPLONG);
BPLONG bpx_get_integer(TERM);
double bpx_get_float(TERM);
const char* bpx_get_name(TERM);
int bpx_get_arity(TERM);
TERM bpx_get_arg(BPLONG, TERM);
TERM bpx_get_car(TERM);
TERM bpx_get_cdr(TERM);
TERM bpx_build_var(void);
TERM bpx_build_integer(BPLONG);
TERM bpx_build_float(double);
TERM bpx_build_atom(const char *);
TERM bpx_build_list(void);
TERM bpx_build_nil(void);
TERM bpx_build_structure(const char *, BPLONG);
bool bpx_unify(TERM, TERM);
TERM bpx_string_2_term(const char *);
const char* bpx_term_2_string(TERM);
#endif /* BPX_H */

View File

@ -0,0 +1,108 @@
#include <stdarg.h>
#include "bprolog.h"
#include "core/bpx.h"
/*--------------------------------------------------------------------*/
#ifndef __YAP_PROLOG__
TERM bpx_build_atom(const char *);
#endif
/*--------------------------------------------------------------------*/
TERM err_runtime;
TERM err_internal;
TERM err_cycle_detected;
TERM err_invalid_likelihood;
TERM err_invalid_free_energy;
TERM err_invalid_numeric_value;
TERM err_invalid_goal_id;
TERM err_invalid_switch_instance_id;
TERM err_underflow;
TERM err_overflow;
TERM err_ctrl_c_pressed;
TERM ierr_invalid_likelihood;
TERM ierr_invalid_free_energy;
TERM ierr_function_not_implemented;
TERM ierr_unmatched_branches;
/*--------------------------------------------------------------------*/
TERM build_runtime_error(const char *s)
{
TERM t;
if (s == NULL) return bpx_build_atom("prism_runtime_error");
t = bpx_build_structure("prism_runtime_error",1);
bpx_unify(bpx_get_arg(1,t),bpx_build_atom(s));
return t;
}
TERM build_internal_error(const char *s)
{
TERM t;
if (s == NULL) return bpx_build_atom("prism_internal_error");
t = bpx_build_structure("prism_internal_error",1);
bpx_unify(bpx_get_arg(1,t),bpx_build_atom(s));
return t;
}
/*--------------------------------------------------------------------*/
void register_prism_errors(void)
{
err_runtime = build_runtime_error(NULL);
err_internal = build_internal_error(NULL);
err_cycle_detected = build_runtime_error("cycle_detected");
err_invalid_likelihood = build_runtime_error("invalid_likelihood");
err_invalid_free_energy = build_runtime_error("invalid_free_energy");
err_invalid_numeric_value = build_runtime_error("invalid_numeric_value");
err_invalid_goal_id = build_runtime_error("invalid_goal_id");
err_invalid_switch_instance_id = build_runtime_error("invalid_switch_instance_id");
err_underflow = build_runtime_error("underflow");
err_overflow = build_runtime_error("overflow");
err_ctrl_c_pressed = build_runtime_error("ctrl_c_pressed");
ierr_invalid_likelihood = build_internal_error("invalid_likelihood");
ierr_invalid_free_energy = build_internal_error("invalid_free_energy");
ierr_function_not_implemented = build_internal_error("function_not_implemented");
ierr_unmatched_branches = build_internal_error("unmatched_branches");
}
/*--------------------------------------------------------------------*/
void emit_error(const char *fmt, ...)
{
va_list ap;
fprintf(curr_out, "*** PRISM ERROR: ");
va_start(ap, fmt);
vfprintf(curr_out, fmt, ap);
va_end(ap);
fprintf(curr_out, "\n");
fflush(curr_out);
}
void emit_internal_error(const char *fmt, ...)
{
va_list ap;
fprintf(curr_out, "*** PRISM INTERNAL ERROR: ");
va_start(ap, fmt);
vfprintf(curr_out, fmt, ap);
va_end(ap);
fprintf(curr_out, "\n");
fflush(curr_out);
}
/*--------------------------------------------------------------------*/

View File

@ -0,0 +1,66 @@
#ifndef ERROR_H
#define ERROR_H
/*--------------------------------------------------------------------*/
#define RET_ERR(err) \
do { \
exception = (err); \
return BP_ERROR; \
} while (0)
#define RET_RUNTIME_ERR \
do { \
exception = err_runtime; \
return BP_ERROR; \
} while (0)
#define RET_INTERNAL_ERR \
do { \
exception = err_internal; \
return BP_ERROR; \
} while (0)
#define RET_ON_ERR(expr) \
do { \
if ((expr) == BP_ERROR) return BP_ERROR; \
} while (0)
#define RET_ERR_ON_ERR(expr,err) \
do { \
if ((expr) == BP_ERROR) { \
exception = (err); \
return BP_ERROR; \
} \
} while (0)
/*--------------------------------------------------------------------*/
extern TERM err_runtime;
extern TERM err_internal;
extern TERM err_cycle_detected;
extern TERM err_invalid_likelihood;
extern TERM err_invalid_free_energy;
extern TERM err_invalid_numeric_value;
extern TERM err_invalid_goal_id;
extern TERM err_invalid_switch_instance_id;
extern TERM err_underflow;
extern TERM err_overflow;
extern TERM err_ctrl_c_pressed;
extern TERM ierr_invalid_likelihood;
extern TERM ierr_invalid_free_energy;
extern TERM ierr_function_not_implemented;
extern TERM ierr_unmatched_branches;
/*--------------------------------------------------------------------*/
TERM build_runtime_error(const char *);
TERM build_internal_error(const char *);
void emit_error(const char *, ...);
void emit_internal_error(const char *, ...);
/*--------------------------------------------------------------------*/
#endif /* ERROR_H */

View File

@ -0,0 +1,11 @@
#include "core/fputil.h"
double fputil_snan(void)
{
return +sqrt(-1);
}
double fputil_qnan(void)
{
return -sqrt(-1);
}

View File

@ -0,0 +1,51 @@
#ifndef FPUTIL_H
#define FPUTIL_H
/*--------------------------------------------------------------------*/
#include <math.h>
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ >= 199901L
#define C99
#endif
#endif
/*--------------------------------------------------------------------*/
#if defined C99
/* (empty) */
#elif defined _MSC_VER
#include <float.h>
#define isfinite _finite
#define isnan _isnan
#define INFINITY HUGE_VAL
#elif defined LINUX
# ifndef isfinite
# define isfinite finite
# endif
# ifndef isnan
# define isnan isnan
# endif
# ifndef INFINITY
# define INFINITY HUGE_VAL
# endif
#elif defined DARWIN
/* (empty) */
#else
#define isfinite(x) (0.0 * (x) != 0.0)
#define isnan(x) ((x) != (x))
#define INFINITY HUGE_VAL
#endif
#define SNAN fputil_snan()
#define QNAN fputil_qnan()
/*--------------------------------------------------------------------*/
double fputil_snan(void);
double fputil_qnan(void);
/*--------------------------------------------------------------------*/
#endif /* FPUTIL_H */

View File

@ -0,0 +1,306 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*-
This file contains a portable implementation for a couple of gamma-
family functions, originally written for the PRISM programming system
<http://sato-www.cs.titech.ac.jp/prism/>.
The code is based on SPECFUN (Fortran program collection for special
functions by W. J. Cody et al. at Argonne National Laboratory), which
is available in public domain at <http://www.netlib.org/specfun/>.
Here is the license terms for this file (just provided to explicitly
state that the code can be used for any purpose):
------------------------------------------------------------------------------
Copyright (c) 2007-2009 Yusuke Izumi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
------------------------------------------------------------------------------
*/
#include <math.h>
#include "core/gamma.h"
#define PI (3.14159265358979323846) /* pi */
#define PI_2 (1.57079632679489661923) /* pi / 2 */
#define PI_4 (0.78539816339744830962) /* pi / 4 */
#define LN_SQRT2PI (0.91893853320467274178) /* ln(sqrt(2 * pi)) */
/**
* Computes ln(|Gamma(x)|).
*/
double lngamma(double x)
{
/* Constants for [0.5,1.5) -------------------------------------------*/
const double D1 = -5.772156649015328605195174e-01;
const double P1[] = {
+4.945235359296727046734888e+00, +2.018112620856775083915565e+02,
+2.290838373831346393026739e+03, +1.131967205903380828685045e+04,
+2.855724635671635335736389e+04, +3.848496228443793359990269e+04,
+2.637748787624195437963534e+04, +7.225813979700288197698961e+03
};
const double Q1[] = {
+6.748212550303777196073036e+01, +1.113332393857199323513008e+03,
+7.738757056935398733233834e+03, +2.763987074403340708898585e+04,
+5.499310206226157329794414e+04, +6.161122180066002127833352e+04,
+3.635127591501940507276287e+04, +8.785536302431013170870835e+03
};
/* Constants for [1.5,4.0) -------------------------------------------*/
const double D2 = +4.227843350984671393993777e-01;
const double P2[] = {
+4.974607845568932035012064e+00, +5.424138599891070494101986e+02,
+1.550693864978364947665077e+04, +1.847932904445632425417223e+05,
+1.088204769468828767498470e+06, +3.338152967987029735917223e+06,
+5.106661678927352456275255e+06, +3.074109054850539556250927e+06
};
const double Q2[] = {
+1.830328399370592604055942e+02, +7.765049321445005871323047e+03,
+1.331903827966074194402448e+05, +1.136705821321969608938755e+06,
+5.267964117437946917577538e+06, +1.346701454311101692290052e+07,
+1.782736530353274213975932e+07, +9.533095591844353613395747e+06
};
/* Constants for [4.0,12.0) ------------------------------------------*/
const double D4 = +1.791759469228055000094023e+00;
const double P4[] = {
+1.474502166059939948905062e+04, +2.426813369486704502836312e+06,
+1.214755574045093227939592e+08, +2.663432449630976949898078e+09,
+2.940378956634553899906876e+10, +1.702665737765398868392998e+11,
+4.926125793377430887588120e+11, +5.606251856223951465078242e+11
};
const double Q4[] = {
+2.690530175870899333379843e+03, +6.393885654300092398984238e+05,
+4.135599930241388052042842e+07, +1.120872109616147941376570e+09,
+1.488613728678813811542398e+10, +1.016803586272438228077304e+11,
+3.417476345507377132798597e+11, +4.463158187419713286462081e+11
};
/* Constants for [12.0,Infinity) -------------------------------------*/
const double C[] = {
-2.955065359477124231624146e-02, +6.410256410256410034009811e-03,
-1.917526917526917633674555e-03, +8.417508417508417139715760e-04,
-5.952380952380952917890600e-04, +7.936507936507936501052685e-04,
-2.777777777777777883788657e-03, +8.333333333333332870740406e-02
};
/*--------------------------------------------------------------------*/
const double EPS = 2.22e-16;
const double P68 = 87.0 / 128.0;
const double BIG = 2.25e+76;
/*--------------------------------------------------------------------*/
double p, q, y;
int i, n;
if (x != x) /* NaN */
return x;
else if (0 * x != 0) /* Infinity */
return HUGE_VAL;
else if (x <= 0.0) {
q = modf(-2.0 * x, &p);
n = (int)(p);
q = sin(PI_2 * (n % 2 == 0 ? q : 1.0 - q));
return log(PI / q) - lngamma(1.0 - x);
}
else if (x < EPS)
return -log(x);
else if (x < 0.5) {
p = 0.0;
q = 1.0;
y = x;
for (i = 0; i < 8; i++) {
p = p * y + P1[i];
q = q * y + Q1[i];
}
return x * (D1 + y * (p / q)) - log(x);
}
else if (x < P68) {
p = 0.0;
q = 1.0;
y = x - 1.0;
for (i = 0; i < 8; i++) {
p = p * y + P2[i];
q = q * y + Q2[i];
}
return y * (D2 + y * (p / q)) - log(x);
}
else if (x < 1.5) {
p = 0.0;
q = 1.0;
y = x - 1.0;
for (i = 0; i < 8; i++) {
p = p * y + P1[i];
q = q * y + Q1[i];
}
return y * (D1 + y * (p / q));
}
else if (x < 4.0) {
p = 0.0;
q = 1.0;
y = x - 2.0;
for (i = 0; i < 8; i++) {
p = p * y + P2[i];
q = q * y + Q2[i];
}
return y * (D2 + y * (p / q));
}
else if (x < 12.0) {
p = 0.0;
q = -1.0;
y = x - 4.0;
for (i = 0; i < 8; i++) {
p = p * y + P4[i];
q = q * y + Q4[i];
}
return D4 + y * (p / q);
}
else if (x < BIG) {
p = 0.0;
q = log(x);
y = 1.0 / (x * x);
for (i = 0; i < 8; i++) {
p = p * y + C[i];
}
return p / x + LN_SQRT2PI - 0.5 * q + x * (q - 1.0);
}
else {
q = log(x);
return LN_SQRT2PI - 0.5 * q + x * (q - 1.0);
}
/*--------------------------------------------------------------------*/
}
/**
* Computes Psi(x) = (d/dx)(ln(Gamma(x)))
*/
double digamma(double x)
{
/* Constants for [0.5,3.0] -------------------------------------------*/
const double P1[] = {
+4.5104681245762934160e-03, +5.4932855833000385356e+00,
+3.7646693175929276856e+02, +7.9525490849151998065e+03,
+7.1451595818951933210e+04, +3.0655976301987365674e+05,
+6.3606997788964458797e+05, +5.8041312783537569993e+05,
+1.6585695029761022321e+05
};
const double Q1[] = {
+9.6141654774222358525e+01, +2.6287715790581193330e+03,
+2.9862497022250277920e+04, +1.6206566091533671639e+05,
+4.3487880712768329037e+05, +5.4256384537269993733e+05,
+2.4242185002017985252e+05, +6.4155223783576225996e-08
};
/* Constants for (3.0,Infinity) --------------------------------------*/
const double P2[] = {
-2.7103228277757834192e+00, -1.5166271776896121383e+01,
-1.9784554148719218667e+01, -8.8100958828312219821e+00,
-1.4479614616899842986e+00, -7.3689600332394549911e-02,
-6.5135387732718171306e-21
};
const double Q2[] = {
+4.4992760373789365846e+01, +2.0240955312679931159e+02,
+2.4736979003315290057e+02, +1.0742543875702278326e+02,
+1.7463965060678569906e+01, +8.8427520398873480342e-01
};
/*--------------------------------------------------------------------*/
const double MIN = 2.23e-308;
const double MAX = 4.50e+015;
const double SMALL = 5.80e-009;
const double LARGE = 2.71e+014;
const double X01 = 187.0 / 128.0;
const double X02 = 6.9464496836234126266e-04;
/*--------------------------------------------------------------------*/
double p, q, y, sgn;
int i, n;
sgn = (x > 0.0) ? +1.0 : -1.0;
y = fabs(x);
if (x != x) /* NaN */
return x;
else if (x < -MAX || y < MIN)
return -1.0 * sgn * HUGE_VAL;
else if (y < SMALL)
return digamma(1.0 - x) - 1.0 / x;
else if (x < 0.5) {
q = modf(4.0 * y, &p);
n = (int)(p);
switch (n % 4) {
case 0:
return digamma(1.0 - x) - sgn * PI / tan(PI_4 * q);
case 1:
return digamma(1.0 - x) - sgn * PI * tan(PI_4 * (1.0 - q));
case 2:
return digamma(1.0 - x) + sgn * PI * tan(PI_4 * q);
case 3:
return digamma(1.0 - x) + sgn * PI / tan(PI_4 * (1.0 - q));
}
}
else if (x <= 3.0) {
p = 0.0;
q = 1.0;
for (i = 0; i < 8; i++) {
p = p * x + P1[i];
q = q * x + Q1[i];
}
p = p * x + P1[8];
return p / q * ((x - X01) - X02);
}
else if (x < LARGE) {
p = 0.0;
q = 1.0;
y = 1.0 / (x * x);
for (i = 0; i < 6; i++) {
p = p * y + P2[i];
q = q * y + Q2[i];
}
p = p * y + P2[6];
return p / q - 0.5 / x + log(x);
}
return log(x);
}

View File

@ -0,0 +1,7 @@
#ifndef GAMMA_H
#define GAMMA_H
double lngamma(double);
double digamma(double);
#endif /* GAMMA_H */

View File

@ -0,0 +1,197 @@
#include <stdlib.h>
/*--------------------------------------------------------------------*/
#define REGISTER_CPRED(p,n) \
do { extern int pc_ ## p ## _ ## n (void); insert_cpred("$pc_" #p, n, pc_ ## p ## _ ## n); } while (0)
/*--------------------------------------------------------------------*/
typedef struct sym_rec * SYM_REC_PTR;
typedef long int TERM;
SYM_REC_PTR insert_cpred(const char *, int, int(*)(void));
void exit(int);
#ifdef __YAP_PROLOG__
int YAP_UserCpredicate(const char *s, int (*f)(void), unsigned long int n);
SYM_REC_PTR insert_cpred(const char *s, int n, int(*f)(void))
{
YAP_UserCPredicate(s, f, n);
return NULL;
}
#endif
/*--------------------------------------------------------------------*/
void register_prism_errors(void);
#ifdef MPI
void mp_init(int *argc, char **argv[]);
void mp_done(void);
void mp_quit(int);
#endif
/*--------------------------------------------------------------------*/
void bp4p_init(int *argc, char **argv[])
{
#ifdef MPI
mp_init(argc, argv);
#endif
}
void bp4p_exit(int status)
{
#ifdef MPI
mp_done();
#endif
exit(status);
}
void bp4p_quit(int status)
{
#ifdef MPI
mp_quit(status);
#else
exit(status);
#endif
}
void bp4p_register_preds(void)
{
/* core/idtable.c */
REGISTER_CPRED(prism_id_table_init,0);
REGISTER_CPRED(prism_goal_id_register,2);
REGISTER_CPRED(prism_sw_id_register,2);
REGISTER_CPRED(prism_sw_ins_id_register,2);
REGISTER_CPRED(prism_goal_id_get,2);
REGISTER_CPRED(prism_sw_id_get,2);
REGISTER_CPRED(prism_sw_ins_id_get,2);
REGISTER_CPRED(prism_goal_count,1);
REGISTER_CPRED(prism_sw_count,1);
REGISTER_CPRED(prism_sw_ins_count,1);
REGISTER_CPRED(prism_goal_term,2);
REGISTER_CPRED(prism_sw_term,2);
REGISTER_CPRED(prism_sw_ins_term,2);
/* core/random.c */
REGISTER_CPRED(random_auto_seed, 1);
REGISTER_CPRED(random_init_by_seed, 1);
REGISTER_CPRED(random_init_by_list, 1);
REGISTER_CPRED(random_float, 1);
REGISTER_CPRED(random_gaussian, 1);
REGISTER_CPRED(random_int, 2);
REGISTER_CPRED(random_int, 3);
REGISTER_CPRED(random_get_state, 1);
REGISTER_CPRED(random_set_state, 1);
/* core/util.c */
REGISTER_CPRED(lngamma, 2);
/* up/em_preds.c */
REGISTER_CPRED(prism_prepare,4);
REGISTER_CPRED(prism_em,6);
REGISTER_CPRED(prism_vbem,2);
REGISTER_CPRED(prism_both_em,2);
REGISTER_CPRED(compute_inside,2);
REGISTER_CPRED(compute_probf,1);
/* up/viterbi.c */
REGISTER_CPRED(compute_viterbi,5);
REGISTER_CPRED(compute_n_viterbi,3);
REGISTER_CPRED(compute_n_viterbi_rerank,4);
/* up/hindsight.c */
REGISTER_CPRED(compute_hindsight,4);
/* up/graph.c */
REGISTER_CPRED(alloc_egraph,0);
REGISTER_CPRED(clean_base_egraph,0);
REGISTER_CPRED(clean_egraph,0);
REGISTER_CPRED(export_switch,2);
REGISTER_CPRED(add_egraph_path,3);
REGISTER_CPRED(alloc_sort_egraph,1);
REGISTER_CPRED(clean_external_tables,0);
REGISTER_CPRED(export_sw_info,1);
REGISTER_CPRED(import_sorted_graph_size,1);
REGISTER_CPRED(import_sorted_graph_gid,2);
REGISTER_CPRED(import_sorted_graph_paths,2);
REGISTER_CPRED(get_gnode_inside,2);
REGISTER_CPRED(get_gnode_outside,2);
REGISTER_CPRED(get_gnode_viterbi,2);
REGISTER_CPRED(get_snode_inside,2);
REGISTER_CPRED(get_snode_expectation,2);
REGISTER_CPRED(import_occ_switches,3);
REGISTER_CPRED(import_graph_stats,4);
/* up/flags.c */
REGISTER_CPRED(set_daem,1);
REGISTER_CPRED(set_em_message,1);
REGISTER_CPRED(set_em_progress,1);
REGISTER_CPRED(set_error_on_cycle,1);
REGISTER_CPRED(set_explicit_empty_expls,1);
REGISTER_CPRED(set_fix_init_order,1);
REGISTER_CPRED(set_init_method,1);
REGISTER_CPRED(set_itemp_init,1);
REGISTER_CPRED(set_itemp_rate,1);
REGISTER_CPRED(set_log_scale,1);
REGISTER_CPRED(set_max_iterate,1);
REGISTER_CPRED(set_num_restart,1);
REGISTER_CPRED(set_prism_epsilon,1);
REGISTER_CPRED(set_show_itemp,1);
REGISTER_CPRED(set_std_ratio,1);
REGISTER_CPRED(set_verb_em,1);
REGISTER_CPRED(set_verb_graph,1);
REGISTER_CPRED(set_warn,1);
REGISTER_CPRED(set_debug_level,1);
/* up/util.c */
REGISTER_CPRED(mp_mode,0);
REGISTER_CPRED(get_term_depth,2);
REGISTER_CPRED(mtrace,0);
REGISTER_CPRED(muntrace,0);
REGISTER_CPRED(sleep,1);
#ifdef MPI
/* mp/mp_preds.c */
REGISTER_CPRED(mp_size,1);
REGISTER_CPRED(mp_rank,1);
REGISTER_CPRED(mp_master,0);
REGISTER_CPRED(mp_abort,0);
REGISTER_CPRED(mp_wtime,1);
REGISTER_CPRED(mp_sync,2);
REGISTER_CPRED(mp_send_goal,1);
REGISTER_CPRED(mp_recv_goal,1);
REGISTER_CPRED(mpm_bcast_command,1);
REGISTER_CPRED(mps_bcast_command,1);
REGISTER_CPRED(mps_revert_stdout,0);
/* mp/mp_em_preds.c */
REGISTER_CPRED(mpm_prism_em,6);
REGISTER_CPRED(mps_prism_em,0);
REGISTER_CPRED(mpm_prism_vbem,2);
REGISTER_CPRED(mps_prism_vbem,0);
REGISTER_CPRED(mpm_prism_both_em,2);
REGISTER_CPRED(mps_prism_both_em,0);
REGISTER_CPRED(mpm_import_graph_stats,4);
REGISTER_CPRED(mps_import_graph_stats,0);
/* mp/mp_sw.c */
REGISTER_CPRED(mp_send_switches,0);
REGISTER_CPRED(mp_recv_switches,0);
REGISTER_CPRED(mp_send_swlayout,0);
REGISTER_CPRED(mp_recv_swlayout,0);
REGISTER_CPRED(mpm_alloc_occ_switches,0);
/* mp/mp_flags.c */
REGISTER_CPRED(mpm_share_prism_flags,0);
REGISTER_CPRED(mps_share_prism_flags,0);
#endif
/* up/error.c; FIXME: There would be a better place to call */
register_prism_errors();
}
/*--------------------------------------------------------------------*/

View File

@ -0,0 +1,9 @@
#ifndef GLUE_H
#define GLUE_H
void bp4p_init(void);
void bp4p_exit(int);
void bp4p_quit(int);
void bp4p_register_preds(void);
#endif /* GLUE_H */

View File

@ -0,0 +1,175 @@
#include "core/xmalloc.h"
#include "core/vector.h"
#include "core/termpool.h"
#include "core/idtable.h"
#include "core/stuff.h"
/*--------------------------------------------------------------------*/
/* table.c */
TERM unnumberVarTerm(TERM, BPLONG_PTR, BPLONG_PTR);
/*--------------------------------------------------------------------*/
struct id_table {
TERM_POOL *store;
struct id_table_entry *elems;
IDNUM *bucks;
IDNUM nbucks;
};
struct id_table_entry {
TERM term;
IDNUM next;
};
/*--------------------------------------------------------------------*/
static void id_table_rehash(ID_TABLE *this)
{
IDNUM *bucks, nbucks, i, j;
nbucks = 2 * this->nbucks + 1;
/* find the next prime number */
for (i = 3; i * i <= nbucks; ) {
if (nbucks % i == 0) {
nbucks += 2;
i = 3;
}
else {
i += 2;
}
}
bucks = MALLOC(sizeof(struct hash_entry *) * nbucks);
for (i = 0; i < nbucks; i++)
bucks[i] = ID_NONE;
for (i = 0; i < VECTOR_SIZE(this->elems); i++) {
j = (IDNUM)((BPULONG)(this->elems[i].term) % nbucks);
this->elems[i].next = bucks[j];
bucks[j] = i;
}
FREE(this->bucks);
this->nbucks = nbucks;
this->bucks = bucks;
}
static IDNUM id_table_search(const ID_TABLE *this, TERM term)
{
BPULONG hash;
IDNUM i;
hash = (BPULONG)(term);
i = this->bucks[hash % this->nbucks];
while (i != ID_NONE) {
if (term == this->elems[i].term) {
return i;
}
i = this->elems[i].next;
}
return ID_NONE;
}
static IDNUM id_table_insert(ID_TABLE *this, TERM term)
{
BPULONG hash;
IDNUM n;
const char *bpx_term_2_string(TERM);
hash = (BPULONG)(term);
n = (IDNUM)(VECTOR_SIZE(this->elems));
if (n >= this->nbucks) {
id_table_rehash(this);
}
VECTOR_PUSH_NONE(this->elems);
this->elems[n].term = term;
this->elems[n].next = this->bucks[hash % this->nbucks];
this->bucks[hash % this->nbucks] = n;
/* fprintf(curr_out,">> TERM: %s = %d\n",bpx_term_2_string(term),n); */
return n;
}
/*--------------------------------------------------------------------*/
ID_TABLE * id_table_create(void)
{
ID_TABLE *this;
IDNUM i;
this = MALLOC(sizeof(struct id_table));
this->elems = NULL;
this->nbucks = 17; /* prime number */
this->bucks = MALLOC(sizeof(IDNUM) * this->nbucks);
this->store = term_pool_create();
for (i = 0; i < this->nbucks; i++)
this->bucks[i] = ID_NONE;
VECTOR_INIT(this->elems);
return this;
}
void id_table_delete(ID_TABLE *this)
{
VECTOR_FREE(this->elems);
FREE(this->bucks);
term_pool_delete(this->store);
FREE(this);
}
/*--------------------------------------------------------------------*/
TERM id_table_id2term(const ID_TABLE *this, IDNUM i)
{
return this->elems[i].term; /* numbered */
}
IDNUM id_table_retrieve(const ID_TABLE *this, TERM term)
{
term = term_pool_retrieve(this->store, term);
return id_table_search(this, term);
}
IDNUM id_table_register(ID_TABLE *this, TERM term)
{
BPULONG hash;
IDNUM i;
term = term_pool_register(this->store, term);
hash = (BPULONG)(term);
i = id_table_search(this, term);
if (i == ID_NONE) {
i = id_table_insert(this, term);
}
return i;
}
int id_table_count(const ID_TABLE *this)
{
return (int)VECTOR_SIZE(this->elems);
}
/*--------------------------------------------------------------------*/
TERM unnumber_var_term(TERM term)
{
BPLONG mvn = -1;
return unnumberVarTerm(term, local_top, &mvn);
}

View File

@ -0,0 +1,29 @@
#ifndef IDTABLE_H
#define IDTABLE_H
#include "bpx.h"
/*--------------------------------------------------------------------*/
#define ID_NONE ((IDNUM)(-1))
/*--------------------------------------------------------------------*/
typedef struct id_table ID_TABLE;
typedef unsigned int IDNUM;
/*--------------------------------------------------------------------*/
ID_TABLE * id_table_create(void);
void id_table_delete(ID_TABLE *);
TERM id_table_id2term(const ID_TABLE *, IDNUM);
IDNUM id_table_retrieve(const ID_TABLE *, TERM);
IDNUM id_table_register(ID_TABLE *, TERM);
int id_table_count(const ID_TABLE *);
TERM unnumber_var_term(TERM);
/*--------------------------------------------------------------------*/
#endif /* IDTABLE_H */

View File

@ -0,0 +1,249 @@
#include <string.h>
#include "core/idtable.h"
/*--------------------------------------------------------------------*/
static ID_TABLE *g_table = NULL; /* goals */
static ID_TABLE *s_table = NULL; /* switches */
static ID_TABLE *i_table = NULL; /* switch instances */
/*--------------------------------------------------------------------*/
/* cpreds.c */
char * bp_term_2_string(TERM);
/* unify.c */
int unify(TERM, TERM);
/*--------------------------------------------------------------------*/
int prism_goal_id_register(TERM term)
{
return id_table_register(g_table, term);
}
int prism_sw_id_register(TERM term)
{
return id_table_register(s_table, term);
}
int prism_sw_ins_id_register(TERM term)
{
return id_table_register(i_table, term);
}
int prism_goal_id_get(TERM term)
{
return id_table_retrieve(g_table, term);
}
int prism_sw_id_get(TERM term)
{
return id_table_retrieve(s_table, term);
}
int prism_sw_ins_id_get(TERM term)
{
return id_table_retrieve(i_table, term);
}
int prism_goal_count(void)
{
return id_table_count(g_table);
}
int prism_sw_count(void)
{
return id_table_count(s_table);
}
int prism_sw_ins_count(void)
{
return id_table_count(i_table);
}
TERM prism_goal_term(IDNUM i)
{
return id_table_id2term(g_table, i);
}
TERM prism_sw_term(IDNUM i)
{
return id_table_id2term(s_table, i);
}
TERM prism_sw_ins_term(IDNUM i)
{
return id_table_id2term(i_table, i);
}
char * prism_goal_string(IDNUM i)
{
return bp_term_2_string(prism_goal_term(i));
}
char * prism_sw_string(IDNUM i)
{
return bp_term_2_string(prism_sw_term(i));
}
char * prism_sw_ins_string(IDNUM i)
{
return bp_term_2_string(prism_sw_ins_term(i));
}
/* Note: the strings returned by strdup() should be released by the caller. */
char * copy_prism_goal_string(IDNUM i)
{
return strdup(prism_goal_string(i));
}
char * copy_prism_sw_string(IDNUM i)
{
return strdup(prism_sw_string(i));
}
char * copy_prism_sw_ins_string(IDNUM i)
{
return strdup(prism_sw_ins_string(i));
}
/*--------------------------------------------------------------------*/
int pc_prism_id_table_init_0(void)
{
if (g_table != NULL) id_table_delete(g_table);
if (s_table != NULL) id_table_delete(s_table);
if (i_table != NULL) id_table_delete(i_table);
g_table = id_table_create();
s_table = id_table_create();
i_table = id_table_create();
return BP_TRUE;
}
int pc_prism_goal_id_register_2(void)
{
TERM term;
IDNUM id;
term = ARG(1,2);
XDEREF(term);
id = prism_goal_id_register(term);
return unify(MAKEINT(id), ARG(2,2));
}
int pc_prism_sw_id_register_2(void)
{
TERM term;
IDNUM id;
term = ARG(1,2);
XDEREF(term);
id = prism_sw_id_register(term);
return unify(MAKEINT(id), ARG(2,2));
}
int pc_prism_sw_ins_id_register_2(void)
{
TERM term;
IDNUM id;
term = ARG(1,2);
XDEREF(term);
id = prism_sw_ins_id_register(term);
return unify(MAKEINT(id), ARG(2,2));
}
int pc_prism_goal_id_get_2(void)
{
TERM term;
IDNUM id;
term = ARG(1,2);
XDEREF(term);
id = prism_goal_id_get(term);
if (id == ID_NONE) return BP_FALSE;
return unify(MAKEINT(id), ARG(2,2));
}
int pc_prism_sw_id_get_2(void)
{
TERM term;
IDNUM id;
term = ARG(1,2);
XDEREF(term);
id = prism_sw_id_get(term);
if (id == ID_NONE) return BP_FALSE;
return unify(MAKEINT(id), ARG(2,2));
}
int pc_prism_sw_ins_id_get_2(void)
{
TERM term;
IDNUM id;
term = ARG(1,2);
XDEREF(term);
id = prism_sw_ins_id_get(term);
if (id == ID_NONE) return BP_FALSE;
return unify(MAKEINT(id), ARG(2,2));
}
int pc_prism_goal_count_1(void)
{
return unify(MAKEINT(prism_goal_count()), ARG(1,1));
}
int pc_prism_sw_count_1(void)
{
return unify(MAKEINT(prism_sw_count()), ARG(1,1));
}
int pc_prism_sw_ins_count_1(void)
{
return unify(MAKEINT(prism_sw_ins_count()), ARG(1,1));
}
int pc_prism_goal_term_2(void)
{
TERM id, term;
id = ARG(1,2);
XDEREF(id);
term = unnumber_var_term(prism_goal_term((IDNUM)INTVAL(id)));
return unify(term, ARG(2,2));
}
int pc_prism_sw_term_2(void)
{
TERM id, term;
id = ARG(1,2);
XDEREF(id);
term = unnumber_var_term(prism_sw_term((IDNUM)INTVAL(id)));
return unify(term, ARG(2,2));
}
int pc_prism_sw_ins_term_2(void)
{
TERM id, term;
id = ARG(1,2);
XDEREF(id);
term = unnumber_var_term(prism_sw_ins_term((IDNUM)INTVAL(id)));
return unify(term, ARG(2,2));
}

View File

@ -0,0 +1,41 @@
#ifndef IDTABLE_AUX_H
#define IDTABLE_AUX_H
/*--------------------------------------------------------------------*/
int prism_goal_id_register(TERM);
int prism_sw_id_register(TERM);
int prism_sw_ins_id_register(TERM);
int prism_goal_id_get(TERM);
int prism_sw_id_get(TERM);
int prism_sw_ins_id_get(TERM);
int prism_goal_count(void);
int prism_sw_id_count(void);
int prism_sw_ins_id_count(void);
TERM prism_goal_term(IDNUM);
TERM prism_sw_term(IDNUM);
TERM prism_sw_ins_term(IDNUM);
char * prism_goal_string(IDNUM);
char * prism_sw_string(IDNUM);
char * prism_sw_ins_string(IDNUM);
char * copy_prism_goal_string(IDNUM);
char * copy_prism_sw_string(IDNUM);
char * copy_prism_sw_ins_string(IDNUM);
int pc_prism_id_table_init(void);
int pc_prism_goal_id_register(void);
int pc_prism_sw_id_register(void);
int pc_prism_sw_ins_id_register(void);
int pc_prism_goal_id_get(void);
int pc_prism_sw_id_get(void);
int pc_prism_sw_ins_id_get(void);
int pc_prism_goal_count(void);
int pc_prism_sw_count(void);
int pc_prism_sw_ins_count(void);
int pc_prism_goal_term(void);
int pc_prism_sw_term(void);
int pc_prism_sw_ins_term(void);
/*--------------------------------------------------------------------*/
#endif /* IDTABLE_AUX_H */

View File

@ -0,0 +1,360 @@
/*
This source module contains reduced (and slightly modified) version
of mt19937ar.c implemented by Makoto Matsumoto and Takuji Nishimura.
The original file is available in the following website:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
Here is the original copyright notice.
========================================================================
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
========================================================================
*/
/***********[ REDUCED VERSION OF MT19937AR.C STARTS HERE ]***********/
/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializes mt[N] with a seed */
static void init_genrand(unsigned long s)
{
mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
mt[mti] =
(1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void init_by_array(unsigned long init_key[], int key_length)
{
int i, j, k;
init_genrand(19650218UL);
i=1;
j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
j++;
if (i>=N) {
mt[0] = mt[N-1];
i=1;
}
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) {
mt[0] = mt[N-1];
i=1;
}
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}
/* generates a random number on [0,0xffffffff]-interval */
static unsigned long genrand_int32(void)
{
unsigned long y;
static unsigned long mag01[2]={0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= N) { /* generate N words at one time */
int kk;
if (mti == N+1) /* if init_genrand() has not been called, */
init_genrand(5489UL); /* a default initial seed is used */
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
/* generates a random number on [0,1) with 53-bit resolution */
static double genrand_res53(void)
{
unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
/* These real versions are due to Isaku Wada, 2002/01/09 added */
/***********[ REDUCED VERSION OF MT19937AR.C ENDS HERE ]***********/
/*--------------------------------------------------------------------*/
#include <math.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "core/bpx.h"
#include "core/random.h"
#include "core/vector.h"
#ifndef M_PI
#define M_PI (3.14159265358979324)
#endif
static int gauss_flag = 0;
/*--------------------------------------------------------------------*/
int random_int(int n)
{
unsigned long p, q, r;
assert(n > 0);
if (n == 1) {
return 0;
}
p = 0xFFFFFFFFul - (0xFFFFFFFFul % n + 1) % n;
q = p / n + 1;
while ((r = genrand_int32()) > p) ;
return (int)(r / q);
}
double random_float(void)
{
return genrand_res53();
}
/* Box-Muller method */
double random_gaussian(double mu, double sigma)
{
double u1, u2;
static double g1, g2;
gauss_flag = !(gauss_flag);
if (gauss_flag) {
u1 = genrand_res53();
u2 = genrand_res53();
g1 = sqrt(-2.0 * log(u1)) * cos(2.0 * M_PI * u2);
g2 = sqrt(-2.0 * log(u1)) * sin(2.0 * M_PI * u2);
return sigma * g1 + mu;
}
else {
return sigma * g2 + mu;
}
}
/* N(0,1)-version:
double random_gaussian(void)
{
double u1, u2;
static double next;
gauss_flag = !(gauss_flag);
if (gauss_flag) {
do {
u1 = genrand_res53();
}
while (u1 == 0.0);
do {
u2 = genrand_res53();
}
while (u2 == 0.0);
next = sqrt(-2.0 * log(u1)) * sin(2.0 * M_PI * u2);
return sqrt(-2.0 * log(u1)) * cos(2.0 * M_PI * u2);
}
else {
return next;
}
}
*/
/*--------------------------------------------------------------------*/
int pc_random_auto_seed_1(void)
{
BPLONG seed = (BPLONG)(time(NULL));
return bpx_unify(ARG(1,1), bpx_build_integer(seed));
}
int pc_random_init_by_seed_1(void)
{
init_genrand((unsigned long)(bpx_get_integer(ARG(1,1))));
return BP_TRUE;
}
int pc_random_init_by_list_1(void)
{
unsigned long *seed;
TERM t, u;
VECTOR_INIT(seed);
t = ARG(1,1);
while (! bpx_is_nil(t)) {
u = bpx_get_car(t);
t = bpx_get_cdr(t);
VECTOR_PUSH(seed, (unsigned long)(bpx_get_integer(u)));
}
init_by_array(seed, VECTOR_SIZE(seed));
return BP_TRUE;
}
int pc_random_float_1(void)
{
return bpx_unify(ARG(1,1), bpx_build_float(random_float()));
}
int pc_random_gaussian_1(void)
{
return bpx_unify(ARG(1,1), bpx_build_float(random_gaussian(0.0,1.0)));
}
int pc_random_int_2(void)
{
int n_max = bpx_get_integer(ARG(1,2));
int n_out = random_int(n_max);
return bpx_unify(ARG(2,2), bpx_build_integer((BPLONG)(n_out)));
}
int pc_random_int_3(void)
{
int n_min = bpx_get_integer(ARG(1,3));
int n_max = bpx_get_integer(ARG(2,3));
int n_out = random_int(n_max - n_min + 1) + n_min;
return bpx_unify(ARG(3,3), bpx_build_integer((BPLONG)(n_out)));
}
/*--------------------------------------------------------------------*/
int pc_random_get_state_1(void)
{
int i, j;
TERM t, u;
unsigned long temp;
t = bpx_build_structure("$randstate", 4 * N / 3 + 1);
bpx_unify(bpx_get_arg(1, t), bpx_build_integer(mti));
for (i = 0; i < 4 * N / 3; i++) {
j = i / 4 * 3;
temp = 0;
if (i % 4 > 0) {
temp |= mt[j + i % 4 - 1] << (8 * (3 - i % 4));
}
if (i % 4 < 3) {
temp |= mt[j + i % 4 - 0] >> (8 * (1 + i % 4));
}
temp &= 0xFFFFFF; /* == 2^24 - 1 */
u = bpx_get_arg(i + 2, t);
bpx_unify(u, bpx_build_integer(temp));
}
return bpx_unify(ARG(1,1), t);
}
int pc_random_set_state_1(void)
{
int i, j;
TERM term;
unsigned long temp;
term = ARG(1,1);
assert(strcmp(bpx_get_name(term), "$randstate") == 0);
assert(bpx_get_arity(term) == 4 * N / 3 + 1);
mti = bpx_get_integer(bpx_get_arg(1, term));
for (i = 0; i < N; i++) {
j = i / 3 * 4;
mt[i] = 0;
temp = bpx_get_integer(bpx_get_arg(j + i % 3 + 2, term));
mt[i] |= temp << (8 * (1 + i % 3));
temp = bpx_get_integer(bpx_get_arg(j + i % 3 + 3, term));
mt[i] |= temp >> (8 * (2 - i % 3));
mt[i] &= 0xFFFFFFFF;
}
return BP_TRUE;
}
/*--------------------------------------------------------------------*/

View File

@ -0,0 +1,14 @@
#ifndef RANDOM_H
#define RANDOM_H
#include <stddef.h>
/*--------------------------------------------------------------------*/
int random_int(int);
double random_float(void);
double random_gaussian(double, double);
/*--------------------------------------------------------------------*/
#endif /* RANDOM_H */

View File

@ -0,0 +1,23 @@
#ifndef STUFF_H
#define STUFF_H
/*--------------------------------------------------------------------*/
typedef enum { false, true } bool;
/*--------------------------------------------------------------------*/
#if defined _MSC_VER
#define NORET void __declspec(noreturn)
#define PRINTF_LIKE_FUNC(m, n) /* empty */
#elif defined __GNUC__
#define NORET void __attribute__((noreturn))
#define PRINTF_LIKE_FUNC(m, n) __attribute__((format(printf, m, n)))
#else /* other */
#define NORET void
#define PRINTF_LIKE_FUNC(m, n) /* empty */
#endif
/*--------------------------------------------------------------------*/
#endif /* STUFF_H */

View File

@ -0,0 +1,424 @@
#include <assert.h>
#include "core/termpool.h"
#include "core/xmalloc.h"
#include "core/vector.h"
#include "core/stuff.h"
/* FIXME */
#define prism_quit(msg) quit("*** {PRISM FATAL ERROR: " msg "}\n")
NORET quit(const char *);
/*--------------------------------------------------------------------*/
/* [04 Apr 2009, by yuizumi]
* This value should be sufficiently large enough to have malloc(3)
* return an address with its top bit set on 32-bit Linux systems.
*/
#define BLOCK_SIZE 1048576
/*--------------------------------------------------------------------*/
/* [05 Apr 2009, by yuizumi]
* The area referred by this variable is shared by prism_hash_value()
* and term_pool_store(), under the assumption that BPLONG values and
* BPLONG_PTR values (i.e. pointers) are aligned in the same way even
* without cast operations.
*/
static BPLONG_PTR work;
/*--------------------------------------------------------------------*/
struct term_pool {
BPLONG_PTR head;
BPLONG_PTR curr;
BPLONG_PTR tail;
struct hash_entry **bucks;
size_t nbucks;
size_t count;
};
struct hash_entry {
TERM term;
BPULONG hash;
struct hash_entry *next;
};
/*--------------------------------------------------------------------*/
/* Functions from B-Prolog */
/* mic.c */
void c_STATISTICS(void);
/* table.c */
void numberVarTermOpt(TERM);
TERM unnumberVarTerm(TERM, BPLONG_PTR, BPLONG_PTR);
/* unify.c */
int unifyNumberedTerms(TERM, TERM);
/*--------------------------------------------------------------------*/
static ptrdiff_t trail_pos0 = 0;
static void number_vars(TERM term)
{
assert(trail_pos0 == 0);
trail_pos0 = trail_up_addr - trail_top;
PRE_NUMBER_VAR(0);
numberVarTermOpt(term);
if (number_var_exception != 0) {
prism_quit("suspension variables not supported in Prism");
}
}
static void revert_vars(void)
{
BPLONG_PTR trail_top0;
assert(trail_pos0 != 0);
trail_top0 = trail_up_addr - trail_pos0;
UNDO_TRAILING;
trail_pos0 = 0;
}
/* [29 Mar 2009, by yuizumi]
* See Also: "Algorithms in C, Third Edition," by Robert Sedgewick,
* Addison-Wesley, 1998.
*/
static BPULONG prism_hash_value(TERM term)
{
TERM t, *rest;
BPLONG i, n;
SYM_REC_PTR sym;
BPULONG a = 2130563839ul;
BPULONG b = 1561772629ul;
BPULONG h = 0;
BPULONG u;
rest = (TERM *)work;
VECTOR_PUSH(rest, term);
while (! VECTOR_EMPTY(rest)) {
t = VECTOR_POP(rest);
nderef_loop:
switch (XTAG(t)) {
case REF0:
case REF1:
XNDEREF(t, nderef_loop);
assert(false); /* numbered by number_vars() */
case ATM:
case INT:
case NVAR:
u = (BPULONG)t;
break;
case LST:
VECTOR_PUSH(rest, GET_CDR(t));
VECTOR_PUSH(rest, GET_CAR(t));
u = (BPULONG)LST;
break;
case STR:
sym = GET_STR_SYM_REC(t);
n = GET_ARITY_STR(sym);
for (i = n; i >= 1; i--) {
VECTOR_PUSH(rest, GET_ARG(t, i));
}
u = (BPULONG)ADDTAG(sym, STR);
break;
case SUSP:
assert(false); /* rejected by number_vars() */
default:
assert(false);
}
h = (a * h) + (BPULONG)(u);
a *= b;
}
work = (BPLONG *)rest;
return h;
}
/*--------------------------------------------------------------------*/
static BPLONG_PTR term_pool_allocate(TERM_POOL *this, size_t size)
{
BPLONG_PTR p_tmp;
assert(size <= MAX_ARITY + 1);
if (this->head == NULL || this->curr + size > this->tail) {
BP_MALLOC(p_tmp, BLOCK_SIZE, "(prism part)");
*p_tmp = (BPLONG)(this->head);
this->head = p_tmp + 0;
this->curr = p_tmp + 1;
this->tail = p_tmp + BLOCK_SIZE;
}
p_tmp = this->curr;
this->curr += size;
return p_tmp;
}
/*--------------------------------------------------------------------*/
static TERM term_pool_store(TERM_POOL *this, TERM term)
{
TERM *p, *q, **rest;
BPLONG i, n;
SYM_REC_PTR sym;
rest = (void *)(work);
VECTOR_PUSH(rest, &term);
while (! VECTOR_EMPTY(rest)) {
p = VECTOR_POP(rest);
nderef_loop:
switch (XTAG(*p)) {
case REF0:
case REF1:
XNDEREF(*p, nderef_loop);
assert(false); /* numbered by number_vars() */
case ATM:
case INT:
case NVAR:
break;
case LST:
q = term_pool_allocate(this, 2);
*(q + 1) = GET_CDR(*p);
VECTOR_PUSH(rest, q + 1);
*(q + 0) = GET_CAR(*p);
VECTOR_PUSH(rest, q + 0);
*p = ADDTAG(q, LST);
break;
case STR:
sym = GET_STR_SYM_REC(*p);
n = GET_ARITY_STR(sym);
q = term_pool_allocate(this, n + 1);
*q = (TERM)(sym);
for (i = n; i >= 1; i--) {
*(q + i) = GET_ARG(*p, i);
VECTOR_PUSH(rest, q + i);
}
*p = ADDTAG(q, STR);
break;
case SUSP:
assert(false); /* rejected by number_vars() */
default:
assert(false);
}
}
work = (void *)(rest);
return term;
}
/*--------------------------------------------------------------------*/
static void term_pool_rehash(TERM_POOL *this)
{
struct hash_entry **bucks, *p, *q;
size_t nbucks, i;
nbucks = 2 * this->nbucks + 1;
/* find the next prime number */
for (i = 3; i * i <= nbucks; ) {
if (nbucks % i == 0) {
nbucks += 2;
i = 3;
}
else {
i += 2;
}
}
bucks = MALLOC(sizeof(struct hash_entry *) * nbucks);
for (i = 0; i < nbucks; i++)
bucks[i] = NULL;
for (i = 0; i < this->nbucks; i++) {
p = this->bucks[i];
while (p != NULL) {
q = p;
p = p->next;
q->next = bucks[q->hash % nbucks];
bucks[q->hash % nbucks] = q;
}
}
FREE(this->bucks);
this->nbucks = nbucks;
this->bucks = bucks;
}
/*--------------------------------------------------------------------*/
static TERM term_pool_search(const TERM_POOL *this, TERM term, BPULONG hash)
{
struct hash_entry *p;
p = this->bucks[hash % this->nbucks];
while (p != NULL) {
if (hash == p->hash) {
if (unifyNumberedTerms(term, p->term)) {
return p->term;
}
}
p = p->next;
}
return NULL_TERM;
}
static TERM term_pool_insert(TERM_POOL *this, TERM term, BPULONG hash)
{
struct hash_entry *entry;
if (++(this->count) >= this->nbucks)
term_pool_rehash(this);
entry = MALLOC(sizeof(struct hash_entry));
entry->term = term_pool_store(this, term);
entry->hash = hash;
entry->next = this->bucks[hash % this->nbucks];
this->bucks[hash % this->nbucks] = entry;
return entry->term;
}
/*--------------------------------------------------------------------*/
static TERM term_pool_intern(const TERM_POOL *this1, TERM_POOL *this2, TERM term)
{
BPULONG hash;
TERM rval;
assert(this2 == NULL || this2 == this1);
nderef_loop:
switch (XTAG(term)) {
case REF0:
case REF1:
XNDEREF(term, nderef_loop);
return MAKE_NVAR(0);
case ATM:
case INT:
case NVAR:
return term;
case LST:
case STR:
break;
case SUSP:
prism_quit("suspension variables not supported in Prism");
default:
assert(false);
}
number_vars(term);
hash = prism_hash_value(term);
rval = term_pool_search(this1, term, hash);
if (rval == NULL_TERM && this2 != NULL) {
rval = term_pool_insert(this2, term, hash);
}
revert_vars();
return rval;
}
/*--------------------------------------------------------------------*/
TERM_POOL * term_pool_create(void)
{
TERM_POOL *this;
int i;
this = MALLOC(sizeof(struct term_pool));
this->head = NULL;
this->curr = NULL;
this->tail = NULL;
this->nbucks = 17;
this->count = 0;
this->bucks = MALLOC(sizeof(struct hash_entry *) * this->nbucks);
for (i = 0; i < this->nbucks; i++)
this->bucks[i] = NULL;
if (work == NULL) {
VECTOR_INIT_CAPA(work, 4096);
}
return this;
}
/*--------------------------------------------------------------------*/
void term_pool_delete(TERM_POOL *this)
{
BPLONG_PTR p1, p2;
struct hash_entry *q1, *q2;
int i;
p1 = this->head;
while (p1 != NULL) {
p2 = p1;
p1 = (BPLONG_PTR)(*p1);
FREE(p2);
}
for (i = 0; i < this->nbucks; i++) {
q1 = this->bucks[i];
while (q1 != NULL) {
q2 = q1;
q1 = q1->next;
FREE(q2);
}
}
FREE(this->bucks);
FREE(this);
}
/*--------------------------------------------------------------------*/
TERM term_pool_retrieve(const TERM_POOL *this, TERM term)
{
return term_pool_intern(this, NULL, term);
}
TERM term_pool_register(TERM_POOL *this, TERM term)
{
return term_pool_intern(this, this, term);
}
/*--------------------------------------------------------------------*/

View File

@ -0,0 +1,20 @@
#ifndef TERMPOOL_H
#define TERMPOOL_H
#include "bpx.h"
/*--------------------------------------------------------------------*/
typedef struct term_pool TERM_POOL;
/*--------------------------------------------------------------------*/
TERM_POOL * term_pool_create(void);
void term_pool_delete(TERM_POOL *);
TERM term_pool_retrieve(const TERM_POOL *, TERM);
TERM term_pool_register(TERM_POOL *, TERM);
/*--------------------------------------------------------------------*/
#endif /* TERMPOOL_H */

View File

@ -0,0 +1,87 @@
#include "core/xmalloc.h"
#include "core/vector.h"
#include <assert.h>
/*--------------------------------------------------------------------*/
#define INITIAL_CAPA 16
#undef VECTOR_SIZE
#undef VECTOR_CAPA
/* allow these to be L-values */
#define VECTOR_SIZE(v) (((size_t *)(v))[-1])
#define VECTOR_CAPA(v) (((size_t *)(v))[-2])
/*--------------------------------------------------------------------*/
void * vector_create(size_t unit, size_t size, size_t capa)
{
void *ptr, *vec;
ptr = MALLOC(sizeof(size_t) * 2 + unit * capa);
vec = ((size_t *)(ptr)) + 2;
VECTOR_SIZE(vec) = size;
VECTOR_CAPA(vec) = capa;
return vec;
}
void vector_delete(void *vec)
{
free(((size_t *)(vec)) - 2);
}
void * vector_expand(void *vec, size_t unit)
{
size_t capa;
if (VECTOR_SIZE(vec) >= VECTOR_CAPA(vec)) {
capa = VECTOR_CAPA(vec) * 2;
if (capa < INITIAL_CAPA) {
capa = INITIAL_CAPA;
}
vec = vector_realloc(vec, unit, capa);
}
++(VECTOR_SIZE(vec));
return vec;
}
void * vector_reduce(void *vec)
{
assert(VECTOR_SIZE(vec) > 0);
--(VECTOR_SIZE(vec));
return vec;
}
void * vector_resize(void *vec, size_t unit, size_t size)
{
vec = vector_reserve(vec, unit, size);
VECTOR_SIZE(vec) = size;
return vec;
}
void * vector_reserve(void *vec, size_t unit, size_t capa)
{
if (VECTOR_CAPA(vec) < capa) {
vec = vector_realloc(vec, unit, capa);
}
return vec;
}
void * vector_realloc(void *vec, size_t unit, size_t capa)
{
void *ptr;
if (VECTOR_CAPA(vec) == capa)
return vec;
assert(VECTOR_SIZE(vec) <= capa);
ptr = ((size_t *)(vec)) - 2;
ptr = REALLOC(ptr, sizeof(size_t) * 2 + unit * capa);
vec = ((size_t *)(ptr)) + 2;
VECTOR_CAPA(vec) = capa;
return vec;
}
/*--------------------------------------------------------------------*/

View File

@ -0,0 +1,59 @@
#ifndef VECTOR_H
#define VECTOR_H
#include "stddef.h"
/*--------------------------------------------------------------------*/
#define VECTOR_INIT(v) \
((v) = vector_create(sizeof(*(v)), 0, 0))
#define VECTOR_INIT_SIZE(v, n) \
((v) = vector_create(sizeof(*(v)), n, n))
#define VECTOR_INIT_CAPA(v, m) \
((v) = vector_create(sizeof(*(v)), 0, m))
#define VECTOR_FREE(v) \
((v) = (vector_delete(v), NULL))
/*--------------------------------------------------------------------*/
#define VECTOR_SIZE(v) \
((size_t)(((const size_t *)(v))[-1]))
#define VECTOR_CAPA(v) \
((size_t)(((const size_t *)(v))[-2]))
#define VECTOR_PUSH(v, x) \
((v) = vector_expand(v, sizeof(*(v))), (v)[VECTOR_SIZE(v) - 1] = (x))
#define VECTOR_POP(v) \
((v) = vector_reduce(v), (v)[VECTOR_SIZE(v)])
#define VECTOR_PUSH_NONE(v) \
((v) = vector_expand(v, sizeof(*(v))))
#define VECTOR_RESIZE(v, n) \
((v) = vector_resize(v, sizeof(*(v)), n))
#define VECTOR_RESERVE(v, m) \
((v) = vector_reserve(v, sizeof(*(v)), m))
#define VECTOR_STRIP(v) \
((v) = vector_realloc(v, sizeof(*(v)), VECTOR_SIZE(v)))
#define VECTOR_CLEAR(v) \
((void)(((const size_t *)(v))[-1] = 0))
#define VECTOR_EMPTY(v) \
(VECTOR_SIZE(v) == 0)
/*--------------------------------------------------------------------*/
void * vector_create(size_t, size_t, size_t);
void vector_delete(void *);
void * vector_expand(void *, size_t);
void * vector_reduce(void *);
void * vector_resize(void *, size_t, size_t);
void * vector_reserve(void *, size_t, size_t);
void * vector_realloc(void *, size_t, size_t);
/*--------------------------------------------------------------------*/
#endif /* VECTOR_H */

View File

@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
#include "core/xmalloc.h"
/*--------------------------------------------------------------------*/
void * xmalloc
(size_t size, const char *file, unsigned int line)
{
void *ptr;
ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Out of memory in %s(%u)\n", file, line);
exit(1); /* FIXME */
}
return ptr;
}
void * xrealloc
(void *oldptr, size_t size, const char *file, unsigned int line)
{
void *newptr;
newptr = realloc(oldptr, size);
if (newptr == NULL && size > 0) {
fprintf(stderr, "Out of memory in %s(%u)\n", file, line);
exit(1); /* FIXME */
}
return newptr;
}
/*--------------------------------------------------------------------*/

View File

@ -0,0 +1,25 @@
#ifndef XMALLOC_H
#define XMALLOC_H
#include <stdlib.h>
/*--------------------------------------------------------------------*/
void * xmalloc(size_t, const char *, unsigned int);
void * xrealloc(void *, size_t, const char *, unsigned int);
/*--------------------------------------------------------------------*/
#ifdef MALLOC_TRACE
# define MALLOC(size) malloc((size))
# define REALLOC(oldptr,size) realloc((oldptr),(size))
# define FREE(ptr) (free(ptr), (ptr) = NULL)
#else
# define MALLOC(size) xmalloc((size), __FILE__, __LINE__)
# define REALLOC(oldptr,size) xrealloc((oldptr), (size), __FILE__, __LINE__)
# define FREE(ptr) (free(ptr), (ptr) = NULL)
#endif
/*--------------------------------------------------------------------*/
#endif /* XMALLOC_H */

View File

@ -0,0 +1,56 @@
# -*- Makefile -*-
##----------------------------------------------------------------------
CORE_OBJS = core$(S)glue.$(O) \
core$(S)bpx.$(O) \
core$(S)idtable.$(O) \
core$(S)idtable_preds.$(O) \
core$(S)termpool.$(O) \
core$(S)vector.$(O) \
core$(S)random.$(O) \
core$(S)gamma.$(O) \
core$(S)xmalloc.$(O) \
core$(S)fputil.$(O) \
core$(S)error.$(O)
UP_OBJS = up$(S)graph.$(O) \
up$(S)graph_aux.$(O) \
up$(S)em_preds.$(O) \
up$(S)em_ml.$(O) \
up$(S)em_vb.$(O) \
up$(S)em_aux.$(O) \
up$(S)em_aux_ml.$(O) \
up$(S)em_aux_vb.$(O) \
up$(S)viterbi.$(O) \
up$(S)hindsight.$(O) \
up$(S)flags.$(O) \
up$(S)util.$(O)
MP_OBJS = mp$(S)mp_core.$(O) \
mp$(S)mp_em_aux.$(O) \
mp$(S)mp_em_ml.$(O) \
mp$(S)mp_em_preds.$(O) \
mp$(S)mp_em_vb.$(O) \
mp$(S)mp_flags.$(O) \
mp$(S)mp_preds.$(O) \
mp$(S)mp_sw.$(O)
OBJS = $(CORE_OBJS) $(UP_OBJS)
##----------------------------------------------------------------------
INSTALLDIR = ..$(S)..$(S)bin
CORE_DIR = core
UP_DIR = up
MP_DIR = mp
SUBDIRS = $(CORE_DIR) $(UP_DIR)
##----------------------------------------------------------------------
#BP4P_A = bp4prism$(S)lib$(S)bp4prism-$(PLATFORM).$(A)
BP4P_A =
##----------------------------------------------------------------------

View File

@ -0,0 +1,11 @@
===================== README (src/c/makefiles) =====================
This directory contains the Makefiles which are included into the
Makefiles in the above directory:
Makefile.opts.gmake ... settings for GNU make
Makefile.opts.nmake ... settings for nmake (MSVC++)
Makefile.files ... source file names
If you would like to change the default settings, please modify
these Makefiles.

View File

@ -0,0 +1,21 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_H
#define MP_H
/*-------------------------------------------------------------------------*/
#include <mpi.h>
/*-------------------------------------------------------------------------*/
#define TAG_GOAL_REQ (1)
#define TAG_GOAL_LEN (2)
#define TAG_GOAL_STR (3)
#define TAG_SWITCH_REQ (4)
#define TAG_SWITCH_RES (5)
/*-------------------------------------------------------------------------*/
#endif /* MP_H */

View File

@ -0,0 +1,101 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
/* [27 Aug 2007, by yuizumi]
* FIXME: mp_debug() is currently platform-dependent.
*/
#ifdef MPI
#include "up/up.h"
#include "mp/mp.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>
#include <unistd.h> /* STDOUT_FILENO */
#include <mpi.h>
/* Currently mpprism works only on Linux systems. */
#define DEV_NULL "/dev/null"
/*-------------------------------------------------------------------------*/
int fd_dup_stdout = -1;
int mp_size;
int mp_rank;
/*-------------------------------------------------------------------------*/
static void close_stdout(void)
{
fd_dup_stdout = dup(STDOUT_FILENO);
if (fd_dup_stdout < 0)
return;
if (freopen(DEV_NULL, "w", stdout) == NULL) {
close(fd_dup_stdout);
fd_dup_stdout = -1;
}
}
/*-------------------------------------------------------------------------*/
void mp_init(int *argc, char **argv[])
{
MPI_Init(argc, argv);
MPI_Comm_size(MPI_COMM_WORLD, &mp_size);
MPI_Comm_rank(MPI_COMM_WORLD, &mp_rank);
if (mp_size < 2) {
printf("Two or more processes required to run mpprism.\n");
MPI_Finalize();
exit(1);
}
if (mp_rank > 0) {
close_stdout();
}
}
void mp_done(void)
{
MPI_Finalize();
}
NORET mp_quit(int status)
{
fprintf(stderr, "The system is aborted by Rank #%d.\n", mp_rank);
MPI_Abort(MPI_COMM_WORLD, status);
exit(status); /* should not reach here */
}
/*-------------------------------------------------------------------------*/
void mp_debug(const char *fmt, ...)
{
#ifdef MP_DEBUG
char str[1024];
va_list ap;
struct timeval tv;
int s, u;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
gettimeofday(&tv, NULL);
s = tv.tv_sec;
u = tv.tv_usec;
fprintf(stderr, "[RANK:%d] %02d:%02d:%02d.%03d -- %s\n",
mp_rank, (s / 3600) % 24, (s / 60) % 60, s % 60, u / 1000, str);
#endif
}
/*-------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,19 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_CORE_H
#define MP_CORE_H
/*-------------------------------------------------------------------------*/
extern int mp_size;
extern int mp_rank;
extern int fd_dup_stdout;
/*-------------------------------------------------------------------------*/
void mp_debug(const char *, ...);
NORET mp_quit(int);
/*-------------------------------------------------------------------------*/
#endif /* MP_CORE_H */

View File

@ -0,0 +1,256 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
#include "up/em.h"
#include "up/graph.h"
#include "mp/mp.h"
#include "mp/mp_core.h"
#include "mp/mp_sw.h"
#include <stdlib.h>
/*------------------------------------------------------------------------*/
int sw_msg_size = 0;
static void * sw_msg_send = NULL;
static void * sw_msg_recv = NULL;
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
NORET quit(const char *);
/*------------------------------------------------------------------------*/
void alloc_sw_msg_buffers(void)
{
sw_msg_send = MALLOC(sizeof(double) * sw_msg_size);
sw_msg_recv = MALLOC(sizeof(double) * sw_msg_size);
}
void release_sw_msg_buffers(void)
{
free(sw_msg_send);
sw_msg_send = NULL;
free(sw_msg_recv);
sw_msg_recv = NULL;
}
/*------------------------------------------------------------------------*/
void mpm_bcast_fixed(void)
{
SW_INS_PTR sw_ins_ptr;
char *meg_ptr;
int i;
meg_ptr = sw_msg_send;
for (i = 0; i < occ_switch_tab_size; i++) {
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
*(meg_ptr++) = (!!sw_ins_ptr->fixed) | ((!!sw_ins_ptr->fixed_h) << 1);
}
}
MPI_Bcast(sw_msg_send, sw_msg_size, MPI_CHAR, 0, MPI_COMM_WORLD);
mp_debug("mpm_bcast_fixed");
}
void mps_bcast_fixed(void)
{
SW_INS_PTR sw_ins_ptr;
char *meg_ptr;
int i;
MPI_Bcast(sw_msg_recv, sw_msg_size, MPI_CHAR, 0, MPI_COMM_WORLD);
mp_debug("mps_bcast_fixed");
for (i = 0; i < occ_switch_tab_size; i++) {
meg_ptr = sw_msg_recv;
meg_ptr += occ_position[i];
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
sw_ins_ptr->fixed = !!(*meg_ptr & 1);
sw_ins_ptr->fixed_h = !!(*meg_ptr & 2);
meg_ptr++;
}
}
}
void mpm_bcast_inside(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
meg_ptr = sw_msg_send;
for (i = 0; i < occ_switch_tab_size; i++) {
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
*(meg_ptr++) = sw_ins_ptr->inside;
}
}
MPI_Bcast(sw_msg_send, sw_msg_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
mp_debug("mpm_bcast_inside");
}
void mps_bcast_inside(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
MPI_Bcast(sw_msg_recv, sw_msg_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
mp_debug("mps_bcast_inside");
for (i = 0; i < occ_switch_tab_size; i++) {
meg_ptr = sw_msg_recv;
meg_ptr += occ_position[i];
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
sw_ins_ptr->inside = *(meg_ptr++);
}
}
}
void mpm_bcast_inside_h(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
meg_ptr = sw_msg_send;
for (i = 0; i < occ_switch_tab_size; i++) {
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
*(meg_ptr++) = sw_ins_ptr->inside_h;
}
}
MPI_Bcast(sw_msg_send, sw_msg_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
mp_debug("mpm_bcast_inside_h");
}
void mps_bcast_inside_h(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
MPI_Bcast(sw_msg_recv, sw_msg_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
mp_debug("mps_bcast_inside_h");
for (i = 0; i < occ_switch_tab_size; i++) {
meg_ptr = sw_msg_recv;
meg_ptr += occ_position[i];
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
sw_ins_ptr->inside_h = *(meg_ptr++);
}
}
}
void mpm_bcast_smooth(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
meg_ptr = sw_msg_send;
for (i = 0; i < occ_switch_tab_size; i++) {
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
*(meg_ptr++) = sw_ins_ptr->smooth;
}
}
MPI_Bcast(sw_msg_send, sw_msg_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
mp_debug("mpm_bcast_smooth");
}
void mps_bcast_smooth(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
MPI_Bcast(sw_msg_recv, sw_msg_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
mp_debug("mps_bcast_smooth");
for (i = 0; i < occ_switch_tab_size; i++) {
meg_ptr = sw_msg_recv;
meg_ptr += occ_position[i];
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
sw_ins_ptr->smooth = *(meg_ptr++);
}
}
}
/*------------------------------------------------------------------------*/
void clear_sw_msg_send(void)
{
double *meg_ptr;
double *end_ptr;
meg_ptr = sw_msg_send;
end_ptr = meg_ptr + sw_msg_size;
while (meg_ptr != end_ptr) {
*(meg_ptr++) = 0.0;
}
}
void mpm_share_expectation(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
MPI_Allreduce(sw_msg_send, sw_msg_recv, sw_msg_size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
meg_ptr = sw_msg_recv;
for (i = 0; i < occ_switch_tab_size; i++) {
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
sw_ins_ptr->total_expect = *(meg_ptr++);
}
}
}
void mps_share_expectation(void)
{
SW_INS_PTR sw_ins_ptr;
double *meg_ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
meg_ptr = sw_msg_send;
meg_ptr += occ_position[i];
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
*(meg_ptr++) = sw_ins_ptr->total_expect;
}
}
MPI_Allreduce(sw_msg_send, sw_msg_recv, sw_msg_size, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
for (i = 0; i < occ_switch_tab_size; i++) {
meg_ptr = sw_msg_recv;
meg_ptr += occ_position[i];
for (sw_ins_ptr = occ_switches[i]; sw_ins_ptr != NULL; sw_ins_ptr = sw_ins_ptr->next) {
sw_ins_ptr->total_expect = *(meg_ptr++);
}
}
}
double mp_sum_value(double value)
{
double g_value;
MPI_Allreduce(&value, &g_value, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
return g_value;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,29 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_EM_AUX_H
#define MP_EM_AUX_H
/*-------------------------------------------------------------------------*/
extern int sw_msg_size;
/*-------------------------------------------------------------------------*/
void alloc_sw_msg_buffers(void);
void release_sw_msg_buffers(void);
void mpm_bcast_fixed(void);
void mps_bcast_fixed(void);
void mpm_bcast_inside(void);
void mps_bcast_inside(void);
void mpm_bcast_inside_h(void);
void mps_bcast_inside_h(void);
void mpm_bcast_smooth(void);
void mps_bcast_smooth(void);
void clear_sw_msg_send(void);
void mpm_share_expectation(void);
void mps_share_expectation(void);
double mp_sum_value(double);
/*-------------------------------------------------------------------------*/
#endif /* MP_EM_AUX_H */

View File

@ -0,0 +1,265 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "core/error.h"
#include "up/up.h"
#include "up/em.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/em_ml.h"
#include "up/graph.h"
#include "up/flags.h"
#include "up/util.h"
#include "mp/mp.h"
#include "mp/mp_core.h"
#include "mp/mp_em_aux.h"
#include <mpi.h>
/*------------------------------------------------------------------------*/
void mpm_share_preconds_em(int *smooth)
{
int ivals[4];
int ovals[4];
ivals[0] = sw_msg_size;
ivals[1] = 0;
ivals[2] = 0;
ivals[3] = *smooth;
MPI_Allreduce(ivals, ovals, 4, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
sw_msg_size = ovals[0];
num_goals = ovals[1];
failure_observed = ovals[2];
*smooth = ovals[3];
mp_debug("msgsize=%d, #goals=%d, failure=%s, smooth = %s",
sw_msg_size, num_goals, failure_observed ? "on" : "off", *smooth ? "on" : "off");
alloc_sw_msg_buffers();
mpm_bcast_fixed();
if (*smooth) {
mpm_bcast_smooth();
}
}
void mps_share_preconds_em(int *smooth)
{
int ivals[4];
int ovals[4];
ivals[0] = 0;
ivals[1] = num_goals;
ivals[2] = failure_observed;
ivals[3] = 0;
MPI_Allreduce(ivals, ovals, 4, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
sw_msg_size = ovals[0];
num_goals = ovals[1];
failure_observed = ovals[2];
*smooth = ovals[3];
mp_debug("msgsize=%d, #goals=%d, failure=%s, smooth = %s",
sw_msg_size, num_goals, failure_observed ? "on" : "off", *smooth ? "on" : "off");
alloc_sw_msg_buffers();
mps_bcast_fixed();
if (*smooth) {
mps_bcast_smooth();
}
}
/*------------------------------------------------------------------------*/
int mpm_run_em(EM_ENG_PTR emptr)
{
int r, iterate, old_valid, converged, saved=0;
double likelihood, log_prior;
double lambda, old_lambda=0.0;
config_em(emptr);
for (r = 0; r < num_restart; r++) {
SHOW_PROGRESS_HEAD("#em-iters", r);
initialize_params();
mpm_bcast_inside();
clear_sw_msg_send();
itemp = daem ? itemp_init : 1.0;
iterate = 0;
while (1) {
if (daem) {
SHOW_PROGRESS_TEMP(itemp);
}
old_valid = 0;
while (1) {
if (CTRLC_PRESSED) {
SHOW_PROGRESS_INTR();
RET_ERR(err_ctrl_c_pressed);
}
if (failure_observed) {
inside_failure = mp_sum_value(0.0);
}
log_prior = emptr->smooth ? emptr->compute_log_prior() : 0.0;
lambda = mp_sum_value(log_prior);
likelihood = lambda - log_prior;
mp_debug("local lambda = %.9f, lambda = %.9f", log_prior, lambda);
if (verb_em) {
if (emptr->smooth) {
prism_printf("Iteration #%d:\tlog_likelihood=%.9f\tlog_prior=%.9f\tlog_post=%.9f\n", iterate, likelihood, log_prior, lambda);
}
else {
prism_printf("Iteration #%d:\tlog_likelihood=%.9f\n", iterate, likelihood);
}
}
if (!isfinite(lambda)) {
emit_internal_error("invalid log likelihood or log post: %s (at iterateion #%d)",
isnan(lambda) ? "NaN" : "infinity", iterate);
RET_ERR(ierr_invalid_likelihood);
}
if (old_valid && old_lambda - lambda > prism_epsilon) {
emit_error("log likelihood or log post decreased [old: %.9f, new: %.9f] (at iteration #%d)",
old_lambda, lambda, iterate);
RET_ERR(err_invalid_likelihood);
}
if (itemp == 1.0 && likelihood > 0.0) {
emit_error("log likelihood greater than zero [value: %.9f] (at iteration #%d)",
likelihood, iterate);
RET_ERR(err_invalid_likelihood);
}
converged = (old_valid && lambda - old_lambda <= prism_epsilon);
if (converged || REACHED_MAX_ITERATE(iterate)) {
break;
}
old_lambda = lambda;
old_valid = 1;
mpm_share_expectation();
SHOW_PROGRESS(iterate);
RET_ON_ERR(emptr->update_params());
iterate++;
}
if (itemp == 1.0) {
break;
}
itemp *= itemp_rate;
if (itemp >= 1.0) {
itemp = 1.0;
}
}
SHOW_PROGRESS_TAIL(converged, iterate, lambda);
if (r == 0 || lambda > emptr->lambda) {
emptr->lambda = lambda;
emptr->likelihood = likelihood;
emptr->iterate = iterate;
saved = (r < num_restart - 1);
if (saved) {
save_params();
}
}
}
if (saved) {
restore_params();
}
emptr->bic = compute_bic(emptr->likelihood);
emptr->cs = emptr->smooth ? compute_cs(emptr->likelihood) : 0.0;
return BP_TRUE;
}
int mps_run_em(EM_ENG_PTR emptr)
{
int r, iterate, old_valid, converged, saved=0;
double likelihood;
double lambda, old_lambda=0.0;
config_em(emptr);
for (r = 0; r < num_restart; r++) {
mps_bcast_inside();
clear_sw_msg_send();
itemp = daem ? itemp_init : 1.0;
iterate = 0;
while (1) {
old_valid = 0;
while (1) {
RET_ON_ERR(emptr->compute_inside());
RET_ON_ERR(emptr->examine_inside());
if (failure_observed) {
inside_failure = mp_sum_value(inside_failure);
}
likelihood = emptr->compute_likelihood();
lambda = mp_sum_value(likelihood);
mp_debug("local lambda = %.9f, lambda = %.9f", likelihood, lambda);
converged = (old_valid && lambda - old_lambda <= prism_epsilon);
if (converged || REACHED_MAX_ITERATE(iterate)) {
break;
}
old_lambda = lambda;
old_valid = 1;
RET_ON_ERR(emptr->compute_expectation());
mps_share_expectation();
RET_ON_ERR(emptr->update_params());
iterate++;
}
if (itemp == 1.0) {
break;
}
itemp *= itemp_rate;
if (itemp >= 1.0) {
itemp = 1.0;
}
}
if (r == 0 || lambda > emptr->lambda) {
emptr->lambda = lambda;
saved = (r < num_restart - 1);
if (saved) {
save_params();
}
}
}
if (saved) {
restore_params();
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,15 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_EM_ML_H
#define MP_EM_ML_H
/*-------------------------------------------------------------------------*/
void mpm_share_preconds_em(int *);
void mps_share_preconds_em(int *);
int mpm_run_em(EM_ENG_PTR);
int mps_run_em(EM_ENG_PTR);
/*-------------------------------------------------------------------------*/
#endif /* MP_EM_ML_H */

View File

@ -0,0 +1,167 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
#include "up/em.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/em_aux_vb.h"
#include "up/graph.h"
#include "up/flags.h"
#include "mp/mp.h"
#include "mp/mp_core.h"
#include "mp/mp_em_aux.h"
#include "mp/mp_em_ml.h"
#include "mp/mp_em_vb.h"
#include "mp/mp_sw.h"
#include <mpi.h>
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
NORET myquit(int, const char *);
/*------------------------------------------------------------------------*/
int pc_mpm_prism_em_6(void)
{
struct EM_Engine em_eng;
/* [28 Aug 2007, by yuizumi]
* occ_switches[] will be freed in pc_import_occ_switches/1.
* occ_position[] is not allocated.
*/
RET_ON_ERR(check_smooth(&em_eng.smooth));
mpm_share_preconds_em(&em_eng.smooth);
RET_ON_ERR(mpm_run_em(&em_eng));
release_sw_msg_buffers();
release_num_sw_vals();
return
bpx_unify(bpx_get_call_arg(1,6), bpx_build_integer(em_eng.iterate)) &&
bpx_unify(bpx_get_call_arg(2,6), bpx_build_float(em_eng.lambda)) &&
bpx_unify(bpx_get_call_arg(3,6), bpx_build_float(em_eng.likelihood)) &&
bpx_unify(bpx_get_call_arg(4,6), bpx_build_float(em_eng.bic)) &&
bpx_unify(bpx_get_call_arg(5,6), bpx_build_float(em_eng.cs)) &&
bpx_unify(bpx_get_call_arg(6,6), bpx_build_integer(em_eng.smooth));
}
int pc_mps_prism_em_0(void)
{
struct EM_Engine em_eng;
mps_share_preconds_em(&em_eng.smooth);
RET_ON_ERR(mps_run_em(&em_eng));
release_sw_msg_buffers();
release_occ_switches();
release_num_sw_vals();
release_occ_position();
return BP_TRUE;
}
int pc_mpm_prism_vbem_2(void)
{
struct VBEM_Engine vb_eng;
RET_ON_ERR(check_smooth_vb());
mpm_share_preconds_vbem();
RET_ON_ERR(mpm_run_vbem(&vb_eng));
release_sw_msg_buffers();
release_num_sw_vals();
return
bpx_unify(bpx_get_call_arg(1,2), bpx_build_integer(vb_eng.iterate)) &&
bpx_unify(bpx_get_call_arg(2,2), bpx_build_float(vb_eng.free_energy));
}
int pc_mps_prism_vbem_0(void)
{
struct VBEM_Engine vb_eng;
mps_share_preconds_vbem();
RET_ON_ERR(mps_run_vbem(&vb_eng));
release_sw_msg_buffers();
release_occ_switches();
release_num_sw_vals();
release_occ_position();
return BP_TRUE;
}
int pc_mpm_prism_both_em_2(void)
{
struct VBEM_Engine vb_eng;
RET_ON_ERR(check_smooth_vb());
mpm_share_preconds_vbem();
RET_ON_ERR(mpm_run_vbem(&vb_eng));
get_param_means();
release_sw_msg_buffers();
release_num_sw_vals();
return
bpx_unify(bpx_get_call_arg(1,2), bpx_build_integer(vb_eng.iterate)) &&
bpx_unify(bpx_get_call_arg(2,2), bpx_build_float(vb_eng.free_energy));
}
int pc_mps_prism_both_em_0(void)
{
struct VBEM_Engine vb_eng;
mps_share_preconds_vbem();
RET_ON_ERR(mps_run_vbem(&vb_eng));
get_param_means();
release_sw_msg_buffers();
release_occ_switches();
release_num_sw_vals();
release_occ_position();
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
int pc_mpm_import_graph_stats_4(void)
{
int dummy[4] = { 0 };
int stats[4];
double avg_shared;
MPI_Reduce(dummy, stats, 4, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
avg_shared = (double)(stats[3]) / stats[0];
return
bpx_unify(bpx_get_call_arg(1,4), bpx_build_integer(stats[0])) &&
bpx_unify(bpx_get_call_arg(2,4), bpx_build_integer(stats[1])) &&
bpx_unify(bpx_get_call_arg(3,4), bpx_build_integer(stats[2])) &&
bpx_unify(bpx_get_call_arg(4,4), bpx_build_float(avg_shared));
}
int pc_mps_import_graph_stats_0(void)
{
int dummy[4];
int stats[4];
graph_stats(stats);
MPI_Reduce(stats, dummy, 4, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
mp_debug("# subgoals = %d", stats[0]);
mp_debug("# goal nodes = %d", stats[1]);
mp_debug("# switch nodes = %d", stats[2]);
mp_debug("# sharings = %d", stats[3]);
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,19 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_EM_PREDS_H
#define MP_EM_PREDS_H
/*-------------------------------------------------------------------------*/
int pc_mpm_prism_em_6(void);
int pc_mps_prism_em_0(void);
int pc_mpm_prism_vbem_2(void);
int pc_mps_prism_vbem_0(void);
int pc_mpm_prism_both_em_7(void);
int pc_mps_prism_both_em_0(void);
int pc_mpm_import_graph_stats_4(void);
int pc_mps_import_graph_stats_0(void);
/*-------------------------------------------------------------------------*/
#endif /* MP_EM_PREDS_H */

View File

@ -0,0 +1,256 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
#include "up/em.h"
#include "up/em_aux.h"
#include "up/em_aux_vb.h"
#include "up/em_vb.h"
#include "up/graph.h"
#include "up/flags.h"
#include "up/util.h"
#include "mp/mp.h"
#include "mp/mp_core.h"
#include "mp/mp_em_aux.h"
#include <mpi.h>
/*------------------------------------------------------------------------*/
void mpm_share_preconds_vbem(void)
{
int ivals[3];
int ovals[3];
ivals[0] = sw_msg_size;
ivals[1] = 0;
ivals[2] = 0;
MPI_Allreduce(ivals, ovals, 3, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
sw_msg_size = ovals[0];
num_goals = ovals[1];
failure_observed = ovals[2];
mp_debug("msgsize=%d, #goals=%d, failure=%s",
sw_msg_size, num_goals, failure_observed ? "on" : "off");
alloc_sw_msg_buffers();
mpm_bcast_fixed();
}
void mps_share_preconds_vbem(void)
{
int ivals[3];
int ovals[3];
ivals[0] = 0;
ivals[1] = num_goals;
ivals[2] = failure_observed;
MPI_Allreduce(ivals, ovals, 3, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
sw_msg_size = ovals[0];
num_goals = ovals[1];
failure_observed = ovals[2];
mp_debug("msgsize=%d, #goals=%d, failure=%s",
sw_msg_size, num_goals, failure_observed ? "on" : "off");
alloc_sw_msg_buffers();
mps_bcast_fixed();
}
/*------------------------------------------------------------------------*/
int mpm_run_vbem(VBEM_ENG_PTR vbptr)
{
int r, iterate, old_valid, converged, saved=0;
double free_energy, old_free_energy=0.0;
double l0, l1;
config_vbem(vbptr);
for (r = 0; r < num_restart; r++) {
SHOW_PROGRESS_HEAD("#vbem-iters", r);
initialize_hyperparams();
mpm_bcast_inside_h();
mpm_bcast_smooth();
clear_sw_msg_send();
itemp = daem ? itemp_init : 1.0;
iterate = 0;
while (1) {
if (daem) {
SHOW_PROGRESS_TEMP(itemp);
}
old_valid = 0;
while (1) {
if (CTRLC_PRESSED) {
SHOW_PROGRESS_INTR();
RET_ERR(err_ctrl_c_pressed);
}
RET_ON_ERR(vbptr->compute_pi());
if (failure_observed) {
inside_failure = mp_sum_value(0.0);
}
l0 = vbptr->compute_free_energy_l0();
l1 = vbptr->compute_free_energy_l1();
free_energy = mp_sum_value(l0 - l1);
mp_debug("local free_energy = %.9f, free_energy = %.9f", l0 - l1, free_energy);
if (verb_em) {
prism_printf("Iteration #%d:\tfree_energy=%.9f\n", iterate, free_energy);
}
if (!isfinite(free_energy)) {
emit_internal_error("invalid variational free energy: %s (at iteration #%d)",
isnan(free_energy) ? "NaN" : "infinity", iterate);
RET_ERR(err_invalid_free_energy);
}
if (old_valid && old_free_energy - free_energy > prism_epsilon) {
emit_error("variational free energy decreased [old: %.9f, new: %.9f] (at iteration #%d)",
old_free_energy, free_energy, iterate);
RET_ERR(err_invalid_free_energy);
}
if (itemp == 1.0 && free_energy > 0.0) {
emit_error("variational free energy greater than zero [value: %.9f] (at iteration #%d)",
free_energy, iterate);
RET_ERR(err_invalid_free_energy);
}
converged = (old_valid && free_energy - old_free_energy <= prism_epsilon);
if (converged || REACHED_MAX_ITERATE(iterate)) {
break;
}
old_free_energy = free_energy;
old_valid = 1;
mpm_share_expectation();
SHOW_PROGRESS(iterate);
RET_ON_ERR(vbptr->update_hyperparams());
iterate++;
}
if (itemp == 1.0) {
break;
}
itemp *= itemp_rate;
if (itemp >= 1.0) {
itemp = 1.0;
}
}
SHOW_PROGRESS_TAIL(converged, iterate, free_energy);
if (r == 0 || free_energy > vbptr->free_energy) {
vbptr->free_energy = free_energy;
vbptr->iterate = iterate;
saved = (r < num_restart - 1);
if (saved) {
save_hyperparams();
}
}
}
if (saved) {
restore_hyperparams();
}
transfer_hyperparams();
return BP_TRUE;
}
int mps_run_vbem(VBEM_ENG_PTR vbptr)
{
int r, iterate, old_valid, converged, saved=0;
double free_energy, old_free_energy=0.0;
double l2;
config_vbem(vbptr);
for (r = 0; r < num_restart; r++) {
mps_bcast_inside_h();
mps_bcast_smooth();
clear_sw_msg_send();
itemp = daem ? itemp_init : 1.0;
iterate = 0;
while (1) {
old_valid = 0;
while (1) {
RET_ON_ERR(vbptr->compute_pi());
RET_ON_ERR(vbptr->compute_inside());
RET_ON_ERR(vbptr->examine_inside());
if (failure_observed) {
inside_failure = mp_sum_value(inside_failure);
}
l2 = vbptr->compute_likelihood() / itemp;
free_energy = mp_sum_value(l2);
mp_debug("local free_energy = %.9f, free_energy = %.9f", l2, free_energy);
converged = (old_valid && free_energy - old_free_energy <= prism_epsilon);
if (converged || REACHED_MAX_ITERATE(iterate)) {
break;
}
old_free_energy = free_energy;
old_valid = 1;
RET_ON_ERR(vbptr->compute_expectation());
mps_share_expectation();
RET_ON_ERR(vbptr->update_hyperparams());
iterate++;
}
if (itemp == 1.0) {
break;
}
itemp *= itemp_rate;
if (itemp >= 1.0) {
itemp = 1.0;
}
}
if (r == 0 || free_energy > vbptr->free_energy) {
vbptr->free_energy = free_energy;
saved = (r < num_restart - 1);
if (saved) {
save_hyperparams();
}
}
}
if (saved) {
restore_hyperparams();
}
transfer_hyperparams();
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,15 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_EM_VB_H
#define MP_EM_VB_H
/*-------------------------------------------------------------------------*/
void mpm_share_preconds_vbem(void);
void mps_share_preconds_vbem(void);
int mpm_run_vbem(VBEM_ENG_PTR);
int mps_run_vbem(VBEM_ENG_PTR);
/*-------------------------------------------------------------------------*/
#endif /* MP_EM_VB_H */

View File

@ -0,0 +1,77 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/flags.h"
#include <mpi.h>
/*------------------------------------------------------------------------*/
#define PUT(msg,pos,type,value) \
MPI_Pack(&(value),1,(type),(msg),sizeof(msg),&(pos),MPI_COMM_WORLD)
#define GET(msg,pos,type,value) \
MPI_Unpack((msg),sizeof(msg),&(pos),&(value),1,(type),MPI_COMM_WORLD)
/*------------------------------------------------------------------------*/
int pc_mpm_share_prism_flags_0(void)
{
char msg[256];
int pos = 0;
PUT( msg , pos , MPI_INT , daem );
PUT( msg , pos , MPI_INT , em_message );
PUT( msg , pos , MPI_INT , em_progress );
PUT( msg , pos , MPI_INT , error_on_cycle );
PUT( msg , pos , MPI_INT , fix_init_order );
PUT( msg , pos , MPI_INT , init_method );
PUT( msg , pos , MPI_DOUBLE , itemp_init );
PUT( msg , pos , MPI_DOUBLE , itemp_rate );
PUT( msg , pos , MPI_INT , log_scale );
PUT( msg , pos , MPI_INT , max_iterate );
PUT( msg , pos , MPI_INT , num_restart );
PUT( msg , pos , MPI_DOUBLE , prism_epsilon );
PUT( msg , pos , MPI_DOUBLE , std_ratio );
PUT( msg , pos , MPI_INT , verb_em );
PUT( msg , pos , MPI_INT , verb_graph );
PUT( msg , pos , MPI_INT , warn );
MPI_Bcast(msg, sizeof(msg), MPI_PACKED, 0, MPI_COMM_WORLD);
return BP_TRUE;
}
int pc_mps_share_prism_flags_0(void)
{
char msg[256];
int pos = 0;
MPI_Bcast(msg, sizeof(msg), MPI_PACKED, 0, MPI_COMM_WORLD);
GET( msg , pos , MPI_INT , daem );
GET( msg , pos , MPI_INT , em_message );
GET( msg , pos , MPI_INT , em_progress );
GET( msg , pos , MPI_INT , error_on_cycle );
GET( msg , pos , MPI_INT , fix_init_order );
GET( msg , pos , MPI_INT , init_method );
GET( msg , pos , MPI_DOUBLE , itemp_init );
GET( msg , pos , MPI_DOUBLE , itemp_rate );
GET( msg , pos , MPI_INT , log_scale );
GET( msg , pos , MPI_INT , max_iterate );
GET( msg , pos , MPI_INT , num_restart );
GET( msg , pos , MPI_DOUBLE , prism_epsilon );
GET( msg , pos , MPI_DOUBLE , std_ratio );
GET( msg , pos , MPI_INT , verb_em );
GET( msg , pos , MPI_INT , verb_graph );
GET( msg , pos , MPI_INT , warn );
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,13 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_FLAGS_H
#define MP_FLAGS_H
/*-------------------------------------------------------------------------*/
int pc_mpm_share_prism_flags_0(void);
int pc_mps_share_prism_flags_0(void);
/*-------------------------------------------------------------------------*/
#endif /* MP_FLAGS_H */

View File

@ -0,0 +1,191 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
#include "bprolog.h"
#include "core/error.h"
#include "up/up.h"
#include "mp/mp.h"
#include "mp/mp_core.h"
#include <unistd.h> /* STDOUT_FILENO */
#include <string.h>
#include <mpi.h>
/*------------------------------------------------------------------------*/
/* cpred.c (B-Prolog) */
int bp_string_2_term(const char *, TERM, TERM);
/*------------------------------------------------------------------------*/
static char str_prealloc[65536];
/*------------------------------------------------------------------------*/
static int send_term(TERM arg, int mode, int rank)
{
char *str;
int len;
str = (char *)bpx_term_2_string(arg);
len = strlen(str);
switch (mode) {
case 0:
MPI_Send (&len, 1 , MPI_INT , rank, TAG_GOAL_LEN, MPI_COMM_WORLD);
MPI_Send ( str, len, MPI_CHAR, rank, TAG_GOAL_STR, MPI_COMM_WORLD);
break;
case 1:
MPI_Bcast(&len, 1 , MPI_INT , rank, MPI_COMM_WORLD);
MPI_Bcast( str, len, MPI_CHAR, rank, MPI_COMM_WORLD);
break;
}
mp_debug("SEND(%d,%d): %s", mode, rank, str);
return BP_TRUE;
}
static int recv_term(TERM arg, int mode, int rank)
{
char *str;
TERM op1, op2;
int len, res;
switch (mode) {
case 0:
MPI_Recv (&len, 1, MPI_INT, rank, TAG_GOAL_LEN, MPI_COMM_WORLD, NULL);
break;
case 1:
MPI_Bcast(&len, 1, MPI_INT, rank, MPI_COMM_WORLD);
break;
}
if (len < sizeof(str_prealloc))
str = str_prealloc;
else {
str = MALLOC(len + 1);
}
switch (mode) {
case 0:
MPI_Recv (str, len, MPI_CHAR, rank, TAG_GOAL_STR, MPI_COMM_WORLD, NULL);
break;
case 1:
MPI_Bcast(str, len, MPI_CHAR, rank, MPI_COMM_WORLD);
break;
}
*(str + len) = '\0';
mp_debug("RECV(%d,%d): %s", mode, rank, str);
op1 = bpx_build_var();
op2 = bpx_build_var();
res = bp_string_2_term(str,op1,op2);
if (str != str_prealloc) {
free(str);
}
if (res == BP_TRUE) {
return bpx_unify(arg, op1);
}
return res;
}
/*------------------------------------------------------------------------*/
int pc_mp_size_1(void)
{
return bpx_unify(bpx_get_call_arg(1,1), bpx_build_integer(mp_size));
}
int pc_mp_rank_1(void)
{
return bpx_unify(bpx_get_call_arg(1,1), bpx_build_integer(mp_rank));
}
int pc_mp_master_0(void)
{
return (mp_rank == 0) ? BP_TRUE : BP_FALSE;
}
int pc_mp_abort_0(void)
{
mp_quit(0);
}
int pc_mp_wtime_1(void)
{
return bpx_unify(bpx_get_call_arg(1,1), bpx_build_float(MPI_Wtime()));
}
int pc_mp_sync_2(void)
{
int args[2], amin[2], amax[2];
args[0] = bpx_get_integer(bpx_get_call_arg(1,2)); /* tag */
args[1] = bpx_get_integer(bpx_get_call_arg(2,2)); /* sync-id */
mp_debug("SYNC(%d,%d): BGN", args[0], args[1]);
MPI_Allreduce(args, amin, 2, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
MPI_Allreduce(args, amax, 2, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
if (amin[0] != amax[0]) {
emit_internal_error("failure on sync (%d,%d)", args[0], args[1]);
RET_INTERNAL_ERR;
}
if (amin[1] < 0) {
return BP_FALSE;
}
if (amin[1] != amax[1]) {
emit_internal_error("failure on sync (%d,%d)", args[0], args[1]);
RET_INTERNAL_ERR;
}
mp_debug("SYNC(%d,%d): END", args[0], args[1]);
return BP_TRUE;
}
int pc_mp_send_goal_1(void)
{
MPI_Status status;
MPI_Recv(NULL, 0, MPI_INT, MPI_ANY_SOURCE, TAG_GOAL_REQ, MPI_COMM_WORLD, &status);
return send_term(bpx_get_call_arg(1,1), 0, status.MPI_SOURCE);
}
int pc_mp_recv_goal_1(void)
{
MPI_Send(NULL, 0, MPI_INT, 0, TAG_GOAL_REQ, MPI_COMM_WORLD);
return recv_term(bpx_get_call_arg(1,1), 0, 0);
}
int pc_mpm_bcast_command_1(void)
{
return send_term(bpx_get_call_arg(1,1), 1, 0);
}
int pc_mps_bcast_command_1(void)
{
return recv_term(bpx_get_call_arg(1,1), 1, 0);
}
int pc_mps_revert_stdout_0(void)
{
if (fd_dup_stdout >= 0) {
dup2(fd_dup_stdout, STDOUT_FILENO);
close(fd_dup_stdout);
fd_dup_stdout = -1;
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,22 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_PREDS_H
#define MP_PREDS_H
/*-------------------------------------------------------------------------*/
int pc_mp_size_1(void);
int pc_mp_rank_1(void);
int pc_mp_master_0(void);
int pc_mp_abort_0(void);
int pc_mp_wtime_1(void);
int pc_mp_sync_2(void);
int pc_mp_send_goal_1(void);
int pc_mp_recv_goal_1(void);
int pc_mpm_bcast_command_1(void);
int pc_mps_bcast_command_1(void);
int pc_mps_revert_stdout_0(void);
/*-------------------------------------------------------------------------*/
#endif /* MP_PREDS_H */

View File

@ -0,0 +1,206 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifdef MPI
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "core/idtable.h"
#include "core/idtable_preds.h"
#include "up/up.h"
#include "up/em_aux.h"
#include "up/graph.h"
#include "up/flags.h"
#include "mp/mp.h"
#include "mp/mp_core.h"
#include "mp/mp_em_aux.h"
#include <mpi.h>
#include <stdlib.h>
#include <string.h>
/*------------------------------------------------------------------------*/
int *occ_position = NULL;
static int * sizes = NULL;
static int ** swids = NULL;
#define L(i) (sizes[i * 2 + 0]) /* length of the message from RANK #i */
#define N(i) (sizes[i * 2 + 1]) /* number of switches in RANK #i*/
/*------------------------------------------------------------------------*/
/* cpred.c (B-Prolog) */
int bp_string_2_term(const char *, TERM, TERM);
/* mic.c (B-Prolog) */
NORET quit(const char *);
/*------------------------------------------------------------------------*/
static void parse_switch_req(const char *msg, int src)
{
const char *p;
TERM op1, op2;
int i;
swids[src] = MALLOC(sizeof(int) * N(src));
p = msg;
for (i = 0; i < N(src); i++) {
op1 = bpx_build_var();
op2 = bpx_build_var();
bp_string_2_term(p, op1, op2);
swids[src][i] = prism_sw_id_register(op1);
while (*(p++) != '\0') ;
}
}
/*------------------------------------------------------------------------*/
int pc_mp_send_switches_0(void)
{
char *msg, *str;
TERM msw;
int msglen, msgsiz;
int vals[2];
int i, n;
msglen = 0;
msgsiz = 65536;
msg = MALLOC(msgsiz);
for (i = 0; i < occ_switch_tab_size; i++) {
msw = bpx_get_arg(1, prism_sw_ins_term(occ_switches[i]->id));
str = (char *)bpx_term_2_string(msw);
n = strlen(str) + 1;
if (msgsiz <= msglen + n) {
msgsiz = (msglen + n + 65536) & ~65535;
msg = REALLOC(msg, msgsiz);
}
strcpy(msg + msglen, str);
msglen += n;
}
msg[msglen++] = '\0'; /* this is safe */
vals[0] = msglen;
vals[1] = occ_switch_tab_size;
MPI_Gather(vals, 2, MPI_INT, NULL, 0, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Send(msg, msglen, MPI_CHAR, 0, TAG_SWITCH_REQ, MPI_COMM_WORLD);
free(msg);
return BP_TRUE;
}
int pc_mp_recv_switches_0(void)
{
int i, lmax, vals[2];
char *msg;
sizes = MALLOC(sizeof(int) * 2 * mp_size);
swids = MALLOC(sizeof(int *) * mp_size);
MPI_Gather(vals, 2, MPI_INT, sizes, 2, MPI_INT, 0, MPI_COMM_WORLD);
lmax = 0;
for (i = 1; i < mp_size; i++) {
if (lmax < L(i)) {
lmax = L(i);
}
}
msg = MALLOC(lmax);
for (i = 1; i < mp_size; i++) {
MPI_Recv(msg, L(i), MPI_CHAR, i, TAG_SWITCH_REQ, MPI_COMM_WORLD, NULL);
parse_switch_req(msg, i);
}
free(msg);
return BP_TRUE;
}
int pc_mp_send_swlayout_0(void)
{
int i, j, *msg, *pos;
msg = MALLOC(sizeof(int) * sw_tab_size);
pos = MALLOC(sizeof(int) * sw_ins_tab_size);
j = 0;
for (i = 0; i < occ_switch_tab_size; i++) {
pos[occ_switches[i]->id] = j;
j += num_sw_vals[i];
}
sw_msg_size = j;
for (i = 1; i < mp_size; i++) {
for (j = 0; j < N(i); j++) {
msg[j] = pos[switches[swids[i][j]]->id];
}
MPI_Send(msg, N(i), MPI_INT, i, TAG_SWITCH_RES, MPI_COMM_WORLD);
free(swids[i]);
}
free(pos);
free(msg);
free(sizes);
free(swids);
return BP_TRUE;
}
int pc_mp_recv_swlayout_0(void)
{
occ_position = MALLOC(sizeof(int) * occ_switch_tab_size);
MPI_Recv(occ_position, occ_switch_tab_size, MPI_INT, 0, TAG_SWITCH_RES, MPI_COMM_WORLD, NULL);
/* debug */
{
int i;
TERM msw;
for (i = 0; i < occ_switch_tab_size; i++) {
msw = bpx_get_arg(1, prism_sw_ins_term(occ_switches[i]->id));
mp_debug("%s -> %d", bpx_term_2_string(msw), occ_position[i]);
}
}
return BP_TRUE;
}
int pc_mpm_alloc_occ_switches_0(void)
{
occ_switches = MALLOC(sizeof(SW_INS_PTR) * sw_tab_size);
occ_switch_tab_size = sw_tab_size;
memcpy(occ_switches, switches, sizeof(SW_INS_PTR) * sw_tab_size);
if (fix_init_order) {
sort_occ_switches();
}
alloc_num_sw_vals();
return BP_TRUE;
}
void release_occ_position(void)
{
free(occ_position);
occ_position = NULL;
}
/*------------------------------------------------------------------------*/
#endif /* MPI */

View File

@ -0,0 +1,22 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef MP_SW_H
#define MP_SW_H
/*-------------------------------------------------------------------------*/
extern int *occ_position;
/*-------------------------------------------------------------------------*/
int pc_mp_send_switches_0(void);
int pc_mp_recv_switches_0(void);
int pc_mp_send_swlayout_0(void);
int pc_mp_recv_swlayout_0(void);
int pc_mpm_alloc_occ_switches_0(void);
void release_occ_position(void);
/*-------------------------------------------------------------------------*/
#endif /* MP_SW_H */

View File

@ -0,0 +1,106 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
#ifndef __EM_H__
#define __EM_H__
/*------------------------------------------------------------------------*/
#define DEFAULT_MAX_ITERATE (10000)
/*------------------------------------------------------------------------*/
struct EM_Engine {
int smooth; /* [in ] flag: use MAP? */
double lambda; /* [out] log post */
double likelihood; /* [out] log likelihood */
int iterate; /* [out] number of iterations */
double bic; /* [out] BIC score */
double cs; /* [out] CS score */
/* Functions called during computation. */
int (* compute_inside )(void);
int (* examine_inside )(void);
int (* compute_expectation )(void);
double (* compute_likelihood )(void);
double (* compute_log_prior )(void);
int (* update_params )(void);
};
struct VBEM_Engine {
double free_energy; /* [out] free energy */
int iterate; /* [out] number of iterations */
/* Functions called during computation. */
int (* compute_pi )(void);
int (* compute_inside )(void);
int (* examine_inside )(void);
int (* compute_expectation )(void);
double (* compute_free_energy_l0 )(void);
double (* compute_free_energy_l1 )(void);
double (* compute_likelihood )(void);
int (* update_hyperparams )(void);
};
typedef struct EM_Engine * EM_ENG_PTR;
typedef struct VBEM_Engine * VBEM_ENG_PTR;
/*------------------------------------------------------------------------*/
#define SHOW_PROGRESS(n) \
do { \
if(!verb_em && em_message > 0 && (n) % em_progress == 0) { \
if((n) % (em_progress * 10) == 0) \
prism_printf("%d", n); \
else \
prism_printf("."); \
} \
} while (0)
#define SHOW_PROGRESS_HEAD(str, r) \
do { \
if(num_restart > 1) { \
if(verb_em) \
prism_printf("<<<< RESTART #%d >>>>\n", r); \
else if(em_message > 0) \
prism_printf("[%d] ", r); \
} \
if(!verb_em && em_message > 0) \
prism_printf("%s: ", str); \
} while (0)
#define SHOW_PROGRESS_TAIL(converged, n, x) \
do { \
const char *str = \
converged ? "Converged" : "Stopped"; \
\
if(verb_em) \
prism_printf("* %s (%.9f)\n", str, x); \
else if(em_message > 0) \
prism_printf("(%d) (%s: %.9f)\n", n, str, x); \
} while (0)
#define SHOW_PROGRESS_TEMP(x) \
do { \
if(verb_em) \
prism_printf("* Temperature = %.3f\n", x); \
else if(em_message > 0 && show_itemp) \
prism_printf("<%.3f>", x); \
else \
prism_printf("*"); \
} while (0)
#define SHOW_PROGRESS_INTR() \
do { \
if(verb_em) \
prism_printf("* Interrupted\n"); \
else if(em_message > 0) \
prism_printf("(Interrupted)\n"); \
} while (0)
#define REACHED_MAX_ITERATE(n) \
((max_iterate == -1 && (n) >= DEFAULT_MAX_ITERATE) || \
(max_iterate >= +1 && (n) >= max_iterate))
/*------------------------------------------------------------------------*/
#endif /* __EM_H__ */

View File

@ -0,0 +1,151 @@
/* -*- c-basic-offset: 2; tab-width: 8 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
#include "up/graph.h"
#include "up/flags.h"
/*------------------------------------------------------------------------*/
int * num_sw_vals = NULL;
double itemp;
double inside_failure;
int failure_observed;
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
int compare(TERM,TERM);
void quit(const char *);
/*------------------------------------------------------------------------*/
/* for sort_occ_switches() */
static int compare_sw_ins(const void *a, const void *b)
{
SW_INS_PTR sw_ins_a, sw_ins_b;
TERM msw_a, msw_b;
sw_ins_a = *(const SW_INS_PTR *)(a);
sw_ins_b = *(const SW_INS_PTR *)(b);
msw_a = prism_sw_ins_term(sw_ins_a->id);
msw_b = prism_sw_ins_term(sw_ins_b->id);
return compare(bpx_get_arg(1,msw_a), bpx_get_arg(1,msw_b));
}
/*------------------------------------------------------------------------*/
/* Set flags of switches appearing in the e-graphs and allocate an array
* of pointers to such switches (This routine is based on compute_inside()).
*/
void alloc_occ_switches(void)
{
int i,j,k;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
SW_INS_PTR sw_ins_ptr;
int *occ_sw_flags;
int b;
/* Initialize the `occ' counters in switch instances */
for (i = 0; i < sw_ins_tab_size; i++) {
switch_instances[i]->occ = 0;
}
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
path_ptr = eg_ptr->path_ptr;
while (path_ptr != NULL) {
for (k = 0; k < path_ptr->sws_len; k++) {
path_ptr->sws[k]->occ = 1;
}
path_ptr = path_ptr->next;
}
}
/* Temporarily make an array of flags each of which indicates whether
a switch (not switch instance) occurs in the e-graphs */
occ_sw_flags = (int *)MALLOC(sizeof(int) * sw_tab_size);
occ_switch_tab_size = 0;
for (i = 0; i < sw_tab_size; i++) {
sw_ins_ptr = switches[i];
b = 0;
while (sw_ins_ptr != NULL) {
b |= sw_ins_ptr->occ;
sw_ins_ptr = sw_ins_ptr->next;
}
occ_sw_flags[i] = b;
if (b) occ_switch_tab_size++;
}
occ_switches =
(SW_INS_PTR *)MALLOC(sizeof(SW_INS_PTR) * occ_switch_tab_size);
j = 0;
for (i = 0; i < sw_tab_size; i++) {
if (occ_sw_flags[i]) {
occ_switches[j] = switches[i]; /* Copy */
j++;
}
}
free(occ_sw_flags);
}
void sort_occ_switches(void)
{
qsort(occ_switches,occ_switch_tab_size,sizeof(SW_INS_PTR),compare_sw_ins);
}
void release_occ_switches(void)
{
free(occ_switches);
occ_switches = NULL;
}
void alloc_num_sw_vals(void)
{
int i,n;
SW_INS_PTR sw_ins_ptr;
num_sw_vals = (int *)MALLOC(sizeof(int) * occ_switch_tab_size);
for (i = 0; i < occ_switch_tab_size; i++) {
sw_ins_ptr = occ_switches[i];
n = 0;
while (sw_ins_ptr != NULL) {
n++;
sw_ins_ptr = sw_ins_ptr->next;
}
num_sw_vals[i] = n;
}
}
void release_num_sw_vals(void)
{
free(num_sw_vals);
num_sw_vals = NULL;
}
/*------------------------------------------------------------------------*/
void transfer_hyperparams_prolog(void)
{
int i;
SW_INS_PTR sw_ins_ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
sw_ins_ptr = occ_switches[i];
while (sw_ins_ptr != NULL) {
sw_ins_ptr->smooth = sw_ins_ptr->smooth_prolog;
sw_ins_ptr->inside_h = sw_ins_ptr->smooth_prolog + 1.0;
sw_ins_ptr = sw_ins_ptr->next;
}
}
}
/*------------------------------------------------------------------------*/

View File

@ -0,0 +1,16 @@
#ifndef EM_AUX_H
#define EM_AUX_H
extern int * num_sw_vals; /* #-vals of switches that occur in e-graphs */
extern double itemp; /* inversed temperature (for DAEM) */
extern double inside_failure; /* inside prob. of failure */
extern int failure_observed; /* flag: true if failure is observed */
void alloc_occ_switches(void);
void sort_occ_switches(void);
void release_occ_switches(void);
void alloc_num_sw_vals(void);
void release_num_sw_vals(void);
void transfer_hyperparams_prolog(void);
#endif /* EM_AUX_H */

View File

@ -0,0 +1,777 @@
/* -*- c-basic-offset: 2; tab-width: 8 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "core/random.h"
#include "core/gamma.h"
#include "up/up.h"
#include "up/graph.h"
#include "up/flags.h"
#include "up/em_aux.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
/* We check if all smoothing constants are positive (MAP),
* or all smoothing constants are zero. If some are positive,
* but the others are zero, die immediately. We also check
* if there exist parameters fixed at zero in MAP estimation.
*/
int check_smooth(int *smooth)
{
/*
q = +4 : found non-zero smoothing constants
+2 : found zero-valued smoothing constants
+1 : found parameters fixed to zero
*/
int i, q = 0;
SW_INS_PTR sw_ins_ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
sw_ins_ptr = occ_switches[i];
while (sw_ins_ptr != NULL) {
if (sw_ins_ptr->smooth_prolog < 0) {
emit_error("negative delta values in MAP estimation");
RET_ERR(err_invalid_numeric_value);
}
q |= (sw_ins_ptr->smooth_prolog < TINY_PROB) ? 2 : 4;
q |= (sw_ins_ptr->fixed && sw_ins_ptr->inside < TINY_PROB) ? 1 : 0;
sw_ins_ptr = sw_ins_ptr->next;
}
}
switch (q) {
case 0: /* p.counts = (none), w/o 0-valued params */
case 1: /* p.counts = (none), with 0-valued params */
emit_internal_error("unexpected case in check_smooth()");
RET_ERR(ierr_unmatched_branches);
case 2: /* p.counts = 0 only, w/o 0-valued params */
case 3: /* p.counts = 0 only, with 0-valued params */
*smooth = 0;
break;
case 4: /* p.counts = + only, w/o 0-valued params */
*smooth = 1;
break;
case 5: /* p.counts = + only, with 0-valued params */
emit_error("parameters fixed to zero in MAP estimation");
RET_ERR(err_invalid_numeric_value);
case 6: /* p.counts = (both), w/o 0-valued params */
case 7: /* p.counts = (both), with 0-valued params */
emit_error("mixture of zero and non-zero pseudo counts");
RET_ERR(err_invalid_numeric_value);
}
transfer_hyperparams_prolog();
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
static void initialize_params_noisy_uniform(void)
{
int i;
SW_INS_PTR ptr;
double sum,p;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
p = 1.0 / num_sw_vals[i];
sum = 0.0;
while (ptr != NULL) {
ptr->inside = random_gaussian(p, std_ratio * p);
if (ptr->inside < INIT_PROB_THRESHOLD)
ptr->inside = INIT_PROB_THRESHOLD;
sum += ptr->inside;
ptr = ptr->next;
}
ptr = occ_switches[i];
while (ptr != NULL) { /* normalize */
ptr->inside = ptr->inside / sum;
ptr = ptr->next;
}
}
}
static void initialize_params_random(void)
{
int i;
SW_INS_PTR ptr;
double sum,p;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
p = 1.0 / num_sw_vals[i];
sum = 0.0;
while (ptr != NULL) {
sum += (ptr->inside = p + random_float());
ptr = ptr->next;
}
ptr = occ_switches[i];
while (ptr != NULL) { /* normalize */
ptr->inside = ptr->inside / sum;
ptr = ptr->next;
}
}
}
void initialize_params(void)
{
if (init_method == 1)
initialize_params_noisy_uniform();
if (init_method == 2)
initialize_params_random();
}
/*------------------------------------------------------------------------*/
int compute_inside_scaling_none(void)
{
int i,k;
double sum,this_path_inside;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
sum = 0.0;
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL)
sum = 1.0; /* path_ptr should not be NULL; but it happens */
while (path_ptr != NULL) {
this_path_inside = 1.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside *= path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside *= path_ptr->sws[k]->inside;
}
path_ptr->inside = this_path_inside;
sum += this_path_inside;
path_ptr = path_ptr->next;
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
int compute_inside_scaling_log_exp(void)
{
int i,k,u;
double sum, this_path_inside, first_path_inside = 0.0, sum_rest;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL) {
sum = 0.0; /* path_ptr should not be NULL; but it happens */
}
else {
sum_rest = 0.0;
u = 0;
while (path_ptr != NULL) {
this_path_inside = 0.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside += path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside += log(path_ptr->sws[k]->inside);
}
path_ptr->inside = this_path_inside;
if (u == 0) {
first_path_inside = this_path_inside;
sum_rest += 1.0;
}
else if (this_path_inside - first_path_inside >= log(HUGE_PROB)) {
sum_rest *= exp(first_path_inside - this_path_inside);
first_path_inside = this_path_inside;
sum_rest += 1.0; /* maybe sum_rest gets 1.0 */
}
else {
sum_rest += exp(this_path_inside - first_path_inside);
}
path_ptr = path_ptr->next;
u++;
}
sum = first_path_inside + log(sum_rest);
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
int compute_daem_inside_scaling_none(void)
{
int i,k;
double sum,this_path_inside;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
sum = 0.0;
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL)
sum = 1.0; /* path_ptr should not be NULL; but it happens */
while (path_ptr != NULL) {
this_path_inside = 1.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside *= path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside *= pow(path_ptr->sws[k]->inside, itemp);
}
path_ptr->inside = this_path_inside;
sum += this_path_inside;
path_ptr = path_ptr->next;
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
int compute_daem_inside_scaling_log_exp(void)
{
int i,k,u;
double sum, this_path_inside, first_path_inside = 0.0, sum_rest;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL) {
sum = 0.0; /* path_ptr should not be NULL; but it happens */
}
else {
sum_rest = 0.0;
u = 0;
while (path_ptr != NULL) {
this_path_inside = 0.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside += path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside += itemp * log(path_ptr->sws[k]->inside);
}
path_ptr->inside = this_path_inside;
if (u == 0) {
first_path_inside = this_path_inside;
sum_rest += 1.0;
}
else if (this_path_inside - first_path_inside >= log(HUGE_PROB)) {
sum_rest *= exp(first_path_inside - this_path_inside);
first_path_inside = this_path_inside;
sum_rest += 1.0; /* maybe sum_rest gets 1.0 */
}
else {
sum_rest += exp(this_path_inside - first_path_inside);
}
path_ptr = path_ptr->next;
u++;
}
sum = first_path_inside + log(sum_rest);
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
int examine_inside_scaling_none(void)
{
int i;
double inside;
inside_failure = 0.0;
for (i = 0; i < num_roots; i++) {
inside = expl_graph[roots[i]->id]->inside;
if (i == failure_root_index) {
inside_failure = inside;
if (!(1.0 - inside_failure > 0.0)) {
emit_error("Probability of failure being unity");
RET_ERR(err_invalid_numeric_value);
}
}
else {
if (!(inside > 0.0)) {
emit_error("Probability of an observed goal being zero");
RET_ERR(err_invalid_numeric_value);
}
}
}
return BP_TRUE;
}
int examine_inside_scaling_log_exp(void)
{
int i;
double inside;
/* [23 Aug 2007, by yuizumi]
* By the code below, inside_failure can take only a non-zero value
* when `failure' is observed. We can therefore safely use zero as
* an indicator of failure being not observed. Zero is chosen just
* for convenience in implementation of the parallel version.
*/
inside_failure = 0.0;
for (i = 0; i < num_roots; i++) {
inside = expl_graph[roots[i]->id]->inside;
if (i == failure_root_index) {
inside_failure = inside; /* log-scale */
if (!(inside_failure < 0.0)) {
emit_error("Probability of failure being unity");
RET_ERR(err_invalid_numeric_value);
}
}
else {
if (!isfinite(inside)) {
emit_error("Probability of an observed goal being zero");
RET_ERR(err_invalid_numeric_value);
}
}
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
int compute_expectation_scaling_none(void)
{
int i,k;
EG_PATH_PTR path_ptr;
EG_NODE_PTR eg_ptr,node_ptr;
SW_INS_PTR sw_ptr;
double q;
for (i = 0; i < sw_ins_tab_size; i++) {
switch_instances[i]->total_expect = 0.0;
}
for (i = 0; i < sorted_egraph_size; i++) {
sorted_expl_graph[i]->outside = 0.0;
}
for (i = 0; i < num_roots; i++) {
eg_ptr = expl_graph[roots[i]->id];
if (i == failure_root_index) {
eg_ptr->outside = num_goals / (1.0 - inside_failure);
}
else {
eg_ptr->outside = roots[i]->count / eg_ptr->inside;
}
}
for (i = sorted_egraph_size - 1; i >= 0; i--) {
eg_ptr = sorted_expl_graph[i];
path_ptr = eg_ptr->path_ptr;
while (path_ptr != NULL) {
q = eg_ptr->outside * path_ptr->inside;
if (q > 0.0) {
for (k = 0; k < path_ptr->children_len; k++) {
node_ptr = path_ptr->children[k];
node_ptr->outside += q / node_ptr->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
sw_ptr = path_ptr->sws[k];
sw_ptr->total_expect += q;
}
}
path_ptr = path_ptr->next;
}
}
return BP_TRUE;
}
int compute_expectation_scaling_log_exp(void)
{
int i,k;
EG_PATH_PTR path_ptr;
EG_NODE_PTR eg_ptr,node_ptr;
SW_INS_PTR sw_ptr;
double q,r;
for (i = 0; i < sw_ins_tab_size; i++) {
switch_instances[i]->total_expect = 0.0;
switch_instances[i]->has_first_expectation = 0;
switch_instances[i]->first_expectation = 0.0;
}
for (i = 0; i < sorted_egraph_size; i++) {
sorted_expl_graph[i]->outside = 0.0;
sorted_expl_graph[i]->has_first_outside = 0;
sorted_expl_graph[i]->first_outside = 0.0;
}
for (i = 0; i < num_roots; i++) {
eg_ptr = expl_graph[roots[i]->id];
if (i == failure_root_index) {
eg_ptr->first_outside =
log(num_goals / (1.0 - exp(inside_failure)));
}
else {
eg_ptr->first_outside =
log((double)(roots[i]->count)) - eg_ptr->inside;
}
eg_ptr->has_first_outside = 1;
eg_ptr->outside = 1.0;
}
/* sorted_expl_graph[to] must be a root node */
for (i = sorted_egraph_size - 1; i >= 0; i--) {
eg_ptr = sorted_expl_graph[i];
/* First accumulate log-scale outside probabilities: */
if (!eg_ptr->has_first_outside) {
emit_internal_error("unexpected has_first_outside[%s]",
prism_goal_string(eg_ptr->id));
RET_INTERNAL_ERR;
}
else if (!(eg_ptr->outside > 0.0)) {
emit_internal_error("unexpected outside[%s]",
prism_goal_string(eg_ptr->id));
RET_INTERNAL_ERR;
}
else {
eg_ptr->outside = eg_ptr->first_outside + log(eg_ptr->outside);
}
path_ptr = sorted_expl_graph[i]->path_ptr;
while (path_ptr != NULL) {
q = sorted_expl_graph[i]->outside + path_ptr->inside;
for (k = 0; k < path_ptr->children_len; k++) {
node_ptr = path_ptr->children[k];
r = q - node_ptr->inside;
if (!node_ptr->has_first_outside) {
node_ptr->first_outside = r;
node_ptr->outside += 1.0;
node_ptr->has_first_outside = 1;
}
else if (r - node_ptr->first_outside >= log(HUGE_PROB)) {
node_ptr->outside *= exp(node_ptr->first_outside - r);
node_ptr->first_outside = r;
node_ptr->outside += 1.0;
}
else {
node_ptr->outside += exp(r - node_ptr->first_outside);
}
}
for (k = 0; k < path_ptr->sws_len; k++) {
sw_ptr = path_ptr->sws[k];
if (!sw_ptr->has_first_expectation) {
sw_ptr->first_expectation = q;
sw_ptr->total_expect += 1.0;
sw_ptr->has_first_expectation = 1;
}
else if (q - sw_ptr->first_expectation >= log(HUGE_PROB)) {
sw_ptr->total_expect *= exp(sw_ptr->first_expectation - q);
sw_ptr->first_expectation = q;
sw_ptr->total_expect += 1.0;
}
else {
sw_ptr->total_expect += exp(q - sw_ptr->first_expectation);
}
}
path_ptr = path_ptr->next;
}
}
/* unscale total_expect */
for (i = 0; i < sw_ins_tab_size; i++) {
sw_ptr = switch_instances[i];
if (!sw_ptr->has_first_expectation) continue;
if (!(sw_ptr->total_expect > 0.0)) {
emit_error("unexpected expectation for %s",prism_sw_ins_string(i));
RET_ERR(err_invalid_numeric_value);
}
sw_ptr->total_expect =
exp(sw_ptr->first_expectation + log(sw_ptr->total_expect));
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
double compute_likelihood_scaling_none(void)
{
int i;
double likelihood,adjuster,inside;
likelihood = 0.0;
adjuster = failure_observed ? log(1.0-inside_failure) : 0.0;
for (i = 0; i < num_roots; i++) {
if (i == failure_root_index) continue; /* skip failure */
inside = expl_graph[roots[i]->id]->inside; /* always positive */
likelihood += roots[i]->count * (log(inside) - adjuster);
}
return likelihood;
}
double compute_likelihood_scaling_log_exp(void)
{
int i;
double likelihood,adjuster,inside;
likelihood = 0.0;
adjuster = failure_observed ? log(1.0-exp(inside_failure)) : 0.0;
for (i = 0; i < num_roots; i++) {
if (i == failure_root_index) continue; /* skip failure */
inside = expl_graph[roots[i]->id]->inside; /* log-scale */
likelihood += roots[i]->count * (inside - adjuster);
}
return likelihood;
}
/*------------------------------------------------------------------------*/
double compute_log_prior(void)
{
int i;
SW_INS_PTR sw_ins_ptr;
double lp;
lp = 0.0;
for (i = 0; i < occ_switch_tab_size; i++) {
sw_ins_ptr = occ_switches[i];
while (sw_ins_ptr != NULL) {
lp += sw_ins_ptr->smooth * log(sw_ins_ptr->inside);
sw_ins_ptr = sw_ins_ptr->next;
}
}
return lp;
}
double compute_daem_log_prior(void)
{
int i;
SW_INS_PTR sw_ins_ptr;
double lp;
lp = 0.0;
for (i = 0; i < occ_switch_tab_size; i++) {
sw_ins_ptr = occ_switches[i];
while (sw_ins_ptr != NULL) {
lp += sw_ins_ptr->smooth * log(sw_ins_ptr->inside);
sw_ins_ptr = sw_ins_ptr->next;
}
}
return itemp * lp;
}
/*------------------------------------------------------------------------*/
int update_params(void)
{
int i;
SW_INS_PTR ptr,next;
double sum,cur_prob_sum;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
sum = 0.0;
while (ptr != NULL) {
sum += ptr->total_expect;
ptr = ptr->next;
}
if (sum != 0.0) {
cur_prob_sum = 0.0;
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
next = ptr->next;
while (next != NULL) {
if (ptr->fixed == 0) ptr->inside = ptr->total_expect / sum;
if (log_scale && ptr->inside < log(TINY_PROB)) {
emit_error("Parameter being zero (-inf in log scale) -- %s",
prism_sw_ins_string(ptr->id));
RET_ERR(err_underflow);
}
cur_prob_sum += ptr->inside;
ptr = next;
next = ptr->next;
}
ptr->inside = 1.0-cur_prob_sum; /* Normalize */
}
}
return BP_TRUE;
}
int update_params_smooth(void)
{
int i;
SW_INS_PTR ptr,next;
double sum,cur_prob_sum;
double denom;
int n;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
n = num_sw_vals[i];
sum = 0.0;
while (ptr != NULL) {
sum += ptr->total_expect + ptr->smooth;
ptr = ptr->next;
}
denom = sum;
if (sum != 0.0) {
cur_prob_sum = 0.0;
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
next = ptr->next;
while (next != NULL) {
if (ptr->fixed == 0)
ptr->inside = (ptr->total_expect + ptr->smooth) / denom;
cur_prob_sum += ptr->inside;
ptr = next;
next = ptr->next;
}
ptr->inside = 1.0-cur_prob_sum; /* Normalize */
}
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
void save_params(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
while (ptr != NULL) {
ptr->best_inside = ptr->inside;
ptr->best_total_expect = ptr->total_expect;
ptr = ptr->next;
}
}
}
void restore_params(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
while (ptr != NULL) {
ptr->inside = ptr->best_inside;
ptr->total_expect = ptr->best_total_expect;
ptr = ptr->next;
}
}
}
/*------------------------------------------------------------------------*/
double compute_bic(double likelihood)
{
double bic = likelihood;
int i, num_sw_ins, num_params;
num_sw_ins = 0;
for (i = 0; i < occ_switch_tab_size; i++) {
SW_INS_PTR ptr = occ_switches[i];
while (ptr != NULL) {
num_sw_ins++;
ptr = ptr->next;
}
}
/* Get the number of free parameters: */
num_params = num_sw_ins - occ_switch_tab_size;
bic = likelihood - 0.5 * num_params * log(num_goals);
return bic;
}
double compute_cs(double likelihood)
{
double cs;
double l0, l1, l2;
int i;
SW_INS_PTR ptr;
double smooth_sum;
/* Compute BD score using the expectations: */
l0 = 0.0;
for (i = 0; i < occ_switch_tab_size; i++) {
smooth_sum = 0.0;
ptr = occ_switches[i];
while (ptr != NULL) {
smooth_sum += (ptr->smooth + 1.0);
ptr = ptr->next;
}
l0 += lngamma(smooth_sum);
smooth_sum = 0.0;
ptr = occ_switches[i];
while (ptr != NULL) {
smooth_sum += (ptr->total_expect + ptr->smooth + 1.0);
ptr = ptr->next;
}
l0 -= lngamma(smooth_sum);
ptr = occ_switches[i];
while (ptr != NULL) {
l0 += lngamma(ptr->total_expect + ptr->smooth + 1.0);
l0 -= lngamma(ptr->smooth + 1.0);
ptr = ptr->next;
}
}
/* Compute the likelihood of complete data using the expectations: */
l1 = 0.0;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
while (ptr != NULL) {
l1 += ptr->total_expect * log(ptr->inside);
ptr = ptr->next;
}
}
/* Get the log-likelihood: */
l2 = likelihood;
cs = l0 - l1 + l2;
return cs;
}
/*------------------------------------------------------------------------*/

View File

@ -0,0 +1,26 @@
#ifndef EM_AUX_ML_H
#define EM_AUX_ML_H
int check_smooth(int *);
void initialize_params(void);
int compute_inside_scaling_none(void);
int compute_inside_scaling_log_exp(void);
int compute_daem_inside_scaling_none(void);
int compute_daem_inside_scaling_log_exp(void);
int examine_inside_scaling_none(void);
int examine_inside_scaling_log_exp(void);
int compute_expectation_scaling_none(void);
int compute_expectation_scaling_log_exp(void);
double compute_likelihood_scaling_none(void);
double compute_likelihood_scaling_log_exp(void);
double compute_log_prior(void);
double compute_daem_log_prior(void);
int update_params(void);
int update_params_smooth(void);
void save_params(void);
void restore_params(void);
double compute_bic(double);
double compute_cs(double);
#endif /* EM_AUX_ML_H */

View File

@ -0,0 +1,569 @@
/* -*- c-basic-offset: 2; tab-width: 8 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "core/random.h"
#include "core/gamma.h"
#include "up/up.h"
#include "up/graph.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/flags.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
/* Just check if there is any negative hyperparameter */
int check_smooth_vb(void)
{
int i;
SW_INS_PTR sw_ins_ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
sw_ins_ptr = occ_switches[i];
while (sw_ins_ptr != NULL) {
if (sw_ins_ptr->smooth_prolog <= -1.0) {
emit_internal_error("illegal hyperparameters");
RET_INTERNAL_ERR;
}
sw_ins_ptr = sw_ins_ptr->next;
}
}
transfer_hyperparams_prolog();
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
void initialize_hyperparams(void)
{
int i;
SW_INS_PTR ptr;
double p,r;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
while (ptr != NULL) {
ptr->smooth = ptr->smooth_prolog;
ptr = ptr->next;
}
}
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed_h > 0) {
while (ptr != NULL) {
ptr->inside_h = ptr->smooth + 1.0;
ptr->total_expect = 0.0;
ptr = ptr->next;
}
}
else {
p = 1.0 / num_sw_vals[i];
while (ptr != NULL) {
r = random_gaussian(0.0, std_ratio * p);
ptr->inside_h =
(ptr->smooth + 1.0 < EPS) ? EPS : ptr->smooth + 1.0;
ptr->inside_h *= (1.0 + fabs(r));
ptr->smooth = ptr->inside_h - 1.0;
ptr->total_expect = 0.0;
ptr = ptr->next;
}
}
}
}
/*------------------------------------------------------------------------*/
int compute_pi_scaling_none(void)
{
int i;
SW_INS_PTR ptr;
double alpha_sum, psi0;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
alpha_sum = 0.0;
while (ptr != NULL) {
alpha_sum += ptr->inside_h;
ptr = ptr->next;
}
psi0 = digamma(alpha_sum);
ptr = occ_switches[i];
while (ptr != NULL) {
ptr->pi = exp(digamma(ptr->inside_h) - psi0);
ptr = ptr->next;
}
}
return BP_TRUE;
}
int compute_pi_scaling_log_exp(void)
{
int i;
SW_INS_PTR ptr;
double alpha_sum, psi0;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
alpha_sum = 0.0;
while (ptr != NULL) {
alpha_sum += ptr->inside_h;
ptr = ptr->next;
}
psi0 = digamma(alpha_sum);
ptr = occ_switches[i];
while (ptr != NULL) {
ptr->pi = digamma(ptr->inside_h) - psi0;
ptr = ptr->next;
}
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
int compute_inside_vb_scaling_none(void)
{
int i,k;
double sum,this_path_inside;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
sum = 0.0;
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL) sum = 1.0;
while (path_ptr != NULL) {
this_path_inside = 1.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside *= path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside *= path_ptr->sws[k]->pi;
}
path_ptr->inside = this_path_inside;
sum += this_path_inside;
path_ptr = path_ptr->next;
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
int compute_inside_vb_scaling_log_exp(void)
{
int i,k,u;
double sum, this_path_inside, first_path_inside = 0.0, sum_rest;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
sum = 0.0;
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL) {
sum = 0.0;
}
else {
sum_rest = 0.0;
u = 0;
while (path_ptr != NULL) {
this_path_inside = 0.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside += path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside += path_ptr->sws[k]->pi; /* log-scale */
}
path_ptr->inside = this_path_inside;
if (u == 0) {
first_path_inside = this_path_inside;
sum_rest += 1.0;
}
else if (this_path_inside - first_path_inside >= log(HUGE_PROB)) {
sum_rest *= exp(first_path_inside - this_path_inside);
first_path_inside = this_path_inside;
sum_rest += 1.0;
}
else {
sum_rest += exp(this_path_inside - first_path_inside);
}
path_ptr = path_ptr->next;
u++;
}
sum = first_path_inside + log(sum_rest);
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
int compute_daem_inside_vb_scaling_none(void)
{
int i,k;
double sum,this_path_inside;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
sum = 0.0;
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL) sum = 1.0;
while (path_ptr != NULL) {
this_path_inside = 1.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside *= path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside *= pow(path_ptr->sws[k]->pi,itemp);
}
path_ptr->inside = this_path_inside;
sum += this_path_inside;
path_ptr = path_ptr->next;
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
int compute_daem_inside_vb_scaling_log_exp(void)
{
int i,k,u;
double sum, this_path_inside, first_path_inside = 0.0, sum_rest;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
sum = 0.0;
path_ptr = eg_ptr->path_ptr;
if (path_ptr == NULL) {
sum = 0.0;
}
else {
sum_rest = 0.0;
u = 0;
while (path_ptr != NULL) {
this_path_inside = 0.0;
for (k = 0; k < path_ptr->children_len; k++) {
this_path_inside += path_ptr->children[k]->inside;
}
for (k = 0; k < path_ptr->sws_len; k++) {
this_path_inside += itemp * path_ptr->sws[k]->pi;
}
path_ptr->inside = this_path_inside;
if (u == 0) {
first_path_inside = this_path_inside;
sum_rest += 1.0;
}
else if (this_path_inside - first_path_inside >= log(HUGE_PROB)) {
sum_rest *= exp(first_path_inside - this_path_inside);
first_path_inside = this_path_inside;
sum_rest += 1.0;
}
else {
sum_rest += exp(this_path_inside - first_path_inside);
}
path_ptr = path_ptr->next;
u++;
}
sum = first_path_inside + log(sum_rest);
}
eg_ptr->inside = sum;
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
/* [27 Aug 2007, by yuizumi]
* A variational free energy F is given by:
* F = F0 - F1 + L'
* where:
* F0 = compute_[daem_]free_energy_l0()
* F1 = compute_[daem_]free_energy_l1_scaling_{none|log_exp}()
* L' = compute_likelihood() / itemp
*/
double compute_free_energy_l0(void)
{
double l0 = 0.0;
double smooth_sum;
SW_INS_PTR ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
smooth_sum = 0.0;
ptr = occ_switches[i];
while (ptr != NULL) {
smooth_sum += (ptr->smooth + 1.0);
ptr = ptr->next;
}
l0 += lngamma(smooth_sum);
smooth_sum = 0.0;
ptr = occ_switches[i];
while (ptr != NULL) {
smooth_sum += (ptr->inside_h);
ptr = ptr->next;
}
l0 -= lngamma(smooth_sum);
ptr = occ_switches[i];
while (ptr != NULL) {
l0 += lngamma(ptr->inside_h);
l0 -= lngamma(ptr->smooth + 1.0);
ptr = ptr->next;
}
}
return l0;
}
double compute_daem_free_energy_l0(void)
{
double l0 = 0.0;
double smooth_sum;
SW_INS_PTR ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
smooth_sum = 0.0;
ptr = occ_switches[i];
while (ptr != NULL) {
smooth_sum += (ptr->smooth + 1.0);
ptr = ptr->next;
}
l0 += lngamma(smooth_sum);
smooth_sum = 0.0;
ptr = occ_switches[i];
while (ptr != NULL) {
smooth_sum += (ptr->inside_h);
ptr = ptr->next;
}
l0 -= lngamma(smooth_sum) / itemp;
ptr = occ_switches[i];
while (ptr != NULL) {
l0 += lngamma(ptr->inside_h) / itemp;
l0 -= lngamma(ptr->smooth + 1.0);
ptr = ptr->next;
}
}
return l0;
}
double compute_free_energy_l1_scaling_none(void)
{
double l1 = 0.0;
SW_INS_PTR ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
while (ptr != NULL) {
l1 += ((ptr->inside_h - 1.0) - ptr->smooth) * log(ptr->pi);
ptr = ptr->next;
}
}
return l1;
}
double compute_free_energy_l1_scaling_log_exp(void)
{
double l1 = 0.0;
SW_INS_PTR ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
while (ptr != NULL) {
/* pi is in log-scale */
l1 += (ptr->inside_h - (ptr->smooth + 1.0)) * ptr->pi;
ptr = ptr->next;
}
}
return l1;
}
double compute_daem_free_energy_l1_scaling_none(void)
{
double l1 = 0.0;
SW_INS_PTR ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
while (ptr != NULL) {
l1 += ((ptr->inside_h - 1.0) / itemp - ptr->smooth) * log(ptr->pi);
ptr = ptr->next;
}
}
return l1;
}
double compute_daem_free_energy_l1_scaling_log_exp(void)
{
double l1 = 0.0;
SW_INS_PTR ptr;
int i;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
while (ptr != NULL) {
/* pi is in log-scale */
l1 += ((ptr->inside_h - 1.0) / itemp - ptr->smooth) * ptr->pi;
ptr = ptr->next;
}
}
return l1;
}
/*------------------------------------------------------------------------*/
int update_hyperparams(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed_h > 0) continue;
while (ptr != NULL) {
ptr->inside_h = ptr->total_expect + ptr->smooth + 1.0;
ptr = ptr->next;
}
}
return BP_TRUE;
}
int update_daem_hyperparams(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed_h > 0) continue;
while (ptr != NULL) {
ptr->inside_h = itemp * (ptr->total_expect + ptr->smooth) + 1.0;
ptr = ptr->next;
}
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
void save_hyperparams(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed_h > 0) continue;
while (ptr != NULL) {
ptr->best_inside_h = ptr->inside_h;
ptr = ptr->next;
}
}
}
void restore_hyperparams(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed_h > 0) continue;
while (ptr != NULL) {
ptr->inside_h = ptr->best_inside_h;
ptr = ptr->next;
}
}
}
void transfer_hyperparams(void)
{
int i;
SW_INS_PTR ptr;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed_h > 0) continue;
while (ptr != NULL) {
ptr->smooth = ptr->inside_h - 1.0;
ptr = ptr->next;
}
}
}
/*------------------------------------------------------------------------*/
void get_param_means(void)
{
int i;
SW_INS_PTR ptr;
double sum;
for (i = 0; i < occ_switch_tab_size; i++) {
ptr = occ_switches[i];
if (ptr->fixed > 0) continue;
sum = 0.0;
while (ptr != NULL) {
sum += ptr->inside_h;
ptr = ptr->next;
}
ptr = occ_switches[i];
while (ptr != NULL) {
ptr->inside = ptr->inside_h / sum;
ptr = ptr->next;
}
}
}
/*------------------------------------------------------------------------*/

View File

@ -0,0 +1,25 @@
#ifndef EM_AUX_VB_H
#define EM_AUX_VB_H
int check_smooth_vb(void);
void initialize_hyperparams(void);
int compute_pi_scaling_none(void);
int compute_pi_scaling_log_exp(void);
int compute_inside_vb_scaling_none(void);
int compute_inside_vb_scaling_log_exp(void);
int compute_daem_inside_vb_scaling_none(void);
int compute_daem_inside_vb_scaling_log_exp(void);
double compute_free_energy_l0(void);
double compute_daem_free_energy_l0(void);
double compute_free_energy_l1_scaling_none(void);
double compute_free_energy_l1_scaling_log_exp(void);
double compute_daem_free_energy_l1_scaling_none(void);
double compute_daem_free_energy_l1_scaling_log_exp(void);
int update_hyperparams(void);
int update_daem_hyperparams(void);
void save_hyperparams(void);
void restore_hyperparams(void);
void transfer_hyperparams(void);
void get_param_means(void);
#endif /* EM_AUX_VB_H */

View File

@ -0,0 +1,162 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
#include "up/graph_aux.h"
#include "up/em.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/flags.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
void config_em(EM_ENG_PTR em_ptr)
{
if (log_scale) {
em_ptr->compute_inside = daem ? compute_daem_inside_scaling_log_exp : compute_inside_scaling_log_exp;
em_ptr->examine_inside = examine_inside_scaling_log_exp;
em_ptr->compute_expectation = compute_expectation_scaling_log_exp;
em_ptr->compute_likelihood = compute_likelihood_scaling_log_exp;
em_ptr->compute_log_prior = daem ? compute_daem_log_prior : compute_log_prior;
em_ptr->update_params = em_ptr->smooth ? update_params_smooth : update_params;
}
else {
em_ptr->compute_inside = daem ? compute_daem_inside_scaling_none : compute_inside_scaling_none;
em_ptr->examine_inside = examine_inside_scaling_none;
em_ptr->compute_expectation = compute_expectation_scaling_none;
em_ptr->compute_likelihood = compute_likelihood_scaling_none;
em_ptr->compute_log_prior = daem ? compute_daem_log_prior : compute_log_prior;
em_ptr->update_params = em_ptr->smooth ? update_params_smooth : update_params;
}
}
/*------------------------------------------------------------------------*/
int run_em(EM_ENG_PTR em_ptr)
{
int r, iterate, old_valid, converged, saved = 0;
double likelihood, log_prior;
double lambda, old_lambda = 0.0;
config_em(em_ptr);
for (r = 0; r < num_restart; r++) {
SHOW_PROGRESS_HEAD("#em-iters", r);
initialize_params();
itemp = daem ? itemp_init : 1.0;
iterate = 0;
/* [21 Aug 2007, by yuizumi]
* while-loop for inversed temperature (DAEM). Note that this
* loop is evaluated only once for EM without annealing, since
* itemp initially set to 1.0 by the code above.
*/
while (1) {
if (daem) {
SHOW_PROGRESS_TEMP(itemp);
}
old_valid = 0;
while (1) {
if (CTRLC_PRESSED) {
SHOW_PROGRESS_INTR();
RET_ERR(err_ctrl_c_pressed);
}
RET_ON_ERR(em_ptr->compute_inside());
RET_ON_ERR(em_ptr->examine_inside());
likelihood = em_ptr->compute_likelihood();
log_prior = em_ptr->smooth ? em_ptr->compute_log_prior() : 0.0;
lambda = likelihood + log_prior;
if (verb_em) {
if (em_ptr->smooth) {
prism_printf("Iteration #%d:\tlog_likelihood=%.9f\tlog_prior=%.9f\tlog_post=%.9f\n", iterate, likelihood, log_prior, lambda);
}
else {
prism_printf("Iteration #%d:\tlog_likelihood=%.9f\n", iterate, likelihood);
}
}
if (debug_level) {
prism_printf("After I-step[%d]:\n", iterate);
prism_printf("likelihood = %.9f\n", likelihood);
print_egraph(debug_level, PRINT_EM);
}
if (!isfinite(lambda)) {
emit_internal_error("invalid log likelihood or log post: %s (at iteration #%d)",
isnan(lambda) ? "NaN" : "infinity", iterate);
RET_ERR(ierr_invalid_likelihood);
}
if (old_valid && old_lambda - lambda > prism_epsilon) {
emit_error("log likelihood or log post decreased [old: %.9f, new: %.9f] (at iteration #%d)",
old_lambda, lambda, iterate);
RET_ERR(err_invalid_likelihood);
}
if (itemp == 1.0 && likelihood > 0.0) {
emit_error("log likelihood greater than zero [value: %.9f] (at iteration #%d)",
likelihood, iterate);
RET_ERR(err_invalid_likelihood);
}
converged = (old_valid && lambda - old_lambda <= prism_epsilon);
if (converged || REACHED_MAX_ITERATE(iterate)) {
break;
}
old_lambda = lambda;
old_valid = 1;
RET_ON_ERR(em_ptr->compute_expectation());
if (debug_level) {
prism_printf("After O-step[%d]:\n", iterate);
print_egraph(debug_level, PRINT_EM);
}
SHOW_PROGRESS(iterate);
RET_ON_ERR(em_ptr->update_params());
iterate++;
}
/* [21 Aug 2007, by yuizumi]
* Note that 1.0 can be represented exactly in IEEE 754.
*/
if (itemp == 1.0) {
break;
}
itemp *= itemp_rate;
if (itemp >= 1.0) {
itemp = 1.0;
}
}
SHOW_PROGRESS_TAIL(converged, iterate, lambda);
if (r == 0 || lambda > em_ptr->lambda) {
em_ptr->lambda = lambda;
em_ptr->likelihood = likelihood;
em_ptr->iterate = iterate;
saved = (r < num_restart - 1);
if (saved) {
save_params();
}
}
}
if (saved) {
restore_params();
}
em_ptr->bic = compute_bic(em_ptr->likelihood);
em_ptr->cs = em_ptr->smooth ? compute_cs(em_ptr->likelihood) : 0.0;
return BP_TRUE;
}

View File

@ -0,0 +1,8 @@
#ifndef EM_ML_H
#define EM_ML_H
void config_em(EM_ENG_PTR);
int run_em(EM_ENG_PTR);
#endif /* EM_ML_H */

View File

@ -0,0 +1,181 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
#include "up/graph.h"
#include "up/graph_aux.h"
#include "up/em.h"
#include "up/em_ml.h"
#include "up/em_vb.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/em_aux_vb.h"
#include "up/viterbi.h"
#include "up/hindsight.h"
#include "up/flags.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
NORET myquit(int, const char *);
/*------------------------------------------------------------------------*/
int pc_prism_prepare_4(void)
{
TERM p_fact_list;
int size;
p_fact_list = bpx_get_call_arg(1,4);
size = bpx_get_integer(bpx_get_call_arg(2,4));
num_goals = bpx_get_integer(bpx_get_call_arg(3,4));
failure_root_index = bpx_get_integer(bpx_get_call_arg(4,4));
failure_observed = (failure_root_index != -1);
if (failure_root_index != -1) {
failure_subgoal_id = prism_goal_id_get(failure_atom);
if (failure_subgoal_id == -1) {
emit_internal_error("no subgoal ID allocated to `failure'");
RET_INTERNAL_ERR;
}
}
initialize_egraph_index();
alloc_sorted_egraph(size);
RET_ON_ERR(sort_egraphs(p_fact_list));
#ifndef MPI
if (verb_graph) {
print_egraph(0, PRINT_NEUTRAL);
}
#endif /* !(MPI) */
alloc_occ_switches();
if (fix_init_order) {
sort_occ_switches();
}
alloc_num_sw_vals();
return BP_TRUE;
}
int pc_prism_em_6(void)
{
struct EM_Engine em_eng;
RET_ON_ERR(check_smooth(&em_eng.smooth));
RET_ON_ERR(run_em(&em_eng));
release_num_sw_vals();
return
bpx_unify(bpx_get_call_arg(1,6), bpx_build_integer(em_eng.iterate )) &&
bpx_unify(bpx_get_call_arg(2,6), bpx_build_float (em_eng.lambda )) &&
bpx_unify(bpx_get_call_arg(3,6), bpx_build_float (em_eng.likelihood)) &&
bpx_unify(bpx_get_call_arg(4,6), bpx_build_float (em_eng.bic )) &&
bpx_unify(bpx_get_call_arg(5,6), bpx_build_float (em_eng.cs )) &&
bpx_unify(bpx_get_call_arg(6,6), bpx_build_integer(em_eng.smooth )) ;
}
int pc_prism_vbem_2(void)
{
struct VBEM_Engine vb_eng;
RET_ON_ERR(check_smooth_vb());
RET_ON_ERR(run_vbem(&vb_eng));
release_num_sw_vals();
return
bpx_unify(bpx_get_call_arg(1,2), bpx_build_integer(vb_eng.iterate)) &&
bpx_unify(bpx_get_call_arg(2,2), bpx_build_float(vb_eng.free_energy));
}
int pc_prism_both_em_2(void)
{
struct VBEM_Engine vb_eng;
RET_ON_ERR(check_smooth_vb());
RET_ON_ERR(run_vbem(&vb_eng));
get_param_means();
release_num_sw_vals();
return
bpx_unify(bpx_get_call_arg(1,2), bpx_build_integer(vb_eng.iterate)) &&
bpx_unify(bpx_get_call_arg(2,2), bpx_build_float(vb_eng.free_energy));
}
int pc_compute_inside_2(void)
{
int gid;
double prob;
EG_NODE_PTR eg_ptr;
gid = bpx_get_integer(bpx_get_call_arg(1,2));
initialize_egraph_index();
alloc_sorted_egraph(1);
RET_ON_ERR(sort_one_egraph(gid, 0, 1));
if (verb_graph) {
print_egraph(0, PRINT_NEUTRAL);
}
eg_ptr = expl_graph[gid];
if (log_scale) {
RET_ON_ERR(compute_inside_scaling_log_exp());
prob = eg_ptr->inside;
}
else {
RET_ON_ERR(compute_inside_scaling_none());
prob = eg_ptr->inside;
}
return bpx_unify(bpx_get_call_arg(2,2), bpx_build_float(prob));
}
/*------------------------------------------------------------------------*/
int pc_compute_probf_1(void)
{
EG_NODE_PTR eg_ptr;
int prmode;
prmode = bpx_get_integer(bpx_get_call_arg(1,1));
if (prmode == 3) {
compute_max();
return BP_TRUE;
}
eg_ptr = expl_graph[roots[0]->id];
failure_root_index = -1;
/* [31 Mar 2008, by yuizumi]
* compute_outside_scaling_*() is needed to be called because
* eg_ptr->outside computed by compute_expectation_scaling_*()
* is different from the outside probability.
*/
if (log_scale) {
RET_ON_ERR(compute_inside_scaling_log_exp());
if (prmode != 1) {
RET_ON_ERR(compute_expectation_scaling_log_exp());
RET_ON_ERR(compute_outside_scaling_log_exp());
}
}
else {
RET_ON_ERR(compute_inside_scaling_none());
if (prmode != 1) {
RET_ON_ERR(compute_expectation_scaling_none());
RET_ON_ERR(compute_outside_scaling_none());
}
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/

View File

@ -0,0 +1,11 @@
#ifndef EM_PREDS_H
#define EM_PREDS_H
int pc_prism_prepare_4(void);
int pc_prism_em_6(void);
int pc_prism_vbem_2(void);
int pc_prism_both_em_7(void);
int pc_compute_inside_2(void);
int pc_compute_probf_1(void);
#endif /* EM_PREDS_H */

View File

@ -0,0 +1,170 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "core/random.h"
#include "up/up.h"
#include "up/graph_aux.h"
#include "up/em.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/em_aux_vb.h"
#include "up/flags.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
void config_vbem(VBEM_ENG_PTR vb_ptr)
{
if (log_scale) {
vb_ptr->compute_pi = compute_pi_scaling_log_exp;
vb_ptr->compute_inside = daem ? compute_daem_inside_vb_scaling_log_exp : compute_inside_vb_scaling_log_exp;
vb_ptr->examine_inside = examine_inside_scaling_log_exp;
vb_ptr->compute_expectation = compute_expectation_scaling_log_exp;
vb_ptr->compute_free_energy_l0 = daem ? compute_daem_free_energy_l0 : compute_free_energy_l0;
vb_ptr->compute_free_energy_l1 = daem ? compute_daem_free_energy_l1_scaling_log_exp : compute_free_energy_l1_scaling_log_exp;
vb_ptr->compute_likelihood = compute_likelihood_scaling_log_exp;
vb_ptr->update_hyperparams = daem ? update_daem_hyperparams : update_hyperparams;
}
else {
vb_ptr->compute_pi = compute_pi_scaling_none;
vb_ptr->compute_inside = daem ? compute_daem_inside_vb_scaling_none : compute_inside_vb_scaling_none;
vb_ptr->examine_inside = examine_inside_scaling_none;
vb_ptr->compute_expectation = compute_expectation_scaling_none;
vb_ptr->compute_free_energy_l0 = daem ? compute_daem_free_energy_l0 : compute_free_energy_l0;
vb_ptr->compute_free_energy_l1 = daem ? compute_daem_free_energy_l1_scaling_none : compute_free_energy_l1_scaling_none;
vb_ptr->compute_likelihood = compute_likelihood_scaling_none;
vb_ptr->update_hyperparams = daem ? update_daem_hyperparams : update_hyperparams;
}
}
/*------------------------------------------------------------------------*/
int run_vbem(VBEM_ENG_PTR vb_ptr)
{
int r, iterate, old_valid, converged, saved = 0;
double free_energy, old_free_energy = 0.0;
double l0, l1, l2;
config_vbem(vb_ptr);
for (r = 0; r < num_restart; r++) {
SHOW_PROGRESS_HEAD("#vbem-iters", r);
initialize_hyperparams();
itemp = daem ? itemp_init : 1.0;
iterate = 0;
/* [21 Aug 2007, by yuizumi]
* while-loop for inversed temperature (DAEM). Note that this
* loop is evaluated only once for EM without annealing, since
* itemp initially set to 1.0 by the code above.
*/
while (1) {
if (daem) {
SHOW_PROGRESS_TEMP(itemp);
}
old_valid = 0;
while (1) {
if (CTRLC_PRESSED) {
SHOW_PROGRESS_INTR();
RET_ERR(err_ctrl_c_pressed);
}
RET_ON_ERR(vb_ptr->compute_pi());
RET_ON_ERR(vb_ptr->compute_inside());
RET_ON_ERR(vb_ptr->examine_inside());
/* compute free_energy */
l0 = vb_ptr->compute_free_energy_l0();
l1 = vb_ptr->compute_free_energy_l1();
l2 = vb_ptr->compute_likelihood() / itemp; /* itemp == 1.0 for non-DAEM */
free_energy = l0 - l1 + l2;
if (verb_em) {
prism_printf("Iteration #%d:\tfree_energy=%.9f\n", iterate, free_energy);
}
if (debug_level) {
prism_printf("After I-step[%d]:\n", iterate);
prism_printf("free_energy = %.9f\n", free_energy);
print_egraph(debug_level, PRINT_VBEM);
}
if (!isfinite(free_energy)) {
emit_internal_error("invalid variational free energy: %s (at iteration #%d)",
isnan(free_energy) ? "NaN" : "infinity", iterate);
RET_ERR(err_invalid_free_energy);
}
if (old_valid && old_free_energy - free_energy > prism_epsilon) {
emit_error("variational free energy decreased [old: %.9f, new: %.9f] (at iteration #%d)",
old_free_energy, free_energy, iterate);
RET_ERR(err_invalid_free_energy);
}
if (itemp == 1.0 && free_energy > 0.0) {
emit_error("variational free energy exceeds zero [value: %.9f] (at iteration #%d)",
free_energy, iterate);
RET_ERR(err_invalid_free_energy);
}
converged = (old_valid && free_energy - old_free_energy <= prism_epsilon);
if (converged || REACHED_MAX_ITERATE(iterate)) {
break;
}
old_free_energy = free_energy;
old_valid = 1;
RET_ON_ERR(vb_ptr->compute_expectation());
if (debug_level) {
prism_printf("After O-step[%d]:\n", iterate);
print_egraph(debug_level, PRINT_VBEM);
}
SHOW_PROGRESS(iterate);
RET_ON_ERR(vb_ptr->update_hyperparams());
if (debug_level) {
prism_printf("After update[%d]:\n", iterate);
print_egraph(debug_level, PRINT_VBEM);
}
iterate++;
}
/* [21 Aug 2007, by yuizumi]
* Note that 1.0 can be represented exactly in IEEE 754.
*/
if (itemp == 1.0) {
break;
}
itemp *= itemp_rate;
if (itemp >= 1.0) {
itemp = 1.0;
}
}
SHOW_PROGRESS_TAIL(converged, iterate, free_energy);
if (r == 0 || free_energy > vb_ptr->free_energy) {
vb_ptr->free_energy = free_energy;
vb_ptr->iterate = iterate;
saved = (r < num_restart - 1);
if (saved) {
save_hyperparams();
}
}
}
if (saved) {
restore_hyperparams();
}
transfer_hyperparams();
return BP_TRUE;
}

View File

@ -0,0 +1,8 @@
#ifndef EM_VB_H
#define EM_VB_H
void config_vbem(VBEM_ENG_PTR);
int run_vbem(VBEM_ENG_PTR);
#endif /* EM_VB_H */

View File

@ -0,0 +1,158 @@
/* -*- c-basic-offset: 4 ; tab-width: 4 -*- */
/*------------------------------------------------------------------------*/
#include "bprolog.h"
#include "up/up.h"
/*------------------------------------------------------------------------*/
/*
* Since these variables are initialized on start-up by the predicate
* reset_prism_flags/0, the initial values below are not actually used.
* The values are just for reference.
*
* Also, don't forget to modify mp_flags.c when adding new flags.
*/
int daem = 0;
int em_message = 1;
int em_progress = 10;
int error_on_cycle = 1;
int explicit_empty_expls = 1;
int fix_init_order = 1;
int init_method = 1;
double itemp_init = 0.1;
double itemp_rate = 1.2;
int log_scale = 0;
int max_iterate = -1; /* == DEFAULT_MAX_ITERATE */
int num_restart = 1;
double prism_epsilon = 0.0001;
int show_itemp = 0;
double std_ratio = 0.1;
int verb_em = 0;
int verb_graph = 0;
static int warn = 0;
/*
* This variable does not correspond to any prism flags, and hence is
* not initialized by reset_prism_flags/0.
*/
int debug_level = 0;
/*------------------------------------------------------------------------*/
int pc_set_daem_1(void)
{
daem = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_em_message_1(void)
{
em_message = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_em_progress_1(void)
{
em_progress = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_error_on_cycle_1(void)
{
error_on_cycle = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_explicit_empty_expls_1(void)
{
explicit_empty_expls = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_fix_init_order_1(void)
{
fix_init_order = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_init_method_1(void)
{
init_method = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_itemp_init_1(void)
{
itemp_init = bpx_get_float(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_itemp_rate_1(void)
{
itemp_rate = bpx_get_float(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_log_scale_1(void)
{
log_scale = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_max_iterate_1(void)
{
max_iterate = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_num_restart_1(void)
{
num_restart = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_prism_epsilon_1(void)
{
prism_epsilon = bpx_get_float(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_show_itemp_1(void)
{
show_itemp = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_std_ratio_1(void)
{
std_ratio = bpx_get_float(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_verb_em_1(void)
{
verb_em = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_verb_graph_1(void)
{
verb_graph = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_warn_1(void)
{
warn = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
int pc_set_debug_level_1(void)
{
debug_level = bpx_get_integer(bpx_get_call_arg(1,1));
return BP_TRUE;
}
/*------------------------------------------------------------------------*/

View File

@ -0,0 +1,48 @@
#ifndef FLAGS_H
#define FLAGS_H
/*========================================================================*/
int pc_set_daem_1(void);
int pc_set_em_message_1(void);
int pc_set_em_progress_1(void);
int pc_set_error_on_cycle_1(void);
int pc_set_explicit_empty_expls_1(void);
int pc_set_fix_init_order_1(void);
int pc_set_init_method_1(void);
int pc_set_itemp_init_1(void);
int pc_set_itemp_rate_1(void);
int pc_set_log_scale_1(void);
int pc_set_max_iterate_1(void);
int pc_set_num_restart_1(void);
int pc_set_prism_epsilon_1(void);
int pc_set_show_itemp_1(void);
int pc_set_std_ratio_1(void);
int pc_set_verb_em_1(void);
int pc_set_verb_graph_1(void);
int pc_set_warn_1(void);
int pc_set_debug_level_1(void);
/*========================================================================*/
extern int daem;
extern int em_message;
extern int em_progress;
extern int error_on_cycle;
extern int explicit_empty_expls;
extern int fix_init_order;
extern int init_method;
extern double itemp_init;
extern double itemp_rate;
extern int log_scale;
extern int max_iterate;
extern int num_restart;
extern double prism_epsilon;
extern int show_itemp;
extern double std_ratio;
extern int verb_em;
extern int verb_graph;
extern int warn;
extern int debug_level;
#endif /* FLAGS_H */

View File

@ -0,0 +1,888 @@
#include "up/up.h"
#include "up/flags.h"
#include "up/graph.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
NORET quit(const char *);
NORET myquit(int, const char *);
/* univ.c (B-Prolog) */
int list_length(BPLONG, BPLONG);
/*------------------------------------------------------------------------*/
static int max_egraph_size = INIT_MAX_EGRAPH_SIZE;
static int max_sorted_egraph_size = INIT_MAX_EGRAPH_SIZE;
static int egraph_size = 0;
static int max_sw_tab_size = INIT_MAX_SW_TABLE_SIZE;
static int max_sw_ins_tab_size = INIT_MAX_SW_INS_TABLE_SIZE;
static int index_to_sort = 0;
static int suppress_init_flags = 0; /* flag: suppress INIT_VISITED_FLAGS? */
int sorted_egraph_size = 0;
EG_NODE_PTR *expl_graph = NULL;
EG_NODE_PTR *sorted_expl_graph = NULL;
ROOT *roots = NULL;
int num_roots;
int num_goals;
int min_node_index;
int max_node_index;
SW_INS_PTR *switches = NULL;
SW_INS_PTR *switch_instances = NULL;
SW_INS_PTR *occ_switches = NULL; /* subset of switches */
int sw_tab_size = 0;
int sw_ins_tab_size = 0;
int occ_switch_tab_size = 0;
int failure_subgoal_id;
int failure_root_index;
/*------------------------------------------------------------------------*/
static void alloc_switch_table(void)
{
int i;
sw_tab_size = 0;
switches = (SW_INS_PTR *)MALLOC(max_sw_tab_size * sizeof(SW_INS_PTR));
for (i = 0; i < max_sw_tab_size; i++)
switches[i] = NULL;
}
static void expand_switch_table(int req_sw_tab_size)
{
int old_size,i;
if (req_sw_tab_size > max_sw_tab_size) {
old_size = max_sw_tab_size;
while (req_sw_tab_size > max_sw_tab_size)
max_sw_tab_size *= 2;
switches = (SW_INS_PTR *)REALLOC(switches,
max_sw_tab_size * sizeof(SW_INS_PTR));
for (i = old_size; i < max_sw_tab_size; i++)
switches[i] = NULL;
}
}
static void clean_switch_table(void)
{
if (switches != NULL) {
FREE(switches);
sw_tab_size = 0;
max_sw_tab_size = INIT_MAX_SW_TABLE_SIZE;
}
}
/*------------------------------------------------------------------------*/
static SW_INS_PTR alloc_switch_instance(void)
{
SW_INS_PTR sw_ptr = (SW_INS_PTR)MALLOC(sizeof(struct SwitchInstance));
sw_ptr->inside = 0.5;
return sw_ptr;
}
static void alloc_switch_instance_table(void)
{
int i;
sw_ins_tab_size = 0;
switch_instances =
(SW_INS_PTR *)MALLOC(max_sw_ins_tab_size * sizeof(SW_INS_PTR));
for (i = 0; i < max_sw_ins_tab_size; i++)
switch_instances[i] = NULL;
}
static void expand_switch_instance_table(int req_sw_ins_tab_size)
{
int old_size,i;
if (req_sw_ins_tab_size > max_sw_ins_tab_size) {
old_size = max_sw_ins_tab_size;
while (req_sw_ins_tab_size > max_sw_ins_tab_size)
max_sw_ins_tab_size *= 2;
switch_instances =
(SW_INS_PTR *)REALLOC(switch_instances,
max_sw_ins_tab_size * sizeof(SW_INS_PTR));
for (i = old_size; i < max_sw_ins_tab_size; i++)
switch_instances[i] = NULL;
}
}
static void clean_switch_instance_table(void)
{
int i;
if (switch_instances != NULL) {
for (i = 0; i < max_sw_ins_tab_size; i++)
FREE(switch_instances[i]);
FREE(switch_instances);
sw_ins_tab_size = 0;
max_sw_ins_tab_size = INIT_MAX_SW_INS_TABLE_SIZE;
}
}
/*------------------------------------------------------------------------*/
static EG_NODE_PTR alloc_egraph_node(void)
{
EG_NODE_PTR node_ptr = (EG_NODE_PTR)MALLOC(sizeof(struct ExplGraphNode));
node_ptr->inside = 1.0;
node_ptr->visited = 0;
node_ptr->path_ptr = NULL;
node_ptr->top_n = NULL;
node_ptr->top_n_len = 0;
node_ptr->shared = 0;
return node_ptr;
}
int pc_alloc_egraph_0(void)
{
int i;
alloc_switch_table();
alloc_switch_instance_table();
egraph_size = 0;
expl_graph = (EG_NODE_PTR *)MALLOC(max_egraph_size * sizeof(EG_NODE_PTR));
for (i = 0; i < max_egraph_size; i++) {
expl_graph[i] = alloc_egraph_node();
expl_graph[i]->id = i;
}
return BP_TRUE;
}
static void expand_egraph(int req_egraph_size)
{
int old_size,i;
if (req_egraph_size > max_egraph_size) {
old_size = max_egraph_size;
while (req_egraph_size > max_egraph_size) {
if (max_egraph_size > MAX_EGRAPH_SIZE_EXPAND_LIMIT) {
max_egraph_size += MAX_EGRAPH_SIZE_EXPAND_LIMIT;
}
else {
max_egraph_size *= 2;
}
}
expl_graph =
(EG_NODE_PTR *)REALLOC(expl_graph,
max_egraph_size * sizeof(EG_NODE_PTR));
for (i = old_size; i < max_egraph_size; i++) {
expl_graph[i] = alloc_egraph_node();
expl_graph[i]->id = i;
}
}
}
static void clean_sorted_egraph(void)
{
FREE(sorted_expl_graph);
}
/* Clean-up the base support graphs and switches */
static void clean_base_egraph(void)
{
int i,j;
EG_PATH_PTR path_ptr,next_path_ptr;
clean_switch_table();
clean_switch_instance_table();
if (expl_graph != NULL) {
for (i = 0; i < max_egraph_size; i++) {
if (expl_graph[i] == NULL) continue;
path_ptr = expl_graph[i]->path_ptr;
while (path_ptr != NULL) {
FREE(path_ptr->children);
FREE(path_ptr->sws);
next_path_ptr = path_ptr->next;
FREE(path_ptr);
path_ptr = next_path_ptr;
}
if (expl_graph[i]->top_n != NULL) {
for (j = 0; j < expl_graph[i]->top_n_len; j++) {
FREE(expl_graph[i]->top_n[j]->top_n_index);
FREE(expl_graph[i]->top_n[j]);
}
FREE(expl_graph[i]->top_n);
}
FREE(expl_graph[i]);
}
FREE(expl_graph);
egraph_size = 0;
max_egraph_size = INIT_MAX_EGRAPH_SIZE;
INIT_MIN_MAX_NODE_NOS;
}
}
int pc_clean_base_egraph_0(void)
{
clean_base_egraph();
return BP_TRUE;
}
int pc_clean_egraph_0(void)
{
clean_sorted_egraph();
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
int pc_export_switch_2(void)
{
BPLONG sw,sw_ins_ids,sw_ins_id;
SW_INS_PTR *curr_ins_ptr;
sw = bpx_get_integer(bpx_get_call_arg(1,2));
sw_ins_ids = bpx_get_call_arg(2,2);
if (sw >= max_sw_tab_size) expand_switch_table(sw + 1);
if (sw >= sw_tab_size) sw_tab_size = sw + 1;
curr_ins_ptr = &switches[sw];
while (bpx_is_list(sw_ins_ids)) {
sw_ins_id = bpx_get_integer(bpx_get_car(sw_ins_ids));
sw_ins_ids = bpx_get_cdr(sw_ins_ids);
if (sw_ins_id >= max_sw_ins_tab_size)
expand_switch_instance_table(sw_ins_id + 1);
if (sw_ins_id >= sw_ins_tab_size) sw_ins_tab_size = sw_ins_id + 1;
switch_instances[sw_ins_id] = alloc_switch_instance();
switch_instances[sw_ins_id]->id = sw_ins_id;
*curr_ins_ptr = switch_instances[sw_ins_id];
curr_ins_ptr = &switch_instances[sw_ins_id]->next;
}
*curr_ins_ptr = NULL;
return BP_TRUE;
}
static int add_egraph_path(int node_id, TERM children_prolog, TERM sws_prolog)
{
EG_PATH_PTR path_ptr;
EG_NODE_PTR *children;
SW_INS_PTR *sws;
int len,k;
int child,sw;
TERM p_child,p_sw;
int list_length(BPLONG, BPLONG);
if (node_id >= max_egraph_size) expand_egraph(node_id + 1);
if (node_id >= egraph_size) egraph_size = node_id + 1;
path_ptr = (EG_PATH_PTR)MALLOC(sizeof(struct ExplGraphPath));
len = list_length(children_prolog, children_prolog);
if (len > 0) {
path_ptr->children_len = len;
children = (EG_NODE_PTR *)MALLOC(sizeof(EG_NODE_PTR) * len);
k = 0;
while (bpx_is_list(children_prolog)) {
p_child = bpx_get_car(children_prolog);
if (!bpx_is_integer(p_child))
RET_ERR(err_invalid_goal_id);
child = bpx_get_integer(p_child);
children[k] = expl_graph[child];
k++;
children_prolog = bpx_get_cdr(children_prolog);
}
path_ptr->children = children;
}
else {
path_ptr->children_len = 0;
path_ptr->children = NULL;
}
len = list_length(sws_prolog, sws_prolog);
if (len > 0) {
path_ptr->sws_len = len;
sws = (SW_INS_PTR *)MALLOC(sizeof(SW_INS_PTR) * len);
k = 0;
while (bpx_is_list(sws_prolog)) {
p_sw = bpx_get_car(sws_prolog);
if (!bpx_is_integer(p_sw))
RET_ERR(err_invalid_switch_instance_id);
sw = bpx_get_integer(p_sw);
sws[k] = switch_instances[sw];
k++;
sws_prolog = bpx_get_cdr(sws_prolog);
}
path_ptr->sws = sws;
}
else {
path_ptr->sws_len = 0;
path_ptr->sws = NULL;
}
path_ptr->next = expl_graph[node_id]->path_ptr;
expl_graph[node_id]->path_ptr = path_ptr;
return BP_TRUE;
}
int pc_add_egraph_path_3(void)
{
TERM p_node_id,p_children,p_sws;
int node_id;
/* children_prolog and sws_prolog must be in the table area */
p_node_id = bpx_get_call_arg(1,3);
p_children = bpx_get_call_arg(2,3);
p_sws = bpx_get_call_arg(3,3);
if (!bpx_is_integer(p_node_id)) RET_ERR(err_invalid_goal_id);
node_id = bpx_get_integer(p_node_id);
XDEREF(p_children);
XDEREF(p_sws);
RET_ON_ERR(add_egraph_path(node_id,p_children,p_sws));
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
void alloc_sorted_egraph(int n)
{
int i;
max_sorted_egraph_size = INIT_MAX_EGRAPH_SIZE;
sorted_expl_graph =
(EG_NODE_PTR *)MALLOC(sizeof(EG_NODE_PTR) * max_sorted_egraph_size);
roots = (ROOT *)MALLOC(sizeof(ROOT *) * n);
for (i = 0; i < n; i++)
roots[i] = NULL;
num_roots = n;
}
static void expand_sorted_egraph(int req_sorted_egraph_size)
{
if (req_sorted_egraph_size > max_sorted_egraph_size) {
while (req_sorted_egraph_size > max_sorted_egraph_size) {
if (max_sorted_egraph_size > MAX_EGRAPH_SIZE_EXPAND_LIMIT)
max_sorted_egraph_size += MAX_EGRAPH_SIZE_EXPAND_LIMIT;
else
max_sorted_egraph_size *= 2;
}
sorted_expl_graph =
(EG_NODE_PTR *)
REALLOC(sorted_expl_graph,
max_sorted_egraph_size * sizeof(EG_NODE_PTR));
}
}
/*------------------------------------------------------------------------*/
void initialize_egraph_index(void)
{
index_to_sort = 0;
}
static int topological_sort(int node_id)
{
EG_PATH_PTR path_ptr;
EG_NODE_PTR *children;
int k,len;
EG_NODE_PTR child_ptr;
expl_graph[node_id]->visited = 2;
UPDATE_MIN_MAX_NODE_NOS(node_id);
path_ptr = expl_graph[node_id]->path_ptr;
while (path_ptr != NULL) {
children = path_ptr->children;
len = path_ptr->children_len;
for (k = 0; k < len; k++) {
child_ptr = children[k];
if (child_ptr->visited == 2 && error_on_cycle)
RET_ERR(err_cycle_detected);
if (child_ptr->visited == 0) {
RET_ON_ERR(topological_sort(child_ptr->id));
expand_sorted_egraph(index_to_sort + 1);
sorted_expl_graph[index_to_sort++] = child_ptr;
}
child_ptr->shared += 1;
}
path_ptr = path_ptr->next;
}
expl_graph[node_id]->visited = 1;
return BP_TRUE;
}
int sort_one_egraph(int root_id, int root_index, int count)
{
roots[root_index] = (ROOT)MALLOC(sizeof(struct ObservedFactNode));
roots[root_index]->id = root_id;
roots[root_index]->count = count;
if (expl_graph[root_id]->visited == 1) {
/*
* This top-goal is also a sub-goal of another top-goal. This
* should occur only when INIT_VISITED_FLAGS is suppressed
* (i.e. we have more than one observed goal in learning).
*/
if (suppress_init_flags) return BP_TRUE;
}
if (expl_graph[root_id]->visited != 0) RET_INTERNAL_ERR;
RET_ON_ERR(topological_sort(root_id));
expand_sorted_egraph(index_to_sort + 1);
sorted_expl_graph[index_to_sort] = expl_graph[root_id];
index_to_sort++;
sorted_egraph_size = index_to_sort;
/* initialize flags after use */
if (!suppress_init_flags) INIT_VISITED_FLAGS;
return BP_TRUE;
}
int sort_egraphs(TERM p_fact_list) /* assumed to be dereferenced in advance */
{
TERM pair;
int root_index = 0, goal_id, count;
sorted_egraph_size = 0;
suppress_init_flags = 1;
while (bpx_is_list(p_fact_list)) {
pair = bpx_get_car(p_fact_list);
p_fact_list = bpx_get_cdr(p_fact_list);
goal_id = bpx_get_integer(bpx_get_arg(1,pair));
count = bpx_get_integer(bpx_get_arg(2,pair));
if (sort_one_egraph(goal_id,root_index,count) == BP_ERROR) {
INIT_VISITED_FLAGS;
return BP_ERROR;
}
root_index++;
}
suppress_init_flags = 0;
INIT_VISITED_FLAGS;
return BP_TRUE;
}
/*
* Sort the explanation graph such that no node sorted_expl_graph[i] calls
* node sorted_expl_graph[j] if i < j.
*
* This function is used only for probf/1-2, so we don't have to consider
* about scaling here.
*/
int pc_alloc_sort_egraph_1(void)
{
int root_id;
root_id = bpx_get_integer(bpx_get_call_arg(1,1));
index_to_sort = 0;
alloc_sorted_egraph(1);
RET_ON_ERR(sort_one_egraph(root_id,0,1));
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
static void clean_root_tables(void)
{
int i;
if (roots != NULL) {
for (i = 0; i < num_roots; i++)
FREE(roots[i]);
FREE(roots);
}
}
int pc_clean_external_tables_0(void)
{
clean_root_tables();
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
/*
* Export probabilities of switches from Prolog to C. Switches is
* a list of switches, each of which takes the form:
*
* sw(Id,InstanceIds,Probs,SmoothCs,Fixed,FixedH),
*
* where
* Id: identifier of the switch
* InstanceIds: list of ids of the instances of the switch
* Probs: current probabilities assigned to the instance switches
* SmoothCs: current pseudo counts assigned to the instance switches
* Fixed: probabilities fixed?
* FixedH: pseudo counts fixed?
*
* The structures for switch instances have been allocated. This
* function only fills out the initial probabilities.
*/
int pc_export_sw_info_1(void)
{
int sw_id,instance_id,fixed,fixed_h;
double prob,smooth;
TERM p_switches, p_switch;
TERM p_instance_list,p_prob_list,p_smooth_list;
TERM p_prob,p_smooth;
p_switches = bpx_get_call_arg(1,1);
while (bpx_is_list(p_switches)) {
/* p_switch: sw(Id,InstList,ProbList,SmoothCList,FixedP,FixedH) */
p_switch = bpx_get_car(p_switches);
sw_id = bpx_get_integer(bpx_get_arg(1,p_switch));
p_instance_list = bpx_get_arg(2,p_switch);
p_prob_list = bpx_get_arg(3,p_switch);
p_smooth_list = bpx_get_arg(4,p_switch);
fixed = bpx_get_integer(bpx_get_arg(5,p_switch));
fixed_h = bpx_get_integer(bpx_get_arg(6,p_switch));
while (bpx_is_list(p_instance_list)) {
instance_id = bpx_get_integer(bpx_get_car(p_instance_list));
p_prob = bpx_get_car(p_prob_list);
p_smooth = bpx_get_car(p_smooth_list);
if (bpx_is_integer(p_prob)) {
prob = (double)bpx_get_integer(p_prob);
}
else if (bpx_is_float(p_prob)) {
prob = bpx_get_float(p_prob);
}
else {
RET_ERR(illegal_arguments);
}
if (bpx_is_integer(p_smooth)) {
smooth = (double)bpx_get_integer(p_smooth);
}
else if (bpx_is_float(p_smooth)) {
smooth = bpx_get_float(p_smooth);
}
else {
RET_ERR(illegal_arguments);
}
switch_instances[instance_id]->inside = prob;
switch_instances[instance_id]->fixed = fixed;
switch_instances[instance_id]->fixed_h = fixed_h;
switch_instances[instance_id]->smooth_prolog = smooth;
p_instance_list = bpx_get_cdr(p_instance_list);
p_prob_list = bpx_get_cdr(p_prob_list);
p_smooth_list = bpx_get_cdr(p_smooth_list);
}
p_switches = bpx_get_cdr(p_switches);
}
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
/* the following functions are needed by probf */
int pc_import_sorted_graph_size_1(void)
{
return bpx_unify(bpx_get_call_arg(1,1),
bpx_build_integer(sorted_egraph_size));
}
int pc_import_sorted_graph_gid_2(void)
{
int idx = bpx_get_integer(bpx_get_call_arg(1,2));
return bpx_unify(bpx_get_call_arg(2,2),
bpx_build_integer(sorted_expl_graph[idx]->id));
}
int pc_import_sorted_graph_paths_2(void)
{
TERM paths0,paths1,glist,slist,t0,t1,p_tmp;
EG_PATH_PTR path_ptr;
EG_NODE_PTR *children;
SW_INS_PTR *sws;
int node_id,k,len;
node_id = bpx_get_integer(bpx_get_call_arg(1,2));
path_ptr = sorted_expl_graph[node_id]->path_ptr;
if (path_ptr == NULL) {
if (explicit_empty_expls) {
t0 = bpx_build_list();
t1 = bpx_build_list();
bpx_unify(bpx_get_car(t0),bpx_build_nil());
bpx_unify(bpx_get_cdr(t0),t1);
bpx_unify(bpx_get_car(t1),bpx_build_nil());
bpx_unify(bpx_get_cdr(t1),bpx_build_nil());
paths0 = bpx_build_list();
bpx_unify(bpx_get_car(paths0),t0);
bpx_unify(bpx_get_cdr(paths0),bpx_build_nil());
}
else paths0 = bpx_build_nil();
}
else {
paths0 = bpx_build_nil();
while (path_ptr != NULL) {
len = path_ptr->children_len;
children = path_ptr->children;
if (len > 0) {
glist = bpx_build_list();
p_tmp = glist;
for (k = 0; k < len; k++) {
bpx_unify(bpx_get_car(p_tmp),
bpx_build_integer(children[k]->id));
if (k == len - 1) {
bpx_unify(bpx_get_cdr(p_tmp),bpx_build_nil());
}
else {
bpx_unify(bpx_get_cdr(p_tmp),bpx_build_list());
p_tmp = bpx_get_cdr(p_tmp);
}
}
}
else glist = bpx_build_nil();
len = path_ptr->sws_len;
sws = path_ptr->sws;
if (len > 0) {
slist = bpx_build_list();
p_tmp = slist;
for (k = 0; k < len; k++) {
bpx_unify(bpx_get_car(p_tmp),bpx_build_integer(sws[k]->id));
if (k == len - 1) {
bpx_unify(bpx_get_cdr(p_tmp),bpx_build_nil());
}
else {
bpx_unify(bpx_get_cdr(p_tmp),bpx_build_list());
p_tmp = bpx_get_cdr(p_tmp);
}
}
}
else slist = bpx_build_nil();
if (explicit_empty_expls ||
!bpx_is_nil(glist) || !bpx_is_nil(slist)) {
t0 = bpx_build_list();
t1 = bpx_build_list();
bpx_unify(bpx_get_car(t0),glist);
bpx_unify(bpx_get_cdr(t0),t1);
bpx_unify(bpx_get_car(t1),slist);
bpx_unify(bpx_get_cdr(t1),bpx_build_nil());
paths1 = bpx_build_list();
bpx_unify(bpx_get_car(paths1),t0);
bpx_unify(bpx_get_cdr(paths1),paths0);
paths0 = paths1;
}
path_ptr = path_ptr->next;
}
}
return bpx_unify(bpx_get_call_arg(2,2),paths0);
}
int pc_get_gnode_inside_2(void)
{
int idx = bpx_get_integer(bpx_get_call_arg(1,2));
return bpx_unify(bpx_get_call_arg(2,2),
bpx_build_float(expl_graph[idx]->inside));
}
int pc_get_gnode_outside_2(void)
{
int idx = bpx_get_integer(bpx_get_call_arg(1,2));
return bpx_unify(bpx_get_call_arg(2,2),
bpx_build_float(expl_graph[idx]->outside));
}
int pc_get_gnode_viterbi_2(void)
{
int idx = bpx_get_integer(bpx_get_call_arg(1,2));
return bpx_unify(bpx_get_call_arg(2,2),
bpx_build_float(expl_graph[idx]->max));
}
int pc_get_snode_inside_2(void)
{
int idx = bpx_get_integer(bpx_get_call_arg(1,2));
double val = switch_instances[idx]->inside;
if (log_scale) val = log(val);
return bpx_unify(bpx_get_call_arg(2,2),bpx_build_float(val));
}
int pc_get_snode_expectation_2(void)
{
int idx = bpx_get_integer(bpx_get_call_arg(1,2));
return bpx_unify(bpx_get_call_arg(2,2),
bpx_build_float(switch_instances[idx]->total_expect));
}
int pc_import_occ_switches_3(void)
{
TERM p_sw_list,p_sw_list0,p_sw_list1;
TERM p_sw_ins_list0,p_sw_ins_list1,sw,sw_ins;
TERM p_num_sw, p_num_sw_ins;
int i;
int num_sw_ins;
void release_occ_switches();
#ifdef __YAP_PROLOG__
TERM *hstart;
restart:
hstart = heap_top;
#endif
p_sw_list = bpx_get_call_arg(1,3);
p_num_sw = bpx_get_call_arg(2,3);
p_num_sw_ins = bpx_get_call_arg(3,3);
p_sw_list0 = bpx_build_nil();
num_sw_ins = 0;
for (i = 0; i < occ_switch_tab_size; i++) {
SW_INS_PTR ptr;
#ifdef __YAP_PROLOG__
if ( heap_top + 64*1024 >= local_top ) {
H = hstart;
/* running out of stack */
extern int Yap_gcl(UInt gc_lim, Int predarity, CELL *current_env, yamop *nextop);
Yap_gcl(4*64*1024, 3, ENV, P);
goto restart;
}
#endif
sw = bpx_build_structure("sw",2);
bpx_unify(bpx_get_arg(1,sw), bpx_build_integer(i));
p_sw_ins_list0 = bpx_build_nil();
ptr = occ_switches[i];
while (ptr != NULL) {
num_sw_ins++;
if (ptr->inside <= 0.0) ptr->inside = 0.0; /* FIXME: quick hack */
sw_ins = bpx_build_structure("sw_ins",4);
bpx_unify(bpx_get_arg(1,sw_ins),bpx_build_integer(ptr->id));
bpx_unify(bpx_get_arg(2,sw_ins),bpx_build_float(ptr->inside));
bpx_unify(bpx_get_arg(3,sw_ins),bpx_build_float(ptr->smooth));
bpx_unify(bpx_get_arg(4,sw_ins),bpx_build_float(ptr->total_expect));
p_sw_ins_list1 = bpx_build_list();
bpx_unify(bpx_get_car(p_sw_ins_list1),sw_ins);
bpx_unify(bpx_get_cdr(p_sw_ins_list1),p_sw_ins_list0);
p_sw_ins_list0 = p_sw_ins_list1;
ptr = ptr->next;
}
bpx_unify(bpx_get_arg(2,sw),p_sw_ins_list0);
p_sw_list1 = bpx_build_list();
bpx_unify(bpx_get_car(p_sw_list1),sw);
bpx_unify(bpx_get_cdr(p_sw_list1),p_sw_list0);
p_sw_list0 = p_sw_list1;
}
release_occ_switches();
return
bpx_unify(p_sw_list, p_sw_list0) &&
bpx_unify(p_num_sw, bpx_build_integer(occ_switch_tab_size)) &&
bpx_unify(p_num_sw_ins, bpx_build_integer(num_sw_ins));
}
/*------------------------------------------------------------------------*/
void graph_stats(int stats[4])
{
int num_goal_nodes = 0;
int num_switch_nodes = 0;
int total_shared = 0;
int i;
EG_NODE_PTR eg_ptr;
EG_PATH_PTR path_ptr;
for (i = 0; i < sorted_egraph_size; i++) {
eg_ptr = sorted_expl_graph[i];
total_shared += eg_ptr->shared;
path_ptr = eg_ptr->path_ptr;
while (path_ptr != NULL) {
num_goal_nodes += path_ptr->children_len;
num_switch_nodes += path_ptr->sws_len;
path_ptr = path_ptr->next;
}
}
stats[0] = sorted_egraph_size;
stats[1] = num_goal_nodes;
stats[2] = num_switch_nodes;
stats[3] = total_shared;
}
int pc_import_graph_stats_4(void)
{
int stats[4];
double avg_shared;
graph_stats(stats);
avg_shared = (double)(stats[3]) / stats[0];
return
bpx_unify(bpx_get_call_arg(1,4), bpx_build_integer(stats[0])) &&
bpx_unify(bpx_get_call_arg(2,4), bpx_build_integer(stats[1])) &&
bpx_unify(bpx_get_call_arg(3,4), bpx_build_integer(stats[2])) &&
bpx_unify(bpx_get_call_arg(4,4), bpx_build_float(avg_shared));
}

View File

@ -0,0 +1,82 @@
#ifndef GRAPH_H
#define GRAPH_H
/*====================================================================*/
#define INIT_MAX_SW_TABLE_SIZE 16
#define INIT_MAX_SW_INS_TABLE_SIZE 64
#define INIT_MAX_EGRAPH_SIZE (1 << 8)
#define MAX_EGRAPH_SIZE_EXPAND_LIMIT (128 << 10)
/* node_id should be non-negative */
#define UPDATE_MIN_MAX_NODE_NOS(node_id) do { \
if (min_node_index < 0 || node_id < min_node_index) \
min_node_index = node_id; \
if (node_id > max_node_index) \
max_node_index = node_id; \
} while (0)
#define INIT_MIN_MAX_NODE_NOS do { \
min_node_index = -1; \
max_node_index = -1; \
} while (0)
#define INIT_VISITED_FLAGS do { \
int i; \
for (i = min_node_index; i <= max_node_index; i++) \
expl_graph[i]->visited = 0; \
} while (0)
/*====================================================================*/
int pc_alloc_egraph_0(void);
int pc_clean_base_egraph_0(void);
int pc_clean_egraph_0(void);
int pc_export_switch_2(void);
int pc_add_egraph_path_3(void);
int pc_alloc_sort_egraph_1(void);
int pc_clean_external_tables_0(void);
int pc_export_sw_info_1(void);
int pc_import_sorted_graph_size_1(void);
int pc_import_sorted_graph_gid_2(void);
int pc_import_sorted_graph_paths_2(void);
int pc_get_gnode_inside_2(void);
int pc_get_gnode_outside_2(void);
int pc_get_gnode_viterbi_2(void);
int pc_get_snode_inside_2(void);
int pc_get_snode_expectation_2(void);
int pc_import_occ_switches_3(void);
void graph_stats(int[4]);
/*--------------------------------------------------------------------*/
void alloc_sorted_egraph(int);
void initialize_egraph_index(void);
int sort_one_egraph(int, int, int);
int sort_egraphs(TERM);
/*====================================================================*/
extern int sorted_egraph_size;
extern EG_NODE_PTR *expl_graph;
extern EG_NODE_PTR *sorted_expl_graph;
extern int num_roots;
extern int num_goals;
extern ROOT *roots;
extern int min_node_index;
extern int max_node_index;
extern int sw_tab_size;
extern int sw_ins_tab_size;
extern int occ_switch_tab_size;
extern SW_INS_PTR *switches;
extern SW_INS_PTR *switch_instances;
extern SW_INS_PTR *occ_switches;
extern int failure_subgoal_id;
extern int failure_root_index;
/*====================================================================*/
#endif /* GRAPH_H */

View File

@ -0,0 +1,299 @@
#include <stdlib.h>
#include "bprolog.h"
#include "up/up.h"
#include "up/graph.h"
#include "up/graph_aux.h"
#include "up/flags.h"
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
void quit(const char *);
/*------------------------------------------------------------------------*/
static EG_NODE_PTR *subgraph;
static int subgraph_size;
static int max_subgraph_size;
/*------------------------------------------------------------------------*/
static void alloc_subgraph(void)
{
max_subgraph_size = INIT_MAX_EGRAPH_SIZE;
subgraph = (EG_NODE_PTR *)MALLOC(sizeof(EG_NODE_PTR) * max_subgraph_size);
}
static void expand_subgraph(int req_subgraph_size)
{
if (req_subgraph_size > max_subgraph_size) {
while (req_subgraph_size > max_subgraph_size) {
if (max_subgraph_size > MAX_EGRAPH_SIZE_EXPAND_LIMIT)
max_subgraph_size += MAX_EGRAPH_SIZE_EXPAND_LIMIT;
else
max_subgraph_size *= 2;
}
subgraph = REALLOC(subgraph, sizeof(EG_NODE_PTR) * max_subgraph_size);
}
}
static void release_subgraph(void)
{
free(subgraph);
subgraph = NULL;
}
static void traverse_egraph(EG_NODE_PTR node_ptr)
{
int i;
EG_NODE_PTR c_node_ptr;
EG_PATH_PTR path_ptr;
node_ptr->visited = 1;
path_ptr = node_ptr->path_ptr;
while (path_ptr != NULL) {
for (i = 0; i < path_ptr->children_len; i++) {
c_node_ptr = path_ptr->children[i];
if (c_node_ptr->visited != 1) {
if (c_node_ptr->visited == 0) {
traverse_egraph(c_node_ptr);
}
expand_subgraph(subgraph_size + 1);
subgraph[subgraph_size] = c_node_ptr;
subgraph_size++;
}
}
path_ptr = path_ptr->next;
}
}
/*------------------------------------------------------------------------*/
/* `mode' is a macro prefixed by `PRINT_' */
void print_egraph(int level, int mode)
{
ROOT root_ptr;
EG_NODE_PTR eg_ptr, node_ptr;
EG_PATH_PTR path_ptr;
SW_INS_PTR sw_ptr;
int log_scale1;
int r,u,e,i,k,len;
/* disable scaling for non-learning */
log_scale1 = (mode > 0) ? log_scale : 0;
alloc_subgraph();
for (r = 0; r < num_roots; r++) {
root_ptr = roots[r];
if (level >= 1) {
fprintf(curr_out," <<Goal[%d]: %s (id=%d, count=%d)>>\n",
r,prism_goal_string(root_ptr->id),
root_ptr->id,root_ptr->count);
}
else {
fprintf(curr_out," <<Goal[%d]: (count=%d)>>\n",r,root_ptr->count);
}
subgraph_size = 0;
traverse_egraph(expl_graph[root_ptr->id]);
expand_subgraph(subgraph_size + 1);
subgraph[subgraph_size] = expl_graph[root_ptr->id];
for (i = subgraph_size; i >= 0; i--) {
eg_ptr = subgraph[i];
if (eg_ptr->visited == 2) {
fprintf(curr_out," g[%d]:%s\n",
eg_ptr->id,prism_goal_string(eg_ptr->id));
fprintf(curr_out," **** already shown ****\n");
continue;
}
eg_ptr->visited = 2;
if (level == 0) {
fprintf(curr_out," g[%d]:%s\n",
eg_ptr->id,prism_goal_string(eg_ptr->id));
}
if (level >= 3) {
fprintf(curr_out," g[%d]:%s.addr = <%p>\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),eg_ptr);
}
if (level >= 1) {
if (log_scale1) {
fprintf(curr_out," g[%d]:%s.inside = %.9e (%.9e)\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->inside,exp(eg_ptr->inside));
fprintf(curr_out," g[%d]:%s.outside = %.9e (%.9e)\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->outside,exp(eg_ptr->outside));
fprintf(curr_out," g[%d]:%s.first_outside = %.9e (%.9e)\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->first_outside,exp(eg_ptr->first_outside));
}
else {
fprintf(curr_out," g[%d]:%s.inside = %.9e\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->inside);
fprintf(curr_out," g[%d]:%s.outside = %.9e\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->outside);
}
if (mode == PRINT_VITERBI) {
fprintf(curr_out," g[%d]:%s.max = %.9e\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->max);
fprintf(curr_out," g[%d]:%s.top_n_len = %d\n",
eg_ptr->id,prism_goal_string(eg_ptr->id),
eg_ptr->top_n_len);
if (eg_ptr->top_n != NULL) {
for (e = 0; e < eg_ptr->top_n_len; e++) {
if (eg_ptr->top_n[e] == NULL) continue;
fprintf(curr_out," top_n[%d]->goal_id = %d\n",
e,eg_ptr->top_n[e]->goal_id);
fprintf(curr_out," top_n[%d]->path_ptr = %p\n",
e,eg_ptr->top_n[e]->path_ptr);
len = eg_ptr->top_n[e]->children_len;
for (k = 0; k < len; k++) {
fprintf(curr_out,
" top_n[%d]->goal[%d] = %s (%d)\n",
e,k,prism_goal_string(eg_ptr->top_n[e]->path_ptr->children[k]->id),eg_ptr->top_n[e]->path_ptr->children[k]->id);
fprintf(curr_out," top_n[%d]->top_n_index[%d] = %d\n",
e,k,eg_ptr->top_n[e]->top_n_index[k]);
}
fprintf(curr_out," top_n[%d]->max = %.9e\n",
e,eg_ptr->top_n[e]->max);
}
}
}
}
path_ptr = eg_ptr->path_ptr;
u = 0;
while (path_ptr != NULL) {
if (level == 0) {
fprintf(curr_out," path[%d]:\n",u);
}
if (level >= 3) {
fprintf(curr_out," path[%d].chilren_len = %d\n",
u,path_ptr->children_len);
fprintf(curr_out," path[%d].sws_len = %d\n",
u,path_ptr->sws_len);
}
if (level >= 1) {
if (log_scale1) {
fprintf(curr_out," path[%d].inside = %.9e (%.9e)\n",
u,path_ptr->inside,exp(path_ptr->inside));
}
else {
fprintf(curr_out," path[%d].inside = %.9e\n",
u,path_ptr->inside);
}
}
for (k = 0; k < path_ptr->children_len; k++) {
node_ptr = path_ptr->children[k];
if (level == 0) {
fprintf(curr_out," g[%d]:%s\n",
node_ptr->id,prism_goal_string(node_ptr->id));
}
if (level >= 3) {
fprintf(curr_out," g[%d]:%s.addr = <%p>\n",
node_ptr->id,prism_goal_string(node_ptr->id),
node_ptr);
}
if (level >= 1) {
if (log_scale1) {
fprintf(curr_out,
" g[%d]:%s.inside = %.9e (%.9e)\n",
node_ptr->id,
prism_goal_string(node_ptr->id),
node_ptr->inside,exp(node_ptr->inside));
fprintf(curr_out,
" g[%d]:%s.outside = %.9e (%.9e)\n",
node_ptr->id,
prism_goal_string(node_ptr->id),
node_ptr->outside,exp(node_ptr->outside));
fprintf(curr_out,
" g[%d]:%s.first_outside = %.9e (%.9e)\n",
node_ptr->id,
prism_goal_string(node_ptr->id),
node_ptr->first_outside,
exp(node_ptr->first_outside));
}
else {
fprintf(curr_out," g[%d]:%s.inside = %.9e\n",
node_ptr->id,
prism_goal_string(node_ptr->id),
node_ptr->inside);
fprintf(curr_out," g[%d]:%s.outside = %.9e\n",
node_ptr->id,
prism_goal_string(node_ptr->id),
node_ptr->outside);
}
}
}
for (k = 0; k < path_ptr->sws_len; k++) {
sw_ptr = path_ptr->sws[k];
if (level == 0) {
fprintf(curr_out," sw[%d]:%s\n",
sw_ptr->id,prism_sw_ins_string(sw_ptr->id));
}
if (level >= 1) {
if (mode == PRINT_EM) {
fprintf(curr_out," sw[%d]:%s.inside = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->inside);
fprintf(curr_out," sw[%d]:%s.total_e = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->total_expect);
}
if (mode == PRINT_VBEM) {
fprintf(curr_out," sw[%d]:%s.pi = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->pi);
fprintf(curr_out," sw[%d]:%s.smooth = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->smooth);
fprintf(curr_out," sw[%d]:%s.inside = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->inside);
fprintf(curr_out,
" sw[%d]:%s.inside_h = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->inside_h);
fprintf(curr_out," sw[%d]:%s.total_e = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->total_expect);
}
if (mode == PRINT_VITERBI) {
fprintf(curr_out," sw[%d]:%s.inside = %.9e\n",
sw_ptr->id,
prism_sw_ins_string(sw_ptr->id),
sw_ptr->inside);
}
}
}
path_ptr = path_ptr->next;
u++;
}
}
}
INIT_VISITED_FLAGS;
release_subgraph();
}
/*------------------------------------------------------------------------*/

View File

@ -0,0 +1,15 @@
#ifndef GRAPH_AUX_H
#define GRAPH_AUX_H
/*
* mode for print_egraph
* (positive for EM learning; negative for other inferences)
*/
#define PRINT_NEUTRAL 0
#define PRINT_EM 1
#define PRINT_VBEM 2
#define PRINT_VITERBI -1
void print_egraph(int, int);
#endif /* GRAPH_AUX_H */

View File

@ -0,0 +1,300 @@
#include "up/up.h"
#include "up/graph.h"
#include "up/graph_aux.h"
#include "up/em_aux.h"
#include "up/em_aux_ml.h"
#include "up/flags.h"
#include "up/util.h"
/*------------------------------------------------------------------------*/
#define INIT_MAX_HINDSIGHT_GOAL_SIZE 100
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
NORET quit(const char *);
/*------------------------------------------------------------------------*/
static int * hindsight_goals = NULL;
static double * hindsight_probs = NULL;
static int max_hindsight_goal_size;
static int hindsight_goal_size;
/*------------------------------------------------------------------------*/
static void alloc_hindsight_goals(void)
{
int i;
hindsight_goal_size = 0;
max_hindsight_goal_size = INIT_MAX_HINDSIGHT_GOAL_SIZE;
hindsight_goals = (int *)MALLOC(max_hindsight_goal_size * sizeof(TERM));
hindsight_probs =
(double *)MALLOC(max_hindsight_goal_size * sizeof(double));
for (i = 0; i < max_hindsight_goal_size; i++) {
hindsight_goals[i] = -1;
hindsight_probs[i] = 0.0;
}
}
static void expand_hindsight_goals(int req_hindsight_goal_size)
{
int old_size,i;
if (req_hindsight_goal_size > max_hindsight_goal_size) {
old_size = max_hindsight_goal_size;
while (req_hindsight_goal_size > max_hindsight_goal_size) {
max_hindsight_goal_size *= 2;
}
hindsight_goals =
(int *)REALLOC(hindsight_goals,
max_hindsight_goal_size * sizeof(TERM));
hindsight_probs =
(double *)REALLOC(hindsight_probs,
max_hindsight_goal_size * sizeof(double));
for (i = old_size; i < max_hindsight_goal_size; i++) {
hindsight_goals[i] = -1;
hindsight_probs[i] = 0.0;
}
}
}
/*
* Be warned that eg_ptr->outside will have a value different from that
* in the compute_expectation-family functions.
*/
int compute_outside_scaling_none(void)
{
int i,k;
EG_PATH_PTR path_ptr;
EG_NODE_PTR eg_ptr,node_ptr;
double q;
if (num_roots != 1) {
emit_internal_error("illegal call to compute_outside");
RET_ERR(build_internal_error("no_observed_data"));
}
for (i = 0; i < sorted_egraph_size; i++) {
sorted_expl_graph[i]->outside = 0.0;
}
eg_ptr = expl_graph[roots[0]->id];
eg_ptr->outside = roots[0]->count;
for (i = (sorted_egraph_size - 1); i >= 0; i--) {
eg_ptr = sorted_expl_graph[i];
path_ptr = eg_ptr->path_ptr;
while (path_ptr != NULL) {
q = eg_ptr->outside * path_ptr->inside;
if (q > 0.0) {
for (k = 0; k < path_ptr->children_len; k++) {
node_ptr = path_ptr->children[k];
node_ptr->outside += q / node_ptr->inside;
}
}
path_ptr = path_ptr->next;
}
}
return BP_TRUE;
}
int compute_outside_scaling_log_exp(void)
{
int i,k;
EG_PATH_PTR path_ptr;
EG_NODE_PTR eg_ptr,node_ptr;
double q,r;
if (num_roots != 1) {
emit_internal_error("illegal call to compute_outside");
RET_ERR(build_internal_error("no_observed_data"));
}
for (i = 0; i < sorted_egraph_size; i++) {
sorted_expl_graph[i]->outside = 0.0;
sorted_expl_graph[i]->has_first_outside = 0;
sorted_expl_graph[i]->first_outside = 0.0;
}
eg_ptr = expl_graph[roots[0]->id];
eg_ptr->outside = 1.0;
eg_ptr->has_first_outside = 1;
eg_ptr->first_outside = log((double)(roots[0]->count));
/* sorted_expl_graph[to] must be a root node */
for (i = sorted_egraph_size - 1; i >= 0; i--) {
eg_ptr = sorted_expl_graph[i];
/* First accumulate log-scale outside probabilities: */
if (!eg_ptr->has_first_outside) {
emit_internal_error("unexpected has_first_outside[%s]",prism_goal_string(eg_ptr->id));
RET_INTERNAL_ERR;
}
else if (!(eg_ptr->outside > 0.0)) {
emit_internal_error("unexpected outside[%s]",
prism_goal_string(eg_ptr->id));
RET_INTERNAL_ERR;
}
else {
eg_ptr->outside = eg_ptr->first_outside + log(eg_ptr->outside);
}
path_ptr = sorted_expl_graph[i]->path_ptr;
while (path_ptr != NULL) {
q = sorted_expl_graph[i]->outside + path_ptr->inside;
for (k = 0; k < path_ptr->children_len; k++) {
node_ptr = path_ptr->children[k];
r = q - node_ptr->inside;
if (!node_ptr->has_first_outside) {
node_ptr->first_outside = r;
node_ptr->outside += 1.0;
node_ptr->has_first_outside = 1;
}
else if (r - node_ptr->first_outside >= log(HUGE_PROB)) {
node_ptr->outside *= exp(node_ptr->first_outside - r);
node_ptr->first_outside = r;
node_ptr->outside += 1.0;
}
else {
node_ptr->outside += exp(r - node_ptr->first_outside);
}
}
path_ptr = path_ptr->next;
}
}
return BP_TRUE;
}
static int get_hindsight_goals_scaling_none(TERM p_subgoal, int is_cond)
{
int i,j;
EG_NODE_PTR eg_ptr;
TERM t;
double denom;
if (is_cond) {
denom = expl_graph[roots[0]->id]->inside;
}
else {
denom = 1.0;
}
j = 0;
for (i = 0; i < sorted_egraph_size - 1; i++) {
eg_ptr = sorted_expl_graph[i];
t = prism_goal_term((IDNUM)(eg_ptr->id));
if (bpx_is_unifiable(p_subgoal, t)) {
if (j >= max_hindsight_goal_size) expand_hindsight_goals(j + 1);
if (j >= hindsight_goal_size) hindsight_goal_size = j + 1;
hindsight_goals[j] = eg_ptr->id;
hindsight_probs[j] = eg_ptr->inside * eg_ptr->outside / denom;
j++;
}
}
return BP_TRUE;
}
static int get_hindsight_goals_scaling_log_exp(TERM p_subgoal, int is_cond)
{
int i,j;
EG_NODE_PTR eg_ptr;
TERM t;
double denom;
if (is_cond) {
denom = expl_graph[roots[0]->id]->inside;
}
else {
denom = 0.0;
}
j = 0;
for (i = 0; i < sorted_egraph_size - 1; i++) {
eg_ptr = sorted_expl_graph[i];
t = prism_goal_term(eg_ptr->id);
if (bpx_is_unifiable(p_subgoal, t)) {
if (j >= max_hindsight_goal_size) expand_hindsight_goals(j + 1);
if (j >= hindsight_goal_size) hindsight_goal_size = j + 1;
hindsight_goals[j] = eg_ptr->id;
hindsight_probs[j] = eg_ptr->inside + eg_ptr->outside - denom;
j++;
}
}
return BP_TRUE;
}
int pc_compute_hindsight_4(void)
{
TERM p_subgoal,p_hindsight_pairs,t,t1,p_pair;
int goal_id,is_cond,j;
goal_id = bpx_get_integer(bpx_get_call_arg(1,4));
p_subgoal = bpx_get_call_arg(2,4);
is_cond = bpx_get_integer(bpx_get_call_arg(3,4));
initialize_egraph_index();
alloc_sorted_egraph(1);
RET_ON_ERR(sort_one_egraph(goal_id,0,1));
if (verb_graph) print_egraph(0,PRINT_NEUTRAL);
alloc_hindsight_goals();
if (log_scale) {
RET_ON_ERR(compute_inside_scaling_log_exp());
RET_ON_ERR(compute_outside_scaling_log_exp());
RET_ON_ERR(get_hindsight_goals_scaling_log_exp(p_subgoal,is_cond));
}
else {
RET_ON_ERR(compute_inside_scaling_none());
RET_ON_ERR(compute_outside_scaling_none());
RET_ON_ERR(get_hindsight_goals_scaling_none(p_subgoal,is_cond));
}
if (hindsight_goal_size > 0) {
/* Build the list of pairs of a subgoal and its hindsight probability */
p_hindsight_pairs = bpx_build_list();
t = p_hindsight_pairs;
for (j = 0; j < hindsight_goal_size; j++) {
p_pair = bpx_build_list();
t1 = p_pair;
bpx_unify(bpx_get_car(t1),
bpx_build_integer(hindsight_goals[j]));
bpx_unify(bpx_get_cdr(t1),bpx_build_list());
t1 = bpx_get_cdr(t1);
bpx_unify(bpx_get_car(t1),bpx_build_float(hindsight_probs[j]));
bpx_unify(bpx_get_cdr(t1),bpx_build_nil());
bpx_unify(bpx_get_car(t),p_pair);
if (j == hindsight_goal_size - 1) {
bpx_unify(bpx_get_cdr(t),bpx_build_nil());
}
else {
bpx_unify(bpx_get_cdr(t),bpx_build_list());
t = bpx_get_cdr(t);
}
}
}
else {
p_hindsight_pairs = bpx_build_nil();
}
FREE(hindsight_goals);
FREE(hindsight_probs);
return bpx_unify(bpx_get_call_arg(4,4),p_hindsight_pairs);
}

View File

@ -0,0 +1,15 @@
#ifndef HINDSIGHT_H
#define HINDSIGHT_H
/*============================================================================*/
int pc_compute_hindsight_4(void);
/*----------------------------------------------------------------------------*/
int compute_outside_scaling_none(void);
int compute_outside_scaling_log_exp(void);
/*============================================================================*/
#endif /* HINDSIGHT_H */

View File

@ -0,0 +1,118 @@
#ifndef UP_H
#define UP_H
#include "core/bpx.h"
#include "core/xmalloc.h"
#include "core/stuff.h"
#include "core/idtable.h"
#include "core/idtable_preds.h"
#include "core/error.h"
#ifndef _MSC_VER
#include <unistd.h>
#endif
#ifdef MALLOC_TRACE
#include <mcheck.h>
#endif
/* core binary version */
#define BINARY_VERSION "20070529"
#define INIT_PROB_THRESHOLD 1e-9
#define EPS 1e-12
#define NULL_TERM ((TERM)(0)) /* reference to null */
/* IEEE 64bit double: 4.94e-324 ... 1.797e+308 (for positive) */
#define HUGE_PROB 1.0e+280
#define TINY_PROB 1.0e-300
/* Data structures for support graphs */
typedef struct ExplGraphPath *EG_PATH_PTR;
struct ExplGraphPath {
int children_len;
int sws_len;
struct ExplGraphNode **children; /* an array of pointers to children nodes */
struct SwitchInstance **sws; /* an array of pointers to switches */
double inside; /* Inside propability of this path */
double max; /* Max propability of this path (for Viterbi) */
struct ExplGraphPath *next; /* next path in a list */
};
typedef struct ViterbiEntry *V_ENT_PTR;
struct ViterbiEntry {
int goal_id;
EG_PATH_PTR path_ptr; /* path for a node */
int children_len; /* number of children in the path */
int *top_n_index; /* indices of paths in the top-N lists for children */
double max; /* max. prob of the path with the sub-paths indicated by top_n_index[] */
};
typedef struct ExplGraphNode *EG_NODE_PTR;
struct ExplGraphNode {
int id;
double inside, outside; /* inside and outside propabilities */
double max; /* max probabilities */
EG_PATH_PTR max_path; /* pointer to the path with max prob. */
V_ENT_PTR *top_n; /* top-N list (for top-N Viterbi) */
int top_n_len; /* size of top-N list (for top-N Viterbi) */
int shared; /* number of goals which call this subgoal */
EG_PATH_PTR path_ptr;
double first_outside;
char has_first_outside;
char visited; /* flag: each node needs to occur at most once */
};
typedef struct ViterbiList *V_LIST_PTR;
struct ViterbiList {
V_ENT_PTR entry;
V_LIST_PTR prev;
V_LIST_PTR next;
};
/* Data structures for switches (this data structure might have
a little bit redundancy due to `fixed' and `occ' flags) */
typedef struct SwitchInstance *SW_INS_PTR;
struct SwitchInstance {
int id;
char fixed; /* parameter is fixed or not */
char fixed_h; /* hyperparameter is fixed or not */
char occ; /* occurring in the current expl graphs or not (temporarily used) */
double inside; /* theta (parameter) in ML/MAP */
double inside_h; /* alpha (hyperparameter) in VB */
double smooth; /* pseudo count which equals alpha - 1.0 */
double smooth_prolog; /* original pseudo count passed from the Prolog part */
double pi;
double best_inside; /* best theta */
double best_inside_h; /* best alpha */
double first_expectation;
char has_first_expectation;
double total_expect; /* Sigma ru */
double best_total_expect; /* best Sigma ru */
int count; /* number of occurrences in complete data */
SW_INS_PTR next; /* connect next instance of the same switch */
};
typedef struct ObservedFactNode *ROOT;
struct ObservedFactNode {
int id;
int count; /* number of occurrences */
};
#define CTRLC_PRESSED (toam_signal_vec & INTERRUPT)
/* isfinite()/isnan() on non-C99-complient compilers */
#ifdef _MSC_VER
#include <float.h>
#define isfinite _finite
#define isnan _isnan
#endif
#ifdef LINUX
#ifndef isfinite
#define isfinite finite
#endif
#endif
#endif /* UP_H */

View File

@ -0,0 +1,147 @@
#include <stdarg.h>
#include "bprolog.h"
#include "up/up.h"
#include "core/gamma.h"
/*------------------------------------------------------------------------*/
/* mic.c (B-Prolog) */
int compare(TERM, TERM);
/*------------------------------------------------------------------------*/
int prism_printf(const char *fmt, ...)
{
va_list ap;
int rv;
va_start(ap, fmt);
rv = vfprintf(curr_out, fmt, ap);
va_end(ap);
fflush(curr_out);
return rv;
}
/*------------------------------------------------------------------------*/
int pc_mp_mode_0(void)
{
#ifdef MPI
return BP_TRUE;
#else
return BP_FALSE;
#endif
}
/*------------------------------------------------------------------------*/
int compare_sw_ins(const void *a, const void *b)
{
SW_INS_PTR sw_ins_a, sw_ins_b;
TERM msw_a, msw_b;
sw_ins_a = *(const SW_INS_PTR *)(a);
sw_ins_b = *(const SW_INS_PTR *)(b);
msw_a = prism_sw_ins_term(sw_ins_a->id);
msw_b = prism_sw_ins_term(sw_ins_b->id);
return compare(bpx_get_arg(1,msw_a), bpx_get_arg(1,msw_b));
}
/*------------------------------------------------------------------------*/
int get_term_depth(TERM t)
{
SYM_REC_PTR sym;
int i, n, d, di;
XDEREF(t);
SWITCH_OP(t, l_term_depth, { return 0; }, { return 0; }, {
if (IsNumberedVar(t)) return 0;
d = 0;
i = 0;
while (bpx_is_list(t)) {
di = get_term_depth(bpx_get_car(t)) + (++i);
d = d > di ? d : di;
t = bpx_get_cdr(t);
}
di = get_term_depth(t) + i;
d = d > di ? d : di;
return d;
}, {
sym = GET_STR_SYM_REC(t);
if (sym == float_psc) return 0;
n = GET_ARITY_STR(sym);
d = 0;
for (i = 1; i <= n; i++) {
di = get_term_depth(bpx_get_arg(i, t));
d = d > di ? d : di;
}
return d + 1;
}, { return 0; });
return 0; /* arbitrary */
}
int pc_get_term_depth_2(void)
{
return bpx_unify(bpx_build_integer(get_term_depth(bpx_get_call_arg(1,2))),
bpx_get_call_arg(2,2));
}
/*------------------------------------------------------------------------*/
int pc_lngamma_2(void)
{
double x = bpx_get_float(bpx_get_call_arg(1,2));
TERM t = bpx_build_float(lngamma(x));
return bpx_unify(bpx_get_call_arg(2,2),t);
}
/*------------------------------------------------------------------------*/
int pc_mtrace_0(void)
{
#ifdef MALLOC_TRACE
mtrace();
#endif
return BP_TRUE;
}
int pc_muntrace_0(void)
{
#ifdef MALLOC_TRACE
muntrace();
#endif
return BP_TRUE;
}
/*------------------------------------------------------------------------*/
/* effective only for Linux and Mac OS X */
void xsleep(unsigned int milliseconds)
{
#ifndef _MSC_VER
usleep(milliseconds * 1000);
#endif
}
int pc_sleep_1(void)
{
xsleep(bpx_get_integer(bpx_get_call_arg(1,1)));
return BP_TRUE;
}

View File

@ -0,0 +1,23 @@
#ifndef UTIL_H
#define UTIL_H
/*====================================================================*/
int pc_mp_mode_0(void);
int pc_get_term_depth_2(void);
int prism_printf(const char *, ...);
int compare_sw_ins(const void *, const void *);
int get_term_depth(TERM);
int pc_lngamma_2(void);
int pc_mtrace_0(void);
int pc_muntrace_0(void);
void xsleep(unsigned int);
int pc_sleep_1(void);
/*====================================================================*/
#endif /* UTIL_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
#ifndef VITERBI_H
#define VITERBI_H
int pc_compute_viterbi_5(void);
int pc_compute_n_viterbi_3(void);
int pc_compute_n_viterbi_rerank_4(void);
void compute_max(void);
void compute_n_max(int);
#endif /* VITERBI_H */

View File

@ -0,0 +1,108 @@
#
# default base directory for YAP installation
#
ROOTDIR = @prefix@
#
# where the binary should be
#
BINDIR = $(ROOTDIR)/bin
#
# where YAP should look for binary libraries
#
LIBDIR=@libdir@/Yap
#
# where YAP should look for architecture-independent Prolog libraries
#
SHAREDIR=$(ROOTDIR)/share
#
#
# You shouldn't need to change what follows.
#
INSTALL=@INSTALL@
INSTALL_DATA=@INSTALL_DATA@
INSTALL_PROGRAM=@INSTALL_PROGRAM@
srcdir=@srcdir@
YAP_EXTRAS=@YAP_EXTRAS@
# -*- Makefile -*-
##----------------------------------------------------------------------
TARGETS = prism.pl
PRISM_VERSION = 2.0
PL_CORE = $(srcdir)/core/message.pl \
$(srcdir)/core/error.pl \
$(srcdir)/core/random.pl \
$(srcdir)/core/format.pl
PL_TRANS = $(srcdir)/trans/trans.pl \
$(srcdir)/trans/dump.pl \
$(srcdir)/trans/verify.pl \
$(srcdir)/trans/bpif.pl
PL_UP = $(srcdir)/up/dynamic.pl \
$(srcdir)/up/main.pl \
$(srcdir)/up/switch.pl \
$(srcdir)/up/learn.pl \
$(srcdir)/up/prob.pl \
$(srcdir)/up/viterbi.pl \
$(srcdir)/up/hindsight.pl \
$(srcdir)/up/expl.pl \
$(srcdir)/up/sample.pl \
$(srcdir)/up/dist.pl \
$(srcdir)/up/list.pl \
$(srcdir)/up/hash.pl \
$(srcdir)/up/flags.pl \
$(srcdir)/up/util.pl \
$(srcdir)/up/bigarray.pl
PL_BAT = $(srcdir)/up/batch.pl
PL_MP = $(srcdir)/mp/mp_main.pl \
$(srcdir)/mp/mp_learn.pl
PL_BP = $(srcdir)/bp/eval.pl
PL_UP_ALL = $(PL_CORE) $(PL_UP) $(PL_TRANS) $(PL_BP) $(srcdir)/prism.yap
PL_MP_ALL = $(PL_MP)
PL_BAT_ALL = $(PL_BAT)
##----------------------------------------------------------------------
all: $(TARGETS)
install: $(TARGETS)
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/prism
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/prism/bp
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/prism/core
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/prism/mp
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/prism/trans
mkdir -p $(DESTDIR)$(SHAREDIR)/Yap/prism/up
$(INSTALL_DATA) $(srcdir)/prism.yap $(DESTDIR)$(SHAREDIR)/Yap
for p in $(PL_BAT); do $(INSTALL_DATA) $$p $(DESTDIR)$(SHAREDIR)/Yap/prism/up; done
for p in $(PL_BP); do $(INSTALL_DATA) $$p $(DESTDIR)$(SHAREDIR)/Yap/prism/bp; done
for p in $(PL_CORE); do $(INSTALL_DATA) $$p $(DESTDIR)$(SHAREDIR)/Yap/prism/core; done
for p in $(PL_MP); do $(INSTALL_DATA) $$p $(DESTDIR)$(SHAREDIR)/Yap/prism/mp; done
for p in $(PL_TRANS); do $(INSTALL_DATA) $$p $(DESTDIR)$(SHAREDIR)/Yap/prism/trans; done
for p in $(PL_UP); do $(INSTALL_DATA) $$p $(DESTDIR)$(SHAREDIR)/Yap/prism/up; done
clean:
rm -f prism.pl mpprism.pl batch.pl
prism.pl: $(PL_UP_ALL)
cat $^ > $@
mpprism.pl: $(PL_MP_ALL)
cat $^ > $@
batch.pl: $(PL_BAT_ALL)
cat $^ > $@
%.out: %.pl $(COMPILER)
sh $(COMPILER) $<
.PHONY: all install clean

View File

@ -0,0 +1,40 @@
======================= README (src/prolog) ======================
This directory contains the Prolog source files of the PRISM part,
along with a minimal set of source files from B-Prolog, required
to build the PRISM system. It is assumed that the compilation is
done on Linux, Mac OS X or Cygwin and that GNU make is used.
Makefile ... Makefile
Compile.sh ... auxiliary shell script called by Makefile
core/ ... base components of the PRISM's Prolog part
trans/ ... translator from PRISM to Prolog
up/ ... probabilistic inferences
mp/ ... parallel EM learning
bp/ ... source file(s) from B-Prolog
`up' and `mp' stands for uni-processor and multi-processor,
respectively. The source code of the First Order Compiler is
not available, and currently we have no plan for releasing it
to public.
[How to compile the Prolog part]
Since the compiled code of the C part is used for the compilation
of the Prolog part, please make compilation and installation at
$(TOP)/src/c/ (for instruction, please see README in the directory)
in advance.
Then, just type at the shell:
make
The compiled byte code will be installed (copied) into $(TOP)/bin
by typing:
make install
You can clean up the compiled byte codes by:
make clean

View File

@ -0,0 +1,388 @@
/* tracer and debugger of B-Prolog,
Neng-Fa Zhou
*/
/*********************** eval_call(Call) no trace ******************/
eval_call(Goal,_CP), var(Goal) =>
handle_exception(illegal_predicate, Goal).
/*
eval_call((A : B),CP) =>
eval_call(A,CP),
'_$cutto'(CP),
eval_call(B,CP).
eval_call((A ? B),CP) =>
eval_call(A,CP),
eval_call(B,CP).
*/
eval_call(true,_CP) => true.
eval_call((A,B),CP) =>
eval_call(A,CP),
eval_call(B,CP).
eval_call((A -> B ; C),CP) =>
eval_if_then_else(C,CP,A,B).
eval_call((A;B),CP) =>
eval_or(A,B,CP).
eval_call((A -> B),CP) =>
eval_if_then(A,B,CP).
eval_call(not(A),_CP) =>
'_$savecp'(CP1),
eval_not(A,CP1).
eval_call(\+(A),_CP) =>
'_$savecp'(CP1),
eval_not(A,CP1).
eval_call('!',CP) =>
'_$cutto'(CP).
eval_call(call(X),_CP) =>
'_$savecp'(CP1),
eval_call(X,CP1).
eval_call(Xs,_CP), [_|_]<=Xs =>
consult_list(Xs).
eval_call(Goal,_CP), b_IS_CONSULTED_c(Goal) =>
'_$savecp'(CP1),
clause(Goal,Body),
eval_call(Body,CP1).
eval_call(Goal,_CP) =>
call(Goal).
%% Prism-specific part
eval_call('_$initialize_var'(_Vars),_CP) => true.
eval_call('_$if_then_else'(C,A,B),CP) => eval_call((C->A;B),CP).
eval_if_then_else(_C,CP,A,B) ?=>
'_$savecp'(CP1),
eval_call(A,CP1),!,
eval_call(B,CP).
eval_if_then_else(C,CP,_A,_B) =>
eval_call(C,CP).
eval_or(A,_B,CP) ?=>
eval_call(A,CP).
eval_or(_A,B,CP) =>
eval_call(B,CP).
eval_if_then(A,B,CP) =>
'_$savecp'(CP1),
eval_call(A,CP1),!,
eval_call(B,CP).
eval_not(A,CP) ?=>
eval_call(A,CP),!,
fail.
eval_not(_A,_CP) => true.
/*********************** eval_call(Call) ******************/
$trace_call(Call), b_IS_DEBUG_MODE =>
'_$savecp'(CP),
eval_debug_call(Call,0,CP).
$trace_call(Call) =>
'_$savecp'(CP),
eval_call(Call,CP).
eval_debug_call(Goal,_Depth,_CP), var(Goal) =>
handle_exception(illegal_predicate, Goal).
/*
eval_debug_call((A : B),Depth,CP) =>
eval_debug_call(A,Depth,CP),
'_$cutto'(CP),
eval_debug_call(B,Depth,CP).
eval_debug_call((A ? B),Depth,CP) =>
eval_debug_call(A,Depth,CP),
eval_debug_call(B,Depth,CP).
*/
eval_debug_call((A,B),Depth,CP) =>
eval_debug_call(A,Depth,CP),
eval_debug_call(B,Depth,CP).
eval_debug_call((A -> B ; C),Depth,CP) =>
eval_debug_if_then_else(C,Depth,CP,A,B).
eval_debug_call((A;B),Depth,CP) =>
eval_debug_or(A,B,Depth,CP).
eval_debug_call((A -> B),Depth,CP) =>
eval_debug_if_then(A,B,Depth,CP).
eval_debug_call(not(A),Depth,_CP) =>
'_$savecp'(CP1),
eval_debug_not(A,Depth,CP1).
eval_debug_call(\+(A),Depth,_CP) =>
'_$savecp'(CP1),
eval_debug_not(A,Depth,CP1).
eval_debug_call('!',_Depth,CP) =>
'_$cutto'(CP).
eval_debug_call('_$cutto'(X),_Depth,_CP) =>
'_$cutto'(X).
eval_debug_call($trace_call(X),_Depth,_CP) =>
$trace_call(X).
eval_debug_call(call(X),Depth,_CP) =>
'_$savecp'(CP1),
eval_debug_call(X,Depth,CP1).
eval_debug_call($query(X),Depth,CP) =>
eval_debug_call(X,Depth,CP).
eval_debug_call(true,_Depth,_CP) => true.
eval_debug_call($internal_match(X,Y),_Depth,_CP) =>
nonvar(Y),X=Y.
eval_debug_call(trace,_Depth,_CP) => trace.
eval_debug_call(op(Prec,Fix,Op),_Depth,_CP) =>
op(Prec,Fix,Op).
eval_debug_call(dynamic(Calls),_Depth,_CP) =>
dynamic(Calls).
eval_debug_call(nospy,_Depth,_CP) =>
nospy.
eval_debug_call(nospy(X),_Depth,_CP) =>
nospy(X).
eval_debug_call(notrace,_Depth,_CP) =>
notrace.
eval_debug_call(spy(S),_Depth,_CP) =>
spy(S).
eval_debug_call(nospy(S),_Depth,_CP) =>
nospy(S).
eval_debug_call(Xs,_Depth,_CP), [_|_]<=Xs =>
consult_list(Xs).
eval_debug_call(Goal,Depth,_CP) =>
c_SAVE_AR(AR),
c_next_global_call_number(CallNo),
$eval_and_monitor_call(Goal,Depth,CallNo,AR).
%% Prism-specific part
eval_debug_call(Goal,_Depth,_CP), var(Goal) =>
handle_exception(illegal_predicate, Goal).
eval_debug_call('_$initialize_var'(_Vars),_Depth,_CP) => true.
eval_debug_call('_$if_then_else'(C,A,B),Depth,CP) =>
eval_debug_call((C->A;B),Depth,CP).
eval_debug_call(msw(Sw,V),Depth,CP) =>
$pp_require_ground(Sw,$msg(0101),msw/2),
c_SAVE_AR(AR),
c_next_global_call_number(CallNo),
$prism_sample_msw(Sw,V,Depth,CP,CallNo,AR).
eval_debug_if_then_else(_C,Depth,CP,A,B) ?=>
'_$savecp'(NewCP),
eval_debug_call(A,Depth,NewCP),!,
eval_debug_call(B,Depth,CP).
eval_debug_if_then_else(C,Depth,CP,_A,_B) =>
eval_debug_call(C,Depth,CP).
eval_debug_or(A,_B,Depth,CP) ?=>
eval_debug_call(A,Depth,CP).
eval_debug_or(_A,B,Depth,CP) =>
eval_debug_call(B,Depth,CP).
eval_debug_if_then(A,B,Depth,CP) =>
'_$savecp'(NewCP),
eval_debug_call(A,Depth,NewCP),!,
eval_debug_call(B,Depth,CP).
eval_debug_not(A,Depth,CP) ?=>
eval_debug_call(A,Depth,CP),!,
fail.
eval_debug_not(_A,_Depth,_CP) => true.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
$eval_and_monitor_call(Call,Depth,CallNo,AR) ?=>
c_get_dg_flag(Flag),
$print_call(Flag,' Call: ',Call,Depth,CallNo,AR),
Depth1 is 1+Depth,
$eval_single_call(Call,Depth1),
$switch_skip_off(AR),
$eval_call_exit(Call,Depth,CallNo,AR).
$eval_and_monitor_call(Call,Depth,CallNo,AR) =>
c_get_dg_flag(Flag),
$print_call(Flag,' Fail: ',Call,Depth,CallNo,AR),
fail.
$eval_call_exit(Call,Depth,CallNo,AR) ?=>
c_get_dg_flag(Flag),
$print_call(Flag,' Exit: ',Call,Depth,CallNo,AR).
$eval_call_exit(Call,Depth,CallNo,AR) =>
c_get_dg_flag(Flag),
$print_call(Flag,' Redo: ',Call,Depth,CallNo,AR),
fail.
$eval_single_call(Call,Depth), b_IS_CONSULTED_c(Call) =>
'_$savecp'(CP),
clause(Call,Body),
eval_debug_call(Body,Depth,CP).
$eval_single_call(Call,_Depth) =>
call(Call).
/*
---------------------------------------------
|repeat | skip | leap | creep | spy | debug |
---------------------------------------------
#define DG_FLAG_DEBUG 0x1
#define DG_FLAG_SPY 0x2
#define DG_FLAG_C 0x4
#define DG_FLAG_L 0x8
#define DG_FLAG_S 0x10
#define DG_FLAG_R 0x20
*/
%% Prism-specific part
$print_call(_F,_T,$pu_values(_,_), _D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_is_prob_pred(_,_), _D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_is_tabled_pred(_,_), _D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_parameters(_,_,_), _D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_hyperparameters(_,_,_,_),_D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_expectations(_,_,_), _D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_hyperexpectations(_,_,_),_D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_fixed_parameters(_), _D,_CNo,_AR) => true.
$print_call(_F,_T,$pd_fixed_hyperparameters(_),_D,_CNo,_AR) => true.
$print_call(_Flag,_Type,write_call(_), _Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,write_call(_,_),_Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,(?? _), _Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,(??* _), _Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,(??> _), _Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,(??< _), _Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,(??+ _), _Depth,_CallNo,_AR) => true.
$print_call(_Flag,_Type,(??- _), _Depth,_CallNo,_AR) => true.
$print_call(Flag,Type,$prism_expl_msw(I,V,_SwId),Depth,CallNo,AR) =>
$print_call(Flag,Type,msw(I,V),Depth,CallNo,AR).
$print_call(Flag,Type,Call,Depth,CallNo,_AR),
Flag /\ 2'100000 =:= 2'100000 => %repeat
'$readl_userio'(I,O),
tab(2*Depth),write(Type),write('('),write(CallNo),write(') '),
print(Call),nl,
'$readl_resetio'(I,O).
$print_call(Flag,Type,Call,Depth,CallNo,AR),
Flag /\ 2'1000 =:= 2'1000 ?=> %leap
c_is_spy_point(Call),!,
$real_print_call(Type,Call,Depth,CallNo),
$next_monitor_instruction(Type,Call,Depth,CallNo,AR).
$print_call(Flag,Type,Call,Depth,CallNo,AR),
Flag /\ 2'100 =:= 2'100 => %creap
$real_print_call(Type,Call,Depth,CallNo),
$next_monitor_instruction(Type,Call,Depth,CallNo,AR).
$print_call(Flag,Type,Call,Depth,CallNo,AR),
Flag /\ 2'10000 =:= 2'10000 ?=> %skip
c_is_skip_ar(AR),!,
$real_print_call(Type,Call,Depth,CallNo),
$next_monitor_instruction(Type,Call,Depth,CallNo,AR).
$print_call(_Flag,_Type,_Call,_Depth,_AR,_CallNo) => true.
$real_print_call(Type,Call,Depth,CallNo):-
'$readl_userio'(I,O),
tab(2*Depth),write(Type),write('('),write(CallNo),write(') '),
print(Call),writename(' ?'),
'$readl_resetio'(I,O).
$next_monitor_instruction(Type,Call,Depth,CallNo,AR):-
$get_monitor_instruction(Inst),
$process_monitor_instruction(Type,Call,Depth,CallNo,AR,Inst).
/*
#define DG_FLAG_DEBUG 0x1
#define DG_FLAG_SPY 0x2
#define DG_FLAG_C 0x4
#define DG_FLAG_L 0x8
#define DG_FLAG_S 0x10
#define DG_FLAG_R 0x20
*/
$process_monitor_instruction(_Type,_Call,_Depth,_CallNo,_AR,0'a) =>
abort. % abort
$process_monitor_instruction(_Type,_Call,_Depth,_CallNo,_AR,0'r) =>
c_set_dg_flag(2'100000). % repeat
$process_monitor_instruction(_Type,_Call,_Depth,_CallNo,_AR,0'c) =>
c_set_dg_flag(2'100). % creep
$process_monitor_instruction(_Type,_Call,_Depth,_CallNo,_AR,10) =>
c_set_dg_flag(2'100). % return
$process_monitor_instruction(_Type,_Call,_Depth,_CallNo,_AR,0'n) =>
c_get_dg_flag(Flag),
NewFlag is Flag/\2'11,
c_init_dg_flag(NewFlag). % no trace
$process_monitor_instruction(_Type,_Call,_Depth,_CallNo,_AR,0'l) =>
c_set_dg_flag(2'1000). % leap
$process_monitor_instruction(Type,Call,Depth,CallNo,AR,0's) =>
((Type==' Fail: ';Type==' Exit: ')->
write(user_output,'Option not applicable'),nl(user_output),
$real_print_call(Type,Call,Depth,CallNo),
$next_monitor_instruction(Type,Call,Depth,CallNo,AR);
c_set_dg_flag(2'10000),
c_set_skip_ar(AR)). % skip
$process_monitor_instruction(Type,Call,Depth,CallNo,AR,_) => % other ?
$print_help(Type),
$real_print_call(Type,Call,Depth,CallNo),
$next_monitor_instruction(Type,Call,Depth,CallNo,AR).
$print_help(_Type):-
write(user,' a abort'),nl(user),
write(user,' ? help'),nl(user),
write(user,' h help'),nl(user),
write(user,'<cr> creep'),nl(user),
write(user,' c creep'),nl(user),
write(user,' h help'),nl(user),
write(user,' l leap'),nl(user),
write(user,' n nodebug'),nl(user),
write(user,' r repeat creep'),nl(user),
write(user,' s skip'),nl(user),nl(user).
$get_monitor_instruction(Command):-
'$readl_userio'(I,O),
get0(Command),
$get_until_return(Command),
'$readl_resetio'(I,O).
$get_until_return(10) => true.
$get_until_return(_Command) =>
get0(X),
$get_until_return(X).
$switch_skip_off(AR):-
c_is_skip_ar(AR),!,
c_set_skip_ar(0),
c_set_dg_flag(2'100). % creep
$switch_skip_off(_) => true.
/**************trace/1 spy/1******************/
/* vsc: not supported in YAP yet
trace =>
c_init_dg_flag(1).
spy(S), var(S) =>
c_get_spy_points(S).
spy([X|Xs]) =>
spy(X),
spy(Xs).
spy([]) => true.
spy(Pred), F/N<=Pred, atom(F),integer(N) =>
(c_CURRENT_PREDICATE(F,N)->
'$readl_userio'(I,O),
write('Spy point '), write(Pred), write(' has been set.'),nl,
'$readl_resetio'(I,O),
c_add_spy_point(F,N);
handle_exception(predicate_not_exist, Pred)).
spy(F), atom(F) =>
$search_preds(F,25,[],X),
(X\==[]->spy(X); handle_exception(predicate_not_exist, F)).
spy(F):-
handle_exception(illegal_argument, spy(F)).
$search_preds(_X,N,P0,P), N<0 =>
P=P0.
$search_preds(X,N,P0,P):-
c_CURRENT_PREDICATE(X,N),!,
N1 is N-1,
$search_preds(X,N1,[X/N|P0],P).
$search_preds(X,N,P0,P) =>
N1 is N-1,
$search_preds(X,N1,P0,P).
notrace =>
c_init_dg_flag(0),
nospy.
nospy([X|Xs]) =>
nospy(X),
nospy(Xs).
nospy([]) => true.
nospy(F/N), atom(F), integer(N) =>
c_remove_spy_point(F,N).
nospy(F), atom(F) =>
$search_preds(F,25,[],X),
nospy(X).
nospy(F) =>
handle_exception(illegal_predicate, nospy(F)).
nospy:-
c_remove_spy_points.
trace(Call) =>
$trace_call(Call).
*/

Some files were not shown because too many files have changed in this diff Show More