Octopusal Networks

This work is based on the ideas that Dr. Edward De Bono explained in the books "The mechanism of mind" and "I'm Right, You Are Wrong", which I highly recommend. In these books De Bono carries out a model of the mind the I found very interesting. I don't actually know if someone else implemented this, anyway this notebook is my interpretation of the model in python.

For each new feature of the model I build some classes and do some examples to show the results, you can also just read the comments and see the output and then return on the code if you are interested.

Octopuses, tentacles and the beach

Imagine a neurone as an octopus with a large number of tentacles (not the usual eight). Some of these tentacles may be very long. Each of them rests on the body of another octopus and can transmit to that octopus an electric shock. If an octopus receives a sufficient number of shocks it wakes up and proceeds to shock others. The beach is covered with a large number of octopuses all linked up in this way. Any octopus may be linked up, by means of long tentacles, to an octopus quite far away. But for the sake of convenience we shall assume an octopus is linked to its physical neighbours.

So to start we create three classes: Octopus, Tentacle and Beach.

An octopus can be awake or sleeping, each time that it receives a shock its excitement increase, when the excitement pass a certain threshold it wakes up and starts to shock others.

A tentacle for now has two attributes, the octopus owner and the octopus on which it rests. It can shock the octopus on which it rests.

The beach take in the constructor the parameters width and height and construct a list of octopuses of length = width * height. Then each octopus is connected to its neighbours. When we print out an instance of the class Beach the emoji πŸ™represent an octopus sleeping and the emoji πŸ’‘represent an octopus awake.

In [1]:
class Octopus:

    shocks_threshold = 2

    def __init__(self, id):
        self.id = id
        self.awake = False
        self.excitement = 0
        self.tentacles = []

    def shocked(self, power):
        self.excitement += power
        if (self.excitement >= Octopus.shocks_threshold):
            self.awake = True

    def detail(self):
        result = f'{self}\n'
        for tentacle in self.tentacles:
            result += f'\t{tentacle}\n'
        return result

    def __str__(self):
        return f'Octopus {self.id} [awake: {self.awake}, excitement: {self.excitement}]'
In [2]:
class Tentacle:

    def __init__(self, id, owner, connected):
        self.id = id
        self.owner = owner
        self.connected = connected
        owner.tentacles.append(self)

    def shock(self):
        self.connected.shocked(1)

    def __str__(self):
        id = self.id
        owner = self.owner
        connected = self.connected
        return f'Tentacle {id}: Octopus {owner.id} -> Octopus {connected.id}'
