Qu’est-ce que ADiMat ?
ADiMat signifie Automatisches Differenzieren für Matlab, c’est donc un programme tournant sous Matlab qui permet de “différencier” (calculer la différentielle, ou “dériver”) n’importe quelle fonction écrite en Matlab, autrement dit une bête boite noire :
function sorties = f(entrees)
% le corps de la fonction
% transformant les entrées en sorties
end
Pourquoi utiliser AdiMat ?
Parce que parfois la fonction \(f\) peut être extrêmement compliquée, et donc la jacobienne très difficile à écrire voir impossible à expliciter. Nous verrons plus loin, après l’installation, un exemple illustrant un cas difficile et la facilité avec laquelle ADiMat fournit une solution.
Installation de ADiMat
1) Télécharger l’archive correspondant à votre système d’exploitation et l’extraire dans votre HOME
(~/
).
tar xzvf adimat-0.5.7-3269-GNU_Linux-x86_64.tar.gz
2) Dans votre dossier d’installation Matlab (chez moi ~/Matlab/
) ouvrez le fichier startup.m
et ajoutez ces deux lignes à la fin :
setenv('ADIMAT_HOME', '~/adimat-0.5.7-3269-GNU_Linux-x86_64');
ADiMat_startup
Ce qui renseignera le chemin vers le dossier d’installation d’ADiMat via la variable d’environnement ADIMAT_HOME
. Et la seconde ligne initialisera le programme ADiMat au démarrage de Matlab.
Parfois le fichier startup.m
ne se trouve pas à la racine du dossier Matlab mais plus profondément dans l’arborescence, pour le localiser placez vous dans le dossier Matlab et tapez simplement :
locate startup.m
3) Placez le fichier de démarrage suivant se trouvant dans votre dossier d’installation ADiMat :
~/adimat-0.5.7-3269-GNU_Linux-x86_64/share/adimat/runtime/ADiMat_startup.m
dans le même dossier Matlab où se trouve startup.m
4) Relancez Matlab, et l’installation est terminée.
Utilisation d’ADiMat
C’est très simple, une fois définie votre fonction \(f\) :
function sorties = f(entrees)
% le corps de la fonction
% transformant les entrées en sorties
end
Le calcul de jacobienne évaluée au point (arg1,...,argN) s
’obtient alors tout simplement par :
J = admDiffFor(@f, 1, arg1, ..., argN)
Matlab vous demande alors si vous l’autorisez à communiquer avec le serveur d’ADiMat, répondez yes.
Si tout se passe bien il devrait vous calculer la matrice jacobienne \(J\). Il se peut que vous obteniez à la place des erreurs, par exemple pour ma part je n’avais pas l’interpréteur /bin/zsh
d’installé, ni la librairie libssl0.9.8
sudo apt-get install zsh
sudo apt-get install libssl0.9.8
Exemple d’utilisation
Pour illustrer l’intérêt de la librairie, je vais traiter un exemple qui m’a sauvé la mise dans le cadre d’un filtrage de Kalman.
On part d’une équation différentielle d’ordre 2 que l’on réduit à l’ordre 1 en considérant 2 variables regroupées dans le vecteur \(\mathbf{Y}=\begin{pmatrix}z\\v\end{pmatrix}\), ainsi l’équation différentielle se réécrit \[\frac{d\mathbf{Y}}{dt}=f(t,\mathbf{Y})\]
Nous discrétisons ensuite l’équation différentielle suivant un schéma de Runge-Kutta d’ordre 4 (RK4) : \[\mathbf{Y}_{n+1}=\mathbf{Y}_n+\frac{h}{6}(k_1+2k_2+2k_3+k_4)\]
avec \[\left\{\begin{array}{l}k_1=f(t_n,\mathbf{Y}_n)\\k_2=f\left(t_n+\frac{h}{2},\mathbf{Y}_n+\frac{h}{2}k_1\right)\\k_3=f\left(t_n+\frac{h}{2},\mathbf{Y}_n+\frac{h}{2}k_2\right)\\k_4=f(t_n+h,\mathbf{Y}_n+hk_3)\end{array}\right.\]
Nous avons relié l’état \(\mathbf{Y}_n\) à l’état suivant \(\mathbf{Y}_{n+1}\) via une certaine fonction \(RK_4\) : \[\mathbf{Y}_{n+1}=RK_4(\mathbf{Y}_n)\]
Dont l’implémentation est bien sûr :
function [z1 v1] = RK4(z,v)
global h cstar
k1 = model(1,[z,v],cstar);
k2 = model(1,[z+h/2*k1(1),v+h/2*k1(2)],cstar);
k3 = model(1,[z+h/2*k2(1),v+h/2*k2(2)],cstar);
k4 = model(1,[z+h*k3(1),v+h*k3(2)],cstar);
z1 = z + h/6*[k1(1)+2*k2(1)+2*k3(1)+k4(1)];
v1 = v + h/6*[k1(2)+2*k2(2)+2*k3(2)+k4(2)];
end
Calculer la jacobienne de la fonction \(RK_4\) à la main est difficile car comme vous pouvez le voir les \(k_i\) sont des composées de la fonction \(f\) avec elle-même. Ce qui signifie que pour calculer : \[J_{(z_n,v_n)}(RK_4)=\begin{pmatrix}\frac{\partial (RK_4)_1}{\partial z}(z_n,v_n) & \frac{\partial (RK_4)_1}{\partial v}(z_n,v_n)\\ \frac{\partial (RK_4)_2}{\partial z}(z_n,v_n) & \frac{\partial (RK_4)_2}{\partial v}(z_n,v_n)\end{pmatrix}\]
vous allez devoir calculer ces dérivées partielles en utilisant plusieurs fois (à 4 niveaux car \(k_4\) est une composée de \(f\) 4 fois) la règle de la chaîne, ce qui est, vous en conviendrez, assez ardu.
ADiMat va faire le travail à votre place en utilisant une technique s’appuyant également sur la règle de la chaîne, à savoir la différentiation automatique. Et en une ligne vous obtenez le résultat escompté :
JRK4(n) = admDiffFor(@RK4, 1, z(n), v(n));