APL contre MATLAB
Charles HUBERT
Introduction
Dans cet article je compare les deux langages de programmation APL et MATLAB. Il existe entre eux de nombreuses différences qui influent beaucoup sur leur efficacité pratique ; mais pour ne pas lasser le lecteur je me suis limité à un petit nombre de ces différences permettant de se faire une idée.
Si MATLAB n'utilise guère que les caractères ASCII, au contraire APL se sert de caractères spéciaux (souvent des idéogrammes) plus faciles à retenir que les nombreux symboles de fonctions ou les mots réservés de MATLAB.
Dans la suite, les exemples dans les deux langages seront repérés par
MATLAB et APL
Si certaines fonctions de ma composition interviennent, ces repères deviendront
MATLAB/HUB et APL/HUB
Souvent apparaîtront côte à côte une même fonction en MATLAB et en APL afin de les comparer.
Les réponses de MATLAB sont souvent bavardes ; celles d'APL ne contiennent que l'essentiel ou que les détails qu'on a demandés. La manipulation de la zone de travail (workspace) est beaucoup plus facile en APL qu'en MATLAB.
Les symboles
Les deux langages contiennent des fonctions que nous appellerons primitives parce qu'ils les connaissent sans avoir à les définir : par exemple l'addition "+".
En MATLAB les primitives qui ne sont pas représentées par un ou plusieurs caractères spéciaux le sont par des symboles construits de la même façon que les symboles créés par le programmeur (exemple "size"). Celui-ci ne peut pas utiliser ces symboles, ni les mots réservés (exemple "if"), pour autre chose.
En APL une
fonction ou une variable primitive est représentée, ou bien par un caractère
spécial (exemple : multiplication ), ou bien par un mot préfixé par le
caractère spécial
(quad, exemple : date et heure
= time stamp).
Le nom d'une fonction ou d'une variable primitive contient toujours un
caractère spécial ce qui empêche tout conflit avec un objet créé par le
programmeur. Il n'y a pas de mot réservé.
Pendant un travail en MATLAB, une fonction "truc" (par exemple) est un fichier du même nom "truc.m" sur le disque dur. Comme c'est le nom du fichier qui compte, la fonction pourra être appelée par "TRUC" ou "Truc" ou "tRuC",... car la gestion des fichiers confond les majuscules et les minuscules ; de plus si on a remplacé "truc" par "machin" dans la ligne "function" du fichier "truc.m", MATLAB considérera qu'il s'agit toujours de la fonction "truc" et non de la fonction "machin".
Pendant un travail en APL, une fonction "truc" (par exemple) se trouve en mémoire vive (RAM). Alors "truc" ou "TRUC" ou "Truc" ou "tRuC" sont autant de fonctions différentes car APL distingue les majuscules et les minuscules. On peut en profiter pour placer une majuscule au premier caractère de chacun des mots qui composent un symbole, ce qui améliore la lisibilité ; par exemple "RacPol" signifie Racines de Polynômes.
En MATLAB, les variables se placent à deux niveaux : local (privé) et global (public). Une variable globale est accessible partout où elle figure dans une déclaration "global". Si elle ne figure pas dans une déclaration "global", elle n'est accessible que dans la fonction où elle est affectée. La déclaration "global" équivaut à la déclaration "common" du fortran.
En APL, les variables et fonctions se placent dans une arborescence dynamique. On déclare les symboles (variables et fonctions) locaux à une fonction ("Fonc" par exemple) dans sa ligne de définition. Les objets désignés par ces symboles sont accessibles dans "Fonc" et dans toute autre fonction que "Fonc" appelle directement ou indirectement, qui les traite alors comme globaux. Ces objets sont inaccessibles avant d'entrer dans "Fonc" ou après en être sorti. Cette organisation arborescente des symboles rend de grands services en APL. En MATLAB il faut s'en passer.
APL offre la
possibilité de numéroter (indicer) les composantes d'un vecteur à partir de
zéro ou un. La variable primitive (index origin) désigne
cette origine ; on peut la choisir par
ou
. Dans la pratique, l'origine zéro
simplifie la programmation plus souvent que l'origine un.
Un algorithme simple
Le but de
cet exemple est de comparer les deux versions d'une fonction qui utilise la
même méthode pour calculer des nombres bien connus. Partons de la définition
suivante : un nombre premier est un entier naturel dont le nombre de
diviseurs est égal à 2. L'entier n>0 étant donné, il faut calculer la
liste des nombres premiers en programmant cette définition. Voici
les deux fonctions :
Pour être raisonnable limitons-nous à 500 :
La fonction "Prem" est plus longue en MATLAB qu'en APL ; MATLAB encombre sa réponse de commentaires inutiles.
La liste des valeurs différentes dans un
tableau
Voici une
fonction qui donne la liste des valeurs différentes contenues dans un tableau
dans l'ordre où elles s'y trouvent.
Exemple :
Les données
étant rangées dans un ordre différent dans les deux langages, il faut
transposer l'argument d'un côté ou de l'autre pour retrouver les résultats dans
le même ordre :
La
transposition s'écrit en APL : elle fait tourner
la matrice autour de
sa diagonale
La fonction "ValDif" est plus longue en MATLAB qu'en APL.
Huit dames sur un échiquier
Il s'agit de
disposer sur un échiquier huit dames mutuellement imprenables. Rappelons que
l'échiquier est une table carrée de cases ; il faut y placer huit
dames (pièces du jeu) de manière qu'il y ait une dame sur chaque ligne, une
dame sur chaque colonne, au plus une dame sur chaque parallèle aux deux
diagonales ("\" et "/").
La fonction
"dame" en MATLAB donne toutes les solutions sous la forme d'une
matrice dont chaque colonne décrit une solution en indiquant, pour chaque ligne
de l'échiquier, le numéro de la case que la dame doit y occuper. La fonction
"Dame" en APL donne la même chose sous la forme transposée de la précédente,
les cases étant numérotées à partir de zéro au lieu de un. Le côté de
l'échiquier n'a pas d'importance pour l'algorithme ; on peut choisir une
autre valeur que 8, c'est l'argument "n". Voici les deux
fonctions :
Pour
faciliter la comparaison des deux résultats, on ajoute 1 à la solution APL
et on la transpose. Exemple pour la dimension 5 :
Une fonction "Visu" permet de visualiser ces solutions :
Parmi les
solutions qui ne diffèrent entre elles que par une symétrie du carré, une
fonction "NonSym" n'en retient qu'une :
La fonction "Dame" est plus longue en MATLAB qu'en APL.
La dimension des tableaux
En MATLAB les données sont des tableaux (arrays) dont la dimension comporte au moins deux nombres ; ce sont au moins des matrices. Un vecteur est une matrice ou bien à une ligne, ou bien à une colonne. Un scalaire est une matrice à une ligne et une colonne. La dimension peut comporter plus de deux nombres ; MATLAB parle alors de matrice multidimensionnelle.
En APL c'est la même chose, sauf que la dimension comporte un nombre pour un vecteur et zéro nombre pour un scalaire.
MATLAB parcourt les tableaux en faisant varier les premiers indices plus vite que les derniers (comme le fortran) : il écrit verticalement puis, quand la colonne est pleine, passe à la colonne suivante.
APL fait l'inverse : il écrit horizontalement puis, quand la ligne est pleine, passe à la ligne suivante, comme dans un texte français (ou anglais,...) normal.
Un tableau
de dimension "3 4 5 6" est vu par MATLAB comme
6 paquets de 5 matrices de 4 colonnes de 3 cases, par APL
comme 3 paquets de 4 matrices de 5 lignes de 6 cases. Pour
visualiser le même tableau de la même façon, il faut le transformer par une des
deux fonctions :
En MATLAB
"visapl" simule comment APL présente un tableau ; en APL
"VisMtl" simule comment MATLAB présente un tableau. Elles sont en
quelque sorte inverses l'une de l'autre. Dans les exemples "Dim"
construit en APL un tableau suivant les conventions de MATLAB.
Matrice de dimension "3 5" :
Notons qu'APL redimensionne 99 valeurs en ne prenant que les
15 premières valeurs.
Tableau de dimension "3 5 2" :
Tableau de dimension "3 5 3 2" :
Dans MATLAB
on trouve les fonctions "size", "reshape" (pourquoi pas
resize ?), "zeros", "ones". En s'y prenant autrement,
une seule fonction "dim" aurait pu faire tout cela, et même un peu
plus : c'est ce que la primitive "ρ" (rho) fait
en APL. On peut programmer "dim" en MATLAB ; la voici
accompagnée de la fonction "Dim" qui simule la même chose en APL en
tenant compte de la convention de rangement des valeurs par MATLAB :
Quand on travaille en APL, on n'a pas besoin de "Dim" puisque
avec son arrangement des données la primitive "ρ"
suffit :
Quand on
l'appelle avec un argument, "dim" donne sa dimension, c'est ce que
"size" fait. Considérons :
alors :
Changeons la dimension de "a" :
mais :
"reshape" exige que l'argument "a" contienne le même nombre
de valeurs que le résultat.
Quand on
l'appelle avec deux arguments, "dim" construit une matrice dont la
dimension est décrite par le deuxième argument, en prenant cycliquement ses
valeurs dans le premier argument ; "dim" n'exige pas que
l'argument "a" contienne le même nombre de valeurs que le résultat.
Pour faire la même chose il faut dans un langage ou dans l'autre retourner la
dimension et transposer l'argument et le résultat, ce que la fonction
"Dim" fait :
ou bien :
ou bien :
ou encore :
Avec
"dim", les fonctions "zeros" et "ones" deviennent
superflues :
Ces exemples montrent qu'une fonction MATLAB bien conçue aurait pu en remplacer plusieurs pour faire la même chose avec moins de limitation.
Le produit des polynômes
Dans MATLAB
il existe une fonction "conv" qui multiple deux polynômes. Pourquoi
"conv" ? Parce que le produit de deux polynômes se ramène à un
produit de convolution. Par souci de pédagogie, je préfère dire l'inverse. En
APL/HUB c'est "PolMul". Mais "conv" ne multiplie que deux
polynômes ; au-delà il faut itérer l'opération :
Il faut donc écrire :
ou programmer une boucle :
mais l'argument de "prodpoly" doit être un vecteur de cellules.
Cet exemple révèle l'impossibilité en MATLAB de répéter simplement une opération "conv" sur plusieurs données "a b c d". En APL la fonction "prodpoly" est superflue car la primitive "/" distribue la fonction "PolMul" entre les cases du vecteur gigogne "a" sans avoir rien à programmer.
Et la somme des polynômes ?
En MATLAB il
faut programmer une fonction, par exemple ;
Le choix par MATLAB de ranger les coefficients suivant les puissances décroissantes est maladroit. Afin de placer les coefficients de la même puissance sur la même colonne la fonction "sompoly" range les coefficients de chaque polynôme suivant les puissances croissantes par "fliplr", puis, en fin de calcul, range les coefficients de la somme suivant les puissances décroissantes par "fliplr" pour que le résultat respecte la convention de MATLAB, comme les cases de l'argument. Notons aussi que "sum" fait la somme des lignes d'une matrice, sauf si elle ne contient qu'une ligne auquel cas elle fait la somme des colonnes ; c'est pour contourner cette exception gênante que "sompoly" initialise la copie des polynômes à deux lignes nulles.
En APL, où
on range les coefficients suivant les puissances croissantes, on peut
construire facilement l'instruction qui calcule la somme,
"DISP" étant une fonction APL/HUB qui visualise la structure
d'un tableau :
Pour ajouter ou multiplier un nombre quelconque de polynômes en MATLAB il a fallu programmer deux fonctions ; en APL il n'y a rien à programmer, quelques caractères suffisent.
Le produit matriciel dans les tableaux
En MATLAB on peut calculer le produit de deux matrices par la notation "a*b". Mais cela ne s'étend pas à des tableaux de plus de deux dimensions.
En APL ce
produit s'écrit et
fonctionne sur des tableaux de dimensions quelconques. Par exemple si
"a" a 3 dimensions et "b" en a 4, on aura :
Voici une
fonction "tabprod" qui, en MATLAB, fait la même chose que la
combinaison de primitives d'APL :
Par exemple, considérons un premier argument :
puis un deuxième argument :
et calculons le produit défini comme en APL :
Comparons les résultats :
Si le
produit de matrices s'écrit en APL, c'est parce que chaque valeur du
résultat est une somme
de produits
. C'est un cas particulier d'un concept
général : celui de "f.g" où "f" et "g"
sont deux fonctions quelconques calculant sur deux scalaires. Par exemple la
combinaison
calcule
des produits
de puissances
;
si on veut calculer :
on peut construire la matrice des exposants :
placer dans les variables "x" et "a" les valeurs
et l'expression
calcule alors "p".
De nombreuses fonctions mathématiques de MATLAB sont restreintes aux seules matrices.
La structure des données
En MATLAB les données sont des tableaux (arrays) dont la dimension comporte au moins deux nombres ; ce sont au moins des matrices. Un vecteur est une matrice, ou bien à une ligne, ou bien à une colonne. Un scalaire est une matrice à une ligne et une colonne. La dimension peut comporter plus de deux nombres ; MATLAB parle alors de matrice multidimensionnelle. Toutes les cases d'un même tableau doivent être de même type : logique, nombre, caractère, structure ou cellule (tableau) et ce type ne change que si on réaffecte le tableau tout entier. Si on affecte dans un tableau des valeurs de type différent, MATLAB convertit cette valeur s'il sait le faire, c'est-à-dire entre logique, nombre et caractère. Si les cases d'un tableau contiennent des caractères on peut y faire des opérations mathématiques : ajouter 10 aux caractères ! les multiplier par 3 ! les diviser par 2 ! etc... Si les cases d'un tableau contiennent des cellules ou des structures les opérations mathématiques sont interdites au tableau entier ; pour cela il faut sortir du tableau le contenu de chaque case pour faire le calcul.
En APL les
données sont aussi des tableaux, mais la dimension comporte un seul nombre pour
un vecteur et zéro nombre pour un scalaire, et aussi deux nombres pour une
matrice, trois nombres pour un paquet de matrices, etc... Chaque case peut
contenir, indépendamment des autres cases, un nombre, ou un caractère, ou un
tableau ; dans ce dernier cas il s'agit d'un tableau gigogne ; ainsi
les cases d'un même tableau peuvent être de types différents. Si on affecte
dans un tableau des valeurs de type différent, aucune conversion n'intervient.
Il n'y a donc qu'une seule structure de donnée, qui permet de faire tout ce qui
nécessite des structures différentes en MATLAB. Toutes les fonctions primitives
d'APL s'appliquent à ces tableaux, à tous les niveaux, sous réserve de
compatibilité de dimension, logique, mathématique (on ne peut pas ajouter 10 à
des caractères...), etc...
Exemple de conversion de caractères en nombres :
Exemple de conversion de nombres en caractères :
Exemples d'interdiction ; soit une variable :
elle ne contient que des nombres auxquels MATLAB ne peut pas
ajouter 10 :
Soit une autre variable :
Ces deux variables ne contiennent que des nombres, mais MATLAB ne peut pas les
ajouter :
tandis qu'APL sait faire tout cela.
L'utilisation
convenable de cette propriété des données APL dans la programmation de la
fonction "PolMul" permet la répercussion d'une valeur multiple sur le
produit des polynômes :
c'est-à-dire :
d'où le produit :
Ce travail est plus lourd en MATLAB, puisqu'il faut créer trois polynômes "a" et les multiplier par "b" un par un dans une boucle de programme.
L'unique structure des données APL est plus puissante et plus facile à manier que les diverses structures de données MATLAB.
Un polynôme et ses racines
MATLAB décrit un polynôme suivant les puissances décroissantes ; alors :
"poly" construit un polynôme dont on donne les racines,
"roots" calcule les racines d'un polynôme.
Construisons
ainsi un polynôme de degré 6 :
puis calculons ses racines :
APL/HUB
décrit un polynôme suivant les puissances croissantes : ainsi l'indice, en
origine zéro, de chaque coefficient est égal à l'exposant de la variable pour
le terme correspondant. Quand des nombres complexes sont susceptibles
d'intervenir on les représente par leurs deux composantes ; on représente
les vecteurs réels soit par une colonne (partie réelle), soit par deux, la
deuxième (partie imaginaire) étant nulle. "PolRac" calcule un Polynôme
(ou plusieurs) dont on donne les Racines : "RacPol" calcule
les Racines d'un Polynôme (ou plusieurs). On obtient alors :
Jusqu'ici tout va bien.
En MATLAB
"ones" construit une matrice pleine de "1" ;
faisons le même exercice pour un polynôme dont les 6 racines
valent 1 :
tandis que :
L'algorithme de MATLAB s'en tire bien quand c'est facile, les choses se gâtent quand c'est difficile ; celui d'APL/HUB calcule juste dans tous les cas.
Considérons
maintenant le tableau à trois dimensions "p" qui contient deux
polynômes et exécutons :
Au lieu de calculer les racines des deux polynômes :
et
il met bout à bout leurs coefficients, sans broncher, et calcule les racines du
polynôme ainsi obtenu :
comme le prouve le calcul en APL/HUB. Absurde !
MATLAB ne prend pas assez de précautions pour garantir la précision de certains calculs ; il peut faire des calculs qui n'ont aucun sens.
Fonctions de MATLAB superflues en APL
Il existe dans MATLAB de nombreuses fonctions primitives dont APL se passe sans inconvénient.
D'abord APL a choisi d'abandonner les conventions d'écriture mathématique. C'est une habitude qu'on prend assez vite.
Toutes les
fonctions ont la même syntaxe. Il y a trois types de fonctions : à zéro,
un ou deux arguments. Par exemple si "F0" n'a pas d'argument,
"F1" en a un "x" et "F2" en a deux "x"
et "y", on les appelle par les expressions :
On a la correspondance :
et ici la fonction "F1" en APL a un argument droit subdivisé en trois
sous-arguments "a", "b", "c". Dans
l'expression :
la fonction "F2" a deux sous-arguments gauches
"a", "b" et trois sous-arguments droits
"c", "d", "e" ; il n'y a pas de
correspondance en MATLAB où il faut se débrouiller autrement. Tout comme le
signe de multiplication se place entre deux nombres, la fonction
"PolMul" se place entre deux polynômes :
En APL la syntaxe est la même ; en MATLAB quand on passe des nombres aux
polynômes, il faut changer de syntaxe.
Ensuite APL
a abandonné toute priorité d'exécution, comme multiplication avant
addition ; seule subsiste la priorité des parenthèses. Pour diverses
raisons, une instruction ou l'intérieur d'une parenthèse s'exécutent de droite
à gauche :
Si MATLAB, fortran, C... exécutaient vraiment de gauche à droite, on n'écrirait
pas
s = a*x +
b*y + c*z
mais
a*x + b*y
+ c*z = s
comme avec une calculette.
Puis APL
dispose de primitives, appelées opérateurs, qui prennent une ou plusieurs
fonctions comme arguments. Ainsi la réduction répète sa fonction de gauche entre les
colonnes (suivant la dernière dimension) de son argument droit ; nous
avons vu cela dans :
La réduction fait
la même chose suivant la première dimension. Exemples de fonctions MATLAB
superflues en APL :
et :
Le balayage ou
permet par exemple :
De nombreuses fonctions de MATLAB sont superflues en APL ; celui-ci les remplace par des combinaisons simples de primitives qui indiquent clairement ce qu'elles font.
Fonctions primitives APL absentes de MATLAB
Il existe
dans APL des fonctions sans équivalent dans MATLAB. Il y a d'abord les
fonctions qui travaillent sur les tableaux gigognes. Nous en avons vu un
exemple à propos de la somme des polynômes ; la primitive ouvre les cases d'un
tableau, transformant un vecteur en matrice :
Voyons une autre primitive APL sans équivalent dans MATLAB.
La
primitive
(iota) donne la première occurence d'une valeur dans un vecteur :
Ici "a" est un vecteur de dimension 12 et l'instruction sert à adopter
l'origine 1 pour les indices, comme en MATLAB. 16 de x est à la
7ème position dans a, 13 est pour la première fois à la 4ème,
22 à la 12ème,... 7 à la 13ème (au delà
de "a") ...
Cette
primitive
fonctionne avec des vecteurs gigognes :
Les fonctions de l'automatique
La "Control System Toolbox" contient des fonctions spécialisées à l'automatique. Pour se conformer à une certaine conception en vogue dans ce domaine, chaque case d'un tableau peut contenir une fraction rationnelle ; mais MATLAB l'appelle "fonction de transfert" (transfert function). On peut appeler la variable "s" ou "p" ou "z", mais pas "x" par exemple.
Transformée inverse de Laplace (automatique)
Pour
calculer la transformée inverse de Laplace d'une fraction rationnelle F(p), il
faut faire un détour : traiter F(p) comme la fonction de transfert d'un
système linéaire invariant et lui appliquer une impulsion de Dirac. Prenons les
deux fractions :
La valeur est
susceptible d'être cachée dans une description compliquée. La transformée
inverse de F1(p) est exactement :
Notons et
les pôles
de F2(p), on a avec une bonne précision :
sa transformée inverse est :
Pour le terme
est négligeable,
est très proche de
ln 2 ; f2(t) est donc très proche de f1(t). Par le choix du
coefficient ln 2 on voit que :
Nous ajoutons un terme du second degré nul au dénominateur de F1 pour ramener cette fraction à la même forme que F2.
En MATLAB on
fait les deux calculs séparément :
et cela donne :
La courbe bleue de f1(t) est correcte ; mais la courbe verte montre que le coefficient 1E‑15 entraîne une dégradation appréciable de la précision de f2(t).
On peut
encore construire un tableau "F" contenant les deux fractions
précédentes et calculer f1(t) seule, puis f1(t) et f2(t) ensemble. On peut
ensuite tracer f1(t) seule, puis extraite du calcul couplé avec f2(t) :
et cela donne :
La courbe
bleue de f1(t) calculée seule est correcte ; mais la courbe verte montre
que la présence de f2(t) dans le calcul dégrade la précision de f1(t). Ici
n'est pas
négligeable, cette petite cause produit de grands effets.
En APL/HUB
on fait les deux calculs simultanément :
une ligne de code suffit, et cela donne :
Puisque
l'intervalle 5 est subdivisé en 50 parties, il y a un point à chaque
multiple de 5/50=0.1 ; pour la courbe f2(t) se superpose à f1(t) et
l'écrase. Le coefficient 1E‑15 ne dégrade pas la précision. Le calcul
proprement dit s'analyse :
L'argument droit de "FntLap" est un tableau gigogne qui se développe :
c'est une matrice à deux lignes (numérateur, dénominateur) et trois colonnes
(second degré).
Au lieu de deux valeurs d'un coefficient on aurait pu en placer dix, cent, mille ; "FntLap" ferait encore les calculs simultanément, tandis qu'en MATLAB il faudrait faire une boucle de programme.
MATLAB ne prend pas assez de précautions pour garantir la précision de certains calculs.
Le temps de calcul (automatique)
Considérons
un système d'ordre deux de fonction de transfert :
On veut tracer
sa réponse à un échelon unité en fonction du coefficient d'amortissement La transformée de
Laplace de cette réponse est :
Prenons 100
valeurs de en
progression arithmétique :
0.2, 0.4, ... 2
En APL on
peut faire :
et sur un certain ordinateur on obtient après une seconde deux (1.2s) :
En MATLAB,
par manque de tableaux gigognes analogues à APL, une manière facile consiste à
faire une boucle dans une fonction ; chaque passage dans la boucle fait le
calcul pour un et
trace la courbe correspondante :
Puis on fait :
On obtient les mêmes courbes qu'avec APL sur le même ordinateur après soixante‑quinze secondes (75s).
Un
utilisateur expérimenté de MATLAB a modifié la fonction "echord2" en
déplaçant les courbes en dehors de la boucle :
On obtient encore les mêmes courbes sur le même ordinateur après une seconde deux (1.2s)
aussi ; un piège.
En APL/HUB, c'est une seule ligne de code sans fonction. En APL/HUB, on peut se mettre dans les mêmes conditions que l'exemple MATLAB qui prend 75s en faisant chaque calcul et chaque courbe dans une boucle, donc dans une fonction ; on obtient le même graphique après une seconde neuf (1.9s) seulement.
Courbe de Black (automatique)
Dans l'étude
d'un système asservi, on peut être amené à tracer sa fonction de transfert en
boucle ouverte dans le plan de Black, appelé Nichols par MATLAB. Prenons comme
exemple la fonction de transfert en boucle ouverte :
ce système est instable à cause d'un pôle à partie réelle positive. On trace la
courbe de Black par :
ce qui donne :
Si on multiplie F(p) par un coefficient de gain "K", ce qui translate verticalement la courbe de log K par rapport aux axes, on ne peut pas facilement en déduire le nombre de pôles instables (à parties réelles positives) en boucle fermée en fonction de K. De plus, la courbe est assortie d'une grille en traits interrompus qui permettait autrefois de calculer graphiquement, point par point, la fonction de transfert en boucle fermée. Depuis que l'ordinateur permet de faire ce calcul rapidement, cette grille est obsolète.
Une
amélioration de la courbe de Black consiste à tracer le logarithme (complexe)
de la courbe de Nyquist complète par :
où on a marqué quatre valeurs de K ; l'argument gauche de
"BodBlk" s'analyse :
et cela donne :
Le nombre de pôles instables (à parties réelles positives) en boucle fermée est
le nombre de tours de la courbe autour des points critiques pour le réglage du
gain ; il est indiqué sur la figure :
et on peut vérifier les pôles en boucle fermée arrondis à près, encore une seule ligne de
code pour calculer ces quatre cas :
L'argument
droit de "LieuTrsf" se développe :
c'est une matrice à deux lignes : numérateur, dénominateur.
Le "nichols" de MATLAB ne trace que la partie jaune de "BodBlk" d'APL/HUB ; c'est la programmation moderne d'une technique obsolète.
Historique
J'ai abandonné le fortran en 1972 pour essayer puis adopter l'APL. Il y avait une différence colossale entre les deux langages. Beaucoup de gens étaient adversaires de l'APL, la majorité des informaticiens. Depuis cette époque, beaucoup d'informaticiens semblent manifester une farouche hostilité à l'APL. Pourquoi ? Diverses explications sont possibles, mais ce ne sont que des hypothèses.
La programmation en APL bouleversait les méthodes de l'informatique de l'époque. Par exemple, il ne fallait plus parcourir les cases d'un tableau pour les traiter une par une dans des boucles emboîtées, car APL fournissait des primitives efficaces sur tableaux. Les informaticiens n'y retrouvaient pas ce qu'ils avaient appris à l'école et, la programmation étant simplifiée, ils pouvaient craindre que des clients potentiels n'aient plus besoin de leurs services.
Les fonctions APL n'étaient pas compilées, mais interprétées ; et une règle disait que les programmes compilés s'exécutent plus vite que ceux interprétés. Ce n'était pas vrai pour toutes les fonctions APL, et on oubliait le temps passé par l'homme à l'analyse et à la programmation. Comparés à ceux d'aujourd'hui, les ordinateurs de l'époque (grosses armoires en salles climatisées) étaient lents et coûteux. Depuis, les méthodes d'interprétation se sont améliorées. Le travail en APL était globalement efficace, et ceux qui l'utilisaient couramment refusaient de revenir au fortran. Comme conséquence de cette hostilité, quand les décideurs d'une entreprise doivent acheter un logiciel, ils demandent conseil à leurs informaticiens qui ne leur recommandent surtout pas APL.
Vers 1990 on commence à entendre parler de MATLAB. Je me demande bien pourquoi ceux qui l'ont créé ont voulu refaire ce qui existait déjà en plus puissant, si ce n'est l'hostilité déjà signalée ; car APL connaissait les tableaux gigognes et un ensemble de concepts et de primitives permettant de les traiter efficacement par des programmes concis.
Bien entendu il existe des algorithmes d'analyse numérique en fortran, C ou MATLAB. Il en existe aussi en APL, nous en avons vu dans ce texte. Pour ceux qui n'existent pas en APL, il faut savoir que les diverses réalisations d'APL fournissent des passerelles entre APL et des algorithmes en binaire exécutable, qu'ils proviennent de fortran, C ou assembleur. De plus il faut comprendre qu'on peut traduire en APL des programmes fortran, C ou MATLAB sans trop de difficulté, car la version APL est toujours beaucoup plus simple. Naturellement cela représente un peu de travail ; mais il en vaut le coût. Ce faisant, on peut étendre le domaine d'application des algorithmes APL ainsi construits au-delà de ce qu'on peut espérer en fortran, C ou MATLAB. C'est la transformation inverse qui est compliquée, voire impossible.
Conclusion
MATLAB semble dériver du fortran, dont il a supprimé les déclarations de type et de dimension, auquel il a incorporé des matrices obligées.
Il essaie de forcer les données à être matricielles : par exemple il place les coefficients d'un polynôme dans une matrice à une ligne, alors que la notion de matrice n'a rien à voir avec celle de polynôme. Il fournit un grand nombre d'algorithmes de traitement réservé aux matrices. Mais si un problème ne peut pas être mis sous cette forme (arborescences, valeurs multiples d'une donnée, etc...) il faut faire une programmation du genre fortran.
Il y a des pièges dans fortran, il y en a aussi dans MATLAB mais ce ne sont toujours pas les mêmes.
Il y a plusieurs structures de données en MATLAB ; en APL une seule structure suffit pour en faire davantage.
Il y a plusieurs syntaxes en MATLAB suivant les fonctions ; en APL une seule syntaxe suffit, simplifiant la programmation.
Le choix des symboles de fonctions est plus restreint en MATLAB qu'en APL.
MATLAB place chaque fonction dans un fichier ; APL place toutes les fonctions en mémoire vive.
Les variables et fonctions d'APL s'organisent dans une structure arborescente dynamique ; dans MATLAB il n'y a que deux niveaux : privé et public.
Les fonctions qui font la même chose sont plus longues en MATLAB qu'en APL, quelquefois de beaucoup.
Une fonction MATLAB programmée en imitant APL peut en remplacer plusieurs tout en étant plus tolérante.
APL sait faire sans programmation des opérations que MATLAB ne peut faire qu'avec de longues fonctions.
Certains calculs numériques de MATLAB peuvent être faux, le choix de la méthode n'étant probablement pas le bon.
Certains calculs peuvent prendre plus de temps en MATLAB qu'en APL.
MATLAB peut faire des calculs qui n'ont aucun sens.
Certaines primitives de MATLAB sont superflues en APL.
Certaines primitives d'APL n'ont pas d'équivalent dans MATLAB.
......
Arrêtons là l'énumération ; bref, APL est plus simple, plus concis, plus puissant, plus cohérent et plus précis que MATLAB.
Pour ces raisons, et bien d'autres, je continue à utiliser APL et non pas MATLAB, qui compliquerait mon travail.
Le
site :
http://www.afapl.asso.fr
contient des fonctions APL, des articles sur APL, ainsi qu'une présentation
d'APL.