La suite logistique

Une première plongée dans la complexité et le chaos.
14 avril 2018

Je lis présentement Complexity: A Guided Tour, un formidable ouvrage écrit par la scientifique américaine Melanie Mitchell. Je viens d’y apprendre l’existence de la suite logistique, grâce à laquelle j’ai réalisé l’animation ci-dessus. Il s’agit de la plus célèbre équation dans le champ de la théorie du chaos. La voici :

xt+1=Rxt(1xt)

À la base, cette équation sert à modéliser la croissance de la taille d’une population d’une génération à l’autre. Afin de la décortiquer, considérons tout d’abord le taux de natalité d’une population, que l’on nommera TN et calculera ainsi :

TN=vp×1000

v représente le nombre de naissances (dans une année complète, par exemple) tandis que p représente la taille de la population totale. Ceci dit, je me demande si p représente la taille de la population au début ou à la fin de l’année. Est-ce que la population p inclut les nouvelles naissances v ?Le quotient v par p est multiplié par 1000 parce que le taux de natalité s’exprime couramment en pour mille. Le taux de mortalité (TM) se calcule de la même façon mais en remplaçant les naissances par les décès. Une autre notion fondamentale est la capacité porteuse (K) d’un environnement : le nombre maximal d’individus d’une population qu’un environnement peut soutenir. Voici le modèle logistique utilisant ces données et permettant de calculer la taille de la population (n) lors de la génération t :

nt+1=(TNTM)(ntn2tK)

Le nombre d’individus succombant à la surpopulation est représenté par n2tK (chose que je ne comprends pas et qu’il me faudrait investiguer). Maintenant, afin d’en arriver à la simple équation de la suite logistique, il faut d’abord considérer la valeur R, calculée ainsi : R=TNTM. On obtient donc l’équation suivante :

nt+1=R(ntn2tK)

Il faut ensuite diviser chaque côté de l’équation par la capacité porteuse (K) :

nt+1K=R(ntKn2tK2)

Maintenant, chose très intéressante, nous allons représenter ntK (qui est la taille de la population divisée par la capacité porteuse, donc la portion de la capacité porteuse qui est présentement utilisée) par la valeur xt. En remplaçant cette première expression par cette seconde, plus simple, l’on obtient finalement la suite logistique Je trouve amusant de remarquer que le terme « logistique » est ici plutôt arbitraire. Il provient d’un ouvrage du mathématicien français Pierre François Verhulst et, selon Wikipedia, l’auteur « n’explique pas son choix mais “ logistique ” a la même racine que logarithme et logistikos signifie “ calcul ” en grec. » Ce serait difficile de choisir un terme plus imprécis.:

xt+1=R(xtx2t)

On peut réduire cette équation ainsi :

xt+1=Rxt(1xt)

Donc, lorsque xt=0, la population n’occupe présentement aucune part de la capacité porteuse, et lorsque xt=1, elle accapare cette capacité porteuse au complet. La valeur de xt se situe toujours entre 0 et 1, ce qui peut s’exprimer ainsi : xt[0;1].

Une équation au comportement fascinant

Pour réaliser l’animation en tête de cet article, j’ai écrit un court programme me permettant d’explorer les propriétés surprenantes de cette suite logistique. Je trouve important de mentionner que, lors de ces expériences, je ne porte pas nécessairement attention aux origines “réelles” ou “physiques” de cette équation — j’ai ainsi beaucoup aimé ce passage tiré du livre de Mitchell : « Lorsque ce modèle simplifié [la suite logistique] leur est présenté, les scientifiques et les mathématicien·ne·s oublient prestement tout ce qui concerne la croissance des populations, la capacité porteuse, ou toute autre chose reliée au monde réel, et se perdent tout simplement dans le comportement fascinant de l’équation elle-même. Nous ferons la même chose. »

Après plusieurs expériences, j’ai eu l’idée de créer un graphe avec des sommets définis par des variables x et y, auxquelles je donne tout d’abord des valeurs initiales très légèrement différentes :

x0=0.0001y0=0.0002

