Categories

# Abstract Python

The use of computers in mathematics for long and complex calculations has allowed us to use mathematical tools to model the real world in detail that would have been unimaginable in past decades. In recent years, computational mathematical tools have been used for a huge variety of tasks, from detecting gravitational waves to contactless payment. All of these tasks are computational problems, usually involving very long or complex calculations, but the link between mathematics and computer science is much deeper than as a tool for solving computational problems.

Mathematics and computers share the same basic language, the language of logic, but they also share a philosophy. In object orientated programming, objects are created according to a template called a class. A class outlines the properties and operations that can be performed on the corresponding objects, and can inherit properties from parent classes. This allows the programmer to ensure objects that are similar in some way to share a common collection of properties and operations. This process of abstraction is very powerful and flexible, and is precisely the same as the process of abstraction that has been employed by mathematicians.

There are, of course, differences in mathematical abstraction and the creation of classes in object orientated programming. There are many reasons to create an object in a computer program but, in my experience, most fall into two broad categories: objects created as convenient “containers” for information; and objects created to “interface” with another resource or program. In mathematics, we seek to understand the “big picture” that abstraction offers, and often an extra level of abstraction can help to solve problems that would otherwise be difficult.

Recently I have explored how we might use the similarities between mathematical construction and object orientated programming to better understand some of the basic objects in mathematics, specifically permutations and functions on finite sets. Of course, there are software packages that can perform symbolic algebra but I hope to describe how one might implement a simple permutation class in Python as an instructional device.

A permutation is a bijective function from a set to itself; more simply, it is a rearrangement of the elements in a set. The most basic operation one can perform with a permutation is to evaluate it at an element of the set. For this purpose, we must store information about how elements are “moved” by the permutation. Python provides us with a convenient container object to store such information called a dictionary. A simple implementation of a permutation in Python might be as follows.

```class Permutation:
"A simple permutation class"

def __init__(self, spec):
self.spec = spec

def evaluate(self, element):
return self.spec[element]```

The keyword class tells Python that we are creating a new object class, which in this case is called Permutation. The two lines starting with def are declarations of methods for the Permutation class. The first tells Python how to assign the specification (stored in self.spec) for the permutation to the object, and the second tells Python how to evaluate the permutation at a given element. (We are making some assumptions that spec is a dictionary and that element is a valid key for spec.) We can create permutation objects using this class as follows.

```spec = {1 : 2, 2 : 3, 3 : 1}
p = Permutation(spec)
p.evaluate(1) # returns 2
p.evaluate(2) # returns 3```

Note that we do not need to provide the self variable to the __init__ function, this is done automatically by Python when creating an object. The dot is used in Python – and many other object orientated languages – to access the properties and methods of an object.

At the moment, we haven’t checked that the function we have implemented here is actually a permutation. For this, we must check that it is a function from a set to itself, so that the only values that can be returned from the evaluate method belong to the same set as those elements that can be used as inputs, and that every input corresponds to a unique output. This can be achieved by checking whether the set of keys of the dictionary spec (the valid inputs) is the same as the set of values of the dictionary (the possible outputs). Using the Python set built-in type, we will remove repeated elements and so checking for equality will check both conditions. At the same time, we can add some checks to make sure the inputs are valid for our methods. Let us modify the implementation above.

```class Permutation:
"A simple permutation class"

def __init__(self, spec):
if not isinstance(spec, dict):
raise TypeError('spec must be of type dict')
if not set(spec.keys()) == set(spec.values()):
raise ValueError('Set of keys and values differ')
self.spec = spec

def evaluate(self, element):
try:
return self.spec[element]
except KeyError:
raise ValueError('Invalid input')```

Here we are using the raise keyword to produce an error when spec does not satisfy the conditions of being a dictionary (dict) or does not define a valid permutation. The TypeError and ValueError objects are standard error types in Python. In the evaluate method, we try to return the output of the permutation, from the specification, when element is input. In the case where element is not a valid input, it will not be a key of the dictionary spec, and Python will raise a KeyError. We catch that error with the except statement, and raise our own error.

The class definition above covers creation and evaluation of a permutation object in Python, but of course permutations have many additional properties. These properties can be added as object properties or object methods, but I will let you try this for yourself.