
| Taille du fichier source (en octets) | Taille sans saut de ligne ni espace (en octets) | |||
|---|---|---|---|---|
| MathML | TeX | MathML | Tex | |
| A | 1411 | 137 | 878 | 125 |
| B | 3009 | 193 | 1659 | 180 |
| C | 3603 | 271 | 1810 | 240 |
| D | 5754 | 400 | 2565 | 339 |
| E | 2506 | 272 | 1541 | 210 |
| F | 4339 | 418 | 2364 | 405 |
| G | 1088 | 132 | 716 | 120 |
| H | 3372 | 242 | 1595 | 205 |
| Mon temps (en minutes) | Temps d'un volontaire (en minutes) | |||
|---|---|---|---|---|
| Wysiwyg | TeX | Wysiwyg | Tex | |
| A | 1'10 | 5'59 | 1'04 | 0'56 |
| B | 1'21 | 4'13 | 1'06 | 1'12 |
| C | 2'57 | 4'47 | 1'10 | 1'20 |
| D | 3'19 | 8'50 | 1'36 | 1'36 |
| E | 2'45 | 6'40 | 1'20 | 1'35 |
| F | 4'10 | 6'45 | 2'15 | 2'29 |
| G | 1'16 | 5'20 | 0'41 | 0'42 |
| H | 2'53 | 7'25 | 1'43 | 1'19 |
Les fonctions utilisées dans les algorithmes suivants correspondent, sauf mention contraire, à celles de la librairie Thot [3] utilisée par Amaya. Leurs noms sont jugés suffisamment explicites pour ne pas rentrer dans des explications détaillées. Le type principalement utilisé est un arbre dont les fils en chaque n½ud sont totalement ordonnés. On utilisera aussi des entiers et nil pour un objet non défini.
On utilise ici une fonction Appliquer qui prend pour
paramètre une fonction transformation. Ceci n'est a priori pas
possible en C, mais il s'agit juste de donner une méthode générale pour
ajouter un terme à une égalité : on prend le dernier terme, on le transforme
et on l'ajoute comme dernier fils de l'arbre.
AjouterTermeEgalites (égalités, transformation) dernier_terme = ObtenirDernierFils (égalités) nouveau_terme = Appliquer (dernier_terme, transformation) InsererApres (nouveau_terme, dernier_terme)
L'algorithme renvoie le développement du sinus à partir d'un arbre sin(a+b) supposé bien formé. C'est un cas très particulier et il faudrait avoir un algorithme plus général, mais il a l'avantage de donner un exemple simple de manipulation d'arbres. Remarquons tout de même qu'il faudrait, pour éviter d'alourdir le code, ajouter des fonctions de création d'arbres de formule.
DevelopperSinAPlusB (arbre) somme = ObtenirPremierFils(arbre) B = ObtenirPremierFils(somme) RemplacerParSuccesseur(B) A = B RemplacerParSuccesseur(B) sinA = CreerArbre (apply) operateur = CreerArbre (sin) InsererCommePremierFils (operateur, sinA) InsererApres(A, operateur) [idem pour cosA, sinB, cosB] sinAcosB = CreerArbre (apply) operateur = CreerArbre (times) InsererCommePremierFils (operateur, sinAcosB) InsererApres(sinA, operateur) InsererApres(cosB, sinA) [idem pour cosAsinB] developpe = CreerArbre (apply) operateur = CreerArbre (plus) InsererCommePremierFils (operateur, développe) InsererApres(sinAcosB, operateur) InsererApres(cosAsinB, sinAcosB) retourner développe
La première opération consiste à créer l'arbre de la transposée donc tout
d'abord ses lignes (matrixrow). Comme on sait que ce nombre de
lignes correspond au nombres de colonne de la matrice initiale, on prend une
ligne de cette dernière, on parcourt tous ses coefficients et on créer pour
chacun une ligne dans la transposée. On doit ensuite copier les lignes de la
matrice initiale dans les colonnes de la transposée. Comme les colonnes ne
sont pas des fils d'arbre de matrice, on doit faire deux boucles imbriquées :
la première parcourt les lignes de la matrice initiale, la seconde copie les
coefficients de chaque ligne dans une colonne de la transposée, en parcourant
chacune de ses lignes. Notons que Thot ne permet pas d'insérer directement un
élément comme dernier fils d'un arbre donc pour éviter un coup du à
l'utilisation d'ObtenirDernierFils, on parcourt les lignes de la
matrice initiale à l'envers .
TransposerMatrice (matrice)
transposee = CreerArbre (matrix)
ligne = ObtenirDernierFils (matrice)
coefficient = ObtenirPremierFils (ligne)
tant que coefficient <> nil faire
ligne2 = CreerArbre (matrixrow)
InsererCommePremierFils (Iigne2, transposee)
RemplacerParSuccesseur (coefficient)
fin tant que
tant que ligne <> nil faire
ligne2 = ObtenirPremierFils (transposee)
coefficient = ObtenirPremierFils (ligne)
tant que coefficient <> nil faire
coefficient2 = CopierArbre (coefficient)
InsererCommePremierFils (coefficient2, ligne2)
RemplacerParSuccesseur (coefficient)
RemplacerParSuccesseur (ligne2)
fin tant que
RemplacerParPredecesseur (ligne)
fin tant que
retourner transposee
L'algorithme consiste à créer une copie de l'arbre somme (on pourrait aussi travailler directement cet arbre) et parcourir la somme avec deux curseurs. Le curseur rapide compare les termes de la somme succédant au terme pointé par le curseur lent, compte combien lui sont égaux et les supprime le cas échéant. Si il y a au moins un autre terme égal à celui pointé par le curseur lent, on supprime ce dernier et le remplace par un arbre représentant le produit repétitions fois terme repété.
On suppose qu'on dispose d'une fonction EstEgal qui compare
deux arbres d'expressions. La plus simple retournerait l'égalité de deux
arbres, mais notons que des expressions mathématiques peuvent être égales
sans avoir exactement le même arbre. L'algorithme n'est pas optimal puisque
des termes comme ab et ba ou 2x et -5x ne sont pas regroupés.
RegrouperTermesSomme (somme)
somme2 = CopierArbre (somme)
terme = ObtenirPremierFils
RemplacerParSuccesseur (terme)
tant que terme <> nil faire
repetitions = 1
terme2 = terme;
RemplacerParSuccesseur (terme2)
tant que teraie2 <> nil faire
si EstEgal(terme, terme2) alors
repetitions = repetitions + 1
terme3 = terme2
RemplacerParSuccesseur(terme2)
Supprimer Arbre (terme3)
fin si
fin faire
si repetitions > 1 alors
termes_regroupes = CreerArbre (apply)
fil = CreerArbre(times)
InsererCommePremmierFils (fils, termes_regroupes)
InsererApres (CreerArbreNombre (repetitions), fils)
InsererApres (CopierArbre (terme), fils)
InsererApres (termes_regroupes, terme)
SupprimerArbre (terme)
fin si
RemplacerParSuccesseur (terme)
fin faire
retourner somme
Voici un exemple de rédaction chronométrée. A gauche du document rédigé se trouve le temps en secondes mis pour l'édition. Les fragments de formules qui auraient pu être générés par une transformation ont été mise en bleue.
| Fragment de démonstration | Temps d'édition (en seconde) |
| 20 ; 39 | |
| si et | 74 ; 17 ; 17 |
| donc pour x=2, vérifie le critère de Leibniz | 73 |
| et | 11 ; 65 ; 3 ; 35 |
| 35 | |
| la fonction cos est continue donc il existe tel que | 116 |
| est l'image réciproque d'un fermé par une fonction continue donc est fermé. | 38 ; 52 ; 16 |
| donc on peut poser et | 77 |
| Puisque cos 0 = 1 > 0 et que cos est continue sur et ne s'annule pas, | 65 |
| 50 | |
| Or sin'x=cosx, donc sin est strictement croissante sur cet intervalle et | 55 |
| Or donc | 2 ; 46 ; 11 |
| 16 ; 43 ; 2 | |
| 10 ; 42 ; 2 | |
| 60 | |
| On vérifie ensuite que est bien la plus petite période via le tableau de variation. | 25 |
Amaya [2] est un logiciel libre développé par des chercheurs de l'INRIA et des membres du W3C. Il a pour objectif la démonstration des nouvelles technologies internet.
Nous allons présenter ici un aperçu de ses fonctionnalités concernant l'édition de documents mathématiques.
Ci-contre, une capture d'écran où seule les panneaux qui nous intéressent de la barre d'outils ont été affichés.
Les formules mathématiques se distinguent d'un document classique par l'utilisation d'un affichage bidimensionnel et d'une structure récursive. Amaya gère le déplacement d'un curseur dans la formule par les touches directionnelles ou la souris de façon assez naturelle.

