diff --git a/docs/plans/2026-11-02-comparaison-references.md b/docs/plans/2026-11-02-comparaison-references.md index 9e85935..4dc2aec 100644 --- a/docs/plans/2026-11-02-comparaison-references.md +++ b/docs/plans/2026-11-02-comparaison-references.md @@ -2,7 +2,7 @@ - **Date** : 2026-11-02 - **Étape** : 0a.4 -- **Statut** : en cours +- **Statut** : terminé - **Exécutant** : sous-agent general-purpose, dans un worktree isolé ## Objectif @@ -73,4 +73,48 @@ leur cause, les commandes de vérification. ## Résultat -À remplir à la clôture. +Terminé le 2026-11-02, branche `comparaison-travail`. `make lint` et +`make test` passent (7/7) ; les 32 positions concordent aux deux niveaux +avec la tolérance retenue, sans aucune égalité de meilleur coup à signaler. + +**Fait.** + +- `engine-cli --ply N reference POSITION_ID MATCH_ID [DÉS]` produit un niveau + au format de `tests/reference/` (`evaluation`, puis `moves` ou `cube`). + Nombres écrits avec 9 chiffres significatifs (float32 exact). +- `tests/reference/compare.py` (Python 3) et `tests/test_engine_reference.sh` + (lancé par `make test`) : comparaison dans l'image `ustagammon/build-c:2`, + qui reçoit Python 3 et jq. `tests/test_reference.sh` se relance dans cette + image : plus de jq sur le PC. `CREDITS.md` à jour. +- Critères, tolérance et mesures documentés dans `tests/reference/README.md`. + +**Défauts du moteur embarqué trouvés et corrigés** (`engine/engine.c`) : + +- en match, l'équité des coups classés était convertie deux fois par + `mwc2eq` (`ScoreMove` la convertit déjà) ; +- `engine_best_moves` n'appliquait pas tout `hint` : `fAnalyse` était faux + et `RefreshMoveList` absent (classement par niveau d'évaluation, puis + départage des égalités). + +Changements d'interface : `engine_cube` gagne `optimal` et `decision_text` ; +`decision` prend le nom de l'énumération de gnubg (`DOUBLE_TAKE`…), comme +les références (`tests/test_engine.sh` adapté). + +**Tolérance : 0,002**, sur probabilités et équités. Mesures sur 2 598 +nombres : écart maximal 9,5e-4 et 99 % des écarts sous 1,6e-4, que le moteur +soit compilé avec ou sans `-ffast-math` (les deux builds diffèrent entre eux +de 1,1e-6 au plus). La cause est la sigmoïde de gnubg de bureau en SSE2 avec +`-ffast-math`, qui calcule `1/x` par `_mm_rcp_ps` (environ 12 bits) ; preuve : +le moteur compilé en SSE2 pour l'essai redonne les références au bit près. +L'écart maximal vient d'un seul coup (`opening-64-match`, 2 plis, `8/2 6/2`), +où l'écart de 1e-4 fait basculer un choix discret de la recherche. + +**Critère de divergence vérifié** : sur une copie de `results/` avec une +équité décalée de 0,01, un nombre de coups légaux, une décision de videau et +un meilleur coup modifiés, `compare.py --results ` échoue avec un +tableau de 10 écarts lisibles. + +**Suites possibles** : mesurer de même sur téléphone (NEON, autre +approximation de la division) ; envisager un build SSE2 d'`engine-cli` sur PC +si l'on veut une concordance au bit près (non retenu : le moteur de +l'application tournera en C générique ou en NEON). diff --git a/tests/reference/README.md b/tests/reference/README.md index f7f68ea..3474fa2 100644 --- a/tests/reference/README.md +++ b/tests/reference/README.md @@ -236,7 +236,7 @@ qui produit un objet de même structure que `plies[""]` : `evaluation`, puis `moves` (avec les dés) ou `cube` (sans). Le classement des coups suit la méthode de `hint` décrite plus haut (`engine_best_moves` dans `engine/engine.c`). Pour voir tous les nombres comparés : -`BUILD_C_IMAGE=ustagammon/build-c:2 tests/test_engine_reference.sh --details`. +`BUILD_C_IMAGE=ustagammon/build-c:2 bash tests/test_engine_reference.sh --details`. Une concordance au bit près n'est pas attendue (ADR 0005) : le jeu d'instructions (SSE2 pour gnubg de bureau, C générique pour le moteur diff --git a/tests/test_engine_reference.sh b/tests/test_engine_reference.sh old mode 100644 new mode 100755