wolffd@0: function CPD = gmux_CPD(bnet, self, varargin) wolffd@0: % GMUX_CPD Make a Gaussian multiplexer node wolffd@0: % wolffd@0: % CPD = gmux_CPD(bnet, node, ...) is used similarly to gaussian_CPD, wolffd@0: % except we assume there is exactly one discrete parent (call it M) wolffd@0: % which is used to select which cts parent to pass through to the output. wolffd@0: % i.e., we define P(Y=y|M=m, X1, ..., XK) = N(y | W(m)*x(m) + mu(m), Sigma(m)) wolffd@0: % where Y represents this node, and the Xi's are the cts parents. wolffd@0: % All the Xi must have the same size, and the num values for M must be K. wolffd@0: % wolffd@0: % Currently the params for this kind of CPD cannot be learned. wolffd@0: % wolffd@0: % Optional arguments [ default in brackets ] wolffd@0: % wolffd@0: % mean - mu(:,i) is the mean given M=i [ zeros(Y,K) ] wolffd@0: % cov - Sigma(:,:,i) is the covariance given M=i [ repmat(1*eye(Y,Y), [1 1 K]) ] wolffd@0: % weights - W(:,:,i) is the regression matrix given M=i [ randn(Y,X,K) ] 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: clamp = 0; wolffd@0: CPD = class(CPD, 'gmux_CPD', generic_CPD(clamp)); wolffd@0: return; wolffd@0: elseif isa(bnet, 'gmux_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: CPD = class(CPD, 'gmux_CPD', generic_CPD(1)); wolffd@0: wolffd@0: ns = bnet.node_sizes; wolffd@0: ps = parents(bnet.dag, self); wolffd@0: dps = myintersect(ps, bnet.dnodes); wolffd@0: cps = myintersect(ps, bnet.cnodes); wolffd@0: fam_sz = ns([ps self]); wolffd@0: wolffd@0: CPD.self = self; wolffd@0: CPD.sizes = fam_sz; wolffd@0: wolffd@0: % Figure out which (if any) of the parents are discrete, and which cts, and how big they are wolffd@0: % dps = discrete parents, cps = cts parents wolffd@0: CPD.cps = find_equiv_posns(cps, ps); % cts parent index wolffd@0: CPD.dps = find_equiv_posns(dps, ps); wolffd@0: if length(CPD.dps) ~= 1 wolffd@0: error('gmux must have exactly 1 discrete parent') wolffd@0: end wolffd@0: ss = fam_sz(end); wolffd@0: cpsz = fam_sz(CPD.cps(1)); % in gaussian_CPD, cpsz = sum(fam_sz(CPD.cps)) wolffd@0: if ~all(fam_sz(CPD.cps) == cpsz) wolffd@0: error('all cts parents must have same size') wolffd@0: end wolffd@0: dpsz = fam_sz(CPD.dps); wolffd@0: if dpsz ~= length(cps) wolffd@0: error(['the arity of the mux node is ' num2str(dpsz) ... wolffd@0: ' but there are ' num2str(length(cps)) ' cts parents']); wolffd@0: end wolffd@0: wolffd@0: % set default params wolffd@0: %CPD.mean = zeros(ss, 1); wolffd@0: %CPD.cov = eye(ss); wolffd@0: %CPD.weights = randn(ss, cpsz); wolffd@0: CPD.mean = zeros(ss, dpsz); wolffd@0: CPD.cov = 1*repmat(eye(ss), [1 1 dpsz]); wolffd@0: CPD.weights = randn(ss, cpsz, dpsz); wolffd@0: wolffd@0: args = varargin; wolffd@0: nargs = length(args); wolffd@0: for i=1:2:nargs wolffd@0: switch args{i}, wolffd@0: case 'mean', CPD.mean = args{i+1}; wolffd@0: case 'cov', CPD.cov = args{i+1}; wolffd@0: case 'weights', CPD.weights = args{i+1}; wolffd@0: otherwise, wolffd@0: error(['invalid argument name ' args{i}]); wolffd@0: end wolffd@0: end 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.sizes = []; wolffd@0: CPD.cps = []; wolffd@0: CPD.dps = []; wolffd@0: CPD.mean = []; wolffd@0: CPD.cov = []; wolffd@0: CPD.weights = []; wolffd@0: