/** * Find the derivative * * @param NumericMatrix $mA * @param IntType $extra The current row to find the next weighted random row from * * @throws MathMatrixException * @throws NotMarkovException * * @return IntType */ public function derive(NumericMatrix $mA, $extra = null) { if (!$mA->is('Markov')) { throw new NotMarkovException(); } if (!$extra instanceof IntType) { throw new MathMatrixException('The extra parameter is not an IntType'); } $this->comp = new Comparator(); $this->calc = new Calculator(); $this->zero = TypeFactory::createInt(0); return $this->nextWeightedRandom($mA, $extra); }
public function testDecomposeCanSolveLinearEquation() { //solve //x + y + z = 5 //2x + 3y + 5z = 8 //4x + 5z = 2 $mA = new NumericMatrix([[1, 1, 1], [2, 3, 5], [4, 0, 5]]); $mB = new NumericMatrix([[5], [8], [2]]); $ret = $this->object->decompose($mA, $mB); $expected = new NumericMatrix([[3], [4], [-2]]); //z $this->assertTrue($expected->equality($ret->right, false)); }
/** * 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; }
/** * Divide a mtix by another * * @param NumericMatrix $mA First matrix operand - required * @param NumericMatrix $extra Second Matrix operand - required * * @return NumericMatrix */ public function compute(NumericMatrix $mA, $extra = null) { $this->assertParameterIsMatrix($extra, 'Parameter is not a matrix'); if ($mA->is('empty')) { $mA = $this->createCorrectMatrixType($mA, [1]); } if ($extra->is('empty')) { $extra = $this->createCorrectMatrixType($extra, [1]); } $this->assertMatrixColumnsAreEqual($mA, $extra)->assertMatrixRowsAreEqual($mA, $extra); $fI = new Invert(); $mI = $fI->transform($extra); $mul = new MM(); return $mul($mA, $mI); }
/** * @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)); }
/** * Construct a complete Matrix with all entries set to a complex number * Takes a source matrix or array (which can be incomplete and converts each * entry to complex number type, setting a default value if entry does not exist. * * If a Matrix is supplied as $source, the data is cloned into the ComplexMatrix * converting to complex number values, with no further checks, although you * may get exceptions thrown if conversion is not possible. * * If you don't supply a default value, then 0+0i will be used * * @param Matrix|array $source Array to initialise the matrix with * @param ComplexType $normalizeDefault Value to set missing vertices * */ public function __construct($source, ComplexType $normalizeDefault = null) { if (is_null($normalizeDefault)) { $ri = RationalTypeFactory::create(0, 1); $normalizeDefault = ComplexTypeFactory::create($ri, clone $ri); } parent::__construct($source, $normalizeDefault); }
/** * 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); }
public function testYouCanShiftAnotherMatrixByMultiplyingWithAShiftMatrix() { $uShift = new ShiftMatrix(new IntType(5), new StringType(ShiftMatrix::SM_TYPE_UPPER), new IntType(IdentityMatrix::IDM_TYPE_INT)); $mA = new NumericMatrix([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25]]); $uTest = new NumericMatrix([[0, 1, 2, 3, 4], [0, 6, 7, 8, 9], [0, 11, 12, 13, 14], [0, 16, 17, 18, 19], [0, 21, 22, 23, 24]]); $mB = $mA('Mul\\Matrix', $uShift); $this->assertEquals($uTest->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT]), $mB->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT])); $lShift = new ShiftMatrix(new IntType(5), new StringType(ShiftMatrix::SM_TYPE_LOWER), new IntType(IdentityMatrix::IDM_TYPE_INT)); $lTest = new NumericMatrix([[2, 3, 4, 5, 0], [7, 8, 9, 10, 0], [12, 13, 14, 15, 0], [17, 18, 19, 20, 0], [22, 23, 24, 25, 0]]); $mB = $mA('Mul\\Matrix', $lShift); $this->assertEquals($lTest->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT]), $mB->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT])); $uTest2 = new NumericMatrix([[6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20], [21, 22, 23, 24, 25], [0, 0, 0, 0, 0]]); $mB = $uShift('Mul\\Matrix', $mA); $this->assertEquals($uTest2->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT]), $mB->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT])); $lTest2 = new NumericMatrix([[0, 0, 0, 0, 0], [1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]); $mB = $lShift('Mul\\Matrix', $mA); $this->assertEquals($lTest2->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT]), $mB->setFormatter(new AsciiNumeric())->display(['outputType' => AsciiNumeric::TP_INT])); }
/** * @inheritDoc */ public function compute(NumericMatrix $mA, $extra = null) { $this->assertParameterIsMatrix($extra, 'Parameter is not a matrix'); if ($mA->is('empty') || $extra->is('empty')) { return $this->createCorrectMatrixType($mA, []); } $this->assertMatrixColumnsAreEqual($mA, $extra)->assertMatrixRowsAreEqual($mA, $extra); $data = (new ZMatrix())->create([$mA->rows(), $mA->columns()])->toArray(); $dA = $mA->toArray(); $dB = $extra->toArray(); $cols = $mA->columns(); $rows = $mA->rows(); $calc = new Calculator(); for ($row = 0; $row < $rows; $row++) { for ($col = 0; $col < $cols; $col++) { $data[$row][$col] = $this->doCompute($dA[$row][$col], $dB[$row][$col], $calc); } } return $this->createCorrectMatrixType($mA, $data); }
/** * Construct a complete Matrix with all entries set to Chippyash/Type * Takes a source matrix or array (which can be incomplete and converts each * entry to Chippyash/Type), setting a default value if entry does not exist. * * If a NumericMatrix is supplied as $source, the data is cloned into the Matrix * with no further checks. * * @param NumericMatrix|array $source Array to initialise the matrix with * @param mixed $normalizeDefault Value to set missing vertices * @throws \Chippyash\Math\Matrix\Exceptions\MathMatrixException */ public function __construct($source, $normalizeDefault = 0) { if ($source instanceof self) { $this->store($source->toArray()); return; } if (is_array($source)) { if (is_int($normalizeDefault)) { $default = TypeFactory::createInt($normalizeDefault); } elseif (is_float($normalizeDefault)) { $default = RationalTypeFactory::fromFloat($normalizeDefault); } elseif (!$normalizeDefault instanceof NumericTypeInterface) { throw new MathMatrixException('NumericMatrix expects numeric default value'); } else { $default = $normalizeDefault; } parent::__construct($source, false, true, $default); } else { throw new MathMatrixException('NumericMatrix expects NumericMatrix or array as source data'); } }
/** * ShiftMatrix constructor. * * @param IntType $size Number of required rows and columns * @param StringType $shiftType SM_TYPE_UPPER|SM_TYPE_LOWER * @param IntType|null $identityType Type of identity entries: default == IdentityType::IDM_TYPE_INT * */ public function __construct(IntType $size, StringType $shiftType, IntType $identityType = null) { $mA = (new Identity())->create([$size()]); $new = TypeFactory::createInt(0); $fS = new Shift(); if ($shiftType() == self::SM_TYPE_UPPER) { $mB = $fS($mA, [1, $new]); } if ($shiftType() == self::SM_TYPE_LOWER) { $mB = $fS($mA, [-1, $new]); } parent::__construct($mB); }
/** * Compute inverse using determinants method * We are expecting a non singular, square matrix (complete, n=m, n>1) * * @param \Chippyash\Matrix\Matrix $mA * @return Matrix */ public function invert(NumericMatrix $mA) { $rows = $mA->rows(); $cols = $mA->columns(); $work = array(); $fDet = new Det(); $fCof = new Cofactor(); for ($row = 0; $row < $rows; $row++) { for ($col = 0; $col < $cols; $col++) { $t = $fDet($fCof($mA, [$row + 1, $col + 1])); if (fmod($row + $col, 2) == 0) { $work[$row][$col] = $t; } else { $work[$row][$col] = $t->negate(); } $r = $row + 1; $c = $col + 1; } } $fTr = new Transpose(); $fDiv = new Scalar(); return $fTr($fDiv($this->createCorrectMatrixType($mA, $work), $fDet($mA))); }
/** * Construct a complete matrix whose entries are a result of a function * * The function must accept two parameters * e.g. $function($row, $col) {return $row - $col;} * * $row and $col are 1 based * * @param callable $function * @param IntType $rows Number of required rows * @param IntType $cols Number or required columns * * @throws \InvalidArgumentException */ public function __construct(callable $function, IntType $rows, IntType $cols) { if ($rows() < 1) { throw new \InvalidArgumentException('$rows must be >= 1'); } if ($cols() < 1) { throw new \InvalidArgumentException('$cols must be >= 1'); } $source = array(); $rc = $rows(); $cc = $cols(); for ($r = 0; $r < $rc; $r++) { for ($c = 0; $c < $cc; $c++) { $source[$r][$c] = $function($r + 1, $c + 1); } } parent::__construct($source); }
/** * 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; }); }
public function testEqualityWithLooseSettingReturnsFalseForDifferentClassAndDifferentContent() { $mN = new NumericMatrix([[2]]); $mR = new RationalMatrix([[12]]); $this->assertFalse($mN->equality($mR, false)); }
/** * Massage where mA is rectangle * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @param \Chippyash\Math\Matrix\NumericMatrix $mB * @param array $product * @return \Chippyash\Math\Matrix\NumericMatrix */ protected function massageRectangle(NumericMatrix $mA, NumericMatrix $mB, array $product) { if ($mB->is('rectangle') && $mA->rows() < $mB->rows()) { return $this->createCorrectMatrixType($mA, [[$product[0][0], $product[0][1]], [$product[1][0], $product[1][1]]]); } return $this->createCorrectMatrixType($mA, $product); }
/** * Compute determinant using a strategy * * @param \Chippyash\Math\Matrix\NumericMatrix $mA * @return numeric * @throws UndefinedComputationException * * @todo put back in LU determinant strategy once figured out what is wrong with it */ protected function getDeterminant(NumericMatrix $mA) { switch ($this->method) { case self::METHOD_AUTO: if ($mA->rows() <= self::$luLimit) { $strategy = new Lu(); } else { throw new UndefinedComputationException('No available strategy found to determine the determinant'); } break; case self::METHOD_LAPLACE: $strategy = new Laplace(); break; case self::METHOD_LU: $strategy = new Lu(); break; default: throw new UndefinedComputationException('Unknown determinant computation method'); } return $strategy->determinant($mA); }
/** * Return determinant of a 2X2 matrix * @link http://en.wikipedia.org/wiki/Matrix_determinant#2.C2.A0.C3.97.C2.A02_matrices * [[a, b] * [c, d]] * ad - bc * * @param \Chippyash\Math\Matrix\NumericMatrix $mA */ protected function det2(NumericMatrix $mA) { $c = $this->calc(); return $c->sub($c->mul($mA->get(1, 1), $mA->get(2, 2)), $c->mul($mA->get(1, 2), $mA->get(2, 1))); }
/** * Construct a complete Matrix with all entries set to a rational number * Takes a source matrix or array (which can be incomplete and converts each * entry to rational number, setting a default value if entry does not exist. * * If a Matrix is supplied as $source, the data is cloned into the RationalMatrix * converting to rational number values, with no further checks, although you * may get exceptions thrown if conversion is not possible. * * @param Matrix|array $source Array to initialise the matrix with * @param mixed $normalizeDefault Value to set missing vertices * */ public function __construct($source, $normalizeDefault = 0) { $default = $this->convertNumberToRational($normalizeDefault); parent::__construct($source, $default); }