Mathématiques avec Python et Ruby/Quaternions et octonions en Ruby

Complexes modifier

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

Definition et affichage modifier

Définition modifier

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
	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
	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

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

Module modifier

Le module d'un quaternion est un réel:

	def abs
		Math.hypot(@a.abs,@b.abs)
	end


Conjugué modifier

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

Addition modifier

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

La soustraction des quaternions relève d'un principe analogue:

	def -(q)
		Quaternion.new(@a-q.a,@b-q.b)
	end

Multiplication modifier

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

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

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

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

Définition modifier

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

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

Les fonctions sur les octonions se définissent presque comme celles sur les quaternions, Cayley-Dickson oblige:

Module modifier

Comme pour les quaternions:

	def abs
		Math.hypot(@a.abs,@b.abs)
	end

Conjugué modifier

	def conj
		Octonion.new(@a.conj,Quaternion.new(0,0)-@b)
	end

Opérations modifier

Addition modifier

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

	def -(o)
		Octonion.new(@a-o.a,@b-o.b)
	end

Multiplication modifier

	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

	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

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.

Bibliographie modifier

  • En fait, les quaternions existent déjà sous Ruby, à condition de les télécharger: [1]; sur le même site, l'auteur propose aussi des octonions.
  • Sur les octonions, le livre de John Baez est une lecture hautement conseillée: [2]