To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / _FullBNT / BNT / CPDs / @boolean_CPD / boolean_CPD.m @ 8:b5b38998ef3b
History | View | Annotate | Download (4.74 KB)
| 1 |
function CPD = boolean_CPD(bnet, self, ftype, fname, pfail) |
|---|---|
| 2 |
% BOOLEAN_CPD Make a tabular CPD representing a (noisy) boolean function |
| 3 |
% |
| 4 |
% CPD = boolean_cpd(bnet, self, 'inline', f) uses the inline function f |
| 5 |
% to specify the CPT. |
| 6 |
% e.g., suppose X4 = X2 AND (NOT X3). Then we can write |
| 7 |
% bnet.CPD{4} = boolean_CPD(bnet, 4, 'inline', inline('(x(1) & ~x(2)'));
|
| 8 |
% Note that x(1) refers pvals(1) = X2, and x(2) refers to pvals(2)=X3. |
| 9 |
% |
| 10 |
% CPD = boolean_cpd(bnet, self, 'named', f) assumes f is a function name. |
| 11 |
% f can be built-in to matlab, or a file. |
| 12 |
% e.g., If X4 = X2 AND X3, we can write |
| 13 |
% bnet.CPD{4} = boolean_CPD(bnet, 4, 'named', 'and');
|
| 14 |
% e.g., If X4 = X2 OR X3, we can write |
| 15 |
% bnet.CPD{4} = boolean_CPD(bnet, 4, 'named', 'any');
|
| 16 |
% |
| 17 |
% CPD = boolean_cpd(bnet, self, 'rnd') makes a random non-redundant bool fn. |
| 18 |
% |
| 19 |
% CPD = boolean_CPD(bnet, self, 'inline'/'named', f, pfail) |
| 20 |
% will put probability mass 1-pfail on f(parents), and put pfail on the other value. |
| 21 |
% This is useful for simulating noisy boolean functions. |
| 22 |
% If pfail is omitted, it is set to 0. |
| 23 |
% (Note that adding noise to a random (non-redundant) boolean function just creates a different |
| 24 |
% (potentially redundant) random boolean function.) |
| 25 |
% |
| 26 |
% Note: This cannot be used to simulate a noisy-OR gate. |
| 27 |
% Example: suppose C has parents A and B, and the |
| 28 |
% link of A->C fails with prob pA and the link B->C fails with pB. |
| 29 |
% Then the noisy-OR gate defines the following distribution |
| 30 |
% |
| 31 |
% A B P(C=0) |
| 32 |
% 0 0 1.0 |
| 33 |
% 1 0 pA |
| 34 |
% 0 1 pB |
| 35 |
% 1 1 pA * PB |
| 36 |
% |
| 37 |
% By contrast, boolean_CPD(bnet, C, 'any', p) would define |
| 38 |
% |
| 39 |
% A B P(C=0) |
| 40 |
% 0 0 1-p |
| 41 |
% 1 0 p |
| 42 |
% 0 1 p |
| 43 |
% 1 1 p |
| 44 |
|
| 45 |
|
| 46 |
if nargin==0 |
| 47 |
% This occurs if we are trying to load an object from a file. |
| 48 |
CPD = tabular_CPD(bnet, self); |
| 49 |
return; |
| 50 |
elseif isa(bnet, 'boolean_CPD') |
| 51 |
% This might occur if we are copying an object. |
| 52 |
CPD = bnet; |
| 53 |
return; |
| 54 |
end |
| 55 |
|
| 56 |
if nargin < 5, pfail = 0; end |
| 57 |
|
| 58 |
ps = parents(bnet.dag, self); |
| 59 |
ns = bnet.node_sizes; |
| 60 |
psizes = ns(ps); |
| 61 |
self_size = ns(self); |
| 62 |
|
| 63 |
psucc = 1-pfail; |
| 64 |
|
| 65 |
k = length(ps); |
| 66 |
switch ftype |
| 67 |
case 'inline', f = eval_bool_fn(fname, k); |
| 68 |
case 'named', f = eval_bool_fn(fname, k); |
| 69 |
case 'rnd', f = mk_rnd_bool_fn(k); |
| 70 |
otherwise, error(['unknown function type ' ftype]); |
| 71 |
end |
| 72 |
|
| 73 |
CPT = zeros(prod(psizes), self_size); |
| 74 |
ndx = find(f==0); |
| 75 |
CPT(ndx, 1) = psucc; |
| 76 |
CPT(ndx, 2) = pfail; |
| 77 |
ndx = find(f==1); |
| 78 |
CPT(ndx, 2) = psucc; |
| 79 |
CPT(ndx, 1) = pfail; |
| 80 |
if k > 0 |
| 81 |
CPT = reshape(CPT, [psizes self_size]); |
| 82 |
end |
| 83 |
|
| 84 |
clamp = 1; |
| 85 |
CPD = tabular_CPD(bnet, self, CPT, [], clamp); |
| 86 |
|
| 87 |
|
| 88 |
|
| 89 |
%%%%%%%%%%%% |
| 90 |
|
| 91 |
function f = eval_bool_fn(fname, n) |
| 92 |
% EVAL_BOOL_FN Evaluate a boolean function on all bit vectors of length n |
| 93 |
% f = eval_bool_fn(fname, n) |
| 94 |
% |
| 95 |
% e.g. f = eval_bool_fn(inline('x(1) & x(3)'), 3)
|
| 96 |
% returns 0 0 0 0 0 1 0 1 |
| 97 |
|
| 98 |
ns = 2*ones(1, n); |
| 99 |
f = zeros(1, 2^n); |
| 100 |
bits = ind2subv(ns, 1:2^n); |
| 101 |
for i=1:2^n |
| 102 |
f(i) = feval(fname, bits(i,:)-1); |
| 103 |
end |
| 104 |
|
| 105 |
%%%%%%%%%%%%%%% |
| 106 |
|
| 107 |
function f = mk_rnd_bool_fn(n) |
| 108 |
% MK_RND_BOOL_FN Make a random bit vector of length n that encodes a non-redundant boolean function |
| 109 |
% f = mk_rnd_bool_fn(n) |
| 110 |
|
| 111 |
red = 1; |
| 112 |
while red |
| 113 |
f = sample_discrete([0.5 0.5], 2^n, 1)-1; |
| 114 |
red = redundant_bool_fn(f); |
| 115 |
end |
| 116 |
|
| 117 |
%%%%%%%% |
| 118 |
|
| 119 |
|
| 120 |
function red = redundant_bool_fn(f) |
| 121 |
% REDUNDANT_BOOL_FN Does a boolean function depend on all its input values? |
| 122 |
% r = redundant_bool_fn(f) |
| 123 |
% |
| 124 |
% f is a vector of length 2^n, representing the output for each bit vector. |
| 125 |
% An input is redundant if there is no assignment to the other bits |
| 126 |
% which changes the output e.g., input 1 is redundant if u(2:n) s.t., |
| 127 |
% f([0 u(2:n)]) <> f([1 u(2:n)]). |
| 128 |
% A function is redundant it it has any redundant inputs. |
| 129 |
|
| 130 |
n = log2(length(f)); |
| 131 |
ns = 2*ones(1,n); |
| 132 |
red = 0; |
| 133 |
for i=1:n |
| 134 |
ens = ns; |
| 135 |
ens(i) = 1; |
| 136 |
U = ind2subv(ens, 1:2^(n-1)); |
| 137 |
U(:,i) = 1; |
| 138 |
f1 = f(subv2ind(ns, U)); |
| 139 |
U(:,i) = 2; |
| 140 |
f2 = f(subv2ind(ns, U)); |
| 141 |
if isequal(f1, f2) |
| 142 |
red = 1; |
| 143 |
return; |
| 144 |
end |
| 145 |
end |
| 146 |
|
| 147 |
|
| 148 |
%%%%%%%%%% |
| 149 |
|
| 150 |
function [b, iter] = rnd_truth_table(N) |
| 151 |
% RND_TRUTH_TABLE Construct the output of a random truth table s.t. each input is non-redundant |
| 152 |
% b = rnd_truth_table(N) |
| 153 |
% |
| 154 |
% N is the number of inputs. |
| 155 |
% b is a random bit string of length N, representing the output of the truth table. |
| 156 |
% Non-redundant means that, for each input position k, |
| 157 |
% there are at least two bit patterns, u and v, that differ only in the k'th position, |
| 158 |
% s.t., f(u) ~= f(v), where f is the function represented by b. |
| 159 |
% We use rejection sampling to ensure non-redundancy. |
| 160 |
% |
| 161 |
% Example: b = [0 0 0 1 0 0 0 1] is indep of 3rd input (AND of inputs 1 and 2) |
| 162 |
|
| 163 |
bits = ind2subv(2*ones(1,N), 1:2^N)-1; |
| 164 |
redundant = 1; |
| 165 |
iter = 0; |
| 166 |
while redundant & (iter < 4) |
| 167 |
iter = iter + 1; |
| 168 |
b = sample_discrete([0.5 0.5], 1, 2^N)-1; |
| 169 |
redundant = 0; |
| 170 |
for i=1:N |
| 171 |
on = find(bits(:,i)==1); |
| 172 |
off = find(bits(:,i)==0); |
| 173 |
if isequal(b(on), b(off)) |
| 174 |
redundant = 1; |
| 175 |
break; |
| 176 |
end |
| 177 |
end |
| 178 |
end |
| 179 |
|