/** * 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>"; }
/** * det * Calculate determinant * @return float Determinant */ function det() { $L = new LUDecomposition($this); return $L->det(); }
function fitcircle($X, $Y) { $points = sizeof($X); if ($points < 3) { return array("cx" => 0, "cy" => 0, "r" => 0, "err" => 100); } // Mean of points $meanX = 0; $meanY = 0; for ($i = 0; $i < sizeof($X); $i++) { $meanX += $X[$i]; $meanY += $Y[$i]; } $meanX /= $points; $meanY /= $points; // Auxiliary means $mXx = 0; $mXy = 0; $mYy = 0; $mRx = 0; $mRy = 0; for ($i = 0; $i < sizeof($X); $i++) { $x = $X[$i]; $y = $Y[$i]; $r = $x * $x + $y * $y; $mXx += $x * ($x - $meanX); $mXy += $x * ($y - $meanY); $mYy += $y * ($y - $meanY); $mRx += $r * ($x - $meanX); $mRy += $r * ($y - $meanY); } $mXx /= $points; $mXy /= $points; $mYy /= $points; $mRx /= $points; $mRy /= $points; // Assemble matrix $A[0][0] = $mXx; $A[0][1] = 2.0 * $mXy; $A[1][0] = 0.0; $A[1][1] = $mYy; $matrixA = new Matrix($A); // A=A+transpose(A) $matrixA = $matrixA->plus($matrixA->transpose()); // Assemble B vector $b[0][0] = $mRx; $b[1][0] = $mRy; $matrixB = new Matrix($b); // Calculate center Solve A*x=b for x,then center=x $LU = new LUDecomposition($matrixA); if ($LU->isNonsingular()) { $C = $matrixA->solve($matrixB); $cx = $C->get(0, 0); $cy = $C->get(1, 0); // Calculate radius $meanR2 = 0; $maxR2 = 0; $minR2 = 10000; for ($i = 0; $i < sizeof($X); $i++) { $x = $X[$i]; $y = $Y[$i]; $r2 = ($x - $cx) * ($x - $cx) + ($y - $cy) * ($y - $cy); if ($r2 > $maxR2) { $maxR2 = $r2; } if ($r2 < $minR2) { $minR2 = $r2; } $meanR2 += $r2; } $meanR2 /= $points; $radius = sqrt($meanR2); // Calculate error $err = sqrt($maxR2) / sqrt($minR2); // Return return array("cx" => $cx, "cy" => $cy, "r" => $radius, "err" => $err); } else { return array("cx" => 0, "cy" => 0, "r" => 0, "err" => 100); } }