In [3]:
class Beach:

    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.octopuses = []
        self.create_octopuses()
        self.connect_neighbours()

    def create_octopus(self, id):
        return Octopus(id=id)

    def create_octopuses(self):
        for i in range(0, self.width * self.height):
            octopus = self.create_octopus(id=i)
            self.octopuses.append(octopus)     

    def create_tentacle(self, id, owner, connected):
        return Tentacle(id=id, owner=owner, \
                        connected=connected)

    def connect_neighbours(self):
        width = self.width
        height = self.height

        def get_neighbours(x, y):
            neighbours = []
            neighbours.append((x - 1, y - 1))
            neighbours.append((x - 1, y))
            neighbours.append((x - 1, y + 1))
            neighbours.append((x, y - 1))
            neighbours.append((x, y + 1))
            neighbours.append((x + 1, y - 1))
            neighbours.append((x + 1, y))
            neighbours.append((x + 1, y + 1))
            return neighbours

        for i in range(0, width * height):
            octopus = self.octopuses[i]
            coors_neighbours = get_neighbours(i // height, i % width)
            tentacle_id = 0
            for x, y in coors_neighbours:
                try:
                    neighbour = self.get(x, y)
                    tentacle = self.create_tentacle(id=tentacle_id, owner=octopus, \
                                                    connected=neighbour)
                    tentacle_id += 1
                except:
                    continue

    def get(self, x, y,):
        width = self.width
        height = self.height
        if (0 <= x < height) and (0 <= y < width):
            return self.octopuses[x * width + y]
        else:
            raise Exception

    def detail(self):
        result = ''
        for octopus in self.octopuses:
            result += octopus.detail()
        return result

    def __str__(self):
        result = '\n'
        for x in range(0, self.height):
            for y in range(0, self.width):
                octopus = self.octopuses[x * self.width + y]
                result += 'πŸ’‘' if octopus.awake else 'πŸ™'
            result += '\n'
        return result

In the next cell we create a beach of dimensions 4 x 4 and just print it out.

In [4]:
beach = Beach(width=4, height=4)
print(beach)
πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™

Yellow patch

Now if we stimulate a group of octopuses, for example by shining a bright light from a helicopter above, they become active and start sending out shocks along their tentacles. In order to see what is happening we shall assume that when an octopus is awake its colour changes to yellow. So now we see a patch of yellow spreading outwards from the group we stimulated with the bright light. Now that yellow patch could go on spreading until it covered until it covered the whole beach of octopuses. This would be somewhat equivalent to an epilectic fit in the brain, with all systems activated.

Here we introduce the class Helicopter that has a static method with two parameters: the beach and the clause where. The parameter "where" is a list of coordinates that tell the helicopter which octopuses to wake up.

Then we extend the class Beach to create the class BeachWithSpreading. This class adds time and movement to the beach. The main method is "animate" that starts by waking up the octopus specified by the parameter "where" and then make a loop for certain iterations where each octopus awake shocks every other octopus connected to him. If at a certain point all octopuses are sleeping the loop stop because nothing can happen.

In [5]:
from random import shuffle

class Helicopter:

    @staticmethod
    def light(beach, where):
        shuffle(where)
        for x, y in where:
            octopus = beach.get(x, y)
            octopus.shocked(Octopus.shocks_threshold)

In the next example we create an array "center" that has the coordinates of the four octopuses at the center of the beach and then use the helicopter to wake them up.

In [6]:
size = 10
half = int(size / 2)
center = [(half, half), (half, half - 1), (half - 1 , half), (half - 1, half - 1)]

beach = Beach(width=size, height=size)

Helicopter.light(beach, center)

print(beach)
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

In [7]:
class AllSleepingException(Exception):
    pass

class BeachWithSpreading(Beach):

    def __init__(self, width, height, shocks_threshold=3):
        super().__init__(width, height)
        Octopus.shocks_threshold = shocks_threshold

    def start(self, where):
        Helicopter.light(self, where)

    def print_start(self, show):
        if show:
            print('Start')
            print(self)

    def iteration(self):
        awake = [o for o in self.octopuses if o.awake]
        if len(awake) == 0:
            raise AllSleepingException
        for octopus in awake:
            for tentacle in octopus.tentacles:
                tentacle.shock()

    def print_iteration(self, show, i):
        if show:
            print(f'Iteration {i + 1}')
            print(self)

    def animate(self, where=None, iterations=10, show=True):
        if where != None:
            self.start(where)
        self.print_start(show)
        for i in range(0, iterations):
            try:
                self.iteration()
                self.print_iteration(show, i)
            except AllSleepingException:
                if show == True:
                    print('It looks like everyone is sleeping πŸ˜•')
                break

In the next example we create a beach and animate it with the parameter "where" set at "center", that is the array created previously. You can see how the yellow patch spreads to take all the beach

In [8]:
beach = BeachWithSpreading(width=10, height=10)
beach.animate(where=center)
Start

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 1

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 2

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 3

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 4

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 5

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 6

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 7

πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™

Iteration 8

πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™

Iteration 9

πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘

Iteration 10

πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘
πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘

Smell

Let us now add another feature. When an octopus is awake (and yellow) it gives off a pungent smell - a sort of cross between decaying fish and ammonia. This smell is so unpleasant to all octopuses that if the strength of the smell reaches a certain level they refuse to be woken up. So when the spreading yellow patch of activated octopuses has reached a certain size the smell will have reached a certain level of strength. At this point no further octopus will wake up, so the patch stays limited that size.

In neurological terms we have a spreading activation and a build-up inhibition. This inhibition could be brought about through a build-up of chemicals or direct negative feedback carried by another set of nerves. The function is the same.

Now we introduce the class OctopusWithSmell that adds to the class Octopus a mechanism by which if the smell in the environment (passed in the constructor) pass a certain threshold the octopus can't wake up. It also increase the smell in the environment when the octopus wakes up.

In [9]:
class OctopusWithSmell(Octopus):

    smell_threshold = 20

    def __init__(self, id, environment):
        super().__init__(id)
        self.environment = environment

    def shocked(self, power=0):
        if (self.awake):
            return
        self.excitement += power
        if (self.excitement >= Octopus.shocks_threshold and
            self.environment.smell < OctopusWithSmell.smell_threshold):
            self.awake = True
            self.environment.smell += 1
In [10]:
class BeachWithSmell(BeachWithSpreading):

    def __init__(self, width, height, shocks_threshold=5, smell_threshold=20):
        super().__init__(width, height, shocks_threshold)
        self.smell = 0
        OctopusWithSmell.smell_threshold = smell_threshold

    def create_octopus(self, id):
        return OctopusWithSmell(id=id, environment=self)

    def print_iteration(self, show, i):
        if show:
            print(f'Iteration {i + 1} - smell: {self.smell}')
            print(self)

As you can see in the next cell, this time the yellow patch stop to spread at a certain point, when the smell has reached a certain level.

In [11]:
beach = BeachWithSmell(width=10, height=10)
beach.animate(center)
Start

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 1 - smell: 4

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 2 - smell: 4

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 3 - smell: 12

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 4 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 5 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 6 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 7 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 8 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 9 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 10 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Soreness

If this was all there was to it, the patch of yellowness would always be circular around the octopuses on whom the helicopter light had first shone. So let us add another effect. If an octopus is already awake when it receives an electric shock through a tentacle, that patch of skin under the tentacle gets rather sore. This soreness means that the octopus is much more likely to respond to a shock from this particular tentacle. This means that if two spots of helicopter light awake two groups of nearby octopuses, in the future the connection between those two groups will be stronger than with other octopuses.

This effect gives rise to the important phenomenon of association and also to reconstruction. If two helicopter lights have been used in this way and in the future only one light is used, the yellow patch is more likely to spread to the group that is better connected than anywhere else. So the situation is recreated as if there were two spots of light at the same time, and the yellow patch does not spread as a simple circle around the stimulus point but follows the track of increased connectedness which itself depends on past experience. In this way the crowd of octopuses can repeat or reconstruct a pattern. Even if the input is not the exact this time, the same shape of yellow patch can be produced.

To add this effect we just change the method "shock" on the class Tentacle to manage the fact that if both octopus are awake the soreness of the tentacle increase. We also add the method "night" to the beach that desactivates all octopuses but keeps the connections between them.

In [12]:
class TentacleWithSoreness(Tentacle):

    def __init__(self, id, owner, connected):
        super().__init__(id, owner, connected)
        self.soreness = 1

    def shock(self):
        if self.connected.awake:
            self.soreness += 1
        else:
            self.connected.shocked(self.soreness)
            
    def __str__(self):
        return super().__str__() + f': Soreness {self.soreness}'
In [13]:
class BeachWithSoreness(BeachWithSmell):

    def __init__(self, width, height, shocks_threshold=50, smell_threshold=50):
        super().__init__(width, height, shocks_threshold, smell_threshold)

    def create_tentacle(self, id, owner, connected):
        return TentacleWithSoreness(id=id, owner=owner, \
                                    connected=connected)

    def print_night(self):
        print()
        print("Night\n")
        for i in range(0, self.height):
            print("🌚" * self.width)
        print("\n")
            
    def night(self, show=False):
        for octopus in self.octopuses:
            if octopus.awake: self.smell -= 1
            octopus.awake = False
            octopus.excitement = 0
        if show: self.print_night()

In the next example we first animate the beach for 10 iteration with a shape like an "L", so that the octopuses on this shape get connected. Then we make sleep all octopuses and animate again the beach but only with the vertical part of the "L". This time the yellow patch insted of spreding circularly it follows the past experience and recreates the "L".

In [14]:
size = 10
half = int(size / 2)

L_form_horizontal = []
L_form_vertical = []
for x in range(0 + half // 2, size - half // 2):
    L_form_vertical.append((x, half // 2))
    L_form_vertical.append((x, half // 2 - 1))
for y in range(0 + half // 2, size - half // 2):
    L_form_horizontal.append((half + half // 2, y))
    L_form_horizontal.append((half + half // 2 - 1, y))
L_form = L_form_vertical +  L_form_horizontal
    
beach = BeachWithSoreness(width=10, height=10)
beach.animate(L_form, show=False)
beach.night(show=False)
beach.animate(L_form_vertical, iterations=11, show=True)
Start

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 1 - smell: 12

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 2 - smell: 13

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 3 - smell: 14

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 4 - smell: 14

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 5 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 6 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 7 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 8 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 9 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 10 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 11 - smell: 20

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Tiredness

What happens next? The yellow patch is no longer spreading but is limited (by the stink). It has followed previous experience. Now the active octopuses have only a short attention span, so they start to get bored and tired. As they start to get bored, the stink they are giving out drops sharply. This means that other octopuses outside the first yellow patch who are receiving enough shocks to be awakened but have been discouraged by the stinck can now wake up and get active. The original group now fall asleep, so their yellow patch disappear. The yellow patch shifts to the new group of recently awakened octopuses. The tired octopuses will take a while to recover from their tiredness.

So now we get a shift in the yellow patch from one group to another. The patch, always limited in size by the stink, will continue to shift across the beach. If one group is well connected by long tentacles to a distant group, the patch may disappear in one area and appear in a distant area. The way one one area after another becomes yellow is a sequence or pattern. For a given set of conditions the pattern will be constant.

To accomplish this, we add at each iteration a call to the method "tired" that sleeps the octopuses very tired. An octopus will fall asleep if he has been awake for more than a certain number of iterations. When an octopus fall a sleep has to sleep some time to recover, so we added the fields "recovering" and "recovering_status" that tracks how much they have to sleep to recover their energies and be activated again.

In [15]:
class OctopusWithTiredness(OctopusWithSmell):

    tiredness_threshold = 10
    recovery_threshold = 10

    def __init__(self, id, environment):
        super().__init__(id, environment)
        self.tiredness = 0
        self.recovering = False
        self.recover_status = 0

    def tired(self):
        self.tiredness += 1
        if (self.tiredness >
            OctopusWithTiredness.tiredness_threshold):
            self.sleep(night=False)

    def recover(self):
        self.recover_status += 1
        if (self.recover_status >=
            OctopusWithTiredness.recovery_threshold):
            self.recovering = False
            self.recover_status = 0
            
    def shocked(self, power=0):
        if not self.recovering:
            super().shocked(power)

    def sleep(self, night=True):
        if self.awake: self.environment.smell -= 1
        self.awake = False
        self.excitement = 0
        self.tiredness = 0
        if night:
            self.recovering = False
            self.recover_status = 0
        else:
            self.recovering = True
In [16]:
from random import shuffle

class BeachWithTiredness(BeachWithSoreness):

    def __init__(self, width, height, shocks_threshold=80, smell_threshold=50,
                 tiredness_threshold=5, recovery_threshold=5):
        super().__init__(width, height, shocks_threshold, smell_threshold)
        OctopusWithTiredness.tiredness_threshold = tiredness_threshold
        OctopusWithTiredness.recovery_threshold = recovery_threshold

    def create_octopus(self, id):
        return OctopusWithTiredness(id=id, environment=self)

    def iteration(self):
        awake = [o for o in self.octopuses if o.awake]
        if len(awake) == 0:
            raise AllSleepingException
        shuffle(awake)
        for octopus in awake:
            octopus.tired()
            for tentacle in octopus.tentacles:
                tentacle.shock()
        recovering = [o for o in self.octopuses if o.recovering]
        for octopus in recovering:
            octopus.recover()

    def night(self, show=False):
        for octopus in self.octopuses:
            octopus.sleep()
        if show: self.print_night()

In this example we reause the "L" form utilized in the previous example but this time the yellow patch instead of recreating the entire pattern, will shift from one part of the "L" to another.

In [17]:
size = 10
half = int(size / 2)

L_form_horizontal = []
L_form_vertical = []
for x in range(0 + half // 2, size - half // 2):
    L_form_vertical.append((x, half // 2))
    L_form_vertical.append((x, half // 2 - 1))
for y in range(0 + half // 2, size - half // 2):
    L_form_horizontal.append((half + half // 2, y))
    L_form_horizontal.append((half + half // 2 - 1, y))
L_form = L_form_vertical +  L_form_horizontal

beach = BeachWithTiredness(width=10, height=10, tiredness_threshold=15)
beach.animate(L_form, show=False)
beach.night(show=False)
beach.animate(L_form_vertical, iterations=20, show=True)
Start

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 1 - smell: 12

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 2 - smell: 12

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 3 - smell: 13

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 4 - smell: 14

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 5 - smell: 14

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 6 - smell: 14

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 7 - smell: 14

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 8 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 9 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 10 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 11 - smell: 16

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 12 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 13 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 14 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 15 - smell: 18

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 16 - smell: 8

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 17 - smell: 8

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 18 - smell: 8

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 19 - smell: 7

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Iteration 20 - smell: 8

πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ’‘πŸ’‘πŸ’‘πŸ’‘πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™
πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™πŸ™

Listeners

Let's make the beach more active and attach some listeners to some octopuses, so that when an octopus with a listener wakes up or falls asleep, that listener is fired and based on some conditions can carry out an action.

In [18]:
class OctopusWithListeners(OctopusWithTiredness):

    def __init__(self, id, environment):
        super().__init__(id, environment)
        self.listeners = []

    def attach_listener(self, listener):
        self.listeners.append(listener)

    def fire_listeners(self):
        for listener in self.listeners:
            listener.fire(self)

    def shocked(self, power=0):
        was_awake = self.awake
        super().shocked(power)
        is_awake = self.awake
        if (not was_awake and is_awake):
            self.fire_listeners()
            
    def tired(self):
        was_awake = self.awake
        super().tired()
        is_awake = self.awake
        if (was_awake and not is_awake):
            self.fire_listeners()
In [19]:
class BeachWithListeners(BeachWithTiredness):

    def __init__(self, width, height, shocks_threshold=80,
                 smell_threshold=50, tiredness_threshold=5, recovery_threshold=5):
        super().__init__(width, height, shocks_threshold, smell_threshold, tiredness_threshold, recovery_threshold)
        self.listeners = set([])

    def create_octopus(self, id):
        return OctopusWithListeners(id=id, environment=self)

    def attach_listener(self, where, listener):
        self.listeners.add(listener)
        for x, y in where:
            octopus = self.get(x, y)
            octopus.attach_listener(listener)
    
    def night(self, show=False):
        super().night()
        for listener in self.listeners:
            listener.reset()

With all this in place we can now teach our beach to count. To do this we first train the beach assigning a pattern to each number and connecting the patterns. Then we attach some listeners to print the numbers and eventually we animate the beach with only the pattern corresponding to the number one. You can see how this lead the beach to print all the numbers. If you change the parameters "show", you can see the patterns in the training stage and then how in the test stage the yellow patch traverse all the beach following the patterns.

In [20]:
class NumberListener():
    
    def __init__(self, number):
        self.threshold = 16
        self.number = number

    def reset(self):
        self.threshold = 16
        
    def fire(self, octopus):
        if octopus.awake:
            self.threshold -= 1
        else:
            self.threshold += 1
        if (self.threshold == 0):
            print(self.number)
            self.threshold = 16

from numbers_patterns import *

beach = BeachWithListeners(
    width=28, height=28,
    tiredness_threshold=10,
    recovery_threshold=30,
    smell_threshold=16 + 16 + 12,
    shocks_threshold=60
)

beach.animate(one + after1 + two, iterations=10, show=False)
beach.night(show=False)
beach.animate(two + after2 + three, iterations=10, show=False)
beach.night(show=False)
beach.animate(three + after3 + four, iterations=10, show=False)
beach.night(show=False)
beach.animate(four + after4 + five, iterations=10, show=False)
beach.night(show=False)
beach.animate(five + after5 + six, iterations=10, show=False)
beach.night(show=False)
beach.animate(six + after6 + seven, iterations=10, show=False)
beach.night(show=False)
beach.animate(seven + after7 + eight, iterations=10, show=False)
beach.night(show=False)
beach.animate(eight + after8 + nine, iterations=10, show=False)
beach.night(show=False)

beach.attach_listener(one, NumberListener(1))
beach.attach_listener(two, NumberListener(2))
beach.attach_listener(three, NumberListener(3))
beach.attach_listener(four, NumberListener(4))
beach.attach_listener(five, NumberListener(5))
beach.attach_listener(six, NumberListener(6))
beach.attach_listener(seven, NumberListener(7))
beach.attach_listener(eight, NumberListener(8))
beach.attach_listener(nine, NumberListener(9))

OctopusWithSmell.smell_threshold = 16 + 12
beach.animate(one, iterations=210, show=False)
beach.night()
1
2
3
4
5
6
7
8
9

Conclusions

To summarize we can list the characteristicts of the system:

  1. Activity of an octopus can stimulate other octopuses into activity if they are connected by tentacles.
  2. The total size of the activated group is limited by negative feedback (the pungent smell).
  3. A tiring factor means that activity will shift from the stimulated group to the next ready group.
  4. Stimulation is on a 'threshold' basis and is non-linear.
  5. Any octopuses which are activated at the same time will have an increased connectedness.

As the result of this simple characteristicts the system is capable of the following general behaviour:

  1. Attention.
  2. Pattern recognition and reconstruction.
  3. Integration of different inputs.
  4. Creating sequence patterns bringing in past experience.

The behaviour of this model depends very largerly on the parameters, like other algorithms in machine learning the process of tuning of hyperparameters is central. Are also possible a lot of different architectures. In this notebook every octopus is connected only to its neighbours but this is only one possible choice. We can connect all octopuses to each other and the behaviour would be very different. Or we can do multiple beaches and connect them like layers in neural networks. And so on.

In the next notebook we we will use octopusal networks to recognize the handwritten digits of the MNIST database

This is a very limited and inefficient implementation and I think that there is still a lot to explore. If you are interested in this work feel free to contact me at [email protected]

Marco Nunnari
May 2018