Infinity Crystals¶
Infinity crystals, denoted
All infinity crystals that are currently implemented in Sage can be accessed
by typing crystals.infinity.<tab>
.
Marginally large tableaux¶
Marginally large tableaux were introduced by J. Hong and H. Lee as a realization
of the crystal
Here is an example in type
sage: B = crystals.infinity.Tableaux(['A',2])
sage: b = B.highest_weight_vector()
sage: b.pp()
1 1
2
sage: b.f_string([1,2,2,1,2,1,2,2,2,2,2]).pp()
1 1 1 1 1 1 1 1 1 2 2 3
2 3 3 3 3 3 3 3
>>> from sage.all import *
>>> B = crystals.infinity.Tableaux(['A',Integer(2)])
>>> b = B.highest_weight_vector()
>>> b.pp()
1 1
2
>>> b.f_string([Integer(1),Integer(2),Integer(2),Integer(1),Integer(2),Integer(1),Integer(2),Integer(2),Integer(2),Integer(2),Integer(2)]).pp()
1 1 1 1 1 1 1 1 1 2 2 3
2 3 3 3 3 3 3 3
B = crystals.infinity.Tableaux(['A',2]) b = B.highest_weight_vector() b.pp() b.f_string([1,2,2,1,2,1,2,2,2,2,2]).pp()
Since the crystal is infinite, we must specify the subcrystal we would like to view:
sage: B = crystals.infinity.Tableaux(['A',2])
sage: S = B.subcrystal(max_depth=4)
sage: G = B.digraph(subset=S)
sage: view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> B = crystals.infinity.Tableaux(['A',Integer(2)])
>>> S = B.subcrystal(max_depth=Integer(4))
>>> G = B.digraph(subset=S)
>>> view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
B = crystals.infinity.Tableaux(['A',2]) S = B.subcrystal(max_depth=4) G = B.digraph(subset=S) view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

