/** * @param NumericMatrix $mA * @param NumericTypeInterface $start * @param NumericTypeInterface $target * @param NumericTypeInterface $limit * * @return NumericMatrix */ protected function walk(NumericMatrix $mA, NumericTypeInterface $start, NumericTypeInterface $target, NumericTypeInterface $limit) { $zero = TypeFactory::createInt(0); $one = TypeFactory::createInt(1); $calc = new Calculator(); $comp = new Comparator(); $lim = $calc->sub($limit, $one); $walk = [$start]; while ($comp->neq($start, $target) && $comp->neq($lim, $zero)) { $start = $mA('MarkovWeightedRandom', $start); $walk[] = $start; $lim = $calc->sub($lim, $one); } return new NumericMatrix($walk); }
/** * @param $sum * @param $rowArray * * @return mixed * * @throws MathMatrixException */ protected function getNextRow($sum, $rowArray) { return FFor::create(['sum' => $sum, 'rowArray' => $rowArray])->targetWeight(function ($sum) { return TypeFactory::createInt(mt_rand(1, $sum())); })->nextRow(function ($targetWeight, $rowArray) { foreach ($rowArray as $key => $weight) { if ($this->comp->lt($weight, $this->zero)) { throw new MathMatrixException('Negative weights not allowed'); } $targetWeight = $this->calc->sub($targetWeight, $weight); if ($this->comp->lte($targetWeight, $this->zero)) { return TypeFactory::createInt($key + 1); } } })->fyield('nextRow'); }
/** * Subtract a single scalar value from each member of the matrix and return result * Boolean values are converted to 0 (false) and 1 (true). Use the logical * computations if required. * String values do a string replace for the scalar, replacing occurences of * if with '' * * @param NumericMatrix $mA First matrix to act on - required * @param scalar $extra value to subtract * * @return Matrix * * @throws Chippyash/Matrix/Exceptions/ComputationException */ public function compute(NumericMatrix $mA, $extra = null) { if ($mA->is('empty')) { return $this->createCorrectMatrixType($mA); } $scalar = $this->createCorrectScalarType($mA, $extra); $data = $mA->toArray(); $lx = $mA->columns(); $ly = $mA->rows(); $calc = new Calculator(); for ($row = 0; $row < $ly; $row++) { for ($col = 0; $col < $lx; $col++) { $data[$row][$col] = $calc->sub($data[$row][$col], $scalar); } } return $this->createCorrectMatrixType($mA, $data); }
/** * @inheritDoc */ protected function doCompute(NumericTypeInterface $a, NumericTypeInterface $b, Calculator $calc) { return $calc->sub($a, $b); }
/** * LU Decomposition constructor. * * @param \Chippyash\Math\Matrix\NumericMatrix $mA */ protected function LUDecomposition(NumericMatrix $mA) { // Use a "left-looking", dot-product, Crout/Doolittle algorithm. $LU = $mA->toArray(); $m = $this->rows = $mA->rows(); $n = $this->cols = $mA->columns(); for ($i = 0; $i < $m; $i++) { $this->piv[$i] = $i; } $this->pivsign = 1; $LUrowi = []; $LUcolj = []; $calc = new Calculator(); $comp = new Comparator(); $zeroInt = $this->createCorrectScalarType($mA, 0); // Outer loop. for ($j = 0; $j < $n; $j++) { // Make a copy of the j-th column to localize references. for ($i = 0; $i < $m; $i++) { $LUcolj[$i] =& $LU[$i][$j]; } // Apply previous transformations. for ($i = 0; $i < $m; $i++) { $LUrowi = $LU[$i]; // Most of the time is spent in the following dot product. $kmax = min($i, $j); $s = clone $zeroInt; for ($k = 0; $k < $kmax; $k++) { $s = $calc->add($s, $calc->mul($LUrowi[$k], $LUcolj[$k])); } $LUcolj[$i] = $calc->sub($LUcolj[$i], $s); $LUrowi[$j] = $LUcolj[$i]; } // Find pivot and exchange if necessary. $p = $j; for ($i = $j + 1; $i < $m; $i++) { if ($comp->gt($LUcolj[$i]->abs(), $LUcolj[$p]->abs())) { $p = $i; } } if ($p != $j) { for ($k = 0; $k < $n; $k++) { //swap $t = $LU[$p][$k]; $LU[$p][$k] = $LU[$j][$k]; $LU[$j][$k] = $t; } $k = $this->piv[$p]; $this->piv[$p] = $this->piv[$j]; $this->piv[$j] = $k; $this->pivsign = $this->pivsign * -1; } // Compute multipliers. if ($j < $m && $comp->neq($LU[$j][$j], $zeroInt)) { for ($i = $j + 1; $i < $m; $i++) { $LU[$i][$j] = $calc->div($LU[$i][$j], $LU[$j][$j]); } } } $this->set('LU', $this->createCorrectMatrixType($mA, $LU)); }