Distance entre un point et un domaine

Dans le cadre du travail mené sur les indices HSIC, il est nécessaire de disposer de “fonctions de poids” qui sont toutes des fonctions de la forme :

f_c = g \circ d_C,

où g est une fonction \mathbb{R} \rightarrow \mathbb{R}, C est une réunion finie d’intervalles inclus dans \mathbb{R}, et d_C est la fonction qui à tout point de \mathbb{R} associe sa distance à C.

Actuellement, tout Domain dispose d’une méthode contains qui renvoie un booléen indiquant si le point fourni en entrée lui appartient. Cette méthode permet donc de traiter le cas particulier où g est constante sur l’intervalle ouvert ]0,+\infty[, quoique de façon maladroite puisqu’on voudrait disposer d’un objet Function permettant de créer une ComposedFunction avec g.

Je propose donc la création d’une méthode Domain::getIndicatorFunction renvoyant une Function telle qu’évaluer cette fonction en un point donné soit équivalent au fait d’évaluer Domain::contains en ce point. À mon avis, cette méthode pourrait être utile dans d’autres contextes que celui des HSIC.

Pour traiter le cas où g n’est pas constante sur ]0,+\infty[, l’idéal serait à mon avis que tout Domain dispose d’une méthode getDistanceToDomainFunction fonctionnant de la même manière que Domain::getIndicatorFunction, mais renvoyant la distance euclidienne au domaine en question. Cependant, cela paraît difficile à faire en toute généralité. @JPelamatti et @KieranDelamotte ont d’autres idées permettant de traiter spécifiquement le cas de domaines réunions finies d’intervalles de \mathbb{R}.

Je reprends une partie de mes échanges avec Julien et Joseph à propos de ce sujet.

Une autre piste serait peut-être d’introduire une classe de fonctions sur
les domaines qui prend en entrée un Domain et un Point (ici on prendrait un
Intervalle) et renvoie un Point (et un Domain?) un peu comme la

FieldFunction

La distance pourrait être obtenue à partir d’une collection de telles fonctions.

Pour compléter ce que dit Joseph, la définition d’une méthode Domain::getDistanceToDomainFunction permettrait de définir des fonctions de poids qui combinent et composent la distance d’un point à plusieurs domaines distincts. Par exemple, une fonction exponentielle negative de la moyenne des distances à une collection de domaines.

Quelques remarques additionelles :

  • Comme dit par @josephmure, l’implémentation de Domain::getDistanceToDomainFunction semble relativement simple dans le cas d’un objet Interval , ce qui est le cas le plus commun que l’on s’attend des applications liées aux indices HSIC. Ceci même en dimension > 1 .
  • De même, l’implémentation d’une distance d’un point à un MeshDomain devrait pouvoir se calculer en itérant sur chaque maille du mesh (avec un coût de calcul potentiellement large).
  • La distance entre un point et un objet DomainUnion devrait pouvoir se calculer de façon recursive en calculant la distance aux différent domaines de l’union
  • Des implémentations plus problématiques peuvent s’envisager par exemple pour DomainIntersection ainsi que pour LevelSet , car dans ces cas-ci, des processus d’optimisation seraient nécessaires afin de déterminer la distance minimale d’un point à un domaine spécifique.
  • Pour une implémentation générique de Domain::getDistanceToDomainFunction , @vchabri suggérait de regarder ce qui est déjà implémenté pour la méthode FORM pour l’identification des points de défaillance, par exemple getNearestPointAlgorithm .

Il me semble que ces considerations restent valables même dans le cadre de la solution alternative proposée par @KieranDelamotte.

Ce que je suggérais lors d’un CT précédent est justement d’implémenter un service Domain::computeDistanceToDomainFunction qui renvoie une NotYetImplementedException par défaut, qui est implémentée pour les classes Interval et DomainUnion. Ca ne serait pas difficile à implémenter efficacement pour MeshDomain grace à KDTree (coût logarithmique en le nombre de noeuds). On pourrait également l’implémenter pour LevelSet soit en résolvant directement le problème d’optimisation soit en s’appuyant sur LevelSetMesher pour se ramener à un MeshDomain. Le tout est d’avoir au minimum ce qui sert pour les HSIC, plus si possible.

Concernant la conversion de méthodes en Function, il faut distinguer les cas où l’on souhaite vraiment fournir cette fonction à l’utilisateur ou si l’on veut cette fonction uniquement en interne de certains algorithmes. Il est tout à fait possible de créer ces fonctions localement (voir par exemple grep -l EvaluationImplementation ~/openturns/lib/src/Uncertainty/Distribution/*cxx) et de les renvoyer à l’utiisateur (voir par exemple GeneralLinearModelAlgorithm::getObjectiveFunction()).

On peut dans la foulée implémenter la méthode Domain::getIndicatorFunction selon le même schéma.

Dans la PR ci-dessous, @JPelamatti et moi avons implémenté la stratégie de @regislebrun.

Pour ce faire, nous nous sommes appuyés sur la classe existante IndicatorFunction.
Je l’ai modifiée de sorte qu’elle puisse s’appliquer à n’importe quel domaine, et non pas seulement un LevelSet comme c’est le cas dans la version 1.17.
Le constructeur de IndicatorFunction accepte maintenant n’importe quel domaine. Son opérateur () délègue la tâche à la méthode contains du domaine.

Suivant le même principe, @JPelamatti a donné une méthode computeDistanceToDomain aux classes Interval et DomainUnion. La classe mère DomainImplementation “implémente” cette méthode en produisant une NotYetImplementedException.

On pourra par la suite implémenter computeDistanceToDomain pour d’autres domaines comme MeshDomain et LevelSet, comme indiqué par @regislebrun.

La nouvelle classe DistanceToDomainFunction fonctionne de manière similaire à IndicatorFunction : le constructeur prend un domaine comme argument (en vérifiant que sa méthode computeDistanceToDomain fonctionne réellement) et l’opérateur () délègue le calcul à la méthode computeDistanceToDomain du domaine.

1 Like