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
See also
For mutation types of combinatorial quivers, see QuiverMutationType()
. Cluster seeds are closely related to ClusterSeed()
.
- class sage.combinat.cluster_algebra_quiver.quiver.ClusterQuiver(data, frozen=None, user_labels=None)[source]¶
Bases:
SageObject
The quiver associated to an exchange matrix.
INPUT:
data
– can be any of the following:* :class:`QuiverMutationType` * :class:`str` -- string representing a :class:`QuiverMutationType` or a common quiver type (see Examples) * :class:`ClusterQuiver` * :class:`Matrix` -- a skew-symmetrizable matrix * :class:`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 aDiGraph
, it is ignored otherwiseuser_labels
– (default:None
) sets the names of the labels for the vertices of the quiver if the input type is not aDiGraph
; otherwise it is ignored
EXAMPLES:
From a
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 sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]); Q Quiver on 5 vertices of type ['A', 5] >>> Q = ClusterQuiver(['B',Integer(2)]); Q Quiver on 2 vertices of type ['B', 2] >>> Q2 = ClusterQuiver(['C',Integer(2)]); Q2 Quiver on 2 vertices of type ['B', 2] >>> MT = Q.mutation_type(); MT.standard_quiver() == Q True >>> MT = Q2.mutation_type(); MT.standard_quiver() == Q2 False >>> Q = ClusterQuiver(['A',[Integer(2),Integer(5)],Integer(1)]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] >>> Q = ClusterQuiver(['A', [Integer(5),Integer(0)],Integer(1)]); Q Quiver on 5 vertices of type ['D', 5] >>> Q.is_finite() True >>> Q.is_acyclic() False >>> Q = ClusterQuiver(['F', Integer(4), [Integer(2),Integer(1)]]); Q Quiver on 6 vertices of type ['F', 4, [1, 2]] >>> MT = Q.mutation_type(); MT.standard_quiver() == Q False >>> dg = Q.digraph(); Q.mutate([Integer(2),Integer(1),Integer(4),Integer(0),Integer(5),Integer(3)]) >>> dg2 = Q.digraph(); dg2.is_isomorphic(dg,edge_labels=True) False >>> dg2.is_isomorphic(MT.standard_quiver().digraph(),edge_labels=True) True >>> Q = ClusterQuiver(['G',Integer(2), (Integer(3),Integer(1))]); Q Quiver on 4 vertices of type ['G', 2, [1, 3]] >>> MT = Q.mutation_type(); MT.standard_quiver() == Q False >>> Q = ClusterQuiver(['GR',[Integer(3),Integer(6)]]); Q Quiver on 4 vertices of type ['D', 4] >>> MT = Q.mutation_type(); MT.standard_quiver() == Q False >>> Q = ClusterQuiver(['GR',[Integer(3),Integer(7)]]); Q Quiver on 6 vertices of type ['E', 6] >>> Q = ClusterQuiver(['TR',Integer(2)]); Q Quiver on 3 vertices of type ['A', 3] >>> MT = Q.mutation_type(); MT.standard_quiver() == Q False >>> Q.mutate([Integer(1),Integer(0)]); MT.standard_quiver() == Q True >>> Q = ClusterQuiver(['TR',Integer(3)]); Q Quiver on 6 vertices of type ['D', 6] >>> MT = Q.mutation_type(); MT.standard_quiver() == Q False
From a
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 sage.all import * >>> Q = ClusterQuiver(['A',[Integer(2),Integer(5)],Integer(1)]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] >>> 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 sage.all import * >>> Q = ClusterQuiver(['A',[Integer(2),Integer(5)],Integer(1)]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] >>> T = ClusterQuiver( Q._M ); T Quiver on 7 vertices >>> Q = ClusterQuiver( matrix([[Integer(0),Integer(1),-Integer(1)],[-Integer(1),Integer(0),Integer(1)],[Integer(1),-Integer(1),Integer(0)],[Integer(1),Integer(2),Integer(3)]]) ); Q Quiver on 4 vertices with 1 frozen vertex >>> 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 sage.all import * >>> Q = ClusterQuiver(['A',[Integer(2),Integer(5)],Integer(1)]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] >>> T = ClusterQuiver( Q._digraph ); T Quiver on 7 vertices >>> Q = ClusterQuiver( DiGraph([[Integer(1),Integer(2)],[Integer(2),Integer(3)],[Integer(3),Integer(4)],[Integer(4),Integer(1)]]) ); Q Quiver on 4 vertices >>> Q = ClusterQuiver(DiGraph([['a', 'b'], ['b', 'c'], ['c', 'd'], ['d', 'e']]), ... frozen=['c']); Q Quiver on 5 vertices with 1 frozen vertex >>> Q.mutation_type() [ ['A', 2], ['A', 2] ] >>> 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(sort=True) ); T Quiver on 7 vertices sage: Q = ClusterQuiver([[1, 2], [2, 3], [3, 4], [4, 1]]); Q Quiver on 4 vertices
>>> from sage.all import * >>> Q = ClusterQuiver(['A',[Integer(2),Integer(5)],Integer(1)]); Q Quiver on 7 vertices of type ['A', [2, 5], 1] >>> T = ClusterQuiver( Q._digraph.edges(sort=True) ); T Quiver on 7 vertices >>> Q = ClusterQuiver([[Integer(1), Integer(2)], [Integer(2), Integer(3)], [Integer(3), Integer(4)], [Integer(4), Integer(1)]]); Q Quiver on 4 vertices
- b_matrix()[source]¶
Return 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]
>>> from sage.all import * >>> ClusterQuiver(['A',Integer(4)]).b_matrix() [ 0 1 0 0] [-1 0 -1 0] [ 0 1 0 1] [ 0 0 -1 0] >>> ClusterQuiver(['B',Integer(4)]).b_matrix() [ 0 1 0 0] [-1 0 -1 0] [ 0 1 0 1] [ 0 0 -2 0] >>> ClusterQuiver(['D',Integer(4)]).b_matrix() [ 0 1 0 0] [-1 0 -1 -1] [ 0 1 0 0] [ 0 1 0 0] >>> ClusterQuiver(QuiverMutationType([['A',Integer(2)],['B',Integer(2)]])).b_matrix() [ 0 1 0 0] [-1 0 0 0] [ 0 0 0 1] [ 0 0 -2 0]
- canonical_label(certificate=False)[source]¶
Return the canonical labelling of
self
.See
sage.graphs.generic_graph.GenericGraph.canonical_label()
.INPUT:
certificate
– boolean (default:False
); ifTrue
, the dictionary fromself.vertices()
to the vertices of the returned quiver is returned as well
EXAMPLES:
sage: Q = ClusterQuiver(['A',4]); Q.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))] sage: T = Q.canonical_label(); T.digraph().edges(sort=True) [(0, 3, (1, -1)), (1, 2, (1, -1)), (1, 3, (1, -1))] sage: T, iso = Q.canonical_label(certificate=True) sage: T.digraph().edges(sort=True); 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})
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(4)]); Q.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))] >>> T = Q.canonical_label(); T.digraph().edges(sort=True) [(0, 3, (1, -1)), (1, 2, (1, -1)), (1, 3, (1, -1))] >>> T, iso = Q.canonical_label(certificate=True) >>> T.digraph().edges(sort=True); iso [(0, 3, (1, -1)), (1, 2, (1, -1)), (1, 3, (1, -1))] {0: 0, 1: 3, 2: 1, 3: 2} >>> Q = ClusterQuiver(QuiverMutationType([['B',Integer(2)],['A',Integer(1)]])); Q Quiver on 3 vertices of type [ ['B', 2], ['A', 1] ] >>> Q.canonical_label() Quiver on 3 vertices of type [ ['A', 1], ['B', 2] ] >>> Q.canonical_label(certificate=True) (Quiver on 3 vertices of type [ ['A', 1], ['B', 2] ], {0: 1, 1: 2, 2: 0})
- d_vector_fan()[source]¶
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: # needs sage.geometry.polyhedron sage.libs.singular 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
>>> from sage.all import * >>> # needs sage.geometry.polyhedron sage.libs.singular >>> Fd = ClusterQuiver([[Integer(1),Integer(2)]]).d_vector_fan(); Fd Rational polyhedral fan in 2-d lattice N >>> Fd.ngenerating_cones() 5 >>> Fd = ClusterQuiver([[Integer(1),Integer(2)],[Integer(2),Integer(3)]]).d_vector_fan(); Fd Rational polyhedral fan in 3-d lattice N >>> Fd.ngenerating_cones() 14 >>> Fd.is_smooth() True >>> Fd = ClusterQuiver([[Integer(1),Integer(2)],[Integer(2),Integer(3)],[Integer(3),Integer(1)]]).d_vector_fan(); Fd Rational polyhedral fan in 3-d lattice N >>> Fd.ngenerating_cones() 14 >>> Fd.is_smooth() False
- digraph()[source]¶
Return the underlying digraph of
self
.EXAMPLES:
sage: ClusterQuiver(['A',1]).digraph() Digraph on 1 vertex sage: list(ClusterQuiver(['A',1]).digraph()) [0] sage: ClusterQuiver(['A',1]).digraph().edges(sort=True) [] sage: ClusterQuiver(['A',4]).digraph() Digraph on 4 vertices sage: ClusterQuiver(['A',4]).digraph().edges(sort=True) [(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(sort=True) [(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(sort=True) [(0, 1, (1, -1)), (2, 3, (1, -2))] sage: ClusterQuiver(['C', 4], user_labels = ['x', 'y', 'z', 'w']).digraph().edges(sort=True) [('x', 'y', (1, -1)), ('z', 'w', (2, -1)), ('z', 'y', (1, -1))]
>>> from sage.all import * >>> ClusterQuiver(['A',Integer(1)]).digraph() Digraph on 1 vertex >>> list(ClusterQuiver(['A',Integer(1)]).digraph()) [0] >>> ClusterQuiver(['A',Integer(1)]).digraph().edges(sort=True) [] >>> ClusterQuiver(['A',Integer(4)]).digraph() Digraph on 4 vertices >>> ClusterQuiver(['A',Integer(4)]).digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))] >>> ClusterQuiver(['B',Integer(4)]).digraph() Digraph on 4 vertices >>> ClusterQuiver(['A',Integer(4)]).digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))] >>> ClusterQuiver(QuiverMutationType([['A',Integer(2)],['B',Integer(2)]])).digraph() Digraph on 4 vertices >>> ClusterQuiver(QuiverMutationType([['A',Integer(2)],['B',Integer(2)]])).digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 3, (1, -2))] >>> ClusterQuiver(['C', Integer(4)], user_labels = ['x', 'y', 'z', 'w']).digraph().edges(sort=True) [('x', 'y', (1, -1)), ('z', 'w', (2, -1)), ('z', 'y', (1, -1))]
- exchangeable_part()[source]¶
Return the restriction to the principal part (i.e. exchangeable part) of
self
, the subquiver obtained by deleting the frozen vertices ofself
.EXAMPLES:
sage: Q = ClusterQuiver(['A',4]) sage: T = ClusterQuiver(Q.digraph().edges(sort=True), frozen=[3]) sage: T.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))] sage: T.exchangeable_part().digraph().edges(sort=True) [(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
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(4)]) >>> T = ClusterQuiver(Q.digraph().edges(sort=True), frozen=[Integer(3)]) >>> T.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1)), (2, 3, (1, -1))] >>> T.exchangeable_part().digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 1, (1, -1))] >>> Q2 = Q.principal_extension() >>> Q3 = Q2.principal_extension() >>> Q2.exchangeable_part() == Q3.exchangeable_part() True
- first_sink()[source]¶
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
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.mutate([Integer(1),Integer(2),Integer(4),Integer(3),Integer(2)]) >>> Q.first_sink() 0
- first_source()[source]¶
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
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.mutate([Integer(2),Integer(1),Integer(3),Integer(4),Integer(2)]) >>> Q.first_source() 1
- free_vertices()[source]¶
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']
>>> from sage.all import * >>> Q = ClusterQuiver(DiGraph([['a', 'b'], ['c', 'b'], ['c', 'd'], ['e', 'd']]), ... frozen=['b', 'd']) >>> Q.free_vertices() ['a', 'c', 'e']
- frozen_vertices()[source]¶
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: sorted(Q.frozen_vertices()) ['b', 'd']
>>> from sage.all import * >>> Q = ClusterQuiver(DiGraph([['a', 'b'], ['c', 'b'], ['c', 'd'], ['e', 'd']]), ... frozen=['b', 'd']) >>> sorted(Q.frozen_vertices()) ['b', 'd']
- g_vector_fan()[source]¶
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
>>> from sage.all import * >>> Fg = ClusterQuiver([[Integer(1),Integer(2)]]).g_vector_fan(); Fg Rational polyhedral fan in 2-d lattice N >>> Fg.ngenerating_cones() 5 >>> Fg = ClusterQuiver([[Integer(1),Integer(2)],[Integer(2),Integer(3)]]).g_vector_fan(); Fg Rational polyhedral fan in 3-d lattice N >>> Fg.ngenerating_cones() 14 >>> Fg.is_smooth() True >>> Fg = ClusterQuiver([[Integer(1),Integer(2)],[Integer(2),Integer(3)],[Integer(3),Integer(1)]]).g_vector_fan(); Fg Rational polyhedral fan in 3-d lattice N >>> Fg.ngenerating_cones() 14 >>> Fg.is_smooth() True
- interact(fig_size=1, circular=True)[source]¶
Start an interactive window for cluster quiver mutations.
Only in Jupyter notebook mode.
INPUT:
fig_size
– (default: 1) factor by which the size of the plot is multipliedcircular
– boolean (default:True
); ifTrue
, the circular plot is chosen, otherwise >>spring<< is used
- is_acyclic()[source]¶
Return 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
>>> from sage.all import * >>> ClusterQuiver(['A',Integer(4)]).is_acyclic() True >>> ClusterQuiver(['A',[Integer(2),Integer(1)],Integer(1)]).is_acyclic() True >>> ClusterQuiver([[Integer(0),Integer(1)],[Integer(1),Integer(2)],[Integer(2),Integer(0)]]).is_acyclic() False
- is_bipartite(return_bipartition=False)[source]¶
Return
True
ifself
is bipartite.EXAMPLES:
sage: ClusterQuiver(['A',[3,3],1]).is_bipartite() True sage: ClusterQuiver(['A',[4,3],1]).is_bipartite() False
>>> from sage.all import * >>> ClusterQuiver(['A',[Integer(3),Integer(3)],Integer(1)]).is_bipartite() True >>> ClusterQuiver(['A',[Integer(4),Integer(3)],Integer(1)]).is_bipartite() False
- is_finite()[source]¶
Return
True
ifself
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
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(3)]) >>> Q.is_finite() True >>> Q = ClusterQuiver(['A',[Integer(2),Integer(2)],Integer(1)]) >>> Q.is_finite() False >>> Q = ClusterQuiver([['A',Integer(3)],['B',Integer(3)]]) >>> Q.is_finite() True >>> Q = ClusterQuiver(['T',[Integer(4),Integer(4),Integer(4)]]) >>> Q.is_finite() False >>> Q = ClusterQuiver([['A',Integer(3)],['T',[Integer(4),Integer(4),Integer(4)]]]) >>> Q.is_finite() False >>> Q = ClusterQuiver([['A',Integer(3)],['T',[Integer(2),Integer(2),Integer(3)]]]) >>> Q.is_finite() True >>> Q = ClusterQuiver([['A',Integer(3)],['D',Integer(5)]]) >>> Q.is_finite() True >>> Q = ClusterQuiver([['A',Integer(3)],['D',Integer(5),Integer(1)]]) >>> Q.is_finite() False >>> Q = ClusterQuiver([[Integer(0),Integer(1),Integer(2)],[Integer(1),Integer(2),Integer(2)],[Integer(2),Integer(0),Integer(2)]]) >>> Q.is_finite() False >>> Q = ClusterQuiver([[Integer(0),Integer(1),Integer(2)],[Integer(1),Integer(2),Integer(2)],[Integer(2),Integer(0),Integer(2)],[Integer(3),Integer(4),Integer(1)],[Integer(4),Integer(5),Integer(1)]]) >>> Q.is_finite() False
- is_mutation_finite(nr_of_checks=None, return_path=False)[source]¶
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 ofself
)return_path
– (default:False
) ifTrue
, in case ofself
not being mutation finite, a path fromself
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
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(10)]) >>> Q._mutation_type = None >>> Q.is_mutation_finite() True >>> Q = ClusterQuiver([(Integer(0),Integer(1)),(Integer(1),Integer(2)),(Integer(2),Integer(3)),(Integer(3),Integer(4)),(Integer(4),Integer(5)),(Integer(5),Integer(6)),(Integer(6),Integer(7)),(Integer(7),Integer(8)),(Integer(2),Integer(9))]) >>> Q.is_mutation_finite() False
- m()[source]¶
Return the number of frozen vertices of
self
.EXAMPLES:
sage: Q = ClusterQuiver(['A',4]) sage: Q.m() 0 sage: T = ClusterQuiver(Q.digraph().edges(sort=True), frozen=[3]) sage: T.n() 3 sage: T.m() 1
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(4)]) >>> Q.m() 0 >>> T = ClusterQuiver(Q.digraph().edges(sort=True), frozen=[Integer(3)]) >>> T.n() 3 >>> T.m() 1
- mutate(data, inplace=True)[source]¶
Mutates
self
at a sequence of vertices.INPUT:
sequence
– a vertex ofself
, an iterator of vertices ofself
, 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 verticesinplace
– boolean (default:True
); ifFalse
, the result is returned, otherwiseself
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: dg = DiGraph() sage: dg.add_vertices(['a','b','c','d','e']) sage: dg.add_edges([['a','b'], ['b','c'], ['c','d'], ['d','e']]) sage: Q2 = ClusterQuiver(dg, 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: dg = DiGraph([['a', 'b'], ['b', 'c']], format='list_of_edges') sage: Q = ClusterQuiver(dg);Q Quiver on 3 vertices sage: Q.mutate(['a','b'],inplace=False).digraph().edges(sort=True) [('a', 'b', (1, -1)), ('c', 'b', (1, -1))]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(4)]); Q.b_matrix() [ 0 1 0 0] [-1 0 -1 0] [ 0 1 0 1] [ 0 0 -1 0] >>> Q.mutate(Integer(0)); Q.b_matrix() [ 0 -1 0 0] [ 1 0 -1 0] [ 0 1 0 1] [ 0 0 -1 0] >>> T = Q.mutate(Integer(0), inplace=False); T Quiver on 4 vertices of type ['A', 4] >>> Q.mutate(Integer(0)) >>> Q == T True >>> Q.mutate([Integer(0),Integer(1),Integer(0)]) >>> Q.b_matrix() [ 0 -1 1 0] [ 1 0 0 0] [-1 0 0 1] [ 0 0 -1 0] >>> Q = ClusterQuiver(QuiverMutationType([['A',Integer(1)],['A',Integer(3)]])) >>> Q.b_matrix() [ 0 0 0 0] [ 0 0 1 0] [ 0 -1 0 -1] [ 0 0 1 0] >>> T = Q.mutate(Integer(0),inplace=False) >>> Q == T True >>> Q = ClusterQuiver(['A',Integer(3)]); Q.b_matrix() [ 0 1 0] [-1 0 -1] [ 0 1 0] >>> Q.mutate('first_sink'); Q.b_matrix() [ 0 -1 0] [ 1 0 1] [ 0 -1 0] >>> Q.mutate('first_source'); Q.b_matrix() [ 0 1 0] [-1 0 -1] [ 0 1 0] >>> dg = DiGraph() >>> dg.add_vertices(['a','b','c','d','e']) >>> dg.add_edges([['a','b'], ['b','c'], ['c','d'], ['d','e']]) >>> Q2 = ClusterQuiver(dg, 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] >>> 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] >>> dg = DiGraph([['a', 'b'], ['b', 'c']], format='list_of_edges') >>> Q = ClusterQuiver(dg);Q Quiver on 3 vertices >>> Q.mutate(['a','b'],inplace=False).digraph().edges(sort=True) [('a', 'b', (1, -1)), ('c', 'b', (1, -1))]
- mutation_class(depth=+Infinity, show_depth=False, return_paths=False, data_type='quiver', up_to_equivalence=True, sink_source=False)[source]¶
Return the mutation class of
self
together with certain constraints.INPUT:
depth
– (default:infinity
) integer, only seeds with distance at most depth fromself
are returnedshow_depth
– boolean (default:False
); ifTrue
, the actual depth of the mutation is shownreturn_paths
– boolean (default:False
); ifTrue
, a shortest path of mutation sequences fromself
to the given quiver is returned as welldata_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 fromself
are returned
sink_source
– boolean (default:False
); ifTrue
, 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: len(Ts) 14 sage: Ts[0] (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(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
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(3)]) >>> Ts = Q.mutation_class() >>> 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] >>> Ts = Q.mutation_class(depth=Integer(1)) >>> 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] >>> 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 >>> Ts = Q.mutation_class(return_paths=True) >>> 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]) >>> Ts = Q.mutation_class(up_to_equivalence=False) >>> 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] >>> Ts = Q.mutation_class(return_paths=True,up_to_equivalence=False) >>> len(Ts) 14 >>> Ts[Integer(0)] (Quiver on 3 vertices of type ['A', 3], []) >>> 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 >>> 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
- mutation_class_iter(depth=+Infinity, show_depth=False, return_paths=False, data_type='quiver', up_to_equivalence=True, sink_source=False)[source]¶
Return an iterator for the mutation class of
self
together with certain constraints.INPUT:
depth
– integer (default: infinity); only quivers with distance at most depth fromself
are returned.show_depth
– boolean (default:False
); ifTrue
, the actual depth of the mutation is shownreturn_paths
– boolean (default:False
); ifTrue
, a shortest path of mutation sequences fromself
to the given quiver is returned as welldata_type
– (default:'quiver'
) can be one of the following:* "quiver" * "matrix" * "digraph" * "dig6" * "path"
up_to_equivalence
– boolean (default:True
); ifTrue
, only one quiver for each graph-isomorphism class is recordedsink_source
– boolean (default:False
); ifTrue
, 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: mutation_class = list(it) sage: len(mutation_class) 14 sage: mutation_class[0] (Quiver on 3 vertices of type ['A', 3], []) 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: dg = DiGraph([['a', 'b'], ['b', 'c']], format='list_of_edges') sage: S = ClusterQuiver(dg, 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]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(3)]) >>> it = Q.mutation_class_iter() >>> 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] >>> it = Q.mutation_class_iter(depth=Integer(1)) >>> 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] >>> it = Q.mutation_class_iter(show_depth=True) >>> for T in it: pass Depth: 0 found: 1 Time: ... s Depth: 1 found: 3 Time: ... s Depth: 2 found: 4 Time: ... s >>> it = Q.mutation_class_iter(return_paths=True) >>> 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]) >>> it = Q.mutation_class_iter(up_to_equivalence=False) >>> 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] >>> it = Q.mutation_class_iter(return_paths=True,up_to_equivalence=False) >>> mutation_class = list(it) >>> len(mutation_class) 14 >>> mutation_class[Integer(0)] (Quiver on 3 vertices of type ['A', 3], []) >>> Q = ClusterQuiver(['A',Integer(3)]) >>> it = Q.mutation_class_iter(data_type='path') >>> for T in it: print(T) [] [1] [0] [0, 1] >>> Q = ClusterQuiver(['A',Integer(3)]) >>> it = Q.mutation_class_iter(return_paths=True,data_type='matrix') >>> next(it) ( [ 0 0 1] [ 0 0 1] [-1 -1 0], [] ) >>> dg = DiGraph([['a', 'b'], ['b', 'c']], format='list_of_edges') >>> S = ClusterQuiver(dg, frozen=['b']) >>> 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]
- mutation_sequence(sequence, show_sequence=False, fig_size=1.2)[source]¶
Return a list containing the sequence of quivers obtained from
self
by a sequence of mutations on vertices.INPUT:
sequence
– list or tuple of vertices ofself
show_sequence
– boolean (default:False
); ifTrue
, a png containing the mutation sequence is shownfig_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] ]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(4)]) >>> seq = Q.mutation_sequence([Integer(0),Integer(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]] >>> [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] ]
- mutation_type()[source]¶
Return the mutation type of
self
.Return 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
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]
>>> from sage.all import * >>> ClusterQuiver(['A',Integer(4)]).mutation_type() ['A', 4] >>> ClusterQuiver(['A',(Integer(3),Integer(1)),Integer(1)]).mutation_type() ['A', [1, 3], 1] >>> ClusterQuiver(['C',Integer(2)]).mutation_type() ['B', 2] >>> ClusterQuiver(['B',Integer(4),Integer(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] ]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q._mutation_type = None >>> Q.mutation_type() ['A', 5] >>> Q = ClusterQuiver([(Integer(0),Integer(1)),(Integer(1),Integer(2)),(Integer(2),Integer(3)),(Integer(3),Integer(4))]) >>> Q.mutation_type() ['A', 5] >>> Q = ClusterQuiver(DiGraph([['a', 'b'], ['c', 'b'], ['c', 'd'], ['e', 'd']]), ... frozen=['c']) >>> 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]]
>>> from sage.all import * >>> Q = ClusterQuiver(['E',Integer(8),[Integer(1),Integer(1)]]); Q Quiver on 10 vertices of type ['E', 8, [1, 1]] >>> Q._mutation_type = None; Q Quiver on 10 vertices >>> 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]
>>> from sage.all import * >>> Q = ClusterQuiver(['D',Integer(4),Integer(1)]) >>> Q._mutation_type = None >>> 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]
>>> from sage.all import * >>> Q = ClusterQuiver(['X',Integer(6)]) >>> Q._mutation_type = None >>> 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]]
>>> from sage.all import * >>> dg = DiGraph(); dg.add_edges([(Integer(9),Integer(0)),(Integer(9),Integer(4)),(Integer(4),Integer(6)),(Integer(6),Integer(7)),(Integer(7),Integer(8)),(Integer(8),Integer(3)),(Integer(3),Integer(5)),(Integer(5),Integer(6)),(Integer(8),Integer(1)),(Integer(2),Integer(3))]) >>> ClusterQuiver( dg ).mutation_type() # long time ['E', 8, [1, 1]] >>> dg = DiGraph( { Integer(0):[Integer(3)], Integer(1):[Integer(0),Integer(4)], Integer(2):[Integer(0),Integer(6)], Integer(3):[Integer(1),Integer(2),Integer(7)], Integer(4):[Integer(3),Integer(8)], Integer(5):[Integer(2)], Integer(6):[Integer(3),Integer(5)], Integer(7):[Integer(4),Integer(6)], Integer(8):[Integer(7)] } ) >>> ClusterQuiver( dg ).mutation_type() # long time ['E', 8, 1] >>> dg = DiGraph( { Integer(0):[Integer(3),Integer(9)], Integer(1):[Integer(0),Integer(4)], Integer(2):[Integer(0),Integer(6)], Integer(3):[Integer(1),Integer(2),Integer(7)], Integer(4):[Integer(3),Integer(8)], Integer(5):[Integer(2)], Integer(6):[Integer(3),Integer(5)], Integer(7):[Integer(4),Integer(6)], Integer(8):[Integer(7)], Integer(9):[Integer(1)] } ) >>> 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'
>>> from sage.all import * >>> Q = ClusterQuiver(['GR',[Integer(4),Integer(9)]]) >>> Q._mutation_type = None >>> 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]]
>>> from sage.all import * >>> Q = ClusterQuiver([['A', Integer(3)], ['B', Integer(3)]]) >>> Q._mutation_type = None >>> Q.mutation_type() [ ['A', 3], ['B', 3] ] >>> Q = ClusterQuiver([['A', Integer(3)], ['T', [Integer(4),Integer(4),Integer(4)]]]) >>> Q._mutation_type = None >>> Q.mutation_type() [['A', 3], 'undetermined infinite mutation type'] >>> Q = ClusterQuiver([['A', Integer(3)], ['B', Integer(3)], ['T', [Integer(4),Integer(4),Integer(4)]]]) >>> Q._mutation_type = None >>> Q.mutation_type() [['A', 3], ['B', 3], 'undetermined infinite mutation type'] >>> Q = ClusterQuiver([[Integer(0),Integer(1),Integer(2)],[Integer(1),Integer(2),Integer(2)],[Integer(2),Integer(0),Integer(2)],[Integer(3),Integer(4),Integer(1)],[Integer(4),Integer(5),Integer(1)]]) >>> Q.mutation_type() ['undetermined finite mutation type', ['A', 3]]
- n()[source]¶
Return 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
>>> from sage.all import * >>> ClusterQuiver(['A',Integer(4)]).n() 4 >>> ClusterQuiver(['A',(Integer(3),Integer(1)),Integer(1)]).n() 4 >>> ClusterQuiver(['B',Integer(4)]).n() 4 >>> ClusterQuiver(['B',Integer(4),Integer(1)]).n() 5
- number_of_edges()[source]¶
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: 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
>>> from sage.all import * >>> S = ClusterQuiver(['A',Integer(4)]); S.number_of_edges() 3 >>> S = ClusterQuiver(['B',Integer(4)]); S.number_of_edges() 3
- plot(circular=True, center=(0, 0), directed=True, mark=None, save_pos=False, greens=[])[source]¶
Return the plot of the underlying digraph of
self
.INPUT:
circular
– boolean (default:True
); ifTrue
, the circular plot is chosen, otherwise >>spring<< is usedcenter
– (default: (0,0)) sets the center of the circular plot, otherwise it is ignoreddirected
– boolean (default:True
); ifTrue
, the directed version is shown, otherwise the undirectedmark
– (default:None
) if set to i, the vertex i is highlightedsave_pos
– boolean (default:False
); ifTrue
, the positions of the vertices are savedgreens
– (default:[]
) if set to a list, will display the green vertices as green
EXAMPLES:
sage: Q = ClusterQuiver(['A',5]) sage: Q.plot() # needs sage.plot sage.symbolic Graphics object consisting of 15 graphics primitives sage: Q.plot(circular=True) # needs sage.plot sage.symbolic Graphics object consisting of 15 graphics primitives sage: Q.plot(circular=True, mark=1) # needs sage.plot sage.symbolic Graphics object consisting of 15 graphics primitives
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.plot() # needs sage.plot sage.symbolic Graphics object consisting of 15 graphics primitives >>> Q.plot(circular=True) # needs sage.plot sage.symbolic Graphics object consisting of 15 graphics primitives >>> Q.plot(circular=True, mark=Integer(1)) # needs sage.plot sage.symbolic Graphics object consisting of 15 graphics primitives
- poincare_semistable(theta, d)[source]¶
Return the Poincaré polynomial of the moduli space of semi-stable representations of dimension vector \(d\).
INPUT:
theta
– stability weight, as list or vector of rationalsd
– dimension vector, as list or vector of coprime integers
The semi-stability is taken with respect to the slope function
\[\mu(d) = \theta(d) / \operatorname{dim}(d)\]where \(d\) is a dimension vector.
This uses the matrix-inversion algorithm from [Rei2002].
EXAMPLES:
sage: Q = ClusterQuiver(['A',2]) sage: Q.poincare_semistable([1,0],[1,0]) 1 sage: Q.poincare_semistable([1,0],[1,1]) 1 sage: K2 = ClusterQuiver(matrix([[0,2],[-2,0]])) sage: theta = (1, 0) sage: K2.poincare_semistable(theta, [1,0]) 1 sage: K2.poincare_semistable(theta, [1,1]) v^2 + 1 sage: K2.poincare_semistable(theta, [1,2]) 1 sage: K2.poincare_semistable(theta, [1,3]) 0 sage: K3 = ClusterQuiver(matrix([[0,3],[-3,0]])) sage: theta = (1, 0) sage: K3.poincare_semistable(theta, (2,3)) v^12 + v^10 + 3*v^8 + 3*v^6 + 3*v^4 + v^2 + 1 sage: K3.poincare_semistable(theta, (3,4))(1) 68
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(2)]) >>> Q.poincare_semistable([Integer(1),Integer(0)],[Integer(1),Integer(0)]) 1 >>> Q.poincare_semistable([Integer(1),Integer(0)],[Integer(1),Integer(1)]) 1 >>> K2 = ClusterQuiver(matrix([[Integer(0),Integer(2)],[-Integer(2),Integer(0)]])) >>> theta = (Integer(1), Integer(0)) >>> K2.poincare_semistable(theta, [Integer(1),Integer(0)]) 1 >>> K2.poincare_semistable(theta, [Integer(1),Integer(1)]) v^2 + 1 >>> K2.poincare_semistable(theta, [Integer(1),Integer(2)]) 1 >>> K2.poincare_semistable(theta, [Integer(1),Integer(3)]) 0 >>> K3 = ClusterQuiver(matrix([[Integer(0),Integer(3)],[-Integer(3),Integer(0)]])) >>> theta = (Integer(1), Integer(0)) >>> K3.poincare_semistable(theta, (Integer(2),Integer(3))) v^12 + v^10 + 3*v^8 + 3*v^6 + 3*v^4 + v^2 + 1 >>> K3.poincare_semistable(theta, (Integer(3),Integer(4)))(Integer(1)) 68
REFERENCES:
[Rei2002]Markus Reineke, The Harder-Narasimhan system in quantum groups and cohomology of quiver moduli, arXiv math/0204059
- principal_extension(inplace=False)[source]¶
Return 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 ofself
.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(sort=True) [(0, 1, (1, -1))] sage: T.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 0, (1, -1)), (3, 1, (1, -1))] sage: T2.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 0, (1, -1)), (3, 1, (1, -1)), (4, 0, (1, -1)), (5, 1, (1, -1))]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(2)]); Q Quiver on 2 vertices of type ['A', 2] >>> T = Q.principal_extension(); T Quiver on 4 vertices of type ['A', 2] with 2 frozen vertices >>> T2 = T.principal_extension(); T2 Quiver on 6 vertices of type ['A', 2] with 4 frozen vertices >>> Q.digraph().edges(sort=True) [(0, 1, (1, -1))] >>> T.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 0, (1, -1)), (3, 1, (1, -1))] >>> T2.digraph().edges(sort=True) [(0, 1, (1, -1)), (2, 0, (1, -1)), (3, 1, (1, -1)), (4, 0, (1, -1)), (5, 1, (1, -1))]
- qmu_save(filename=None)[source]¶
Save
self
in a.qmu
file.This file can then be opened in Bernhard Keller’s Quiver Applet.
See https://webusers.imj-prg.fr/~bernhard.keller/quivermutation/
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: import tempfile sage: with tempfile.NamedTemporaryFile(suffix='.qmu') as f: # needs sage.plot sage.symbolic ....: Q.qmu_save(f.name)
>>> from sage.all import * >>> Q = ClusterQuiver(['F',Integer(4),[Integer(1),Integer(2)]]) >>> import tempfile >>> with tempfile.NamedTemporaryFile(suffix='.qmu') as f: # needs sage.plot sage.symbolic ... Q.qmu_save(f.name)
Make sure we can save quivers with \(m != n\) frozen variables, see Issue #14851:
sage: S = ClusterSeed(['A',3]) sage: T1 = S.principal_extension() sage: Q = T1.quiver() sage: import tempfile sage: with tempfile.NamedTemporaryFile(suffix='.qmu') as f: # needs sage.plot sage.symbolic ....: Q.qmu_save(f.name)
>>> from sage.all import * >>> S = ClusterSeed(['A',Integer(3)]) >>> T1 = S.principal_extension() >>> Q = T1.quiver() >>> import tempfile >>> with tempfile.NamedTemporaryFile(suffix='.qmu') as f: # needs sage.plot sage.symbolic ... Q.qmu_save(f.name)
- relabel(relabelling, inplace=True)[source]¶
Return the quiver after doing a relabelling.
Will relabel the vertices of the quiver.
INPUT:
relabelling
– dictionary of labels to move aroundinplace
– boolean (default:True
); ifTrue
, will return a duplicate of the quiver
EXAMPLES:
sage: S = ClusterQuiver(['A',4]).relabel({1:'5',2:'go'})
>>> from sage.all import * >>> S = ClusterQuiver(['A',Integer(4)]).relabel({Integer(1):'5',Integer(2):'go'})
- reorient(data)[source]¶
Reorient
self
with respect to the given total order, or with respect to an iterator of edges inself
to be reverted.Warning
This operation might change the mutation type of
self
.INPUT:
data
– an iterator defining a total order onself.vertices()
, or an iterator of edges inself
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]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',(Integer(2),Integer(3)),Integer(1)]) >>> Q.mutation_type() ['A', [2, 3], 1] >>> Q.reorient([(Integer(0),Integer(1)),(Integer(1),Integer(2)),(Integer(2),Integer(3)),(Integer(3),Integer(4))]) >>> Q.mutation_type() ['D', 5] >>> Q.reorient([Integer(0),Integer(1),Integer(2),Integer(3),Integer(4)]) >>> Q.mutation_type() ['A', [1, 4], 1]
- save_image(filename, circular=False)[source]¶
Save the plot of the underlying digraph of
self
.INPUT:
filename
– the filename the image is saved tocircular
– boolean (default:False
); ifTrue
, the circular plot is chosen, otherwise >>spring<< is used
EXAMPLES:
sage: Q = ClusterQuiver(['F',4,[1,2]]) sage: import tempfile sage: with tempfile.NamedTemporaryFile(suffix='.png') as f: # needs sage.plot sage.symbolic ....: Q.save_image(f.name)
>>> from sage.all import * >>> Q = ClusterQuiver(['F',Integer(4),[Integer(1),Integer(2)]]) >>> import tempfile >>> with tempfile.NamedTemporaryFile(suffix='.png') as f: # needs sage.plot sage.symbolic ... Q.save_image(f.name)
- show(fig_size=1, circular=False, directed=True, mark=None, save_pos=False, greens=[])[source]¶
Show the plot of the underlying digraph of
self
.INPUT:
fig_size
– (default: 1) factor by which the size of the plot is multipliedcircular
– boolean (default:False
); ifTrue
, the circular plot is chosen, otherwise >>spring<< is useddirected
– boolean (default:True
); ifTrue
, the directed version is shown, otherwise the undirectedmark
– boolean (default:None
); if set to i, the vertex i is highlightedsave_pos
– boolean (default:False
); ifTrue
, the positions of the vertices are savedgreens
– (default:[]
) if set to a list, will display the green vertices as green
- sinks()[source]¶
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]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.mutate([Integer(1),Integer(2),Integer(4),Integer(3),Integer(2)]) >>> Q.sinks() [0, 2] >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.mutate([Integer(2),Integer(1),Integer(3),Integer(4),Integer(2)]) >>> Q.sinks() [3]
- sources()[source]¶
Return 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]
>>> from sage.all import * >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.mutate([Integer(1),Integer(2),Integer(4),Integer(3),Integer(2)]) >>> Q.sources() [] >>> Q = ClusterQuiver(['A',Integer(5)]) >>> Q.mutate([Integer(2),Integer(1),Integer(3),Integer(4),Integer(2)]) >>> Q.sources() [1]