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

""" 

Koszul Complexes 

""" 

 

######################################################################## 

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

# 

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

# as published by the Free Software Foundation; either version 2 of 

# the License, or (at your option) any later version. 

# 

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

######################################################################## 

from six.moves import range 

 

from sage.structure.unique_representation import UniqueRepresentation 

from sage.structure.parent import Parent 

from sage.combinat.combination import rank 

from sage.arith.all import binomial 

from sage.rings.all import ZZ 

from sage.matrix.constructor import matrix 

from sage.homology.chain_complex import ChainComplex_class 

 

import itertools 

 

class KoszulComplex(ChainComplex_class, UniqueRepresentation): 

r""" 

A Koszul complex. 

 

Let `R` be a ring and consider `x_1, x_2, \ldots, x_n \in R`. The 

*Koszul complex* `K_*(x_1, \ldots, x_n)` is given by defining a 

chain complex structure on the exterior algebra `\bigwedge^n R` with 

the basis `e_{i_1} \wedge \cdots \wedge e_{i_a}`. The differential is 

given by 

 

.. MATH:: 

 

\partial(e_{i_1} \wedge \cdots \wedge e_{i_a}) = 

\sum_{r=1}^a (-1)^{r-1} x_{i_r} e_{i_1} \wedge \cdots \wedge 

\hat{e}_{i_r} \wedge \cdots \wedge e_{i_a}, 

 

where `\hat{e}_{i_r}` denotes the omitted factor. 

 

Alternatively we can describe the Koszul complex by considering the 

basic complex `K_{x_i}` 

 

.. MATH:: 

 

0 \rightarrow R \xrightarrow{x_i} R \rightarrow 0. 

 

Then the Koszul complex is given by 

`K_*(x_1, \ldots, x_n) = \bigotimes_i K_{x_i}`. 

 

INPUT: 

 

- ``R`` -- the base ring 

- ``elements`` -- a tuple of elements of ``R`` 

 

EXAMPLES:: 

 

sage: R.<x,y,z> = QQ[] 

sage: K = KoszulComplex(R, [x,y]) 

sage: ascii_art(K) 

[-y] 

[x y] [ x] 

0 <-- C_0 <------ C_1 <----- C_2 <-- 0 

sage: K = KoszulComplex(R, [x,y,z]) 

sage: ascii_art(K) 

[-y -z 0] [ z] 

[ x 0 -z] [-y] 

[x y z] [ 0 x y] [ x] 

0 <-- C_0 <-------- C_1 <----------- C_2 <----- C_3 <-- 0 

sage: K = KoszulComplex(R, [x+y*z,x+y-z]) 

sage: ascii_art(K) 

[-x - y + z] 

[ y*z + x x + y - z] [ y*z + x] 

0 <-- C_0 <---------------------- C_1 <------------- C_2 <-- 0 

 

REFERENCES: 

 

- :wikipedia:`Koszul_complex` 

""" 

@staticmethod 

def __classcall_private__(cls, R=None, elements=None): 

""" 

Normalize input to ensure a unique representation. 

 

TESTS:: 

 

sage: R.<x,y,z> = QQ[] 

sage: K1 = KoszulComplex(R, [x,y,z]) 

sage: K2 = KoszulComplex(R, (x,y,z)) 

sage: K3 = KoszulComplex((x,y,z)) 

sage: K1 is K2 and K2 is K3 

True 

 

Check some corner cases:: 

 

sage: K1 = KoszulComplex(ZZ) 

sage: K2 = KoszulComplex(()) 

sage: K3 = KoszulComplex(ZZ, []) 

sage: K1 is K2 and K2 is K3 

True 

sage: K1 is KoszulComplex() 

True 

""" 

if elements is None: 

if R is None: 

R = () 

elements = R 

if not elements: 

R = ZZ # default to ZZ as the base ring if no elements are given 

elif isinstance(R, Parent): 

elements = () 

else: 

R = elements[0].parent() 

elif R is None: # elements is not None 

R = elements[0].parent() 

return super(KoszulComplex, cls).__classcall__(cls, R, tuple(elements)) 

 

def __init__(self, R, elements): 

""" 

Initialize ``self``. 

 

EXAMPLES:: 

 

sage: R.<x,y,z> = QQ[] 

sage: K = KoszulComplex(R, [x,y]) 

sage: TestSuite(K).run() 

""" 

# Generate the differentials 

self._elements = elements 

n = len(elements) 

I = list(range(n)) 

diff = {} 

zero = R.zero() 

for i in I: 

M = matrix(R, binomial(n,i), binomial(n,i+1), zero) 

j = 0 

for comb in itertools.combinations(I, i+1): 

for k,val in enumerate(comb): 

r = rank(comb[:k] + comb[k+1:], n, False) 

M[r,j] = (-1)**k * elements[val] 

j += 1 

M.set_immutable() 

diff[i+1] = M 

diff[0] = matrix(R, 0, 1, zero) 

diff[0].set_immutable() 

diff[n+1] = matrix(R, 1, 0, zero) 

diff[n+1].set_immutable() 

ChainComplex_class.__init__(self, ZZ, ZZ(-1), R, diff) 

 

def _repr_(self): 

""" 

Return a string representation of ``self``. 

 

EXAMPLES:: 

 

sage: R.<x,y,z> = QQ[] 

sage: KoszulComplex(R, [x,y,z]) 

Koszul complex defined by (x, y, z) over 

Multivariate Polynomial Ring in x, y, z over Rational Field 

 

sage: KoszulComplex(ZZ, []) 

Trivial Koszul complex over Integer Ring 

""" 

if not self._elements: 

return "Trivial Koszul complex over {}".format(self.base_ring()) 

return "Koszul complex defined by {} over {}".format(self._elements, self.base_ring())