Mackey  V3.1
A C++ library for computing RO(G) graded homology
Tutorial

The code examples here can be compiled from the .cpp file in the demo folder.

Includes

Many parts of the library are standalone (apart from the Eigen dependency) so they can be individually included. To keep things simple, we provide a single header file Mackey.hpp that includes the entire library (and Eigen)

Attention
If you are using MSVC, including Eigen will give compilation errors unless you define the following macro:
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
Make sure to define the macro before including the header Mackey.hpp
Note
To enable multithreading via openMP define the macro MACKEY_USE_OPENMP and enable openMP in your compiler (on Clang and GCC this is done by the flag -fopenmp)

With that in mind, we start with:

  #include "Mackey.hpp"

Namespaces

Everything in this library is under the namespace mackey. For the following code examples we use:

  using namespace mackey;

Template parameters

The three template parameters that need to be set are the ambient group \(G\), the coefficient ring \(R\) and the \(G\)-space \(X\).

From the get-go the library provides support for:

  • groups \(G=C_{2^n}\) via the class C2power
  • fields \(\mathbf Z/p\) via the class Z
  • the point via the class Point.
  • the space \(B_{C_4}\Sigma_2\) via the class BC4S2
Note
The ring \(\mathbf Z\) corresponds to the usual signed integer types eg int64_t so there's no need to define a wrapper around it.

For performance+memory reasons (see Dense vs sparse), we also need to consider the type of rank arrays and differential matrices that we want to use.

  • A rank array is a dense Eigen row matrix of signed integer scalar type.
    It is used to store the ranks of the chain complexes (see Equivariant chain complexes)
  • A differential matrix is a dense or sparse column major Eigen matrix whose scalar type corresponds to \(R\).
    It is used to store the differentials of the chain complexes

We define \(G,R,X\) and the rank/differential types all at once. For example:

  Point<C2power<5,Eigen::Matrix<short,1,-1>,Eigen::Matrix<Z<3>,-1,-1>>>

is the type corresponding to group \(C_{2^5}\), coefficients \(\mathbf Z/3\) and using dense matrices for the differentials. The rank arrays have scalar type short.

Another example:

  C2power<1, Eigen::Matrix<char,1,-1>,Eigen::SparseMatrix<int64_t>>

corresponds to group \(C_2\), coefficients in \(\mathbf Z\) with 64bit accuracy and sparse matrices for the differentials. The rank arrays have scalar type char.

For the following examples we shall use the configuration:

  typedef C2power<2, Eigen::Matrix<char,1,-1>,Eigen::SparseMatrix<char,0,size_t>> group_t;

which means \(\mathbf Z\) coefficients and group \(C_4\).

Step 2: Computing with the library

The additive structure

The class AdditiveStructure computes the homology of all spheres in a given range as Mackey functors.

Example:

  AdditiveStructure<group_t> A({-3,-4},{5,6});

computes the homology of all spheres \(S^{n\sigma+m\lambda}\) with \(-3\le n\le 5, -4\le m\le 6\).

Note
For \(C_4\) the sphere \(S^{n\sigma+m\lambda}\) is represented by a vector {n,m} . More generally for \(C_{2^n}\) the sphere \(S^{t_1\sigma+\sum_it_i\lambda_i}\) is represented by {t_1,...,t_n}. This is specified in C2n.hpp.

To identify the Mackey functors in the "universal" notation ("Universal" Mackey functor notation) use:

  A.identify();     
  std::cout << A << "\n";

The answer is of the form

  The 2 homology of the 4,6 sphere is 002   

which means

\[H_2(S^{4\sigma+6\lambda})= 002\]

in our "universal notation".

If the program did not manage to write the Mackey functor in that notation then the printed name will look like "unknown 0,...".

You can survey the identified and unknown Mackeys by

  std::cout << A.identified()<< "\n";
  std::cout << A.unknown()<< "\n";

Factorization

The class Factorization computes the multiplication graph ("Universal" Mackey functor notation) given the "basic irreducibles".

In this case let us use \(a_{\sigma},u_{2\sigma},a_{\lambda},u_{\lambda}\) as our irreducibles:

  std::vector<std::vector<int>> basic_irr= { {0,1,0},{2,2,0},{0,0,1},{2,0,1} };
  std::vector<std::string> basic_irr_names= { "asigma", "u2sigma", "alambda", "ulambda" };
