Skip to content
Snippets Groups Projects
To find the state of this project's repository at the time of any of these versions, check out the tags.
CHANGES.md 25.18 KiB

9 janvier 2025

Modification des sorties [u] pour avoir, à chaque tour, le nombre de vendeurs viables, par type de matière première vendue.

8 janvier 2025

Sorties des traces des simulations, pour les flux de matières premières, les clients et les vendeurs (agrégées au moment des changements de stratégies et en fin de simulation).

27 novembre 2024

Refonte du modèle : introduction des matières premières extraites et recyclées.

27 septembre 2024

Ajout du calcul de pondération en fonction du nombre de clients depuis le début de la simulation (POND_MODE 4), ce qui n'est pas le nombre de ventes (POND_MODE 1).

Ce mode converge très difficilement.

24 septembre 2024

Correction d'un bug : la pondération petits / gros vendeurs omettait la soustraction de la pondération de ce vendeur à la somme des pondérations, lorsqu'il n'y avait pas affaire avec ce vendeur.

17 septembre 2024

Version utilisée pour les diagrammes de la réunion du 24/09/24.

Qualité est devenue continue.

Disparition du seuil, qui devient identique pour tous les vendeurs.

Modifications sur les pondérations :

  • La fidélité est désactivée. Ainsi on peut faire tourner le modèle sans contraintes et ajouter les biais pour observer les changements.
  • Une pondération qui favorise les plus petits vendeurs et les plus gros est activable. Pour le moment basée sur le nombre de ventes depuis le début de la simulation.
    Cette pondération est celle d'une courbe (bx - a)² + c (de mémoire. c'est pê ax-b…), les paramètres a,b,c sont dans la fonction init() des clients.
  • Et on peut désactiver pour n'avoir qu'un tirage aléatoire.

Il est possible d'avoir la trajectoire dans les sorties (c'est vite très verbeux, il faut limiter le nombre de simus).

Tout ça se commande à partir du fichier congig.h qui devient un peu touffu. Mais il est très documenté.