Néanmoins, dans certain cas, il est difficile de savoir dans quelle partie est positionnée le curseur. Ainsi, les formules rencontrées dans un article sont souvent insérées à l'intérieur d'un texte et l'utilisateur peut se demander s'il est ou non à l'intérieur d'une zone d'édition de formule. Dans Amaya, un encadré rouge permet de lever l'ambiguïté. Sur la formule ci-contre, il est dur de savoir si le curseur (en bleu) est à l'intérieur ou non du radical. Pour résoudre se problème, Amaya propose une vue structure.
Une autre difficulté se rencontre dans la manipulation de fragments de formule. En effet comme pour un texte, il est naturel de vouloir copier/coller, couper, supprimer ou transformer une sous-expression... Ci-dessous, on a l'exemple d'une formule dont on veut transformer un fragment (image 1). Comme pour le positionnement du curseur, la sélection à l'aide de la souris peul se révéler imprécise (image 2). Amaya offre une méthode confortable de sélection se déplaçant dans l'arbre de la formule : F2 et F4, combinés avec la touche Shift, respectivement un parcours en profondeur et en largeur de l'arbre de la formule. Nous sélectionnons ainsi précisément le fragment souhaité (image 3) et lui appliquons diverses transformations comme changer sa couleur en orange (image 4). Dans la barre d'état se trouve le chemin à partir de la racine (image 5) pouvant servir à la sélection des n½uds.

Enfin, se pose la question de l'insertion de constructions dans Amaya. Avant que j'y apporte des modifications, le logiciel disposait déjà des deux palettes citées plus haut permettant en cliquant sur un bouton d'insérer des symboles et des balises de présentation MathML. Toutefois, la rédaction était fastidieuse, le principal problème étant l'absence de constructions classiques.
Ma contribution a alors consistée en la programmation de fonctions générant l'arbre de telles constructions (incluant celles du chapitre 4 de [1]), certaines nécessitant la demande de paramètres comme les dimensions d'une matrice. Pour plus de rapidité j'ai ajouté des raccourcis clavier pour les constructions les utilisées ainsi que pour l'insertion de lettres grecques (par exemple Ctrl + (g ; a) pour alpha) dont l'usage est fréquent dans les formules mathématiques.
