79 const std::vector<T>& ai,
const T& st3,
82 "m3pp22_fitc_approx_cov_multiclass requires transcendental arithmetic");
83 using fitdetail::num_exp;
84 using fitdetail::num_sqrt;
92 const std::size_t m = ai.size();
93 if (m == 0)
throw InputError(
"m3pp22_fitc_approx_cov_multiclass: no classes");
94 if (m > 2)
throw InputError(
"m3pp22_fitc_approx_cov_multiclass: no more than two classes "
105 if (mmpp.
D0.rows() == 1) {
108 for (std::size_t i = 0; i < m; ++i) asum += ai[i];
109 for (std::size_t i = 0; i < m; ++i)
110 res.
mmap.Dc.push_back(
Matrix<T>(1, 1, T(ai[i] / asum * mmpp.
D1(0, 0))));
115 res.
mmap.Dc.push_back(mmpp.
D1);
119 if (mmpp.
D0.rows() != 2)
120 throw InputError(
"m3pp22_fitc_approx_cov_multiclass: the underlying MAP must have order 2");
122 const T l1 = mmpp.
D1(0, 0);
123 const T l2 = mmpp.
D1(1, 1);
124 const T r1 = mmpp.
D0(0, 1);
125 const T r2 = mmpp.
D0(1, 0);
129 const T E = num_exp(T(-(r1 + r2) * t));
130 const T G = one - E - (r1 + r2) * t;
131 const T w0 = (two * r1 * G * (a1 * a1 * (r1 + r2) - a1 * r2 * (l1 - l2))) /
132 (r2 * pw(T(r1 + r2), 3));
133 const T w1 = -(two * r1 * G * (two * a1 * l2 * (r1 + r2) - l2 * r2 * (l1 - l2))) /
134 (r2 * pw(T(r1 + r2), 3));
135 const T w2 = ((two * l2 * l2 * r2 * t) * (r1 + r2) + two * l2 * l2 * r1 * (one - E)) /
136 (r2 * pw(T(r1 + r2), 2)) -
137 (two * l2 * l2 * t) / r2;
138 const T w3 = (r1 + r2) / (l2 * r1);
139 const T w4 = (l1 * r2) / (l2 * r1);
141 throw NumericError(
"m3pp22_fitc_approx_cov_multiclass: the covariance is linear in the "
142 "marking probability, so the reference's two-root inversion degenerates");
145 T L1 = -inf, L2 = -inf, U1 = inf, U2 = inf;
146 bool infeasible1 =
false, infeasible2 =
false;
148 const T z = w0 - w1 * w1 / (four * w2);
160 if (w0 > L1) L1 = w0;
161 }
else if (w2 < zero) {
165 if (w0 < U2) U2 = w0;
166 }
else if (w2 > zero) {
171 const T tmp = two * a1 * w3 * w2 + w1;
172 const T bnd = z + tmp * tmp / (four * w2);
174 if (bnd < U1) U1 = bnd;
175 }
else if (w2 > zero) {
179 if (bnd > L2) L2 = bnd;
180 }
else if (w2 < zero) {
186 const T tmp = two * w2 + w1;
187 const T bnd = z + tmp * tmp / (four * w2);
189 if (bnd < U1) U1 = bnd;
190 }
else if (w2 > zero) {
194 if (bnd > L2) L2 = bnd;
195 }
else if (w2 < zero) {
201 const T tmp = two * a1 * w2 * w3 - two * w2 * w4 + w1;
202 const T bnd = z + tmp * tmp / (four * w2);
204 if (bnd > L1) L1 = bnd;
205 }
else if (w2 < zero) {
209 if (bnd < U2) U2 = bnd;
210 }
else if (w2 > zero) {
215 if (infeasible1 && infeasible2)
216 throw NumericError(
"m3pp22_fitc_approx_cov_multiclass: empty feasibility region");
221 sigma = st3 < U1 ? st3 : U1;
222 if (sigma < L1) sigma = L1;
224 }
else if (infeasible1) {
225 sigma = st3 < U2 ? st3 : U2;
226 if (sigma < L2) sigma = L2;
229 T s1 = st3 < U1 ? st3 : U1;
230 if (s1 < L1) s1 = L1;
231 T s2 = st3 < U2 ? st3 : U2;
232 if (s2 < L2) s2 = L2;
242 const T disc = w1 * w1 - four * w2 * (w0 - sigma);
244 throw NumericError(
"m3pp22_fitc_approx_cov_multiclass: negative discriminant after "
245 "clamping the covariance");
246 const T rt = num_sqrt(disc);
247 T q2 = root == 1 ? T((-w1 + rt) / (two * w2)) : T((-w1 - rt) / (two * w2));
248 T q1 = (a1 * (r1 + r2) - l2 * q2 * r1) / (l1 * r2);
251 if (!(q1 >= tol && q1 <= one + tol && q2 >= tol && q2 <= one + tol))
252 throw NumericError(
"m3pp22_fitc_approx_cov_multiclass: the marking probabilities left "
254 if (q1 < zero) q1 = zero;
255 if (q1 > one) q1 = one;
256 if (q2 < zero) q2 = zero;
257 if (q2 > one) q2 = one;
259 Matrix<T> Dc1(2, 2, zero), Dc2(2, 2, zero);
262 Dc2(0, 0) = (one - q1) * l1;
263 Dc2(1, 1) = (one - q2) * l2;
264 res.
mmap.Dc.push_back(Dc1);
265 res.
mmap.Dc.push_back(Dc2);
Mmpp2FitcApproxResult< T > mmpp2_fitc_approx(const T &a, const T &bt1, const T &bt2, const T &binf, const T &m3t2, const T &t1, const T &t2, const AugLagOptions< T > &opt)
Fit an MMPP(2) to counting characteristics.
M3pp22FitcCovResult< T > m3pp22_fitc_approx_cov(const T &a, const T &bt1, const T &bt2, const T &binf, const T &m3t2, const T &t1, const T &t2, const std::vector< T > &ai, const T &st3, const T &t3, const AugLagOptions< T > &opt)
Fit the underlying MMPP(2) by optimization, then apply the covariance split.
M3pp22FitcCovResult< T > m3pp22_fitc_approx_cov_multiclass(const Map< T > &mmpp, const std::vector< T > &ai, const T &st3, const T &t3)
Split a GIVEN MMPP(2) into two classes, matching the per-class rates exactly and the count covariance...
AugLagOptions< T > auglag_defaults()
Defaults: rho0 = 10, growth 10, feasibility 1e-10, 50 outer iterations.