static void _update_aggregated_state_frechet_matrices( cross_site_ws_t csw, model_and_data_t m, nd_axis_struct *edge_axis, nd_axis_struct *trans_axis, const int *first_idx, const int *second_idx, slong prec) { arb_mat_t P, L, Q; arb_t rate; slong first_state, second_state; slong cat, trans_idx; slong state_count = model_and_data_state_count(m); slong edge_count = model_and_data_edge_count(m); slong rate_category_count = model_and_data_rate_category_count(m); arb_init(rate); arb_mat_init(P, state_count, state_count); arb_mat_init(L, state_count, state_count); arb_mat_init(Q, state_count, state_count); /* set entries of L to the requested transition weights */ for (trans_idx = 0; trans_idx < trans_axis->n; trans_idx++) { first_state = first_idx[trans_idx]; second_state = second_idx[trans_idx]; arb_add(arb_mat_entry(L, first_state, second_state), arb_mat_entry(L, first_state, second_state), trans_axis->agg_weights + trans_idx, prec); } /* multiply entries of L by the rate matrix entries */ arb_mat_mul_entrywise(L, L, csw->rate_matrix, prec); /* divide L by the global weight divisor */ arb_mat_scalar_div_arb(L, L, trans_axis->agg_weight_divisor, prec); for (cat = 0; cat < rate_category_count; cat++) { slong edge; const arb_struct * cat_rate = csw->rate_mix_rates + cat; for (edge = 0; edge < edge_count; edge++) { slong idx = m->edge_map->order[edge]; const arb_struct * edge_rate = csw->edge_rates + idx; arb_mat_struct *fmat; if (!edge_axis->request_update[edge]) continue; fmat = cross_site_ws_trans_frechet_matrix(csw, cat, idx); arb_mul(rate, edge_rate, cat_rate, prec); arb_mat_scalar_mul_arb(Q, csw->rate_matrix, rate, prec); _arb_mat_exp_frechet(P, fmat, Q, L, prec); } } arb_clear(rate); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(Q); }
/* rate matrix and edge rates have already been updated */ static void _update_transition_matrices(cross_site_ws_t w, slong prec) { slong i, j; arb_t s; arb_init(s); for (i = 0; i < w->rate_category_count; i++) { for (j = 0; j < w->edge_count; j++) { arb_mat_struct *tmat; tmat = cross_site_ws_transition_matrix(w, i, j); arb_mul(s, w->rate_mix_rates + i, w->edge_rates + j, prec); arb_mat_scalar_mul_arb(tmat, w->rate_matrix, s, prec); arb_mat_exp(tmat, tmat, prec); } } arb_clear(s); }
/* * Update the frechet matrix for each rate category and edge. * At this point the rate matrix has been normalized * to have zero row sums, but it has not been scaled * by the edge rate coefficients. * The frechet matrices must already have been initialized. */ static void _update_state_pair_frechet_matrices( cross_site_ws_t csw, model_and_data_t m, nd_axis_struct *edge_axis, slong first_state, slong second_state, slong prec) { arb_mat_t P, L, Q; slong cat; arb_t rate; slong state_count = model_and_data_state_count(m); slong edge_count = model_and_data_edge_count(m); slong rate_category_count = model_and_data_rate_category_count(m); arb_init(rate); arb_mat_init(P, state_count, state_count); arb_mat_init(L, state_count, state_count); arb_mat_init(Q, state_count, state_count); arb_set(arb_mat_entry(L, first_state, second_state), arb_mat_entry(csw->rate_matrix, first_state, second_state)); for (cat = 0; cat < rate_category_count; cat++) { slong edge; const arb_struct * cat_rate = csw->rate_mix_rates + cat; for (edge = 0; edge < edge_count; edge++) { slong idx = m->edge_map->order[edge]; const arb_struct * edge_rate = csw->edge_rates + idx; arb_mat_struct *fmat; if (!edge_axis->request_update[edge]) continue; fmat = cross_site_ws_trans_frechet_matrix(csw, cat, idx); arb_mul(rate, edge_rate, cat_rate, prec); arb_mat_scalar_mul_arb(Q, csw->rate_matrix, rate, prec); _arb_mat_exp_frechet(P, fmat, Q, L, prec); } } arb_clear(rate); arb_mat_clear(P); arb_mat_clear(L); arb_mat_clear(Q); }
int main() { long iter; flint_rand_t state; printf("exp...."); fflush(stdout); flint_randinit(state); /* check exp(A)*exp(c*A) = exp((1+c)*A) */ for (iter = 0; iter < 1000; iter++) { arb_mat_t A, E, F, EF, G; fmpq_mat_t Q; arb_t c, d; long n, qbits, prec; n = n_randint(state, 5); qbits = 2 + n_randint(state, 300); prec = 2 + n_randint(state, 300); arb_init(c); arb_init(d); fmpq_mat_init(Q, n, n); arb_mat_init(A, n, n); arb_mat_init(E, n, n); arb_mat_init(F, n, n); arb_mat_init(EF, n, n); arb_mat_init(G, n, n); fmpq_mat_randtest(Q, state, qbits); arb_mat_set_fmpq_mat(A, Q, prec); arb_mat_exp(E, A, prec); arb_randtest(c, state, prec, 10); arb_mat_scalar_mul_arb(F, A, c, prec); arb_mat_exp(F, F, prec); arb_add_ui(d, c, 1, prec); arb_mat_scalar_mul_arb(G, A, d, prec); arb_mat_exp(G, G, prec); arb_mat_mul(EF, E, F, prec); if (!arb_mat_overlaps(EF, G)) { printf("FAIL\n\n"); printf("n = %ld, prec = %ld\n", n, prec); printf("c = \n"); arb_printd(c, 15); printf("\n\n"); printf("A = \n"); arb_mat_printd(A, 15); printf("\n\n"); printf("E = \n"); arb_mat_printd(E, 15); printf("\n\n"); printf("F = \n"); arb_mat_printd(F, 15); printf("\n\n"); printf("E*F = \n"); arb_mat_printd(EF, 15); printf("\n\n"); printf("G = \n"); arb_mat_printd(G, 15); printf("\n\n"); abort(); } arb_clear(c); arb_clear(d); fmpq_mat_clear(Q); arb_mat_clear(A); arb_mat_clear(E); arb_mat_clear(F); arb_mat_clear(EF); arb_mat_clear(G); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }