matrix.php
来自「视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.」· PHP 代码 · 共 1,490 行 · 第 1/4 页
PHP
1,490 行
} } if (!empty($data)) { return $this->setData($data); } else { return PEAR::raiseError('Undefined error'); } }/*}}}*/ /** * Multiplies a vector by this matrix * * @param object Math_Vector $v1 * @return object an instance of Math_Vector on success, PEAR_Error otherwise * @see getSize() * @see getRow() * @see Math_Vector::get() */ function &vectorMultiply(&$v1) {/*{{{*/ if (!Math_VectorOp::isVector($v1)) { return PEAR::raiseError ("Wrong parameter, a Math_Vector object"); } list($nr, $nc) = $this->getSize(); $nv = $v1->size(); if ($nc != $nv) { return PEAR::raiseError("Incompatible number of columns in matrix ($nc) must ". "be the same as the number of elements ($nv) in the vector"); } $data = array(); for ($i=0; $i < $nr; $i++) { $data[$i] = 0; for ($j=0; $j < $nv; $j++) { $data[$i] += $this->getElement($i,$j) * $v1->get($j); } } return new Math_Vector($data); }/*}}}*/ // Static operations /** * Create a matrix from a file, using data stored in the given format * * Lines starting with '#' will be assumed to be comments and will be skipped * * @static * @access public * @param string $filename name of file containing matrix data * @param optional string $format one of 'serialized' (default) or 'csv' * @return object a Math_Matrix instance on success, a PEAR_Error otherwise */ function &readFromFile ($filename, $format='serialized') {/*{{{*/ if (!file_exists($filename) || !is_readable($filename)) { return PEAR::raiseError('File cannot be opened for reading'); } if (filesize($filename) == 0) { return PEAR::raiseError('File is empty'); } if ($format == 'serialized') { if (function_exists("file_get_contents")) { $objser = file_get_contents($filename); } else { $objser = implode("",file($filename)); } $obj = unserialize($objser); if (Math_Matrix::isMatrix($obj)) { return $obj; } else { return PEAR::raiseError('File did not contain a Math_Matrix object'); } } else { // assume CSV data $data = array(); $lines = file($filename); foreach ($lines as $line) { if (preg_match('/^#/', $line)) { continue; } else { $data[] = explode(',',trim($line)); } } $m =& new Math_Matrix(); $e = $m->setData($data); if (PEAR::isError($e)) { return $e; } else { return $m; } } }/*}}}*/ /** * Writes matrix object to a file using the given format * * @static * @access public * @param object Math_Matrix $matrix the matrix object to store * @param string $filename name of file to contain the matrix data * @param optional string $format one of 'serialized' (default) or 'csv' * @return mixed TRUE on success, a PEAR_Error otherwise */ function writeToFile (&$matrix, $filename, $format='serialized') {/*{{{*/ if (!Math_Matrix::isMatrix($matrix)) { return PEAR::raiseError("Parameter must be a Math_Matrix object"); } if ($matrix->isEmpty()) { return PEAR::raiseError("Math_Matrix object is empty"); } if ($format == 'serialized') { $data = serialize($matrix); } else { $data = ''; list($nr, $nc) = $matrix->getSize(); for ($i=0; $i<$nr; $i++) { $row = $matrix->getRow($i); if (PEAR::isError($row)) { return $row; } $data .= implode(',', $row)."\n"; } } $fp = fopen($filename, "w"); if (!$fp) { return PEAR::raiseError("Cannot write matrix to file $filename"); } fwrite($fp, $data); fclose($fp); return true; }/*}}}*/ /** * Checks if the object is a Math_Matrix instance * * @static * @access public * @param object Math_Matrix $matrix * @return boolean TRUE on success, FALSE otherwise */ function isMatrix (&$matrix) {/*{{{*/ if (function_exists("is_a")) { return is_a($matrix, "Math_Matrix"); } else { return (get_class($matrix) == "math_matrix"); } }/*}}}*/ /** * Returns a Math_Matrix object of size (nrows, ncols) filled with a value * * @static * @access public * @param integer $nrows number of rows in the generated matrix * @param integer $ncols number of columns in the generated matrix * @param numeric $value the fill value * @return object a Math_Matrix instance on success, PEAR_Error otherwise */ function &makeMatrix ($nrows, $ncols, $value) {/*{{{*/ if (!is_int($nrows) && is_int($ncols) && !is_numeric($value)) { return PEAR::raiseError('Number of rows, columns, and a numeric fill value expected'); } for ($i=0; $i<$nrows; $i++) { $m[$i] = explode(":",substr(str_repeat($value.":",$ncols),0,-1)); } return new Math_Matrix($m); }/*}}}*/ /** * Returns the Math_Matrix object of size (nrows, ncols), filled with the value 1 (one) * * @static * @access public * @param integer $nrows number of rows in the generated matrix * @param integer $ncols number of columns in the generated matrix * @return object a Math_Matrix instance on success, PEAR_Error otherwise * @see Math_Matrix::makeMatrix() */ function &makeOne ($nrows, $ncols) {/*{{{*/ return Math_Matrix::makeMatrix ($nrows, $ncols, 1); }/*}}}*/ /** * Returns the Math_Matrix object of size (nrows, ncols), filled with the value 0 (zero) * * @static * @access public * @param integer $nrows number of rows in the generated matrix * @param integer $ncols number of columns in the generated matrix * @return object a Math_Matrix instance on success, PEAR_Error otherwise * @see Math_Matrix::makeMatrix() */ function &makeZero ($nrows, $ncols) {/*{{{*/ return Math_Matrix::makeMatrix ($nrows, $ncols, 0); }/*}}}*/ /** * Returns a square unit Math_Matrix object of the given size * * A unit matrix is one in which the elements follow the rules: * e[i][j] = 1, if i == j * e[i][j] = 0, if i != j * Such a matrix is also called an 'identity matrix' * * @static * @access public * @param integer $size number of rows and columns in the generated matrix * @return object a Math_Matrix instance * @see Math_Matrix::makeIdentity() */ function &makeUnit ($size) {/*{{{*/ for ($i=0; $i<$size; $i++) { for ($j=0; $j<$size; $j++) { if ($i == $j) { $data[$i][$j] = (float) 1.0; } else { $data[$i][$j] = (float) 0.0; } } } return new Math_Matrix($data); }/*}}}*/ /** * Returns the identity matrix of the given size. An alias of Math_Matrix::makeUnit() * * @static * @access public * @param integer $size number of rows and columns in the generated matrix * @return object a Math_Matrix instance * @see Math_Matrix::makeUnit() */ function &makeIdentity($size) {/*{{{*/ return Math_Matrix::makeUnit($size); }/*}}}*/ /** * Solves a system of linear equations: Ax = b * * A system such as: * <pre> * a11*x1 + a12*x2 + ... + a1n*xn = b1 * a21*x1 + a22*x2 + ... + a2n*xn = b2 * ... * ak1*x1 + ak2*x2 + ... + akn*xn = bk * </pre> * can be rewritten as: * <pre> * Ax = b * </pre> * where: * - A is matrix of coefficients (aij, i=1..k, j=1..n), * - b a vector of values (bi, i=1..k), * - x the vector of unkowns (xi, i=1..n) * Using: x = (Ainv)*b * where: * - Ainv is the inverse of A * * @static * @access public * @param object Math_Matrix $a the matrix of coefficients * @param object Math_Vector $b the vector of values * @return mixed a Math_Vector object on succcess, PEAR_Error otherwise * @see vectorMultiply() */ function solve($a, $b) { // check that the vector classes are defined if (!Math_Matrix::isMatrix($a) && !Math_VectorOp::isVector($b)) { return PEAR::raiseError('Incorrect parameters, expecting a Math_Matrix and a Math_Vector'); } $e = $a->invert(); if (PEAR::isError($e)) { return $e; } return $a->vectorMultiply($b); } /** * Solves a system of linear equations: Ax = b, using an iterative error correction algorithm * * A system such as: * <pre> * a11*x1 + a12*x2 + ... + a1n*xn = b1 * a21*x1 + a22*x2 + ... + a2n*xn = b2 * ... * ak1*x1 + ak2*x2 + ... + akn*xn = bk * </pre> * can be rewritten as: * <pre> * Ax = b * </pre> * where: * - A is matrix of coefficients (aij, i=1..k, j=1..n), * - b a vector of values (bi, i=1..k), * - x the vector of unkowns (xi, i=1..n) * Using: x = (Ainv)*b * where: * - Ainv is the inverse of A * * The error correction algorithm uses the approach that if: * - xp is the approximate solution * - bp the values obtained from pluging xp into the original equation * We obtain * <pre> * A(x - xp) = (b - bp), * or * A*xadj = (b - bp) * </pr> * where: * - xadj is the adjusted value (= Ainv*(b - bp)) * therefore, we calculate iteratively new values of x using the estimated * xadj and testing to check if we have decreased the error. * * @static * @access public * @param object Math_Matrix $a the matrix of coefficients * @param object Math_Vector $b the vector of values * @return mixed a Math_Vector object on succcess, PEAR_Error otherwise * @see vectorMultiply() * @see invert() * @see Math_VectorOp::add() * @see Math_VectorOp::substract() * @see Math_VectorOp::length() */ function solveEC($a, $b) {/*{{{*/ $ainv = $a->clone(); $e = $ainv->invert(); if (PEAR::isError($e)) { return $e; } $x = $ainv->vectorMultiply($b); if (PEAR::isError($x)) { return $x; } // initial guesses $bprime = $a->vectorMultiply($x); if (PEAR::isError($bprime)) { return $bprime; } $err = Math_VectorOp::substract($b, $bprime); $adj = $ainv->vectorMultiply($err); if (PEAR::isError($adj)) { return $adj; } $adjnorm = $adj->length(); $xnew = $x; // compute new solutions and test for accuracy // iterate no more than 10 times for ($i=0; $i<10; $i++) { $xnew = Math_VectorOp::add($x, $adj); $bprime = $a->vectorMultiply($xnew); $err = Math_VectorOp::substract($b, $bprime); $newadj = $ainv->vectorMultiply($err); $newadjnorm = $newadj->length(); // did we improve the accuracy? if ($newadjnorm < $adjnorm) { $adjnorm = $newadjnorm; $x = $xnew; $adj = $newadj; } else { // we did improve the accuracy, so break; break; } } return $x; }/*}}}*/ } // end of Math_Matrix class /*}}}*/// vim: ts=4:sw=4:et:// vim6: fdl=1:?>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?