Hide keyboard shortcuts

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

""" 

Orthogonal Symmetric Functions 

 

AUTHORS: 

 

- Travis Scrimshaw (2013-11-10): Initial version 

""" 

from __future__ import absolute_import 

#***************************************************************************** 

# Copyright (C) 2013 Travis Scrimshaw <tscrim at ucdavis.edu> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# 

# This code is distributed in the hope that it will be useful, 

# but WITHOUT ANY WARRANTY; without even the implied warranty of 

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 

# General Public License for more details. 

# 

# The full text of the GPL is available at: 

# 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

from . import sfa 

import sage.libs.lrcalc.lrcalc as lrcalc 

from sage.combinat.partition import Partitions 

from sage.misc.cachefunc import cached_method 

from sage.rings.all import ZZ, QQ, Integer 

from sage.matrix.all import matrix 

 

class SymmetricFunctionAlgebra_orthogonal(sfa.SymmetricFunctionAlgebra_generic): 

r""" 

The orthogonal symmetric function basis (or orthogonal basis, to be short). 

 

The orthogonal basis `\{ o_{\lambda} \}` where `\lambda` is taken over 

all partitions is defined by the following change of basis with the 

Schur functions: 

 

.. MATH:: 

 

s_{\lambda} = \sum_{\mu} \left( \sum_{\nu \in H} c^{\lambda}_{\mu\nu} 

\right) o_{\mu} 

 

where `H` is the set of all partitions with even-width rows and 

`c^{\lambda}_{\mu\nu}` is the usual Littlewood-Richardson (LR) 

coefficients. By the properties of LR coefficients, this can be shown to 

be a upper unitriangular change of basis. 

 

.. NOTE:: 

 

This is only a filtered basis, not a `\ZZ`-graded basis. However this 

does respect the induced `(\ZZ/2\ZZ)`-grading. 

 

INPUT: 

 

- ``Sym`` -- an instance of the ring of the symmetric functions 

 

REFERENCES: 

 

- [ChariKleber2000]_ 

- [KoikeTerada1987]_ 

- [ShimozonoZabrocki2006]_ 

 

EXAMPLES: 

 

Here are the first few orthogonal symmetric functions, in various bases:: 

 

sage: Sym = SymmetricFunctions(QQ) 

sage: o = Sym.o() 

sage: e = Sym.e() 

sage: h = Sym.h() 

sage: p = Sym.p() 

sage: s = Sym.s() 

sage: m = Sym.m() 

 

sage: p(o([1])) 

p[1] 

sage: m(o([1])) 

m[1] 

sage: e(o([1])) 

e[1] 

sage: h(o([1])) 

h[1] 

sage: s(o([1])) 

s[1] 

 

sage: p(o([2])) 

-p[] + 1/2*p[1, 1] + 1/2*p[2] 

sage: m(o([2])) 

-m[] + m[1, 1] + m[2] 

sage: e(o([2])) 

-e[] + e[1, 1] - e[2] 

sage: h(o([2])) 

-h[] + h[2] 

sage: s(o([2])) 

-s[] + s[2] 

 

sage: p(o([3])) 

-p[1] + 1/6*p[1, 1, 1] + 1/2*p[2, 1] + 1/3*p[3] 

sage: m(o([3])) 

-m[1] + m[1, 1, 1] + m[2, 1] + m[3] 

sage: e(o([3])) 

-e[1] + e[1, 1, 1] - 2*e[2, 1] + e[3] 

sage: h(o([3])) 

-h[1] + h[3] 

sage: s(o([3])) 

-s[1] + s[3] 

 

sage: Sym = SymmetricFunctions(ZZ) 

sage: o = Sym.o() 

sage: e = Sym.e() 

sage: h = Sym.h() 

sage: s = Sym.s() 

sage: m = Sym.m() 

sage: p = Sym.p() 

sage: m(o([4])) 

-m[1, 1] + m[1, 1, 1, 1] - m[2] + m[2, 1, 1] + m[2, 2] + m[3, 1] + m[4] 

sage: e(o([4])) 

-e[1, 1] + e[1, 1, 1, 1] + e[2] - 3*e[2, 1, 1] + e[2, 2] + 2*e[3, 1] - e[4] 

sage: h(o([4])) 

-h[2] + h[4] 

sage: s(o([4])) 

-s[2] + s[4] 

 

Some examples of conversions the other way:: 

 

sage: o(h[3]) 

o[1] + o[3] 

sage: o(e[3]) 

o[1, 1, 1] 

sage: o(m[2,1]) 

o[1] - 2*o[1, 1, 1] + o[2, 1] 

sage: o(p[3]) 

o[1, 1, 1] - o[2, 1] + o[3] 

 

Some multiplication:: 

 

sage: o([2]) * o([1,1]) 

o[1, 1] + o[2] + o[2, 1, 1] + o[3, 1] 

sage: o([2,1,1]) * o([2]) 

o[1, 1] + o[1, 1, 1, 1] + 2*o[2, 1, 1] + o[2, 2] + o[2, 2, 1, 1] 

+ o[3, 1] + o[3, 1, 1, 1] + o[3, 2, 1] + o[4, 1, 1] 

sage: o([1,1]) * o([2,1]) 

o[1] + o[1, 1, 1] + 2*o[2, 1] + o[2, 1, 1, 1] + o[2, 2, 1] 

+ o[3] + o[3, 1, 1] + o[3, 2] 

 

Examples of the Hopf algebra structure:: 

 

sage: o([1]).antipode() 

-o[1] 

sage: o([2]).antipode() 

-o[] + o[1, 1] 

sage: o([1]).coproduct() 

o[] # o[1] + o[1] # o[] 

sage: o([2]).coproduct() 

o[] # o[] + o[] # o[2] + o[1] # o[1] + o[2] # o[] 

sage: o([1]).counit() 

0 

sage: o.one().counit() 

1 

""" 

