Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the Tor algebra for matroids #39169

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/sage/matroids/matroid.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -8111,6 +8111,10 @@ cdef class Matroid(SageObject):
from sage.matroids.chow_ring import ChowRing
return ChowRing(M=self, R=R, augmented=augmented, presentation=presentation)

def tor_algebra(self, R):
from sage.matroids.tor_algebra import TorAlgebra
return TorAlgebra(R, self)

cpdef plot(self, B=None, lineorders=None, pos_method=None, pos_dict=None, save_pos=False):
"""
Return geometric representation as a sage graphics object.
Expand Down
192 changes: 192 additions & 0 deletions src/sage/matroids/tor_algebra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
r"""
Tor algebra of matroids

AUTHORS:

- Travis Scrimshaw (2024-12): initial implementation
"""

# ****************************************************************************
# Copyright (C) 2024 Travis Scrimshaw <tcscrims at gmail.com>
#
# 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.
# https://www.gnu.org/licenses/
# ****************************************************************************

from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis
from sage.combinat.free_module import CombinatorialFreeModule


class TorAlgebra(CombinatorialFreeModule):
r"""
The Tor algebra of a matroid.

INPUT:

- ``M`` -- matroid
- ``R`` -- commutative ring

REFERENCES:

- [Binder2024]_

EXAMPLES::

sage: M = matroids.catalog.P8pp()
sage: Tor = M.tor_algebra(QQ)

