Network Science and Epic Poems

Abstract from our last paper A Networks-Science Investigation into the Epic Poems of Ossian
by Joseph Yose, Ralph Kenna, Pádraig MacCarron, Thierry Platini, Justin Tonr

In 1760 James Macpherson published the first volume of a series of epic poems which he claimed to have translated into English from ancient Scottish-Gaelic sources. The poems, which purported to have been composed by a third-century bard named Ossian, quickly achieved wide international acclaim. They invited comparisons with major works of the epic tradition, including Homer’s Iliad and Odyssey, and effected a profound influence on the emergent Romantic period in literature and the arts. However, the work also provoked one of the most famous literary controversies of all time, colouring the reception of the poetry to this day. The authenticity of the poems was questioned by some scholars, while others protested that they misappropriated material from Irish mythological sources. Recent years have seen a growing critical interest in Ossian, initiated by revisionist and counter-revisionist scholarship and by the two-hundred-and-fiftieth anniversary of the first collected edition of the poems in 1765. Here we investigate Ossian from a networks-science point of view. We compare the connectivity structures underlying the societies described in the Ossianic narratives with those of ancient Greek and Irish sources. Despite attempts, from the outset, to position Ossian alongside the Homeric epics and to distance it from Irish sources, our results indicate significant network-structural differences between Macpherson’s text and those of Homer. They also show a strong similarity between Ossianic networks and those of the narratives known as Acallam na Senorach (Colloquy of the Ancients) from the Fenian Cycle of Irish mythology.

Symmetric number

Take a integer n between 10 and 99. We write n=10x+y with x, y between 0 and 9.  We define the symmetric number \bar n=10y+x. For example, if n=74 then \bar n=47.


It is then easy to show that the difference of the square n^2 -\bar n ^2 can be express as the sum of differences between 3 digits symmetric numbers.

n^2 -\bar n ^2=10(m-\bar m)+(m'-\bar m') with

m=100a_x+a_y and m'=100b_x+b_y, with x^2=10a_x+b_x and y^2=10a_y+b_y.


For example with n=74 we have 7^2=4\times 10+9 and 4^2=16, leads to


Minimal Spanning Tree of Weighted Parametrised Graph

I have been recently teaching Graph Theory to second year students. Amongst the things we covered in class were minimal spanning trees. The topic inspired me the following problem.

Let us consider a fully connected graph G with N vertex all labelled from 1 to N. A weight w(e_{i,j}) is associated to each edge e_{i,j}. We define


with a and b real numbers.

Depending of the values of a and b, what can we say about the minimal spanning tree of G ? Is it unique ? If not how many spanning trees are there ?

A toy model for evolution, of a “unicellular mathematical organism”

Here is an idea, with which I wanted to play with for a little while.

Let us look at the evolution of a “unicellular mathematical organism”. We’ll start to say that each organism is defined by its “mathematical DNA” – Here we are going to consider 2 pairs of integers (or chromosomes) only. The first pair is defined by 2 integers a and a'. We will call it the A-pair. The second pair, call it the B-pair, is defined by b and b'. For simplicity we will define A=(a,a') and B=(b,b').

We will say that A is the pair of genes which govern the reproduction, while B is the pair of genes which defines their fitness, and ultimately their death.

It follow that a cell is define by the couple of pairs (A,B)=((a,a'),(b,b')) .

Now here are the rules which govern  the reproduction, birth and death of these cells.

1 – Reproduction and Birth:

When two cells meet [cells 1 and 2, with genomes (A_1, B_1 ) and (A_2, B_2)], they can reproduce (generate a new cell) with probability R(A_1,A_2)R is a function of the pairs A_1 and A_2.

The genome of the new cell is formed by two halfs of the genome of its parents. It can be any of the following outcome:

((a_1,a_2),(b_1,b_2))((a_1,a'_2),(b_1,b_2))((a_1,a'_2),(b_1,b'_2))((a'_1,a_2),(b_1,b_2)), … and all other possibilities.

2 – Death

We will simply say that at any time a cell can die with probability by time unit D(B).

