wolffd@0
|
1 function [strategy, MEU, niter] = solve_limid(engine, varargin)
|
wolffd@0
|
2 % SOLVE_LIMID Find the (locally) optimal strategy for a LIMID
|
wolffd@0
|
3 % [strategy, MEU, niter] = solve_limid(inf_engine, ...)
|
wolffd@0
|
4 %
|
wolffd@0
|
5 % strategy{d} = stochastic policy for node d (a decision node)
|
wolffd@0
|
6 % MEU = maximum expected utility
|
wolffd@0
|
7 % niter = num iterations used
|
wolffd@0
|
8 %
|
wolffd@0
|
9 % The following optional arguments can be specified in the form of name/value pairs:
|
wolffd@0
|
10 % [default in brackets]
|
wolffd@0
|
11 %
|
wolffd@0
|
12 % max_iter - max. num. iterations [ 1 ]
|
wolffd@0
|
13 % tol - tolerance required of consecutive MEU values, used to assess convergence [1e-3]
|
wolffd@0
|
14 % order - order in which decision nodes are optimized [ reverse numerical order ]
|
wolffd@0
|
15 %
|
wolffd@0
|
16 % e.g., solve_limid(engine, 'tol', 1e-2, 'max_iter', 10)
|
wolffd@0
|
17
|
wolffd@0
|
18 bnet = bnet_from_engine(engine);
|
wolffd@0
|
19
|
wolffd@0
|
20 % default values
|
wolffd@0
|
21 max_iter = 1;
|
wolffd@0
|
22 tol = 1e-3;
|
wolffd@0
|
23 D = bnet.decision_nodes;
|
wolffd@0
|
24 order = D(end:-1:1);
|
wolffd@0
|
25
|
wolffd@0
|
26 args = varargin;
|
wolffd@0
|
27 nargs = length(args);
|
wolffd@0
|
28 for i=1:2:nargs
|
wolffd@0
|
29 switch args{i},
|
wolffd@0
|
30 case 'max_iter', max_iter = args{i+1};
|
wolffd@0
|
31 case 'tol', tol = args{i+1};
|
wolffd@0
|
32 case 'order', order = args{i+1};
|
wolffd@0
|
33 otherwise,
|
wolffd@0
|
34 error(['invalid argument name ' args{i}]);
|
wolffd@0
|
35 end
|
wolffd@0
|
36 end
|
wolffd@0
|
37
|
wolffd@0
|
38 CPDs = bnet.CPD;
|
wolffd@0
|
39 ns = bnet.node_sizes;
|
wolffd@0
|
40 N = length(ns);
|
wolffd@0
|
41 evidence = cell(1,N);
|
wolffd@0
|
42 strategy = cell(1, N);
|
wolffd@0
|
43
|
wolffd@0
|
44 iter = 1;
|
wolffd@0
|
45 converged = 0;
|
wolffd@0
|
46 oldMEU = 0;
|
wolffd@0
|
47 while ~converged & (iter <= max_iter)
|
wolffd@0
|
48 for d=order(:)'
|
wolffd@0
|
49 engine = enter_evidence(engine, evidence, 'exclude', d);
|
wolffd@0
|
50 [m, pot] = marginal_family(engine, d);
|
wolffd@0
|
51 %pot = marginal_family_pot(engine, d);
|
wolffd@0
|
52 [policy, score] = upot_to_opt_policy(pot);
|
wolffd@0
|
53 e = bnet.equiv_class(d);
|
wolffd@0
|
54 CPDs{e} = set_fields(CPDs{e}, 'policy', policy);
|
wolffd@0
|
55 engine = update_engine(engine, CPDs);
|
wolffd@0
|
56 strategy{d} = policy;
|
wolffd@0
|
57 end
|
wolffd@0
|
58 engine = enter_evidence(engine, evidence);
|
wolffd@0
|
59 [m, pot] = marginal_nodes(engine, []);
|
wolffd@0
|
60 %pot = marginal_family_pot(engine, []);
|
wolffd@0
|
61 [dummy, MEU] = upot_to_opt_policy(pot);
|
wolffd@0
|
62 if approxeq(MEU, oldMEU, tol)
|
wolffd@0
|
63 converged = 1;
|
wolffd@0
|
64 end
|
wolffd@0
|
65 oldMEU = MEU;
|
wolffd@0
|
66 iter = iter + 1;
|
wolffd@0
|
67 end
|
wolffd@0
|
68 niter = iter - 1;
|