wolffd@0: function CPD = noisyor_CPD(bnet, self, leak_inhibit, inhibit) wolffd@0: % NOISYOR_CPD Make a noisy-or CPD wolffd@0: % CPD = NOISYOR_CPD(BNET, NODE_NUM, LEAK_INHIBIT, INHIBIT) wolffd@0: % wolffd@0: % A noisy-or node turns on if any of its parents are on, provided they are not inhibited. wolffd@0: % The prob. that the i'th parent gets inhibited (flipped from 1 to 0) is inhibit(i). wolffd@0: % The prob that the leak node (a dummy parent that is always on) gets inhibit is leak_inhibit. wolffd@0: % These params default to random values if omitted. wolffd@0: % wolffd@0: % Example: suppose C has parents A and B, and the wolffd@0: % link of A->C fails with prob pA and the link B->C fails with pB. wolffd@0: % Then the noisy-OR gate defines the following distribution wolffd@0: % wolffd@0: % A B P(C=0) wolffd@0: % 0 0 1.0 wolffd@0: % 1 0 pA wolffd@0: % 0 1 pB wolffd@0: % 1 1 pA * PB wolffd@0: % wolffd@0: % Currently, learning is not supported for noisy-or nodes wolffd@0: % (since the M step is somewhat complicated). wolffd@0: % wolffd@0: % For simple generalizations of the noisy-OR model, see e.g., wolffd@0: % - Srinivas, "A generalization of the noisy-OR model", UAI 93 wolffd@0: % - Meek and Heckerman, "Learning Causal interaction models", UAI 97. wolffd@0: wolffd@0: wolffd@0: wolffd@0: if nargin==0 wolffd@0: % This occurs if we are trying to load an object from a file. wolffd@0: CPD = init_fields; wolffd@0: CPD = class(CPD, 'noisyor_CPD', discrete_CPD(1, [])); wolffd@0: return; wolffd@0: elseif isa(bnet, 'noisyor_CPD') wolffd@0: % This might occur if we are copying an object. wolffd@0: CPD = bnet; wolffd@0: return; wolffd@0: end wolffd@0: CPD = init_fields; wolffd@0: wolffd@0: wolffd@0: ps = parents(bnet.dag, self); wolffd@0: fam = [ps self]; wolffd@0: ns = bnet.node_sizes; wolffd@0: assert(all(ns(fam)==2)); wolffd@0: assert(isempty(myintersect(fam, bnet.cnodes))); wolffd@0: wolffd@0: if nargin < 3, leak_inhibit = rand(1, 1); end wolffd@0: if nargin < 4, inhibit = rand(1, length(ps)); end wolffd@0: wolffd@0: CPD.self = self; wolffd@0: CPD.inhibit = inhibit; wolffd@0: CPD.leak_inhibit = leak_inhibit; wolffd@0: wolffd@0: wolffd@0: % For BIC wolffd@0: CPD.nparams = 0; wolffd@0: CPD.nsamples = 0; wolffd@0: wolffd@0: CPD.CPT = []; % cached copy, to speed up CPD_to_CPT wolffd@0: wolffd@0: clamped = 1; wolffd@0: CPD = class(CPD, 'noisyor_CPD', discrete_CPD(clamped, ns([ps self]))); wolffd@0: wolffd@0: wolffd@0: wolffd@0: %%%%%%%%%%% wolffd@0: wolffd@0: function CPD = init_fields() wolffd@0: % This ensures we define the fields in the same order wolffd@0: % no matter whether we load an object from a file, wolffd@0: % or create it from scratch. (Matlab requires this.) wolffd@0: wolffd@0: CPD.self = []; wolffd@0: CPD.inhibit = []; wolffd@0: CPD.leak_inhibit = []; wolffd@0: CPD.nparams = []; wolffd@0: CPD.nsamples = []; wolffd@0: CPD.CPT = [];