Defining the rates R and D.

The reproduction rate R is function of the A-genes of the two organisms. One option is to choose

R(A_1,A_2) = (a_1+a'_1+a_2+a'_2)/K (for some constant K), so that the larger are the integers of each cell, the most likely they are to reproduce. One possible alternative solution would be R(A_1,A_2)=\min(a_1+a'_1)+\min(a_2+a'_2) or the same using \max instead of \min. This would be equivalent as introducing a dominant or recessive gene.

Identically, D could be define by D(B)=b+b'. In this way cell with small integers on the B-gene would be most likely to survive and therefore to transmit their genes to the next generations.


A first algorithm:

Start with N_0 initial cells. Each cell has genome ((a,a'),(b,b')) where a,a',b,b' are integers randomly distributed between 1 and P.

Let r,d be two real numbers such that $r+d=1$. With probability r we are going to select two cells for the reproduction process. With probability d=1-r we are going to select a cell and test its survival skills. So we generate a random number x between 0 and 1. If x<r try the reproduction process, else try the death process.

1 – Reproduction Process:

Select two cells and calculate the probability R(A_1,A_2) one could choose

R=\frac{a_1+a'_1+a_2+a'_2}{4P}, so that 0<R<1. Generate a random number x and if x<R the reproduction process is successful and we generate a new cell.

2 – Death Process:

Select one cell and calculate the probability D(B) one could choose

