"Vous venez d'utiliser le package `ForwardDiff` pour calculer la Jacobienne de la fonction de tir. Ce package utilise les nombres duaux afin de pouvoir diférencier automatiquement vos fonctions. \n",
"\n",
"Les nombres duaux s'écrivent sous la forme $a + b\\varepsilon$ avec $(a,b)\\in \\mathbb{R}^2$ tels que $\\varepsilon^2 = 0$.\n",
"Les nombres duaux s'écrivent sous la forme $a + b\\, \\varepsilon$ avec $(a,b)\\in \\mathbb{R}^2$ et surtout avec $\\varepsilon^2 = 0$. Nous allons voir comment nous pouvons les utiliser pour calculer des dérivées.\n",
"\n",
"On définit une fonction\n",
"Soit une fonction $f \\colon \\mathbb{R} \\to \\mathbb{R}$ dérivable, de dérivée $f'$. On pose par définition\n",
"On a alors (par définition même) les propriétés suivantes (il restera à vérifier qu'elles sont consistantes). Posons $d = x + \\varepsilon$, alors :\n",
"1. Vérifier la constistance des propriétés ci-dessus.\n",
"2. Soit $f(x) = x^2$. Coder la fonction $f(x)$ et coder sa dérivée à l'aide des nombres duaux. Vérifier le résultat pour $x = 2$ par exemple.\n",
"3. Soit $g(y) = \\cos(y)$. Coder la fonction $h(x) = g \\circ f(x)$ et sa dérivée à l'aide des nombres duaux.\n",
"Que remarquez-vous ? Que devez-vous implémenter pour que cela fonctionne ?\n",
"\n",
"1. Calculer à la main $J_F$ la Jacobienne de $F$.\n",
"**Remarques importantes.** \n",
"\n",
"2. Calculer à la main $F(x + e_1 \\varepsilon )$ et $F(x + e_2 \\varepsilon )$ avec $(e_1, e_2)$ les vecteurs unitaires de la base canonique, et mettre le résultat sous la forme duale. Que remarquez-vous ? \n",
"- Vous utiliserez les fonctions suivantes.\n",
"\n",
"3. Coder ci-dessous $F$ et $J_F$ grâce aux nombre duaux. Calculez $F(x)$ et $J_F(x)$ pour $x = \\left(1, 5 \\right)$. Vérifier le résultat.\n",
"```julia\n",
"d = Dual(x, 1) # crée le vecteur dual x + ϵ\n",
"dualpart(d) # Récupère la partie duale du vecteur d\n",
"```\n",
"\n",
"- En `Julia`, nous pouvons typer les fonctions pour utiliser le \"polymorphisme\" appelé aussi \"multiple dispatch\", ce qui permet de choisir le comportement d'une fonction en fonction du type des arguments. Par exemple :\n",
"\n",
"```julia\n",
"julia> fun(y::Integer) = 2y\n",
"julia> fun(y::Real) = y/2\n",
"julia> fun(2)\n",
"4\n",
"julia> fun(2.0)\n",
"1.0\n",
"```\n",
"\n",
"**Note.**\n",
"**Attention !**\n",
"\n",
"Voici quelques fonctions utiles :\n",
"La fonction $f$ étant déjà définie plus haut, définissez en utilisant une majuscule :\n",
"\n",
"```julia\n",
"a = Dual.(x, e1) # crée le vecteur dual x + e₁ϵ\n",
"dualpart.(a) # Récupère la partie dual du vecteur a\n",
Le but est de résoudre par du tir simple indirect, deux problèmes simples de contrôle optimal dont le contrôle maximisant est lisse.
Le premier problème est en dimension 1 et possède des conditions aux limites simples tandis que le second est en dimension 2 et aura des conditions de transversalités sur le vecteur adjoint.
On propose un dernier exercice sur la dérivation de fonctions par les nombres duaux.
1. Afficher le flot du système hamiltonien associé et afficher 5 fronts aux temps $0$, $0.25$, $0.5$, $0.75$ et $1$ ainsi que quelques extrémales. On utilisera le TP précédent.
2. Coder la fonction de tir
$$
S(p_0) = \pi(z(t_f, x_0, p_0)) - x_f,
$$
où $t_f = 1$, $x_0=-1$, $x_f = 0$ et où $z=(x,p)$ et $\pi(z) = x$. Vous pouvez utiliser votre cours.
3. Afficher la fonction de tir pour $p_0 \in [0, 1]$.
4. Résoudre l'équation $S(p_0) = 0$ et tracer l'extrémale dans le plan de phase, cf. question 1. Vous donnerez une bonne initialisation au solveur de Newton sous-jacent.
Vous venez d'utiliser le package `ForwardDiff` pour calculer la Jacobienne de la fonction de tir. Ce package utilise les nombres duaux afin de pouvoir diférencier automatiquement vos fonctions.
Les nombres duaux s'écrivent sous la forme $a + b\varepsilon$ avec $(a,b)\in \mathbb{R}^2$ tels que $\varepsilon^2 = 0$.
Les nombres duaux s'écrivent sous la forme $a + b\,\varepsilon$ avec $(a,b)\in \mathbb{R}^2$ et surtout avec $\varepsilon^2 = 0$. Nous allons voir comment nous pouvons les utiliser pour calculer des dérivées.
On définit une fonction
Soit une fonction $f \colon \mathbb{R} \to \mathbb{R}$ dérivable, de dérivée $f'$. On pose par définition
2. Calculer à la main $F(x + e_1 \varepsilon )$ et $F(x + e_2 \varepsilon )$ avec $(e_1, e_2)$ les vecteurs unitaires de la base canonique, et mettre le résultat sous la forme duale. Que remarquez-vous ?
1. Vérifier la constistance des propriétés ci-dessus.
2. Soit $f(x) = x^2$. Coder la fonction $f(x)$ et coder sa dérivée à l'aide des nombres duaux. Vérifier le résultat pour $x = 2$ par exemple.
3. Soit $g(y) = \cos(y)$. Coder la fonction $h(x) = g \circ f(x)$ et sa dérivée à l'aide des nombres duaux.
Que remarquez-vous ? Que devez-vous implémenter pour que cela fonctionne ?
3. Coder ci-dessous $F$ et $J_F$ grâce aux nombre duaux. Calculez $F(x)$ et $J_F(x)$ pour $x = \left(1, 5 \right)$. Vérifier le résultat.
**Remarques importantes.**
- Vous utiliserez les fonctions suivantes.
```julia
d=Dual(x,1)# crée le vecteur dual x + ϵ
dualpart(d)# Récupère la partie duale du vecteur d
```
- En `Julia`, nous pouvons typer les fonctions pour utiliser le "polymorphisme" appelé aussi "multiple dispatch", ce qui permet de choisir le comportement d'une fonction en fonction du type des arguments. Par exemple :
```julia
julia>fun(y::Integer)=2y
julia>fun(y::Real)=y/2
julia>fun(2)
4
julia>fun(2.0)
1.0
```
**Note.**
**Attention !**
Voici quelques fonctions utiles :
La fonction $f$ étant déjà définie plus haut, définissez en utilisant une majuscule :
```julia
a=Dual.(x,e1)# crée le vecteur dual x + e₁ϵ
dualpart.(a)# Récupère la partie dual du vecteur a