/// /// \return A new-and-improved F matrix. /// static matrix_type improve_f( 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 matrix_type * fif, ///< The Fin-force matrix. const bool frb) ///< Using frequency-bounds. { 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)); assert(nullptr == fif || !frb); const auto I = g.get_height(); const auto K = fa.get_height(); const auto J = fa.get_width(); assert(nullptr == fif || verification_type:: validate_fif_size(*fif, K, J)); matrix_type f_dst (K, J); static const std::vector<size_t> fixed_active_set; matrix_type derivative_vec (K, 1); matrix_type hessian_mat (K, K); const auto frb_delta = value_type(1.0) / (value_type(2 * I) + value_type(1.0)); for (size_t j = 0; j < J; j++) { const auto f_column = fa.copy_column(j); g.compute_derivatives_f( q, fa, fb, qfa, qfb, j, derivative_vec, hessian_mat); const auto coefficients_mat = _create_coefficients_mat(K, 0); auto b_vec = _create_b_vec(f_column, 0); if (nullptr != fif) { for (size_t k = 0; k < fif->get_height(); k++) { b_vec[k + 0] = value_type(0); b_vec[k + K] = value_type(0); } } else if (frb) { for (size_t k = 0; k < K; k++) { b_vec[k + 0] -= frb_delta; b_vec[k + K] -= frb_delta; } } 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++) f_dst(k, j) = f_column[k] + delta_vec[k]; } f_dst.clamp(min, max); return f_dst; }