# Surreal Numbers in Python 2

## Recap

In the last post, we started creating the Surreal Numbers with a Functional approach, going along with the Grimm Whitepaper. However, even with only 3 Numbers created, we have lots of data to keep straight. Perhaps some encapsulation would be handy…

### Making a class

We’ll start with a simple class declaration: every Surreal has a “day” it was born on, and consists of a Left and Right set of numbers.

``````class Surreal:
birthday=None
left_set=()
right_set=()
``````

When a Number is “created”, we will know these values, so we’ll include them in the constructor. We also want to sanity check `Axiom 1`, so we’ll check that all Left Set values are less-than all Right Set values.

``````    def __init__(self, birthday, left_set: tuple, right_set: tuple):
for l in left_set:
for r in right_set:
assert l < r, "Not a Surreal Number: Violates Axiom 1"

self.birthday = birthday
assert self.birthday is not None, "Invalid Birthday Provided"

self.left_set = left_set
self.right_set = right_set
``````

Let’s include the definition of `less-than`, so we can begin to order our Surreal numbers. Recall Axiom 2:

One number is less than or equal to another number if and only if no member of the first number’s left set is greater than or equal to the second number, and no member of the second number’s right set is less than or equal to the first number

We can add `less-than` as a dunder/magic method, so we can directly compare `Surreal` objects as Numbers

``````    def __le__(self, other):

for l in self.left_set:
if l >= other: return False
for ro in other.right_set:
if self >= ro: return False

return True
``````

For convenience, let’s also include a pretty print function in the form of a `__str__` method, so we can use the same symbolic convention as the paper:

``````    def __str__(self):
return "{" + ",".join(map(str, self.left_set)) + "|" + ",".join(map(str, self.right_set)) + "}"
``````

Now that we have our basic functionality, we can try it out some of the previous Numbers we’ve created:

Let’s ensure that the symbol for `0` looks right:

Then, let’s manually create the other 2 numbers:

Another method of comparison for Surreals is known as “simplicity”. One surreal is “simpler” than another if its birthday is less-than the others. For our example, `0` is the simplest, followed by `-1` and `1`. We can add this function to our `Surreal` class:

``````    def is_simpler_than(self, other):
return self.birthday < other.birthday
``````

And we can also programatically check this is true:

Now, generating these numbers from scratch will quickly get tedius, as on the second day the number of valid Surreals will jump from 3 to 24. We should come up with some sort of combinatoric solution. Skipping slightly ahead in Grimm, we can see the numbers generated on the 2nd day are:

``````0 = {|} 1 = {0|} −1 = {|0} {1|}
{−1|} {0, 1|} {0, −1|} {−1, 1|}
{−1, 0, 1|} {|1} {| − 1} {|0, 1}
{|0, −1} {| − 1, 1} {| − 1, 0, 1} {−1|0}
{−1|1} {−1|0, 1} {0|1} {−1, 0|1}.
``````

The pattern expressed in the Left and Right sets is known as a Power Set. We can use a code recepie from the `itertools` module to simplify their creation.

We can then (naievely) generate some Surreals. To save on memory and processing time, we will use an iterator instead of generating all values at once.

But what exactly are these “numbers” we’re creating? We’ll explore that, as well as how dyadic rationals (and those beyond) will fit in as well.

Written on June 1, 2021