B=\frac{b+b'}{2P}, so that 0<B<1. Generate a random number x and if x<D the cell dies.


Below you see the evolution of the Population size as a function of the time, when choosing parameters: r=0.3, d=0.7 and P=10, and initial condition N_0=100. Note that the evolution is non-monotonic.

Screen Shot 2015-08-04 at 11.52.27




import sys , math , cmath , random , shelve

import numpy

proba_r = 0.5

proba_d = 0.5

N_step = 140

N_specie_0 = 100       # Number of initial species

class organism() :        # we here define the class which will generate organisms as objects

    def __init__(self):

        a = random.randint( 1 , 10 )

        ap = random.randint( 1 , 10 )

        b = random.randint( 1 , 10 )

        bp = random.randint( 1 , 10 )

        self.A = [ a , ap ]

        self.B = [ b , bp ]

Average_A = []

Average_B = []

Pop_size = []

Tab_of_object = []

for ii in range( N_specie_0 ):

    Tab_of_object += [ organism() ]

aaa = 0

bbb = 0

for obj in Tab_of_object :

    aaa += obj.A[ 0 ] + obj.A[ 1 ]

    bbb += obj.B[ 0 ] + obj.B[ 1 ]

aaa = aaa * 1.0 / (2 * len( Tab_of_object ))

bbb = bbb * 1.0 / (2 * len( Tab_of_object ))

Average_A += [ aaa ]

Average_B += [ bbb ]

Pop_size += [ len( Tab_of_object ) ]

for tt in range( N_step ) :

    LL = len(Tab_of_object)

    for ppp in range( LL ) :      # a time step is the realisation of LL updates where LL is the number of total organisms

        if ( len( Tab_of_object ) == 1 ) : #the code quit is we have only one object left as reproduction is then impossible

            print “quiting”


        x = random.random()

        if ( x < proba_r)  :

            index_1 = random.choice( range( len( Tab_of_object ) ) )

            index_2 = index_1

            while ( index_2 == index_1 ) :

                index_2 = random.choice( range( len( Tab_of_object ) ) )

            obj_1 = Tab_of_object[ index_1 ]

            obj_2 = Tab_of_object[ index_2 ]

            R = ( obj_1.A[0] + obj_1.A[1] + obj_2.A[0] + obj_2.A[1] ) * 1.0 / ( 4.0 * 10.0 )

            y = random.random()

            if ( y < R ) :

                obj_baby = organism()

                obj_baby.A[ 0 ] = obj_1.A[ random.choice( [ 0 , 1 ] ) ]

                obj_baby.A[ 1 ] = obj_2.A[ random.choice( [ 0 , 1 ] ) ]

                obj_baby.B[ 0 ] = obj_1.B[ random.choice( [ 0 , 1 ] ) ]

                obj_baby.B[ 1 ] = obj_2.B[ random.choice( [ 0 , 1 ] ) ]

                Tab_of_object += [ obj_baby ]

        if ( proba_r < x < ( proba_r + proba_d ) ) :

            index_of_obj_to_kill = random.choice( range( len( Tab_of_object ) ) )

            obj = Tab_of_object[ index_of_obj_to_kill ]

            D = ( obj.B[0] + obj.B[1] ) * 1.0 / ( 2.0 * 10.0 )

            y = random.random()

            if ( y < D ) :

                Tab_of_object.pop( index_of_obj_to_kill )

    aaa = 0

    bbb = 0

    for obj in Tab_of_object :

        aaa += obj.A[ 0 ] + obj.A[ 1 ]

        bbb += obj.B[ 0 ] + obj.B[ 1 ]

    aaa = aaa * 1.0 / (2.0 * len( Tab_of_object ) )

    bbb = bbb * 1.0 / (2.0 * len( Tab_of_object ) )

    Average_A += [ aaa ]

    Average_B += [ bbb ]

    Pop_size += [ len( Tab_of_object ) ]

import matplotlib.pyplot as plt

plt.plot( Pop_size )

plt.xlabel(‘time step’)


plt.plot( Average_A )

plt.plot( Average_B )

plt.xlabel(‘time step’)

plt.ylabel(‘Average_A Average_B’)

The road we take when we read numbers.

1989 may or may not be a special number to you.
It may be a special number  if you  were born in 1989 or if you did buy Taylor Swift’s last album or maybe for some other reason. If not, well I’m guessing that 1989 is nothing special to you. Depending on its status in your mind, you are not going to read this number in the same way.
Sarah Wiseman from UCL gives a really interesting presentation on how we read numbers. See the numberphile video
She makes the distinction between numbers which have a meaning (this is relative to you) – most likely 314 has a meaning to you – and numbers which don’t mean anything (maybe like 209123002).



Associativity is not always given

Many of my students tends to believe that associativity of a given operation is always true.
We have seen in the previous post that addition is associative so that we always have (a+b)+c=a+(b+c). This actually hold true for all integers (positives and negatives).

But clearly you would agree that subtraction is not associative. (a-b)-c\ne a-(b-c).

This has obviously to do with the way subtraction is define. One way to think of it is to write -a as the additive inverse (or opposite) of a, such that: a+(-a)=0. The subtraction b-a is then defined as b+(-a). The rule is that we can replace +(-a) directly by -a.

It follows that the additive inverse of b+c is (-b)+(-c) as b+c+(-b)+(-c)=0. Therefore we chose to write the additive inverse of b+c as -(b+c).

Let us now have a look at (a-b)-c=(a+(-b))+(-c)=a+((-b)+(-c))=a+(-(b+c)) which we write a-(b+c) so that clearly subtraction is not associative


Showing that addition is associative and commutative using Mathematical Induction

I recently found a book left on the AMRC coffee table “Fundamental Concepts of Mathematics” by R.L. Goodstein. Inside his book Goodstein propose to use mathematical induction to show that addition is commutative.


We start by defining addition


We first need to define the addition of two number as satisfying the following property: m+(n+1)=(m+n)+1 (this is associativity with 1 under addition). Let us refer this property as A_0.


Showing associativity for all integers


We can first show that associativity is always true. We write A_1 the property m+(n+p)=(m+n)+p.

The proof by induction is:

1) we know A_1 to be true for p=1 as it give A_0

2) let us assume it exists an integers k satisfying A_1 so that we can write m+(n+k)=(m+n)+k.

It follows that:

using A_0    m+(n+(k+1))=m+((n+k)+1)

using A_0    m+(n+(k+1))=(m+(n+k))+1

since A_1 is true for k    m+(n+(k+1))=((m+n)+k)+1

