/// /// \return A new-and-improved Q matrix. /// static matrix_type improve_q( const genotype_matrix_type & g, ///< The G matrix. const matrix_type & q, ///< The Q matrix. const matrix_type & fa, ///< The F matrix. const matrix_type & fb, ///< The 1-F matrix. const matrix_type & qfa, ///< The Q*F matrix. const matrix_type & qfb, ///< The Q*(1-F) matrix. const forced_grouping_type * fg) ///< The force-grouping. { assert(verification_type::validate_gqf_sizes(g, q, fa)); assert(verification_type::validate_gqf_sizes(g, q, fb)); assert(verification_type::validate_q(q)); assert(verification_type::validate_f(fa)); const auto I = q.get_height(); const auto K = q.get_width(); matrix_type q_dst (I, K); const std::vector<size_t> fixed_active_set { K + K }; matrix_type derivative_vec (K, 1); matrix_type hessian_mat (K, K); for (size_t i = 0; i < I; i++) { const auto q_row = q.copy_row(i); g.compute_derivatives_q( q, fa, fb, qfa, qfb, i, derivative_vec, hessian_mat); const auto coefficients_mat = _create_coefficients_mat(K, 1); auto b_vec = _create_b_vec(q_row, 1); if (nullptr != fg) { for (size_t k = 0; k < K; k++) { b_vec[k + 0] -= fg->get_min(i, k); b_vec[k + K] += fg->get_max(i, k) - value_type(1); } } std::vector<size_t> active_set { 0 }; matrix_type delta_vec (K, 1); delta_vec[0] = -b_vec[0]; qpas_type::loop_over_active_set( b_vec, coefficients_mat, hessian_mat, derivative_vec, fixed_active_set, active_set, delta_vec); for (size_t k = 0; k < K; k++) q_dst(i, k) = q_row[k] + delta_vec[k]; q_dst.clamp_row(i, min, max); const auto sum = q_dst.get_row_sum(i); q_dst.multiply_row(i, value_type(1) / sum); } return q_dst; }