
Contour showing height of Arts Tower Sheffield


I recently finished an Undergraduate Research program run by the University of Sheffield mathematics department.
My subject was the highly abstract concept of “Mackey functors”. These are a niche but important part of many advanced mathematical concepts, including stable homotopy theory, and representation theory.
Their invention was motivated by trying to create a formal mathematical object which could find morphisms between different properties between a group and it’s subgroups. For instance, we may want to find a map between the order of a group’s subgroups. We may write a sketch to demonstrate what these mappings between subgroups should look like:

How do we formalise this into a concrete mathematical idea?
In order to have any hope in defining such an object, we must explore a bit of category theory. But don’t worry, the initial definition is not actually too hard to understand!
A category is comprised of two types of things, a collection of objects (
), and a collection of “morphisms” between these objects (
).
These are subject to two criteria, or axioms:
Some examples of categories include:
One of the ways to define a Mackey functor is to use a function and then axiomatically enforce the existence of morphisms which go “up” subgroups and morphisms which go “down” subgroups. As the previously presented diagram suggests, we want our object to contain a morphisms to and from each pair of subgroups.
Consider a group . A
-Mackey functor
is a function from the subgroups of
to abelian groups in the
of abelian groups,
.
The category must contain the following morphisms…
for all subgroups of
and all elements
. The morphisms are subject to the following axioms:
Most of these rules are actually quite simple ideas. Most of them mathematicians are very familiar with, such as the idea that conjugation has to play well. For instance, if we reduce from to
, then reduce again from
to
, we would expect that to be the same thing as reducing from
to
(this is what the second axiom is saying).
The axiom that doesn’t make sense is the notorious double coset formula – the last one. The story of why this axiom is included is quite interesting. It was originally included because it was a property that many examples of Mackey functor-like objects were exhibiting. It was then observed later on in a clever reformulation of the Mackey functor where it’s inclusion becomes undeniable.
Let’s consider the constant -Mackey functor.
We must define a mapping from each of the subgroups of to an abelian group. By definition, the constant Mackey functor assigns the same abelian group (we can call it
), to each of the subgroups.

We can then determine the restriction and transfer morphisms.
The restriction morphism is , so in this case, we simply define it as the inclusion map. As the domain of this function is a subset of the codomain, we can define a map which takes every element in the domain to the same element in the codomain. We can denote this as:
The transfer map is a bit more interesting. In the case of the constant Mackey functor, it happens that it is defined as so:
For a transfer we define it as multiplying an element
by the index of
in
(
). This is quite similar to what we were doing in the original example I gave of what a Mackey functor does – it’s revealed the change in size as we move up subgroups.

In this case conjugation is also just the identity morphism. All these groups are normal so conjugation does nothing to them.
You maybe wondering how we decided these functions are the transfer and restriction morphism. It all comes down to the axioms. We define this Mackey functor to take all subgroups to the same abelian group (hence “constant”), and then we look at the axioms. The restriction, transfer and conjugation we choose must satisfy the axioms, and the axiom that imposes the most limitation on what these can be is the double coset formula. By taking the double coset formula, we can cleverly choose subgroups so that the formula simplifies down and reveals some information about the morphism we are looking at. It is via this method that the correct function actually pops out.
This definition of a Mackey functor using a functor is nice enough, but you may have noticed that it’s a Mackey functor, not function. Let’s look at what a functor is
A functor is a mapping between categories. Given two categories and
, a functor creates an association from every object
in
, to a corresponding object
in
, and similarly, for the morphisms
in
, it provides a morphism
in
.
These maps are subject to maintaining proper composition. The functor must map composed morphisms in to the composition of the mapping of the individual morphisms, i.e.:
. This can be represented by the following commutative diagram:

Okay so with functors, we can map from a category to a category. So instead of mapping from the subgroups of to the category of abelian groups, and then axiomatically enforcing the existence of the morphisms we want, it would be nice to find a special category in which we can make a sensible assignment from each morphism in said category to restriction, transfer and conjugation.
That category turns out to be . Using this object, we can create a full definition of a Mackey functor in just a few lines:
A Mackey functor is a functor
Thanks for reading!
We all know the definition of the factorial ! as but there are even more definitions of factorials that mathematicians have invented.
The double factorial looks like this . It can be used to easily denote the product of the odd or even numbers less than or equal to n
The subfactorial has a really intuitive practical application. Imagine you have n tokens in defined positions in an array. You take all the tokens out and want to place every token back into the array so that none of the tokens end up in the position they were just in. This is called derangement.
For instance, ,
You can arrange this set in the following ways: .
Only two of these sets satisfies the above criteria, and
Therefore we say
The Primorial is denoted and is the product of primes less than and equal to n.
Primorials are used in the search for large prime numbers. Each primorial has more distinct prime factors than any number smaller than it.
The more common definition of the Superfactorial. It is defined as such:
For example:
You can look at it another way by expanding the factorials:
And so:
Another definition of the Superfactorial uses tetration.
It grows insanely fast.
Annoyingly also denoted
Finally the hyperfactorial is defined like this:
Or:
And hence is very similar to the Sloane definition of the superfactorial:
Fractal Flow is my largest programming project so far; here’s a little about it:
I started Fractal Flow on January 12th 2022, after a few months of learning and tinkering with the Windows Presentation Foundation in my Computer Science class. The application was to be my coursework, which makes up 20% of the AQA A-level Computer Science grade.
January was not usually the month in which my college starts pupils on the NEA (Non-Examination Assessment), however my teacher had offered that I start early due to my prior knowledge in programming. I snatched the offer, hoping I could turn this opportunity to spend hours of my time programming into something more than just my A-level coursework – I wanted to create a piece of professional software that could persist as a gem in my portfolio for years to come.
Fractal Flow is a fractal generator. Its job is to generate and export images of fractals, geometric shapes which contain a high level of detail when zooming in and often contain entire versions of themselves.
One of the most famous fractals is the Mandelbrot Set, first visualised by Benoit Mandelbrot in 1980. This infinitely detailed object is constructed over the complex plane with the formula , a deceptively simple operation for the immense complexity which is generated.