using A_0    m+(n+(k+1))=(m+n)+(k+1)

We now see that if k satisfies A_1 then the next integer k+1 satisfies A_1. Since A_1  is true for k=1 it is true for all positive integers.


Showing that addition with 1 is commutative


From here we can show commutativity with 1. We refer to this property as C_0: a+1=1+a for all a (positive) integers.

The proof by induction is the following:

1) we know that C_0 is true for a=1, as we simply have 1+1=1+1

2) let us assume that it exists an integer k for which C_0 is true. Then we can write k+1=1+k.

Since k satisfies C_0    (k+1)+1=(1+k)+1

using A_0    (k+1)+1=1+(k+1)

We now see that if k satisfy C_0 then the next integer k+1 satisfy C_0. Since C_0  is true for k=1 it is true for all positive integers.


Showing that addition is commutative for all integers


Next we can show the property C_1: commutativity with any integer a+b=b+a.

The proof by induction is:

1) we know C_1 is true for b=1 as it gives a+1=1+a which simply is C_0 which we now know to be true.

2) let us assume that C_1 is true for some integer k then we can write a+k=k+a.

It follows that

using A_0   a+(k+1)=(a+k)+1

since C_1 is true for k    a+(k+1)=(k+a)+1

using A_0    a+(k+1)=k+(a+1)

using C_0    a+(k+1)=k+(1+a)

using A_1    a+(k+1)=(k+1)+a

So that we see that if k satisfy C_1 then the next integer k+1 satisfy C_1. Therefore C_1 is true for all integers.

Martin Gardner – Problem 1 – The Returning Explorer

In “My Best Mathematical and Logic Puzzles” Martin Gardner’s first problem is titled “The Returning Explorer” in reference of the following riddle.

“”An explorer walks one mile due south, turns and walks one mile due east, turns again and walks one mile due north. He finds himself back where he started. He then shoot [or see (depending of the riddle you wish to tell)] a bear. What color is the bear ?””

The problem proposed by M. Gardner is then to find all points on the globe from which you can walk one mile south, east and north and finally end up at your starting point.

There is an infinite number of points which satisfies this property. Can you find them and give the latitude at which you need to start your journey ?

The answer is the following.  Writing R the earth radius and \phi_n the latitude (n is integer), all latitude on which you can start are given by:

\phi_n=\frac{1}{R}-arccos\left(\frac{1}{2\pi R n}\right).

Which at the first order in 1/R leads to

\phi_n=-\frac{\pi}{2}+\frac{1}{R}\frac{2\pi n+1}{2\pi n}.

Now, starting from any other latitude \theta_0, you would not be able to “complete a triangle” by walking south for X miles, east for Y miles and back north for X miles. But how far away from the starting point would you be exactly ?

Well if you were to walk back west from the finish to the starting point, you would have to walk for a distance \Delta

\Delta =Y\frac{\cos(\theta_0)}{\cos(\theta_0-X/R)}.

Assuming X/R\ll1 we have

\Delta\simeq Y\frac{\cos(\theta_0)}{\cos(\theta_0)+\frac{X}{R}\sin(\theta_0)}.

However, this is not the shortest distance. The fact is that the shortest path between two points A and B on a sphere is along the circle of radius R passing by A and B. Can we find out what the shortest path is ?


Visiting Scholar at U Del

Since Feb 1st 2015, I am a visiting scholar at University of Delaware. I am working with Professor Abhuydai Singh in the Electronical and Engineering Department.

I also had the chance to meet with Professor Pak Wing Fok. In addition of sharing a car for our regular trips between philadelphia and Newyark, both of us are sharing similar research interests in bio-physics and stochastic processes.

So far I had the change to give two presentation of my work:

 ———————————– ———————————– ———————————–

February 2015

Department of Mathematical Sciences, University of Delaware :

Analytical Approaches for simple models of Gene Expression

  ———————————– ———————————– ———————————

March 2015

Department of Physics, Virginia Tech, Society of Physics Students :

Birth and Death on Lineland or a purely geometrical model of creation and annihilation of particles