void bool_mat_transpose(bool_mat_t B, const bool_mat_t A) { slong i, j; if (bool_mat_nrows(B) != bool_mat_ncols(A) || bool_mat_ncols(B) != bool_mat_nrows(A)) { flint_printf("bool_mat_transpose: Incompatible dimensions.\n"); abort(); } if (bool_mat_is_empty(A)) return; if (A == B) /* In-place, guaranteed to be square */ { int tmp; for (i = 0; i < bool_mat_nrows(B) - 1; i++) { for (j = i + 1; j < bool_mat_ncols(B); j++) { tmp = bool_mat_get_entry(B, i, j); bool_mat_set_entry(B, i, j, bool_mat_get_entry(B, j, i)); bool_mat_set_entry(B, j, i, tmp); } } } else /* Not aliased; general case */ { for (i = 0; i < bool_mat_nrows(B); i++) for (j = 0; j < bool_mat_ncols(B); j++) bool_mat_set_entry(B, i, j, bool_mat_get_entry(A, j, i)); } }
int bool_mat_is_transitive(const bool_mat_t mat) { slong n, i, j, k; if (!bool_mat_is_square(mat)) { flint_printf("bool_mat_is_transitive: a square matrix is required!\n"); abort(); } if (bool_mat_is_empty(mat)) return 1; n = bool_mat_nrows(mat); for (i = 0; i < n; i++) for (j = 0; j < n; j++) for (k = 0; k < n; k++) if (bool_mat_get_entry(mat, i, j) && bool_mat_get_entry(mat, j, k) && !bool_mat_get_entry(mat, i, k)) { return 0; } return 1; }
void bool_mat_add(bool_mat_t res, const bool_mat_t mat1, const bool_mat_t mat2) { slong i, j; if (bool_mat_is_empty(mat1)) return; for (i = 0; i < bool_mat_nrows(mat1); i++) for (j = 0; j < bool_mat_ncols(mat1); j++) bool_mat_set_entry(res, i, j, (bool_mat_get_entry(mat1, i, j) | bool_mat_get_entry(mat2, i, j))); }
void bool_mat_mul(bool_mat_t C, const bool_mat_t A, const bool_mat_t B) { slong ar, ac, br, bc, i, j, k; ar = bool_mat_nrows(A); ac = bool_mat_ncols(A); br = bool_mat_nrows(B); bc = bool_mat_ncols(B); if (ac != br || ar != bool_mat_nrows(C) || bc != bool_mat_ncols(C)) { flint_printf("bool_mat_mul: incompatible dimensions\n"); abort(); } if (br == 0) { bool_mat_zero(C); return; } if (A == C || B == C) { bool_mat_t T; bool_mat_init(T, ar, bc); bool_mat_mul(T, A, B); bool_mat_swap(T, C); bool_mat_clear(T); return; } for (i = 0; i < ar; i++) { for (j = 0; j < bc; j++) { int any = 0; for (k = 0; k < br && !any; k++) any |= (bool_mat_get_entry(A, i, k) & bool_mat_get_entry(B, k, j)); bool_mat_set_entry(C, i, j, any); } } }
void _brute_force_all_pairs_longest_walk(fmpz_mat_t B, const bool_mat_t A) { slong i, j, n; n = bool_mat_nrows(A); /* set entries of B according to the longest observed walk */ { slong k; bool_mat_t T; bool_mat_init(T, n, n); bool_mat_one(T); fmpz_mat_zero(B); for (k = 0; k < 2*n+1; k++) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (bool_mat_get_entry(T, i, j)) { fmpz_set_si(fmpz_mat_entry(B, i, j), k); } } } bool_mat_mul(T, T, A); } bool_mat_clear(T); } /* set special values 0, -1, -2 */ { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { slong x; fmpz *p; p = fmpz_mat_entry(B, i, j); x = fmpz_get_si(p); if (x < 1) { x = (i == j) ? 0 : -1; } else if (x > n-1) { x = -2; } fmpz_set_si(p, x); } } } }
void bool_mat_mul_entrywise(bool_mat_t C, const bool_mat_t A, const bool_mat_t B) { slong i, j; if (bool_mat_nrows(A) != bool_mat_nrows(B) || bool_mat_ncols(A) != bool_mat_ncols(B)) { flint_printf("bool_mat_mul_entrywise: incompatible dimensions\n"); flint_abort(); } for (i = 0; i < bool_mat_nrows(A); i++) { for (j = 0; j < bool_mat_ncols(A); j++) { bool_mat_set_entry(C, i, j, (bool_mat_get_entry(A, i, j) & bool_mat_get_entry(B, i, j))); } } }
void bool_mat_complement(bool_mat_t dest, const bool_mat_t src) { slong i, j; if (bool_mat_is_empty(src)) return; for (i = 0; i < bool_mat_nrows(src); i++) for (j = 0; j < bool_mat_ncols(src); j++) bool_mat_set_entry(dest, i, j, !bool_mat_get_entry(src, i, j)); }
int bool_mat_all(const bool_mat_t mat) { slong i, j; if (bool_mat_is_empty(mat)) return 1; for (i = 0; i < bool_mat_nrows(mat); i++) for (j = 0; j < bool_mat_ncols(mat); j++) if (!bool_mat_get_entry(mat, i, j)) return 0; return 1; }
void _bool_mat_permute(bool_mat_t B, const bool_mat_t A, const slong *perm) { slong n, i, j; if (!bool_mat_is_square(A)) abort(); /* assert */ if (A == B) abort(); /* assert */ n = bool_mat_nrows(A); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { bool_mat_set_entry( B, perm[i], perm[j], bool_mat_get_entry(A, i, j)); } } }
static int _toposort_visit(_toposort_s *s, const bool_mat_t A, slong n) { if (s->u[n]) return 1; if (!s->v[n]) { slong m; s->u[n] = 1; for (m = 0; m < s->size; m++) if (bool_mat_get_entry(A, n, m)) if (_toposort_visit(s, A, m)) return 1; s->v[n] = 1; s->u[n] = 0; s->post[s->npost++] = n; } return 0; }
static void _tarjan_strongconnect(slong *sccs, _tarjan_t t, const bool_mat_t A, slong v) { slong idx, w, scc; idx = _tarjan_next_idx(t); *_tarjan_index(t, v) = idx; *_tarjan_lowlink(t, v) = idx; _tarjan_push(t, v); for (w = 0; w < t->dim; w++) { if (bool_mat_get_entry(A, v, w)) { if (*_tarjan_index(t, w) == _tarjan_UNDEFINED) { _tarjan_strongconnect(sccs, t, A, w); *_tarjan_lowlink(t, v) = FLINT_MIN( *_tarjan_lowlink(t, v), *_tarjan_lowlink(t, w)); } else if (_tarjan_onstack(t, w)) { *_tarjan_lowlink(t, v) = FLINT_MIN( *_tarjan_lowlink(t, v), *_tarjan_index(t, w)); } } } if (*_tarjan_lowlink(t, v) == *_tarjan_index(t, v)) { scc = _tarjan_next_scc(t); while (w != v) { w = _tarjan_pop(t); if (sccs[w] != _tarjan_UNDEFINED) flint_abort(); /* assert */ sccs[w] = scc; } } }
slong bool_mat_nilpotency_degree(const bool_mat_t A) { slong n; if (!bool_mat_is_square(A)) { flint_printf("bool_mat_nilpotency_degree: a square matrix is required!\n"); abort(); } if (bool_mat_is_empty(A)) return 0; n = bool_mat_nrows(A); if (n == 1) { return bool_mat_get_entry(A, 0, 0) ? -1 : 1; } else { _toposort_s s; slong i; int has_cycle; int result; _toposort_init(&s, n); for (has_cycle = 0, i = 0; !has_cycle && i < n; i++) if (!s.v[i]) has_cycle = _toposort_visit(&s, A, i); if (has_cycle) { result = -1; } else { /* Find the length of the longest path within the DAG */ /* http://stackoverflow.com/a/10737524/4072759 */ slong x, y, z; slong max_overall; fmpz_mat_t E; fmpz_mat_init(E, n, n); fmpz_mat_zero(E); max_overall = 0; for (i = n - 1; i >= 0; i--) { slong max_in = 0; y = s.post[i]; for (x = 0; x < n; x++) { max_in = FLINT_MAX(max_in, fmpz_get_si(fmpz_mat_entry(E, x, y))); } for (z = 0; z < n; z++) { if (bool_mat_get_entry(A, y, z)) { fmpz_set_si(fmpz_mat_entry(E, y, z), max_in + 1); max_overall = FLINT_MAX(max_overall, max_in + 1); } } } fmpz_mat_clear(E); result = max_overall + 1; } _toposort_clear(&s); return result; } }