Questions fréquentes

Les 8 questions les plus posées sur le moteur BikeOptim, avec des réponses détaillées.

Quelle est la différence entre BikeOptim et le moteur legacy ? +

BikeOptim est un moteur autonome en CPython, successeur du moteur pyRevit (IronPython) gelé dans legacy/. Il apporte trois avancées majeures :

  • Packing exact (M3) — Résolution par CP-SAT au lieu d'heuristiques
  • Accessibilité garantie (M4) — Graphe de circulation Dijkstra/BFS
  • Optimisation NSGA-II (M5) — Front de Pareto multi-objectif
Le moteur legacy reste disponible comme référence. Les « golden numbers » servent de benchmark.
Pourquoi les unités sont en mètres et pas en pieds ? +

Les fichiers Revit stockent les coordonnées en pieds (unité interne de Revit), mais le moteur BikeOptim travaille exclusivement en mètres.

La conversion est effectuée à l'import (module io). Ce choix est motivé par :

  • Les cotes réglementaires françaises sont en mètres (1,50 m d'allée, 0,38 m d'entraxe…)
  • Plus naturel pour le debug et la visualisation
  • Cohérence avec les bibliothèques scientifiques (numpy, shapely)
1 pied = 0,3048 m → valeur_m = valeur_ft × 0.3048
Comment ajouter une nouvelle pièce ? +

Pour ajouter une pièce au moteur :

  1. Créer un fichier JSON au format bikeoptim-room/1 dans data/rooms/
  2. Les coordonnées doivent être en pieds (Revit) — le moteur les convertira
  3. Inclure : contour, portes, obstacles internes (poteaux)
  4. Ajouter les résultats attendus dans le banc de tests
// Exemple minimal : data/rooms/ma_piece.json { "format": "bikeoptim-room/1", "name": "Local vélo RDC", "boundary": [[0, 0], [20, 0], [20, 15], [0, 15]], "doors": [{"center": [10, 0], "width": 3.28}], "obstacles": [] }
Pourquoi l'optimiseur trouve parfois moins de vélos que le glouton ? +

L'optimiseur maximise la capacité accessible, pas la capacité brute. Un placement glouton peut entasser 35 vélos, mais si 10 sont injoignables depuis les portes, la solution est moins bonne qu'un placement de 28 vélos tous accessibles.

Glouton — 29 vélos

29 places brutes
15 injoignables
= 14 accessibles

Optimiseur — 28 vélos

28 places brutes
0 injoignable
= 28 accessibles ✓

💡
28 vélos accessibles > 29 vélos dont 15 injoignables. La qualité prime sur la quantité brute.
Le moteur gère-t-il les poteaux ? +

Oui. Les poteaux sont modélisés comme des obstacles internes dans le JSON de la pièce.

Le constructeur les évite automatiquement : les emprises vélo doivent être intégralement contenues dans le polygone de la pièce, sans chevaucher aucun obstacle.

  • Les poteaux réduisent la surface utile mais ne bloquent pas le moteur
  • Le graphe de circulation contourne les obstacles
  • Le packing exact (M3) intègre les poteaux comme contraintes de non-chevauchement
Qu'est-ce que le « filet jamais pire » ? +

C'est la garantie que le moteur ne peut jamais produire un résultat inférieur au glouton.

Le mécanisme est simple : pour chaque configuration, deux algorithmes sont évalués en parallèle :

  1. Exact (M3) — Le solveur CP-SAT cherche l'optimum
  2. Glouton (M2) — Le constructeur heuristique place les vélos

On garde le meilleur résultat. Impossible de régresser par rapport à l'heuristique.

résultat = max(exact(g), glouton(g))
Comment fonctionne le déterminisme ? +

Tout aléa dans le moteur passe par un unique générateur : random.Random(seed).

Deux exécutions avec le même seed donnent exactement le même résultat : même population initiale, mêmes mutations, même front de Pareto final.

# Reproductibilité garantie import random rng = random.Random(42) # seed fixe result_a = optimize(room, rng=random.Random(42)) result_b = optimize(room, rng=random.Random(42)) assert result_a == result_b # toujours vrai
🔒
Le déterminisme est essentiel pour le debug, les tests de régression et la reproductibilité scientifique.
Quelles sont les prochaines étapes (M6) ? +

