wolffd@0
|
1 function fg = mk_fgraph(G, node_sizes, factors, varargin)
|
wolffd@0
|
2 % MK_FGRAPH Make a factor graph
|
wolffd@0
|
3 % fg = mk_fgraph(G, node_sizes, factors, ...)
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % A factor graph is a bipartite graph, with one side containing variables,
|
wolffd@0
|
6 % and the other containing functions of (subsets of) these variables.
|
wolffd@0
|
7 % For details, see "Factor Graphs and the Sum-Product Algorithm",
|
wolffd@0
|
8 % F. Kschischang and B. Frey and H-A. Loeliger,
|
wolffd@0
|
9 % IEEE Trans. Info. Theory, 2001
|
wolffd@0
|
10 %
|
wolffd@0
|
11 % G(i,j) = 1 if there is an arc from variable i to factor j
|
wolffd@0
|
12 %
|
wolffd@0
|
13 % node_sizes(i) is the number of values node i can take on,
|
wolffd@0
|
14 % or the length of node i if i is a continuous-valued vector.
|
wolffd@0
|
15 %
|
wolffd@0
|
16 % 'factors' is the list of factors (kernel functions)
|
wolffd@0
|
17 %
|
wolffd@0
|
18 % The list below gives optional arguments [default value in brackets].
|
wolffd@0
|
19 %
|
wolffd@0
|
20 % equiv_class - equiv_class(i)=j means factor node i gets its params from factors{j} [1:F]
|
wolffd@0
|
21 % discrete - the list of nodes which are discrete random variables [1:N]
|
wolffd@0
|
22 %
|
wolffd@0
|
23 % e.g., fg = mk_fgraph(G, [2 2], {bnet.CPD{1},bnet.CPD{2}}, 'discrete', [1 2])
|
wolffd@0
|
24
|
wolffd@0
|
25 fg.G = G;
|
wolffd@0
|
26 fg.node_sizes = node_sizes;
|
wolffd@0
|
27 fg.factors = factors;
|
wolffd@0
|
28 [fg.nvars fg.nfactors] = size(G);
|
wolffd@0
|
29
|
wolffd@0
|
30 % default values for parameters
|
wolffd@0
|
31 fg.equiv_class = 1:fg.nfactors;
|
wolffd@0
|
32 fg.dnodes = 1:fg.nvars;
|
wolffd@0
|
33
|
wolffd@0
|
34 if nargin >= 4
|
wolffd@0
|
35 args = varargin;
|
wolffd@0
|
36 nargs = length(args);
|
wolffd@0
|
37 for i=1:2:nargs
|
wolffd@0
|
38 switch args{i},
|
wolffd@0
|
39 case 'equiv_class', fg.equiv_class = args{i+1};
|
wolffd@0
|
40 case 'discrete', fg.dnodes = args{i+1};
|
wolffd@0
|
41 otherwise,
|
wolffd@0
|
42 error(['invalid argument name ' args{i}]);
|
wolffd@0
|
43 end
|
wolffd@0
|
44 end
|
wolffd@0
|
45 end
|
wolffd@0
|
46
|
wolffd@0
|
47 % so that determine_pot_type will work...
|
wolffd@0
|
48 fg.utility_nodes = [];
|
wolffd@0
|
49 %fg.decision_nodes = [];
|
wolffd@0
|
50 %fg.chance_nodes = fg.nvars;
|
wolffd@0
|
51
|
wolffd@0
|
52 fg.dom = cell(1, fg.nfactors);
|
wolffd@0
|
53 for f=1:fg.nfactors
|
wolffd@0
|
54 fg.dom{f} = find(G(:,f));
|
wolffd@0
|
55 end
|
wolffd@0
|
56 fg.dep = cell(1, fg.nvars);
|
wolffd@0
|
57 for x=1:fg.nvars
|
wolffd@0
|
58 fg.dep{x} = find(G(x,:));
|
wolffd@0
|
59 end
|
wolffd@0
|
60 fg.cnodes = mysetdiff(1:fg.nvars, fg.dnodes);
|