Example

Two examples are provided in BTIDG2:
  1. using the hard-coded brain structure to generate a matrix of a user-defined size

  2. using the user provided brain structure confiuration file to generate a brain matrix

Hard-coded Brain

The workflow of using a hard-coded brain structure is as follow:

1. Initialize the MPI environment

//Initialisation MPI
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

int q = sqrt(size);
int npr; //number of row in the 2D MPI grid
int npc; //number of column in the 2D MPI grid
npr = q;
npc = q;

long long n = 64; //size of matrix to be generated
long nbRow = n/npr;
long nbCol = n/npc;

/*
    for the hard-coded brain sturcture,
        1. MPI 2D grid is expected to be square,
        2. n is divisible by npr, and npc
        3. n is divisble by 8
*/

2. Fetching a hard-coded example brain

Brain brain = generate_hard_brain(n);

//display the brief info of generated brain structure
if (my_rank == 0 && debug)
{
    printf_recap_brain(&brain);
}

3. Initialize the distribution of sparse matrix

struct MatrixDist MatrixDist;
MatrixDist = initMatrixDist(my_rank, npr, npc, n);
if (my_rank == 0 && debug)
{
    printf("----------------------\nInfo of your matrix :\n");
    printf("Size : %li * %li = %li\n",n,n, n * n);
    printf("%i blocks on rows (with %li lines per block) and %i blocks on columns (with %li columns per block)\n",npr,nbRow,npc,nbCol);
}

4. neuron types random choice

int *neuron_types;
neuron_types = (int *)malloc(n * sizeof(int)); //vector which will contain the types of all the neurons

//choice of neuron type for each neuron in the brain
if (MatrixDist.indc == 0) //choice of processes that will randomly choose the types of neurons
{
    generate_neuron_types(&brain, MatrixDist.indl*nbRow, nbRow, neuron_types + MatrixDist.indl*nbRow);
}

//redistribution of selected neuron types to other processes
for (int i = 0; i < npr; i++)
{
    MPI_Bcast(neuron_types + i * nbRow, nbRow, MPI_INT, i * npc, MPI_COMM_WORLD);
}

5. generation of brain matrix

Below is the step of the generation of a brain matrix, which is stored in A_CSR.

struct csr A_CSR;

struct BrainMatrixInfo MatrixDebugInfo;
brainAdjMatrixCSR(&A_CSR, MatrixDist, &brain, neuron_types, &MatrixDebugInfo);

6. clean up

free_brain(&brain);
free(neuron_types);
free(A_CSR.Row);
free(A_CSR.Column);
free(A_CSR.Value);
free(MatrixDebugInfo.nb_connections);

Configured Brain

BTIDG2 provides a parser based on Python which is able to convert a formatted JSON configure file to a C header file with user desgined brain structure.

1. JSON config file

Here’s an example of JSON configuration file, which determines two different connected brain parts.

[
        {
                "namePart": "part1",
                "id": 0,
                "connectionOpposite" : 0.2,
                "distribution": [0.8,0.2],
                "nbTypeNeuron": 2,
                "nbNeuron": 10,
                "typeNeuron":[
                        {
                                "name": "A",
                                "nbNeuron": 7,
                                "nbConnection": 2
                        },
                        {
                                "name": "B",
                                "nbNeuron": 3,
                                "nbConnection": 5
                        }
                ]
        },
        {
                "namePart": "part2",
                "id": 1,
                "connectionOpposite" : 0.2,
                "distribution": [0.25,0.75],
                "nbTypeNeuron": 1,
                "nbNeuron":5,
                "typeNeuron":[
                        {
                                "name": "C",
                                "nbNeuron": 5,
                                "nbConnection": 6
                        }
                ]
        }
]
The description of the parts are:
  • Distribution: a table that contains the probabilities of distribution to the other parties. At index 0 connection to the part of index 0. The table contains the internal connections between the same part

  • connectionOpposite: probability of connection to the opposite side of the brain (left/right).

  • typeNeuron: a dictionary table corresponding to the neuron present in the part of the brain.

  • nbNeuron: the number of neurons.

  • nbConnection: the number of connections of a neuron.

  • id, namePart, name: fields for humans, they are only used to identify themselves.

2. convert JSON file to C header

Assume that the config file is littleConfigTest.json, a C header file littleConfigTest.h can be generated within the same folder through the following converter.

python ${BTIDG2_ROOT}/translator/converter.py ittleConfigTest.json

The generated header file is as below:

int get_nb_part(){
        return 4;
}