Le tracé de la matrice de transition permet un tracé de courbe de chaleur. Les paramètres ont un peu changé (c'est documenté tant bien que mal).

3 septembre 2024

Version GPU.

Le code a été réécrit en se basant sur les librairies CUDA.

La structure du code a été changée. La boucle principale est dans main.cu.

Les sorties sont sous la même forme que précédemment à quelques petites modifications près ; on retrouve les lignes [i], [t], [b] et [q].

Un seuil_min a été ajouté, qui peut être mis à 0.

Compilation et exécution

Pour commencer, éditer le fichier config.h qui contient les paramètres des simulations. Le fichier est commenté, en espérant que ces commentaires soient suffisamment compréhensibles.

La distribution de la population des clients est dans stats.h qui contient le tableau de la répartition des revenus par ménage en 2018.

# Compilation
nvcc main.cu -o ccsyl

# Exécution avec sortie à chaque tour
./ccsyl | tee resultats.txt | grep '^\[t'

Pistes d'amélioration

L'exécution sollicite la carte graphique et un coeur du processeur. On se rend compte que la partie du processeur comprend ce qui n'est pas parallélisable, et qu'il constitue un nouveau goulot d'étranglement.

Donc toute optimisation à ce niveau a un impact important. En particulier il y a quelques additions de tableaux qui pourraient faire l'objet d'un algorithme de type reduce. Celui-ci est proposé dans les outils CUDA.

23 août 2024

Nouvelle branche

Le commit d'aujourd'hui sera suivi de la création d'une nouvelle branche ; le modèle commençant à se préciser, des simulations en masse sont à prévoir.

Le présent code parallélise les simulations sur les différents cœurs à l'aide de la librairie openmp, mais étant donné que le code des clients est plutôt simple, il serait beaucoup plus efficace de le paralléliser sur un GPU. C'est ce qui sera fait sur la branche master, tandis que la v1 contient le code actuel sur openmp.

Matrices de transition

L'étude des classes de qualité, de marges et de seuils se voit étoffée du tracé des matrices de transition.

Sur l'axe vertical, on a les classes à l'état initial, et sur l'axe horizontal on a les classes à la fin de la simulation. Seules les simulations ayant convergé sont représentées.

Celles-ci sont calculées et tracées dans classes/matrice_transition.scm :

cd classes/

emacs matrice_transition.scm
# Il faut renseigner V : nombre de vendeurs,
# Q : nombre de classes de qualité, et _COL_A_AFFICHER
# (_COL_Q : qualité, _COL_M : Marges et _COL_S : seuils),
# puis :

xzcat ../v5q4-100k-cs0.5.txt.xz | \
  guile -s matrice_transition.scm gnuplot norm | gnuplot

La configuration n'est pas des plus ergonomiques, désolé, je n'avais pas fait de scheme depuis longtemps.

Ici on a utilisé l'argument gnuplot, qui génère une sortie qui peut être directement pipée sur gnuplot pour la visualisation. Sans l'argument gnuplot, on obtient simplement la matirce sur la sortie standard.

L'argument norm normalise la matrice ligne par ligne. Il est également disponible sans le mode gnuplot.

La lecture des arguments est rigide : il faut donner les arguments dans l'ordre et exactement comme attendu.

5 août 2024

Fidélité relative

(Voir le chapitre “choix du vendeur” au 21 juin 2024)

Plutôt que d'utiliser le coefficient de fidélité d'un client pour un vendeur, qui ne tient pas compte de ce coefficient pour les autres vendeurs (et pour le même client), il semble plus intéressant de considérer la probabilité que ce vendeur soit choisi en priorité par ce client.

C'est ce qu'on appelle la fidélité relative du client pour ce vendeur.

Classes de qualités

Le projet est de donner des résultats par « classe de qualité ». On veut, dans les sorties, avoir l'effectif des vendeurs pour chaque qualité.
Exemple :

qualité 1 2 3 4
Simu 1 2 0 1 2
Simu 2 1 1 2 1
Simu 3 1 2 2 0
(…)

On dira que (2, 0, 1, 2) est la classe de qualités de la première simulation.

On espère, sur un nombre de simulations suffisamment important, voir s'il y a des aggrégats et des manques dans les classes de qualités.

À noter qu'on pourra tenter la même chose sur d'autres valeurs que la qualité (il suffira de les discrétiser). Dans un premier temps on discrétisera marge et seuils en autant de valeurs que la qualité.

Sorties

Dans les sorties, les résultats par classes de qualités sont donnés par les lignes commençant par [q].

Parce qu'il est intéressant de comparer la distribution des classes de qualités avant et après la simulation, les classes de qualité de la population telle qu'elle est répartie au début de la simulation sont écrites aussi, dans les colonnes de même nom commençant par I_.

Nombre de simulations

Si on prend Q = nombre de classes de qualité et V = nombre de vendeurs, le nombre de combinaisons possibles n'est pas trivial.

Si on note N_V^Q le nombre de classes pour V vendeurs et Q qualités possibles, on a :

  • N_V^1 = 1
  • N_1^Q = Q
  • N_V^Q = N_{V-1}^Q + N_V^{Q-1}

Pour expliquer cette dernière formule, prenons par exemple D_4^3 (désolé pour l'absence de rigueur dans la notation, il a été choisi de privilégier la compréhension visuelle) :

D_4^3 = \begin{matrix} (0 & 0 & 4)\\ (0 & 1 & 3)\\ &\vdots&\\ (3 & 1 & 0)\\ (4 & 0 & 0) \end{matrix}

En ajoutant une colonne (donc une qualité), on obtient (la séparation en deux est là pour bien distinguer deux parties, mais c'est à lire ligne par ligne, de la même façon qu'au-dessus) :

D_4^{3+1} = \begin{matrix}\begin{bmatrix} 0 & (0 & 0 & 4)\\ 0 & (0 & 1 & 3)\\ \vdots & &\vdots&\\ 0 & (3 & 1 & 0)\\ 0 & (4 & 0 & 0) \end{bmatrix}\\ \begin{Bmatrix} 1 & 0 & 0 & 3\\ \vdots & &\vdots&\\ 1 & 3 & 0 & 0\\ 2 & 0 & 0 & 2\\ \vdots & &\vdots&\\ \end{Bmatrix}\end{matrix}

Dans la partie entre crochets [], on a simplement une colonne de 0 devant D_4^3 (on a laissé les parenthèses exprès pour reconnaître D_4^3). Quant à la partie entre accolades, si on soustrait 1 à toutes les valeurs de la première colonne, on a exactement D_3^4.

Une démonstration plus rigoureuse reste à produire (la propagation récursive d'une hypothèse d'absurdité semble tendre les bras).

Compte-tenu de l'écriture récursive du calcul du nombre de classes, son écriture dans un langage à parenthèses va de soi. Je ne résiste pas à l'envie d'en copier-coller le code (en scheme, donc) :

(define card
  (lambda (v q)
    (if (= q 1)
        1
        (if (= v 1)
            q
            (+ (card v (1- q)) (card (1- v) q))))))

Pour 5 vendeurs et 4 qualités, on a donc 56 classes de qualité. Pour 10 vendeurs on passe à 286 classes.

Le code pour compter les combinaisons de classes est dans un répertoire classes/. Il est composé de classes.scm qui contient les outils pour générer ou compter les combinaisons de classes et de classes_main.scm qui permet de lire les fichiers résultats de simulations.

Combinaisons de classes

Les classes de qualités ne sont pas équiprobables. Par exemple, s'il n'y a qu'une façon d'obtenir la classe (0 5 0 0) (tous les vendeurs vendent la qualité 2), il y a plusieurs façons d'obtenir la classe (4 0 0 1) : soit le vendeur 1 vend la qualité 4 et les autres vendent la qualité 1, soit c'est le vendeur 2 qui vend la qualité 4 et les autres la qualité 1, ….

On a en tout 5 possibilités d'obtenir la classe (4 0 0 1) contre une seule d'obtenir (0 5 0 0). On dira qu'il y a 1 combinaison pour la classe (0 5 0 0) et 5 combinaisons pour la classe (4 0 0 1).

Dans le processus de simulation, les tirages aléatoires rendent équiprobables chaque combinaison. Par conséquent les classes de qualité ne le sont pas. On associe donc aux sorties le nombre de combinaisons à chaque classe de qualité.

Simulations

Voici les paramètres du dernier commit d'aujourd'hui (14 août 2024), à partir desquels on donne les premières interprétations :

  • On fait 10240 simulations, soit 10 fois le nombre de combinaisons de classes.
  • On a 5 vendeurs et 250 clients. C'est peu, notamment pour le nombre de vendeurs, mais il s'agit avant tout de tester.
  • On a 4 qualités possibles, et on discrétisera les seuils et marges en autant de classes.
  • Les vendeurs changent de stratégie après 10 déficits successifs.
  • On termine la simulation après 100 itérations sans déficit, et on limite le nombre de pas de temps à 2100 (2000, mais on refait 100 itérations sans changement de stratégie commerciale avant d'afficher les résultats).
    On a augmenté le nombre d'itérations sans déficit pour s'assurer d'une vraie stabilisation du système avant d'écrire les résultats.
  • Les pondérations des vendeurs sont plafonnées à 50 et un vendeur qui change de stratégie commerciale distribue aléatoirement 2 points de pondération aux clients.
  • Le coefficient de survie des vendeurs est de 0,5. Celui-ci sert à déterminer le seuil maximum, qui est égal à la somme des budgets des clients multiplié par le coefficient de survie et divisé par le nombre de vendeurs.
  • La marge maximum des vendeurs est de 10 (le coût de fabrication étant égal à la qualité, donc entre 1 et 4).
  • Le budget des clients est distribué selon la répartition du plafond de revenus par ménage et par centiles en 2018. Le budget d'un client est strictement supérieur au plus bas coût de fabrication.
  • Les valeurs initiales des vendeurs sont tirées aléatoirement. Précédemment, ceux-ci étaient initialisés aux valeurs maximales. On est passé à un tirage aléatoire pour plusieurs raisons :
    • vérifier dans l'état initial qu'on obtient bien les valeurs théoriques d'effectifs de classes,
    • observer les différences entre les résultats en fin de simulation et les valeurs moyennes pour faire émerger des phénomènes,
    • gommer la prime à l'état initial qui résulte d'une initialisation toujours identique.

Premiers résultats

Étant toujours en cours de développement de l'outil de simulation, il s'agit ici simplement d'observations effectuées sur des simulations effectuées avec des jeux de paramètres allégés. Il est trop tôt pour en tirer des conclusions.

Néanmoins, on a pu observer :

  • une tendance à converger plus facilement dans les classes de faibles qualités (et donc de faibles coût de fabrication),
  • cette même tendance est encore plus forte en ce qui concerne les seuils,
  • en revanche, les classes de marges moyennes sont favorisées.

21 juin 2024

État actuel

On a un truc qui tourne et qui donne des résultats, et on explore.

Fonctionnement

Vendeurs

On a \gamma + 1 (actuellement 5) vendeurs qui vendent des trucs.

Le vendeur i vend des trucs qui ont :

  • une certaine qualité q_i, (q_i \in \{1,2,3,4\});

  • un coût de production c(q_i) (égal à la qualité : produire un truc de qualité 1 coûte 1฿1, 2฿ pour la qualité 2, etc…).

  • Sur un truc, le vendeur i se fait une marge m_i,

  • et du coup il le vend à un certain prix : p_i = m_i + c(q_i).

Pijaca

Pijaca (ou Пијаца, prononcer « piyatsa ») signifie marché en serbe, dans le second sens donné par le Larousse, à savoir « Réunion de commerçants ambulants qui, à jours fixes, vendent dans un lieu dépendant du domaine public des produits comestibles, des articles ménagers, vestimentaires, etc. ».

C'est pour ne pas le confondre avec les 7 autres sens français du mot qu'on utilise le mot Serbe.

Notre pijaca est un marché aux trucs.

Voici les règles du pijaca :

  • Tous les vendeurs sont présents.
  • Tous les clients sont présents.
  • Les vendeurs ont suffisamment de stock de truc pour répondre à toutes les sollicitations des clients.
  • Si un client ne fait pas affaire, c'est parce qu'aucun vendeur n'est en capacité de satisfaire sa demande (le fonctionnement des clients est décrit plus loin).
  • Lorsqu'un client sollicite un vendeur, si celui-ci est en mesure de satisfaire sa demande alors la transaction se fait, au prix du vendeur.

À l'issue du pijaca, tous les clients qui peuvent être satisfaits ont fait affaire.

Vendeurs (suite)

À la fin d'un jour de pijaca, les vendeurs ont vendu un certain nombre de trucs. Si le vendeur i a vendu N_i trucs, il a fait :

  • un chiffre d'affaires Ca_i = N_i * p_i,
  • un bénéfice B_i = N_i.m_i.

Pour que le vendeur i soit viable (c'est-à-dire qu'il peut vivre de son activité commerciale), il faut que son bénéfice soit supérieur à un seuil S_i.

On considère qu'il existe un fond autogéré des vendeurs (le FAVEUR) pour les vendeurs déficitaires. Le règlement du FAVEUR dit qu'au bout d'un certain nombre (10) de jours de pijaca successifs de déficit, le vendeur change sa stratégie commerciale. Quand il en a changé, il faut le même nombre de jours de déficit successifs pour en changer à nouveau.

Stratégie commerciale

Un changement de stratégie commerciale consiste à changer une et une seule de ces trois valeurs :

  • qualité,
  • marge,
  • ou seuil.

Le choix de la valeur à changer se fait de façon aléatoire, avec un tirage équiprobable.

Clients