Daniel@0: function mpe = find_mpe(engine, evidence, varargin) Daniel@0: % FIND_MPE Find the most probable explanation of the data (belprop) Daniel@0: % function mpe = find_mpe(engine, evidence,...) Daniel@0: % Daniel@0: % evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector). Daniel@0: % Daniel@0: % This finds the marginally most likely value for each hidden node, Daniel@0: % and may give the wrong results even if the graph is acyclic, Daniel@0: % unless you set break_ties = 1. Daniel@0: % Daniel@0: % The following optional arguments can be specified in the form of name/value pairs: Daniel@0: % [default value in brackets] Daniel@0: % Daniel@0: % break_ties is optional. If 1, we will force ties to be broken consistently Daniel@0: % by calling enter_evidence N times. (see Jensen96, p106) Default = 1. Daniel@0: Daniel@0: break_ties = 1; Daniel@0: Daniel@0: % parse optional params Daniel@0: args = varargin; Daniel@0: nargs = length(args); Daniel@0: for i=1:2:nargs Daniel@0: switch args{i}, Daniel@0: case 'break_ties', break_ties = args{i+1}; Daniel@0: otherwise, Daniel@0: error(['invalid argument name ' args{i}]); Daniel@0: end Daniel@0: end Daniel@0: Daniel@0: engine = enter_evidence(engine, evidence, 'maximize', 1); Daniel@0: Daniel@0: observed = ~isemptycell(evidence); Daniel@0: evidence = evidence(:); % hack to handle unrolled DBNs Daniel@0: N = length(evidence); Daniel@0: mpe = cell(1,N); Daniel@0: for i=1:N Daniel@0: m = marginal_nodes(engine, i); Daniel@0: % observed nodes are all set to 1 inside the inference engine, so we must undo this Daniel@0: if observed(i) Daniel@0: mpe{i} = evidence{i}; Daniel@0: else Daniel@0: mpe{i} = argmax(m.T); Daniel@0: if break_ties Daniel@0: evidence{i} = mpe{i}; Daniel@0: [engine, ll] = enter_evidence(engine, evidence, 'maximize', 1); Daniel@0: end Daniel@0: end Daniel@0: end Daniel@0: