Double complexes – the user's interface

We briefly review the mathematical notion of a double complex. Let $\mathcal A$ be an Abelian category. A double complex $D_{\bullet, \bullet}$ consists of a collection of objects $D_{i, j}$ in $\mathcal A$ with indices $(i, j) \in \mathbb Z^2$ and usually arranged in a matrix-like grid, together with two collections of morphisms $D_{i, j} \to D_{i \pm 1, j}$, the horizontal morphisms, and $D_{i, j} \to D_{i, j \pm 1}$, the vertical morphisms, so that both the rows and the columns of $D_{\bullet, \bullet}$ are complexes in the classical sense and such that all resulting squares of maps commute.

In practice one usually encounters complexes which are bounded in the sense that outside some specified area of indices $(i, j) \in \mathbb Z^2$ the entries $D_{i, j}$ are all zero. Such entries are then usually omitted.

Basic getters and attributes

In OSCAR the generic functionality for double complexes is declared for the abstract type AbsDoubleComplexOfMorphisms. These functions comprise

  getindex(D::AbsDoubleComplexOfMorphisms, i::Int, j::Int) # Get the `(i,j)`-th entry of `D`
horizontal_mapMethod
horizontal_map(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Return the morphism $dc[i, j] → dc[i ± 1, j]$ (the sign depending on the horizontal_direction of dc).

source
vertical_mapMethod
vertical_map(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Return the morphism $dc[i, j] → dc[i, j ± 1]$ (the sign depending on the vertical_direction of dc).

source

In which direction the maps in the rows and columns go can be asked with the following methods:

horizontal_directionMethod
horizontal_direction(dc::AbsDoubleComplexOfMorphisms)

Return a symbol :chain or :cochain depending on whether the morphisms of the rows of dc decrease or increase the (co-)homological index.

source
vertical_directionMethod
vertical_direction(dc::AbsDoubleComplexOfMorphisms)

Return a symbol :chain or :cochain depending on whether the morphisms of the columns of dc decrease or increase the (co-)homological index.

source

Double complexes can be bounded or unbounded. It is important to note that even if such bounds exist and are known, this is a priori not related to whether or not certain entries are computable! I.e. even in the case of a bounded complex dc it might still be valid to call dc[i, j] beyond that bound. In general, one should use the following functions to determine whether or not it is legitimate to ask for a specific entry.

has_indexMethod
has_index(D::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Return true if the (i, j)-th entry of D is already known, false otherwise.

If the result is false, then it might nevertheless still be possible to compute D[i, j]; use can_compute_index for such queries.

source
can_compute_indexMethod
can_compute_index(D::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Returns true if the entry D[i, j] is known or D knows how to compute it.

source
has_horizontal_mapMethod
has_horizontal_map(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Checks whether the double complex dc has the horizontal morphism dc[i, j] → dc[i ± 1, j], the sign depending on the horizontal_direction of dc.

If this returns false this might just mean that the map has not been computed, yet. Use can_compute_horizontal_map to learn whether or not this is possible.

source
can_compute_horizontal_mapMethod
can_compute_horizontal_map(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Returns true if dc can compute the horizontal morphism dc[i, j] → dc[i ± 1, j], the sign depending on the horizontal_direction of dc, and false otherwise.

source
has_vertical_mapMethod
has_vertical_map(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Checks whether the double complex dc has the vertical morphism dc[i, j] → dc[i, j ± 1], the sign depending on the vertical_direction of dc.

If this returns false this might just mean that the map has not been computed, yet. Use can_compute_vertical_map to learn whether or not this is possible.

source
can_compute_vertical_mapMethod
can_compute_vertical_map(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int)

Returns true if dc can compute the vertical morphism dc[i, j] → dc[i, j ± 1], the sign depending on the vertical_direction of dc, and false otherwise.

source

Explicitly known bounds for the non-zero entries of a complex are nevertheless relevant for various generic functionalities. For example, computing a total complex is only possible in practice if one has an a priori estimate where the non-zero entries are located. For such purposes, we provide the following functionality:

has_upper_boundMethod
has_upper_bound(D::AbsDoubleComplexOfMorphisms)

Returns true if a universal upper bound $j ≤ B$ for non-zero D[i, j] is known; false otherwise.

source
has_lower_boundMethod
has_lower_bound(D::AbsDoubleComplexOfMorphisms)

Returns true if a universal upper bound $B ≤ j$ for non-zero D[i, j] is known; false otherwise.

source
has_right_boundMethod
has_right_bound(D::AbsDoubleComplexOfMorphisms)

Returns true if a universal upper bound $i ≤ B$ for non-zero D[i, j] is known; false otherwise.

source
has_left_boundMethod
has_left_bound(D::AbsDoubleComplexOfMorphisms)

Returns true if a universal upper bound $B ≤ i$ for non-zero D[i, j] is known; false otherwise.

source

If they exist, these bounds can be asked for using

right_boundMethod
right_bound(D::AbsDoubleComplexOfMorphisms)

Returns a bound $B$ such that D[i, j] can be assumed to be zero for $i > B$. Whether or not requests for D[i, j] beyond that bound are legitimate can be checked using can_compute_index.

source
left_boundMethod
left_bound(D::AbsDoubleComplexOfMorphisms)

Returns a bound $B$ such that D[i, j] can be assumed to be zero for $i < B$. Whether or not requests for D[i, j] beyond that bound are legitimate can be checked using can_compute_index.

source
upper_boundMethod
upper_bound(D::AbsDoubleComplexOfMorphisms)

Returns a bound $B$ such that D[i, j] can be assumed to be zero for $j > B$. Whether or not requests for D[i, j] beyond that bound are legitimate can be checked using can_compute_index.

source
lower_boundMethod
lower_bound(D::AbsDoubleComplexOfMorphisms)

Returns a bound $B$ such that D[i, j] can be assumed to be zero for $j < B$. Whether or not requests for D[i, j] beyond that bound are legitimate can be checked using can_compute_index.

source

It is also possible to query whether or not a double complex is already complete in the sense that it knows about all of its non-zero entries.

is_completeMethod
is_complete(dc::AbsDoubleComplexOfMorphisms)

Returns true if for all indices (i, j) with has_index(dc, i, j) = true and dc[i, j] non-zero, the vertex (i, j) is lying on an "island" of non-zero entries in the grid of the double complex, which is bounded by either zero entries or entries for indices (i', j') where can_compute_index(dc, i', j') = false. At least one index dc[i, j] must be known for this to return true.

    ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
… → ? → ? → ? → ? → ? → ? → ? → ? → ? → ? → ? → 0 → 0 → ? → - → - → …
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
… → ? → ? → 0 → 0 → 0 → ? → ? → 0 → 0 → 0 → 0 → * → * → 0 → - → - → …
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
… → 0 → 0 → * → * → * → 0 → ? → 0 → ? → 0 → 0 → * → * → * → - → - → …
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
… → 0 → * → * → * → 0 → ? → ? → 0 → 0 → ? → 0 → * → 0 → * → - → - → …
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
… → 0 → * → * → * → 0 → ? → 0 → 0 → 0 → 0 → * → * → 0 → 0 → - → - → …
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
… → ? → 0 → 0 → 0 → ? → ? → ? → ? → ? → ? → 0 → 0 → ? → ? → - → - → …
    ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   
    ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮   ⋮

Example of a pattern of a double complex with is_complete = true. 0 : zero entry - : entry can not be computed (can_compute_index returns false) * : non-zero entry which has been computed ? : entry can be computed, but that has not yet been done

!!! note If the double complex has several of the above "islands", then is_complete might return true even though one or more of the "islands" have not yet been uncovered. Use this carefully if your full double complex might be separated by zero entries!

source

Generic functionality

total_complexMethod
total_complex(D::AbsDoubleComplexOfMorphisms)

Construct the total complex of the double complex D.

Note that D needs to be reasonably bounded for this to work so that the strands $⨁ ᵢ₊ⱼ₌ₖ Dᵢⱼ$ are finite for every k. Moreover, the generic code uses the internal function _direct_sum. See the docstring of that function to learn more.

source

Constructors

tensor_productMethod
tensor_product(C::ComplexOfMorphisms{ChainType}, D::ComplexOfMorphisms{ChainType}) where {ChainType}

Create the tensor product of two complexes C and D as a double complex.

In order for the generic implementation to work for your specific ChainType the following needs to be implemented.

  • morphism_type(ChainType) must produce the type of morphisms between objects of type ChainType;
  • the call signature for function (fac::TensorProductFactory{ChainType})(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int) needs to be overwritten for your specific instance of ChainType to produce the (i, j)-th entry of the double complex, i.e. the tensor product of C[i] and D[j];
  • the call signature for function (fac::HorizontalTensorMapFactory{ChainType})(dc::AbsDoubleComplexOfMorphisms, i::Int, j::Int) needs to be overwritten to produce the map on tensor products C[i] ⊗ D[j] → C[i±1] ⊗ D[j] induced by the (co-)boundary map on C (the sign depending on the typ of C);
  • similarly for the VerticalTensorMapFactory.

See the file experimental/DoubleComplex/src/tensor_products.jl for examples.

source