1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
<?php
/**
* @package JAMA
*/
require_once "../Matrix.php";
/**
* Example of use of Matrix Class, featuring magic squares.
*/
class MagicSquareExample {
/**
* Generate magic square test matrix.
* @param int n dimension of matrix
*/
function magic($n) {
// Odd order
if (($n % 2) == 1) {
$a = ($n+1)/2;
$b = ($n+1);
for ($j = 0; $j < $n; $j++)
for ($i = 0; $i < $n; $i++)
$M[$i][$j] = $n*(($i+$j+$a) % $n) + (($i+2*$j+$b) % $n) + 1;
// Doubly Even Order
} else if (($n % 4) == 0) {
for ($j = 0; $j < $n; $j++) {
for ($i = 0; $i < $n; $i++) {
if ((($i+1)/2)%2 == (($j+1)/2)%2)
$M[$i][$j] = $n*$n-$n*$i-$j;
else
$M[$i][$j] = $n*$i+$j+1;
}
}
// Singly Even Order
} else {
$p = $n/2;
$k = ($n-2)/4;
$A = $this->magic($p);
$M = array();
for ($j = 0; $j < $p; $j++) {
for ($i = 0; $i < $p; $i++) {
$aij = $A->get($i,$j);
$M[$i][$j] = $aij;
$M[$i][$j+$p] = $aij + 2*$p*$p;
$M[$i+$p][$j] = $aij + 3*$p*$p;
$M[$i+$p][$j+$p] = $aij + $p*$p;
}
}
for ($i = 0; $i < $p; $i++) {
for ($j = 0; $j < $k; $j++) {
$t = $M[$i][$j];
$M[$i][$j] = $M[$i+$p][$j];
$M[$i+$p][$j] = $t;
}
for ($j = $n-$k+1; $j < $n; $j++) {
$t = $M[$i][$j];
$M[$i][$j] = $M[$i+$p][$j];
$M[$i+$p][$j] = $t;
}
}
$t = $M[$k][0]; $M[$k][0] = $M[$k+$p][0]; $M[$k+$p][0] = $t;
$t = $M[$k][$k]; $M[$k][$k] = $M[$k+$p][$k]; $M[$k+$p][$k] = $t;
}
return new Matrix($M);
}
/**
* Simple function to replicate PHP 5 behaviour
*/
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
/**
* Tests LU, QR, SVD and symmetric Eig decompositions.
*
* n = order of magic square.
* trace = diagonal sum, should be the magic sum, (n^3 + n)/2.
* max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
* rank = linear algebraic rank, should equal n if n is odd,
* be less than n if n is even.
* cond = L_2 condition number, ratio of singular values.
* lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
* qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps).
*/
function main() {
?>
<p>Test of Matrix Class, using magic squares.</p>
<p>See MagicSquareExample.main() for an explanation.</p>
<table border='1' cellspacing='0' cellpadding='4'>
<tr>
<th>n</th>
<th>trace</th>
<th>max_eig</th>
<th>rank</th>
<th>cond</th>
<th>lu_res</th>
<th>qr_res</th>
</tr>
<?php
$start_time = $this->microtime_float();
$eps = pow(2.0,-52.0);
for ($n = 3; $n <= 6; $n++) {
echo "<tr>";
echo "<td align='right'>$n</td>";
$M = $this->magic($n);
$t = (int) $M->trace();
echo "<td align='right'>$t</td>";
$O = $M->plus($M->transpose());
$E = new EigenvalueDecomposition($O->times(0.5));
$d = $E->getRealEigenvalues();
echo "<td align='right'>".$d[$n-1]."</td>";
$r = $M->rank();
echo "<td align='right'>".$r."</td>";
$c = $M->cond();
if ($c < 1/$eps)
echo "<td align='right'>".sprintf("%.3f",$c)."</td>";
else
echo "<td align='right'>Inf</td>";
$LU = new LUDecomposition($M);
$L = $LU->getL();
$U = $LU->getU();
$p = $LU->getPivot();
// Java version: R = L.times(U).minus(M.getMatrix(p,0,n-1));
$S = $L->times($U);
$R = $S->minus($M->getMatrix($p,0,$n-1));
$res = $R->norm1()/($n*$eps);
echo "<td align='right'>".sprintf("%.3f",$res)."</td>";
$QR = new QRDecomposition($M);
$Q = $QR->getQ();
$R = $QR->getR();
$S = $Q->times($R);
$R = $S->minus($M);
$res = $R->norm1()/($n*$eps);
echo "<td align='right'>".sprintf("%.3f",$res)."</td>";
echo "</tr>";
}
echo "<table>";
echo "<br />";
$stop_time = $this->microtime_float();
$etime = $stop_time - $start_time;
echo "<p>Elapsed time is ". sprintf("%.4f",$etime) ." seconds.</p>";
}
}
$magic = new MagicSquareExample();
$magic->main();
?>
|