def symmetrized_matrix(self): """ Return the symmetrized matrix of ``self`` if symmetrizable. EXAMPLES:: sage: cm = CartanMatrix(['B',4,1]) sage: cm.symmetrized_matrix() [ 4 0 -2 0 0] [ 0 4 -2 0 0] [-2 -2 4 -2 0] [ 0 0 -2 4 -2] [ 0 0 0 -2 2] """ M = matrix.diagonal(list(self.symmetrizer())) * self M.set_immutable() return M
def next_step(indices, prev, T): for pos,i in enumerate(indices): U = prev * T mu = U * phi[i] mu = mu.stack(matrix.diagonal([B[i]]).dense_matrix()) row_syzygy = matrix(S, syz(mu.transpose())).matrix_from_columns(range(r)) Y = less_generators(row_syzygy) if not Y.is_square(): continue if len(indices) == 1: return [prev, Y] I = list(indices) I.pop(pos) ret = next_step(I, Y, U) if ret is not None: return [prev] + ret return None
def _symmetric_form_matrix(self): r""" Return the matrix for the symmetric form `( | )` in the weight lattice basis. Let `A` be a symmetrizable Cartan matrix with symmetrizer `D`,. This returns the matrix `M^t DA M`, where `M` is dependent upon the type given below. In finite types, `M` is the inverse of the Cartan matrix. In affine types, `M` takes the basis `(\Lambda_0, \Lambda_1, \ldots, \Lambda_r, \delta)` to `(\alpha_0, \ldots, \alpha_r, \Lambda_0)` where `r` is the rank of ``self``. This is used in computing the symmetric form for affine root systems. EXAMPLES:: sage: P = RootSystem(['C',2]).weight_lattice() sage: P._symmetric_form_matrix [1 1] [1 2] sage: P = RootSystem(['C',2,1]).weight_lattice() sage: P._symmetric_form_matrix [0 0 0 1] [0 1 1 1] [0 1 2 1] [1 1 1 0] sage: P = RootSystem(['A',4,2]).weight_lattice() sage: P._symmetric_form_matrix [ 0 0 0 1/2] [ 0 2 2 1] [ 0 2 4 1] [1/2 1 1 0] """ from sage.matrix.constructor import matrix ct = self.cartan_type() cm = ct.cartan_matrix() if cm.det() != 0: cm_inv = cm.inverse() diag = cm.is_symmetrizable(True) return cm_inv.transpose() * matrix.diagonal(diag) if not ct.is_affine(): raise ValueError("only implemented for affine types when the" " Cartan matrix is singular") r = ct.rank() a = ct.a() # Determine the change of basis matrix # La[0], ..., La[r], delta -> al[0], ..., al[r], La[0] M = cm.stack( matrix([1] + [0]*(r-1)) ) M = matrix.block([[ M, matrix([[1]] + [[0]]*r) ]]) M = M.inverse() if a[0] != 1: from sage.rings.all import QQ S = matrix([~a[0]]+[0]*(r-1)) A = cm.symmetrized_matrix().change_ring(QQ).stack(S) else: A = cm.symmetrized_matrix().stack(matrix([1]+[0]*(r-1))) A = matrix.block([[A, matrix([[~a[0]]] + [[0]]*r)]]) return M.transpose() * A * M
def _symmetric_form_matrix(self): r""" Return the matrix for the symmetric form `( | )` in the weight lattice basis. Let `A` be a symmetrizable Cartan matrix with symmetrizer `D`,. This returns the matrix `M^t DA M`, where `M` is dependent upon the type given below. In finite types, `M` is the inverse of the Cartan matrix. In affine types, `M` takes the basis `(\Lambda_0, \Lambda_1, \ldots, \Lambda_r, \delta)` to `(\alpha_0, \ldots, \alpha_r, \Lambda_0)` where `r` is the rank of ``self``. This is used in computing the symmetric form for affine root systems. EXAMPLES:: sage: P = RootSystem(['C',2]).weight_lattice() sage: P._symmetric_form_matrix [1 1] [1 2] sage: P = RootSystem(['C',2,1]).weight_lattice() sage: P._symmetric_form_matrix [0 0 0 1] [0 1 1 1] [0 1 2 1] [1 1 1 0] sage: P = RootSystem(['A',4,2]).weight_lattice() sage: P._symmetric_form_matrix [ 0 0 0 1/2] [ 0 2 2 1] [ 0 2 4 1] [1/2 1 1 0] """ from sage.matrix.constructor import matrix ct = self.cartan_type() cm = ct.cartan_matrix() if cm.det() != 0: cm_inv = cm.inverse() diag = cm.is_symmetrizable(True) return cm_inv.transpose() * matrix.diagonal(diag) if not ct.is_affine(): raise ValueError("only implemented for affine types when the" " Cartan matrix is singular") r = ct.rank() a = ct.a() # Determine the change of basis matrix # La[0], ..., La[r], delta -> al[0], ..., al[r], La[0] M = cm.stack(matrix([1] + [0] * (r - 1))) M = matrix.block([[M, matrix([[1]] + [[0]] * r)]]) M = M.inverse() if a[0] != 1: from sage.rings.all import QQ S = matrix([~a[0]] + [0] * (r - 1)) A = cm.symmetrized_matrix().change_ring(QQ).stack(S) else: A = cm.symmetrized_matrix().stack(matrix([1] + [0] * (r - 1))) A = matrix.block([[A, matrix([[~a[0]]] + [[0]] * r)]]) return M.transpose() * A * M
def construct_free_chain(A): """ Construct the free chain for the hyperplanes ``A``. ALGORITHM: We follow Algorithm 6.5 in [BC2012]_. INPUT: - ``A`` -- a hyperplane arrangement EXAMPLES:: sage: from sage.geometry.hyperplane_arrangement.check_freeness import construct_free_chain sage: H.<x,y,z> = HyperplaneArrangements(QQ) sage: A = H(z, y+z, x+y+z) sage: construct_free_chain(A) [ [1 0 0] [ 1 0 0] [ 0 1 0] [0 1 0] [ 0 z -1] [y + z 0 -1] [0 0 z], [ 0 y 1], [ x 0 1] ] """ AL = list(A) if not AL: # Empty arrangement return [] S = A.parent().ambient_space().symmetric_space() # Compute the morphisms \phi_{H_j} : S^{1xR} \to S / <b_j> B = [H.to_symmetric_space() for H in AL] phi = [matrix(S, [[beta.derivative(x)] for x in S.gens()]) for beta in B] # Setup variables syz = fun_fact.ff.syz G = S.gens() r = len(G) indices = list(range(len(B))) X = [] # Helper function def next_step(indices, prev, T): for pos, i in enumerate(indices): U = prev * T mu = U * phi[i] mu = mu.stack(matrix.diagonal([B[i]]).dense_matrix()) row_syzygy = matrix(S, syz(mu.transpose())).matrix_from_columns( range(r)) Y = less_generators(row_syzygy) if not Y.is_square(): continue if len(indices) == 1: return [prev, Y] I = list(indices) I.pop(pos) ret = next_step(I, Y, U) if ret is not None: return [prev] + ret return None T = matrix.identity(S, r) for i in indices: mu = phi[i].stack(matrix.diagonal([B[i]]).dense_matrix()) row_syzygy = matrix(S, syz(mu.transpose())).matrix_from_columns(range(r)) Y = less_generators(row_syzygy) if not Y.is_square(): continue if len(indices) == 1: return [Y] I = list(indices) I.pop(i) ret = next_step(I, Y, T) if ret is not None: return ret return None
def construct_free_chain(A): """ Construct the free chain for the hyperplanes ``A``. ALGORITHM: We follow Algorithm 6.5 in [BC2012]_. INPUT: - ``A`` -- a hyperplane arrangement EXAMPLES:: sage: from sage.geometry.hyperplane_arrangement.check_freeness import construct_free_chain sage: H.<x,y,z> = HyperplaneArrangements(QQ) sage: A = H(z, y+z, x+y+z) sage: construct_free_chain(A) [ [1 0 0] [ 1 0 0] [ 0 1 0] [0 1 0] [ 0 z -1] [y + z 0 -1] [0 0 z], [ 0 y 1], [ x 0 1] ] """ AL = list(A) if not AL: # Empty arrangement return [] S = A.parent().ambient_space().symmetric_space() # Compute the morphisms \phi_{H_j} : S^{1xR} \to S / <b_j> B = [H.to_symmetric_space() for H in AL] phi = [matrix(S, [[beta.derivative(x)] for x in S.gens()]) for beta in B] # Setup variables syz = fun_fact.ff.syz G = S.gens() r = len(G) indices = list(range(len(B))) # Helper function def next_step(indices, prev, T): for pos,i in enumerate(indices): U = prev * T mu = U * phi[i] mu = mu.stack(matrix.diagonal([B[i]]).dense_matrix()) row_syzygy = matrix(S, syz(mu.transpose())).matrix_from_columns(range(r)) Y = less_generators(row_syzygy) if not Y.is_square(): continue if len(indices) == 1: return [prev, Y] I = list(indices) I.pop(pos) ret = next_step(I, Y, U) if ret is not None: return [prev] + ret return None T = matrix.identity(S, r) for i in indices: mu = phi[i].stack(matrix.diagonal([B[i]]).dense_matrix()) row_syzygy = matrix(S, syz(mu.transpose())).matrix_from_columns(range(r)) Y = less_generators(row_syzygy) if not Y.is_square(): continue if len(indices) == 1: return [Y] I = list(indices) I.pop(i) ret = next_step(I, Y, T) if ret is not None: return ret return None