This is an introduction to the implementation of two-complexes, including issues with scala, ending with constructing a torus. To start with we load the compiled code.

In [1]:

```
import $cp.bin.`superficial-c3516ca6f4.jar`
import superficial._
```

Out[1]:

The code for vertices is rather simple.

```
class Vertex
```

Let us first create a vertex. As it has no abstract methods, we can just ask for a new one.

In [2]:

```
val v0 = new Vertex
```

Out[2]:

Alternatively, we can declare a new object.

In [3]:

```
object v1 extends Vertex
```

Out[3]:

In [5]:

```
3: Int
```

Out[5]:

In [4]:

```
v1 : v1.type
```

Out[4]:

Edges come in pairs, an edge and the same with the opposite orientation (i.e., flipped). Further, each edge has an initial and terminal vertex. We can also describe the boundary as a formal sum. This is *trait*, i.e., an *abstract class*. This means some of its fields are undefined, and have to be defined in a subclass/object with this trait.

```
trait Edge {
/**
* the same edge with the opposite orientation.
*/
def flip: Edge
def terminal: Vertex
def initial: Vertex
def del : FormalSum[Vertex] = FormalSum.reduced(Vector(terminal -> 1, initial -> -1))
}
```

We construct a *loop* at `v0`

, i.e., an edge beginning and ending at `v0`

. But note that we cannot construct just one, as we need to flip it. Instead we will construct a pair of edges, each a flip of the other.

In [6]:

```
object E1 extends Edge{
lazy val flip = E2
val terminal = v0
val initial = v0
}
object E2 extends Edge{
lazy val flip = E1
val terminal = v0
val initial = v0
}
```

Out[6]:

Note a key feature above - we have defined the flip of each of the edges as `lazy val`

. This means this is not computed until it is needed. Otherwise defining each of `E1`

and `E2`

leads to an infinite loop.

We can see some computations on demand.

In [7]:

```
E1.flip
```

Out[7]:

In [8]:

```
E1.flip == E2
```

Out[8]:

In [9]:

```
E1.flip.flip == E1
```

Out[9]:

In [10]:

```
E1 == E2
```

Out[10]:

We now turn to constructing a torus. Recall that this has a single vertex, two edges that become loops and a single face. We will follow the same pattern as above but give things nicer names. We will also make objects `case object`

definitions. This means the names are cleaner (as is equality).

In [11]:

```
case object V extends Vertex
```

Out[11]:

In [12]:

```
case object VV extends Vertex
```

Out[12]:

In [13]:

```
V == VV
```

Out[13]:

In [14]:

```
case class VC() extends Vertex
case class VVC() extends Vertex
```

Out[14]:

In [15]:

```
VC() == VVC()
```

Out[15]:

In [16]:

```
VC() == VC()
```

Out[16]:

In [17]:

```
case object A extends Edge{
lazy val flip = Abar
val terminal = V
val initial = V
}
case object Abar extends Edge{
lazy val flip = A
val terminal = V
val initial = V
}
```

Out[17]:

In [18]:

```
case object B extends Edge{
lazy val flip = Bbar
val terminal = V
val initial = V
}
case object Bbar extends Edge{
lazy val flip = B
val terminal = V
val initial = V
}
```

Out[18]:

In [19]:

```
A.flip
```

Out[19]:

In [20]:

```
Abar.flip
```

Out[20]:

Now we construct the face of the torus. Here is an extract from the code for defining a polygon. We have omitted *concrete* methods, i.e., methods in the trait that are defined, so need not be implemented in subclasses/objects.

```
trait Polygon extends TwoComplex {
val sides: Int
val boundary: Vector[Edge]
val vertices: Set[Vertex]
}
```

Note that this is a two-complex, so we are constructing a torus.

In [21]:

```
case object Torus extends Polygon{
val sides = 4
val boundary = Vector(A, B, Abar, Bbar)
val vertices = Set(V)
}
```

Out[21]:

In [22]:

```
Torus.faces
```

Out[22]:

In [23]:

```
Torus.edges
```

Out[23]:

In [25]:

```
Torus.boundary
```

Out[25]:

Note that there are subclasses that let us construct more directly, but for now (i.e. as of Jan 13, 2020) they are not sufficient. We took a more direct approach to illustrate the structures.