La feuille de route post-M5 inclut :

  • Épi 45° — Support des rangées en épi (angle 45°)
  • Double étage effectif — Racks superposés avec contraintes de hauteur
  • Multi-pièces — Optimisation de plusieurs locaux simultanément
  • Rapport PDF/HTML — Export automatique des résultats
  • Ré-import Revit — Écriture directe du plan dans le modèle BIM
  • CLI — Interface en ligne de commande pour l'intégration CI/CD
🗺️
Ces fonctionnalités sont planifiées mais non encore développées. Les contributions sont bienvenues.

Glossaire

Définitions de tous les termes techniques utilisés dans la documentation BikeOptim.

TermeDéfinition
Emprise Rectangle au sol d'un emplacement vélo, incluant le dégagement nécessaire
Entraxe Distance entre les centres de deux emprises adjacentes dans une même rangée
Bande Une rangée d'emplacements vélo + son allée de desserte associée
Golden numbers Capacités de référence du moteur legacy, utilisées comme benchmark de régression
Glissement Algorithme leftmost-fit pour placer les vélos séquentiellement dans une rangée
Front de Pareto Ensemble des solutions non dominées — aucune autre solution n'est meilleure sur tous les objectifs
Crowding distance Mesure de diversité dans NSGA-II : écart moyen aux voisins sur le front de Pareto
Death penalty Pénalité infinie attribuée à un vélo inaccessible depuis toute porte
CP-SAT Solveur de programmation par contraintes d'OR-Tools, utilisé pour le packing exact
NSGA-II Non-dominated Sorting Genetic Algorithm II — algorithme d'optimisation multi-objectif évolutionnaire
AABB Axis-Aligned Bounding Box — boîte englobante alignée sur les axes, utilisée pour le pré-filtrage de collisions
SAT Separating Axis Theorem — théorème de l'axe séparateur pour la détection exacte de chevauchement entre polygones convexes
DP Dynamic Programming — programmation dynamique, utilisée pour optimiser certains sous-problèmes de placement

Carte des modules

Vue synthétique de l'organisation du code source BikeOptim, avec les fichiers clés de chaque module.

ModuleFichiers clésRôle
bikeoptim.io rooms.py, revit_dump.py I/O — Import JSON et export Revit
bikeoptim.core room_model.py, geometry.py, analysis.py Géométrie — Modèle de salle et opérations spatiales
bikeoptim.catalog systems.py Systèmes — Catalogue des équipements vélo
bikeoptim.solve constructor.py, packing.py, rows.py, zone.py Construction — Placement et packing des emprises
bikeoptim.circulation access.py, connect.py Circulation — Accessibilité et graphe de parcours
bikeoptim.optimize genome.py, phenotype.py, nsga2.py, diversity.py Optimisation — NSGA-II et gestion du front de Pareto
bikeoptim.viz render.py Visualisation — Rendu matplotlib des plans
📂
Convention : chaque module est un package Python avec un __init__.py qui expose l'API publique. Les détails d'implémentation restent privés (préfixe _).
# Structure du projet bikeoptim/ ├── io/ │ ├── rooms.py # Chargement JSON │ └── revit_dump.py # Export Revit ├── core/ │ ├── room_model.py # Modèle de salle │ ├── geometry.py # Opérations géométriques │ └── analysis.py # Analyse de la pièce ├── catalog/ │ └── systems.py # Catalogue de systèmes ├── solve/ │ ├── constructor.py # Constructeur heuristique │ ├── packing.py # Packing exact CP-SAT │ ├── rows.py # Gestion des rangées │ └── zone.py # Découpage en zones ├── circulation/ │ ├── access.py # Analyse d'accessibilité │ └── connect.py # Graphe de connectivité ├── optimize/ │ ├── genome.py # Encodage du génome │ ├── phenotype.py # Décodage phénotype │ ├── nsga2.py # Boucle NSGA-II │ └── diversity.py # Crowding distance └── viz/ └── render.py # Visualisation matplotlib