@@ -19,8 +19,9 @@ AUTHORS:
19
19
# *****************************************************************************
20
20
21
21
from sage.structure.parent cimport Parent
22
- from sage.data_structures.bitset cimport FrozenBitset, Bitset
22
+ from sage.data_structures.bitset cimport Bitset
23
23
from sage.algebras.weyl_algebra import repr_from_monomials
24
+ from sage.data_structures.blas_dict cimport scal
24
25
from copy import copy
25
26
26
27
cdef class CliffordAlgebraElement(IndexedFreeModuleElement):
@@ -95,8 +96,25 @@ cdef class CliffordAlgebraElement(IndexedFreeModuleElement):
95
96
cdef dict next_level, cur, d = {}
96
97
cdef FrozenBitset ml, mr, t
97
98
cdef Py_ssize_t i, j
99
+ cdef CliffordAlgebraElement rhs = < CliffordAlgebraElement> other
98
100
99
- for ml,cl in self :
101
+ # Special case when multiplying by 0
102
+ if not self ._monomial_coefficients:
103
+ return self
104
+ if not rhs._monomial_coefficients:
105
+ return rhs
106
+
107
+ # Special case when multiplying by an element of the base ring
108
+ if len (self ._monomial_coefficients) == 1 :
109
+ ml, cl = next(iter (self ._monomial_coefficients.items()))
110
+ if ml.isempty():
111
+ return rhs._mul_term_self(ml, cl)
112
+ if len (rhs._monomial_coefficients) == 1 :
113
+ mr, cr = next(iter (self ._monomial_coefficients.items()))
114
+ if mr.isempty():
115
+ return self ._mul_self_term(mr, cr)
116
+
117
+ for ml, cl in self :
100
118
# Distribute the current term ``cl`` * ``ml`` over ``other``.
101
119
cur = copy(other._monomial_coefficients) # The current distribution of the term
102
120
for i in reversed (ml):
@@ -150,6 +168,76 @@ cdef class CliffordAlgebraElement(IndexedFreeModuleElement):
150
168
151
169
return self .__class__ (self .parent(), d)
152
170
171
+ cdef CliffordAlgebraElement _mul_self_term(self , FrozenBitset supp, coeff):
172
+ r """
173
+ Multiply ``self * term`` with the ``term`` having support ``supp``
174
+ and coefficient ``coeff``.
175
+
176
+ EXAMPLES::
177
+
178
+ sage: E. <x,y,z> = ExteriorAlgebra( QQ)
179
+ sage: r = sum( E. basis( ))
180
+ sage: x * y # indirect doctest
181
+ x* y
182
+ sage: y * x # indirect doctest
183
+ -x* y
184
+ sage: r * x # indirect doctest
185
+ x* y* z - x* y - x* z + x
186
+ sage: r * -x # indirect doctest
187
+ -x* y* z + x* y + x* z - x
188
+ sage: r * ( 2* x) # indirect doctest
189
+ 2* x* y* z - 2* x* y - 2* x* z + 2* x
190
+ sage: r * y # indirect doctest
191
+ -x* y* z + x* y - y* z + y
192
+ sage: r * z # indirect doctest
193
+ x* y* z + x* z + y* z + z
194
+ sage: r * ( x* y) # indirect doctest
195
+ x* y* z + x* y
196
+ sage: r * ( -x* y) # indirect doctest
197
+ -x* y* z - x* y
198
+ sage: r * ( x* y* z) # indirect doctest
199
+ x* y* z
200
+ sage: r * 1 == r # indirect doctest
201
+ True
202
+ sage: r * -1 == -r # indirect doctest
203
+ True
204
+ sage: r * 2 # indirect doctest
205
+ 2* x* y* z + 2* x* y + 2* x* z + 2* y* z + 2* x + 2* y + 2* z + 2
206
+ """
207
+ cdef dict d
208
+ cdef list to_remove
209
+ cdef Py_ssize_t num_cross, tot_cross, i, j
210
+ cdef FrozenBitset ml
211
+
212
+ if supp.isempty(): # Multiplication by a base ring element
213
+ if coeff == self ._parent._base.one():
214
+ return self
215
+ if coeff == - self ._parent._base.one():
216
+ return self ._neg_()
217
+
218
+ return type (self )(self ._parent,
219
+ scal(coeff, self ._monomial_coefficients,
220
+ factor_on_left = False ))
221
+
222
+ return type (self )(self ._parent, {supp: coeff}) * self
223
+
224
+ cdef CliffordAlgebraElement _mul_term_self(self , FrozenBitset supp, coeff):
225
+ r """
226
+ Multiply ``term * self`` with the ``term`` having support ``supp``
227
+ and coefficient ``coeff``.
228
+ """
229
+ if supp.isempty(): # Multiplication by a base ring element
230
+ if coeff == self ._parent._base.one():
231
+ return self
232
+ if coeff == - self ._parent._base.one():
233
+ return self ._neg_()
234
+
235
+ return type (self )(self ._parent,
236
+ scal(coeff, self ._monomial_coefficients,
237
+ factor_on_left = True ))
238
+
239
+ return type (self )(self ._parent, {supp: coeff}) * self
240
+
153
241
def list (self ):
154
242
"""
155
243
Return the list of monomials and their coefficients in ``self``
@@ -352,15 +440,30 @@ cdef class ExteriorAlgebraElement(CliffordAlgebraElement):
352
440
cdef Parent P = self ._parent
353
441
zero = P._base.zero()
354
442
cdef dict d
355
- cdef Py_ssize_t n = P.ngens()
356
443
cdef ExteriorAlgebraElement rhs = < ExteriorAlgebraElement> other
357
444
cdef list to_remove
358
445
359
446
cdef FrozenBitset ml, mr, t
360
- cdef Py_ssize_t num_cross, tot_cross, i, j
447
+ cdef Py_ssize_t n, num_cross, tot_cross, i, j
361
448
362
- ml = FrozenBitset()
449
+ # Special case: one of them is zero
450
+ if not self ._monomial_coefficients:
451
+ return self
452
+ if not rhs._monomial_coefficients:
453
+ return rhs
454
+
455
+ # Special case: other is a single term
456
+ if len (rhs._monomial_coefficients) == 1 :
457
+ mr, cr = next(iter (rhs._monomial_coefficients.items()))
458
+ return self ._mul_self_term(mr, cr)
363
459
460
+ # Special case: self is a single term
461
+ if len (self ._monomial_coefficients) == 1 :
462
+ ml, cl = next(iter (self ._monomial_coefficients.items()))
463
+ return rhs._mul_term_self(ml, cl)
464
+
465
+ # Do some special processing for the constant monomial in ml
466
+ ml = FrozenBitset()
364
467
if ml in self ._monomial_coefficients:
365
468
const_coeff = self ._monomial_coefficients[ml]
366
469
d = dict (rhs._monomial_coefficients) # Make a shallow copy
@@ -375,11 +478,12 @@ cdef class ExteriorAlgebraElement(CliffordAlgebraElement):
375
478
else :
376
479
d = {}
377
480
378
- for ml,cl in self ._monomial_coefficients.items(): # ml for "monomial on the left"
379
- if not ml: # We already handled the trivial element
481
+ n = P.ngens()
482
+ for ml, cl in self ._monomial_coefficients.items(): # ml for "monomial on the left"
483
+ if ml.isempty(): # We already handled the trivial element
380
484
continue
381
485
for mr,cr in rhs._monomial_coefficients.items(): # mr for "monomial on the right"
382
- if not mr :
486
+ if mr.isempty() :
383
487
t = ml
384
488
else :
385
489
if not ml.isdisjoint(mr):
@@ -402,12 +506,199 @@ cdef class ExteriorAlgebraElement(CliffordAlgebraElement):
402
506
if tot_cross % 2 :
403
507
cr = - cr
404
508
405
- d[t] = d.get(t, zero) + cl * cr
406
- if not d[t] :
509
+ val = d.get(t, zero) + cl * cr
510
+ if not val :
407
511
del d[t]
512
+ else :
513
+ d[t] = val
408
514
409
515
return self .__class__ (P, d)
410
516
517
+ cdef CliffordAlgebraElement _mul_self_term(self , FrozenBitset supp, coeff):
518
+ r """
519
+ Multiply ``self * term`` with the ``term`` having support ``supp``
520
+ and coefficient ``coeff``.
521
+
522
+ EXAMPLES::
523
+
524
+ sage: E. <x,y,z> = ExteriorAlgebra( QQ)
525
+ sage: r = sum( E. basis( ))
526
+ sage: x * y # indirect doctest
527
+ x* y
528
+ sage: y * x # indirect doctest
529
+ -x* y
530
+ sage: r * x # indirect doctest
531
+ x* y* z - x* y - x* z + x
532
+ sage: r * -x # indirect doctest
533
+ -x* y* z + x* y + x* z - x
534
+ sage: r * ( 2* x) # indirect doctest
535
+ 2* x* y* z - 2* x* y - 2* x* z + 2* x
536
+ sage: r * y # indirect doctest
537
+ -x* y* z + x* y - y* z + y
538
+ sage: r * z # indirect doctest
539
+ x* y* z + x* z + y* z + z
540
+ sage: r * ( x* y) # indirect doctest
541
+ x* y* z + x* y
542
+ sage: r * ( -x* y) # indirect doctest
543
+ -x* y* z - x* y
544
+ sage: r * ( x* y* z) # indirect doctest
545
+ x* y* z
546
+ sage: r * 1 == r # indirect doctest
547
+ True
548
+ sage: r * -1 == -r # indirect doctest
549
+ True
550
+ sage: r * 2 # indirect doctest
551
+ 2* x* y* z + 2* x* y + 2* x* z + 2* y* z + 2* x + 2* y + 2* z + 2
552
+ """
553
+ cdef dict d
554
+ cdef list to_remove
555
+ cdef Py_ssize_t num_cross, tot_cross, i, j
556
+ cdef FrozenBitset ml
557
+
558
+ if supp.isempty(): # Multiplication by a base ring element
559
+ if coeff == self ._parent._base.one():
560
+ return self
561
+ if coeff == - self ._parent._base.one():
562
+ return self ._neg_()
563
+
564
+ return type (self )(self ._parent,
565
+ scal(coeff, self ._monomial_coefficients,
566
+ factor_on_left = False ))
567
+
568
+ n = self ._parent.ngens()
569
+ d = {}
570
+ for ml, cl in self ._monomial_coefficients.items(): # ml for "monomial on the left"
571
+ if not ml.isdisjoint(supp):
572
+ # if they intersect nontrivially, move along.
573
+ continue
574
+ t = < FrozenBitset> ml._union(supp)
575
+ it = iter (supp)
576
+ j = next(it)
577
+
578
+ num_cross = 0 # keep track of the number of signs
579
+ tot_cross = 0
580
+ for i in ml:
581
+ while i > j:
582
+ num_cross += 1
583
+ try :
584
+ j = next(it)
585
+ except StopIteration :
586
+ j = n + 1
587
+ tot_cross += num_cross
588
+ if tot_cross % 2 :
589
+ d[t] = - cl
590
+ else :
591
+ d[t] = cl
592
+
593
+ if coeff == - self ._parent._base.one():
594
+ for k in d:
595
+ d[k] = - d[k]
596
+ elif coeff != self ._parent._base.one():
597
+ to_remove = []
598
+ for k in d:
599
+ d[k] *= coeff
600
+ if not d[k]: # there might be zero divisors
601
+ to_remove.append(k)
602
+ for k in to_remove:
603
+ del d[k]
604
+ return type (self )(self ._parent, d)
605
+
606
+ cdef CliffordAlgebraElement _mul_term_self(self , FrozenBitset supp, coeff):
607
+ r """
608
+ Multiply ``term * self`` with the ``term`` having support ``supp``
609
+ and coefficient ``coeff``.
610
+
611
+ EXAMPLES::
612
+
613
+ sage: E. <x,y,z> = ExteriorAlgebra( QQ)
614
+ sage: r = sum( E. basis( ))
615
+ sage: x * r # indirect doctest
616
+ x* y* z + x* y + x* z + x
617
+ sage: ( -x) * r # indirect doctest
618
+ -x* y* z - x* y - x* z - x
619
+ sage: ( 2* x) * r # indirect doctest
620
+ 2* x* y* z + 2* x* y + 2* x* z + 2* x
621
+ sage: y * r # indirect doctest
622
+ -x* y* z - x* y + y* z + y
623
+ sage: z * r # indirect doctest
624
+ x* y* z - x* z - y* z + z
625
+ sage: ( x* y) * r # indirect doctest
626
+ x* y* z + x* y
627
+ sage: ( -x* y) * r # indirect doctest
628
+ -x* y* z - x* y
629
+ sage: ( x* y* z) * r # indirect doctest
630
+ x* y* z
631
+ sage: 1 * r == r # indirect doctest
632
+ True
633
+ sage: -1 * r == -r # indirect doctest
634
+ True
635
+ sage: 2 * r # indirect doctest
636
+ 2* x* y* z + 2* x* y + 2* x* z + 2* y* z + 2* x + 2* y + 2* z + 2
637
+ """
638
+ cdef dict d
639
+ cdef list to_remove
640
+ cdef Py_ssize_t n, num_cross, tot_cross, i, j
641
+ cdef FrozenBitset mr, t
642
+
643
+ if supp.isempty(): # Multiplication by a base ring element
644
+ if coeff == self ._parent._base.one():
645
+ return self
646
+ if coeff == - self ._parent._base.one():
647
+ return self ._neg_()
648
+
649
+ return type (self )(self ._parent,
650
+ scal(coeff, self ._monomial_coefficients,
651
+ factor_on_left = True ))
652
+
653
+ n = self ._parent.ngens()
654
+ d = {}
655
+ mr = FrozenBitset()
656
+ # We need to special case the constant coefficient
657
+ const_coeff = None
658
+ if mr in self ._monomial_coefficients:
659
+ const_coeff = self ._monomial_coefficients.pop(mr)
660
+ d[supp] = const_coeff
661
+
662
+ for mr, cr in self ._monomial_coefficients.items(): # mr for "monomial on the right"
663
+ if not supp.isdisjoint(mr):
664
+ # if they intersect nontrivially, move along.
665
+ continue
666
+ t = < FrozenBitset> supp._union(mr)
667
+ it = iter (mr)
668
+ j = next(it) # We assume mr is non-empty here
669
+
670
+ num_cross = 0 # keep track of the number of signs
671
+ tot_cross = 0
672
+ for i in supp:
673
+ while i > j:
674
+ num_cross += 1
675
+ try :
676
+ j = next(it)
677
+ except StopIteration :
678
+ j = n + 1
679
+ tot_cross += num_cross
680
+ if tot_cross % 2 :
681
+ d[t] = - cr
682
+ else :
683
+ d[t] = cr
684
+
685
+ if coeff == - self ._parent._base.one():
686
+ for k in d:
687
+ d[k] = - d[k]
688
+ elif coeff != self ._parent._base.one():
689
+ to_remove = []
690
+ for k in d:
691
+ d[k] = coeff * d[k] # This will work for non-commutative base rings
692
+ if not d[k]: # there might be zero divisors
693
+ to_remove.append(k)
694
+ for k in to_remove:
695
+ del d[k]
696
+
697
+ # Add back the constant coefficient since we removed it for the special case
698
+ if const_coeff is not None :
699
+ self ._monomial_coefficients[FrozenBitset()] = const_coeff
700
+ return type (self )(self ._parent, d)
701
+
411
702
def reduce (self , I , left = True ):
412
703
r """
413
704
Reduce ``self`` with respect to the elements in ``I``.
0 commit comments