Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Split chains/cochains as separate parents and expose cup product
Browse files Browse the repository at this point in the history
  • Loading branch information
vbraun committed Jul 28, 2016
1 parent cadb3b6 commit 294aa8e
Show file tree
Hide file tree
Showing 3 changed files with 694 additions and 133 deletions.
150 changes: 19 additions & 131 deletions src/sage/homology/cell_complex.py
Expand Up @@ -33,14 +33,26 @@
:meth:`~GenericCellComplex.homology` method for cell complexes --
just make sure it gets documented.
"""
from __future__ import absolute_import

########################################################################
# Copyright (C) 2009 John H. Palmieri <palmieri@math.washington.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 __future__ import absolute_import

from sage.structure.sage_object import SageObject
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement
from sage.misc.abstract_method import abstract_method
from sage.homology.chains import Chains, Cochains


class GenericCellComplex(SageObject):
r"""
Expand Down Expand Up @@ -744,7 +756,11 @@ def n_chains(self, n, base_ring=ZZ, cochains=False):
sage: list(simplicial_complexes.Sphere(2).n_chains(1, QQ, cochains=True).basis())
[\chi_(0, 1), \chi_(0, 2), \chi_(0, 3), \chi_(1, 2), \chi_(1, 3), \chi_(2, 3)]
"""
return Chains(tuple(self.n_cells(n)), base_ring, cochains)
n_cells = tuple(self.n_cells(n))
if cochains:
return Cochains(self, n, n_cells, base_ring)
else:
return Chains(self, n, n_cells, base_ring)

def algebraic_topological_model(self, base_ring=QQ):
r"""
Expand Down Expand Up @@ -1115,131 +1131,3 @@ def _repr_(self):
return Name + " complex " + vertex_string + cells_string


class Chains(CombinatorialFreeModule):
r"""
Class for the free module of chains and/or cochains in a given
degree.
INPUT:
- ``n_cells`` -- tuple of `n`-cells, which thus forms a basis for
this module
- ``base_ring`` -- optional (default `\ZZ`)
- ``cochains`` -- boolean (optional, default ``False``); if
``True``, return cochains instead
One difference between chains and cochains is notation. In a
simplicial complex, for example, a simplex ``(0,1,2)`` is written
as "(0,1,2)" in the group of chains but as "\chi_(0,1,2)" in the
group of cochains.
Also, since the free modules of chains and cochains are dual,
there is a pairing `\langle c, z \rangle`, sending a cochain `c`
and a chain `z` to a scalar.
EXAMPLES::
sage: S2 = simplicial_complexes.Sphere(2)
sage: C_2 = S2.n_chains(1)
sage: C_2_co = S2.n_chains(1, cochains=True)
sage: x = C_2.basis()[Simplex((0,2))]
sage: y = C_2.basis()[Simplex((1,3))]
sage: z = x+2*y
sage: a = C_2_co.basis()[Simplex((1,3))]
sage: b = C_2_co.basis()[Simplex((0,3))]
sage: c = 3*a-2*b
sage: z
(0, 2) + 2*(1, 3)
sage: c
-2*\chi_(0, 3) + 3*\chi_(1, 3)
sage: c.eval(z)
6
"""
def __init__(self, n_cells, base_ring=None, cochains=False):
"""
EXAMPLES::
sage: T = cubical_complexes.Torus()
sage: T.n_chains(2, QQ)
Free module generated by {[1,1] x [0,1] x [1,1] x [0,1],
[0,0] x [0,1] x [0,1] x [1,1], [0,0] x [0,1] x [1,1] x [0,1],
[0,0] x [0,1] x [0,0] x [0,1], [0,1] x [1,1] x [0,1] x [0,0],
[0,1] x [0,0] x [0,0] x [0,1], [1,1] x [0,1] x [0,1] x [0,0],
[0,1] x [1,1] x [0,0] x [0,1], [0,0] x [0,1] x [0,1] x [0,0],
[0,1] x [0,0] x [0,1] x [0,0], [0,1] x [0,0] x [1,1] x [0,1],
[0,1] x [1,1] x [1,1] x [0,1], [0,1] x [0,0] x [0,1] x [1,1],
[1,1] x [0,1] x [0,0] x [0,1], [1,1] x [0,1] x [0,1] x [1,1],
[0,1] x [1,1] x [0,1] x [1,1]} over Rational Field
sage: T.n_chains(2).dimension()
16
TESTS::
sage: T.n_chains(2).base_ring()
Integer Ring
sage: T.n_chains(8).dimension()
0
sage: T.n_chains(-3).dimension()
0
"""
if base_ring is None:
base_ring=ZZ
self._cochains = cochains
if cochains:
CombinatorialFreeModule.__init__(self, base_ring, n_cells,
prefix='\\chi', bracket=['_', ''])
else:
CombinatorialFreeModule.__init__(self, base_ring, n_cells,
prefix='', bracket=False)

class Element(CombinatorialFreeModuleElement):

def eval(self, other):
"""
Evaluate this cochain on the chain ``other``.
INPUT:
- ``other`` -- a chain for the same cell complex in the
same dimension with the same base ring
OUTPUT: scalar
EXAMPLES::
sage: S2 = simplicial_complexes.Sphere(2)
sage: C_2 = S2.n_chains(1)
sage: C_2_co = S2.n_chains(1, cochains=True)
sage: x = C_2.basis()[Simplex((0,2))]
sage: y = C_2.basis()[Simplex((1,3))]
sage: z = x+2*y
sage: a = C_2_co.basis()[Simplex((1,3))]
sage: b = C_2_co.basis()[Simplex((0,3))]
sage: c = 3*a-2*b
sage: z
(0, 2) + 2*(1, 3)
sage: c
-2*\chi_(0, 3) + 3*\chi_(1, 3)
sage: c.eval(z)
6
TESTS::
sage: z.eval(c) # z is not a cochain
Traceback (most recent call last):
...
ValueError: this element is not a cochain
sage: c.eval(c) # can't evaluate a cochain on a cochain
Traceback (most recent call last):
...
ValueError: the elements are not compatible
"""
if not self.parent()._cochains:
raise ValueError('this element is not a cochain')
if not (other.parent().indices() == self.parent().indices()
and other.base_ring() == self.base_ring()
and not other.parent()._cochains):
raise ValueError('the elements are not compatible')
result = sum(coeff * other.coefficient(cell) for cell, coeff in self)
return result

0 comments on commit 294aa8e

Please sign in to comment.