wolffd@0: function CPD = update_tied_ess(CPD, domain, engine, evidence, ns, cnodes) wolffd@0: wolffd@0: if ~adjustable_CPD(CPD), return; end wolffd@0: nCPDs = size(domain, 2); wolffd@0: fmarginal = cell(1, nCPDs); wolffd@0: for l=1:nCPDs wolffd@0: fmarginal{l} = marginal_family(engine, nodes(l)); wolffd@0: end wolffd@0: wolffd@0: [ss cpsz dpsz] = size(CPD.weights); wolffd@0: if const_evidence_pattern(engine) wolffd@0: dom = domain(:,1); wolffd@0: dnodes = mysetdiff(1:length(ns), cnodes); wolffd@0: ddom = myintersect(dom, dnodes); wolffd@0: cdom = myintersect(dom, cnodes); wolffd@0: odom = dom(~isemptycell(evidence(dom))); wolffd@0: hdom = dom(isemptycell(evidence(dom))); wolffd@0: % If all hidden nodes are discrete and all cts nodes are observed wolffd@0: % (e.g., HMM with Gaussian output) wolffd@0: % we can add the observed evidence in parallel wolffd@0: if mysubset(ddom, hdom) & mysubset(cdom, odom) wolffd@0: [mu, Sigma, T] = add_cts_ev_to_marginals(fmarginal, evidence, ns, cnodes); wolffd@0: else wolffd@0: mu = zeros(ss, dpsz, nCPDs); wolffd@0: Sigma = zeros(ss, ss, dpsz, nCPDs); wolffd@0: T = zeros(dpsz, nCPDs); wolffd@0: for l=1:nCPDs wolffd@0: [mu(:,:,l), Sigma(:,:,:,l), T(:,l)] = add_ev_to_marginals(fmarginal{l}, evidence, ns, cnodes); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: CPD.nsamples = CPD.nsamples + nCPDs; wolffd@0: wolffd@0: wolffd@0: if dpsz == 1 % no discrete parents wolffd@0: w = 1; wolffd@0: else wolffd@0: w = fullm.T(:); wolffd@0: end wolffd@0: CPD.Wsum = CPD.Wsum + w; wolffd@0: % Let X be the cts parent (if any), Y be the cts child (self). wolffd@0: xi = 1:cpsz; wolffd@0: yi = (cpsz+1):(cpsz+ss); wolffd@0: for i=1:dpsz wolffd@0: muY = fullm.mu(yi, i); wolffd@0: SYY = fullm.Sigma(yi, yi, i); wolffd@0: CPD.WYsum(:,i) = CPD.WYsum(:,i) + w(i)*muY; wolffd@0: CPD.WYYsum(:,:,i) = CPD.WYYsum(:,:,i) + w(i)*(SYY + muY*muY'); % E[X Y] = Cov[X,Y] + E[X] E[Y] wolffd@0: if cpsz > 0 wolffd@0: muX = fullm.mu(xi, i); wolffd@0: SXX = fullm.Sigma(xi, xi, i); wolffd@0: SXY = fullm.Sigma(xi, yi, i); wolffd@0: CPD.WXsum(:,i) = CPD.WXsum(:,i) + w(i)*muX; wolffd@0: CPD.WXYsum(:,:,i) = CPD.WXYsum(:,:,i) + w(i)*(SXY + muX*muY'); wolffd@0: CPD.WXXsum(:,:,i) = CPD.WXXsum(:,:,i) + w(i)*(SXX + muX*muX'); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: %%%%%%%%%%%%% wolffd@0: wolffd@0: function fullm = add_evidence_to_marginal(fmarginal, evidence, ns, cnodes) wolffd@0: wolffd@0: wolffd@0: dom = fmarginal.domain; wolffd@0: wolffd@0: % Find out which values of the discrete parents (if any) are compatible with wolffd@0: % the discrete evidence (if any). wolffd@0: dnodes = mysetdiff(1:length(ns), cnodes); wolffd@0: ddom = myintersect(dom, dnodes); wolffd@0: cdom = myintersect(dom, cnodes); wolffd@0: odom = dom(~isemptycell(evidence(dom))); wolffd@0: hdom = dom(isemptycell(evidence(dom))); wolffd@0: wolffd@0: dobs = myintersect(ddom, odom); wolffd@0: dvals = cat(1, evidence{dobs}); wolffd@0: ens = ns; % effective node sizes wolffd@0: ens(dobs) = 1; wolffd@0: S = prod(ens(ddom)); wolffd@0: subs = ind2subv(ens(ddom), 1:S); wolffd@0: mask = find_equiv_posns(dobs, ddom); wolffd@0: subs(mask) = dvals; wolffd@0: supportedQs = subv2ind(ns(ddom), subs); wolffd@0: wolffd@0: if isempty(ddom) wolffd@0: Qarity = 1; wolffd@0: else wolffd@0: Qarity = prod(ns(ddom)); wolffd@0: end wolffd@0: fullm.T = zeros(Qarity, 1); wolffd@0: fullm.T(supportedQs) = fmarginal.T(:); wolffd@0: wolffd@0: % Now put the hidden cts parts into their right blocks, wolffd@0: % leaving the observed cts parts as 0. wolffd@0: cobs = myintersect(cdom, odom); wolffd@0: chid = myintersect(cdom, hdom); wolffd@0: cvals = cat(1, evidence{cobs}); wolffd@0: n = sum(ns(cdom)); wolffd@0: fullm.mu = zeros(n,Qarity); wolffd@0: fullm.Sigma = zeros(n,n,Qarity); wolffd@0: wolffd@0: if ~isempty(chid) wolffd@0: chid_blocks = block(find_equiv_posns(chid, cdom), ns(cdom)); wolffd@0: end wolffd@0: if ~isempty(cobs) wolffd@0: cobs_blocks = block(find_equiv_posns(cobs, cdom), ns(cdom)); wolffd@0: end wolffd@0: wolffd@0: for i=1:length(supportedQs) wolffd@0: Q = supportedQs(i); wolffd@0: if ~isempty(chid) wolffd@0: fullm.mu(chid_blocks, Q) = fmarginal.mu(:, i); wolffd@0: fullm.Sigma(chid_blocks, chid_blocks, Q) = fmarginal.Sigma(:,:,i); wolffd@0: end wolffd@0: if ~isempty(cobs) wolffd@0: fullm.mu(cobs_blocks, Q) = cvals(:); wolffd@0: end wolffd@0: end