/** * @inheritDoc */ protected function doCompute(NumericTypeInterface $a, NumericTypeInterface $b, Calculator $calc) { if ($this->getComparator()->compare($b, TypeFactory::createInt(0)) === 0) { return null; } return $calc->div($a, $b); }
/** * @inheritDoc */ public function derive(NumericMatrix $mA, $extra = null) { if ($mA->is('empty')) { return TypeFactory::createInt(0); } if ($mA->is('singleitem')) { return $mA->get(1, 1); } $calc = new Calculator(); return array_reduce($mA->toArray(), function ($c1, $row) use($calc) { return array_reduce($row, function ($carry, $item) use($calc) { return $calc->add($item, $carry); }, $c1); }, TypeFactory::createInt(0)); }
/** * @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); }
/** * Find tr(M) * * @param NumericMatrix $mA * @param mixed $extra * @return numeric * * @throws Chippyash/Math/Matrix/Exceptions/UndefinedComputationException */ public function derive(NumericMatrix $mA, $extra = null) { if ($mA->is('singleitem')) { return $mA->get(1, 1); } $this->assertMatrixIsNotEmpty($mA, 'No trace for empty matrix')->assertMatrixIsSquare($mA, 'No trace for non-square matrix'); $tr = new FloatType(0); $size = $mA->rows(); $data = $mA->toArray(); $calc = new Calculator(); for ($x = 0; $x < $size; $x++) { $tr = $calc->add($tr, $data[$x][$x]); } return $tr; }
/** * Multiply each member of the matrix by single scalar value and return result * Boolean values are converted to 0 (false) and 1 (true). Use the logical * computations if required. * String values must conform to the requirements of a rational string number * i.e. '2/3', else an exception will be thrown * * @param Matrix $mA First matrix to act on - required * @param scalar $extra value to add * * @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->mul($data[$row][$col], $scalar); } } return $this->createCorrectMatrixType($mA, $data); }
/** * Carry out the actual multiplication using standard matrix multiplication * method. * * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @param \Chippyash\Math\Matrix\NumericMatrix $mB * @return array * @throws ComputationException */ protected function doComputation(NumericMatrix $mA, NumericMatrix $mB) { $size = max([$mA->columns(), $mA->rows(), $mB->columns(), $mB->rows()]); $product = (new ZMatrix())->create([$size, $size])->toArray(); $dA = $mA->toArray(); $dB = $mB->toArray(); $zero = $this->createCorrectScalarType($mA, 0); $calc = new Calculator(); for ($i = 0; $i < $size; $i++) { for ($k = 0; $k < $size; $k++) { for ($j = 0; $j < $size; $j++) { $a = isset($dA[$i][$k]) ? $dA[$i][$k] : $zero; $b = isset($dB[$k][$j]) ? $dB[$k][$j] : $zero; $product[$i][$j] = $calc->add($product[$i][$j], $calc->mul($a, $b)); } } } return $product; }
/** * @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'); }
/** * Inter row multiplication * * @param array $a * @param NumericTypeInterface $multiple * @param int $rowToMultiplyWith * @param int $rowToAddTo * @param \Chippyash\Math\Type\Calculator $calc */ protected function addMultipleOfOtherRowToRow(array &$a, $multiple, $rowToMultiplyWith, $rowToAddTo, Calculator $calc) { $numberOfColumns = count($a[0]); for ($l = 0; $l < $numberOfColumns; $l++) { $a[$rowToAddTo][$l] = $calc->add($a[$rowToAddTo][$l], $calc->mul($a[$rowToMultiplyWith][$l], $multiple)); } }
/** * @inheritDoc */ protected function doCompute(NumericTypeInterface $a, NumericTypeInterface $b, Calculator $calc) { return $calc->sub($a, $b); }
/** * Invert the matrix * * $mA must be square and nonsingular. * An empty $mA returns an empty matrix * A single entry matrix e.g. [[n]] returns [[1/n]] * A zero single item matrix e.g. [[0]] throws an exception (Division by zero) * * @param Chippyash\Math\Matrix\NumericMatrix $mA First matrix operand - required * @param mixed $extra ignored * * @return Chippyash\Math\Matrix\NumericMatrix * * @throws Chippyash\Matrix\Exceptions\ComputationException * @throws Chippyash\Matrix\Exceptions\UndefinedComputationException */ protected function doTransform(Matrix $mA, $extra = null) { $this->assertMatrixIsNumeric($mA); if ($mA->is('empty')) { return $this->createCorrectMatrixType($mA); } if ($mA->is('singleitem')) { $item = $mA->get(1, 1)->get(); if ($item == 0 || $item == '0+0i') { throw new ComputationException('Division by zero'); } else { $calc = new Calculator(); return $this->createCorrectMatrixType($mA, [$calc->reciprocal($mA->get(1, 1))]); } } $this->assertMatrixIsNonSingular($mA, 'Can only perform inversion on non singular matrix'); $I = $this->invert($mA); return $I; }
/** * Set determinant of original matrix if it is square */ protected function setDeterminant(NumericMatrix $mA) { if (!$mA->is('square')) { //determinant undefined for non square matrix $this->set('Det', null); return; } if ($mA->is('empty')) { $this->set('Det', $this->createCorrectScalarType($mA, 1)); return; } $det = $this->createCorrectScalarType($mA, $this->pivsign); $LU = $this->LU->toArray(); $calc = new Calculator(); $this->set('Det', function () use($det, $LU, $calc) { $c = count($LU); for ($j = 0; $j < $c; $j++) { $det = $calc->mul($det, $LU[$j][$j]); } return $det; }); }