is but one of an infinite set of formulae that can be chosen to create fractals on the complex plane. These unlimited possibilities is what Fractal Flow is designed to explore. The software is fully focused on creating fractals from any formula the user can come up with – doing so with incredible performance.
From the beginning I was laser focussed on creating a product that was not only intuitive and visually attractive, but also competently engineered behind the scenes. The first step to achieving this was abandoning what was expected of me: using WinForms. I taught myself WPF (Windows Presentation Foundation) and furthermore how to use it with a professional approach. MVVM (Model View View Model) allowed for a proper separation between the user interface and the business logic and thus opened the door to code reusability.

I was not happy with leaving my app with a bog-standard UI. Noticing that all the fractal generators I had tried had very tired visuals, I set about changing the expectation for how such software could look by creating a sleek, modern user interface.

This was my first time using the brilliant website Figma. I had a lot of fun designing the pages and selecting iconography and typefaces.
The crown jewel of the application is the rendering technique I developed for it. Rather than running the computationally intense tasks in C# on the CPU, Fractal Flow hands rendering to the GPU. This allows for an enormous increase in performance (over 1000x faster in my tests).
The GPU is faster than the CPU in this field because it allows the concurrent execution of hundreds of calculations simultaneously. The colour of each pixel in these fractal images are completely independent of the other pixels in the image, so they can be treated as completely different processes to each other. This makes parallelisation really easy as each pixel can be sent as a separate job to the GPU.
To harness the power of the GPU in WPF, I used a library which provided access to OpenCL (Open Computing Language). This allowed me to provided a small piece of C code called a kernel that is to be run on the GPU. I could specify how many of these kernels are sent to the GPU and an array of arguments to be distributed between them.
This is where the clever part comes in. From the iterative formula the user specifies to generate their fractal, a line of C code representing that operation is generated. This is then implanted into the kernel to create a new program, specifically programmed to render the fractal. This approach is called metaprogramming, a technique where code writes itself.
I used this approach for technical limitations (my understanding was that using the complex number libraries in the OpenCL library kernel was unsupported so I resorted to a series of macros for my complex operations), and also because I believed that it would reap even greater computational performance over the CPU.

I created my own mathematical formula parser for this application. This was not a necessary step – reinventing the wheel for such a common process is not good practice. Regardless I made a homemade parser because: 1. It was a valuable learning process and 2. It would give me marks in my NEA 3. It allowed me total control over how the parser worked.
Developing this algorithm taught me about Dijkstra‘s Shunting Yard Algorithm (yes the same Dijkstra who invented the route finding algorithm), which converted an expression in infix notation to the Reverse Polish Notation required for execution by computers.
I also made sure my algorithm allowed for relatively natural expression. For instance it accepted notation such as ““, the terse form of “
“. I realised I could summarise token adjacency behaviour in a table:

I left Fractal Flow in a state I was relatively happy with, however there were still many features I envisioned for the application that have not made it to the application yet. For instance I initially wanted the application to be able to produce zooming videos, and have a multitude of different colouring algorithms as found in other fractal generators.
It was investigating colouring algorithms where I found a large problem with the code of Fractal Flow – an issue so large that it led to a downfall in motivation to develop the project. The problem was that many colouring algorithms require information *other* than simply the number of iterations each pixels took before it triggered the bail, such as the distance the iteration that triggered the bail “jumped” from the prior position. Implementing the inclusion of this information would require a large redesign of the render pipeline and considerable thought over how to architect a memory-efficient system.
I learnt an important lesson in discovering this flaw: to always research thoroughly absolutely everything my system might be implementing on top of what I already know it must.
There are also a few areas of the program that are unnecessary or artificially shoe-horned into the designed, with the purpose of hitting more targets on the NEA mark scheme. For example the formula parser discussed earlier, and the use of an SQL database to store fractal definition objects (I think simply storing them in files would be more reasonable).
Fractal Flow is currently over 10000 lines with over 20 classes.

WIP – This is my A-level (Junior/Senior year equivalent) Computer Science coursework as submitted. REMEBER TO MAKE BRANCH IF WORKING ON FURTHER
Fractal Flow is a next generation application for rendering fractal images over the complex plane, with a focus on generating custom user-defined fractals.
<p align=“center”> <img src=“https://github.com/ProgramPhantom/FractalFlow/assets/49105496/bea77f82-704e-496d-a2e5-73ba33bd892d” /> </p>
Fractal Flow aims to streamline and accelerate the process of exploring new fractal objects – beyond the Mandelbrot set. Fractal Flow combines a blazing fast rendering kernel with a UI whioh empowers rapid iteration and generation of ideas.
Started 12th Jan 2022