
Matrices et vecteurs en MQL5
Les collections de données ordonnées, dans lesquelles tous les éléments ont le même type, sont généralement gérées avec des tableaux, dans lesquels chaque élément est accessible par son index. Les tableaux sont largement utilisés dans la résolution de divers problèmes d'algèbre linéaire, dans les tâches de modélisation mathématique ou dans l'apprentissage automatique. D'une manière générale, la solution de ces problèmes repose sur des opérations mathématiques utilisant des matrices et des vecteurs, grâce auxquelles des transformations très complexes peuvent être écrites de manière compacte sous la forme de formules simples. La programmation de ce genre d’opérations nécessite de bonnes connaissances en mathématiques ainsi que la capacité d'écrire des boucles imbriquées complexes. Le débogage et la correction des bugs dans ce genre de programmes peuvent être assez difficiles.
En utilisant les types de données spéciaux ’matrix’ et ’vector’, il est possible de créer un code très proche de la notation mathématique tout en évitant de devoir créer des boucles imbriquées ou de tenir compte de l'indexation correcte des tableaux dans les calculs. Dans cet article, nous verrons comment créer, initialiser et utiliser les objets matrix et vector avec MQL5.
Type 'vector' (vecteur)
Le vecteur est un tableau unidimensionnel d’éléments de type double. Les opérations suivantes sont définies sur les vecteurs : addition, multiplication, norme pour obtenir la longueur ou le module du vecteur. En programmation, les vecteurs sont généralement représentés avec des tableaux d'éléments homogènes, sur lesquels aucune opération vectorielle régulière ne peut être définie, c'est-à-dire que les tableaux ne peuvent pas être additionnés ou multipliés, et qu'ils n'ont pas de norme.
En mathématiques, les vecteurs peuvent être représentés comme des vecteurs de ligne, c'est-à-dire un tableau composé d'1 ligne et de n colonnes, et des vecteurs de chaîne, c'est-à-dire une matrice d'1 colonne et de n lignes. En MQL5, le type 'vector' n'a pas de sous-types ligne et colonne. Le développeur doit donc comprendre quel type de vecteur est utilisé dans une opération particulière.
Utilisez les méthodes intégrées suivantes pour créer et initialiser des vecteurs :
Méthodes | Méthodes équivalentes dans NumPy | Description |
---|---|---|
void vector.Init(ulong size); | Crée un vecteur de la longueur spécifiée, dans lequel les valeurs sont indéfinies. | |
static vector vector::Ones(ulong size); | ones | Crée un vecteur de la longueur spécifiée, rempli avec des 1 |
static vector vector::Zeros(ulong size); | zeros | Crée un vecteur de la longueur spécifiée, rempli avec des 0 |
static vector vector::Full(ulong size,double value); | full | Crée un vecteur de la longueur spécifiée, rempli avec la valeur spécifiée |
opérateur = | Retourne une copie du vecteur | |
void vector.Resize(const vector v); | Redimensionne un vecteur en ajoutant de nouvelles valeurs à la fin |
Exemples de création de vecteurs :
void OnStart() { //--- vector initialization examples vector v; v.Init(7); Print("v = ", v); vector v1=vector::Ones(5); Print("v1 = ", v1); vector v2=vector::Zeros(3); Print("v2 = ", v2); vector v3=vector::Full(6, 2.5); Print("v3 = ", v3); vector v4{1, 2, 3}; Print("v4 = ", v4); v4.Resize(5); Print("after Resize(5) v4 = ", v4); vector v5=v4; Print("v5 = ", v5); v4.Fill(7); Print("v4 = ", v4, " v5 =",v5); } /* Execution result v = [4,5,6,8,10,12,12] v1 = [1,1,1,1,1] v2 = [0,0,0] v3 = [2.5,2.5,2.5,2.5,2.5,2.5] v4 = [1,2,3] after Resize(5) v4 = [1,2,3,7,7] v5 = [1,2,3,7,7] v4 = [7,7,7,7,7] v5 =[1,2,3,7,7] */
La méthode Init() peut être utilisée pour allouer de la mémoire pour le vecteur, mais aussi pour initialiser ses éléments avec des valeurs en utilisant une fonction. Dans ce cas, la taille du vecteur est transmise à la méthode Init dans le premier paramètre et le nom de la fonction est transmis dans le deuxième paramètre. Si la fonction contient des paramètres, ceux-ci doivent être spécifiés immédiatement après le nom de la fonction, séparés par une virgule.
La fonction elle-même doit contenir une référence au vecteur qui lui est transmis dans le premier paramètre. Le vecteur ne doit pas être passé à l'appel à la méthode Init. Voyons le fonctionnement de la méthode avec la fonction Arange comme exemple. Cette fonction imite numpy.arange.
void OnStart() { //--- vector v; v.Init(7,Arange,10,0,0.5); // 3 parameters are passed with Arange call Print("v = ", v); Print("v.size = ",v.Size()); } //+------------------------------------------------------------------+ //| Values are generated within the half-open interval [start, stop)| //+------------------------------------------------------------------+ void Arange(vector& v, double stop, double start = 0, double step = 1) // the function has 4 parameters { if(start >= stop) { PrintFormat("%s wrong parameters! start=%G stop=%G", __FILE__,start, stop); return; } //--- int size = (int)((stop - start) / step); v.Resize(size); double value = start; for(ulong i = 0; i < v.Size(); i++) { v[i] = value; value += step; } } /* Execution result v = [0,0.5,1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8,8.5,9,9.5] v.size = 20 */
La fonction Arange possède 2 paramètres optionnels : "start" et "step". Ainsi, un autre appel possible de Init(7,Arange,10) et son résultat correspondant sont les suivants :
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- vector v; v.Init(7,Arange,10); Print("v = ", v); Print("v.size = ",v.Size()); } ... /* v = [0,1,2,3,4,5,6,7,8,9] v.size = 10 */
Opérations sur les vecteurs
Les opérations habituelles d'addition, de soustraction, de multiplication et de division avec un scalaire peuvent être effectuées sur des vecteurs.
//+------------------------------------------------------------------+ //| vector2_article.mq5 | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- vector v= {1, 2, 3, 4, 5}; Print("Examples without saving vector changes"); Print("v = ", v); Print("v+5 = ", v+5); Print("v-Pi= ", v-M_PI); Print("v*2.0= ", v*2); Print("v/3.0= ", v/3.0); Print("Save all vector changes"); Print("v = ", v); Print("v+5 = ", v=v+5); Print("v-Pi= ", v=v-M_PI); Print("v*2.0= ", v= v*2); Print("v/3.0= ", v= v/3.0); } /* Execution result Examples without saving vector changes v = [1,2,3,4,5] v+5 = [6,7,8,9,10] v-Pi= [-2.141592653589793,-1.141592653589793,-0.1415926535897931,0.8584073464102069,1.858407346410207] v*2.0= [2,4,6,8,10] v/3.0= [0.3333333333333333,0.6666666666666666,1,1.333333333333333,1.666666666666667] Save all vector changes v = [1,2,3,4,5] v+5 = [6,7,8,9,10] v-Pi= [2.858407346410207,3.858407346410207,4.858407346410207,5.858407346410207,6.858407346410207] v*2.0= [5.716814692820414,7.716814692820414,9.716814692820414,11.71681469282041,13.71681469282041] v/3.0= [1.905604897606805,2.572271564273471,3.238938230940138,3.905604897606805,4.572271564273471] */ //+------------------------------------------------------------------+
Les vecteurs prennent en charge les opérations d'addition, de soustraction, de multiplication et de division sur les éléments de 2 vecteurs de même taille.
void OnStart() { //--- vector a = {1, 2, 3}; vector b = {2, 4, 6}; Print("a + b = ", a + b); Print("a - b = ", a - b); Print("a * b = ", a * b); Print("b / a = ", b / a); } /* Execution result a + b = [3,6,9] a - b = [-1,-2,-3] a * b = [2,8,18] b / a = [2,2,2] */
Quatre opérations de multiplication sont définies pour ce type de données :
void OnStart() { //--- vector a={1, 2, 3}; vector b={4, 5, 6}; Print("a = ", a); Print("b = ", b); Print("1) a.Dot(b) = ", a.Dot(b)); Print("2) a.MatMul(b) = ", a.MatMul(b)); Print("3) a.Kron(b) = ", a.Kron(b)); Print("4) a.Outer(b) = \n", a.Outer(b)); } /* Execution result a = [1,2,3] b = [4,5,6] 1) a.Dot(b) = 32.0 2) a.MatMul(b) = 32.0 3) a.Kron(b) = [[4,5,6,8,10,12,12,15,18]] 4) a.Outer(b) = [[4,5,6] [8,10,12] [12,15,18]] */
Comme vous pouvez le voir dans l'exemple, la méthode Outer renvoie une matrice dans laquelle le nombre de lignes et de colonnes correspond aux tailles des vecteurs multipliés. Les méthodes Dot et MatMul fonctionnent de la même manière.
Norme d’un vecteur
La norme d’un vecteur et d’une matrice représente la longueur du vecteur (magnitude) et sa valeur absolue. 3 façons possibles de calculer la norme d'un vecteur sont listées dans ENUM_VECTOR_NORM.void OnStart() { //--- struct str_vector_norm { ENUM_VECTOR_NORM norm; int value; }; str_vector_norm vector_norm[]= { {VECTOR_NORM_INF, 0}, {VECTOR_NORM_MINUS_INF, 0}, {VECTOR_NORM_P, 0}, {VECTOR_NORM_P, 1}, {VECTOR_NORM_P, 2}, {VECTOR_NORM_P, 3}, {VECTOR_NORM_P, 4}, {VECTOR_NORM_P, 5}, {VECTOR_NORM_P, 6}, {VECTOR_NORM_P, 7}, {VECTOR_NORM_P, -1}, {VECTOR_NORM_P, -2}, {VECTOR_NORM_P, -3}, {VECTOR_NORM_P, -4}, {VECTOR_NORM_P, -5}, {VECTOR_NORM_P, -6}, {VECTOR_NORM_P, -7} }; vector v{1, 2, 3, 4, 5, 6, 7}; double norm; Print("v = ", v); //--- for(int i=0; i<ArraySize(vector_norm); i++) { switch(vector_norm[i].norm) { case VECTOR_NORM_INF : norm=v.Norm(VECTOR_NORM_INF); Print("v.Norm(VECTOR_NORM_INF) = ", norm); break; case VECTOR_NORM_MINUS_INF : norm=v.Norm(VECTOR_NORM_MINUS_INF); Print("v.Norm(VECTOR_NORM_MINUS_INF) = ", norm); break; case VECTOR_NORM_P : norm=v.Norm(VECTOR_NORM_P, vector_norm[i].value); PrintFormat("v.Norm(VECTOR_NORM_P,%d) = %G", vector_norm[i].value, norm); } } } /* v = [1,2,3,4,5,6,7] v.Norm(VECTOR_NORM_INF) = 7.0 v.Norm(VECTOR_NORM_MINUS_INF) = 1.0 v.Norm(VECTOR_NORM_P,0) = 7 v.Norm(VECTOR_NORM_P,1) = 28 v.Norm(VECTOR_NORM_P,2) = 11.8322 v.Norm(VECTOR_NORM_P,3) = 9.22087 v.Norm(VECTOR_NORM_P,4) = 8.2693 v.Norm(VECTOR_NORM_P,5) = 7.80735 v.Norm(VECTOR_NORM_P,6) = 7.5473 v.Norm(VECTOR_NORM_P,7) = 7.38704 v.Norm(VECTOR_NORM_P,-1) = 0.385675 v.Norm(VECTOR_NORM_P,-2) = 0.813305 v.Norm(VECTOR_NORM_P,-3) = 0.942818 v.Norm(VECTOR_NORM_P,-4) = 0.980594 v.Norm(VECTOR_NORM_P,-5) = 0.992789 v.Norm(VECTOR_NORM_P,-6) = 0.99714 v.Norm(VECTOR_NORM_P,-7) = 0.998813 */
En utilisant la norme, vous pouvez mesurer la distance entre 2 vecteurs :
void OnStart() { //--- vector a{1,2,3}; vector b{2,3,4}; double distance=(b-a).Norm(VECTOR_NORM_P,2); Print("a = ",a); Print("b = ",b); Print("|a-b| = ",distance); } /* Execution result a = [1,2,3] b = [2,3,4] |a-b| = 1.7320508075688772 */
Type 'matrix'
Le vecteur est un cas particulier de matrice, qui est en fait un tableau à 2 dimensions d’éléments de type double. Ainsi, une matrice peut être vue comme un tableau de vecteurs de même taille. Le nombre de lignes de la matrice correspond au nombre de vecteurs, et le nombre de colonnes est égal à la longueur des vecteurs.
L’addition et la multiplication sont également disponibles pour les matrices. Les langages de programmation conventionnels utilisent des tableaux pour représenter les matrices. Mais les tableaux réguliers ne peuvent pas être ajoutés ou multipliés les uns par les autres, et ils n'ont pas de norme. Il existe de nombreux types de matrices différentes en mathématiques. Par exemple, la matrice d'identité, les matrices symétriques, symétriques de biais, triangulaires supérieures ou inférieures.
Une matrice peut être créée et initialisée avec des méthodes intégrées similaires aux méthodes vectorielles.
Méthode | Méthode équivalente dans NumPy | Description |
---|---|---|
void static matrix.Eye(const int rows, const int cols, const int ndiag=0) | Construit une matrice avec des 1 sur la diagonale spécifiée et des 0 ailleurs. | |
void matrix.Identity() | Remplit une matrice avec des 1 sur la diagonale principale et des 0 ailleurs | |
void static matrix.Ones(const int rows, const int cols) | Construit une nouvelle matrice, du nombre de lignes et de colonnes spécifiés, remplie de 1. | |
void static matrix.Zeros(const int rows, const int cols) | Construit une nouvelle matrice, du nombre de lignes et de colonnes spécifiés, remplie de 0. | |
void static matrix.Tri(const int rows, const int cols, const int ndiag=0) | tri | Construit une matrice avec des 1 sur la diagonale spécifiée et en dessous et des 0 ailleurs. |
void matrix.Diag(const vector v, const int ndiag=0) | diag | Extrait une diagonale ou construit une matrice diagonale |
void matrix.Full(const int rows, const int cols, const scalar value) | Construit une nouvelle matrice, du nombre de lignes et de colonnes spécifiés, remplie d'une valeur scalaire. | |
void matrix.Fill(const scalar value) | Remplit la matrice avec la valeur spécifiée |
Construction de matrices et exemples de remplissage :
void OnStart() { //--- matrix m{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; Print("m = \n", m); matrix ones=matrix::Ones(4, 4); Print("ones = \n", ones); matrix zeros=matrix::Zeros(4, 4); Print("zeros = \n", zeros); matrix eye=matrix::Eye(4, 4); Print("eye = \n", eye); matrix identity(4, 5); Print("matrix_identity\n", identity); identity.Identity(); Print("matrix_identity\n", identity); matrix tri=matrix::Tri(3, 4); Print("tri = \n", tri); Print("tri.Transpose() = \n", tri.Transpose()); // transpose the matrix matrix diag(5, 5); Print("diag = \n", diag); vector d{1, 2, 3, 4, 5}; diag.Diag(d); Print("diag = \n", diag); // insert values from the vector into the matrix diagonal matrix fill(5, 5); fill.Fill(10); Print("fill = \n", fill); matrix full =matrix::Full(5, 5, 100); Print("full = \n", full); matrix init(5, 7); Print("init = \n", init); m.Init(4, 6); Print("init = \n", init); matrix resize=matrix::Full(2, 2, 5); resize.Resize(5,5); Print("resize = \n", resize); } /* Execution result m = [[1,2,3] [4,5,6] [7,8,9]] ones = [[1,1,1,1] [1,1,1,1] [1,1,1,1] [1,1,1,1]] zeros = [[0,0,0,0] [0,0,0,0] [0,0,0,0] [0,0,0,0]] eye = [[1,0,0,0] [0,1,0,0] [0,0,1,0] [0,0,0,1]] matrix_identity [[1,0,0,0,0] [0,1,0,0,0] [0,0,1,0,0] [0,0,0,1,0]] matrix_identity [[1,0,0,0,0] [0,1,0,0,0] [0,0,1,0,0] [0,0,0,1,0]] tri = [[1,0,0,0] [1,1,0,0] [1,1,1,0]] tri.Transpose() = [[1,1,1] [0,1,1] [0,0,1] [0,0,0]] diag = [[0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0]] diag = [[1,0,0,0,0] [0,2,0,0,0] [0,0,3,0,0] [0,0,0,4,0] [0,0,0,0,5]] fill = [[10,10,10,10,10] [10,10,10,10,10] [10,10,10,10,10] [10,10,10,10,10] [10,10,10,10,10]] full = [[100,100,100,100,100] [100,100,100,100,100] [100,100,100,100,100] [100,100,100,100,100] [100,100,100,100,100]] resize = [[5,5,0,0,0] [5,5,0,0,0] [0,0,0,0,0] [0,0,0,0,0] [0,0,0,0,0]] */
L'exemple suivant montre comment vous pouvez utiliser des fonctions personnalisées pour remplir des matrices :
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- matrix random(4, 5, MatrixRandom); Print("random = \n",random); matrix init(3, 6, MatrixSetValues); Print("init = \n", init); } //+------------------------------------------------------------------+ //| Fills the matrix with random values | //+------------------------------------------------------------------+ void MatrixRandom(matrix& m) { for(ulong r=0; r<m.Rows(); r++) { for(ulong c=0; c<m.Cols(); c++) { m[r][c]=double(MathRand())/32767.; } } } //+------------------------------------------------------------------+ //| Fills the matrix with powers of a number | //+------------------------------------------------------------------+ void MatrixSetValues(matrix& m, double initial=1) { double value=initial; for(ulong r=0; r<m.Rows(); r++) { for(ulong c=0; c<m.Cols(); c++) { m[r][c]=value; value*=2; } } } /* Execution result random = [[0.4200262459181494,0.5014496292001098,0.7520371105075229,0.652058473464156,0.08783227027191992] [0.5991088595233008,0.4311960203863643,0.8718832972197638,0.1350138859218116,0.901882992034669] [0.4964445936460463,0.8354747154148991,0.5258339182714317,0.6055482650227363,0.5952940458388012] [0.3959166234321116,0.8146916104617451,0.2053590502639851,0.2657551805169835,0.3672292245246742]] init = [[1,2,4,8,16,32] [64,128,256,512,1024,2048] [4096,8192,16384,32768,65536,131072]] */
Une matrice peut être construite sans initialisation de valeur de 2 manières :
//--- create a matrix of a given 'rows x cols' size matrix m(3, 3); // ------ equivalent matrix m; m.Resize(3, 3);
Norme d’une matrice
Les 9 façons de calculer la norme d'une matrice sont listées dans ENUM_MATRIX_NORM.
void OnStart() { //--- ENUM_MATRIX_NORM matrix_norm[]= {MATRIX_NORM_FROBENIUS, MATRIX_NORM_SPECTRAL, MATRIX_NORM_NUCLEAR, MATRIX_NORM_INF, MATRIX_NORM_MINUS_INF, MATRIX_NORM_P1, MATRIX_NORM_MINUS_P1, MATRIX_NORM_P2, MATRIX_NORM_MINUS_P2 }; matrix m{{1,2,3},{4,5,6},{7,8,9}}; Print("matrix m:\n",m); //--- compute the norm using all ways double norm; for(int i=0; i<ArraySize(matrix_norm); i++) { norm=m.Norm(matrix_norm[i]); PrintFormat("%d. Norm(%s) = %.6f",i+1, EnumToString(matrix_norm[i]),norm); } //--- return; } /* Execution result matrix m: [[1,2,3] [4,5,6] [7,8,9]] 1. Norm(MATRIX_NORM_FROBENIUS) = 16.881943 2. Norm(MATRIX_NORM_SPECTRAL) = 14.790157 3. Norm(MATRIX_NORM_NUCLEAR) = 17.916473 4. Norm(MATRIX_NORM_INF) = 24.000000 5. Norm(MATRIX_NORM_MINUS_INF) = 6.000000 6. Norm(MATRIX_NORM_P1) = 18.000000 7. Norm(MATRIX_NORM_MINUS_P1) = 12.000000 8. Norm(MATRIX_NORM_P2) = 16.848103 9. Norm(MATRIX_NORM_MINUS_P2) = 0.000000 */
Opérations sur les matrices et les vecteurs
Il existe des méthodes spéciales sur les matrices pour résoudre les problèmes mathématiques :
- Transposition
- Addition, soustraction, multiplication et division de matrices élément par élément
- Addition, soustraction, multiplication et division des éléments de la matrice par un scalaire.
- Produit de matrices et de vecteurs par la méthode MatMul (produit matriciel)
- Inner()
- Outer()
- Kron()
- Inv() — inverse de la matrice
- Solve() — résout un système d'équations linéaires
- LstSq() — renvoie la solution des moindres carrés des équations algébriques linéaires (pour les matrices non carrées ou dégénérées).
- PInv() — matrice des moindres carrés pseudo-inverse
- Opérations sur les colonnes, les lignes et les diagonales
Décomposition de matrices :
Méthode | Méthode équivalente dans NumPy | Description |
---|---|---|
bool matrix.Cholesky(matrix& L) | cholesky | Calcule la décomposition de Cholesky |
bool matrix.QR(matrix& Q, matrix& R) | qr | Calcule la décomposition QR |
bool matrix.SVD(matrix& U, matrix& V, vector& singular_values) | Calcule la décomposition SVD | |
bool matrix.Eig(matrix& eigen_vectors, vector& eigen_values) | Calcule les valeurs propres et les vecteurs propres droits d'une matrice carrée. | |
bool matrix.EigVals(vector& eigen_values) | Calcule les valeurs propres d'une matrice générale | |
bool matrix.LU(matrix& L, matrix& U) |
| Implémente la décomposition LU d'une matrice : le produit d'une matrice triangulaire inférieure et d'une matrice triangulaire supérieure. |
bool matrix.LUP(matrix& L, matrix& U, matrix& P) |
| Implémente la décomposition LUP avec pivotement partiel, qui est une factorisation LU avec une permutation des rangées : PA = LU |
Produit de matrices et de vecteurs
La fonction MatMul() est définie pour calculer le produit matriciel de matrices et de vecteurs. Cette méthode est souvent utilisée pour résoudre différents problèmes mathématiques. Les 2 options suivantes sont possibles lors de la multiplication d'une matrice et d'un vecteur :
- Le vecteur horizontal de gauche est multiplié par la matrice de droite : la longueur du vecteur est égale au nombre de colonnes de la matrice ;
- La matrice de gauche est multipliée par le vecteur vertical de droite : le nombre de colonnes de la matrice est égal à la longueur du vecteur.
Si la longueur du vecteur n'est pas égale au nombre de colonnes de la matrice, une erreur d'exécution critique est générée.
Pour multiplier 2 matrices, leur forme doit être la suivante : A[M,N] * B[N,K] = C[M,K], c'est-à-dire que le nombre de colonnes de la matrice de gauche doit être égal au nombre de lignes de la matrice de droite. Si les dimensions ne sont pas cohérentes, le résultat est une matrice vide. Voyons toutes les variantes de produits matriciels avec des exemples :
void OnStart() { //--- initialize matrices matrix m35, m52; m35.Init(3,5,Arange); m52.Init(5,2,Arange); //--- Print("1. Product of horizontal vector v[3] and matrix m[3,5]"); vector v3 = {1,2,3}; Print("On the left v3 = ",v3); Print("On the right m35 = \n",m35); Print("v3.MatMul(m35) = horizontal vector v[5] \n",v3.MatMul(m35)); //--- show that this is really a horizontal vector Print("\n2. Product of matrix m[1,3] and matrix m[3,5]"); matrix m13; m13.Init(1,3,Arange,1); Print("On the left m13 = \n",m13); Print("On the right m35 = \n",m35); Print("m13.MatMul(m35) = matrix m[1,5] \n",m13.MatMul(m35)); Print("\n3. Product of matrix m[3,5] and vertical vector v[5]"); vector v5 = {1,2,3,4,5}; Print("On the left m35 = \n",m35); Print("On the right v5 = ",v5); Print("m35.MatMul(v5) = vertical vector v[3] \n",m35.MatMul(v5)); //--- show that this is really a vertical vector Print("\n4. Product of matrix m[3,5] and matrix m[5,1]"); matrix m51; m51.Init(5,1,Arange,1); Print("On the left m35 = \n",m35); Print("On the right m51 = \n",m51); Print("m35.MatMul(m51) = matrix v[3] \n",m35.MatMul(m51)); Print("\n5. Product of matrix m[3,5] and matrix m[5,2]"); Print("On the left m35 = \n",m35); Print("On the right m52 = \n",m52); Print("m35.MatMul(m52) = matrix m[3,2] \n",m35.MatMul(m52)); Print("\n6. Product of horizontal vector v[5] and matrix m[5,2]"); Print("On the left v5 = \n",v5); Print("On the right m52 = \n",m52); Print("v5.MatMul(m52) = horizontal vector v[2] \n",v5.MatMul(m52)); Print("\n7. Outer() product of horizontal vector v[5] and vertical vector v[3]"); Print("On the left v5 = \n",v5); Print("On the right v3 = \n",v3); Print("v5.Outer(v3) = matrix m[5,3] \n",v5.Outer(v3)); //--- show that the product of matrices generates the same result Print("\n8. Outer() product of the matrix m[1,5] and matrix m[3,1]"); matrix m15,m31; m15.Init(1,5,Arange,1); m31.Init(3,1,Arange,1); Print("On the left m[1,5] = \n",m15); Print("On the right m31 = \n",m31); Print("m15.Outer(m31) = matrix m[5,3] \n",m15.Outer(m31)); } //+------------------------------------------------------------------+ //| Fill the matrix with increasing values | //+------------------------------------------------------------------+ void Arange(matrix & m, double start = 0, double step = 1) // the function has three parameters { //--- ulong cols = m.Cols(); ulong rows = m.Rows(); double value = start; for(ulong r = 0; r < rows; r++) { for(ulong c = 0; c < cols; c++) { m[r][c] = value; value += step; } } //--- } /* Execution result 1. Product of horizontal vector v[3] and matrix m[3,5] On the left v3 = [1,2,3] On the right m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] v3.MatMul(m35) = horizontal vector v[5] [40,46,52,58,64] 2. Product of matrix m[1,3] and matrix m[3,5] On the left m13 = [[1,2,3]] On the right m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] m13.MatMul(m35) = matrix m[1,5] [[40,46,52,58,64]] 3. Product of matrix m[3,5] and vertical vector v[5] On the left m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] On the right v5 = [1,2,3,4,5] m35.MatMul(v5) = vertical vector v[3] [40,115,190] 4. Product of matrix m[3,5] and matrix m[5,1] On the left m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] On the right m51 = [[1] [2] [3] [4] [5]] m35.MatMul(m51) = matrix v[3] [[40] [115] [190]] 5. Product of matrix m[3,5] and matrix m[5,2] On the left m35 = [[0,1,2,3,4] [5,6,7,8,9] [10,11,12,13,14]] On the right m52 = [[0,1] [2,3] [4,5] [6,7] [8,9]] m35.MatMul(m52) = matrix m[3,2] [[60,70] [160,195] [260,320]] 6. The product of horizontal vector v[5] and matrix m[5,2] On the left v5 = [1,2,3,4,5] On the right m52 = [[0,1] [2,3] [4,5] [6,7] [8,9]] v5.MatMul(m52) = horizontal vector v[2] [80,95] 7. Outer() product of horizontal vector v[5] and vertical vector v[3] On the left v5 = [1,2,3,4,5] On the right v3 = [1,2,3] v5.Outer(v3) = matrix m[5,3] [[1,2,3] [2,4,6] [3,6,9] [4,8,12] [5,10,15]] 8. Outer() product of the matrix m[1,5] and matrix m[3,1] On the left m[1,5] = [[1,2,3,4,5]] On the right m31 = [[1] [2] [3]] m15.Outer(m31) = matrix m[5,3] [[1,2,3] [2,4,6] [3,6,9] [4,8,12] [5,10,15]] */
Pour une meilleure compréhension de la disposition des types de matrices et de vecteurs, ces exemples montrent comment les matrices peuvent être utilisées à la place des vecteurs. Cela signifie que les vecteurs peuvent être représentés sous forme de matrices.
Nombres complexes de type "complex".
struct complex { double real; // real part double imag; // imaginary part };Le type ’complex’ peut être transmis par valeur comme paramètre pour les fonctions MQL5 (contrairement aux structures ordinaires, qui ne sont transmises que par référence). Pour les fonctions importées de DLL, le type ’complex’ doit être transmis uniquement par référence.
Le suffixe ’i’ est utilisé pour décrire les constantes complexes :
complex square(complex c) { return(c*c); } void OnStart() { Print(square(1+2i)); // a constant is passed as a parameter } // will print "(-3,4)" - a string representation of a complex numberSeules les opérations simples sont disponibles pour les nombres complexes : =, +, -, *, /, +=, -=, *=, /=, ==, !=.
De nouvelles fonctions mathématiques seront bientôt ajoutées, permettant le calcul de la valeur absolue, du sinus, du cosinus et autres.
Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/9805





- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation