MyraMath


Source: tests/sparse/Permutation.cpp

1 // ========================================================================= //
2 // This file is part of MyraMath, copyright (c) 2014-2019 by Ryan A Chilton //
3 // and distributed by MyraCore, LLC. See LICENSE.txt for license terms. //
4 // ========================================================================= //
5 
11 // Containers.
12 #include <myramath/dense/Vector.h>
13 #include <myramath/dense/Matrix.h>
16 
17 // Algorithms.
18 #include <myramath/dense/gemm.h>
19 #include <myramath/dense/inverse.h>
22 #include <myramath/sparse/gemm.h>
23 #include <myramath/sparse/gemv.h>
25 
26 // Reporting.
27 #include <tests/myratest.h>
28 
30 
31 using namespace myra;
32 
33 namespace {
34 
35 // Tests gemm() operations involving Permutation's.
36 void test_Permutation1(int N)
37  {
38  // Define a random Permutation and its inverse.
39  auto P = Permutation::random(N);
40  P.verify();
41  auto A = P.make_SparseMatrix<double>();
42 
43  // Define random Matrix X.
44  auto X = Matrix<double>::random(N,N);
45 
46  // Check P*X = A*X
47  {
48  Matrix<double> PX = X; gemm_inplace(P,PX);
49  Matrix<double> AX = gemm(A,X);
50  double error = frobenius(PX-AX);
51  myra::out() << " |PX-AX| = " << error << std::endl;
52  REQUIRE(error < 1.0e-9);
53  }
54 
55  // Check P'*X = A'*X
56  {
57  Matrix<double> PtX = X; gemm_inplace(P,'T',PtX);
58  Matrix<double> AtX = gemm(A,'T',X);
59  double error = frobenius(PtX-AtX);
60  myra::out() << " |P'X-A'X| = " << error << std::endl;
61  REQUIRE(error < 1.0e-9);
62  }
63 
64  // Check X*P = X*A
65  {
66  Matrix<double> XP = X; gemm_inplace(XP,P);
67  Matrix<double> XA = gemm(X,A);
68  double error = frobenius(XP-XA);
69  myra::out() << " |XP-XA| = " << error << std::endl;
70  REQUIRE(error < 1.0e-9);
71  }
72 
73  // Check X*P' = X*A'
74  {
75  Matrix<double> XPt = X; gemm_inplace(XPt,P,'T');
76  Matrix<double> XAt = gemm(X,A,'T');
77  double error = frobenius(XPt-XAt);
78  myra::out() << " |XP'-XA'| = " << error << std::endl;
79  REQUIRE(error < 1.0e-9);
80  }
81 
82  }
83 
84 // Tests gemv() operations involving Permutation's.
85 void test_Permutation2(int N)
86  {
87 
88  // Define a random Permutation and its inverse.
89  auto P = Permutation::random(N);
90  P.verify();
91  auto A = P.make_SparseMatrix<double>();
92 
93  // Define random Vector x.
94  auto x = Vector<double>::random(N);
95 
96  // Check P*x = A*x
97  {
98  Vector<double> Px = x; gemv_inplace(P,Px);
99  Vector<double> Ax = gemv(A,x);
100  double error = frobenius(Px-Ax);
101  myra::out() << " |Px-Ax| = " << error << std::endl;
102  REQUIRE(error < 1.0e-9);
103  }
104 
105  // Check P'*x = A'*x
106  {
107  Vector<double> Ptx = x; gemv_inplace(P,'T',Ptx);
108  Vector<double> Atx = gemv(A,'T',x);
109  double error = frobenius(Ptx-Atx);
110  myra::out() << " |P'x-A'x| = " << error << std::endl;
111  REQUIRE(error < 1.0e-9);
112  }
113 
114  }
115 
116 // Tests inverse(Permutation) operation.
117 void test_Permutation3(int N)
118  {
119  // Check that a Permutation and its inverse() lead to inverse matrices.
120  auto P = Permutation::random(N);
121  auto Q = inverse(P);
122  P.verify();
123  Q.verify();
124  auto A = P.make_SparseMatrix<double>().make_Matrix();
125  auto B = Q.make_SparseMatrix<double>().make_Matrix();
126  auto I = Matrix<double>::identity(N);
127  double error = frobenius( gemm(A,B) - I );
128  myra::out() << " |I - P*inverse(P)| = " << error << std::endl;
129  REQUIRE(error < 1.0e-9);
130  }
131 
132 // Tests Permutation*Permutation composition.
133 void test_Permutation4(int N)
134  {
135  // Make random Permutations P and Q.
136  auto P = Permutation::random(N);
137  auto Q = Permutation::random(N);
138  P.verify();
139  Q.verify();
140  auto PQ = multiply(P,Q);
141 
142  // Define random Vector x, copy to y.
143  auto x = Vector<double>::random(N);
144  auto y = x;
145 
146  // Compare P*(Q*x) ..
147  gemv_inplace(Q,x);
148  gemv_inplace(P,x);
149  // .. versus PQ*y
150  gemv_inplace(PQ,y);
151  double error = euclidean(x-y);
152  myra::out() << " |P*(Q*x) - (P*Q)*x| = " << error << std::endl;
153  REQUIRE(error < 1.0e-9);
154  }
155 
156 } // namespace
157 
158 ADD_TEST("Permutation","[sparse]")
159  {
160  test_Permutation1(20);
161  test_Permutation2(20);
162  test_Permutation3(20);
163  test_Permutation4(20);
164  }
Routines for computing euclidean norm of a Vector/VectorRange, or normalizing a Vector/VectorRange to...
Tabulates an IxJ matrix. Allows random access, has column major layout to be compatible with BLAS/LAP...
Definition: bdsqr.h:20
Variety of routines for mixed dense*sparse or dense*sparse matrix multiplies. The dense*dense case is...
Routines for computing Frobenius norms of various algebraic containers.
static Matrix< Number > random(int I, int J)
Generates a random Matrix of specified size.
Definition: Matrix.cpp:353
General purpose compressed-sparse-column (CSC) container.
static Vector< Number > random(int N)
Generates a random Vector of specified size.
Definition: Vector.cpp:276
Definition: syntax.dox:1
static Matrix< Number > identity(int IJ)
Generates an identity Matrix of specified size.
Definition: Matrix.cpp:349
Signatures for sparse matrix * dense vector multiplies. All delegate to gemm() under the hood...
General purpose dense matrix container, O(i*j) storage.
Tabulates a vector of length N, allows random access.
Definition: conjugate.h:21
Container for either a column vector or row vector (depends upon the usage context) ...
Overwrites a LowerMatrix, DiagonalMatrix, or square Matrix with its own inverse. Or, returns it as a copy.
Aggregates a (perm, iperm, swaps) triple into a vocabulary type.
Returns frobenius norm of a SparseMatrix.
static Permutation random(int N)
Generates a random Matrix of specified size.
Definition: Permutation.cpp:188
Variety of routines all for dense Matrix*Matrix multiplies. Delegates to the BLAS.
Interface class for representing subranges of contiguous int&#39;s.


Results: [PASS]

|PX-AX| = 0
|P'X-A'X| = 0
|XP-XA| = 0
|XP'-XA'| = 0
|Px-Ax| = 0
|P'x-A'x| = 0
|I - P*inverse(P)| = 0
|P*(Q*x) - (P*Q)*x| = 0


Go back to Summary of /test programs.