Optimisations

Constant folding

Motivation

Les modèles de calculs écrits en Publicodes sont par design implémentés pour être le plus transparent et intelligible possible pour le plus grand nombre. Cela implique de détailler au maximum les calculs, ce qui peut conduire à une complexité importante des modèles. Cependant, cette complexité n’est justifiée que pour la documentation et non pour le calcul en lui-même.

Par exemple, considérons les règles suivantes :

alimentation . déchets . gestes . bonus compostage biodéchets:
    formule:
        somme:
            - omr . putrescibles . réduction compost
            - (-1) * omr . putrescibles . compostés
    unité: kgCO2e

alimentation . déchets . omr . putrescibles . réduction compost:
    formule: omr . putrescibles * (gisement réduction / quantité réelle)
    unité: kgCO2e

La règle alimentation . déchets . omr . putrescibles . réduction compost dépends de 18 autres règles pour être calculée. Cependant, la valeur ne dépend pas de l’utilisateur·ice et pourrait être calculée à l’avance (c’est une constante). C’est l’objectif de l’optimisation par constant folding : calculer toutes les valeurs qui ne dépendent pas de l’utilisateur à l’avance et remplacer les règles directement par leur valeur.

Ainsi, après optimisation on obtient :

alimentation . déchets . gestes . bonus compostage biodéchets:
    formule:
        somme:
            - 11.505999999999998
            - (-0.4949999999999999)

Usage

L’optimisation par constant folding est disponible dans le module @publicodes/tools/optims via la fonction constantFolding qui prend en paramètre :

  • un moteur Publicodes (instancié avec le jeu de règles à optimiser)
  • un prédicat qui prend en paramètre un couple (nom de la règle, noeud de la règle) et retourne true si la règle doit être conservée après optimisation
  • un objet de paramètres :
    • isFoldedAttr : le nom de l’attribut à utiliser pour marquer une règle comme optimisée (par défaut optimized)

Exemple

import Engine from 'publicodes';
import { constantFolding } from '@publicodes/tools/optims';

const optimizedRules = constantFolding(
    // A publicode engine instantiated with the rules to optimize.
    new Engine(baseRules),
    {
        // A predicate returning true if the rule needs to be kept.
        toKeep: (rule) => {
            return ['root', 'root . bis'].includes(rule.dottedName) || !!rule.rawNode['to keep'];
        }
    }
);