//+------------------------------------------------------------------+ //| linalg.mqh | //| Copyright 2023, Omega Joctan | //| https://www.mql5.com/en/users/omegajoctan | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, Omega Joctan" #property link "https://www.mql5.com/en/users/omegajoctan" #include "MatrixExtend.mqh" //+------------------------------------------------------------------+ //| implementations of standard linear algebra algorithms | //+------------------------------------------------------------------+ class LinAlg { public: LinAlg(void); ~LinAlg(void); template static matrix dot(matrix &A, matrix &B); template static matrix norm(const matrix &A, const matrix &B); template static double norm(const vector &v1, const vector &v2); template static matrix outer(const matrix &A, const matrix &B); static bool svd(matrix &mat, matrix &U, matrix &V, vector &singular_value); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ LinAlg::LinAlg(void) { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ LinAlg::~LinAlg(void) { } //+------------------------------------------------------------------+ //| Dot product of two matrices | Flexible funciton - numpy like | //+------------------------------------------------------------------+ template matrix LinAlg::dot(matrix &A, matrix &B) { matrix Z={}; if (A.Cols() == B.Rows()) //Valid Normal matrix multiplication { Z = A.MatMul(B); return Z; } else { //---Check for one dimensional matrices | Scalar if ((A.Rows()==1 && A.Cols()==1)) { Z = B * A[0][0]; return Z; } if (B.Rows()==1 && B.Cols()==1) { Z = B[0][0] * A; return Z; } //-- Element wise multiplication if (A.Rows()==B.Rows() && A.Cols()==B.Cols()) { Z = A * B; return Z; } } return Z; } //+------------------------------------------------------------------+ //| Matrix or vector norm. | Finds the equlidean distance of the | //| two matrices | //+------------------------------------------------------------------+ template matrix LinAlg::norm(const matrix &A, const matrix &B) { matrix ret = {}; if (B.Cols() != A.Cols()) { Print(__FUNCTION__," Dimensions Error"); return ret; } if (A.Rows()==1 || B.Rows()==1) { matrix A_temp = A, B_temp = B; vector A_vector, B_vector; A_vector.Swap(A_temp); B_vector.Swap(B_temp); ulong size = 0; if (A_vector.Size() >= B_vector.Size()) { size = A_vector.Size(); B_vector.Resize(size); } else { size = B_vector.Size(); A_vector.Resize(size); } ret.Resize(1,1); ret[0][0] = MathSqrt( MathPow(A_vector - B_vector, 2).Sum() ) ; return (ret); } ulong size = A.Rows() > B.Rows() ? A.Rows() : B.Rows(); vector euc(size); for (ulong i=0; i double LinAlg::norm(const vector &v1, const vector &v2) { double dist = 0; if(v1.Size() != v2.Size()) Print(__FUNCTION__, " v1 and v2 not matching in size"); else { double c = 0; for(ulong i=0; i matrix LinAlg::outer(const matrix &A,const matrix &B) { return A.Outer(B); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool LinAlg::svd(matrix &mat, matrix &U,matrix &V,vector &singular_value) { return mat.SVD(U,V,singular_value); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+