# Distance entre un point et un domaine

**URL:** <https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151>\
**Category:** Development\
**Created:** [July 13, 2021, 7:02am UTC](https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151 "2021-07-13T07:02:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![josephmure](https://yyz2.discourse-cdn.com/free1/user_avatar/openturns.discourse.group/josephmure/32/114_2.png) [@josephmure](https://openturns.discourse.group/u/josephmure)\
**Post date:** [July 13, 2021, 7:02am UTC](https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151/1 "2021-07-13T07:02:51Z")

</div>

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](https://openturns.github.io/openturns/1.17/user_manual/_generated/openturns.Domain.html#openturns.Domain.contains) 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](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.ComposedFunction.html) 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}.

---

<div class="post-metadata">

**Author:** ![KieranDelamotte](https://avatars.discourse-cdn.com/v4/letter/k/ce73a5/32.png) [@KieranDelamotte](https://openturns.discourse.group/u/KieranDelamotte)\
**Post date:** [July 13, 2021, 9:50am UTC](https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151/2 "2021-07-13T09:50:09Z")

</div>

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](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.FieldFunction.html?highlight=fieldfunction)

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

---

<div class="post-metadata">

**Author:** ![JPelamatti](https://yyz2.discourse-cdn.com/free1/user_avatar/openturns.discourse.group/jpelamatti/32/101_2.png) [@JPelamatti](https://openturns.discourse.group/u/JPelamatti)\
**Post date:** [July 13, 2021, 1:27pm UTC](https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151/3 "2021-07-13T13:27:29Z")

</div>

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`](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.Interval.html#openturns.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`](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.MeshDomain.html#openturns.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`](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.DomainUnion.html#openturns.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`](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.DomainIntersection.html#openturns.DomainIntersection) ainsi que pour [`LevelSet`](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.LevelSet.html#openturns.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`](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.Analytical.html?highlight=nearestpoint#openturns.Analytical.getNearestPointAlgorithm) .

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

---

<div class="post-metadata">

**Author:** ![regislebrun](https://yyz2.discourse-cdn.com/free1/user_avatar/openturns.discourse.group/regislebrun/32/154_2.png) [@regislebrun](https://openturns.discourse.group/u/regislebrun)\
**Post date:** [July 14, 2021, 12:08pm UTC](https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151/4 "2021-07-14T12:08:24Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![josephmure](https://yyz2.discourse-cdn.com/free1/user_avatar/openturns.discourse.group/josephmure/32/114_2.png) [@josephmure](https://openturns.discourse.group/u/josephmure)\
**Post date:** [August 17, 2021, 7:57am UTC](https://openturns.discourse.group/t/distance-entre-un-point-et-un-domaine/151/5 "2021-08-17T07:57:48Z")

</div>

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

> <https://github.com/openturns/openturns/pull/1887>
>
> \# Extend \[\`IndicatorFunction\`\](https://7905-40717169-gh.circle-artifacts.com/0/h…tml/user\_manual/\_generated/openturns.IndicatorFunction.html#openturns.IndicatorFunction) to all domains
> 
> Previously, it reimplemented code from \`LevelSet\` and did not work for other \`Domains\`.
> 
> \# New functionality
> Coded in tandem with @JPelamatti 
> \- Domains get a new \[\`computeDistanceToDomain\`\](https://7905-40717169-gh.circle-artifacts.com/0/html/user\_manual/\_generated/openturns.Domain.html#openturns.Domain.computeDistanceToDomain) method (only actually implemented for \`Intervals\` and \`DomainUnions\`)
> \- New \[\`DistanceToDomainFunction\`\](https://7905-40717169-gh.circle-artifacts.com/0/html/user\_manual/\_generated/openturns.DistanceToDomainFunction.html#openturns.DistanceToDomainFunction) coded the same way as \`IndicatorFunction\`.

Pour ce faire, nous nous sommes appuyés sur la classe existante [IndicatorFunction](https://openturns.github.io/openturns/latest/user_manual/_generated/openturns.IndicatorFunction.html).  
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.