void destoryBrain(Brain *Cerveau){
        free(Cerveau->brainPart[0].repartitionNeuronCumulee);
        free(Cerveau->brainPart[0].probaConnection);
        free(Cerveau->brainPart[1].repartitionNeuronCumulee);
        free(Cerveau->brainPart[1].probaConnection);
        free(Cerveau->brainPart[2].repartitionNeuronCumulee);
        free(Cerveau->brainPart[2].probaConnection);
        free(Cerveau->brainPart[3].repartitionNeuronCumulee);
        free(Cerveau->brainPart[3].probaConnection);
        free(Cerveau->parties_cerveau);
        free(Cerveau->brainPart);
}

void paramBrain(Brain *Cerveau, long long *n){
        int nbTypeNeuronIci,nb_part=4;
        *n=15;
        BrainPart *brainPart = malloc(sizeof(BrainPart)*nb_part);
        long long *part_cerv = malloc(sizeof(long long)*nb_part);
        part_cerv[0] = 0;
        part_cerv[1] = 5;
        part_cerv[2] = 7;
        part_cerv[3] = 12;
//partie 0
        brainPart[0].nbTypeNeuron = 2;
        brainPart[0].repartitionNeuronCumulee = malloc(sizeof(double)*2);
        brainPart[0].repartitionNeuronCumulee[0] = 0.7;
        brainPart[0].repartitionNeuronCumulee[1] = 1.0;
        brainPart[0].probaConnection = malloc(sizeof(double)*8);
        brainPart[0].probaConnection[0] = 0.08533333333333334;
        brainPart[0].probaConnection[1] = 0.021333333333333336;
        brainPart[0].probaConnection[2] = 0.021333333333333336;
        brainPart[0].probaConnection[3] = 0.005333333333333334;
        brainPart[0].probaConnection[4] = 0.21333333333333337;
        brainPart[0].probaConnection[5] = 0.053333333333333344;
        brainPart[0].probaConnection[6] = 0.053333333333333344;
        brainPart[0].probaConnection[7] = 0.013333333333333336;
//partie 1
        brainPart[1].nbTypeNeuron = 1;
        brainPart[1].repartitionNeuronCumulee = malloc(sizeof(double)*1);
        brainPart[1].repartitionNeuronCumulee[0] = 1.0;
        brainPart[1].probaConnection = malloc(sizeof(double)*4);
        brainPart[1].probaConnection[0] = 0.08000000000000002;
        brainPart[1].probaConnection[1] = 0.24000000000000005;
        brainPart[1].probaConnection[2] = 0.020000000000000004;
        brainPart[1].probaConnection[3] = 0.06000000000000001;
//partie 2
        brainPart[2].nbTypeNeuron = 2;
        brainPart[2].repartitionNeuronCumulee = malloc(sizeof(double)*2);
        brainPart[2].repartitionNeuronCumulee[0] = 0.7;
        brainPart[2].repartitionNeuronCumulee[1] = 1.0;
        brainPart[2].probaConnection = malloc(sizeof(double)*8);
        brainPart[2].probaConnection[0] = 0.021333333333333336;
        brainPart[2].probaConnection[1] = 0.005333333333333334;
        brainPart[2].probaConnection[2] = 0.08533333333333334;
        brainPart[2].probaConnection[3] = 0.021333333333333336;
        brainPart[2].probaConnection[4] = 0.053333333333333344;
        brainPart[2].probaConnection[5] = 0.013333333333333336;
        brainPart[2].probaConnection[6] = 0.21333333333333337;
        brainPart[2].probaConnection[7] = 0.053333333333333344;
//partie 3
        brainPart[3].nbTypeNeuron = 1;
        brainPart[3].repartitionNeuronCumulee = malloc(sizeof(double)*1);
        brainPart[3].repartitionNeuronCumulee[0] = 1.0;
        brainPart[3].probaConnection = malloc(sizeof(double)*4);
        brainPart[3].probaConnection[0] = 0.020000000000000004;
        brainPart[3].probaConnection[1] = 0.06000000000000001;
        brainPart[3].probaConnection[2] = 0.08000000000000002;
        brainPart[3].probaConnection[3] = 0.24000000000000005;
        Cerveau->dimension = *n;
        Cerveau->nb_part = nb_part;
        Cerveau->parties_cerveau = part_cerv;
        Cerveau->brainPart = brainPart;
}

3. Usage of generated header file

The first step is to include the generated header file, here littleConfigTest.h, in your source code.

The most steps of generation is the same as the one with hard-code examples. However, in this example the size of matrix to be generated should be extracted from littleConfigTest.h, rather than using any size defined by users.

#include "littleConfigTest.h"

....

Brain brain;
//construct a brain structure and get the matrix size
//to be generated.
paramBrain(&brain, &n);

...