Coverage for local/lib/python2.7/site-packages/sage/combinat/cluster_algebra_quiver/quiver.py : 80%

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
r""" Quiver
A *quiver* is an oriented graph without loops, two-cycles, or multiple edges. The edges are labelled by pairs `(i,-j)` (with `i` and `j` being positive integers) such that the matrix `M = (m_{ab})` with `m_{ab} = i, m_{ba} = -j` for an edge `(i,-j)` between vertices `a` and `b` is skew-symmetrizable.
.. WARNING::
This is not the standard definition of a quiver. Normally, in cluster algebra theory, a quiver is defined as an oriented graph without loops and two-cycles but with multiple edges allowed; the edges are unlabelled. This notion of quivers, however, can be seen as a particular case of our notion of quivers. Namely, if we have a quiver (in the regular sense of this word) with (precisely) `i` edges from `a` to `b`, then we represent it by a quiver (in our sense of this word) with an edge from `a` to `b` labelled by the pair `(i,-i)`.
For the compendium on the cluster algebra and quiver package see [MS2011]_
AUTHORS:
- Gregg Musiker - Christian Stump
.. SEEALSO:: For mutation types of combinatorial quivers, see :meth:`~sage.combinat.cluster_algebra_quiver.quiver_mutation_type.QuiverMutationType`. Cluster seeds are closely related to :meth:`~sage.combinat.cluster_algebra_quiver.cluster_seed.ClusterSeed`. """ #***************************************************************************** # Copyright (C) 2011 Gregg Musiker <musiker@math.mit.edu> # Christian Stump <christian.stump@univie.ac.at> # # Distributed under the terms of the GNU General Public License (GPL) # http://www.gnu.org/licenses/ #*****************************************************************************
""" The *quiver* associated to an *exchange matrix*.
INPUT:
- ``data`` -- can be any of the following::
* QuiverMutationType * str - a string representing a QuiverMutationType or a common quiver type (see Examples) * ClusterQuiver * Matrix - a skew-symmetrizable matrix * DiGraph - must be the input data for a quiver * List of edges - must be the edge list of a digraph for a quiver
- ``frozen`` -- (default:``None``) sets the list of frozen variables if the input type is a :class:`DiGraph`, it is ignored otherwise
- ``user_labels`` -- (default:``None``) sets the names of the labels for the vertices of the quiver if the input type is not a :class:`DiGraph`; otherwise it is ignored
EXAMPLES:
From a :class:`QuiverMutationType`::
sage: Q = ClusterQuiver(['A',5]); Q Quiver on 5 vertices of type ['A', 5]
sage: Q = ClusterQuiver(['B',2]); Q Quiver on 2 vertices of type ['B', 2] sage: Q2 = ClusterQuiver(['C',2]); Q2 Quiver on 2 vertices of type ['B', 2] sage: MT = Q.mutation_type(); MT.standard_quiver() == Q True sage: MT = Q2.mutation_type(); MT.standard_quiver() == Q2 False
sage: Q = ClusterQuiver(['A',[2,5],1]); Q Quiver on 7 vertices of type ['A', [2, 5], 1]
sage: Q = ClusterQuiver(['A', [5,0],1]); Q Quiver on 5 vertices of type ['D', 5] sage: Q.is_finite() True sage: Q.is_acyclic() False
sage: Q = ClusterQuiver(['F', 4, [2,1]]); Q Quiver on 6 vertices of type ['F', 4, [1, 2]] sage: MT = Q.mutation_type(); MT.standard_quiver() == Q False sage: dg = Q.digraph(); Q.mutate([2,1,4,0,5,3]) sage: dg2 = Q.digraph(); dg2.is_isomorphic(dg,edge_labels=True) False sage: dg2.is_isomorphic(MT.standard_quiver().digraph(),edge_labels=True) True
sage: Q = ClusterQuiver(['G',2, (3,1)]); Q Quiver on 4 vertices of type ['G', 2, [1, 3]] sage: MT = Q.mutation_type(); MT.standard_quiver() == Q False
sage: Q = ClusterQuiver(['GR',[3,6]]); Q Quiver on 4 vertices of type ['D', 4] sage: MT = Q.mutation_type(); MT.standard_quiver() == Q False
sage: Q = ClusterQuiver(['GR',[3,7]]); Q Quiver on 6 vertices of type ['E', 6]
sage: Q = ClusterQuiver(['TR',2]); Q Quiver on 3 vertices of type ['A', 3] sage: MT = Q.mutation_type(); MT.standard_quiver() == Q False sage: Q.mutate([1,0]); MT.standard_quiver() == Q True
sage: Q = ClusterQuiver(['TR',3]); Q Quiver on 6 vertices of type ['D', 6] sage: MT = Q.mutation_type(); MT.standard_quiver() == Q False
From a :class:`ClusterQuiver`::
sage: Q = ClusterQuiver(['A',[2,5],1]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] sage: T = ClusterQuiver( Q ); T Quiver on 7 vertices of type ['A', [2, 5], 1]
From a Matrix::
sage: Q = ClusterQuiver(['A',[2,5],1]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] sage: T = ClusterQuiver( Q._M ); T Quiver on 7 vertices
sage: Q = ClusterQuiver( matrix([[0,1,-1],[-1,0,1],[1,-1,0],[1,2,3]]) ); Q Quiver on 4 vertices with 1 frozen vertex
sage: Q = ClusterQuiver( matrix([]) ); Q Quiver without vertices
From a DiGraph::
sage: Q = ClusterQuiver(['A',[2,5],1]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] sage: T = ClusterQuiver( Q._digraph ); T Quiver on 7 vertices
sage: Q = ClusterQuiver( DiGraph([[1,2],[2,3],[3,4],[4,1]]) ); Q Quiver on 4 vertices
sage: Q = ClusterQuiver(DiGraph([['a', 'b'], ['b', 'c'], ['c', 'd'], ['d', 'e']]), \ frozen=['c']); Q Quiver on 5 vertices with 1 frozen vertex sage: Q.mutation_type() [ ['A', 2], ['A', 2] ] sage: Q Quiver on 5 vertices of type [ ['A', 2], ['A', 2] ] with 1 frozen vertex
From a List of edges::
sage: Q = ClusterQuiver(['A',[2,5],1]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] sage: T = ClusterQuiver( Q._digraph.edges() ); T Quiver on 7 vertices
sage: Q = ClusterQuiver([[1, 2], [2, 3], [3, 4], [4, 1]]); Q Quiver on 4 vertices
TESTS::
sage: Q = ClusterQuiver(DiGraph([[1,1]])) Traceback (most recent call last): ... ValueError: the input DiGraph contains a loop
sage: Q = ClusterQuiver([[1,1]]) Traceback (most recent call last): ... ValueError: the input DiGraph contains a loop
sage: Q = ClusterQuiver(DiGraph([[1, 0],[0,1]])) Traceback (most recent call last): ... ValueError: the input DiGraph contains two-cycles
sage: Q = ClusterQuiver('whatever') Traceback (most recent call last): ... ValueError: the input data was not recognized """ """ TESTS::
sage: Q = ClusterQuiver(['A',4]) sage: TestSuite(Q).run() """
values)}
# constructs a quiver from a mutation type print('The input specifies a mutation type, so the' ' additional parameter frozen is ignored.' ' Use set_frozen to freeze vertices.')
self.relabel(user_labels) if isinstance(user_labels, dict): self._nlist = user_labels.keys() else: self._nlist = user_labels
# constructs a quiver from string representing a mutation type # or a common quiver type (see Examples) # NOTE: for now, any string representing a *reducible type* is # coerced into the standard quiver, but there is now more flexibility # in how to input a connected (irreducible) quiver. and (isinstance(data[0], str) or all(isinstance(comp, (list,tuple)) and isinstance(comp[0], str) for comp in data))): print('The input specifies a mutation type, so the additional' ' parameter frozen is ignored. Use set_frozen to freeze vertices.')
# The command QuiverMutationType_Irreducible (which is not imported # globally) already creates the desired digraph as long as we # bypass the mutation type checking of QuiverMutationType and # format the input appropriately. Thus we handle several # special cases this way. else: else:
quiv = ClusterQuiver( QuiverMutationType_Irreducible( data[0], data[1], data[2] )._digraph ) quiv._mutation_type = mutation_type self.__init__( quiv ) else:
else: else:
else:
# constructs a quiver from a cluster seed self.__init__( data.quiver() )
# constructs a quiver from a quiver print('The input data is a quiver, therefore the additional' ' parameter frozen is ignored. Use set_frozen to freeze vertices.')
# constructs a quiver from a matrix raise ValueError('The principal part of the matrix data must be skew-symmetrizable.')
print('The input data is a matrix, therefore the additional parameter frozen is ignored. Frozen vertices read off accordingly if the matrix is not square.')
else: else:
# constructs a quiver from a digraph
raise ValueError("the optional list of frozen elements" " must be vertices of the digraph") else:
else: raise ValueError("the optional parameter 'frozen' must be" " a list of vertices of the digraph")
# frozen vertices must be preserved else: multi_edges = {} for v1,v2,label in dg.multiple_edges(): if label not in ZZ: raise ValueError("the input DiGraph contains multiple" " edges labeled by non-integers") elif (v1,v2) in multi_edges: multi_edges[(v1,v2)] += label else: multi_edges[(v1,v2)] = label dg.delete_edge(v1,v2) dg.add_edges( [ (v1,v2,multi_edges[(v1,v2)]) for v1,v2 in multi_edges ] )
raise ValueError("the input digraph contains edges" " within the frozen vertices") raise ValueError("the input digraph contains an edge with" " the wrong type of list as a label") dg.set_edge_label( edge[0], edge[1], (edge[2][0], edge[2][1])) edge = (edge[0],edge[1],(edge[2][0],edge[2][1])) raise ValueError("the input digraph contains an edge to or" " from a frozen vertex which is not skew-symmetric") raise ValueError("the input digraph contains an edge of the" " form (a,-b) with negative a")
list(range(n, n + m)) ) raise ValueError("the input digraph must be skew-symmetrizable")
self._description = 'Quiver without vertices' else:
# if data is a list of edges, the appropriate digraph is constructed.
# otherwise, an error is raised else:
# stopgap for bugs arising from coefficients
""" Returns ``True`` if ``self`` and ``other`` represent the same quiver.
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]) sage: T = Q.mutate( 2, inplace=False ) sage: Q.__eq__( T ) False sage: T.mutate( 2 ) sage: Q.__eq__( T ) True """
""" Return a hash of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]) sage: hash(Q) # indirect doctest 7654921743699262111 # 64-bit -1264862561 # 32-bit """
""" Returns the description of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]) sage: Q._repr_() "Quiver on 5 vertices of type ['A', 5]" """ name += ' of ' + self._mutation_type else:
save_pos=False, greens=[]): """ Return the plot of the underlying digraph of ``self``.
INPUT:
- ``circular`` -- (default: ``True``) if ``True``, the circular plot is chosen, otherwise >>spring<< is used. - ``center`` -- (default:(0,0)) sets the center of the circular plot, otherwise it is ignored. - ``directed`` -- (default: ``True``) if ``True``, the directed version is shown, otherwise the undirected. - ``mark`` -- (default: ``None``) if set to i, the vertex i is highlighted. - ``save_pos`` -- (default: ``False``) if ``True``, the positions of the vertices are saved. - ``greens`` -- (default: []) if set to a list, will display the green vertices as green
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]) sage: pl = Q.plot() sage: pl = Q.plot(circular=True) """ # returns positions for graph vertices on two concentric cycles with radius 1 and 2 z = CC(g2[i])*e**(-pi*I/(2*m)) g2[i] = (z.real_part(),z.imag_part()) g1[n+i] = [2*g2[i][0], 2*g2[i][1]]
# So that we don't remove elements of these lists later
# Set up our graph. If it's directed we have a digraph, else just a normal graph else: dg = Graph( self._digraph )
# For each edge in our graph we assign a color
else: else: if (a,b) == (1,-1): color_dict[ colors[1] ].append((v1,v2)) else: color_dict[ colors[5] ].append((v1,v2)) else:
# If a mark is given, then we set that mark apart from the rest # The mark is assumed to be a vertex
if mark in nlist: partition = (nlist.remove(mark), mlist, [mark]) elif mark in mlist: partition = (nlist, mlist.remove(mark), [mark]) else: raise ValueError("The given mark is not a vertex of self.") else:
# Partition out the green vertices if i in nlist: nlist.remove(i) else: mlist.remove(i)
'graph_border' : True, 'edge_colors': color_dict, 'vertex_colors': vertex_color_dict, 'edge_labels' : True, 'vertex_labels': True, } # If we're using vertex dictionary set that as key vkey = self._vertex_dictionary[v] else:
""" Show the plot of the underlying digraph of ``self``.
INPUT:
- ``fig_size`` -- (default: 1) factor by which the size of the plot is multiplied. - ``circular`` -- (default: False) if True, the circular plot is chosen, otherwise >>spring<< is used. - ``directed`` -- (default: True) if True, the directed version is shown, otherwise the undirected. - ``mark`` -- (default: None) if set to i, the vertex i is highlighted. - ``save_pos`` -- (default:False) if True, the positions of the vertices are saved. - ``greens`` -- (default:[]) if set to a list, will display the green vertices as green
TESTS::
sage: Q = ClusterQuiver(['A',5]) sage: Q.show() # long time """ n, m = self._n, self._m plot = self.plot( circular=circular, directed=directed, mark=mark, save_pos=save_pos, greens=greens) if circular: plot.show( figsize=[fig_size*3*(n+m)/4+1,fig_size*3*(n+m)/4+1] ) else: plot.show( figsize=[fig_size*n+1,fig_size*n+1] )
""" Only in notebook mode. Starts an interactive window for cluster seed mutations.
INPUT:
- ``fig_size`` -- (default: 1) factor by which the size of the plot is multiplied. - ``circular`` -- (default: False) if True, the circular plot is chosen, otherwise >>spring<< is used.
TESTS::
sage: Q = ClusterQuiver(['A',4]) sage: Q.interact() # long time 'The interactive mode only runs in the Sage notebook.' """ from sage.plot.plot import EMBEDDED_MODE from sagenb.notebook.interact import interact, selector from sage.misc.all import html,latex
if not EMBEDDED_MODE: return "The interactive mode only runs in the Sage notebook." else: seq = [] sft = [True] sss = [True] ssm = [True] ssl = [True] @interact def player(k=selector(values=list(range(self._n)),nrows = 1,label='Mutate at: '), show_seq=("Mutation sequence:", True), show_matrix=("B-Matrix:", True), show_lastmutation=("Show last mutation:", True) ): ft,ss,sm,sl = sft.pop(), sss.pop(), ssm.pop(), ssl.pop() if ft: self.show(fig_size=fig_size, circular=circular) elif show_seq is not ss or show_matrix is not sm or show_lastmutation is not sl: if seq and show_lastmutation: self.show(fig_size=fig_size, circular=circular, mark=seq[len(seq)-1]) else: self.show(fig_size=fig_size, circular=circular ) else: self.mutate(k) seq.append(k) if not show_lastmutation: self.show(fig_size=fig_size, circular=circular) else: self.show(fig_size=fig_size, circular=circular,mark=k) sft.append(False) sss.append(show_seq) ssm.append(show_matrix) ssl.append(show_lastmutation) if show_seq: html( "Mutation sequence: $" + str( [ seq[i] for i in range(len(seq)) ] ).strip('[]') + "$" ) if show_matrix: html( "B-Matrix:" ) m = self._M #m = matrix(range(1,self._n+1),sparse=True).stack(m) m = latex(m) m = m.split('(')[1].split('\\right')[0] html( "$ $" ) html( "$\\begin{align*} " + m + "\\end{align*}$" ) #html( "$" + m + "$" ) html( "$ $" )
""" Saves the plot of the underlying digraph of ``self``.
INPUT:
- ``filename`` -- the filename the image is saved to. - ``circular`` -- (default: False) if True, the circular plot is chosen, otherwise >>spring<< is used.
EXAMPLES::
sage: Q = ClusterQuiver(['F',4,[1,2]]) sage: Q.save_image(os.path.join(SAGE_TMP, 'sage.png')) """
""" Saves a .qmu file of ``self`` that can then be opened in Bernhard Keller's Quiver Applet.
INPUT:
- ``filename`` -- the filename the image is saved to.
If a filename is not specified, the default name is from_sage.qmu in the current sage directory.
EXAMPLES::
sage: Q = ClusterQuiver(['F',4,[1,2]]) sage: Q.qmu_save(os.path.join(SAGE_TMP, 'sage.qmu'))
Make sure we can save quivers with `m != n` frozen variables, see :trac:`14851`::
sage: S=ClusterSeed(['A',3]) sage: T1=S.principal_extension() sage: Q=T1.quiver() sage: Q.qmu_save(os.path.join(SAGE_TMP, 'sage.qmu')) """ filename = 'from_sage.qmu' except AttributeError: pass filename = filename + '.qmu'
""" Returns the b-matrix of ``self``.
EXAMPLES::
sage: ClusterQuiver(['A',4]).b_matrix() [ 0 1 0 0] [-1 0 -1 0] [ 0 1 0 1] [ 0 0 -1 0]
sage: ClusterQuiver(['B',4]).b_matrix() [ 0 1 0 0] [-1 0 -1 0] [ 0 1 0 1] [ 0 0 -2 0]
sage: ClusterQuiver(['D',4]).b_matrix() [ 0 1 0 0] [-1 0 -1 -1] [ 0 1 0 0] [ 0 1 0 0]
sage: ClusterQuiver(QuiverMutationType([['A',2],['B',2]])).b_matrix() [ 0 1 0 0] [-1 0 0 0] [ 0 0 0 1] [ 0 0 -2 0] """
""" Returns the underlying digraph of ``self``.
EXAMPLES::
sage: ClusterQuiver(['A',1]).digraph() Digraph on 1 vertex sage: ClusterQuiver(['A',1]).digraph().vertices() [0] sage: ClusterQuiver(['A',1]).digraph().edges() []
sage: ClusterQuiver(['A',4]).digraph() Digraph on 4 vertices sage: ClusterQuiver(['A',4]).digraph().edges() [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))]
sage: ClusterQuiver(['B',4]).digraph() Digraph on 4 vertices sage: ClusterQuiver(['A',4]).digraph().edges() [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))]
sage: ClusterQuiver(QuiverMutationType([['A',2],['B',2]])).digraph() Digraph on 4 vertices
sage: ClusterQuiver(QuiverMutationType([['A',2],['B',2]])).digraph().edges() [(0, 1, (1, -1)), (2, 3, (1, -2))]
sage: ClusterQuiver(['C', 4], user_labels = ['x', 'y', 'z', 'w']).digraph().edges() [('x', 'y', (1, -1)), ('z', 'w', (2, -1)), ('z', 'y', (1, -1))] """
""" Returns the mutation type of ``self``.
Returns the mutation_type of each connected component of self if it can be determined, otherwise, the mutation type of this component is set to be unknown.
The mutation types of the components are ordered by vertex labels.
If you do many type recognitions, you should consider to save exceptional mutation types using :meth:`~sage.combinat.cluster_algebra_quiver.quiver_mutation_type.save_quiver_data`
WARNING:
- All finite types can be detected, - All affine types can be detected, EXCEPT affine type D (the algorithm is not yet implemented) - All exceptional types can be detected.
EXAMPLES::
sage: ClusterQuiver(['A',4]).mutation_type() ['A', 4] sage: ClusterQuiver(['A',(3,1),1]).mutation_type() ['A', [1, 3], 1] sage: ClusterQuiver(['C',2]).mutation_type() ['B', 2] sage: ClusterQuiver(['B',4,1]).mutation_type() ['BD', 4, 1]
finite types::
sage: Q = ClusterQuiver(['A',5]) sage: Q._mutation_type = None sage: Q.mutation_type() ['A', 5]
sage: Q = ClusterQuiver([(0,1),(1,2),(2,3),(3,4)]) sage: Q.mutation_type() ['A', 5]
sage: Q = ClusterQuiver(DiGraph([['a', 'b'], ['c', 'b'], ['c', 'd'], ['e', 'd']]), ....: frozen=['c']) sage: Q.mutation_type() [ ['A', 2], ['A', 2] ]
affine types::
sage: Q = ClusterQuiver(['E',8,[1,1]]); Q Quiver on 10 vertices of type ['E', 8, [1, 1]] sage: Q._mutation_type = None; Q Quiver on 10 vertices sage: Q.mutation_type() # long time ['E', 8, [1, 1]]
the not yet working affine type D (unless user has saved small classical quiver data)::
sage: Q = ClusterQuiver(['D',4,1]) sage: Q._mutation_type = None sage: Q.mutation_type() # todo: not implemented ['D', 4, 1]
the exceptional types::
sage: Q = ClusterQuiver(['X',6]) sage: Q._mutation_type = None sage: Q.mutation_type() # long time ['X', 6]
examples from page 8 of [Ke2008]_::
sage: dg = DiGraph(); dg.add_edges([(9,0),(9,4),(4,6),(6,7),(7,8),(8,3),(3,5),(5,6),(8,1),(2,3)]) sage: ClusterQuiver( dg ).mutation_type() # long time ['E', 8, [1, 1]]
sage: dg = DiGraph( { 0:[3], 1:[0,4], 2:[0,6], 3:[1,2,7], 4:[3,8], 5:[2], 6:[3,5], 7:[4,6], 8:[7] } ) sage: ClusterQuiver( dg ).mutation_type() # long time ['E', 8, 1]
sage: dg = DiGraph( { 0:[3,9], 1:[0,4], 2:[0,6], 3:[1,2,7], 4:[3,8], 5:[2], 6:[3,5], 7:[4,6], 8:[7], 9:[1] } ) sage: ClusterQuiver( dg ).mutation_type() # long time ['E', 8, [1, 1]]
infinite types::
sage: Q = ClusterQuiver(['GR',[4,9]]) sage: Q._mutation_type = None sage: Q.mutation_type() 'undetermined infinite mutation type'
reducible types::
sage: Q = ClusterQuiver([['A', 3], ['B', 3]]) sage: Q._mutation_type = None sage: Q.mutation_type() [ ['A', 3], ['B', 3] ]
sage: Q = ClusterQuiver([['A', 3], ['T', [4,4,4]]]) sage: Q._mutation_type = None sage: Q.mutation_type() [['A', 3], 'undetermined infinite mutation type']
sage: Q = ClusterQuiver([['A', 3], ['B', 3], ['T', [4,4,4]]]) sage: Q._mutation_type = None sage: Q.mutation_type() [['A', 3], ['B', 3], 'undetermined infinite mutation type']
sage: Q = ClusterQuiver([[0,1,2],[1,2,2],[2,0,2],[3,4,1],[4,5,1]]) sage: Q.mutation_type() ['undetermined finite mutation type', ['A', 3]]
TESTS::
sage: Q = ClusterQuiver(matrix([[0, 3], [-1, 0], [1, 0], [0, 1]])) sage: Q.mutation_type() ['G', 2] sage: Q = ClusterQuiver(matrix([[0, -1, -1, 1, 0], [1, 0, 1, 0, 1], [1, -1, 0, -1, 0], [-1, 0, 1, 0, 1], [0, -1, 0, -1, 0], [0, 1, 0, -1, -1], [0, 1, -1, 0, 0]])) sage: Q.mutation_type() 'undetermined infinite mutation type' """ # checking if the mutation type is known already # checking mutation type only for the principal part
else:
# checking the type for each connected component # constructing the digraph for this component # turning dg_component into a canonical form # turning dg_component into a canonical form # and getting the corresponding matrix
# checking if this quiver is mutation infinite else: # checking if this quiver is in the database # checking if the algorithm can determine the mutation type # checking if this quiver is of exceptional type by computing the exceptional mutation classes
# the empty quiver case Warning('Quiver has no vertices') mutation_type = None # the connected quiver case # the reducible quiver case else:
""" Returns the number of free vertices of ``self``.
EXAMPLES::
sage: ClusterQuiver(['A',4]).n() 4 sage: ClusterQuiver(['A',(3,1),1]).n() 4 sage: ClusterQuiver(['B',4]).n() 4 sage: ClusterQuiver(['B',4,1]).n() 5 """
""" Returns the number of frozen vertices of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(['A',4]) sage: Q.m() 0
sage: T = ClusterQuiver(Q.digraph().edges(), frozen=[3]) sage: T.n() 3 sage: T.m() 1 """
""" Return the list of free vertices of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(DiGraph([['a', 'b'], ['c', 'b'], ['c', 'd'], ['e', 'd']]), ....: frozen=['b', 'd']) sage: Q.free_vertices() ['a', 'c', 'e'] """
""" Return the list of frozen vertices of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(DiGraph([['a', 'b'], ['c', 'b'], ['c', 'd'], ['e', 'd']]), ....: frozen=['b', 'd']) sage: Q.frozen_vertices() ['b', 'd'] """
""" Returns the canonical labelling of ``self``, see :meth:`sage.graphs.generic_graph.GenericGraph.canonical_label`.
INPUT:
- ``certificate`` -- (default: False) if True, the dictionary from ``self.vertices()`` to the vertices of the returned quiver is returned as well.
EXAMPLES::
sage: Q = ClusterQuiver(['A',4]); Q.digraph().edges() [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))]
sage: T = Q.canonical_label(); T.digraph().edges() [(0, 3, (1, -1)), (1, 2, (1, -1)), (1, 3, (1, -1))]
sage: T,iso = Q.canonical_label(certificate=True); T.digraph().edges(); iso [(0, 3, (1, -1)), (1, 2, (1, -1)), (1, 3, (1, -1))] {0: 0, 1: 3, 2: 1, 3: 2}
sage: Q = ClusterQuiver(QuiverMutationType([['B',2],['A',1]])); Q Quiver on 3 vertices of type [ ['B', 2], ['A', 1] ]
sage: Q.canonical_label() Quiver on 3 vertices of type [ ['A', 1], ['B', 2] ]
sage: Q.canonical_label(certificate=True) (Quiver on 3 vertices of type [ ['A', 1], ['B', 2] ], {0: 1, 1: 2, 2: 0})
TESTS::
sage: Q = ClusterQuiver(['A',4]) sage: _,iso = Q.canonical_label(certify=True); iso doctest:...: DeprecationWarning: use the option 'certificate' instead of 'certify' See http://trac.sagemath.org/21111 for details. {0: 0, 1: 3, 2: 1, 3: 2} """
# computing the canonical form respecting the frozen variables # getting the new ordering for the mutation type if necessary else: else:
""" Returns true if ``self`` is acyclic.
EXAMPLES::
sage: ClusterQuiver(['A',4]).is_acyclic() True
sage: ClusterQuiver(['A',[2,1],1]).is_acyclic() True
sage: ClusterQuiver([[0,1],[1,2],[2,0]]).is_acyclic() False """
""" Returns true if ``self`` is bipartite.
EXAMPLES::
sage: ClusterQuiver(['A',[3,3],1]).is_bipartite() True
sage: ClusterQuiver(['A',[4,3],1]).is_bipartite() False """ else: else:
""" Returns the restriction to the principal part (i.e. exchangeable part) of ``self``, the subquiver obtained by deleting the frozen vertices of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(['A',4]) sage: T = ClusterQuiver(Q.digraph().edges(), frozen=[3]) sage: T.digraph().edges() [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))]
sage: T.exchangeable_part().digraph().edges() [(0, 1, (1, -1)), (2, 1, (1, -1))]
sage: Q2 = Q.principal_extension() sage: Q3 = Q2.principal_extension() sage: Q2.exchangeable_part() == Q3.exchangeable_part() True """
""" Returns the principal extension of ``self``, adding n frozen vertices to any previously frozen vertices. I.e., the quiver obtained by adding an outgoing edge to every mutable vertex of ``self``.
EXAMPLES::
sage: Q = ClusterQuiver(['A',2]); Q Quiver on 2 vertices of type ['A', 2] sage: T = Q.principal_extension(); T Quiver on 4 vertices of type ['A', 2] with 2 frozen vertices sage: T2 = T.principal_extension(); T2 Quiver on 6 vertices of type ['A', 2] with 4 frozen vertices sage: Q.digraph().edges() [(0, 1, (1, -1))] sage: T.digraph().edges() [(0, 1, (1, -1)), (2, 0, (1, -1)), (3, 1, (1, -1))] sage: T2.digraph().edges() [(0, 1, (1, -1)), (2, 0, (1, -1)), (3, 1, (1, -1)), (4, 0, (1, -1)), (5, 1, (1, -1))] """ self.__init__(Q) else:
r""" Return the first vertex of ``self`` that is a sink
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]); sage: Q.mutate([1,2,4,3,2]); sage: Q.first_sink() 0 """
return None
r""" Return all vertices of ``self`` that are sinks
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]); sage: Q.mutate([1,2,4,3,2]); sage: Q.sinks() [0, 2]
sage: Q = ClusterQuiver(['A',5]) sage: Q.mutate([2,1,3,4,2]) sage: Q.sinks() [3] """
r""" Return the first vertex of ``self`` that is a source
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]) sage: Q.mutate([2,1,3,4,2]) sage: Q.first_source() 1 """
return None
r""" Returns all vertices of ``self`` that are sources
EXAMPLES::
sage: Q = ClusterQuiver(['A',5]); sage: Q.mutate([1,2,4,3,2]); sage: Q.sources() []
sage: Q = ClusterQuiver(['A',5]) sage: Q.mutate([2,1,3,4,2]) sage: Q.sources() [1] """
""" Mutates ``self`` at a sequence of vertices.
INPUT:
- ``sequence`` -- a vertex of ``self``, an iterator of vertices of ``self``, a function which takes in the ClusterQuiver and returns a vertex or an iterator of vertices, or a string of the parameter wanting to be called on ClusterQuiver that will return a vertex or an iterator of vertices. - ``inplace`` -- (default: True) if False, the result is returned, otherwise ``self`` is modified.
EXAMPLES::
sage: Q = ClusterQuiver(['A',4]); Q.b_matrix() [ 0 1 0 0] [-1 0 -1 0] [ 0 1 0 1] [ 0 0 -1 0]
sage: Q.mutate(0); Q.b_matrix() [ 0 -1 0 0] [ 1 0 -1 0] [ 0 1 0 1] [ 0 0 -1 0]
sage: T = Q.mutate(0, inplace=False); T Quiver on 4 vertices of type ['A', 4]
sage: Q.mutate(0) sage: Q == T True
sage: Q.mutate([0,1,0]) sage: Q.b_matrix() [ 0 -1 1 0] [ 1 0 0 0] [-1 0 0 1] [ 0 0 -1 0]
sage: Q = ClusterQuiver(QuiverMutationType([['A',1],['A',3]])) sage: Q.b_matrix() [ 0 0 0 0] [ 0 0 1 0] [ 0 -1 0 -1] [ 0 0 1 0]
sage: T = Q.mutate(0,inplace=False) sage: Q == T True
sage: Q = ClusterQuiver(['A',3]); Q.b_matrix() [ 0 1 0] [-1 0 -1] [ 0 1 0] sage: Q.mutate('first_sink'); Q.b_matrix() [ 0 -1 0] [ 1 0 1] [ 0 -1 0] sage: Q.mutate('first_source'); Q.b_matrix() [ 0 1 0] [-1 0 -1] [ 0 1 0]
sage: Q2 = ClusterQuiver(DiGraph([['a', 'b'], ['b', 'c'], ['c', 'd'], ['d', 'e']]),\ frozen=['c']); Q2.b_matrix() [ 0 1 0 0] [-1 0 0 0] [ 0 0 0 1] [ 0 0 -1 0] [ 0 -1 1 0] sage: Q2.mutate('a'); Q2.b_matrix() [ 0 -1 0 0] [ 1 0 0 0] [ 0 0 0 1] [ 0 0 -1 0] [ 0 -1 1 0]
sage: Q = ClusterQuiver(DiGraph([['a', 'b'], ['b', 'c']]));Q Quiver on 3 vertices sage: Q.mutate(['a','b'],inplace = False).digraph().edges() [('a', 'b', (1, -1)), ('c', 'b', (1, -1))]
TESTS::
sage: Q = ClusterQuiver(['A',4]); Q.mutate(0,1) Traceback (most recent call last): ... ValueError: The second parameter must be boolean. To mutate at a sequence of length 2, input it as a list.
sage: Q = ClusterQuiver(['A',4]); Q.mutate(0,0) Traceback (most recent call last): ... ValueError: The second parameter must be boolean. To mutate at a sequence of length 2, input it as a list. """
# If we get a string which is not a cluster variable, execute as a function
# If we get a function, execute it # function should return either integer or sequence data = data(self)
raise ValueError('Not mutating: No vertices given.')
else: seq = list( seq ) raise ValueError('The quiver can only be mutated at a vertex or at a sequence of vertices') v = next(v for v in seq if v not in V) raise ValueError('The quiver cannot be mutated at the vertex %s'%v)
else:
""" Returns a list containing the sequence of quivers obtained from ``self`` by a sequence of mutations on vertices.
INPUT:
- ``sequence`` -- a list or tuple of vertices of ``self``. - ``show_sequence`` -- (default: False) if True, a png containing the mutation sequence is shown. - ``fig_size`` -- (default: 1.2) factor by which the size of the sequence is expanded.
EXAMPLES::
sage: Q = ClusterQuiver(['A',4]) sage: seq = Q.mutation_sequence([0,1]); seq [Quiver on 4 vertices of type ['A', 4], Quiver on 4 vertices of type ['A', 4], Quiver on 4 vertices of type ['A', 4]] sage: [T.b_matrix() for T in seq] [ [ 0 1 0 0] [ 0 -1 0 0] [ 0 1 -1 0] [-1 0 -1 0] [ 1 0 -1 0] [-1 0 1 0] [ 0 1 0 1] [ 0 1 0 1] [ 1 -1 0 1] [ 0 0 -1 0], [ 0 0 -1 0], [ 0 0 -1 0] ] """ else: width_factor = 6 fig_size = fig_size*4*n/3
sequence = list( sequence ) raise ValueError('The quiver can only be mutated at a vertex or at a sequence of vertices') v = next(v for v in sequence if v not in V) raise ValueError('The quiver can only be mutated at the vertex %s'%v )
def _plot_arrow( v, k, center=(0,0) ): return text("$\longleftrightarrow$",(center[0],center[1]), fontsize=25) + text("$\mu_"+str(v)+"$",(center[0],center[1]+0.15), fontsize=15) \ + text("$"+str(k)+"$",(center[0],center[1]-0.2), fontsize=15) plot_sequence = [ quiver_sequence[i].plot( circular=True, center=(i*width_factor,0) ) for i in range(len(quiver_sequence)) ] arrow_sequence = [ _plot_arrow( sequence[i],i+1,center=((i+0.5)*width_factor,0) ) for i in range(len(sequence)) ] sequence = [] for i in range( len( plot_sequence ) ): if i < len( arrow_sequence ): sequence.append( plot_sequence[i] + arrow_sequence[i] ) else: sequence.append( plot_sequence[i] ) plot_obj = Graphics() for elem in sequence: plot_obj += elem plot_obj.show(axes=False, figsize=[fig_size*len(quiver_sequence),fig_size])
""" Reorient ``self`` with respect to the given total order, or with respect to an iterator of edges in ``self`` to be reverted.
.. WARNING::
This operation might change the mutation type of ``self``.
INPUT:
- ``data`` -- an iterator defining a total order on ``self.vertices()``, or an iterator of edges in ``self`` to be reoriented.
EXAMPLES::
sage: Q = ClusterQuiver(['A',(2,3),1]) sage: Q.mutation_type() ['A', [2, 3], 1]
sage: Q.reorient([(0,1),(1,2),(2,3),(3,4)]) sage: Q.mutation_type() ['D', 5]
sage: Q.reorient([0,1,2,3,4]) sage: Q.mutation_type() ['A', [1, 4], 1]
TESTS::
sage: Q = ClusterQuiver(['A',2]) sage: Q.reorient([]) Traceback (most recent call last): ... ValueError: empty input sage: Q.reorient([3,4]) Traceback (most recent call last): ... ValueError: not a total order on the vertices of the quiver or a list of edges to be oriented """
else: self._nlist, self._mlist) self._nlist, self._mlist) else:
""" Returns an iterator for the mutation class of self together with certain constrains.
INPUT:
- ``depth`` -- (default: infinity) integer, only quivers with distance at most depth from self are returned. - ``show_depth`` -- (default: False) if True, the actual depth of the mutation is shown. - ``return_paths`` -- (default: False) if True, a shortest path of mutation sequences from self to the given quiver is returned as well. - ``data_type`` -- (default: "quiver") can be one of the following::
* "quiver" * "matrix" * "digraph" * "dig6" * "path"
- ``up_to_equivalence`` -- (default: True) if True, only one quiver for each graph-isomorphism class is recorded. - ``sink_source`` -- (default: False) if True, only mutations at sinks and sources are applied.
EXAMPLES::
sage: Q = ClusterQuiver(['A',3]) sage: it = Q.mutation_class_iter() sage: for T in it: print(T) Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3]
sage: it = Q.mutation_class_iter(depth=1) sage: for T in it: print(T) Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3]
sage: it = Q.mutation_class_iter(show_depth=True) sage: for T in it: pass Depth: 0 found: 1 Time: ... s Depth: 1 found: 3 Time: ... s Depth: 2 found: 4 Time: ... s
sage: it = Q.mutation_class_iter(return_paths=True) sage: for T in it: print(T) (Quiver on 3 vertices of type ['A', 3], []) (Quiver on 3 vertices of type ['A', 3], [1]) (Quiver on 3 vertices of type ['A', 3], [0]) (Quiver on 3 vertices of type ['A', 3], [0, 1])
sage: it = Q.mutation_class_iter(up_to_equivalence=False) sage: for T in it: print(T) Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3]
sage: it = Q.mutation_class_iter(return_paths=True,up_to_equivalence=False) sage: for T in it: print(T) (Quiver on 3 vertices of type ['A', 3], []) (Quiver on 3 vertices of type ['A', 3], [2]) (Quiver on 3 vertices of type ['A', 3], [1]) (Quiver on 3 vertices of type ['A', 3], [0]) (Quiver on 3 vertices of type ['A', 3], [2, 1]) (Quiver on 3 vertices of type ['A', 3], [0, 1]) (Quiver on 3 vertices of type ['A', 3], [0, 1, 2]) (Quiver on 3 vertices of type ['A', 3], [0, 1, 0]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 2]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 0]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 0, 2]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 0, 1]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 2, 1]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 2, 0])
sage: Q = ClusterQuiver(['A',3]) sage: it = Q.mutation_class_iter(data_type='path') sage: for T in it: print(T) [] [1] [0] [0, 1]
sage: Q = ClusterQuiver(['A',3]) sage: it = Q.mutation_class_iter(return_paths=True,data_type='matrix') sage: next(it) ( [ 0 0 1] [ 0 0 1] [-1 -1 0], [] )
sage: S = ClusterQuiver(DiGraph([['a', 'b'], ['b', 'c']]), frozen=['b']) sage: S.mutation_class() [Quiver on 3 vertices with 1 frozen vertex, Quiver on 3 vertices with 1 frozen vertex, Quiver on 3 vertices with 1 frozen vertex] """ else: return_dig6=return_dig6, show_depth=show_depth, up_to_equivalence=up_to_equivalence, sink_source=sink_source) next_element = data[0] else: raise ValueError("the parameter for data_type was " "not recognized") else:
data_type="quiver", up_to_equivalence=True, sink_source=False): """ Return the mutation class of ``self`` together with certain constrains.
INPUT:
- ``depth`` -- (default: ``infinity`) integer, only seeds with distance at most depth from ``self`` are returned - ``show_depth`` -- (default: ``False``) if ``True``, the actual depth of the mutation is shown - ``return_paths`` -- (default: ``False``) if ``True``, a shortest path of mutation sequences from self to the given quiver is returned as well - ``data_type`` -- (default: ``"quiver"``) can be one of the following:
* ``"quiver"`` -- the quiver is returned * ``"dig6"`` -- the dig6-data is returned * ``"path"`` -- shortest paths of mutation sequences from ``self`` are returned
- ``sink_source`` -- (default: ``False``) if ``True``, only mutations at sinks and sources are applied
EXAMPLES::
sage: Q = ClusterQuiver(['A',3]) sage: Ts = Q.mutation_class() sage: for T in Ts: print(T) Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3]
sage: Ts = Q.mutation_class(depth=1) sage: for T in Ts: print(T) Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3]
sage: Ts = Q.mutation_class(show_depth=True) Depth: 0 found: 1 Time: ... s Depth: 1 found: 3 Time: ... s Depth: 2 found: 4 Time: ... s
sage: Ts = Q.mutation_class(return_paths=True) sage: for T in Ts: print(T) (Quiver on 3 vertices of type ['A', 3], []) (Quiver on 3 vertices of type ['A', 3], [1]) (Quiver on 3 vertices of type ['A', 3], [0]) (Quiver on 3 vertices of type ['A', 3], [0, 1])
sage: Ts = Q.mutation_class(up_to_equivalence=False) sage: for T in Ts: print(T) Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3] Quiver on 3 vertices of type ['A', 3]
sage: Ts = Q.mutation_class(return_paths=True,up_to_equivalence=False) sage: for T in Ts: print(T) (Quiver on 3 vertices of type ['A', 3], []) (Quiver on 3 vertices of type ['A', 3], [2]) (Quiver on 3 vertices of type ['A', 3], [1]) (Quiver on 3 vertices of type ['A', 3], [0]) (Quiver on 3 vertices of type ['A', 3], [2, 1]) (Quiver on 3 vertices of type ['A', 3], [0, 1]) (Quiver on 3 vertices of type ['A', 3], [0, 1, 2]) (Quiver on 3 vertices of type ['A', 3], [0, 1, 0]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 2]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 0]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 0, 2]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 0, 1]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 2, 1]) (Quiver on 3 vertices of type ['A', 3], [2, 1, 2, 0])
sage: Ts = Q.mutation_class(show_depth=True) Depth: 0 found: 1 Time: ... s Depth: 1 found: 3 Time: ... s Depth: 2 found: 4 Time: ... s
sage: Ts = Q.mutation_class(show_depth=True, up_to_equivalence=False) Depth: 0 found: 1 Time: ... s Depth: 1 found: 4 Time: ... s Depth: 2 found: 6 Time: ... s Depth: 3 found: 10 Time: ... s Depth: 4 found: 14 Time: ... s
TESTS::
sage: all(len(ClusterQuiver(['A',n]).mutation_class()) ....: == ClusterQuiver(['A',n]).mutation_type().class_size() ....: for n in [2..6]) True
sage: all(len(ClusterQuiver(['B',n]).mutation_class()) ....: == ClusterQuiver(['B',n]).mutation_type().class_size() ....: for n in [2..6]) True """ raise ValueError('the mutation class can - for infinite mutation' ' types - only be computed up to a given depth') return_paths=return_paths, data_type=data_type, up_to_equivalence=up_to_equivalence, sink_source=sink_source)]
""" Return ``True`` if ``self`` is of finite type.
EXAMPLES::
sage: Q = ClusterQuiver(['A',3]) sage: Q.is_finite() True sage: Q = ClusterQuiver(['A',[2,2],1]) sage: Q.is_finite() False sage: Q = ClusterQuiver([['A',3],['B',3]]) sage: Q.is_finite() True sage: Q = ClusterQuiver(['T',[4,4,4]]) sage: Q.is_finite() False sage: Q = ClusterQuiver([['A',3],['T',[4,4,4]]]) sage: Q.is_finite() False sage: Q = ClusterQuiver([['A',3],['T',[2,2,3]]]) sage: Q.is_finite() True sage: Q = ClusterQuiver([['A',3],['D',5]]) sage: Q.is_finite() True sage: Q = ClusterQuiver([['A',3],['D',5,1]]) sage: Q.is_finite() False
sage: Q = ClusterQuiver([[0,1,2],[1,2,2],[2,0,2]]) sage: Q.is_finite() False
sage: Q = ClusterQuiver([[0,1,2],[1,2,2],[2,0,2],[3,4,1],[4,5,1]]) sage: Q.is_finite() False """ else:
""" Uses a non-deterministic method by random mutations in various directions. Can result in a wrong answer.
INPUT:
- ``nr_of_checks`` -- (default: None) number of mutations applied. Standard is 500*(number of vertices of self). - ``return_path`` -- (default: False) if True, in case of self not being mutation finite, a path from self to a quiver with an edge label (a,-b) and a*b > 4 is returned.
ALGORITHM:
A quiver is mutation infinite if and only if every edge label (a,-b) satisfy a*b > 4. Thus, we apply random mutations in random directions
EXAMPLES::
sage: Q = ClusterQuiver(['A',10]) sage: Q._mutation_type = None sage: Q.is_mutation_finite() True
sage: Q = ClusterQuiver([(0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(2,9)]) sage: Q.is_mutation_finite() False """ is_finite = False is_finite = False else: # turning dg_component into a canonical form # and getting the corresponding matrix
return is_finite, path else:
r""" Return the total number of edges on the quiver
Note: This only works with non-valued quivers. If used on a non-valued quiver then the positive value is taken to be the number of edges added
OUTPUT:
An integer of the number of edges.
EXAMPLES::
sage: S = ClusterQuiver(['A',4]); S.number_of_edges() 3
sage: S = ClusterQuiver(['B',4]); S.number_of_edges() 3 """
r""" Return the quiver after doing a relabelling
Will relabel the vertices of the quiver
INPUT:
- ``relabelling`` -- Dictionary of labels to move around - ``inplace`` -- (default:True) if True, will return a duplicate of the quiver
EXAMPLES::
sage: S = ClusterQuiver(['A',4]).relabel({1:'5',2:'go'}) """ else: quiver = ClusterQuiver(self)
# Instantiation variables
# Organize labels noting that for: # _digraph: { old_vertex: new_vertex} # _vertex_dictionary: {num: new_vertex} # need to make sure we map correctly
# If the key is in the old vertices, use that mapping # And place it in the right order for our dictionary elif isinstance(key, int) and len(old_vertices) > key: # If the key is an integer, grab that particular vertex digraph_labels[old_vertices[key]] = val # And copy it over to our dictionary dict_labels[key] = val
r""" Return the d-vector fan associated with the quiver.
It is the fan whose maximal cones are generated by the d-matrices of the clusters.
This is a complete simplicial fan (and even smooth when the initial quiver is acyclic). It only makes sense for quivers of finite type.
EXAMPLES::
sage: Fd = ClusterQuiver([[1,2]]).d_vector_fan(); Fd Rational polyhedral fan in 2-d lattice N sage: Fd.ngenerating_cones() 5
sage: Fd = ClusterQuiver([[1,2],[2,3]]).d_vector_fan(); Fd Rational polyhedral fan in 3-d lattice N sage: Fd.ngenerating_cones() 14 sage: Fd.is_smooth() True
sage: Fd = ClusterQuiver([[1,2],[2,3],[3,1]]).d_vector_fan(); Fd Rational polyhedral fan in 3-d lattice N sage: Fd.ngenerating_cones() 14 sage: Fd.is_smooth() False
TESTS::
sage: ClusterQuiver(['A',[2,2],1]).d_vector_fan() Traceback (most recent call last): ... ValueError: only makes sense for quivers of finite type """
for s in seed.mutation_class()])
r""" Return the g-vector fan associated with the quiver.
It is the fan whose maximal cones are generated by the g-matrices of the clusters.
This is a complete simplicial fan. It is only supported for quivers of finite type.
EXAMPLES::
sage: Fg = ClusterQuiver([[1,2]]).g_vector_fan(); Fg Rational polyhedral fan in 2-d lattice N sage: Fg.ngenerating_cones() 5
sage: Fg = ClusterQuiver([[1,2],[2,3]]).g_vector_fan(); Fg Rational polyhedral fan in 3-d lattice N sage: Fg.ngenerating_cones() 14 sage: Fg.is_smooth() True
sage: Fg = ClusterQuiver([[1,2],[2,3],[3,1]]).g_vector_fan(); Fg Rational polyhedral fan in 3-d lattice N sage: Fg.ngenerating_cones() 14 sage: Fg.is_smooth() True
TESTS::
sage: ClusterQuiver(['A',[2,2],1]).g_vector_fan() Traceback (most recent call last): ... ValueError: only supported for quivers of finite type """
for s in seed.mutation_class()]) |