/** * Constructor: Get the qr decomposition of the given matrix using householder transformations. * The single householder matrizes are stores within the matrix. * * @param matrix matrix to get the composition of */ public function __construct(&$matrix) { new Assertion($matrix instanceof Matrix, 'Given matrix not of class Matrix.'); $this->_tau = new Vector($matrix->columns()); $this->_matrix = $matrix->copy(); for ($j = 0; $j < $this->_matrix->columns(); $j++) { $norm = 0.0; for ($i = $j; $i < $this->_matrix->rows(); $i++) { $norm += pow($this->_matrix->get($i, $j), 2); } $norm = sqrt($norm); $sign = 1.0; if ($this->_matrix->get($j, $j) < 0) { $sign = -1.0; } $v1 = $this->_matrix->get($j, $j) + $sign * $norm; $scalar = 1; for ($i = $j + 1; $i < $this->_matrix->rows(); $i++) { $this->_matrix->set($i, $j, $this->_matrix->get($i, $j) / $v1); $scalar += pow($this->_matrix->get($i, $j), 2); } $this->_tau->set($j, 2.0 / $scalar); $w = new Vector($this->_matrix->columns()); $w->setAll(0.0); // First calculate w = v_j^T * A. for ($i = $j; $i < $this->_matrix->columns(); $i++) { $w->set($i, $this->_matrix->get($j, $i)); for ($k = $j + 1; $k < $this->_matrix->rows(); $k++) { if ($i == $j) { $w->set($i, $w->get($i) + $this->_matrix->get($k, $j) * $this->_matrix->get($k, $i) * $v1); } else { $w->set($i, $w->get($i) + $this->_matrix->get($k, $j) * $this->_matrix->get($k, $i)); } } $this->_matrix->set($j, $i, $this->_matrix->get($j, $i) - $this->_tau->get($j) * $w->get($i)); for ($k = $j + 1; $k < $this->_matrix->rows(); $k++) { if ($i > $j) { $this->_matrix->set($k, $i, $this->_matrix->get($k, $i) - $this->_tau->get($j) * $this->_matrix->get($k, $j) * $w->get($i)); } } } // Assemble v for trace. $v = new Vector($this->_matrix->rows() - $j); $v->set(0, 1); for ($i = 1; $i < $v->size(); $i++) { $v->set($i, $this->_matrix->get($i, $j)); } $this->_trace[$j] = array('v' => $v, 'matrix' => $this->_matrix->copy()); } }
/** * Multiplay given matrix by given vector. * * @param matrix matrix * @param vector vector * @return vector product matrix*vector */ public static function operate($matrix, $vector) { // First check dimensions. new Assertion($matrix instanceof Matrix, 'Given matrix not of class Matrix.'); new Assertion($vector instanceof Vector, 'Given vector not of class Vector.'); new Assertion($matrix->columns() == $vector->size(), 'Given dimensions are not compatible.'); $result = new Vector($matrix->rows()); $result->setAll(0.0); for ($i = 0; $i < $matrix->rows(); $i++) { for ($j = 0; $j < $matrix->columns(); $j++) { $result->set($i, $result->get($i) + $matrix->get($i, $j) * $vector->get($j)); } } return $result; }
/** * Multiply the given matrix and vector. * * @param matrix matrix * @param vector vector * @return vector product matrix*vector */ public static function multiply($a, $x) { // First check dimensions. new Assertion($a instanceof Matrix, 'Given matrix not of class Matrix.'); new Assertion($x instanceof Vector, 'Given vector not of class Vector.'); new Assertion($a->columns() == $x->size(), 'Given dimensions are not compatible.'); $c = new Vector($a->rows()); $c->setAll(0.0); for ($i = 0; $i < $a->rows(); $i++) { for ($j = 0; $j < $x->size(); $j++) { $c->set($i, $c->get($i) + $a->get($i, $j) * $x->get($j)); } } return $c; }