2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,15 +1,32 @@
|
|||
Suppose that a [[matrix]] <math>M</math> 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>.
|
||||
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>.
|
||||
|
||||
: <math>(M^H)_{ji} = \overline{M_{ij}}</math>
|
||||
::: <big><math>(M^H)_{ji} = \overline{M_{ij}}</math></big>
|
||||
|
||||
This means that row <math>j</math>, column <math>i</math> of the conjugate transpose equals the complex conjugate of row <math>i</math>, column <math>j</math> of the original matrix.
|
||||
|
||||
In the next list, <math>M</math> must also be a square matrix.
|
||||
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>. 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.
|
||||
* 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.
|
||||
|
||||
Given some matrix of complex numbers, find its conjugate transpose. Also determine if it is a Hermitian matrix, normal matrix, or a unitary matrix.
|
||||
|
||||
* MathWorld: [http://mathworld.wolfram.com/ConjugateTranspose.html conjugate transpose], [http://mathworld.wolfram.com/HermitianMatrix.html Hermitian matrix], [http://mathworld.wolfram.com/NormalMatrix.html normal matrix], [http://mathworld.wolfram.com/UnitaryMatrix.html unitary 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>
|
||||
|
|
|
|||
|
|
@ -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))) )
|
||||
45
Task/Conjugate-transpose/Haskell/conjugate-transpose.hs
Normal file
45
Task/Conjugate-transpose/Haskell/conjugate-transpose.hs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import Data.List (transpose)
|
||||
import Data.Complex
|
||||
|
||||
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 a = a `approxEqualMatrix` conjTranspose a
|
||||
isNormalMatrix a = (a `mmul` conjTranspose a) `approxEqualMatrix` (conjTranspose a `mmul` a)
|
||||
isUnitaryMatrix a = (a `mmul` conjTranspose a) `approxEqualMatrix` ident (length a)
|
||||
|
||||
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
|
||||
52
Task/Conjugate-transpose/Perl-6/conjugate-transpose.pl6
Normal file
52
Task/Conjugate-transpose/Perl-6/conjugate-transpose.pl6
Normal 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 }
|
||||
84
Task/Conjugate-transpose/Perl/conjugate-transpose.pl
Normal file
84
Task/Conjugate-transpose/Perl/conjugate-transpose.pl
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
use strict;
|
||||
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 = new Math::MatrixReal($N, $N);
|
||||
$m->one();
|
||||
return $m;
|
||||
}
|
||||
|
||||
sub example1 {
|
||||
my $m = new Math::MatrixReal(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 = new Math::MatrixReal(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 = new Math::MatrixReal(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;
|
||||
}
|
||||
76
Task/Conjugate-transpose/PowerShell/conjugate-transpose.psh
Normal file
76
Task/Conjugate-transpose/PowerShell/conjugate-transpose.psh
Normal 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))"
|
||||
|
|
@ -1,87 +1,83 @@
|
|||
/*REXX pgm performs a conjugate transpose on a complex square matrix. */
|
||||
parse arg N elements; if N=='' then N=3
|
||||
M.=0 /*Matrix has all elements equal to zero*/
|
||||
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. */
|
||||
/*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. */
|
||||
/*──────────────────────────────────one─liner subroutines─────────────────────*/
|
||||
cP: procedure; arg ',' p; return word(strip(translate(p,,'IJ')) 0,1)
|
||||
rP: procedure; parse arg r ','; return word(r 0,1)
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
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*/
|
||||
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
|
||||
/*────────────────────────────────────────────────────────────────────────────*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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*/
|
||||
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*/
|
||||
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
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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(); i=; m.=9
|
||||
numeric digits 9; numeric form; h=d+6; if x<0 then do; x=-x; i='i'; end
|
||||
parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'e'_%2
|
||||
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*/
|
||||
numeric digits d; return (g/1)i /*make complex if X < 0.*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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
|
||||
|
|
|
|||
80
Task/Conjugate-transpose/Rust/conjugate-transpose.rust
Normal file
80
Task/Conjugate-transpose/Rust/conjugate-transpose.rust
Normal 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");
|
||||
}
|
||||
}
|
||||
77
Task/Conjugate-transpose/Scala/conjugate-transpose.scala
Normal file
77
Task/Conjugate-transpose/Scala/conjugate-transpose.scala
Normal 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())
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue