Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Partition backtrack functions for matrices
EXAMPLES::
sage: import sage.groups.perm_gps.partn_ref.refinement_matrices
REFERENCE:
- [1] McKay, Brendan D. Practical Graph Isomorphism. Congressus Numerantium, Vol. 30 (1981), pp. 45-87.
- [2] Leon, Jeffrey. Permutation Group Algorithms Based on Partitions, I: Theory and Algorithms. J. Symbolic Computation, Vol. 12 (1991), pp. 533-583.
"""
#***************************************************************************** # Copyright (C) 2006 - 2011 Robert L. Miller <rlmillster@gmail.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
from __future__ import print_function
from libc.string cimport memcmp
from .data_structures cimport * include "sage/data_structures/bitset.pxi" from sage.rings.integer cimport Integer from .refinement_binary cimport NonlinearBinaryCodeStruct, refine_by_bip_degree from .double_coset cimport double_coset
cdef class MatrixStruct:
def __cinit__(self, matrix): cdef int i, j cdef int *num_rows cdef NonlinearBinaryCodeStruct S_temp
sig_free(num_rows) PS_dealloc(self.temp_col_ps) raise MemoryError
def __dealloc__(self):
def display(self): """ Display the matrix, and associated data.
EXAMPLES::
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct sage: M = MatrixStruct(Matrix(GF(5), [[0,1,1,4,4],[0,4,4,1,1]])) sage: M.display() [0 1 1 4 4] [0 4 4 1 1] <BLANKLINE> 01100 00011 1 <BLANKLINE> 00011 01100 4
""" cdef NonlinearBinaryCodeStruct S_temp
def run(self, partition=None): """ Perform the canonical labeling and automorphism group computation, storing results to self.
INPUT:
partition -- an optional list of lists partition of the columns.
Default is the unit partition.
EXAMPLES::
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]])) sage: M.run() sage: M.automorphism_group() ([[0, 2, 1]], 2, [1]) sage: M.canonical_relabeling() [0, 1, 2]
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1],[1,0,2],[1,2,0],[2,0,1],[2,1,0]])) sage: M.automorphism_group()[1] == 6 True
sage: M = MatrixStruct(matrix(GF(3),[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2]])) sage: M.automorphism_group()[1] == factorial(14) True
""" cdef PartitionStack *part cdef NonlinearBinaryCodeStruct S_temp
else: part = PS_from_list(partition) raise MemoryError
def automorphism_group(self): """ Returns a list of generators of the automorphism group, along with its order and a base for which the list of generators is a strong generating set.
For more examples, see self.run().
EXAMPLES::
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]])) sage: M.automorphism_group() ([[0, 2, 1]], 2, [1])
""" cdef int i, j cdef list generators, base cdef Integer order
def canonical_relabeling(self): """ Returns a canonical relabeling (in list permutation format).
For more examples, see self.run().
EXAMPLES::
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct
sage: M = MatrixStruct(matrix(GF(3),[[0,1,2],[0,2,1]])) sage: M.canonical_relabeling() [0, 1, 2]
""" cdef int i
def is_isomorphic(self, MatrixStruct other): """ Calculate whether self is isomorphic to other.
EXAMPLES::
sage: from sage.groups.perm_gps.partn_ref.refinement_matrices import MatrixStruct sage: M = MatrixStruct(Matrix(GF(11), [[1,2,3,0,0,0],[0,0,0,1,2,3]])) sage: N = MatrixStruct(Matrix(GF(11), [[0,1,0,2,0,3],[1,0,2,0,3,0]])) sage: M.is_isomorphic(N) [0, 2, 4, 1, 3, 5]
""" cdef int *output cdef int *ordering cdef PartitionStack *part cdef NonlinearBinaryCodeStruct S_temp PS_dealloc(part) sig_free(ordering) sig_free(output) raise MemoryError
else: output_py = False
cdef int refine_matrix(PartitionStack *PS, void *S, int *cells_to_refine_by, int ctrb_len):
cdef int compare_matrices(int *gamma_1, int *gamma_2, void *S1, void *S2, int degree): cdef int i
cdef bint all_matrix_children_are_equivalent(PartitionStack *PS, void *S):
""" Tests to make sure that C(gamma(M)) == C(M) for random permutations gamma and random matrices M, and that M.is_isomorphic(gamma(M)) returns an isomorphism.
INPUT:
- n -- run tests on this many matrices - nrows_max -- test matrices with at most this many rows - ncols_max -- test matrices with at most this many columns - perms_per_matrix -- test each matrix with this many random permutations - nsymbols_max -- maximum number of distinct symbols in the matrix
This code generates n random matrices M on at most ncols_max columns and at most nrows_max rows. The density of entries in the basis is chosen randomly between 0 and 1.
For each matrix M generated, we uniformly generate perms_per_matrix random permutations and verify that the canonical labels of M and the image of M under the generated permutation are equal, and that the isomorphism is discovered by the double coset function.
TESTS::
sage: import sage.groups.perm_gps.partn_ref.refinement_matrices sage: sage.groups.perm_gps.partn_ref.refinement_matrices.random_tests() # long time (up to 30s on sage.math, 2011) All passed: ... random tests on ... matrices.
""" from sage.misc.misc import walltime from sage.misc.prandom import random, randint from sage.combinat.permutation import Permutations from sage.matrix.constructor import random_matrix, matrix from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.arith.all import next_prime cdef int h, i, j, nrows, k, num_tests = 0, num_matrices = 0 cdef MatrixStruct M, N for m in range(n): p = random()*(density_range[1]-density_range[0]) + density_range[0] nrows = randint(1, nrows_max) ncols = randint(1, ncols_max) nsymbols = next_prime(randint(1, nsymbols_max)) S = Permutations(ncols) MM = random_matrix(GF(nsymbols), nrows, ncols, sparse=False, density=p) M = MatrixStruct( MM ) M.run()
for i from 0 <= i < perms_per_matrix: perm = [a-1 for a in list(S.random_element())] NN = matrix(GF(nsymbols), nrows, ncols) for j from 0 <= j < ncols: NN.set_column(perm[j], MM.column(j)) N = MatrixStruct(NN) # now N is a random permutation of M N.run()
M_relab = M.canonical_relabeling() N_relab = N.canonical_relabeling()
M_C = matrix(GF(nsymbols), nrows, ncols) N_C = matrix(GF(nsymbols), nrows, ncols)
for j from 0 <= j < ncols: M_C.set_column(M_relab[j], MM.column(j)) N_C.set_column(N_relab[j], NN.column(j))
M_C = matrix(GF(nsymbols), sorted(M_C.rows())) N_C = matrix(GF(nsymbols), sorted(N_C.rows()))
if M_C != N_C: print("M:") print(M.matrix.str()) print("perm:") print(perm) return
isom = M.is_isomorphic(N) if not isom: print("isom FAILURE: M:") print(M.matrix.str()) print("isom FAILURE: N:") print(N.matrix.str()) return
num_tests += perms_per_matrix num_matrices += 2 print("All passed: %d random tests on %d matrices." % (num_tests, num_matrices)) |