def __init__(self, Sym): 

""" 

Initialize ``self``. 

 

TESTS:: 

 

sage: o = SymmetricFunctions(QQ).o() 

sage: TestSuite(o).run() 

""" 

sfa.SymmetricFunctionAlgebra_generic.__init__(self, Sym, "orthogonal", 

'o', graded=False) 

 

# We make a strong reference since we use it for our computations 

# and so we can define the coercion below (only codomains have 

# strong references) 

self._s = Sym.schur() 

 

# Setup the coercions 

M = self._s.module_morphism(self._s_to_o_on_basis, codomain=self, 

triangular='upper', unitriangular=True) 

M.register_as_coercion() 

Mi = self.module_morphism(self._o_to_s_on_basis, codomain=self._s, 

triangular='upper', unitriangular=True) 

Mi.register_as_coercion() 

 

@cached_method 

def _o_to_s_on_basis(self, lam): 

r""" 

Return the orthogonal symmetric function ``o[lam]`` expanded in 

the Schur basis, where ``lam`` is a partition. 

 

TESTS: 

 

Check that this is the inverse:: 

 

sage: o = SymmetricFunctions(QQ).o() 

sage: s = SymmetricFunctions(QQ).s() 

sage: all(o(s(o[la])) == o[la] for i in range(5) for la in Partitions(i)) 

True 

sage: all(s(o(s[la])) == s[la] for i in range(5) for la in Partitions(i)) 

True 

""" 

R = self.base_ring() 

n = sum(lam) 

return self._s._from_dict({ mu: R.sum( (-1)**j * lrcalc.lrcoef_unsafe(lam, mu, nu) 

for nu in Partitions(2*j) 

if all(nu.arm_length(i,i) == nu.leg_length(i,i)+1 

for i in range(nu.frobenius_rank())) 

) 

for j in range(n//2+1) # // 2 for horizontal dominoes 

for mu in Partitions(n-2*j) }) 

 

@cached_method 

def _s_to_o_on_basis(self, lam): 

r""" 

Return the Schur symmetric function ``s[lam]`` expanded in 

the orthogonal basis, where ``lam`` is a partition. 

 

INPUT: 

 

- ``lam`` -- a partition 

 

OUTPUT: 

 

- the expansion of ``s[lam]`` in the orthogonal basis ``self`` 

 

EXAMPLES:: 

 

sage: Sym = SymmetricFunctions(QQ) 

sage: s = Sym.schur() 

sage: o = Sym.orthogonal() 

sage: o._s_to_o_on_basis(Partition([])) 

o[] 

sage: o._s_to_o_on_basis(Partition([4,2,1])) 

o[1] + 2*o[2, 1] + o[2, 2, 1] + o[3] 

+ o[3, 1, 1] + o[3, 2] + o[4, 1] + o[4, 2, 1] 

sage: s(o._s_to_o_on_basis(Partition([3,1]))) == s[3,1] 

True 

""" 

R = self.base_ring() 

n = sum(lam) 

return self._from_dict({ mu: R.sum( lrcalc.lrcoef_unsafe(lam, mu, [2*x for x in nu]) 

for nu in Partitions(j) ) 

for j in range(n//2+1) # // 2 for horizontal dominoes 

for mu in Partitions(n-2*j) })