Note
For any group \(G\), the degree of an element in \(H_kS^V\) is represented by a vector {k,t1,...,tn} where {t1,...,tn} represents \(S^V\).

To compute the multiplication graph in the range \(S^{n\sigma+m\lambda}\), $-5\le n,m\le 5$, use:

  auto F= Factorization<group_t>(2,{ -5,-5 }, { 5,5 },basic_irr, basic_irr_names);

The 2 here signifies that we work on the top level of \(C_4\).

Note
For a group \(G=C_{p^n}\) the level corresponding to \(C_{p^n}/C_{p^i}\) corresponds to the integer \(i\).

Then

  F.compute_with_sources({{0,0,0}}, {"1"});

computes the factorizations by connecting every node in the multiplication graph to \(1\) (if possible). To print the generator at degree \([3,1,0]\) use:

  std::cout<< F.getname({3,1,0});

To print the names of all generators use:

  std::cout<< F;

To print the multiplication graph in the dot format use

  std::cout << F.graph;

If a generator name is ??? then means that the generator could not be obtained by multiplying/dividing the basic irreducibles with 1. This means that additional sources may be needed. To include the generator of \(H_{-3}S^{-2\lambda}\) as our source we use:

  F.compute_with_sources({{0,0,0},{-3,0,-2}}, {"1","s"});

where now both \(1\) and \(s\) are used as sources.

It possible that there are enough sources yet we still get \(?\); that means the basic identification was not enough to compute all products. You can then use

  F.pass_disconnected();

to try redoing the identification now using triple box products. This will be very computationally expensive.

Finally, if only the connectivity of the Multiplication Graph is desired, as opposed to precise factorizations of the generators, you can instead use the MultGraphConnectivity class instead of Factorization:

  auto M= MultGraphConnectivity<group_t>({ -5,-5 }, { 5,5 }, basic_irr);
  M.compute_with_sources({[0,0,0]});

To survey the degrees of elements that may not be connected to any sources use

  std::cout << M.graph.disconnected();

Multiplying generators

The classes Factorization and MultGraphConnectivity work by multiplying all generators of \(H_\star\) in a given range.

To multiply two specific generators together we use the function ROGreen. Example:

  auto linear_combination= ROGreen<group_t>(2,{0,2,-2},{1,3,-4});

performs the operation

\[ H_0^{C_4}(S^{2\sigma-2\lambda}) \otimes H_1^{C_4}(S^{3\sigma-4\lambda}) \to H_1^{C_4}(S^{5\sigma-6\lambda}) \\ a\otimes b\mapsto ab\]

where \(a,b\) are generators of the respective homology groups. Here:

  • The first argument of ROGreen indicates the level the generators live in.
  • The second and third arguments are the degrees of the two generators \(a,b\).
  • The result of the computation linear_combination is a row vector \([t_0,...,t_k]\) of integer entries representing that:

    \[ab=\sum_it_ig_i\]

    where \(g_i\) are the generators of the homology group the product lives in, which in our case is \( H_1^{C_4}(S^{5\sigma-6\lambda})\).
Note
If the homology in the degrees of \(a\) or \(b\) is not cyclic, then we select \(a,b\) by providing two int arguments in RO::Green. For example, providing \(1,2\) selects the second and third generators \(a,b\) of the noncyclic groups respectively.
For convenience we normalize the basis to omit any signs and identify generators of the same cyclic groups (see A caveat) but it's also possible to get the unnormalized version (see the documentation of Green).

Massey products

The method ROMassey computes (triple) Massey products in the Green functor \(H_{\star}\). Example:

  auto Mass= mackey::ROMassey<group_t>(2,{0,1,0},{-3,-3,0},{2,2,0});

computes the Massey product \(\langle a_{\sigma},w_3,u_{2\sigma}\rangle \) and its indeterminacy.

As with the multiplicative structure, the Massey product is expressed in terms of a linear combination of the basis in the homology of the box product, while the indeterminacy is expressed via two groups which we can survey by

  std::cout << Mass.indeterminacy();

We can also provide three optional int arguments at the end for selections, analogous to what we did in Multiplying generators (see Massey for more details).