Using elementary crystals, we can cut irreducible highest weight crystals from
sage: B = crystals.infinity.Tableaux(['A',2])
sage: b = B.highest_weight_vector()
sage: T = crystals.elementary.T(['A',2], B.Lambda()[1] + B.Lambda()[2])
sage: t = T[0]
sage: C = crystals.elementary.Component(['A',2])
sage: c = C[0]
sage: TP = crystals.TensorProduct(C,T,B)
sage: t0 = TP(c,t,b)
sage: STP = TP.subcrystal(generators=[t0])
sage: GTP = TP.digraph(subset=STP)
sage: view(GTP, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> B = crystals.infinity.Tableaux(['A',Integer(2)])
>>> b = B.highest_weight_vector()
>>> T = crystals.elementary.T(['A',Integer(2)], B.Lambda()[Integer(1)] + B.Lambda()[Integer(2)])
>>> t = T[Integer(0)]
>>> C = crystals.elementary.Component(['A',Integer(2)])
>>> c = C[Integer(0)]
>>> TP = crystals.TensorProduct(C,T,B)
>>> t0 = TP(c,t,b)
>>> STP = TP.subcrystal(generators=[t0])
>>> GTP = TP.digraph(subset=STP)
>>> view(GTP, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
B = crystals.infinity.Tableaux(['A',2]) b = B.highest_weight_vector() T = crystals.elementary.T(['A',2], B.Lambda()[1] + B.Lambda()[2]) t = T[0] C = crystals.elementary.Component(['A',2]) c = C[0] TP = crystals.TensorProduct(C,T,B) t0 = TP(c,t,b) STP = TP.subcrystal(generators=[t0]) GTP = TP.digraph(subset=STP) view(GTP, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

Note that the above code can be simplified using the R-crystal:
sage: B = crystals.infinity.Tableaux(['A',2])
sage: b = B.highest_weight_vector()
sage: R = crystals.elementary.R(['A',2], B.Lambda()[1] + B.Lambda()[2])
sage: r = R[0]
sage: TP2 = crystals.TensorProduct(R,B)
sage: t2 = TP2(r,b)
sage: STP2 = TP2.subcrystal(generators=[t2])
sage: GTP2 = TP2.digraph(subset=STP2)
sage: view(GTP2, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> B = crystals.infinity.Tableaux(['A',Integer(2)])
>>> b = B.highest_weight_vector()
>>> R = crystals.elementary.R(['A',Integer(2)], B.Lambda()[Integer(1)] + B.Lambda()[Integer(2)])
>>> r = R[Integer(0)]
>>> TP2 = crystals.TensorProduct(R,B)
>>> t2 = TP2(r,b)
>>> STP2 = TP2.subcrystal(generators=[t2])
>>> GTP2 = TP2.digraph(subset=STP2)
>>> view(GTP2, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
B = crystals.infinity.Tableaux(['A',2]) b = B.highest_weight_vector() R = crystals.elementary.R(['A',2], B.Lambda()[1] + B.Lambda()[2]) r = R[0] TP2 = crystals.TensorProduct(R,B) t2 = TP2(r,b) STP2 = TP2.subcrystal(generators=[t2]) GTP2 = TP2.digraph(subset=STP2) view(GTP2, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

On the other hand, we can embed the irreducible highest weight crystal
sage: Brho = crystals.Tableaux(['A',2],shape=[2,1])
sage: brho = Brho.highest_weight_vector()
sage: B = crystals.infinity.Tableaux(['A',2])
sage: binf = B.highest_weight_vector()
sage: wt = brho.weight()
sage: T = crystals.elementary.T(['A',2],wt)
sage: TlambdaBinf = crystals.TensorProduct(T,B)
sage: hw = TlambdaBinf(T[0],binf)
sage: Psi = Brho.crystal_morphism({brho : hw})
sage: BG = B.digraph(subset=[Psi(x) for x in Brho])
sage: view(BG, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> Brho = crystals.Tableaux(['A',Integer(2)],shape=[Integer(2),Integer(1)])
>>> brho = Brho.highest_weight_vector()
>>> B = crystals.infinity.Tableaux(['A',Integer(2)])
>>> binf = B.highest_weight_vector()
>>> wt = brho.weight()
>>> T = crystals.elementary.T(['A',Integer(2)],wt)
>>> TlambdaBinf = crystals.TensorProduct(T,B)
>>> hw = TlambdaBinf(T[Integer(0)],binf)
>>> Psi = Brho.crystal_morphism({brho : hw})
>>> BG = B.digraph(subset=[Psi(x) for x in Brho])
>>> view(BG, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
Brho = crystals.Tableaux(['A',2],shape=[2,1]) brho = Brho.highest_weight_vector() B = crystals.infinity.Tableaux(['A',2]) binf = B.highest_weight_vector() wt = brho.weight() T = crystals.elementary.T(['A',2],wt) TlambdaBinf = crystals.TensorProduct(T,B) hw = TlambdaBinf(T[0],binf) Psi = Brho.crystal_morphism({brho : hw}) BG = B.digraph(subset=[Psi(x) for x in Brho]) view(BG, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

Note that in the last example, we had to inject Psi
would
not be a crystal morphism (as b.weight() != brho.weight()
).
Generalized Young walls¶
Generalized Young walls were introduced by J.-A. Kim and D.-U. Shin as a model
for
Since this model is only valid for one Cartan type, the input to initialize the crystal is simply the rank of the underlying type:
sage: Y = crystals.infinity.GeneralizedYoungWalls(2)
sage: y = Y.highest_weight_vector()
sage: y.f_string([0,1,2,2,2,1,0,0,1,2]).pp()
2|
|
|
1|2|
0|1|
2|0|1|2|0|
>>> from sage.all import *
>>> Y = crystals.infinity.GeneralizedYoungWalls(Integer(2))
>>> y = Y.highest_weight_vector()
>>> y.f_string([Integer(0),Integer(1),Integer(2),Integer(2),Integer(2),Integer(1),Integer(0),Integer(0),Integer(1),Integer(2)]).pp()
2|
|
|
1|2|
0|1|
2|0|1|2|0|
Y = crystals.infinity.GeneralizedYoungWalls(2) y = Y.highest_weight_vector() y.f_string([0,1,2,2,2,1,0,0,1,2]).pp()
In the weight
method for this model, we can choose whether to view weights
in the extended weight lattice (by default) or in the root lattice:
sage: Y = crystals.infinity.GeneralizedYoungWalls(2)
sage: y = Y.highest_weight_vector()
sage: y.f_string([0,1,2,2,2,1,0,0,1,2]).weight()
Lambda[0] + Lambda[1] - 2*Lambda[2] - 3*delta
sage: y.f_string([0,1,2,2,2,1,0,0,1,2]).weight(root_lattice=True)
-3*alpha[0] - 3*alpha[1] - 4*alpha[2]
>>> from sage.all import *
>>> Y = crystals.infinity.GeneralizedYoungWalls(Integer(2))
>>> y = Y.highest_weight_vector()
>>> y.f_string([Integer(0),Integer(1),Integer(2),Integer(2),Integer(2),Integer(1),Integer(0),Integer(0),Integer(1),Integer(2)]).weight()
Lambda[0] + Lambda[1] - 2*Lambda[2] - 3*delta
>>> y.f_string([Integer(0),Integer(1),Integer(2),Integer(2),Integer(2),Integer(1),Integer(0),Integer(0),Integer(1),Integer(2)]).weight(root_lattice=True)
-3*alpha[0] - 3*alpha[1] - 4*alpha[2]
Y = crystals.infinity.GeneralizedYoungWalls(2) y = Y.highest_weight_vector() y.f_string([0,1,2,2,2,1,0,0,1,2]).weight() y.f_string([0,1,2,2,2,1,0,0,1,2]).weight(root_lattice=True)
As before, we need to indicate a specific subcrystal when attempting to view the crystal graph:
sage: Y = crystals.infinity.GeneralizedYoungWalls(2)
sage: SY = Y.subcrystal(max_depth=3)
sage: GY = Y.digraph(subset=SY)
sage: view(GY, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> Y = crystals.infinity.GeneralizedYoungWalls(Integer(2))
>>> SY = Y.subcrystal(max_depth=Integer(3))
>>> GY = Y.digraph(subset=SY)
>>> view(GY, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
Y = crystals.infinity.GeneralizedYoungWalls(2) SY = Y.subcrystal(max_depth=3) GY = Y.digraph(subset=SY) view(GY, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

One can also make irreducible highest weight crystals using generalized Young walls:
sage: La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights()
sage: YLa = crystals.GeneralizedYoungWalls(2,La[0])
sage: SYLa = YLa.subcrystal(max_depth=3)
sage: GYLa = YLa.digraph(subset=SYLa)
sage: view(GYLa, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> La = RootSystem(['A',Integer(2),Integer(1)]).weight_lattice(extended=True).fundamental_weights()
>>> YLa = crystals.GeneralizedYoungWalls(Integer(2),La[Integer(0)])
>>> SYLa = YLa.subcrystal(max_depth=Integer(3))
>>> GYLa = YLa.digraph(subset=SYLa)
>>> view(GYLa, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() YLa = crystals.GeneralizedYoungWalls(2,La[0]) SYLa = YLa.subcrystal(max_depth=3) GYLa = YLa.digraph(subset=SYLa) view(GYLa, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

In the highest weight crystals, however, weights are always elements of the extended affine weight lattice:
sage: La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights()
sage: YLa = crystals.GeneralizedYoungWalls(2,La[0])
sage: YLa.highest_weight_vector().f_string([0,1,2,0]).weight()
-Lambda[0] + Lambda[1] + Lambda[2] - 2*delta
>>> from sage.all import *
>>> La = RootSystem(['A',Integer(2),Integer(1)]).weight_lattice(extended=True).fundamental_weights()
>>> YLa = crystals.GeneralizedYoungWalls(Integer(2),La[Integer(0)])
>>> YLa.highest_weight_vector().f_string([Integer(0),Integer(1),Integer(2),Integer(0)]).weight()
-Lambda[0] + Lambda[1] + Lambda[2] - 2*delta
La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() YLa = crystals.GeneralizedYoungWalls(2,La[0]) YLa.highest_weight_vector().f_string([0,1,2,0]).weight()
Modified Nakajima monomials¶
Let
Elements of
where
where
Note
Monomial crystals depend on the choice of positive integers
sage: c = Matrix([[0,0,1],[1,0,0],[0,1,0]])
sage: La = RootSystem(['C',3]).weight_lattice().fundamental_weights()
sage: M = crystals.NakajimaMonomials(2*La[1], c=c)
sage: M.c()
[0 0 1]
[1 0 0]
[0 1 0]
>>> from sage.all import *
>>> c = Matrix([[Integer(0),Integer(0),Integer(1)],[Integer(1),Integer(0),Integer(0)],[Integer(0),Integer(1),Integer(0)]])
>>> La = RootSystem(['C',Integer(3)]).weight_lattice().fundamental_weights()
>>> M = crystals.NakajimaMonomials(Integer(2)*La[Integer(1)], c=c)
>>> M.c()
[0 0 1]
[1 0 0]
[0 1 0]
c = Matrix([[0,0,1],[1,0,0],[0,1,0]]) La = RootSystem(['C',3]).weight_lattice().fundamental_weights() M = crystals.NakajimaMonomials(2*La[1], c=c) M.c()
It is shown in [KKS2007] that the connected component of
sage: Minf = crystals.infinity.NakajimaMonomials(['C',3,1])
sage: minf = Minf.highest_weight_vector()
sage: m = minf.f_string([0,1,2,3,2,1,0]); m
Y(0,0)^-1 Y(0,4)^-1 Y(1,0) Y(1,3)
sage: m.weight()
-2*Lambda[0] + 2*Lambda[1] - 2*delta
sage: m.weight_in_root_lattice()
-2*alpha[0] - 2*alpha[1] - 2*alpha[2] - alpha[3]
>>> from sage.all import *
>>> Minf = crystals.infinity.NakajimaMonomials(['C',Integer(3),Integer(1)])
>>> minf = Minf.highest_weight_vector()
>>> m = minf.f_string([Integer(0),Integer(1),Integer(2),Integer(3),Integer(2),Integer(1),Integer(0)]); m
Y(0,0)^-1 Y(0,4)^-1 Y(1,0) Y(1,3)
>>> m.weight()
-2*Lambda[0] + 2*Lambda[1] - 2*delta
>>> m.weight_in_root_lattice()
-2*alpha[0] - 2*alpha[1] - 2*alpha[2] - alpha[3]
Minf = crystals.infinity.NakajimaMonomials(['C',3,1]) minf = Minf.highest_weight_vector() m = minf.f_string([0,1,2,3,2,1,0]); m m.weight() m.weight_in_root_lattice()
We can also model
sage: Minf = crystals.infinity.NakajimaMonomials(['C',3,1])
sage: minf = Minf.highest_weight_vector()
sage: Minf.set_variables('A')
sage: m = minf.f_string([0,1,2,3,2,1,0]); m
A(0,0)^-1 A(0,3)^-1 A(1,0)^-1 A(1,2)^-1 A(2,0)^-1 A(2,1)^-1 A(3,0)^-1
sage: m.weight()
-2*Lambda[0] + 2*Lambda[1] - 2*delta
sage: m.weight_in_root_lattice()
-2*alpha[0] - 2*alpha[1] - 2*alpha[2] - alpha[3]
sage: Minf.set_variables('Y')
>>> from sage.all import *
>>> Minf = crystals.infinity.NakajimaMonomials(['C',Integer(3),Integer(1)])
>>> minf = Minf.highest_weight_vector()
>>> Minf.set_variables('A')
>>> m = minf.f_string([Integer(0),Integer(1),Integer(2),Integer(3),Integer(2),Integer(1),Integer(0)]); m
A(0,0)^-1 A(0,3)^-1 A(1,0)^-1 A(1,2)^-1 A(2,0)^-1 A(2,1)^-1 A(3,0)^-1
>>> m.weight()
-2*Lambda[0] + 2*Lambda[1] - 2*delta
>>> m.weight_in_root_lattice()
-2*alpha[0] - 2*alpha[1] - 2*alpha[2] - alpha[3]
>>> Minf.set_variables('Y')
Minf = crystals.infinity.NakajimaMonomials(['C',3,1]) minf = Minf.highest_weight_vector() Minf.set_variables('A') m = minf.f_string([0,1,2,3,2,1,0]); m m.weight() m.weight_in_root_lattice() Minf.set_variables('Y')
Building the crystal graph output for these monomial crystals is the same as the constructions above:
sage: Minf = crystals.infinity.NakajimaMonomials(['C',3,1])
sage: Sinf = Minf.subcrystal(max_depth=2)
sage: Ginf = Minf.digraph(subset=Sinf)
sage: view(Ginf, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
>>> from sage.all import *
>>> Minf = crystals.infinity.NakajimaMonomials(['C',Integer(3),Integer(1)])
>>> Sinf = Minf.subcrystal(max_depth=Integer(2))
>>> Ginf = Minf.digraph(subset=Sinf)
>>> view(Ginf, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)
Minf = crystals.infinity.NakajimaMonomials(['C',3,1]) Sinf = Minf.subcrystal(max_depth=2) Ginf = Minf.digraph(subset=Sinf) view(Ginf, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window)

Note that this model will also work for any symmetrizable Cartan matrix:
sage: A = CartanMatrix([[2,-4],[-5,2]])
sage: Linf = crystals.infinity.NakajimaMonomials(A); Linf
Infinity Crystal of modified Nakajima monomials of type [ 2 -4]
[-5 2]
sage: Linf.highest_weight_vector().f_string([0,1,1,1,0,0,1,1,0])
Y(0,0)^-1 Y(0,1)^9 Y(0,2)^5 Y(0,3)^-1 Y(1,0)^2 Y(1,1)^5 Y(1,2)^3
>>> from sage.all import *
>>> A = CartanMatrix([[Integer(2),-Integer(4)],[-Integer(5),Integer(2)]])
>>> Linf = crystals.infinity.NakajimaMonomials(A); Linf
Infinity Crystal of modified Nakajima monomials of type [ 2 -4]
[-5 2]
>>> Linf.highest_weight_vector().f_string([Integer(0),Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0)])
Y(0,0)^-1 Y(0,1)^9 Y(0,2)^5 Y(0,3)^-1 Y(1,0)^2 Y(1,1)^5 Y(1,2)^3
A = CartanMatrix([[2,-4],[-5,2]]) Linf = crystals.infinity.NakajimaMonomials(A); Linf Linf.highest_weight_vector().f_string([0,1,1,1,0,0,1,1,0])
Rigged configurations¶
Rigged configurations are sequences of partitions, one partition for each node
in the underlying Dynkin diagram, such that each part of each partition has a
label (or rigging). A crystal structure was defined on these objects in
[Schilling2006], then later extended to work as a model for
sage: RiggedConfigurations.options(display="horizontal")
sage: RC = crystals.infinity.RiggedConfigurations(['C',3,1])
sage: nu = RC.highest_weight_vector().f_string([0,1,2,3,2,1,0]); nu
-2[ ]-1 2[ ]1 0[ ]0 0[ ]0
-2[ ]-1 2[ ]1 0[ ]0
sage: nu.weight()
-2*Lambda[0] + 2*Lambda[1] - 2*delta
sage: RiggedConfigurations.options._reset()
>>> from sage.all import *
>>> RiggedConfigurations.options(display="horizontal")
>>> RC = crystals.infinity.RiggedConfigurations(['C',Integer(3),Integer(1)])
>>> nu = RC.highest_weight_vector().f_string([Integer(0),Integer(1),Integer(2),Integer(3),Integer(2),Integer(1),Integer(0)]); nu
-2[ ]-1 2[ ]1 0[ ]0 0[ ]0
-2[ ]-1 2[ ]1 0[ ]0
>>> nu.weight()
-2*Lambda[0] + 2*Lambda[1] - 2*delta
>>> RiggedConfigurations.options._reset()
RiggedConfigurations.options(display="horizontal") RC = crystals.infinity.RiggedConfigurations(['C',3,1]) nu = RC.highest_weight_vector().f_string([0,1,2,3,2,1,0]); nu nu.weight() RiggedConfigurations.options._reset()
We can check this crystal is isomorphic to the crystal above using Nakajima monomials:
sage: Minf = crystals.infinity.NakajimaMonomials(['C',3,1])
sage: Sinf = Minf.subcrystal(max_depth=2)
sage: Ginf = Minf.digraph(subset=Sinf)
sage: RC = crystals.infinity.RiggedConfigurations(['C',3,1])
sage: RCS = RC.subcrystal(max_depth=2)
sage: RCG = RC.digraph(subset=RCS)
sage: RCG.is_isomorphic(Ginf, edge_labels=True)
True
>>> from sage.all import *
>>> Minf = crystals.infinity.NakajimaMonomials(['C',Integer(3),Integer(1)])
>>> Sinf = Minf.subcrystal(max_depth=Integer(2))
>>> Ginf = Minf.digraph(subset=Sinf)
>>> RC = crystals.infinity.RiggedConfigurations(['C',Integer(3),Integer(1)])
>>> RCS = RC.subcrystal(max_depth=Integer(2))
>>> RCG = RC.digraph(subset=RCS)
>>> RCG.is_isomorphic(Ginf, edge_labels=True)
True
Minf = crystals.infinity.NakajimaMonomials(['C',3,1]) Sinf = Minf.subcrystal(max_depth=2) Ginf = Minf.digraph(subset=Sinf) RC = crystals.infinity.RiggedConfigurations(['C',3,1]) RCS = RC.subcrystal(max_depth=2) RCG = RC.digraph(subset=RCS) RCG.is_isomorphic(Ginf, edge_labels=True)
This model works in Sage for all finite and affine types, as well as any simply laced Cartan matrix.