Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,4 @@
---
category:
- Matrices
from: http://rosettacode.org/wiki/Conjugate_transpose

View file

@ -0,0 +1,33 @@
Suppose that a [[matrix]] <big><math>M</math></big> contains [[Arithmetic/Complex|complex numbers]]. Then the [[wp:conjugate transpose|conjugate transpose]] of <math>M</math> is a matrix <math>M^H</math> containing the [[complex conjugate]]s of the [[matrix transposition]] of <math>M</math>.
::: <big><math>(M^H)_{ji} = \overline{M_{ij}}</math></big>
This means that row <big><math>j</math></big>, column <big><math>i</math></big> of the conjugate transpose equals the
<br>complex conjugate of row <big><math>i</math></big>, column <big><math>j</math></big> of the original matrix.
In the next list, <big><math>M</math></big> must also be a square matrix.
* A [[wp:Hermitian matrix|Hermitian matrix]] equals its own conjugate transpose: <math>M^H = M</math>.
* A [[wp:normal matrix|normal matrix]] is commutative in [[matrix multiplication|multiplication]] with its conjugate transpose: <math>M^HM = MM^H</math>.
* A [[wp:unitary matrix|unitary matrix]] has its [[inverse matrix|inverse]] equal to its conjugate transpose: <math>M^H = M^{-1}</math>. <br> This is true [[wikt:iff|iff]] <math>M^HM = I_n</math> and iff <math>MM^H = I_n</math>, where <math>I_n</math> is the identity matrix.
<br>
;Task:
Given some matrix of complex numbers, find its conjugate transpose.
Also determine if the matrix is a:
::* Hermitian matrix,
::* normal matrix, or
::* unitary matrix.
;See also:
* MathWorld entry: [http://mathworld.wolfram.com/ConjugateTranspose.html conjugate transpose]
* MathWorld entry: [http://mathworld.wolfram.com/HermitianMatrix.html Hermitian matrix]
* MathWorld entry: [http://mathworld.wolfram.com/NormalMatrix.html normal matrix]
* MathWorld entry: [http://mathworld.wolfram.com/UnitaryMatrix.html unitary matrix]
<br><br>

View file

@ -0,0 +1,94 @@
-V eps = 1e-10
F to_str(m)
V r =
L(row) m
V i = L.index
r = I i == 0 {[} E
L(val) row
V j = L.index
I j != 0
r =
r = (#2.4, #2.4).format(val.real, val.imag)
r = I i == m.len - 1 {]} E "\n"
R r
F conjugateTransposed(m)
V r = [[0i] * m.len] * m.len
L(i) 0 .< m.len
L(j) 0 .< m.len
r[j][i] = conjugate(m[i][j])
R r
F mmul(m1, m2)
V r = [[0i] * m1.len] * m1.len
L(i) 0 .< m1.len
L(j) 0 .< m1.len
L(k) 0 .< m1.len
r[i][j] += m1[i][k] * m2[k][j]
R r
F isHermitian(m)
L(i) 0 .< m.len
L(j) 0 .< m.len
I m[i][j] != conjugate(m[j][i])
R 0B
R 1B
F isEqual(m1, m2)
L(i) 0 .< m1.len
L(j) 0 .< m1.len
I m1[i][j] != m2[i][j]
R 0B
R 1B
F isNormal(m)
V h = conjugateTransposed(m)
R isEqual(mmul(m, h), mmul(h, m))
F isIdentity(m)
L(i) 0 .< m.len
L(j) 0 .< m.len
I i == j
I abs(m[i][j] - 1.0) > :eps
R 0B
E
I abs(m[i][j]) > :eps
R 0B
R 1B
F isUnitary(m)
V h = conjugateTransposed(m)
R isIdentity(mmul(m, h)) & isIdentity(mmul(h, m))
F test(m)
print(Matrix)
print(------)
print(to_str(m))
print()
print(Conjugate transposed)
print(--------------------)
print(to_str(conjugateTransposed(m)))
print()
print(Hermitian: (I isHermitian(m) {true} E false))
print(Normal: (I isNormal(m) {true} E false))
print(Unitary: (I isUnitary(m) {true} E false))
V M2 = [[3.0 + 0.0i, 2.0 + 1.0i],
[2.0 - 1.0i, 1.0 + 0.0i]]
V M3 = [[1.0 + 0.0i, 1.0 + 0.0i, 0.0 + 0.0i],
[0.0 + 0.0i, 1.0 + 0.0i, 1.0 + 0.0i],
[1.0 + 0.0i, 0.0 + 0.0i, 1.0 + 0.0i]]
V SR2 = 1 / sqrt(2.0)
V SR2i = SR2 * 1i
V M4 = [[SR2 + 0.0i, SR2 + 0.0i, 0.0 + 0.0i],
[0.0 + SR2i, 0.0 - SR2i, 0.0 + 0.0i],
[0.0 + 0.0i, 0.0 + 0.0i, 0.0 + 1.0i]]
test(M2)
print("\n")
test(M3)
print("\n")
test(M4)

View file

@ -0,0 +1,99 @@
BEGIN # find and classify the complex conjugate transpose of a complex matrix #
# returns the conjugate transpose of m #
OP CONJUGATETRANSPOSE = ( [,]COMPL m )[,]COMPL:
BEGIN
[ 2 LWB m : 2 UPB m, 1 LWB m : 1 UPB m ]COMPL result;
FOR i FROM 1 LWB m TO 1 UPB m DO
FOR j FROM 2 LWB m TO 2 UPB m DO
result[ j, i ] := CONJ m[ i, j ]
OD
OD;
result
END # CONJUGATETRANSPOSE # ;
# returns TRUE if m is an identity matrix, FALSE otherwise #
OP ISIDENTITY = ( [,]COMPL m )BOOL:
IF 1 LWB m /= 2 LWB m OR 1 UPB m /= 2 UPB m THEN
# non-square matrix #
FALSE
ELSE
# the matrix is square #
# returns TRUE IF v - e is nearly 0, FALSE Otherwise #
PROC nearly equal = ( COMPL v, REAL e )BOOL: ABS re OF v - e < 1e-14 AND ABS im OF v < 1e-14;
BOOL result := TRUE;
FOR i FROM 1 LWB m TO 1 UPB m WHILE result DO
IF result := nearly equal( m[ i, i ], 1 ) THEN
# the diagonal element is 1 - test the non-diagonals #
FOR j FROM 1 LWB m TO 1 UPB m WHILE result DO
IF i /= j THEN result := nearly equal( m[ i, j ], 0 ) FI
OD
FI
OD;
result
FI # ISIDENTITY # ;
# returns m multiplied by n #
PRIO X = 7;
OP X = ( [,]COMPL m, n )[,]COMPL:
BEGIN
[ 1 : 1 UPB m, 1 : 2 UPB n ]COMPL r;
FOR i FROM 1 LWB m TO 1 UPB m DO
FOR j FROM 2 LWB n TO 2 UPB n DO
r[ i, j ] := 0;
FOR k TO 2 UPB n DO
r[ i, j ] +:= m[ i, k ] * n[ k, j ]
OD
OD
OD;
r
END # X # ;
# prints the complex matris m #
PROC show matrix = ( [,]COMPL m )VOID:
FOR i FROM 1 LWB m TO 1 UPB m DO
print( ( " " ) );
FOR j FROM 2 LWB m TO 2 UPB m DO
print( ( "( ", fixed( re OF m[ i, j ], -8, 4 )
, ", ", fixed( im OF m[ i, j ], -8, 4 )
, "i )"
)
)
OD;
print( ( newline ) )
OD # show matrix # ;
# display the matrix m, its conjugate transpose and whether it is Hermitian, Normal and Unitary #
PROC show = ( [,]COMPL m )VOID:
BEGIN
[,]COMPL c = CONJUGATETRANSPOSE m;
[,]COMPL cm = c X m;
[,]COMPL mc = m X c;
print( ( "Matrix:", newline ) );
show matrix( m );
print( ( "Conjugate Transpose:", newline ) );
show matrix( c );
BOOL is normal = cm = mc;
BOOL is unitary = IF NOT is normal THEN FALSE
ELSE ISIDENTITY mc
FI;
print( ( IF c = m THEN "" ELSE "not " FI, "Hermitian; "
, IF is normal THEN "" ELSE "not " FI, "Normal; "
, IF is unitary THEN "" ELSE "not " FI, "Unitary"
, newline
)
);
print( ( newline ) )
END # show # ;
# test some matrices for Hermitian, Normal and Unitary #
show( ( ( ( 3.0000 I 0.0000 ), ( 2.0000 I 1.0000 ) )
, ( ( 2.0000 I -1.0000 ), ( 1.0000 I 0.0000 ) )
)
);
show( ( ( ( 1.0000 I 0.0000 ), ( 1.0000 I 0.0000 ), ( 0.0000 I 0.0000 ) )
, ( ( 0.0000 I 0.0000 ), ( 1.0000 I 0.0000 ), ( 1.0000 I 0.0000 ) )
, ( ( 1.0000 I 0.0000 ), ( 0.0000 I 0.0000 ), ( 1.0000 I 0.0000 ) )
)
);
REAL rh = sqrt( 0.5 );
show( ( ( ( rh I 0.0000 ), ( rh I 0.0000 ), ( 0.0000 I 0.0000 ) )
, ( ( 0.0000 I rh ), ( 0.0000 I - rh ), ( 0.0000 I 0.0000 ) )
, ( ( 0.0000 I 0.0000 ), ( 0.0000 I 0.0000 ), ( 0.0000 I 1.0000 ) )
)
)
END

View file

@ -0,0 +1,47 @@
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Complex_Text_IO; use Ada.Complex_Text_IO;
with Ada.Numerics.Complex_Types; use Ada.Numerics.Complex_Types;
with Ada.Numerics.Complex_Arrays; use Ada.Numerics.Complex_Arrays;
procedure ConTrans is
subtype CM is Complex_Matrix;
S2O2 : constant Float := 0.7071067811865;
procedure Print (mat : CM) is begin
for row in mat'Range(1) loop for col in mat'Range(2) loop
Put(mat(row,col), Exp=>0, Aft=>4);
end loop; New_Line; end loop;
end Print;
function almostzero(mat : CM; tol : Float) return Boolean is begin
for row in mat'Range(1) loop for col in mat'Range(2) loop
if abs(mat(row,col)) > tol then return False; end if;
end loop; end loop;
return True;
end almostzero;
procedure Examine (mat : CM) is
CT : CM := Conjugate (Transpose(mat));
isherm, isnorm, isunit : Boolean;
begin
isherm := almostzero(mat-CT, 1.0e-6);
isnorm := almostzero(mat*CT-CT*mat, 1.0e-6);
isunit := almostzero(CT-Inverse(mat), 1.0e-6);
Print(mat);
Put_Line("Conjugate transpose:"); Print(CT);
Put_Line("Hermitian?: " & isherm'Img);
Put_Line("Normal?: " & isnorm'Img);
Put_Line("Unitary?: " & isunit'Img);
end Examine;
hmat : CM := ((3.0+0.0*i, 2.0+1.0*i), (2.0-1.0*i, 1.0+0.0*i));
nmat : CM := ((1.0+0.0*i, 1.0+0.0*i, 0.0+0.0*i),
(0.0+0.0*i, 1.0+0.0*i, 1.0+0.0*i),
(1.0+0.0*i, 0.0+0.0*i, 1.0+0.0*i));
umat : CM := ((S2O2+0.0*i, S2O2+0.0*i, 0.0+0.0*i),
(0.0+S2O2*i, 0.0-S2O2*i, 0.0+0.0*i),
(0.0+0.0*i, 0.0+0.0*i, 0.0+1.0*i));
begin
Put_Line("hmat:"); Examine(hmat); New_Line;
Put_Line("nmat:"); Examine(nmat); New_Line;
Put_Line("umat:"); Examine(umat);
end ConTrans;

View file

@ -0,0 +1,191 @@
#include <cassert>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vector>
template <typename scalar_type> class complex_matrix {
public:
using element_type = std::complex<scalar_type>;
complex_matrix(size_t rows, size_t columns)
: rows_(rows), columns_(columns), elements_(rows * columns) {}
complex_matrix(size_t rows, size_t columns, element_type value)
: rows_(rows), columns_(columns), elements_(rows * columns, value) {}
complex_matrix(size_t rows, size_t columns,
const std::initializer_list<std::initializer_list<element_type>>& values)
: rows_(rows), columns_(columns), elements_(rows * columns) {
assert(values.size() <= rows_);
size_t i = 0;
for (const auto& row : values) {
assert(row.size() <= columns_);
std::copy(begin(row), end(row), &elements_[i]);
i += columns_;
}
}
size_t rows() const { return rows_; }
size_t columns() const { return columns_; }
const element_type& operator()(size_t row, size_t column) const {
assert(row < rows_);
assert(column < columns_);
return elements_[row * columns_ + column];
}
element_type& operator()(size_t row, size_t column) {
assert(row < rows_);
assert(column < columns_);
return elements_[row * columns_ + column];
}
friend bool operator==(const complex_matrix& a, const complex_matrix& b) {
return a.rows_ == b.rows_ && a.columns_ == b.columns_ &&
a.elements_ == b.elements_;
}
private:
size_t rows_;
size_t columns_;
std::vector<element_type> elements_;
};
template <typename scalar_type>
complex_matrix<scalar_type> product(const complex_matrix<scalar_type>& a,
const complex_matrix<scalar_type>& b) {
assert(a.columns() == b.rows());
size_t arows = a.rows();
size_t bcolumns = b.columns();
size_t n = a.columns();
complex_matrix<scalar_type> c(arows, bcolumns);
for (size_t i = 0; i < arows; ++i) {
for (size_t j = 0; j < n; ++j) {
for (size_t k = 0; k < bcolumns; ++k)
c(i, k) += a(i, j) * b(j, k);
}
}
return c;
}
template <typename scalar_type>
complex_matrix<scalar_type>
conjugate_transpose(const complex_matrix<scalar_type>& a) {
size_t rows = a.rows(), columns = a.columns();
complex_matrix<scalar_type> b(columns, rows);
for (size_t i = 0; i < columns; i++) {
for (size_t j = 0; j < rows; j++) {
b(i, j) = std::conj(a(j, i));
}
}
return b;
}
template <typename scalar_type>
std::string to_string(const std::complex<scalar_type>& c) {
std::ostringstream out;
const int precision = 6;
out << std::fixed << std::setprecision(precision);
out << std::setw(precision + 3) << c.real();
if (c.imag() > 0)
out << " + " << std::setw(precision + 2) << c.imag() << 'i';
else if (c.imag() == 0)
out << " + " << std::setw(precision + 2) << 0.0 << 'i';
else
out << " - " << std::setw(precision + 2) << -c.imag() << 'i';
return out.str();
}
template <typename scalar_type>
void print(std::ostream& out, const complex_matrix<scalar_type>& a) {
size_t rows = a.rows(), columns = a.columns();
for (size_t row = 0; row < rows; ++row) {
for (size_t column = 0; column < columns; ++column) {
if (column > 0)
out << ' ';
out << to_string(a(row, column));
}
out << '\n';
}
}
template <typename scalar_type>
bool is_hermitian_matrix(const complex_matrix<scalar_type>& matrix) {
if (matrix.rows() != matrix.columns())
return false;
return matrix == conjugate_transpose(matrix);
}
template <typename scalar_type>
bool is_normal_matrix(const complex_matrix<scalar_type>& matrix) {
if (matrix.rows() != matrix.columns())
return false;
auto c = conjugate_transpose(matrix);
return product(c, matrix) == product(matrix, c);
}
bool is_equal(const std::complex<double>& a, double b) {
constexpr double e = 1e-15;
return std::abs(a.imag()) < e && std::abs(a.real() - b) < e;
}
template <typename scalar_type>
bool is_identity_matrix(const complex_matrix<scalar_type>& matrix) {
if (matrix.rows() != matrix.columns())
return false;
size_t rows = matrix.rows();
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < rows; ++j) {
if (!is_equal(matrix(i, j), scalar_type(i == j ? 1 : 0)))
return false;
}
}
return true;
}
template <typename scalar_type>
bool is_unitary_matrix(const complex_matrix<scalar_type>& matrix) {
if (matrix.rows() != matrix.columns())
return false;
auto c = conjugate_transpose(matrix);
auto p = product(c, matrix);
return is_identity_matrix(p) && p == product(matrix, c);
}
template <typename scalar_type>
void test(const complex_matrix<scalar_type>& matrix) {
std::cout << "Matrix:\n";
print(std::cout, matrix);
std::cout << "Conjugate transpose:\n";
print(std::cout, conjugate_transpose(matrix));
std::cout << std::boolalpha;
std::cout << "Hermitian: " << is_hermitian_matrix(matrix) << '\n';
std::cout << "Normal: " << is_normal_matrix(matrix) << '\n';
std::cout << "Unitary: " << is_unitary_matrix(matrix) << '\n';
}
int main() {
using matrix = complex_matrix<double>;
matrix matrix1(3, 3, {{{2, 0}, {2, 1}, {4, 0}},
{{2, -1}, {3, 0}, {0, 1}},
{{4, 0}, {0, -1}, {1, 0}}});
double n = std::sqrt(0.5);
matrix matrix2(3, 3, {{{n, 0}, {n, 0}, {0, 0}},
{{0, -n}, {0, n}, {0, 0}},
{{0, 0}, {0, 0}, {0, 1}}});
matrix matrix3(3, 3, {{{2, 2}, {3, 1}, {-3, 5}},
{{2, -1}, {4, 1}, {0, 0}},
{{7, -5}, {1, -4}, {1, 0}}});
test(matrix1);
std::cout << '\n';
test(matrix2);
std::cout << '\n';
test(matrix3);
return 0;
}

View file

@ -0,0 +1,181 @@
/* Uses C99 specified complex.h, complex datatype has to be defined and operation provided if used on non-C99 compilers */
#include<stdlib.h>
#include<stdio.h>
#include<complex.h>
typedef struct
{
int rows, cols;
complex **z;
} matrix;
matrix
transpose (matrix a)
{
int i, j;
matrix b;
b.rows = a.cols;
b.cols = a.rows;
b.z = malloc (b.rows * sizeof (complex *));
for (i = 0; i < b.rows; i++)
{
b.z[i] = malloc (b.cols * sizeof (complex));
for (j = 0; j < b.cols; j++)
{
b.z[i][j] = conj (a.z[j][i]);
}
}
return b;
}
int
isHermitian (matrix a)
{
int i, j;
matrix b = transpose (a);
if (b.rows == a.rows && b.cols == a.cols)
{
for (i = 0; i < b.rows; i++)
{
for (j = 0; j < b.cols; j++)
{
if (b.z[i][j] != a.z[i][j])
return 0;
}
}
}
else
return 0;
return 1;
}
matrix
multiply (matrix a, matrix b)
{
matrix c;
int i, j;
if (a.cols == b.rows)
{
c.rows = a.rows;
c.cols = b.cols;
c.z = malloc (c.rows * (sizeof (complex *)));
for (i = 0; i < c.rows; i++)
{
c.z[i] = malloc (c.cols * sizeof (complex));
c.z[i][j] = 0 + 0 * I;
for (j = 0; j < b.cols; j++)
{
c.z[i][j] += a.z[i][j] * b.z[j][i];
}
}
}
return c;
}
int
isNormal (matrix a)
{
int i, j;
matrix a_ah, ah_a;
if (a.rows != a.cols)
return 0;
a_ah = multiply (a, transpose (a));
ah_a = multiply (transpose (a), a);
for (i = 0; i < a.rows; i++)
{
for (j = 0; j < a.cols; j++)
{
if (a_ah.z[i][j] != ah_a.z[i][j])
return 0;
}
}
return 1;
}
int
isUnitary (matrix a)
{
matrix b;
int i, j;
if (isNormal (a) == 1)
{
b = multiply (a, transpose(a));
for (i = 0; i < b.rows; i++)
{
for (j = 0; j < b.cols; j++)
{
if ((i == j && b.z[i][j] != 1) || (i != j && b.z[i][j] != 0))
return 0;
}
}
return 1;
}
return 0;
}
int
main ()
{
complex z = 3 + 4 * I;
matrix a, aT;
int i, j;
printf ("Enter rows and columns :");
scanf ("%d%d", &a.rows, &a.cols);
a.z = malloc (a.rows * sizeof (complex *));
printf ("Randomly Generated Complex Matrix A is : ");
for (i = 0; i < a.rows; i++)
{
printf ("\n");
a.z[i] = malloc (a.cols * sizeof (complex));
for (j = 0; j < a.cols; j++)
{
a.z[i][j] = rand () % 10 + rand () % 10 * I;
printf ("\t%f + %fi", creal (a.z[i][j]), cimag (a.z[i][j]));
}
}
aT = transpose (a);
printf ("\n\nTranspose of Complex Matrix A is : ");
for (i = 0; i < aT.rows; i++)
{
printf ("\n");
aT.z[i] = malloc (aT.cols * sizeof (complex));
for (j = 0; j < aT.cols; j++)
{
aT.z[i][j] = rand () % 10 + rand () % 10 * I;
printf ("\t%f + %fi", creal (aT.z[i][j]), cimag (aT.z[i][j]));
}
}
printf ("\n\nComplex Matrix A %s hermitian",
isHermitian (a) == 1 ? "is" : "is not");
printf ("\n\nComplex Matrix A %s unitary",
isUnitary (a) == 1 ? "is" : "is not");
printf ("\n\nComplex Matrix A %s normal",
isNormal (a) == 1 ? "is" : "is not");
return 0;
}

View file

@ -0,0 +1,30 @@
(defun matrix-multiply (m1 m2)
(mapcar
(lambda (row)
(apply #'mapcar
(lambda (&rest column)
(apply #'+ (mapcar #'* row column))) m2)) m1))
(defun identity-p (m &optional (tolerance 1e-6))
"Is m an identity matrix?"
(loop for row in m
for r = 1 then (1+ r) do
(loop for col in row
for c = 1 then (1+ c) do
(if (eql r c)
(unless (< (abs (- col 1)) tolerance) (return-from identity-p nil))
(unless (< (abs col) tolerance) (return-from identity-p nil)) )))
T )
(defun conjugate-transpose (m)
(apply #'mapcar #'list (mapcar #'(lambda (r) (mapcar #'conjugate r)) m)) )
(defun hermitian-p (m)
(equalp m (conjugate-transpose m)))
(defun normal-p (m)
(let ((m* (conjugate-transpose m)))
(equalp (matrix-multiply m m*) (matrix-multiply m* m)) ))
(defun unitary-p (m)
(identity-p (matrix-multiply m (conjugate-transpose m))) )

View file

@ -0,0 +1,107 @@
import std.stdio, std.complex, std.math, std.range, std.algorithm,
std.numeric;
T[][] conjugateTranspose(T)(in T[][] m) pure nothrow @safe {
auto r = new typeof(return)(m[0].length, m.length);
foreach (immutable nr, const row; m)
foreach (immutable nc, immutable c; row)
r[nc][nr] = c.conj;
return r;
}
bool isRectangular(T)(in T[][] M) pure nothrow @safe @nogc {
return M.all!(row => row.length == M[0].length);
}
T[][] matMul(T)(in T[][] A, in T[][] B) pure nothrow /*@safe*/
in {
assert(A.isRectangular && B.isRectangular &&
!A.empty && !B.empty && A[0].length == B.length);
} body {
auto result = new T[][](A.length, B[0].length);
auto aux = new T[B.length];
foreach (immutable j; 0 .. B[0].length) {
foreach (immutable k, const row; B)
aux[k] = row[j];
foreach (immutable i, const ai; A)
result[i][j] = dotProduct(ai, aux);
}
return result;
}
/// Check any number of complex matrices for equality within
/// some bits of mantissa.
bool areEqual(T)(in Complex!T[][][] matrices, in size_t nBits=20)
pure nothrow /*@safe*/ {
static bool allSame(U)(in U[] v) pure nothrow @nogc {
return v[1 .. $].all!(c => c == v[0]);
}
bool allNearSame(in Complex!T[] v) pure nothrow @nogc {
auto v0 = v[0].Complex!T; // To avoid another cast.
return v[1 .. $].all!(c => feqrel(v0.re, c.re) >= nBits &&
feqrel(v0.im, c.im) >= nBits);
}
immutable x = matrices.map!(m => m.length).array;
if (!allSame(x))
return false;
immutable y = matrices.map!(m => m[0].length).array;
if (!allSame(y))
return false;
foreach (immutable s; 0 .. x[0])
foreach (immutable t; 0 .. y[0])
if (!allNearSame(matrices.map!(m => m[s][t]).array))
return false;
return true;
}
bool isHermitian(T)(in Complex!T[][] m, in Complex!T[][] ct)
pure nothrow /*@safe*/ {
return [m, ct].areEqual;
}
bool isNormal(T)(in Complex!T[][] m, in Complex!T[][] ct)
pure nothrow /*@safe*/ {
return [matMul(m, ct), matMul(ct, m)].areEqual;
}
auto complexIdentitymatrix(in size_t side) pure nothrow /*@safe*/ {
return side.iota.map!(r => side.iota.map!(c => complex(r == c)).array).array;
}
bool isUnitary(T)(in Complex!T[][] m, in Complex!T[][] ct)
pure nothrow /*@safe*/ {
immutable mct = matMul(m, ct);
immutable ident = mct.length.complexIdentitymatrix;
return [mct, matMul(ct, m), ident].areEqual;
}
void main() /*@safe*/ {
alias C = complex;
immutable x = 2 ^^ 0.5 / 2;
immutable data = [[[C(3.0, 0.0), C(2.0, 1.0)],
[C(2.0, -1.0), C(1.0, 0.0)]],
[[C(1.0, 0.0), C(1.0, 0.0), C(0.0, 0.0)],
[C(0.0, 0.0), C(1.0, 0.0), C(1.0, 0.0)],
[C(1.0, 0.0), C(0.0, 0.0), C(1.0, 0.0)]],
[[C(x, 0.0), C(x, 0.0), C(0.0, 0.0)],
[C(0.0, -x), C(0.0, x), C(0.0, 0.0)],
[C(0.0, 0.0), C(0.0, 0.0), C(0.0, 1.0)]]];
foreach (immutable mat; data) {
enum mFormat = "[%([%(%1.3f, %)],\n %)]]";
writefln("Matrix:\n" ~ mFormat, mat);
immutable ct = conjugateTranspose(mat);
"Its conjugate transpose:".writeln;
writefln(mFormat, ct);
writefln("Hermitian? %s.", isHermitian(mat, ct));
writefln("Normal? %s.", isNormal(mat, ct));
writefln("Unitary? %s.\n", isUnitary(mat, ct));
}
}

View file

@ -0,0 +1,90 @@
import std.stdio, std.complex, std.math, std.range, std.algorithm,
std.numeric, std.exception, std.traits;
// alias CM(T) = Complex!T[][]; // Not yet useful.
auto conjugateTranspose(T)(in Complex!T[][] m) pure nothrow /*@safe*/
if (!hasIndirections!T) {
return iota(m[0].length).map!(i => m.transversal(i).map!conj.array).array;
}
T[][] matMul(T)(immutable T[][] A, immutable T[][] B) pure nothrow /*@safe*/ {
immutable Bt = B[0].length.iota.map!(i => B.transversal(i).array).array;
return A.map!(a => Bt.map!(b => a.dotProduct(b)).array).array;
}
/// Check any number of complex matrices for equality within
/// some bits of mantissa.
bool areEqual(T)(in Complex!T[][][] matrices, in size_t nBits=20)
pure nothrow /*@safe*/ {
static bool allSame(U)(in U[] v) pure nothrow @nogc @safe {
return v[1 .. $].all!(c => c == v[0]);
}
bool allNearSame(in Complex!T[] v) pure nothrow @nogc @safe {
auto v0 = v[0].Complex!T; // To avoid another cast.
return v[1 .. $].all!(c => feqrel(v0.re, c.re) >= nBits &&
feqrel(v0.im, c.im) >= nBits);
}
immutable x = matrices.map!(m => m.length).array;
if (!allSame(x))
return false;
immutable y = matrices.map!(m => m[0].length).array;
if (!allSame(y))
return false;
foreach (immutable s; 0 .. x[0])
foreach (immutable t; 0 .. y[0])
if (!allNearSame(matrices.map!(m => m[s][t]).array))
return false;
return true;
}
bool isHermitian(T)(in Complex!T[][] m, in Complex!T[][] ct)
pure nothrow /*@safe*/ {
return [m, ct].areEqual;
}
bool isNormal(T)(immutable Complex!T[][] m, immutable Complex!T[][] ct)
pure nothrow /*@safe*/ {
return [matMul(m, ct), matMul(ct, m)].areEqual;
}
auto complexIdentitymatrix(in size_t side) pure nothrow /*@safe*/ {
return side.iota.map!(r => side.iota.map!(c => complex(r == c)).array).array;
}
bool isUnitary(T)(immutable Complex!T[][] m, immutable Complex!T[][] ct)
pure nothrow /*@safe*/ {
immutable mct = matMul(m, ct);
immutable ident = mct.length.complexIdentitymatrix;
return [mct, matMul(ct, m), ident].areEqual;
}
void main() {
alias C = complex;
immutable x = 2 ^^ 0.5 / 2;
foreach (/*immutable*/ const matrix;
[[[C(3.0, 0.0), C(2.0, 1.0)],
[C(2.0, -1.0), C(1.0, 0.0)]],
[[C(1.0, 0.0), C(1.0, 0.0), C(0.0, 0.0)],
[C(0.0, 0.0), C(1.0, 0.0), C(1.0, 0.0)],
[C(1.0, 0.0), C(0.0, 0.0), C(1.0, 0.0)]],
[[C(x, 0.0), C(x, 0.0), C(0.0, 0.0)],
[C(0.0, -x), C(0.0, x), C(0.0, 0.0)],
[C(0.0, 0.0), C(0.0, 0.0), C(0.0, 1.0)]]]) {
immutable mat = matrix.assumeUnique; //*
enum mFormat = "[%([%(%1.3f, %)],\n %)]]";
writefln("Matrix:\n" ~ mFormat, mat);
immutable ct = conjugateTranspose(mat);
"Its conjugate transpose:".writeln;
writefln(mFormat, ct);
writefln("Hermitian? %s.", isHermitian(mat, ct));
writefln("Normal? %s.", isNormal(mat, ct));
writefln("Unitary? %s.\n", isUnitary(mat, ct));
}
}

View file

@ -0,0 +1,5 @@
// Conjugate transpose. Nigel Galloway: January 10th., 2022
let fN g=let g=g|>List.map(List.map(fun(n,g)->System.Numerics.Complex(n,g)))|>MathNet.Numerics.LinearAlgebra.MatrixExtensions.matrix in (g,g.ConjugateTranspose())
let fG n g=(MathNet.Numerics.LinearAlgebra.Matrix.inverse n-g)|>MathNet.Numerics.LinearAlgebra.Matrix.forall(fun(n:System.Numerics.Complex)->abs n.Real<1e-14&&abs n.Imaginary<1e-14)
let test=[fN [[(3.0,0.0);(2.0,1.0)];[(2.0,-1.0);(1.0,0.0)]];fN [[(1.0,0.0);(1.0,0.0);(0.0,0.0)];[(0.0,0.0);(1.0,0.0);(1.0,0.0)];[(1.0,0.0);(0.0,0.0);(1.0,0.0)]];fN [[(1.0/sqrt 2.0,0.0);(1.0/sqrt 2.0,0.0);(0.0,0.0)];[(0.0,1.0/sqrt 2.0);(0.0,-1.0/sqrt 2.0);(0.0,0.0)];[(0.0,0.0);(0.0,0.0);(0.0,1.0)]]]
test|>List.iter(fun(n,g)->printfn $"Matrix\n------\n%A{n}\nConjugate transposed\n--------------------\n%A{g}\nIs hermitian: %A{n.IsHermitian()}\nIs normal: %A{n*g=g*n}\nIs unitary: %A{fG n g}\n")

View file

@ -0,0 +1,14 @@
USING: kernel math.functions math.matrices sequences ;
IN: rosetta.hermitian
: conj-t ( matrix -- conjugate-transpose )
flip [ [ conjugate ] map ] map ;
: hermitian-matrix? ( matrix -- ? )
dup conj-t = ;
: normal-matrix? ( matrix -- ? )
dup conj-t [ m. ] [ swap m. ] 2bi = ;
: unitary-matrix? ( matrix -- ? )
[ dup conj-t m. ] [ length identity-matrix ] bi = ;

View file

@ -0,0 +1,64 @@
program conjugate_transpose
complex, dimension(3, 3) :: a
integer :: i
a = reshape((/ (i, i=1,9) /), shape(a))
call characterize(a)
a(:2,:2) = reshape((/cmplx(3,0),cmplx(2,-1),cmplx(2,1),cmplx(1,0)/),(/2,2/))
call characterize(a(:2,:2))
call characterize(cmplx(reshape((/1,0,1,1,1,0,0,1,1/),(/3,3/)),0))
a(3,:) = (/cmplx(0,0), cmplx(0,0), cmplx(0,1)/)*sqrt(2.0)
a(2,:) = (/cmplx(0,-1),cmplx(0,1),cmplx(0,0)/)
a(1,:) = (/1,1,0/)
a = a * sqrt(2.0)/2.0
call characterize(a)
contains
subroutine characterize(a)
complex, dimension(:,:), intent(in) :: a
integer :: i, j
do i=1, size(a,1)
print *,(a(i, j), j=1,size(a,1))
end do
print *,'Is Hermitian? ',HermitianQ(a)
print *,'Is normal? ',NormalQ(a)
print *,'Unitary? ',UnitaryQ(a)
print '(/)'
end subroutine characterize
function ct(a) result(b) ! return the conjugate transpose of a matrix
complex, dimension(:,:), intent(in) :: a
complex, dimension(size(a,1),size(a,1)) :: b
b = conjg(transpose(a))
end function ct
function identity(n) result(b) ! return identity matrix
integer, intent(in) :: n
real, dimension(n,n) :: b
integer :: i
b = 0
do i=1, n
b(i,i) = 1
end do
end function identity
logical function HermitianQ(a)
complex, dimension(:,:), intent(in) :: a
HermitianQ = all(a .eq. ct(a))
end function HermitianQ
logical function NormalQ(a)
complex, dimension(:,:), intent(in) :: a
NormalQ = all(matmul(ct(a),a) .eq. matmul(a,ct(a)))
end function NormalQ
logical function UnitaryQ(a)
! if A inverse equals A star
! then multiplying each side by A should result in the identity matrix
! Thus show that A times A star is sufficiently close to I .
complex, dimension(:,:), intent(in) :: a
UnitaryQ = all(abs(matmul(a,ct(a)) - identity(size(a,1))) .lt. 1e-6)
end function UnitaryQ
end program conjugate_transpose

View file

@ -0,0 +1,130 @@
'complex type and operators for it
type complex
real as double
imag as double
end type
operator + ( a as complex, b as complex ) as complex
dim as complex r
r.real = a.real + b.real
r.imag = a.imag + b.imag
return r
end operator
operator * ( a as complex, b as complex ) as complex
dim as complex r
r.real = a.real*b.real - a.imag*b.imag
r.imag = a.real*b.imag + b.real*a.imag
return r
end operator
operator = ( a as complex, b as complex ) as boolean
if not a.real = b.real then return false
if not a.imag = b.imag then return false
return true
end operator
function complex_conjugate( a as complex ) as complex
dim as complex r
r.real = a.real
r.imag = -a.imag
return r
end function
'matrix type and operations for it
'reuses code from the matrix multiplication task
type Matrix
dim as complex m( any , any )
declare constructor ( )
declare constructor ( byval x as uinteger )
end type
constructor Matrix ( )
end constructor
constructor Matrix ( byval x as uinteger )
redim this.m( x - 1 , x - 1 )
end constructor
operator * ( byref a as Matrix , byref b as Matrix ) as Matrix
dim as Matrix ret
dim as uinteger i, j, k
redim ret.m( ubound( a.m , 1 ) , ubound( a.m , 1 ) )
for i = 0 to ubound( a.m , 1 )
for j = 0 to ubound( b.m , 2 )
for k = 0 to ubound( b.m , 1 )
ret.m( i , j ) += a.m( i , k ) * b.m( k , j )
next k
next j
next i
return ret
end operator
function conjugate_transpose( byref a as Matrix ) as Matrix
dim as Matrix ret
dim as uinteger i, j
redim ret.m( ubound( a.m , 1 ) , ubound( a.m , 1 ) )
for i = 0 to ubound( a.m , 1 )
for j = 0 to ubound( a.m , 2 )
ret.m( i, j ) = complex_conjugate(a.m( j, i ))
next j
next i
return ret
end function
'tests if matrices are unitary, hermitian, or normal
operator = (byref a as Matrix, byref b as matrix) as boolean
dim as integer i, j
if ubound(a.m, 1) <> ubound(b.m, 1) then return false
for i = 0 to ubound( a.m , 1 )
for j = 0 to ubound( a.m , 2 )
if not a.m(i,j)=b.m(i,j) then return false
next j
next i
return true
end operator
function is_identity( byref a as Matrix ) as boolean
dim as integer i, j
for i = 0 to ubound( a.m , 1 )
for j = 0 to ubound( a.m , 2 )
if i = j and ( not a.m(i,j).real = 1.0 or not a.m(i,j).imag = 0.0 ) then return false
if i <> j and ( not a.m(i,j).real = 0.0 or not a.m(i,j).imag = 0.0 ) then return false
next j
next i
return true
end function
function is_hermitian( byref a as Matrix ) as boolean
if a = conjugate_transpose(a) then return true
return false
end function
function is_normal( byref a as Matrix ) as boolean
dim as Matrix aa = conjugate_transpose(a)
if a*aa = aa*a then return true else return false
end function
function is_unitary( byref a as Matrix ) as boolean
dim as Matrix aa = conjugate_transpose(a)
if not is_identity( a*aa ) or not is_identity( aa*a ) then return false
return true
end function
'''now some example matrices
dim as Matrix A = Matrix(2) 'an identity matrix
A.m(0,0).real = 1.0 : A.m(0,0).imag = 0.0 : A.m(0,1).real = 0.0 : A.m(0,1).imag = 0.0
A.m(1,0).real = 0.0 : A.m(1,0).imag = 0.0 : A.m(1,1).real = 1.0 : A.m(1,1).imag = 0.0
dim as Matrix B = Matrix(2) 'a hermitian matrix
B.m(0,0).real = 1.0 : B.m(0,0).imag = 0.0 : B.m(0,1).real = 1.0 : B.m(0,1).imag = -1.0
B.m(1,0).real = 1.0 : B.m(1,0).imag = 1.0 : B.m(1,1).real = 1.0 : B.m(1,1).imag = 0.0
dim as Matrix C = Matrix(2) 'a random matrix
C.m(0,0).real = rnd : C.m(0,0).imag = rnd : C.m(0,1).real = rnd : C.m(0,1).imag = rnd
C.m(1,0).real = rnd : C.m(1,0).imag = rnd : C.m(1,1).real = rnd : C.m(1,1).imag = rnd
print is_hermitian(A), is_normal(A), is_unitary(A)
print is_hermitian(B), is_normal(B), is_unitary(B)
print is_hermitian(C), is_normal(C), is_unitary(C)

View file

@ -0,0 +1,112 @@
package main
import (
"fmt"
"math"
"math/cmplx"
)
// a type to represent matrices
type matrix struct {
ele []complex128
cols int
}
// conjugate transpose, implemented here as a method on the matrix type.
func (m *matrix) conjTranspose() *matrix {
r := &matrix{make([]complex128, len(m.ele)), len(m.ele) / m.cols}
rx := 0
for _, e := range m.ele {
r.ele[rx] = cmplx.Conj(e)
rx += r.cols
if rx >= len(r.ele) {
rx -= len(r.ele) - 1
}
}
return r
}
// program to demonstrate capabilites on example matricies
func main() {
show("h", matrixFromRows([][]complex128{
{3, 2 + 1i},
{2 - 1i, 1}}))
show("n", matrixFromRows([][]complex128{
{1, 1, 0},
{0, 1, 1},
{1, 0, 1}}))
show("u", matrixFromRows([][]complex128{
{math.Sqrt2 / 2, math.Sqrt2 / 2, 0},
{math.Sqrt2 / -2i, math.Sqrt2 / 2i, 0},
{0, 0, 1i}}))
}
func show(name string, m *matrix) {
m.print(name)
ct := m.conjTranspose()
ct.print(name + "_ct")
fmt.Println("Hermitian:", m.equal(ct, 1e-14))
mct := m.mult(ct)
ctm := ct.mult(m)
fmt.Println("Normal:", mct.equal(ctm, 1e-14))
i := eye(m.cols)
fmt.Println("Unitary:", mct.equal(i, 1e-14) && ctm.equal(i, 1e-14))
}
// two constructors
func matrixFromRows(rows [][]complex128) *matrix {
m := &matrix{make([]complex128, len(rows)*len(rows[0])), len(rows[0])}
for rx, row := range rows {
copy(m.ele[rx*m.cols:(rx+1)*m.cols], row)
}
return m
}
func eye(n int) *matrix {
r := &matrix{make([]complex128, n*n), n}
n++
for x := 0; x < len(r.ele); x += n {
r.ele[x] = 1
}
return r
}
// print method outputs matrix to stdout
func (m *matrix) print(heading string) {
fmt.Print("\n", heading, "\n")
for e := 0; e < len(m.ele); e += m.cols {
fmt.Printf("%6.3f ", m.ele[e:e+m.cols])
fmt.Println()
}
}
// equal method uses ε to allow for floating point error.
func (a *matrix) equal(b *matrix, ε float64) bool {
for x, aEle := range a.ele {
if math.Abs(real(aEle)-real(b.ele[x])) > math.Abs(real(aEle))*ε ||
math.Abs(imag(aEle)-imag(b.ele[x])) > math.Abs(imag(aEle))*ε {
return false
}
}
return true
}
// mult method taken from matrix multiply task
func (m1 *matrix) mult(m2 *matrix) (m3 *matrix) {
m3 = &matrix{make([]complex128, (len(m1.ele)/m1.cols)*m2.cols), m2.cols}
for m1c0, m3x := 0, 0; m1c0 < len(m1.ele); m1c0 += m1.cols {
for m2r0 := 0; m2r0 < m2.cols; m2r0++ {
for m1x, m2x := m1c0, m2r0; m2x < len(m2.ele); m2x += m2.cols {
m3.ele[m3x] += m1.ele[m1x] * m2.ele[m2x]
m1x++
}
m3x++
}
}
return m3
}

View file

@ -0,0 +1,75 @@
import Data.Complex (Complex(..), conjugate)
import Data.List (transpose)
type Matrix a = [[a]]
main :: IO ()
main =
mapM_
(\a -> do
putStrLn "\nMatrix:"
mapM_ print a
putStrLn "Conjugate Transpose:"
mapM_ print (conjTranspose a)
putStrLn $ "Hermitian? " ++ show (isHermitianMatrix a)
putStrLn $ "Normal? " ++ show (isNormalMatrix a)
putStrLn $ "Unitary? " ++ show (isUnitaryMatrix a))
([ [[3, 2 :+ 1], [2 :+ (-1), 1]]
, [[1, 1, 0], [0, 1, 1], [1, 0, 1]]
, [ [sqrt 2 / 2 :+ 0, sqrt 2 / 2 :+ 0, 0]
, [0 :+ sqrt 2 / 2, 0 :+ (-sqrt 2 / 2), 0]
, [0, 0, 0 :+ 1]
]
] :: [Matrix (Complex Double)])
isHermitianMatrix, isNormalMatrix, isUnitaryMatrix
:: RealFloat a
=> Matrix (Complex a) -> Bool
isHermitianMatrix = mTest id conjTranspose
isNormalMatrix = mTest mmct (mmul =<< conjTranspose)
isUnitaryMatrix = mTest mmct (ident . length)
mTest
:: RealFloat a
=> (a2 -> Matrix (Complex a)) -> (a2 -> Matrix (Complex a)) -> a2 -> Bool
mTest f g = (approxEqualMatrix . f) <*> g
mmct
:: RealFloat a
=> Matrix (Complex a) -> Matrix (Complex a)
mmct = mmul <*> conjTranspose
approxEqualMatrix
:: (Fractional a, Ord a)
=> Matrix (Complex a) -> Matrix (Complex a) -> Bool
approxEqualMatrix a b =
length a == length b &&
length (head a) == length (head b) &&
and (zipWith approxEqualComplex (concat a) (concat b))
where
approxEqualComplex (rx :+ ix) (ry :+ iy) =
abs (rx - ry) < eps && abs (ix - iy) < eps
eps = 1e-14
mmul
:: Num a
=> Matrix a -> Matrix a -> Matrix a
mmul a b =
[ [ sum (zipWith (*) row column)
| column <- transpose b ]
| row <- a ]
ident
:: Num a
=> Int -> Matrix a
ident size =
[ [ fromIntegral $ div a b * div b a
| a <- [1 .. size] ]
| b <- [1 .. size] ]
conjTranspose
:: Num a
=> Matrix (Complex a) -> Matrix (Complex a)
conjTranspose = map (map conjugate) . transpose

View file

@ -0,0 +1 @@
ct =: +@|: NB. Conjugate transpose (ct A is A_ct)

View file

@ -0,0 +1,13 @@
X =: +/ . * NB. Matrix Multiply (x)
HERMITIAN =: 3 2j1 ,: 2j_1 1
(-: ct) HERMITIAN NB. A_ct = A
1
NORMAL =: 1 1 0 , 0 1 1 ,: 1 0 1
((X~ -: X) ct) NORMAL NB. A_ct x A = A x A_ct
1
UNITARY =: (-:%:2) * 1 1 0 , 0j_1 0j1 0 ,: 0 0 0j1 * %:2
(ct -: %.) UNITARY NB. A_ct = A^-1
1

View file

@ -0,0 +1,16 @@
HERMITIAN;NORMAL;UNITARY
+--------+-----+--------------------------+
| 3 2j1|1 1 0| 0.707107 0.707107 0|
|2j_1 1|0 1 1|0j_0.707107 0j0.707107 0|
| |1 0 1| 0 0 0j1|
+--------+-----+--------------------------+
NB. In J, PjQ is P + Q*i and the 0.7071... is sqrt(2)
hermitian=: -: ct
normal =: (X~ -: X) ct
unitary=: ct -: %.
(hermitian,normal,unitary)&.>HERMITIAN;NORMAL;UNITARY
+-----+-----+-----+
|1 1 0|0 1 0|0 1 1|
+-----+-----+-----+

View file

@ -0,0 +1,173 @@
import java.util.Arrays;
import java.util.List;
public final class ConjugateTranspose {
public static void main(String[] aArgs) {
ComplexMatrix one = new ComplexMatrix( new Complex[][] { { new Complex(0, 4), new Complex(-1, 1) },
{ new Complex(1, -1), new Complex(0, 4) } } );
ComplexMatrix two = new ComplexMatrix(
new Complex[][] { { new Complex(1, 0), new Complex(1, 1), new Complex(0, 2) },
{ new Complex(1, -1), new Complex(5, 0), new Complex(-3, 0) },
{ new Complex(0, -2), new Complex(-3, 0), new Complex(0, 0) } } );
final double term = 1.0 / Math.sqrt(2.0);
ComplexMatrix three = new ComplexMatrix( new Complex[][] { { new Complex(term, 0), new Complex(term, 0) },
{ new Complex(0, term), new Complex(0, -term) } } );
List<ComplexMatrix> matricies = List.of( one, two, three );
for ( ComplexMatrix matrix : matricies ) {
System.out.println("Matrix:");
matrix.display();
System.out.println("Conjugate transpose:");
matrix.conjugateTranspose().display();
System.out.println("Hermitian: " + matrix.isHermitian());
System.out.println("Normal: " + matrix.isNormal());
System.out.println("Unitary: " + matrix.isUnitary() + System.lineSeparator());
}
}
}
final class ComplexMatrix {
public ComplexMatrix(Complex[][] aData) {
rowCount = aData.length;
colCount = aData[0].length;
data = Arrays.stream(aData).map( row -> Arrays.copyOf(row, row.length) ).toArray(Complex[][]::new);
}
public ComplexMatrix multiply(ComplexMatrix aOther) {
if ( colCount != aOther.rowCount ) {
throw new RuntimeException("Incompatible matrix dimensions.");
}
Complex[][] newData = new Complex[rowCount][aOther.colCount];
Arrays.stream(newData).forEach( row -> Arrays.fill(row, new Complex(0, 0)) );
for ( int row = 0; row < rowCount; row++ ) {
for ( int col = 0; col < aOther.colCount; col++ ) {
for ( int k = 0; k < colCount; k++ ) {
newData[row][col] = newData[row][col].add(data[row][k].multiply(aOther.data[k][col]));
}
}
}
return new ComplexMatrix(newData);
}
public ComplexMatrix conjugateTranspose() {
if ( rowCount != colCount ) {
throw new IllegalArgumentException("Only applicable to a square matrix");
}
Complex[][] newData = new Complex[colCount][rowCount];
for ( int row = 0; row < rowCount; row++ ) {
for ( int col = 0; col < colCount; col++ ) {
newData[col][row] = data[row][col].conjugate();
}
}
return new ComplexMatrix(newData);
}
public static ComplexMatrix identity(int aSize) {
Complex[][] data = new Complex[aSize][aSize];
for ( int row = 0; row < aSize; row++ ) {
for ( int col = 0; col < aSize; col++ ) {
data[row][col] = ( row == col ) ? new Complex(1, 0) : new Complex(0, 0);
}
}
return new ComplexMatrix(data);
}
public boolean equals(ComplexMatrix aOther) {
if ( aOther.rowCount != rowCount || aOther.colCount != colCount ) {
return false;
}
for ( int row = 0; row < rowCount; row++ ) {
for ( int col = 0; col < colCount; col++ ) {
if ( data[row][col].subtract(aOther.data[row][col]).modulus() > EPSILON ) {
return false;
}
}
}
return true;
}
public void display() {
for ( int row = 0; row < rowCount; row++ ) {
System.out.print("[");
for ( int col = 0; col < colCount - 1; col++ ) {
System.out.print(data[row][col] + ", ");
}
System.out.println(data[row][colCount - 1] + " ]");
}
}
public boolean isHermitian() {
return equals(conjugateTranspose());
}
public boolean isNormal() {
ComplexMatrix conjugateTranspose = conjugateTranspose();
return multiply(conjugateTranspose).equals(conjugateTranspose.multiply(this));
}
public boolean isUnitary() {
ComplexMatrix conjugateTranspose = conjugateTranspose();
return multiply(conjugateTranspose).equals(identity(rowCount)) &&
conjugateTranspose.multiply(this).equals(identity(rowCount));
}
private final int rowCount;
private final int colCount;
private final Complex[][] data;
private static final double EPSILON = 0.000_000_000_001;
}
final class Complex {
public Complex(double aReal, double aImag) {
real = aReal;
imag = aImag;
}
public Complex add(Complex aOther) {
return new Complex(real + aOther.real, imag + aOther.imag);
}
public Complex multiply(Complex aOther) {
return new Complex(real * aOther.real - imag * aOther.imag, real * aOther.imag + imag * aOther.real);
}
public Complex negate() {
return new Complex(-real, -imag);
}
public Complex subtract(Complex aOther) {
return this.add(aOther.negate());
}
public Complex conjugate() {
return new Complex(real, -imag);
}
public double modulus() {
return Math.hypot(real, imag);
}
public boolean equals(Complex aOther) {
return real == aOther.real && imag == aOther.imag;
}
@Override
public String toString() {
String prefix = ( real < 0.0 ) ? "" : " ";
String realPart = prefix + String.format("%.3f", real);
String sign = ( imag < 0.0 ) ? " - " : " + ";
return realPart + sign + String.format("%.3f", Math.abs(imag)) + "i";
}
private final double real;
private final double imag;
}

View file

@ -0,0 +1,6 @@
# transpose/0 expects its input to be a rectangular matrix
# (an array of equal-length arrays):
def transpose:
if (.[0] | length) == 0 then []
else [map(.[0])] + (map(.[1:]) | transpose)
end ;

View file

@ -0,0 +1,27 @@
# x must be real or complex, and ditto for y;
# always return complex
def plus(x; y):
if (x|type) == "number" then
if (y|type) == "number" then [ x+y, 0 ]
else [ x + y[0], y[1]]
end
elif (y|type) == "number" then plus(y;x)
else [ x[0] + y[0], x[1] + y[1] ]
end;
# x must be real or complex, and ditto for y;
# always return complex
def multiply(x; y):
if (x|type) == "number" then
if (y|type) == "number" then [ x*y, 0 ]
else [x * y[0], x * y[1]]
end
elif (y|type) == "number" then multiply(y;x)
else [ x[0] * y[0] - x[1] * y[1], x[0] * y[1] + x[1] * y[0]]
end;
# conjugate of a real or complex number
def conjugate:
if type == "number" then [.,0]
else [.[0], -(.[1]) ]
end;

View file

@ -0,0 +1,5 @@
# a and b are arrays of real/complex numbers
def dot_product(a; b):
a as $a | b as $b
| reduce range(0;$a|length) as $i
(0; . as $s | plus($s; multiply($a[$i]; $b[$i]) ));

View file

@ -0,0 +1,38 @@
# convert a matrix of mixed real/complex entries to all complex entries
def to_complex:
def toc: if type == "number" then [.,0] else . end;
map( map(toc) );
# simple matrix pretty-printer
def pp(wide):
def pad: tostring | (wide - length) * " " + .;
def row: reduce .[] as $x (""; . + ($x|pad));
reduce .[] as $row (""; . + "\n\($row|row)");
# Matrix multiplication
# A and B should both be real/complex matrices,
# A being m by n, and B being n by p.
def matrix_multiply(A; B):
A as $A | B as $B
| ($B[0]|length) as $p
| ($B|transpose) as $BT
| reduce range(0; $A|length) as $i
([]; reduce range(0; $p) as $j
(.; .[$i][$j] = dot_product( $A[$i]; $BT[$j] ) )) ;
# Complex identity matrix of dimension n
def complex_identity(n):
def indicator(i;n): [range(0;n)] | map( [0,0]) | .[i] = [1,0];
reduce range(0; n) as $i ([]; . + [indicator( $i; n )] );
# Approximate equality of two matrices
# Are two real/complex matrices essentially equal
# in the sense that the sum of the squared element-wise differences
# is less than or equal to epsilon?
# The two matrices must be conformal.
def approximately_equal(M; N; epsilon):
def norm: multiply(. ; conjugate ) | .[0];
def sqdiff( x; y): plus(x; multiply(y; -1)) | norm;
reduce range(0;M|length) as $i
(0; reduce range(0; M[0]|length) as $j
(.; 0 + sqdiff( M[$i][$j]; N[$i][$j] ) ) ) <= epsilon;

View file

@ -0,0 +1,23 @@
# (entries may be real and/or complex)
def conjugate_transpose:
map( map(conjugate) ) | transpose;
# A Hermitian matrix equals its own conjugate transpose
def is_hermitian:
to_complex == conjugate_transpose;
# A matrix is normal if it commutes multiplicatively
# with its conjugate transpose
def is_normal:
. as $M
| conjugate_transpose as $H
| matrix_multiply($H; $M) == matrix_multiply($H; $M);
# A unitary matrix (U) has its inverse equal to its conjugate transpose (T)
# i.e. U^-1 == T; NASC is I == UT == TU
def is_unitary:
. as $M
| conjugate_transpose as $H
| complex_identity(length) as $I
| approximately_equal( $I; matrix_multiply($H;$M); 1e-10)
and approximately_equal( $I ; matrix_multiply($M;$H); 1e-10) ;

View file

@ -0,0 +1,29 @@
def hermitian_example:
[ [ 3, [2,1]],
[[2,-1], 1 ] ];
def normal_example:
[ [1, 1, 0],
[0, 1, 1],
[1, 0, 1] ];
def unitary_example:
0.707107
| [ [ [., 0], [., 0], 0 ],
[ [0, -.], [0, .], 0 ],
[ 0, 0, [0,1] ] ];
def demo:
hermitian_example
| ("Hermitian example:", pp(8)),
"",
("Its conjugate transpose is:", (to_complex | conjugate_transpose | pp(8))),
"",
"Hermitian example: \(hermitian_example | is_hermitian )",
"",
"Normal example: \(normal_example | is_normal )",
"",
"Unitary example: \(unitary_example | is_unitary)"
;
demo

View file

@ -0,0 +1,16 @@
$ jq -r -c -n -f Conjugate_transpose.jq
Hermitian example:
3 [2,1]
[2,-1] 1
Conjugate transpose:
[3,-0] [2,1]
[2,-1] [1,-0]
Hermitian example: true
Normal example: true
Unitary example: true

View file

@ -0,0 +1 @@
A'

View file

@ -0,0 +1 @@
ishermitian(A)

View file

@ -0,0 +1,3 @@
eye(A) = A^0
isnormal(A) = size(A,1) == size(A,2) && A'*A == A*A'
isunitary(A) = size(A,1) == size(A,2) && A'*A == eye(A)

View file

@ -0,0 +1,125 @@
// version 1.1.3
typealias C = Complex
typealias Vector = Array<C>
typealias Matrix = Array<Vector>
class Complex(val real: Double, val imag: Double) {
operator fun plus(other: Complex) =
Complex(this.real + other.real, this.imag + other.imag)
operator fun times(other: Complex) =
Complex(this.real * other.real - this.imag * other.imag,
this.real * other.imag + this.imag * other.real)
fun conj() = Complex(this.real, -this.imag)
/* tolerable equality allowing for rounding of Doubles */
infix fun teq(other: Complex) =
Math.abs(this.real - other.real) <= 1e-14 &&
Math.abs(this.imag - other.imag) <= 1e-14
override fun toString() = "${"%.3f".format(real)} " + when {
imag > 0.0 -> "+ ${"%.3f".format(imag)}i"
imag == 0.0 -> "+ 0.000i"
else -> "- ${"%.3f".format(-imag)}i"
}
}
fun Matrix.conjTranspose(): Matrix {
val rows = this.size
val cols = this[0].size
return Matrix(cols) { i -> Vector(rows) { j -> this[j][i].conj() } }
}
operator fun Matrix.times(other: Matrix): Matrix {
val rows1 = this.size
val cols1 = this[0].size
val rows2 = other.size
val cols2 = other[0].size
require(cols1 == rows2)
val result = Matrix(rows1) { Vector(cols2) { C(0.0, 0.0) } }
for (i in 0 until rows1) {
for (j in 0 until cols2) {
for (k in 0 until rows2) {
result[i][j] += this[i][k] * other[k][j]
}
}
}
return result
}
/* tolerable matrix equality using the same concept as for complex numbers */
infix fun Matrix.teq(other: Matrix): Boolean {
if (this.size != other.size || this[0].size != other[0].size) return false
for (i in 0 until this.size) {
for (j in 0 until this[0].size) if (!(this[i][j] teq other[i][j])) return false
}
return true
}
fun Matrix.isHermitian() = this teq this.conjTranspose()
fun Matrix.isNormal(): Boolean {
val ct = this.conjTranspose()
return (this * ct) teq (ct * this)
}
fun Matrix.isUnitary(): Boolean {
val ct = this.conjTranspose()
val prod = this * ct
val ident = identityMatrix(prod.size)
val prod2 = ct * this
return (prod teq ident) && (prod2 teq ident)
}
fun Matrix.print() {
val rows = this.size
val cols = this[0].size
for (i in 0 until rows) {
for (j in 0 until cols) {
print(this[i][j])
print(if(j < cols - 1) ", " else "\n")
}
}
println()
}
fun identityMatrix(n: Int): Matrix {
require(n >= 1)
val ident = Matrix(n) { Vector(n) { C(0.0, 0.0) } }
for (i in 0 until n) ident[i][i] = C(1.0, 0.0)
return ident
}
fun main(args: Array<String>) {
val x = Math.sqrt(2.0) / 2.0
val matrices = arrayOf(
arrayOf(
arrayOf(C(3.0, 0.0), C(2.0, 1.0)),
arrayOf(C(2.0, -1.0), C(1.0, 0.0))
),
arrayOf(
arrayOf(C(1.0, 0.0), C(1.0, 0.0), C(0.0, 0.0)),
arrayOf(C(0.0, 0.0), C(1.0, 0.0), C(1.0, 0.0)),
arrayOf(C(1.0, 0.0), C(0.0, 0.0), C(1.0, 0.0))
),
arrayOf(
arrayOf(C(x, 0.0), C(x, 0.0), C(0.0, 0.0)),
arrayOf(C(0.0, -x), C(0.0, x), C(0.0, 0.0)),
arrayOf(C(0.0, 0.0), C(0.0, 0.0), C(0.0, 1.0))
)
)
for (m in matrices) {
println("Matrix:")
m.print()
val mct = m.conjTranspose()
println("Conjugate transpose:")
mct.print()
println("Hermitian? ${mct.isHermitian()}")
println("Normal? ${mct.isNormal()}")
println("Unitary? ${mct.isUnitary()}\n")
}
}

View file

@ -0,0 +1,10 @@
M:=<<3|2+I>,<2-I|1>>:
with(LinearAlgebra):
IsNormal:=A->EqualEntries(A^%H.A,A.A^%H):
M^%H;
HermitianTranspose(M);
type(M,'Matrix'(hermitian));
IsNormal(M);
IsUnitary(M);

View file

@ -0,0 +1,17 @@
NormalMatrixQ[a_List?MatrixQ] := Module[{b = Conjugate@Transpose@a},a.b === b.a]
UnitaryQ[m_List?MatrixQ] := (Conjugate@Transpose@m.m == IdentityMatrix@Length@m)
m = {{1, 2I, 3}, {3+4I, 5, I}};
m //MatrixForm
->
(1 2I 3
3+4I 5 I)
ConjugateTranspose[m] //MatrixForm
->
(1 3-4I
-2I 5
3 -I)
{HermitianMatrixQ@#, NormalMatrixQ@#, UnitaryQ@#}&@m
-> {False, False, False}

View file

@ -0,0 +1,153 @@
import complex, strformat
type Matrix[M, N: static Positive] = array[M, array[N, Complex[float]]]
const Eps = 1e-10 # Tolerance used for float comparisons.
####################################################################################################
# Templates.
template `[]`(m: Matrix; i, j: Natural): Complex[float] =
## Allow to get value of an element using m[i, j] syntax.
m[i][j]
template `[]=`(m: var Matrix; i, j: Natural; val: Complex[float]) =
## Allow to set value of an element using m[i, j] syntax.
m[i][j] = val
####################################################################################################
# General operations.
func `$`(m: Matrix): string =
## Return the string representation of a matrix using one line per row.
for i, row in m:
result.add(if i == 0: '[' else: ' ')
for j, val in row:
if j != 0: result.add(' ')
result.add(&"({val.re:7.4f}, {val.im:7.4f})")
result.add(if i == m.high: ']' else: '\n')
#---------------------------------------------------------------------------------------------------
func conjugateTransposed[M, N: static int](m: Matrix[M, N]): Matrix[N, M] =
## Return the conjugate transpose of a matrix.
for i in 0..<m.M:
for j in 0..<m.N:
result[j, i] = m[i, j].conjugate()
#---------------------------------------------------------------------------------------------------
func `*`[M, K, N: static int](m1: Matrix[M, K]; m2: Matrix[K, N]): Matrix[M, N] =
# Compute the product of two matrices.
for i in 0..<M:
for j in 0..<N:
for k in 0..<K:
result[i, j] = result[i, j] + m1[i, k] * m2[k, j]
####################################################################################################
# Properties.
func isHermitian(m: Matrix): bool =
## Check if a matrix is hermitian.
when m.M != m.N:
{.error: "hermitian test only allowed for square matrices".}
else:
for i in 0..<m.M:
for j in i..<m.N:
if m[i, j] != m[j, i].conjugate:
return false
result = true
#---------------------------------------------------------------------------------------------------
func isNormal(m: Matrix): bool =
## Check if a matrix is normal.
when m.M != m.N:
{.error: "normal test only allowed for square matrices".}
else:
let h = m.conjugateTransposed
result = m * h == h * m
#---------------------------------------------------------------------------------------------------
func isIdentity(m: Matrix): bool =
## Check if a matrix is the identity matrix.
when m.M != m.N:
{.error: "identity test only allowed for square matrices".}
else:
for i in 0..<m.M:
for j in 0..<m.N:
if i == j:
if abs(m[i, j] - 1.0) > Eps:
return false
else:
if abs(m[i, j]) > Eps:
return false
result = true
#---------------------------------------------------------------------------------------------------
func isUnitary(m: Matrix): bool =
## Check if a matrix is unitary.
when m.M != m.N:
{.error: "unitary test only allowed for square matrices".}
else:
let h = m.conjugateTransposed
result = (m * h).isIdentity and (h * m).isIdentity
#———————————————————————————————————————————————————————————————————————————————————————————————————
when isMainModule:
import math
proc test(m: Matrix) =
echo "\n"
echo "Matrix"
echo "------"
echo m
echo ""
echo "Conjugate transposed"
echo "--------------------"
echo m.conjugateTransposed
when m.M == m.N:
# Only for squares matrices.
echo ""
echo "Hermitian: ", m.isHermitian
echo "Normal: ", m.isNormal
echo "Unitary: ", m.isUnitary
#-------------------------------------------------------------------------------------------------
# Non square matrix.
const M1: Matrix[2, 3] = [[1.0 + im 2.0, 3.0 + im 0.0, 2.0 + im 5.0],
[3.0 - im 1.0, 2.0 + im 0.0, 0.0 + im 3.0]]
# Square matrices.
const M2: Matrix[2, 2] = [[3.0 + im 0.0, 2.0 + im 1.0],
[2.0 - im 1.0, 1.0 + im 0.0]]
const M3: Matrix[3, 3] = [[1.0 + im 0.0, 1.0 + im 0.0, 0.0 + im 0.0],
[0.0 + im 0.0, 1.0 + im 0.0, 1.0 + im 0.0],
[1.0 + im 0.0, 0.0 + im 0.0, 1.0 + im 0.0]]
const SR2 = 1 / sqrt(2.0)
const M4: Matrix[3, 3] = [[SR2 + im 0.0, SR2 + im 0.0, 0.0 + im 0.0],
[0.0 + im SR2, 0.0 - im SR2, 0.0 + im 0.0],
[0.0 + im 0.0, 0.0 + im 0.0, 0.0 + im 1.0]]
test(M1)
test(M2)
test(M3)
test(M4)

View file

@ -0,0 +1,4 @@
conjtranspose(M)=conj(M~)
isHermitian(M)=M==conj(M~)
isnormal(M)=my(H=conj(M~));H*M==M*H
isunitary(M)=M*conj(M~)==1

View file

@ -0,0 +1,49 @@
test: procedure options (main); /* 1 October 2012 */
declare n fixed binary;
put ('Conjugate a complex square matrix.');
put skip list ('What is the order of the matrix?:');
get (n);
begin;
declare (M, MH, MM, MM_MMH, MM_MHM, IDENTITY)(n,n) fixed complex;
declare i fixed binary;
IDENTITY = 0; do i = 1 to n; IDENTITY(I,I) = 1; end;
put skip list ('Please type the matrix:');
get list (M);
do i = 1 to n;
put skip list (M(i,*));
end;
do i = 1 to n;
MH(i,*) = conjg(M(*,i));
end;
put skip list ('The conjugate transpose is:');
do i = 1 to n;
put skip list (MH(i,*));
end;
if all(M=MH) then
put skip list ('Matrix is Hermitian');
call MMULT(M, MH, MM_MMH);
call MMULT(MH, M, MM_MHM);
if all(MM_MMH = MM_MHM) then
put skip list ('Matrix is Normal');
if all(ABS(MM_MMH - IDENTITY) < 0.0001) then
put skip list ('Matrix is unitary');
if all(ABS(MM_MHM - IDENTITY) < 0.0001) then
put skip list ('Matrix is unitary');
end;
MMULT: procedure (M, MH, MM);
declare (M, MH, MM)(*,*) fixed complex;
declare (i, j, n) fixed binary;
n = hbound(M,1);
do i = 1 to n;
do j = 1 to n;
MM(i,j) = sum(M(i,*) * MH(*,j) );
end;
end;
end MMULT;
end test;

View file

@ -0,0 +1,85 @@
use strict;
use warnings;
use English;
use Math::Complex;
use Math::MatrixReal;
my @examples = (example1(), example2(), example3());
foreach my $m (@examples) {
print "Starting matrix:\n", cmat_as_string($m), "\n";
my $m_ct = conjugate_transpose($m);
print "Its conjugate transpose:\n", cmat_as_string($m_ct), "\n";
print "Is Hermitian? ", (cmats_are_equal($m, $m_ct) ? 'TRUE' : 'FALSE'), "\n";
my $product = $m_ct * $m;
print "Is normal? ", (cmats_are_equal($product, $m * $m_ct) ? 'TRUE' : 'FALSE'), "\n";
my $I = identity(($m->dim())[0]);
print "Is unitary? ", (cmats_are_equal($product, $I) ? 'TRUE' : 'FALSE'), "\n";
print "\n";
}
exit 0;
sub cmats_are_equal {
my ($m1, $m2) = @ARG;
my $max_norm = 1.0e-7;
return abs($m1 - $m2) < $max_norm; # Math::MatrixReal overloads abs().
}
# Note that Math::Complex and Math::MatrixReal both overload '~', for
# complex conjugates and matrix transpositions respectively.
sub conjugate_transpose {
my $m_T = ~ shift;
my $result = $m_T->each(sub {~ $ARG[0]});
return $result;
}
sub cmat_as_string {
my $m = shift;
my $n_rows = ($m->dim())[0];
my @row_strings = map { q{[} . join(q{, }, $m->row($ARG)->as_list) . q{]} }
(1 .. $n_rows);
return join("\n", @row_strings);
}
sub identity {
my $N = shift;
my $m = Math::MatrixReal->new($N, $N);
$m->one();
return $m;
}
sub example1 {
my $m = Math::MatrixReal->new(2, 2);
$m->assign(1, 1, cplx(3, 0));
$m->assign(1, 2, cplx(2, 1));
$m->assign(2, 1, cplx(2, -1));
$m->assign(2, 2, cplx(1, 0));
return $m;
}
sub example2 {
my $m = Math::MatrixReal->new(3, 3);
$m->assign(1, 1, cplx(1, 0));
$m->assign(1, 2, cplx(1, 0));
$m->assign(1, 3, cplx(0, 0));
$m->assign(2, 1, cplx(0, 0));
$m->assign(2, 2, cplx(1, 0));
$m->assign(2, 3, cplx(1, 0));
$m->assign(3, 1, cplx(1, 0));
$m->assign(3, 2, cplx(0, 0));
$m->assign(3, 3, cplx(1, 0));
return $m;
}
sub example3 {
my $m = Math::MatrixReal->new(3, 3);
$m->assign(1, 1, cplx(0.70710677, 0));
$m->assign(1, 2, cplx(0.70710677, 0));
$m->assign(1, 3, cplx(0, 0));
$m->assign(2, 1, cplx(0, -0.70710677));
$m->assign(2, 2, cplx(0, 0.70710677));
$m->assign(2, 3, cplx(0, 0));
$m->assign(3, 1, cplx(0, 0));
$m->assign(3, 2, cplx(0, 0));
$m->assign(3, 3, cplx(0, 1));
return $m;
}

View file

@ -0,0 +1,100 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">complex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">m_print</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"["</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008000;">","</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"]"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">conjugate_transpose</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_conjugate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">m_unitary</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">act</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- note: a was normal and act = a*ct already</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">act</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">re</span><span style="color: #0000FF;">,</span><span style="color: #000000;">im</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">act</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #000080;font-style:italic;">-- round to nearest billionth
-- (powers of 2 help the FPU out)</span>
<span style="color: #000000;">re</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">re</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">im</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">im</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">im</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">j</span> <span style="color: #008080;">and</span> <span style="color: #000000;">re</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">j</span> <span style="color: #008080;">and</span> <span style="color: #000000;">re</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">m_mul</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">complex_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">complex_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ct</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">conjugate_transpose</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Original matrix:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">m_print</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Conjugate transpose:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">m_print</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ct</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- note: rounding similar to that in m_unitary may be rqd (in a similar
-- loop in a new m_equal function) on these two equality tests,
-- but as it is, all tests pass with the builtin = operator.</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Hermitian?: %t\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ct</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (this one)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">act</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ct</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">cta</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ct</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">normal</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">act</span><span style="color: #0000FF;">=</span><span style="color: #000000;">cta</span> <span style="color: #000080;font-style:italic;">-- (&this one)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Normal?: %t\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">normal</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Unitary?: %t\n\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">normal</span> <span style="color: #008080;">and</span> <span style="color: #000000;">m_unitary</span><span style="color: #0000FF;">(</span><span style="color: #000000;">act</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{{{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{{{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">x</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}}}}</span>
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">,</span><span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
<!--

View file

@ -0,0 +1,76 @@
function conjugate-transpose($a) {
$arr = @()
if($a) {
$n = $a.count - 1
if(0 -lt $n) {
$m = ($a | foreach {$_.count} | measure-object -Minimum).Minimum - 1
if( 0 -le $m) {
if (0 -lt $m) {
$arr =@(0)*($m+1)
foreach($i in 0..$m) {
$arr[$i] = foreach($j in 0..$n) {@([System.Numerics.complex]::Conjugate($a[$j][$i]))}
}
} else {$arr = foreach($row in $a) {[System.Numerics.complex]::Conjugate($row[0])}}
}
} else {$arr = foreach($row in $a) {[System.Numerics.complex]::Conjugate($row[0])}}
}
$arr
}
function multarrays-complex($a, $b) {
$c = @()
if($a -and $b) {
$n = $a.count - 1
$m = $b[0].count - 1
$c = @([System.Numerics.complex]::new(0,0))*($n+1)
foreach ($i in 0..$n) {
$c[$i] = foreach ($j in 0..$m) {
[System.Numerics.complex]$sum = [System.Numerics.complex]::new(0,0)
foreach ($k in 0..$n){$sum = [System.Numerics.complex]::Add($sum, ([System.Numerics.complex]::Multiply($a[$i][$k],$b[$k][$j])))}
$sum
}
}
}
$c
}
function identity-complex($n) {
if(0 -lt $n) {
$array = @(0) * $n
foreach ($i in 0..($n-1)) {
$array[$i] = @([System.Numerics.complex]::new(0,0)) * $n
$array[$i][$i] = [System.Numerics.complex]::new(1,0)
}
$array
} else { @() }
}
function are-eq ($a,$b) { -not (Compare-Object $a $b -SyncWindow 0)}
function show($a) {
if($a) {
0..($a.Count - 1) | foreach{ if($a[$_]){"$($a[$_])"}else{""} }
}
}
function complex($a,$b) {[System.Numerics.complex]::new($a,$b)}
$id2 = identity-complex 2
$m = @(@((complex 2 7), (complex 9 -5)),@((complex 3 4), (complex 8 -6)))
$hm = conjugate-transpose $m
$mhm = multarrays-complex $m $hm
$hmm = multarrays-complex $hm $m
"`$m ="
show $m
""
"`$hm = conjugate-transpose `$m ="
show $hm
""
"`$m * `$hm ="
show $mhm
""
"`$hm * `$m ="
show $hmm
""
"Hermitian? `$m = $(are-eq $m $hm)"
"Normal? `$m = $(are-eq $mhm $hmm)"
"Unitary? `$m = $((are-eq $id2 $hmm) -and (are-eq $id2 $mhm))"

View file

@ -0,0 +1,72 @@
def conjugate_transpose(m):
return tuple(tuple(n.conjugate() for n in row) for row in zip(*m))
def mmul( ma, mb):
return tuple(tuple(sum( ea*eb for ea,eb in zip(a,b)) for b in zip(*mb)) for a in ma)
def mi(size):
'Complex Identity matrix'
sz = range(size)
m = [[0 + 0j for i in sz] for j in sz]
for i in range(size):
m[i][i] = 1 + 0j
return tuple(tuple(row) for row in m)
def __allsame(vector):
first, rest = vector[0], vector[1:]
return all(i == first for i in rest)
def __allnearsame(vector, eps=1e-14):
first, rest = vector[0], vector[1:]
return all(abs(first.real - i.real) < eps and abs(first.imag - i.imag) < eps
for i in rest)
def isequal(matrices, eps=1e-14):
'Check any number of matrices for equality within eps'
x = [len(m) for m in matrices]
if not __allsame(x): return False
y = [len(m[0]) for m in matrices]
if not __allsame(y): return False
for s in range(x[0]):
for t in range(y[0]):
if not __allnearsame([m[s][t] for m in matrices], eps): return False
return True
def ishermitian(m, ct):
return isequal([m, ct])
def isnormal(m, ct):
return isequal([mmul(m, ct), mmul(ct, m)])
def isunitary(m, ct):
mct, ctm = mmul(m, ct), mmul(ct, m)
mctx, mcty, cmx, ctmy = len(mct), len(mct[0]), len(ctm), len(ctm[0])
ident = mi(mctx)
return isequal([mct, ctm, ident])
def printm(comment, m):
print(comment)
fields = [['%g%+gj' % (f.real, f.imag) for f in row] for row in m]
width = max(max(len(f) for f in row) for row in fields)
lines = (', '.join('%*s' % (width, f) for f in row) for row in fields)
print('\n'.join(lines))
if __name__ == '__main__':
for matrix in [
((( 3.000+0.000j), (+2.000+1.000j)),
(( 2.000-1.000j), (+1.000+0.000j))),
((( 1.000+0.000j), (+1.000+0.000j), (+0.000+0.000j)),
(( 0.000+0.000j), (+1.000+0.000j), (+1.000+0.000j)),
(( 1.000+0.000j), (+0.000+0.000j), (+1.000+0.000j))),
((( 2**0.5/2+0.000j), (+2**0.5/2+0.000j), (+0.000+0.000j)),
(( 0.000+2**0.5/2j), (+0.000-2**0.5/2j), (+0.000+0.000j)),
(( 0.000+0.000j), (+0.000+0.000j), (+0.000+1.000j)))]:
printm('\nMatrix:', matrix)
ct = conjugate_transpose(matrix)
printm('Its conjugate transpose:', ct)
print('Hermitian? %s.' % ishermitian(matrix, ct))
print('Normal? %s.' % isnormal(matrix, ct))
print('Unitary? %s.' % isunitary(matrix, ct))

View file

@ -0,0 +1,79 @@
/*REXX program performs a conjugate transpose on a complex square matrix. */
parse arg N elements; if N==''|N=="," then N=3 /*Not specified? Then use the default.*/
k= 0; do r=1 for N
do c=1 for N; k= k+1; M.r.c= word( word(elements, k) 1, 1)
end /*c*/
end /*r*/
call showCmat 'M' ,N /*display a nicely formatted matrix. */
identity.= 0; do d=1 for N; identity.d.d= 1; end /*d*/
call conjCmat 'MH', "M" ,N /*conjugate the M matrix ───► MH */
call showCmat 'MH' ,N /*display a nicely formatted matrix. */
say 'M is Hermitian: ' word('no yes', isHermitian('M', "MH", N) + 1)
call multCmat 'M', 'MH', 'MMH', N /*multiple the two matrices together. */
call multCmat 'MH', 'M', 'MHM', N /* " " " " " */
say ' M is Normal: ' word('no yes', isHermitian('MMH', "MHM", N) + 1)
say ' M is Unary: ' word('no yes', isUnary('M', N) + 1)
say 'MMH is Unary: ' word('no yes', isUnary('MMH', N) + 1)
say 'MHM is Unary: ' word('no yes', isUnary('MHM', N) + 1)
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
cP: procedure; arg ',' c; return word( strip( translate(c, , 'IJ') ) 0, 1)
rP: procedure; parse arg r ','; return word( r 0, 1) /*◄──maybe return a 0 ↑ */
/*──────────────────────────────────────────────────────────────────────────────────────*/
conjCmat: parse arg matX,matY,rows 1 cols; call normCmat matY, rows
do r=1 for rows; _=
do c=1 for cols; v= value(matY'.'r"."c)
rP= rP(v); cP= -cP(v); call value matX'.'c"."r, rP','cP
end /*c*/
end /*r*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
isHermitian: parse arg matX,matY,rows 1 cols; call normCmat matX, rows
call normCmat matY, rows
do r=1 for rows; _=
do c=1 for cols
if value(matX'.'r"."c) \= value(matY'.'r"."c) then return 0
end /*c*/
end /*r*/; return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
isUnary: parse arg matX,rows 1 cols
do r=1 for rows; _=
do c=1 for cols; z= value(matX'.'r"."c); rP= rP(z); cP= cP(z)
if abs( sqrt( rP(z) **2 + cP(z)**2) - (r==c)) >= .0001 then return 0
end /*c*/
end /*r*/; return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
multCmat: parse arg matA,matB,matT,rows 1 cols; call value matT'.', 0
do r=1 for rows; _=
do c=1 for cols
do k=1 for cols; T= value(matT'.'r"."c); Tr= rP(T); Tc= cP(T)
A= value(matA'.'r"."k); Ar= rP(A); Ac= cP(A)
B= value(matB'.'k"."c); Br= rP(B); Bc= cP(B)
Pr= Ar*Br - Ac*Bc; Pc= Ac*Br + Ar*Bc; Tr= Tr+Pr; Tc= Tc+Pc
call value matT'.'r"."c,Tr','Tc
end /*k*/
end /*c*/
end /*r*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
normCmat: parse arg matN,rows 1 cols
do r=1 to rows; _=
do c=1 to cols; v= translate( value(matN'.'r"."c), , "IiJj")
parse upper var v real ',' cplx
if real\=='' then real= real / 1
if cplx\=='' then cplx= cplx / 1; if cplx=0 then cplx=
if cplx\=='' then cplx= cplx"j"
call value matN'.'r"."c, strip(real','cplx, "T", ',')
end /*c*/
end /*r*/; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
showCmat: parse arg matX,rows,cols; if cols=='' then cols= rows; @@= left('', 6)
say; say center('matrix' matX, 79, ''); call normCmat matX, rows, cols
do r=1 to rows; _=
do c=1 to cols; _= _ @@ left( value(matX'.'r"."c), 9)
end /*c*/
say _
end /*r*/; say; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); numeric form; h=d+6
numeric digits; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g *.5'e'_ % 2
m.=9; do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/; return g

View file

@ -0,0 +1,16 @@
#lang racket
(require math)
(define H matrix-hermitian)
(define (normal? M)
(define MH (H M))
(equal? (matrix* MH M)
(matrix* M MH)))
(define (unitary? M)
(define MH (H M))
(and (matrix-identity? (matrix* MH M))
(matrix-identity? (matrix* M MH))))
(define (hermitian? M)
(equal? (H M) M))

View file

@ -0,0 +1,6 @@
(define M (matrix [[3.000+0.000i +2.000+1.000i]
[2.000-1.000i +1.000+0.000i]]))
(H M)
(normal? M)
(unitary? M)
(hermitian? M)

View file

@ -0,0 +1,4 @@
(array #[#[3.0-0.0i 2.0+1.0i] #[2.0-1.0i 1.0-0.0i]])
#t
#f
#f

View file

@ -0,0 +1,52 @@
for [ # Test Matrices
[ 1, 1+i, 2i],
[ 1-i, 5, -3],
[0-2i, -3, 0]
],
[
[1, 1, 0],
[0, 1, 1],
[1, 0, 1]
],
[
[0.707 , 0.707, 0],
[0.707i, 0-0.707i, 0],
[0 , 0, i]
]
-> @m {
say "\nMatrix:";
@m.&say-it;
my @t = @m».conj.&mat-trans;
say "\nTranspose:";
@t.&say-it;
say "Is Hermitian?\t{is-Hermitian(@m, @t)}";
say "Is Normal?\t{is-Normal(@m, @t)}";
say "Is Unitary?\t{is-Unitary(@m, @t)}";
}
sub is-Hermitian (@m, @t, --> Bool) {
so @m».Complex eqv @t».Complex
}
sub is-Normal (@m, @t, --> Bool) {
so mat-mult(@m, @t)».Complex eqv mat-mult(@t, @m)».Complex
}
sub is-Unitary (@m, @t, --> Bool) {
so mat-mult(@m, @t, 1e-3)».Complex eqv mat-ident(+@m)».Complex;
}
sub mat-trans (@m) { map { [ @m[*;$_] ] }, ^@m[0] }
sub mat-ident ($n) { [ map { [ flat 0 xx $_, 1, 0 xx $n - 1 - $_ ] }, ^$n ] }
sub mat-mult (@a, @b, \ε = 1e-15) {
my @p;
for ^@a X ^@b[0] -> ($r, $c) {
@p[$r][$c] += @a[$r][$_] * @b[$_][$c] for ^@b;
@p[$r][$c].=round(ε); # avoid floating point math errors
}
@p
}
sub say-it (@array) { $_».fmt("%9s").say for @array }

View file

@ -0,0 +1,25 @@
require 'matrix'
# Start with some matrix.
i = Complex::I
matrix = Matrix[[i, 0, 0],
[0, i, 0],
[0, 0, i]]
# Find the conjugate transpose.
# Matrix#conjugate appeared in Ruby 1.9.2.
conjt = matrix.conj.t # aliases for matrix.conjugate.tranpose
print 'conjugate tranpose: '; puts conjt
if matrix.square?
# These predicates appeared in Ruby 1.9.3.
print 'Hermitian? '; puts matrix.hermitian?
print ' normal? '; puts matrix.normal?
print ' unitary? '; puts matrix.unitary?
else
# Matrix is not square. These predicates would
# raise ExceptionForMatrix::ErrDimensionMismatch.
print 'Hermitian? false'
print ' normal? false'
print ' unitary? false'
end

View file

@ -0,0 +1,80 @@
extern crate num; // crate for complex numbers
use num::complex::Complex;
use std::ops::Mul;
use std::fmt;
#[derive(Debug, PartialEq)]
struct Matrix<f32> {
grid: [[Complex<f32>; 2]; 2], // used to represent matrix
}
impl Matrix<f32> { // implements a method call for calculating the conjugate transpose
fn conjugate_transpose(&self) -> Matrix<f32> {
Matrix {grid: [[self.grid[0][0].conj(), self.grid[1][0].conj()],
[self.grid[0][1].conj(), self.grid[1][1].conj()]]}
}
}
impl Mul for Matrix<f32> { // implements '*' (multiplication) for the matrix
type Output = Matrix<f32>;
fn mul(self, other: Matrix<f32>) -> Matrix<f32> {
Matrix {grid: [[self.grid[0][0]*other.grid[0][0] + self.grid[0][1]*other.grid[1][0],
self.grid[0][0]*other.grid[0][1] + self.grid[0][1]*other.grid[1][1]],
[self.grid[1][0]*other.grid[0][0] + self.grid[1][1]*other.grid[1][0],
self.grid[1][0]*other.grid[1][0] + self.grid[1][1]*other.grid[1][1]]]}
}
}
impl Copy for Matrix<f32> {} // implemented to prevent 'moved value' errors in if statements below
impl Clone for Matrix<f32> {
fn clone(&self) -> Matrix<f32> {
*self
}
}
impl fmt::Display for Matrix<f32> { // implemented to make output nicer
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})\n({}, {})", self.grid[0][0], self.grid[0][1], self.grid[1][0], self.grid[1][1])
}
}
fn main() {
let a = Matrix {grid: [[Complex::new(3.0, 0.0), Complex::new(2.0, 1.0)],
[Complex::new(2.0, -1.0), Complex::new(1.0, 0.0)]]};
let b = Matrix {grid: [[Complex::new(0.5, 0.5), Complex::new(0.5, -0.5)],
[Complex::new(0.5, -0.5), Complex::new(0.5, 0.5)]]};
test_type(a);
test_type(b);
}
fn test_type(mat: Matrix<f32>) {
let identity = Matrix {grid: [[Complex::new(1.0, 0.0), Complex::new(0.0, 0.0)],
[Complex::new(0.0, 0.0), Complex::new(1.0, 0.0)]]};
let mat_conj = mat.conjugate_transpose();
println!("Matrix: \n{}\nConjugate transpose: \n{}", mat, mat_conj);
if mat == mat_conj {
println!("Hermitian?: TRUE");
} else {
println!("Hermitian?: FALSE");
}
if mat*mat_conj == mat_conj*mat {
println!("Normal?: TRUE");
} else {
println!("Normal?: FALSE");
}
if mat*mat_conj == identity {
println!("Unitary?: TRUE");
} else {
println!("Unitary?: FALSE");
}
}

View file

@ -0,0 +1,77 @@
object ConjugateTranspose {
case class Complex(re: Double, im: Double) {
def conjugate(): Complex = Complex(re, -im)
def +(other: Complex) = Complex(re + other.re, im + other.im)
def *(other: Complex) = Complex(re * other.re - im * other.im, re * other.im + im * other.re)
override def toString(): String = {
if (im < 0) {
s"${re}${im}i"
} else {
s"${re}+${im}i"
}
}
}
case class Matrix(val entries: Vector[Vector[Complex]]) {
def *(other: Matrix): Matrix = {
new Matrix(
Vector.tabulate(entries.size, other.entries(0).size)((r, c) => {
val rightRow = entries(r)
val leftCol = other.entries.map(_(c))
rightRow.zip(leftCol)
.map{ case (x, y) => x * y } // multiply pair-wise
.foldLeft(new Complex(0,0)){ case (x, y) => x + y } // sum over all
})
)
}
def conjugateTranspose(): Matrix = {
new Matrix(
Vector.tabulate(entries(0).size, entries.size)((r, c) => entries(c)(r).conjugate)
)
}
def isHermitian(): Boolean = {
this == conjugateTranspose()
}
def isNormal(): Boolean = {
val ct = conjugateTranspose()
this * ct == ct * this
}
def isIdentity(): Boolean = {
val entriesWithIndexes = for (r <- 0 until entries.size; c <- 0 until entries(r).size) yield (r, c, entries(r)(c))
entriesWithIndexes.forall { case (r, c, x) =>
if (r == c) {
x == Complex(1.0, 0.0)
} else {
x == Complex(0.0, 0.0)
}
}
}
def isUnitary(): Boolean = {
(this * conjugateTranspose()).isIdentity()
}
override def toString(): String = {
entries.map(" " + _.mkString("[", ",", "]")).mkString("[\n", "\n", "\n]")
}
}
def main(args: Array[String]): Unit = {
val m = new Matrix(
Vector.fill(3, 3)(new Complex(Math.random() * 2 - 1.0, Math.random() * 2 - 1.0))
)
println("Matrix: " + m)
println("Conjugate Transpose: " + m.conjugateTranspose())
println("Hermitian: " + m.isHermitian())
println("Normal: " + m.isNormal())
println("Unitary: " + m.isUnitary())
}
}

View file

@ -0,0 +1,66 @@
func is_Hermitian (Array m, Array t) -> Bool { m == t }
func mat_mult (Array a, Array b, Number ε = -3) {
var p = []
for r, c in (^a ~X ^b[0]) {
for k in (^b) {
p[r][c] := 0 += (a[r][k] * b[k][c]) -> round!(ε)
}
}
return p
}
func mat_trans (Array m) {
var r = []
for i,j in (^m ~X ^m[0]) {
r[j][i] = m[i][j]
}
return r
}
func mat_ident (Number n) {
^n -> map {|i|
[i.of(0)..., 1, (n - i - 1).of(0)...]
}
}
func is_Normal (Array m, Array t) -> Bool {
mat_mult(m, t) == mat_mult(t, m)
}
func is_Unitary (Array m, Array t) -> Bool {
mat_mult(m, t) == mat_ident(m.len)
}
func say_it (Array a) {
a.each {|b|
b.map { "%9s" % _ }.join(' ').say
}
}
[
[
[ 1, 1+1i, 2i],
[1-1i, 5, -3],
[0-2i, -3, 0]
],
[
[1, 1, 0],
[0, 1, 1],
[1, 0, 1]
],
[
[0.707 , 0.707, 0],
[0.707i, -0.707i, 0],
[0 , 0, 1i]
]
].each { |m|
say "\nMatrix:"
say_it(m)
var t = mat_trans(m.map{.map{.conj}})
say "\nTranspose:"
say_it(t)
say "Is Hermitian?\t#{is_Hermitian(m, t)}"
say "Is Normal?\t#{is_Normal(m, t)}"
say "Is Unitary?\t#{is_Unitary(m, t)}"
}

View file

@ -0,0 +1,101 @@
# Computes conjugate transpose of M
let conjTransp = function conjTransp(M) {
return map(range(sizeof M[0]), function(row) {
return map(range(sizeof M), function(col) {
return cplx_conj(M[col][row]);
});
});
};
# Helper for cplxMatMul
let cplxVecScalarMul = function cplxVecScalarMul(A, B, row, col) {
var M = { "re": 0.0, "im": 0.0 };
let N = sizeof A;
for (var i = 0; i < N; i++) {
let P = cplx_mul(A[row][i], B[i][col]);
M = cplx_add(M, P);
}
return M;
};
# Multiplies matrices A and B
# A and B are assumed to be square and of the same size,
# this condition is not checked.
let cplxMatMul = function cplxMatMul(A, B) {
var R = {};
let N = sizeof A;
for (var row = 0; row < N; row++) {
R[row] = {};
for (var col = 0; col < N; col++) {
R[row][col] = cplxVecScalarMul(A, B, row, col);
}
}
return R;
};
# Helper for creating an array representing a complex number
# given its textual representation
let _ = function makeComplex(str) {
let sep = indexof(str, "+", 1);
if sep < 0 {
sep = indexof(str, "-", 1);
}
let reStr = substrto(str, sep);
let imStr = substrfrom(str, sep);
return { "re": tofloat(reStr), "im": tofloat(imStr) };
};
# Formats a complex matrix
let printCplxMat = function printCplxMat(M) {
foreach(M, function(i, row) {
foreach(row, function(j, elem) {
printf(" %.2f%+.2fi", elem.re, elem.im);
});
print();
});
};
# A Hermitian matrix
let H = {
{ _("3+0i"), _("2+1i") },
{ _("2-1i"), _("0+0i") }
};
# A normal matrix
let N = {
{ _("1+0i"), _("1+0i"), _("0+0i") },
{ _("0+0i"), _("1+0i"), _("1+0i") },
{ _("1+0i"), _("0+0i"), _("1+0i") }
};
# A unitary matrix
let U = {
{ _("0.70710678118+0i"), _("0.70710678118+0i"), _("0+0i") },
{ _("0-0.70710678118i"), _("0+0.70710678118i"), _("0+0i") },
{ _("0+0i"), _("0+0i"), _("0+1i") }
};
print("Hermitian matrix:\nH = ");
printCplxMat(H);
print("H* = ");
printCplxMat(conjTransp(H));
print();
print("Normal matrix:\nN = ");
printCplxMat(N);
print("N* = ");
printCplxMat(conjTransp(N));
print("N* x N = ");
printCplxMat(cplxMatMul(conjTransp(N), N));
print("N x N* = ");
printCplxMat(cplxMatMul(N, conjTransp(N)));
print();
print("Unitary matrix:\nU = ");
printCplxMat(U);
print("U* = ");
printCplxMat(conjTransp(U));
print("U x U* = ");
printCplxMat(cplxMatMul(U, conjTransp(U)));
print();

View file

@ -0,0 +1,31 @@
: a=1,2i\3i,4
: a
1 2
+-----------+
1 | 1 2i |
2 | 3i 4 |
+-----------+
: a'
1 2
+-------------+
1 | 1 -3i |
2 | -2i 4 |
+-------------+
: transposeonly(a)
1 2
+-----------+
1 | 1 3i |
2 | 2i 4 |
+-----------+
: a*a'==a'*a
0
: a'==a
0
: a'*a==I(rows(a))
0

View file

@ -0,0 +1,57 @@
package require struct::matrix
package require math::complexnumbers
proc complexMatrix.equal {m1 m2 {epsilon 1e-14}} {
if {[$m1 rows] != [$m2 rows] || [$m1 columns] != [$m2 columns]} {
return 0
}
# Compute the magnitude of the difference between two complex numbers
set ceq [list apply {{epsilon a b} {
expr {[mod [- $a $b]] < $epsilon}
} ::math::complexnumbers} $epsilon]
for {set i 0} {$i<[$m1 columns]} {incr i} {
for {set j 0} {$j<[$m1 rows]} {incr j} {
if {![{*}$ceq [$m1 get cell $i $j] [$m2 get cell $i $j]]} {
return 0
}
}
}
return 1
}
proc complexMatrix.multiply {a b} {
if {[$a columns] != [$b rows]} {
error "incompatible sizes"
}
# Simplest to use a lambda in the complex NS
set cpm {{sum a b} {
+ $sum [* $a $b]
} ::math::complexnumbers}
set c0 [math::complexnumbers::complex 0.0 0.0]; # Complex zero
set c [struct::matrix]
$c add columns [$b columns]
$c add rows [$a rows]
for {set i 0} {$i < [$a rows]} {incr i} {
for {set j 0} {$j < [$b columns]} {incr j} {
set sum $c0
foreach rv [$a get row $i] cv [$b get column $j] {
set sum [apply $cpm $sum $rv $cv]
}
$c set cell $j $i $sum
}
}
return $c
}
proc complexMatrix.conjugateTranspose {matrix} {
set mat [struct::matrix]
$mat = $matrix
$mat transpose
for {set c 0} {$c < [$mat columns]} {incr c} {
for {set r 0} {$r < [$mat rows]} {incr r} {
set val [$mat get cell $c $r]
$mat set cell $c $r [math::complexnumbers::conj $val]
}
}
return $mat
}

View file

@ -0,0 +1,52 @@
proc isHermitian {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
return 0
}
set cc [complexMatrix.conjugateTranspose $matrix]
set result [complexMatrix.equal $matrix $cc $epsilon]
$cc destroy
return $result
}
proc isNormal {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
return 0
}
set mh [complexMatrix.conjugateTranspose $matrix]
set mhm [complexMatrix.multiply $mh $matrix]
set mmh [complexMatrix.multiply $matrix $mh]
$mh destroy
set result [complexMatrix.equal $mhm $mmh $epsilon]
$mhm destroy
$mmh destroy
return $result
}
proc isUnitary {matrix {epsilon 1e-14}} {
if {[$matrix rows] != [$matrix columns]} {
# Must be square!
return 0
}
set mh [complexMatrix.conjugateTranspose $matrix]
set mhm [complexMatrix.multiply $mh $matrix]
set mmh [complexMatrix.multiply $matrix $mh]
$mh destroy
set result [complexMatrix.equal $mhm $mmh $epsilon]
$mhm destroy
if {$result} {
set id [struct::matrix]
$id = $matrix; # Just for its dimensions
for {set c 0} {$c < [$id columns]} {incr c} {
for {set r 0} {$r < [$id rows]} {incr r} {
$id set cell $c $r \
[math::complexnumbers::complex [expr {$c==$r}] 0]
}
}
set result [complexMatrix.equal $mmh $id $epsilon]
$id destroy
}
$mmh destroy
return $result
}

View file

@ -0,0 +1,34 @@
import "/complex" for Complex, CMatrix
import "/fmt" for Fmt
var cm1 = CMatrix.new(
[
[Complex.new(3), Complex.new(2, 1)],
[Complex.new(2, -1), Complex.one ]
]
)
var cm2 = CMatrix.fromReals([ [1, 1, 0], [0, 1, 1], [1, 0, 1] ])
var x = 2.sqrt/2
var cm3 = CMatrix.new(
[
[Complex.new(x), Complex.new(x), Complex.zero],
[Complex.new(0, -x), Complex.new(0, x), Complex.zero],
[Complex.zero, Complex.zero, Complex.imagOne]
]
)
for (cm in [cm1, cm2, cm3]) {
System.print("Matrix:")
Fmt.mprint(cm, 5, 3)
System.print("\nConjugate transpose:")
Fmt.mprint(cm.conjTranspose, 5, 3)
System.print("\nHermitian : %(cm.isHermitian)")
System.print("Normal : %(cm.isNormal)")
System.print("Unitary : %(cm.isUnitary)")
System.print()
}
System.print("For the final example if we use a tolerance of 1e-14:")
var cm4 = cm3 * cm3.conjTranspose
var id = CMatrix.identity(3)
System.print("Unitary : %(cm4.almostEquals(id))")