Mathématiques avec Python et Ruby/Quaternions et octonions en Ruby
Complexes
[modifier | modifier le wikicode]On a vu dans le chapitre précédent que pour Ruby, un nombre complexe z est essentiellement une structure abritant deux réels, accessibles par z.real et z.imag respectivement. La construction de Cayley-Dickson généralise ce point de vue: En prenant deux complexes a et b, on peut les regrouper dans une nouvelle structure qui est considérée comme un nombre: Un quaternion.
Dans toute la suite, on va profiter de la gestion des fractions offerte par cmath, avec
require 'cmath'
Quaternions
[modifier | modifier le wikicode]Definition et affichage
[modifier | modifier le wikicode]Définition
[modifier | modifier le wikicode]La définition d'un quaternion se fait dans une classe nommée Quaternion:
class Quaternion
end
La première méthode, l'initialisation, crée donc deux variables a et b (qui seront des complexes, mais Ruby ne le sait pas encore):
Initialisation
[modifier | modifier le wikicode] def initialize(a,b)
@a,@b = a,b
end
Les nombres complexes a et b seront des propriétés du quaternion:
Propriétés a et b
[modifier | modifier le wikicode] def a
@a
end
def b
@b
end
Désormais on accède aux deux complexes a et b d'un quaternion q par q.a et q.b.
Affichage
[modifier | modifier le wikicode]Pour afficher un quaternion q avec puts(q), il est nécessaire de redéfinir (une sorte de surcharge) sa méthode de conversion en chaîne de caractères (string):
def to_s
'('+a.real.to_s+')+('+a.imag.to_s+')i+('+b.real.to_s+')j+('+b.imag.to_s+')k'
end
La notation des points se lit de droite à gauche, par exemple a.real veut dire la partie réelle de a et q.a.real, la partie réelle du a de q.
Le quaternion de Ruby ne possède alors que deux propriétés, a et b, mais on va se rattraper sur les méthodes, qui opèrent sur un quaternion (ou deux):
Fonctions
[modifier | modifier le wikicode]Module
[modifier | modifier le wikicode]Le module d'un quaternion est un réel:
def abs
Math.hypot(@a.abs,@b.abs)
end
Conjugué
[modifier | modifier le wikicode]Le conjugué d'un quaternion est un quaternion de même module que celui-ci:
def conj
Quaternion.new(@a.conj,-@b)
end
Opérations
[modifier | modifier le wikicode]Addition
[modifier | modifier le wikicode]Pour additionner deux quaternions, on additionne leurs a respectifs, et leurs b respectifs, et on crée un nouveau quaternion à partir des deux nombres complexes obtenus:
def +(q)
Quaternion.new(@a+q.a,@b+q.b)
end
Pour calculer et afficher la somme des quaternions p et q, il suffit alors d'entrer puts(p+q).
Soustraction
[modifier | modifier le wikicode]La soustraction des quaternions relève d'un principe analogue:
def -(q)
Quaternion.new(@a-q.a,@b-q.b)
end
Multiplication
[modifier | modifier le wikicode]Le produit de deux quaternions est plus difficile à définir:
def *(q)
Quaternion.new(@a*q.a-@b*q.b.conj,@a*q.b+@b*q.a.conj)
end
La multiplication des quaternions n'est pas commutative, comme le montre l'exemple suivant:
p=Quaternion.new(Complex(2,1),Complex(3,4))
q=Quaternion.new(Complex(2,5),Complex(-3,-5))
puts(p*q)
puts(q*p)
Division
[modifier | modifier le wikicode]Pour diviser un quaternion par un autre, on peut faire ainsi:
def /(q)
d=q.abs**2
Quaternion.new((@a*q.a.conj+@b*q.b.conj)/d,(-@a*q.b+@b*q.a)/d)
end
Comme ils ont le même module, le quotient d'un quaternion par son conjugué est égal à 1:
p=Quaternion.new(Complex(2,1),Complex(3,4))
puts((p/p.conj).abs)
Cet exemple révèle que , c'est-à-dire que , qui est une décomposition de comme somme de 4 carrés.
Résumé
[modifier | modifier le wikicode]La classe Quaternion de Ruby tient en entier dans un fichier plutôt léger, au vu de ses possibilités:
require 'cmath'
class Quaternion
def initialize(a,b)
@a,@b = a,b
end
def a
@a
end
def b
@b
end
def to_s
'('+a.real.to_s+')+('+a.imag.to_s+')i+('+b.real.to_s+')j+('+b.imag.to_s+')k'
end
def +(q)
Quaternion.new(@a+q.a,@b+q.b)
end
def -(q)
Quaternion.new(@a-q.a,@b-q.b)
end
def *(q)
Quaternion.new(@a*q.a-@b*q.b.conj,@a*q.b+@b*q.a.conj)
end
def abs
Math.hypot(@a.abs,@b.abs)
end
def conj
Quaternion.new(@a.conj,-@b)
end
def /(q)
d=q.abs**2
Quaternion.new((@a*q.a.conj+@b*q.b.conj)/d,(-@a*q.b+@b*q.a.conj)/d)
end
end
Si on enregistre ce fichier sous le nom quaternions.rb, il suffit d'insérer require 'quaternions' pour être en mesure d'effectuer des calculs sur les quaternions.
Octonions
[modifier | modifier le wikicode]Ce qui est intéressant avec la construction de Cayley-Dickson utilisée ci-dessus pour les quaternions, c'est qu'elle se généralise: En définissant une structure (un objet) comprenant deux quaternions a et b, on définit un octonion.
Définition et affichage
[modifier | modifier le wikicode]Définition
[modifier | modifier le wikicode]Comme pour les quaternions, on décrit l'objet octonion dans une classe Octonion:
class Octonion
def initialize(a,b)
@a,@b = a,b
end
def a
@a
end
def b
@b
end
Au passage on définit les propriétés a et b de l'octonion comme celles du quaternion, sauf que cette fois-ci ce ne sont plus des complexes mais des quaternions. Mais comme Ruby est faiblement typé, cette particularité n'apparaîtra que lorsque a ou b sera utilisé.
Affichage
[modifier | modifier le wikicode]Là encore, la méthode to_s se définit comme celle des quaternions, mais il y a 8 nombres à afficher au lieu de 4:
def to_s
'('+a.a.real.to_s+')+('+a.a.imag.to_s+')i+('+a.b.real.to_s+')j+('+a.b.imag.to_s+')k+('+b.a.real.to_s+')l+('+b.a.imag.to_s+')li+('+b.b.real.to_s+')lj+('+b.b.imag.to_s+')lk'
end
Pour accéder au premier de ces nombres, que est la partie réelle du a de a, on note a.a.real. Autrement dit, on parcourt un arbre binaire, de profondeur 3.
Fonctions
[modifier | modifier le wikicode]Les fonctions sur les octonions se définissent presque comme celles sur les quaternions, Cayley-Dickson oblige:
Module
[modifier | modifier le wikicode]Comme pour les quaternions:
def abs
Math.hypot(@a.abs,@b.abs)
end
Conjugué
[modifier | modifier le wikicode] def conj
Octonion.new(@a.conj,Quaternion.new(0,0)-@b)
end
Opérations
[modifier | modifier le wikicode]Addition
[modifier | modifier le wikicode]Comme pour les quaternions, on additionne les octonions composante par composante (a avec o.a, b avec o.b):
def +(o)
Octonion.new(@a+o.a,@b+o.b)
end
Soustraction
[modifier | modifier le wikicode] def -(o)
Octonion.new(@a-o.a,@b-o.b)
end
Multiplication
[modifier | modifier le wikicode] def *(o)
Octonion.new(@a*o.a-o.b*@b.conj,@a.conj*o.b+o.a*@b)
end
Non seulement la multiplication des octonions n'est pas commutative, elle n'est plus associative non plus:
m=Octonion.new(p,q)
n=Octonion.new(q,p)
o=Octonion.new(p,p)
puts((m*n)*o)
puts(m*(n*o))
Division
[modifier | modifier le wikicode] def /(o)
d=1/o.abs**2
Octonion.new((@a*o.a.conj+o.b*@b.conj)*Quaternion.new(d,0),(Quaternion.new(0,0)-@a.conj*o.b+o.a.conj*@b)*Quaternion.new(d,0))
end
Là encore, le quotient d'un octonion par son conjugué est de module 1:
puts(m/m.conj)
puts((m/m.conj).abs)
Résumé
[modifier | modifier le wikicode]L'objet Octonion de Ruby est lui aussi, assez léger:
class Octonion
def initialize(a,b)
@a,@b = a,b
end
def a
@a
end
def b
@b
end
def to_s
'('+a.a.real.to_s+')+('+a.a.imag.to_s+')i+('+a.b.real.to_s+')j+('+a.b.imag.to_s+')k+('+b.a.real.to_s+')l+('+b.a.imag.to_s+')li+('+b.b.real.to_s+')lj+('+b.b.imag.to_s+')lk'
end
def +(o)
Octonion.new(@a+o.a,@b+o.b)
end
def -(o)
Octonion.new(@a-o.a,@b-o.b)
end
def *(o)
Octonion.new(@a*o.a-o.b*@b.conj,@a.conj*o.b+o.a*@b)
end
def abs
Math.hypot(@a.abs,@b.abs)
end
def conj
Octonion.new(@a.conj,Quaternion.new(0,0)-@b)
end
def /(o)
d=1/o.abs**2
Octonion.new((@a*o.a.conj+o.b*@b.conj)*Quaternion.new(d,0),(Quaternion.new(0,0)-@a.conj*o.b+o.a.conj*@b)*Quaternion.new(d,0))
end
end
En l'enregistrant sous le nom octonions.rb, il suffit d'écrire
require 'octonions'
pour être en mesure d'effectuer des calculs sur les octonions en Ruby.