# Quickstart Guide¶

Once you have successfully installed `bats`

, you can follow this guide to help you get started. You can download this guide as a Jupyter notebook here.

You can find additional information and examples in the tutorials and examples, and ultimately the API reference.

First, import `bats`

:

```
[1]:
```

```
import bats
```

## Simplicial Complexes and Homology¶

BATS offers two implementations of simplicial complexes: `SimplicialComplex`

and `LightSimplicialComplex`

. While the internal representations differ, they both have the same interface which can be used.

Simplices in bats should generally be assumed to be *ordered*, meaning that `[0,1,2]`

is not the same as `[1,2,0]`

. If you want to use *unordered* simplices, you can either add vertices in sorted order, or use a sorting algorithm before adding simplices to complexes.

The `add`

method will add simplices, assuming that all faces have previously been added. The `add_recursive`

method will recursively add faces as needed.

```
[7]:
```

```
X = bats.SimplicialComplex()
X.add_recursive([0,1,2])
X.add_recursive([2,3])
X.add([1,3])
X.get_simplices()
```

```
[7]:
```

```
[[0], [1], [2], [3], [0, 1], [0, 2], [1, 2], [2, 3], [1, 3], [0, 1, 2]]
```

Now let’s compute homology

```
[15]:
```

```
R = bats.reduce(X, bats.F2()) # F2 is coefficient field
for k in range(R.maxdim()):
print("dim H_{}: {}".format(k, R.hdim(k)))
```

```
dim H_0: 1
dim H_1: 1
```

The output of `bats.reduce`

is a `ReducedChainComplex`

which holds information used to compute homology.

For `LightSimplicialComplex`

, you need to provide an upper bound on the number of vertices and maximum simplex dimension.

```
[13]:
```

```
n = 4 # number of vertices
d = 2 # max simplex dimension
X = bats.LightSimplicialComplex(n, d)
X.add_recursive([0,1,2])
X.add_recursive([2,3])
X.add([1,3])
X.get_simplices()
```

```
[13]:
```

```
[[0], [1], [2], [3], [0, 1], [0, 2], [1, 2], [2, 3], [1, 3], [0, 1, 2]]
```

```
[14]:
```

```
R = bats.reduce(X, bats.F2())
for k in range(R.maxdim()):
print("dim H_{}: {}".format(k, R.hdim(k)))
```

```
dim H_0: 1
dim H_1: 1
```

## Persistent Homology¶

You can add simplices to a filtration by providing a parameter at which they first appear.

```
[17]:
```

```
F = bats.FilteredSimplicialComplex()
F.add_recursive(0.0, [0,1,2])
F.add_recursive(1.0, [2, 3])
F.add(2.0, [1,3])
F.complex().get_simplices()
```

```
[17]:
```

```
[[0], [1], [2], [3], [0, 1], [0, 2], [1, 2], [2, 3], [1, 3], [0, 1, 2]]
```

again, we can use the `reduce`

function, but now we get a `ReducedFilteredChainComplex`

```
[20]:
```

```
R = bats.reduce(F, bats.F2())
for k in range(R.maxdim()):
for p in R.persistence_pairs(k):
print(p)
```

```
0 : (0,inf) <0,-1>
0 : (0,0) <1,0>
0 : (0,0) <2,1>
0 : (1,1) <3,3>
1 : (0,0) <2,0>
1 : (2,inf) <4,-1>
```

The output of `R.persistence_pairs(k)`

is a vector of `PersistencePairs`

for k-dimensional persistent homology.

A `PersistencePair`

includes 5 pieces of information: * The dimension of the homology class. * The birth and death parameters of the homology class. * The simplex indices responsible for birth and death.

```
[28]:
```

```
p = R.persistence_pairs(1)[-1]
print(p)
print(p.dim(), p.birth(), p.death(), p.birth_ind(), p.death_ind(), sep=', ')
```

```
1 : (2,inf) <4,-1>
1, 2.0, inf, 4, 18446744073709551615
```

infinite bars have a death index set to `2**64 - 1`

## Maps¶

BATS makes dealing with maps between topological spaces and associated chain maps and induced maps on homology easy. The relevant class is a `CellularMap`

which keeps track of what cells in one complex map to what cells in another.

We’ll just look at a wrapper for `CellularMap`

, called `SimplcialMap`

which can be used to extend a map on the vertex set of a `SimplicialComplex`

to a map of simplices.

First, we’ll build identical simplicial complexes `X`

and `Y`

which are both cycle graphs on four vertices.

```
[30]:
```

```
X = bats.SimplicialComplex()
X.add_recursive([0,1])
X.add_recursive([1,2])
X.add_recursive([2,3])
X.add_recursive([0,3])
Y = X
```

We then build a simplicial map from X to Y which is extended from a reflection of the vertices.

```
[31]:
```

```
f0 = [2, 1, 0, 3]
F = bats.SimplicialMap(X, Y, f0)
```

The map is extended by sending vertex `i`

in `X`

to vertex `f0[i]`

in `Y`

. Next, we can apply the chain functor. We’ll use F3 coefficients.

```
[32]:
```

```
CX = bats.Chain(X, bats.F3())
CY = bats.Chain(Y, bats.F3())
CF = bats.Chain(F, bats.F3())
```

Finally, we can compute homology of the chain complexes and the induced maps.

```
[41]:
```

```
RX = bats.reduce(CX)
RY = bats.reduce(CY)
for k in range(RX.maxdim()+1):
HFk = bats.InducedMap(CF, RX, RY, k)
print("induced map in dimension {}:".format(k))
print(HFk.tolist())
```

```
induced map in dimension 0:
[[1]]
induced map in dimension 1:
[[2]]
```

The induced map in dimension 0 is the identity. The induced map in dimension 1 is multiplication by `2 = -1 mod 3`

## Zigzag Homology¶

We’ll now compute a simple zigzag barcode, using the above example. We’ll consider a diagram with two (identical) spaces, connected by a single edge which applies the reflection map in the above example.

```
[43]:
```

```
D = bats.SimplicialComplexDiagram(2,1) # diagram with 2 nodes, 1 edge
D.set_node(0, X)
D.set_node(1, Y)
D.set_edge(0, 0, 1, F) # edge 0: F maps from node 0 to node 1
```

We can now apply the `Chain`

and `Hom`

functors to obtain a diagram of homology vector spaces and maps between them

```
[47]:
```

```
CD = bats.ChainFunctor(D, bats.F3())
```

```
[51]:
```

```
HD = bats.Hom(CD, 1) # computes homology in dimension 1
ps = bats.barcode(HD, 1) # extracts barcode
for p in ps:
print(p)
```

```
1 : (0,1) <0,0>
```

This indicates there is a 1-dimensional homology bar, which is born in the space with index 0 and survives until the space with index 1. The `<0,0>`

indicates which generators are associated with the homology class in the diagram.