Check failure on line 38 in src/sage/matroids/tor_algebra.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Got: {((), ()): 0, (('g',), ()): 1, (('a',), ()): 2, (('f',), ()): 3, (('b',), ()): 4, (('d',), ()): 5, (('c',), ()): 6, (('e',), ()): 7, (('h',), ()): 8, (('g', 'a'), ()): 9, (('g', 'f'), ()): 10, (('g', 'b'), ()): 11, (('g', 'd'), ()): 12, (('g', 'c'), ()): 13, (('g', 'e'), ()): 14, (('g', 'h'), ()): 15, (('a', 'f'), ()): 16, (('a', 'b'), ()): 17, (('a', 'd'), ()): 18, (('a', 'c'), ()): 19, (('a', 'e'), ()): 20, (('a', 'h'), ()): 21, (('f', 'b'), ()): 22, (('f', 'd'), ()): 23, (('f', 'c'), ()): 24, (('f', 'e'), ()): 25, (('f', 'h'), ()): 26, (('b', 'd'), ()): 27, (('b', 'c'), ()): 28, (('b', 'e'), ()): 29, (('b', 'h'), ()): 30, (('d', 'c'), ()): 31, (('d', 'e'), ()): 32, (('d', 'h'), ()): 33, (('c', 'e'), ()): 34, (('c', 'h'), ()): 35, (('e', 'h'), ()): 36, (('g', 'a', 'f'), ()): 37, (('g', 'a', 'b'), ()): 38, (('g', 'a', 'd'), ()): 39, (('g', 'a', 'c'), ()): 40, (('g', 'a', 'e'), ()): 41, (('g', 'a', 'h'), ()): 42, (('g', 'f', 'b'), ()): 43, (('g', 'f', 'd'), ()): 44, (('g', 'f', 'c'), ()): 45, (('g', 'f', 'e'), ()): 46, (('g', 'f', 'h'), ()): 47, (('g', 'b', 'd'), ()): 48, (('g', 'b', 'c'), ()): 49, (('g', 'b', 'e'), ()): 50, (('g', 'b', 'h'), ()): 51, (('g', 'd', 'c'), ()): 52, (('g', 'd', 'e'), ()): 53, (('g', 'd', 'h'), ()): 54, (('g', 'c', 'e'), ()): 55, (('g', 'c', 'h'), ()): 56, (('g', 'e', 'h'), ()): 57, (('a', 'f', 'b'), ()): 58, (('a', 'f', 'd'), ()): 59, (('a', 'f', 'c'), ()): 60, (('a', 'f', 'e'), ()): 61, (('a', 'f', 'h'), ()): 62, (('a', 'b', 'd'), ()): 63, (('a', 'b', 'c'), ()): 64, (('a', 'b', 'e'), ()): 65, (('a', 'b', 'h'), ()): 66, (('a', 'd', 'c'), ()): 67, (('a', 'd', 'e'), ()): 68, (('a', 'd', 'h'), ()): 69, (('a', 'c', 'e'), ()): 70, (('a', 'c', 'h'), ()): 71, (('a', 'e', 'h'), ()): 72, (('f', 'b', 'd'), ()): 73, (('f', 'b', 'c'), ()): 74, (('f', 'b', 'e'), ()): 75, (('f', 'b', 'h'), ()): 76, (('f', 'd', 'c'), ()): 77, (('f', 'd', 'e'), ()): 78, (('f', 'd', 'h'), ()): 79, (('f', 'c', 'e'), ()): 80, (('f', 'c', 'h'), ()): 81, (('f', 'e', 'h'), ()): 82, (('b', 'd', 'c'), ()): 83, (('b', 'd', 'e'), ()): 84, (('b', 'd', 'h'), ()): 85, (('b', 'c', 'e'), ()): 86, (('b', 'c', 'h'), ()): 87, (('b', 'e', 'h'), ()): 88, (('d', 'c', 'e'), ()): 89, (('d', 'c', 'h'), ()): 90, (('d', 'e', 'h'), ()): 91, (('c', 'e', 'h'), ()): 92, (('g', 'a', 'd', 'e'), ()): 93, (('g', 'a', 'c', 'h'), ()): 94, (('g', 'f', 'b', 'd'), ()): 95, (('g', 'b', 'c', 'e'), ()): 96, (('a', 'f', 'b', 'h'), ()): 97, (('a', 'f', 'c', 'e'), ()): 98, (('f', 'd', 'c', 'h'), ()): 99, (('b', 'd', 'e', 'h'), ()): 100} {((), ('g',)): 0, ((), ('a',)): 1, ((), ('f',)): 2, ((), ('b',)): 3, ((), ('d',)): 4, ((), ('c',)): 5, ((), ('e',)): 6, (('g',), ('a',)): 7, (('g',), ('f',)): 8, (('g',), ('b',)): 9, (('g',), ('d',)): 10, (('g',), ('c',)): 11, (('g',), ('e',)): 12, (('a',), ('g',)): 13, (('a',), ('f',)): 14, (('a',), ('b',)): 15, (('a',), ('d',)): 16, (('a',), ('c',)): 17, (('a',), ('e',)): 18, (('f',), ('g',)): 19, (('f',), ('a',)): 20, (('f',), ('b',)): 21, (('f',), ('d',)): 22, (('f',), ('c',)): 23, (('f',), ('e',)): 24, (('b',), ('g',)): 25, (('b',), ('a',)): 26, (('b',), ('f',)): 27, (('b',), ('d',)): 28, (('b',), ('c',)): 29, (('b',), ('e',)): 30, (('d',), ('g',)): 31, (('d',), ('a',)): 32, (('d',), ('f',)): 33, (('d',), ('b',)): 34, (('d',), ('c',)): 35, (('d',), ('e',)): 36, (('c',), ('g',)): 37, (('c',), ('a',)): 38, (('c',), ('f',)): 39, (('c',), ('b',)): 40, (('c',), ('d',)): 41, (('c',), ('e',)): 42, (('e',), ('g',)): 43, (('e',), ('a',)): 44, (('e',), ('f',)): 45, (('e',), ('b',)): 46, (('e',), ('d',)): 47, (('e',), ('c',)): 48, (('h',), ('g',)): 49, (('h',), ('a',)): 50, (('h',), ('f',)): 51, (('h',), ('b',)): 52, (('h',), ('d',)): 53, (('h',), ('c',)): 54, (('g', 'a'), ('f',)): 55, (('g', 'a'), ('b',)): 56, (('g', 'a'), ('d',)): 57, (('g', 'a'), ('c',)): 58, (('g', 'a'), ('e',)): 59, (('g', 'f'), ('a',)): 60, (('g', 'f'), ('b',)): 61, (('g', 'f'), ('d',)): 62, (('g', 'f'), ('c',)): 63, (('g', 'f'), ('e',)): 64, (('g', 'b'), ('a',)): 65, (('g', 'b'), ('f',)): 66, (('g', 'b'), ('d',)): 67, (('g', 'b'), ('c',)): 68, (('
sage: Tor

Check failure on line 39 in src/sage/matroids/tor_algebra.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Got: Tor algebra of P8'': Matroid of rank 4 on 8 elements with 8 nonspanning circuits over Rational Field
"""
def __init__(self, R, M):
r"""
Initialize ``self``.

EXAMPLES::

sage: Tor = matroids.Wheel(3).tor_algebra(QQ)

Check failure on line 47 in src/sage/matroids/tor_algebra.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Got: {((), ()): 0, ((0,), ()): 1, ((1,), ()): 2, ((2,), ()): 3, ((3,), ()): 4, ((4,), ()): 5, ((5,), ()): 6, ((0, 1), ()): 7, ((0, 2), ()): 8, ((0, 3), ()): 9, ((0, 4), ()): 10, ((0, 5), ()): 11, ((1, 2), ()): 12, ((1, 3), ()): 13, ((1, 4), ()): 14, ((1, 5), ()): 15, ((2, 3), ()): 16, ((2, 4), ()): 17, ((2, 5), ()): 18, ((3, 4), ()): 19, ((3, 5), ()): 20, ((4, 5), ()): 21, ((0, 1, 3), ()): 22, ((0, 2, 5), ()): 23, ((1, 2, 4), ()): 24, ((3, 4, 5), ()): 25} {((), (0,)): 0, ((), (1,)): 1, ((), (2,)): 2, ((), (3,)): 3, ((), (4,)): 4, ((0,), (1,)): 5, ((0,), (2,)): 6, ((0,), (3,)): 7, ((0,), (4,)): 8, ((1,), (0,)): 9, ((1,), (2,)): 10, ((1,), (3,)): 11, ((1,), (4,)): 12, ((2,), (0,)): 13, ((2,), (1,)): 14, ((2,), (3,)): 15, ((2,), (4,)): 16, ((3,), (0,)): 17, ((3,), (1,)): 18, ((3,), (2,)): 19, ((3,), (4,)): 20, ((4,), (0,)): 21, ((4,), (1,)): 22, ((4,), (2,)): 23, ((4,), (3,)): 24, ((5,), (0,)): 25, ((5,), (1,)): 26, ((5,), (2,)): 27, ((5,), (3,)): 28, ((0, 1), (2,)): 29, ((0, 1), (3,)): 30, ((0, 1), (4,)): 31, ((0, 2), (1,)): 32, ((0, 2), (3,)): 33, ((0, 2), (4,)): 34, ((0, 3), (1,)): 35, ((0, 3), (2,)): 36, ((0, 3), (4,)): 37, ((0, 4), (1,)): 38, ((0, 4), (2,)): 39, ((0, 4), (3,)): 40, ((0, 5), (1,)): 41, ((0, 5), (2,)): 42, ((0, 5), (3,)): 43, ((1, 2), (0,)): 44, ((1, 2), (3,)): 45, ((1, 2), (4,)): 46, ((1, 3), (0,)): 47, ((1, 3), (2,)): 48, ((1, 3), (4,)): 49, ((1, 4), (0,)): 50, ((1, 4), (2,)): 51, ((1, 4), (3,)): 52, ((1, 5), (0,)): 53, ((1, 5), (2,)): 54, ((1, 5), (3,)): 55, ((2, 3), (0,)): 56, ((2, 3), (1,)): 57, ((2, 3), (4,)): 58, ((2, 4), (0,)): 59, ((2, 4), (1,)): 60, ((2, 4), (3,)): 61, ((2, 5), (0,)): 62, ((2, 5), (1,)): 63, ((2, 5), (3,)): 64, ((3, 4), (0,)): 65, ((3, 4), (1,)): 66, ((3, 4), (2,)): 67, ((3, 5), (0,)): 68, ((3, 5), (1,)): 69, ((3, 5), (2,)): 70, ((4, 5), (0,)): 71, ((4, 5), (1,)): 72, ((4, 5), (2,)): 73, ((0, 1, 3), (2,)): 74, ((0, 1, 3), (4,)): 75, ((0, 2, 5), (1,)): 76, ((0, 2, 5), (3,)): 77, ((1, 2, 4), (0,)): 78, ((1, 2, 4), (3,)): 79, ((3, 4, 5), (0,)): 80, ((3, 4, 5), (1,)): 81} {((), (0, 1)): 0, ((), (0, 2)): 1, ((), (0, 3)): 2, ((), (0, 4)): 3, ((), (1, 2)): 4, ((), (1, 3)): 5, ((), (1, 4)): 6, ((), (2, 3)): 7, ((), (2, 4)): 8, ((), (3, 4)): 9, ((0,), (1, 2)): 10, ((0,), (1, 3)): 11, ((0,), (1, 4)): 12, ((0,), (2, 3)): 13, ((0,), (2, 4)): 14, ((0,), (3, 4)): 15, ((1,), (0, 2)): 16, ((1,), (0, 3)): 17, ((1,), (0, 4)): 18, ((1,), (2, 3)): 19, ((1,), (2, 4)): 20, ((1,), (3, 4)): 21, ((2,), (0, 1)): 22, ((2,), (0, 3)): 23, ((2,), (0, 4)): 24, ((2,), (1, 3)): 25, ((2,), (1, 4)): 26, ((2,), (3, 4)): 27, ((3,), (0, 1)): 28, ((3,), (0, 2)): 29, ((3,), (0, 4)): 30, ((3,), (1, 2)): 31, ((3,), (1, 4)): 32, ((3,), (2, 4)): 33, ((4,), (0, 1)): 34, ((4,), (0, 2)): 35, ((4,), (0, 3)): 36, ((4,), (1, 2)): 37, ((4,), (1, 3)): 38, ((4,), (2, 3)): 39, ((5,), (0, 1)): 40, ((5,), (0, 2)): 41, ((5,), (0, 3)): 42, ((5,), (1, 2)): 43, ((5,), (1, 3)): 44, ((5,), (2, 3)): 45, ((0, 1), (2, 3)): 46, ((0, 1), (2, 4)): 47, ((0, 1), (3, 4)): 48, ((0, 2), (1, 3)): 49, ((0, 2), (1, 4)): 50, ((0, 2), (3, 4)): 51, ((0, 3), (1, 2)): 52, ((0, 3), (1, 4)): 53, ((0, 3), (2, 4)): 54, ((0, 4), (1, 2)): 55, ((0, 4), (1, 3)): 56, ((0, 4), (2, 3)): 57, ((0, 5), (1, 2)): 58, ((0, 5), (1, 3)): 59, ((0, 5), (2, 3)): 60, ((1, 2), (0, 3)): 61, ((1, 2), (0, 4)): 62, ((1, 2), (3, 4)): 63, ((1, 3), (0, 2)): 64, ((1, 3), (0, 4)): 65, ((1, 3), (2, 4)): 66, ((1, 4), (0, 2)): 67, ((1, 4), (0, 3)): 68, ((1, 4), (2, 3)): 69, ((1, 5), (0, 2)): 70, ((1, 5), (0, 3)): 71, ((1, 5), (2, 3)): 72, ((2, 3), (0, 1)): 73, ((2, 3), (0, 4)): 74, ((2, 3), (1, 4)): 75, ((2, 4), (0, 1)): 76, ((2, 4), (0, 3)): 77, ((2, 4), (1, 3)): 78, ((2, 5), (0, 1)): 79, ((2, 5), (0, 3)): 80, ((2, 5), (1, 3)): 81, ((3, 4), (0, 1)): 82, ((3, 4), (0, 2)): 83, ((3, 4), (1, 2)): 84, ((3, 5), (0, 1)): 85, ((3, 5), (0, 2)): 86, ((3, 5), (1, 2)): 87, ((4, 5), (0, 1)): 88, ((4, 5), (0, 2)): 89, ((4, 5), (1, 2)): 90, ((0, 1, 3), (2, 4)): 91, ((0, 2, 5), (1, 3)): 92, ((1, 2, 4), (0, 3)): 93, ((3, 4, 5), (0, 1)): 94} {((), (0, 1, 2)): 0, ((), (0, 1, 3)): 1, ((), (0, 1
sage: TestSuite(Tor).run()

Check failure on line 48 in src/sage/matroids/tor_algebra.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Got: Failure in _test_associativity: Traceback (most recent call last): File "/sage/src/sage/misc/sage_unittest.py", line 298, in run test_method(tester=tester) File "/sage/src/sage/categories/semigroups.py", line 121, in _test_associativity tester.assertEqual((x * y) * z, x * (y * z)) File "sage/structure/element.pyx", line 1505, in sage.structure.element.Element.__mul__ return (<Element>left)._mul_(right) File "sage/structure/element.pyx", line 1551, in sage.structure.element.Element._mul_ return python_op(other) TypeError: 'NotImplementedType' object is not callable ------------------------------------------------------------ Failure in _test_distributivity: Traceback (most recent call last): File "/sage/src/sage/misc/sage_unittest.py", line 298, in run test_method(tester=tester) File "/sage/src/sage/categories/distributive_magmas_and_additive_magmas.py", line 81, in _test_distributivity tester.assertEqual(x * (y + z), (x * y) + (x * z)) File "sage/structure/element.pyx", line 1505, in sage.structure.element.Element.__mul__ return (<Element>left)._mul_(right) File "sage/structure/element.pyx", line 1551, in sage.structure.element.Element._mul_ return python_op(other) TypeError: 'NotImplementedType' object is not callable ------------------------------------------------------------ Failure in _test_elements_eq_symmetric: Traceback (most recent call last): File "/sage/src/sage/misc/sage_unittest.py", line 298, in run test_method(tester=tester) File "/sage/src/sage/categories/sets_cat.py", line 1250, in _test_elements_eq_symmetric tester.assertEqual(x == y, y == x, File "sage/structure/element.pyx", line 1099, in sage.structure.element.Element.__richcmp__ return coercion_model.richcmp(self, other, op) File "sage/structure/coerce.pyx", line 2023, in sage.structure.coerce.CoercionModel.richcmp x, y = self.canonical_coercion(x, y) File "sage/structure/coerce.pyx", line 1350, in sage.structure.coerce.CoercionModel.canonical_coercion y_elt = (<Map>y_map)._call_(y) File "sage/categories/map.pyx", line 1734, in sage.categories.map.FormalCompositeMap._call_ x = f._call_(x) File "sage/categories/morphism.pyx", line 593, in sage.categories.morphism.SetMorphism._call_ cpdef Element _call_(self, x): File "sage/categories/morphism.pyx", line 612, in sage.categories.morphism.SetMorphism._call_ return self._function(x) File "/sage/src/sage/categories/unital_algebras.py", line 72, in from_base_ring return self.one()._lmul_(r) File "sage/misc/cachefunc.pyx", line 2318, in sage.misc.cachefunc.CachedMethodCallerNoArgs.__call__ self.cache = f(self._instance) File "/sage/src/sage/categories/magmas.py", line 497, in one return self(1) File "sage/structure/parent.pyx", line 901, in sage.structure.parent.Parent.__call__ return mor._call_(x) File "sage/categories/map.pyx", line 1734, in sage.categories.map.FormalCompositeMap._call_ x = f._call_(x) File "sage/categories/morphism.pyx", line 593, in sage.categories.morphism.SetMorphism._call_ cpdef Element _call_(self, x): File "sage/categories/morphism.pyx", line 612, in sage.categories.morphism.SetMorphism._call_ return self._function(x) File "/sage/src/sage/categories/unital_algebras.py", line 72, in from_base_ring return self.one()._lmul_(r) File "sage/misc/cachefunc.pyx", line 2318, in sage.misc.cachefunc.CachedMethodCallerNoArgs.__call__ self.cache = f(self._instance) File "/sage/src/sage/categories/magmas.py", line 497, in one return self(1) File "sage/structure/parent.pyx", line 901, in sage.structure.parent.Parent.__call__ return mor._call_(x) File "sage/categories/map.pyx", line 1734, in sage.categories.map.FormalCompositeMap._call_ x = f._call_(x) File "sage/categories/morphism.pyx", line 593, in sage.categories.morphism.SetMorphism._call_ cpdef Element _call_(self, x): File "sage/categories/morphism.pyx", line 612, in sage.categories.morphism.SetMorphism._call_ return self._function(x) File
"""
from itertools import combinations
from sage.homology.chain_complex import ChainComplex
from sage.matrix.constructor import matrix

self._matroid = M
E = tuple(M.groundset())
ordering = {e: i for i, e in enumerate(E)} # used in case E has incomparable elements
n = E[-1]
bases = M.bases()

# get the squarefree basis elements
# we can skip the full groundset (which necessarily has full rank)
sf_basis = [X for k in range(len(E)) for X in combinations(E, k)
if not any(B.issubset(frozenset(X)) for B in bases)]
lin_basis = []
comp_max = []
for i, X in enumerate(sf_basis):
# we use the fact that the order of X is the same as in E
X = frozenset(X)
comp = [v for v in E if v not in X]
comp_max.append(comp.pop())
lin_basis.append(tuple(comp))

# construct the Kozsul complex
diffs = {}
cur_basis = {(X, ()): i for i,X in enumerate(sf_basis)}
for k in range(1, len(E)):
print(cur_basis)
prev_basis = cur_basis
cur_basis = {}
rows = []
for X, L, comp in zip(sf_basis, lin_basis, comp_max):
for Y in combinations(L, k):
cur_basis[X,Y] = len(cur_basis)
row = [0] * len(prev_basis)

for j in range(k):
# compute multipliciation by x_i from (x_i - x_{\ell_+})
assert Y[j] not in X
Yp = Y[:j] + Y[j+1:]
Xp = tuple(sorted(X + (Y[j],), key=ordering.__getitem__))
try:
row[prev_basis[Xp,Yp]] += (-1) ** j
except KeyError:
# Xp goes to 0, nothing more to do for this term
pass

# Compute the multiplication by all x_{\ell_+} from the entire
# wedge product. We need to do this separately since
# we need to combine the factors in different ways.
# If new_comp in Y, then this will be (-1)^deg (Y \ new_comp)
# Otherwise we use the following fact:
# d[(a1 - an) ^ (a2 - an) ^ ... ^ (ak - an)] = d[a1 ^ a2 ^ ... ^ ak]
# For example:
# sage: E.<a,b,c,d,e> = ExteriorAlgebra(QQ)
# sage: (b+e)*(c+e) - (a+e)*(c+e) + (a+e)*(b+e)
# a*b - a*c + b*c
# sage: (b+e)*(c+e)*(d+e) - (a+e)*(c+e)*(d+e) + (a+e)*(b+e)*(d+e) - (a+e)*(b+e)*(c+e)
# -a*b*c + a*b*d - a*c*d + b*c*d
# sage: e - (a+e)
# -a
# sage: (b+e)*e - (a+e)*e + (a+e)*(b+e)
# a*b
# sage: (b+e)*(c+e)*e - (a+e)*(c+e)*e + (a+e)*(b+e)*e - (a+e)*(b+e)*(c+e)
# -a*b*c

Xp = tuple(sorted(X + (comp,), key=ordering.__getitem__))
try:
ind = sf_basis.index(Xp)
except ValueError:
# Xp goes to 0, nothing more to do
rows.append(row)
continue
new_comp = comp_max[ind]
assert ordering[new_comp] < ordering[comp], (new_comp, comp, X, Y)
if new_comp in Y:
assert Y[-1] == new_comp
Yp = Y[:-1]
row[prev_basis[Xp,Yp]] -= (-1) ** len(Yp)
else:
for j in range(k):
Yp = Y[:j] + Y[j+1:]
row[prev_basis[Xp,Yp]] -= (-1) ** j

rows.append(row)
diffs[k] = matrix(R, rows).transpose()
self._kozsul_complex = ChainComplex(diffs, degree_of_differential=-1)
self._cohomology = self._kozsul_complex.homology()

# finish the initialization
C = GradedAlgebrasWithBasis(R)
indices = [(deg, i) for deg, V in self._cohomology.items() for i in range(V.dimension())]

CombinatorialFreeModule.__init__(self, R, indices, category=C)

def _repr_(self):
r"""
EXAMPLES::

sage: M1 = matroids.catalog.Fano()
sage: ch = M1.chow_ring(QQ, False)
sage: ch
Chow ring of Fano: Binary matroid of rank 3 on 7 elements, type (3, 0)
over Rational Field
"""
return "Tor algebra of {} over {}".format(self._matroid, self.base_ring())

def _latex_(self):
r"""
Return the LaTeX output of the polynomial ring and Chow ring ideal.

EXAMPLES::

sage: M1 = matroids.Uniform(2,5)
sage: ch = M1.chow_ring(QQ, False)
sage: ch._latex_()
'A(\\begin{array}{l}\n\\text{\\texttt{U(2,{ }5):{ }Matroid{ }of{ }rank{ }2{ }on{ }5{ }elements{ }with{ }circuit{-}closures}}\\\\\n\\text{\\texttt{{\\char`\\{}2:{ }{\\char`\\{}{\\char`\\{}0,{ }1,{ }2,{ }3,{ }4{\\char`\\}}{\\char`\\}}{\\char`\\}}}}\n\\end{array})_{\\Bold{Q}}'
"""
from sage.misc.latex import latex
return r"\mathrm{{Tor}}({})_{{{}}}".format(latex(self._matroid), latex(self.base_ring()))

def kozsul_complex(self):
"""
Return the Kozsul complex of ``self``.
"""
return self._kozsul_complex

def matroid(self):
r"""
Return the matroid of ``self``.

EXAMPLES::

sage: ch = matroids.Uniform(3,6).chow_ring(QQ, True, 'fy')
sage: ch.matroid()
U(3, 6): Matroid of rank 3 on 6 elements with circuit-closures
{3: {{0, 1, 2, 3, 4, 5}}}
"""
return self._matroid

def degree_on_basis(self, m):
return m[0]

42 changes: 32 additions & 10 deletions src/sage/topology/simplicial_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -3526,18 +3526,44 @@
EXAMPLES::

sage: X = SimplicialComplex([[1,2], [0], [3]])
sage: X._stanley_reisner_base_ring()
sage: X._stanley_reisner_base_ring()[0]
Multivariate Polynomial Ring in x0, x1, x2, x3 over Integer Ring
sage: Y = SimplicialComplex([['a', 'b', 'c']])
sage: Y._stanley_reisner_base_ring(base_ring=QQ)
sage: Y._stanley_reisner_base_ring(base_ring=QQ)[0]
Multivariate Polynomial Ring in a, b, c over Rational Field
sage: Fano = matroids.catalog.Fano()
sage: Z = Fano.lattice_of_flats().order_complex()
sage: Z._stanley_reisner_base_ring(base_ring=QQ)[0]
Multivariate Polynomial Ring in x0, x1, x2, x3, x4, x5, x6, x7, x8,
x9, x10, x11, x12, x13, x14, x15 over Rational Field
sage: Z._stanley_reisner_base_ring(base_ring=QQ)[1]

Check failure on line 3539 in src/sage/topology/simplicial_complex.py

View workflow job for this annotation

GitHub Actions / test-new

Failed example:

Failed example:: Got: {frozenset(): 0, frozenset({'a'}): 1, frozenset({'b', 'c', 'd'}): 2, frozenset({'a', 'b', 'f'}): 3, frozenset({'a', 'c', 'e'}): 4, frozenset({'d', 'e', 'f'}): 5, frozenset({'c'}): 6, frozenset({'b'}): 7, frozenset({'g'}): 8, frozenset({'b', 'e', 'g'}): 9, frozenset({'d'}): 10, frozenset({'a', 'd', 'g'}): 11, frozenset({'f'}): 12, frozenset({'c', 'f', 'g'}): 13, frozenset({'e'}): 14, frozenset({'a', 'b', 'c', 'd', 'e', 'f', 'g'}): 15}
{frozenset(): 0,
frozenset({'d', 'e', 'f'}): 1,
frozenset({'a', 'c', 'e'}): 2,
frozenset({'b'}): 3,
frozenset({'c'}): 4,
frozenset({'g'}): 5,
frozenset({'a', 'b', 'f'}): 6,
frozenset({'b', 'c', 'd'}): 7,
frozenset({'f'}): 8,
frozenset({'a', 'd', 'g'}): 9,
frozenset({'c', 'f', 'g'}): 10,
frozenset({'e'}): 11,
frozenset({'b', 'e', 'g'}): 12,
frozenset({'a'}): 13,
frozenset({'d'}): 14,
frozenset({'a', 'b', 'c', 'd', 'e', 'f', 'g'}): 15}
"""
verts = self._gen_dict.values()
try:
verts = sorted(verts)
except TypeError:
verts = sorted(verts, key=str)
return PolynomialRing(base_ring, verts)
mapping = {v: i for i, v in enumerate(verts)}
try:
return PolynomialRing(base_ring, verts), mapping
except ValueError: # non alphanumeric variable names
return PolynomialRing(base_ring, 'x', len(verts)), mapping

def stanley_reisner_ring(self, base_ring=ZZ):
"""
Expand Down Expand Up @@ -3583,13 +3609,9 @@
sage: Y.stanley_reisner_ring(base_ring=QQ)
Multivariate Polynomial Ring in x0, x1, x2, x3, x4 over Rational Field
"""
R = self._stanley_reisner_base_ring(base_ring)
products = []
for f in self.minimal_nonfaces():
prod = 1
for v in f:
prod *= R(self._gen_dict[v])
products.append(prod)
R, mapping = self._stanley_reisner_base_ring(base_ring)
products = [R.prod(R.gen(mapping[self._gen_dict[v]]) for v in f)
for f in self.minimal_nonfaces()]
return R.quotient(products)

def alexander_dual(self, is_mutable=True):
Expand Down
Loading