Ces variables sont ensuites envoyées 1000 fois dans la suite logistique (dans laquelle R=3.58). Le résultat est affiché sur une seule image d’animation, qui contient donc 1000 points. Ensuite, pour la prochaine image, tout est effacé et les variables x et y sont réinitialisées à leur point de départ, cependant ce point de départ est altéré. À chaque nouvelle image, les deux points de départ sont incrémentés de 0.000001. Par exemple, à la deuxième image de l’animation, le système est initialisé de cette façon :

x0=0.000101y0=0.000201

Ainsi, je crois que si l’on considère a comme étant une image d’animation, et t comme étant toujours l’index de récurrence de la suite logistique appliqué à cette image d’animation, on peut dire que chaque image d’animation est initialisée ainsi :

x0a=0.0001+(a×0.000001)y0a=0.0002+(a×0.000001)

Il est intéressant de constater comment cette suite logistique crée des points aux positions aussi fluctuantes à partir de points initiaux si semblables — une notion très importante et bien expliquée par Melanie Mitchell : la « dépendance sensible aux conditions initiales ».

Le code

Voici le code écrit pour réaliser cette animation. Il contient de nombreux éléments qui font partie de mon programme de base à partir duquel je démarre chacune de mes expérimentations ; ces éléments ne sont pas essentiels mais je trouve néanmoins utile de les laisser en place. Le code entier peut-être lu et téléchargé sur GitHub. Il est distribué librement avec une licence Gnu Gpl 3.0.

let looping = true;
let socket, cnvs, ctx, canvasDOM;
let fileName = "./frames/logistic-map";
let maxFrames = 20;
let x, y;
let startX = 0.0001;
let startY = 0.0002;
let r = 3.58;
// 3.569946
let increment = 0;

function setup() {
    socket = io.connect('http://localhost:8080');
    cnvs = createCanvas(windowWidth / 16 * 9, windowWidth / 16 * 9);
    ctx = cnvs.drawingContext;
    canvasDOM = document.getElementById('defaultCanvas0');
    frameRate(30);
    background(0);
    fill(255, 255);
    noStroke();
    if (!looping) {
        noLoop();
    }
}

function draw() {
    x = startX + increment;
    y = startY + increment;
    background(0, 50);
    translate(-320, -320);
    for (var i = 0; i < 1000; i++) {
        ellipse(x * 1100, y * 1100, 2);
        x = logisticMap(x);
        y = logisticMap(y);
    }
    increment += 0.000001;
    if (exporting && frameCount < maxFrames) {
        frameExport();
    }
}

function logisticMap(n) {
    return r * n * (1 - n);
}

function keyPressed() {
    if (keyCode === 32) {
        if (looping) {
            noLoop();
            looping = false;
        } else {
            loop();
            looping = true;
        }
    }
    if (key == 'p' || key == 'P') {
        frameExport(p);
    }
    if (key == 'r' || key == 'R') {
        window.location.reload();
    }
}

Notes éparses

Il sera très intéressant de voir si je peux utiliser cette suite logistique pour modéliser la croissance d’une population de plantes définies algorithmiquement, par exemple. Un espace pourrait être créé où une certaine population maximale de plantes pourrait survivre — et j’utiliserais la suite logistique pour déterminer combien de plantes y poussent. Quant à la définition de la capacité porteuse, elle pourrait se faire de bien des façons ; par exemple, un terrain pourrait être généré avec du bruit de Perlin et ses ressources naturelles pourraient déterminer la population maximale de plantes.

Également, penser à une population et à sa croissance permet aussi de penser à la génétique qui pourrait déterminer l’apparence d’une plante dessinée algorithmiquement : les “gènes” d’une telle plante représentent aussi une population, et la façon par laquelle cette plante enfante une nouvelle plante représente une nouvelle génération de cette population de gènes. Ainsi, chaque plante peut être imaginée comme une population et toutes ces populations font elles-mêmes partie d’une “métapopulation”. Je m’avance beaucoup — il me faudra voir si je peux me servir de ces notions pour créer des formes intéressantes.

Contexte

Cette note de blog fait partie de mon projet de recherche Vers un cinéma algorithmique, démarré en avril 2018. Je vous invite à consulter la toute première note du projet pour en apprendre davantage.