![]() |
Bienvenue invité ( Connexion | Inscription )
![]() |
![]()
Message
#1
|
|
Macbidouilleur d'Or ! ![]() ![]() ![]() ![]() ![]() Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 ![]() |
Le forum développeur en langages divers est plutôt calme et je me permets donc de faire un vagabondage avec un des langages "bizarres" que j'apprécie, le langage APL.
En effet, j'ai été récemment surpris que l'éditeur de programmation ATOM avait non seulement le support de la syntaxe APL mais que cela en faisait l'un des éditeurs APL les plus confortables que j'ai jamais pratiqué. Peut-être que dans ces conditions, de nouveaux programmeurs curieux aimeraient s'y frotter un peu ? APL est rare. Au temps des ordis 8-bit, seuls le Tandy TRS80 et une variété de Commodore, le super-PET 9000 de l'université canadienne de Waterloo en avaient une implémentation. Rodnay Zacks, l'auteur de livre sur la programmation du 6502, avait créé la sienne, mais je ne l'ai jamais vue. Avant cette époque, il équipait un IBM portable très rare, antérieur au PC DOS qu'on connait, l'IBM 5100 Modèle A, A comme APL. Après cette époque, un portable ultra-rare à base de 68000, l'Ampère WS-1, n'a jamais trouvé son public, vendu seulement en France, hors de son Japon d'origine, jamais validé par la FCC aux USA,... Avis aux les collectionneurs. APL est né chez IBM à la fin des années 1950, créé par Kenneth Iverson. De nos jours, il existe soit une version OpenSource GNU APL, soit une version commerciale gratuite Dyalog APL, qui est devenue l'état de l'art du langage. DyalogAPL propose aussi un portail très pratique en libre d'accès : http://TryAPL.org En France, le langage a été popularisé par Bernard Legrand http://www.afapl.asso.fr/AFAPL_2006_v2.pdf Pourquoi s'y intéresser aujourd'hui ? - Parce c'est un langage orienté calcul ou Data, avant le Big Data - Parce qu'il manipule directement des tableaux, et qu'il a inspiré des langages comme R. - Parce que l'environnement de développement est plus aisé d'approche que dans le passé, j'ai cité ATOM. Commençons par un exemple simple : Cette semaine, j'ai un peu marché et j'ai gardé le kilométrage journalier, et voici ma semaine : Lundi : 5 km Mardi : 3 km Mercredi : 8 km Jeudi : 2 km Vendredi : 6 km Samedi : 8 km Dimanche : 10 km Quelle a été ma moyenne ? Code kms ← 5 3 8 2 6 8 10 +/kms ÷ ⍴ kms 6 Essayez ça sur TryAPL.org +/kms c'est une réduction par l'addition du vecteur kms, s'il avait fallu tout multiplier on aurait pu écrire ×/kms ⍴ kms c'est la dimension de kms, 7 éléments Et la division n'est pas la barre utilisée pour la réduction, mais la superposition de : et -, qui donne le signe de division utilisé par les calculettes. A propos de la réduction, les habitués de Big Data connaissent les moteurs de Map Reduce, on parle de la même reduction dans les deux cas. Et si vous êtes plutôt Scala, il s'agit de l'opération «fold». Maintenant, avec ces kilomètres vous pouvez préférer des totaux partiels après chaque jour. Facile, c'est l'opérateur de scan qui le fait. Code +\kms 5 8 16 18 24 32 42 Le scan existe dans ReactJS ou dans Scala. Comme vous le voyez, avec ces caractères spéciaux, il n'était pas facile d'avoir un environnement de dév, il fallait des claviers spéciaux, des terminaux et des imprimantes spéciales. Plus aujourd'hui, les caractères APL sont dans l'UNICODE supporté par tous les ordis modernes. Voyons un autre problème simple, mais très matheux, l'intersection d'une droite et d'un plan dans l'espace. C'est l'un des exemples du portail Rosetta qui recense les résolutions de ce genre de problème dans différents langages. Mais pas en APL... du moins avant ce post. Défi Rosetta : Intersection droite et plan L'énoncé : - Soit une droite dans l'espace 3D, définie par un point D et un vecteur directeur V - Soit un plan dans l'espace 3D, défini par un point P et un vecteur normal N - Trouver l'intersection I de la droite et du plan - Données : D = (0, 0, 10), V = (0, -1, -1), P = (0, 0, 5), N = ( 0, 0, 1) On va commencer par raisonner géométriquement avec les vecteurs: Puisque le point I appartient à la droite, il existe un paramètre t ∊ R, tel que le vecteur DI = t×V Le vecteur DI c'est en fait I - D de coordonnées Ix - Dx, etc on ne va pas aller par là, on va rester au niveau Point et Vecteur. Donc on a I - D = t × V, ou encore I = D + t × V Comme I appartient aussi au plan, tout vecteur du plan est normal à N. Les maths nous disent si deux vecteurs sont normaux, leur produit scalaire est nul. Le produit scalaire de A par B est le nombre AxBx + AyBy + AzBz, et il est noté A.B, et là encore on va rester à ce haut niveau, sans descendre aux x, y, z. Les maths nous apprennent deux propriétés du produit scalaire qui vont nous être utiles: - Il est distributif par rapport à l'addition de vecteurs : ( A + B ).C = A.C + B.C - Il est associatif par rapport à la multiplication externe par un réel : (t × A).B = t × A.B Réf: Patrice Wira : Un rappel sur les matrices Ici, on veut exprimer que le vecteur IP est normal à N, et le vecteur IP c'est P - I, comme vu précédemment. Donc on a (P - I).N = 0, remplaçons I par sa valeur D + t × V. (P - D - t × V).N = 0 Utilisons la distributivité: (P - D).N - (t × V).N = 0 Puis l'associativité: (P - D).N - t × (V.N) = 0 D'où : t = (P - D).N ÷ V.N Et l'APL dans tous ça ? Le produit scalaire A.B se code +/A × B, donc on peut écrire : t ← (+/(P - D) × N) ÷ +/V × N Ce qui permet de résoudre I : I ← D + t × V A essayer sur TryAPL.org Code V ← 0 ¯1 ¯1 D ← 0 0 10 N ← 0 0 1 P ← 0 0 5 t ← (+/(P - D) × N) ÷ +/V × N I ← D + t × V Et ça donne I 0 ¯5 5 A comparer avec les autres langages ! J-P PS: Tant qu'à faire... j'ai ajouté l'exemple au portail Rosetta Portail Rosetta Ce message a été modifié par Jaypee - 17 Dec 2020, 08:16. |
|
|
![]() |
![]()
Message
#2
|
|
Macbidouilleur d'Or ! ![]() ![]() ![]() ![]() ![]() Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 ![]() |
Un exemple lié à la génétique, calcul du taux de GC d'une séquence ADN.
Les bases de l'ADN sont décrites par les lettres A, C, G, et T. Par exemple, les chaînes 'ACGTACGTACGT' ou 'ACGTAGTCGADTAGTA' représentent des séquences d'ADN. Il s'agit de compter les occurrences des 'CG' et de les rapporter au nombre total de bases dans la séquence. Code ADN ← 'ACGTAGTCGADTAGTACGTAGTCGADTAGTA' On peut trouver les occurrences de 'G' ou 'C' dans ADN soit par un produit cartésien comme dans l'exemple des parenthèses, puis faire un OU logique, ou plus simplement avec l'opérateur d'appartenance: Code ADN,[0.5]ADN ∊ 'GC' A C G T A G T C G A D T A G T A C G T A G T C G A D T A G T A 0 1 1 0 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 1 0 0 0 0 1 0 0 Puis une réduction par l'addition : Code +/ADN ∊'GC' 12 On peut enfin calculer le rapport grâce à l'opérateur Rhô qui retourne le nombre de caractères (de bases) dans la chaîne ADN. Code (+/ADN ∊'GC')÷⍴ADN 0.3870967742 On transforme l'expression en fonction: Code tauxGC ← {(+/⍵ ∊'GC')÷⍴⍵} tauxGC ADN 0.3870967742 Et finalement on peut créer une fonction qui vérifie si le taux de GC > 50%, qui est le test pour déterminer si la séquence est une bactérie ! Code bacterie ← {3 ↑ (3 × 0.5<tauxGC ⍵) ⌽ 'NONOUI'} bacterie ADN NON bacterie 24 ⍴ 'CG' OUI JP Ce message a été modifié par Jaypee - 14 Apr 2021, 06:12. |
|
|
![]()
Message
#3
|
|
Macbidouilleur d'Or ! ![]() ![]() ![]() ![]() ![]() Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 ![]() |
Un exemple lié à la génétique, calcul du taux de GC d'une séquence ADN... Le code est loin d'être correct : On ne doit compter que les liaisons C-G, c-à-d les occurrences de C immédiatement suivi de G. On peut visualiser cela en empilant l'ADN original, sur lui-même, décalé de 1 colonne, on note le C à la fin et le G au début: Code ADN ← 'GACGTAGTCGADTAGTACGTAGTCGADTAGTAC' (ADN),[0.5](1 ⌽ ADN) GACGTAGTCGADTAGTACGTAGTCGADTAGTAC ACGTAGTCGADTAGTACGTAGTCGADTAGTACG Mais ce faisant, on a créé artificiellement une liaison C-G en rapprochant les extrémités, donc une manipulation (génétique) simple, en ajoutant une base neutre à la fin évitera ce problème, sans modifier les autres liaisons. Code (ADN, ' '),[0.5](1 ⌽ ADN, ' ') GACGTAGTCGADTAGTACGTAGTCGADTAGTAC ACGTAGTCGADTAGTACGTAGTCGADTAGTAC G On va maintenant créer un masque avec des 1 à la place des C ou des G, c'est en fait un produit cartésien de couples (x='C', x = 'G') où x vient de l'ADN manipulé : Code (ADN, ' ')∘.='CG' 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 0... Ajoutons juste pour mieux visualiser, l'ADN en première colonne, les A et les T donnent (0, 0), C donne (1,0) et G donne (0, 1): Code (ADN, ' '),(ADN, ' ')∘.='CG' G 0 1 A 0 0 C 1 0 G 0 1 T 0 0 A 0 0 G 0 1 T 0 0 C 1 0 G 0 1 A 0 0 Et comme le résultat est tout en hauteur on va le "coucher" en transposant ligne -> colonne avec l'opérateur qui va bien. Code ⍉(ADN, ' ')∘.='CG' 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 Mais noter qu'on a perdu l'alignement du 1 du C au dessus du 1 du G, il faudrait ne rien toucher de la première ligne et shifter de 1 colonne la deuxième. Facile ! Code 0 1⌽ ⍉(ADN, ' ')∘.='CG' 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 1 Maintenant on veut le masque résultat des 1 sur 1, pour ce faire on va comprimer (ou réduire) par le ET logique colonne par colonne: Code ∧/[1]0 1⌽ ⍉(ADN, ' ')∘.='CG' 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 Le [1] exprime le "colonne par colonne", si on l'avait oublié, on aurait obtenu 0 0, le ET logique de la première ligne, puis le même ET logique pour la seconde ligne. Et pour compter les 1, on comprime (ou réduit) le masque par l'addition: Code +/∧/[1]0 1⌽ ⍉(ADN, ' ')∘.='CG' 4 Mais le taux de CG se calcule en divisant ce compte par la longueur totale : Code (+/∧/[1]0 1⌽ ⍉(ADN, ' ')∘.='CG')÷⍴ADN 0.1212121212 Pour finir on va transformer cette expression en fonction qui accepte l'ADN comme unique argument à droite. Pour cela on remplace ADN par oméga, on enferme l'expression dans des accolades, et on lui donne un nom: Code tauxCG ← {(+/∧/[1]0 1⌽ ⍉(⍵, ' ')∘.='CG')÷⍴⍵} Et on l'applique aux données utilisées: Code tauxCG ADN 0.1212121212 Ou à de nouvelles données: Code tauxCG 'AGTCGATGGATC' 0.08333333333 @+JP Ce message a été modifié par Jaypee - 26 Sep 2021, 09:43. |
|
|
![]() ![]() |
Nous sommes le : 18th July 2025 - 09:10 |