1function [
MMAP, EXACT] = mmap3k_fit(D0, D1,
P, F, B, B2)
2% [
MMAP, EXACT] = mmap3k_fit(D0, D1,
P, F, B, B2)
3% Closed-
form marking fit of an
MMAP(3,K): a marked MAP of third order.
5% The
MMAP(2,K) argument does not depend on the order. Two facts carry over
6% (verified symbolically, see sage/proofs/mmap3k_marking_inverse.py):
7% 1. every per-class characteristic in which the class matrix appears exactly
8% once
is LINEAR in the marking fractions, so z = nnz(D1) fractions per
9% class are determined by z characteristics through a square system;
10% 2. that system
is BLOCK DIAGONAL in the classes, so one z-by-z block
is
11% built once and reused
for every
class: the cost does not grow with K.
13% What changes with the order
is WHICH characteristics are needed. At order two
14% (p_c, F_c, B_c) suffice; at order three the independent set of lowest total
16% (a,b) = (1,0), (1,1), (2,0), (3,0)
17% i.e. p_c, F_c, B_c, B_c^(2)
18% with a the backward and b the forward order of pie*A^a*D1c*A^b*1. Alternating
19% forward and backward orders does NOT stay independent at higher orders.
21% The block
is assembled exactly by evaluating the linear
map on unit markings:
22% no finite differences and no computer algebra, since the
map is linear with a
23% zero offset. This
is preferred to inlining the symbolic inverse, which at
24% order three
is about 5 KB of expressions and
is tied to one sparsity pattern.
26% The underlying MAP(3)
is an input: unlike order two there
is no canonical
27% inverse here that turns moments and autocorrelation into an order-3 MAP.
30% D0, D1: the underlying MAP (any order; validated at orders two and three)
31%
P: class probabilities (sum to one)
32% F: first-order forward moments
33% B: first-order backward moments
34% B2: second-order backward moments (required from order three)
37%
MMAP: the marked MAP as {D0, D1, D11, ..., D1K}
38% EXACT:
true when the closed-
form marking
is feasible
42P =
P(:); F = F(:); B = B(:);
48orders = marking_orders(n, z);
49if nargin < 6 || isempty(B2)
51 error(
'mmap3k_fit: order %d needs the second-order backward moments B2', n);
62rhs = zeros(n,1); rhs(n) = 1;
65% z-by-z block:
column j
is the characteristic vector of a unit marking on the
70 Dc(nzi(jj), nzj(jj)) = D1(nzi(jj), nzj(jj));
72 a = orders(ii,1); b = orders(ii,2);
73 M(ii,jj) = pie * (A^a) * Dc * (A^b) * ones(n,1);
77if abs(det(M)) < 1e-12 * max(1, max(abs(M(:)))^z)
78 error(
'mmap3k_fit: the underlying MAP is on the degenerate locus of the marking system');
85 a = orders(ii,1); b = orders(ii,2);
88 elseif a == 1 && b == 1
90 elseif a == 2 && b == 0
92 elseif a == 3 && b == 0
95 error(
'mmap3k_fit: no target supplied for the characteristic (a=%d, b=%d)', a, b);
101viol = max([0; -q(:); q(:)-1; abs(sum(q,2)-1)]);
102EXACT = viol <= feastol;
111 Dc(nzi(jj), nzj(jj)) = D1(nzi(jj), nzj(jj)) * qc(jj,c);
118function orders = marking_orders(n, z)
119% (backward, forward) orders of an independent characteristic set
121 orders = [1 0; 1 1; 2 0];
123 orders = [1 0; 1 1; 2 0; 3 0];
127 while size(orders,1) < n+1
128 orders = [orders; a 0]; %#ok<AGROW>
132orders = orders(1:z,:);