/**
  * @expectedException BadMethodCallException
  * @expectedExceptionMessage Unsupported comparator method: foo
  */
 public function testMagicCallThrowsExceptionForUnknownMethod()
 {
     $one = new IntType(1);
     $c = new Comparator();
     //use default engine
     $this->assertEquals(true, $c->foo($one, $one));
 }
Esempio n. 2
0
 /**
  * Format the matrix contents for outputting
  *
  * @param Matrix $mA Matrix to format
  * @param array $options Options for formatter
  *  - attribs => Collection of VertexDescription
  *  - optional: edgeFunc => function($weight){return $newWeight;}
  *  - optional: output:string script|object default = script
  *
  * If output is script, return the graphviz dot file contents
  * If output is object then return Fhaculty\Graph\Graph for your own
  * processing via Graphp\GraphViz\GraphViz
  *
  * @return Graph|string
  */
 public function format(Matrix $mA, array $options = array())
 {
     if (!$mA instanceof NumericMatrix) {
         throw new \InvalidArgumentException('Matrix is not NumericMatrix');
     }
     return FFor::create(['mA' => $mA, 'graph' => new Graph(), 'options' => $options])->attribs(function ($options) {
         $attribs = array_key_exists('attribs', $options) ? $options['attribs'] : new Collection([], 'string');
         if ($attribs instanceof Collection) {
             return $attribs;
         }
         throw new \InvalidArgumentException('options[attribs]');
     })->edgeFunc(function ($options) {
         $edgeFunc = array_key_exists('edgeFunc', $options) ? $options['edgeFunc'] : function ($w) {
             return $w;
         };
         if ($edgeFunc instanceof \Closure) {
             return $edgeFunc;
         }
         throw new \InvalidArgumentException('pptions[edgeFunc]');
     })->output(function ($options) {
         return array_key_exists('output', $options) ? $options['output'] : 'script';
     })->vertices(function (Collection $attribs, Matrix $mA, Graph $graph) {
         $vertices = [];
         foreach (range(0, $mA->rows() - 1) as $idx) {
             if (array_key_exists($idx, $attribs)) {
                 $attribute = $attribs[$idx];
                 $vertices[$idx + 1] = $graph->createVertex($attribute->getName());
                 foreach ($attribute->getAttributes() as $key => $val) {
                     $vertices[$idx + 1]->setAttribute($key, $val);
                 }
             } else {
                 $vertices[$idx + 1] = $graph->createVertex();
             }
         }
         return $vertices;
     })->graphViz(function (Graph $graph, Matrix $mA, array $vertices, \Closure $edgeFunc, $output) {
         $comp = new Comparator();
         $zero = TypeFactory::createInt(0);
         $rows = $mA->rows();
         for ($row = 1; $row <= $rows; $row++) {
             for ($col = 1; $col <= $rows; $col++) {
                 if ($comp->compare($zero, $mA->get($row, $col)) != 0) {
                     $vertices[$row]->createEdgeTo($vertices[$col])->setWeight($edgeFunc($mA->get($row, $col)->get()));
                 }
             }
         }
         return $output == 'script' ? (new GraphViz())->createScript($graph) : $graph;
     })->fyield('graphViz');
 }
Esempio n. 3
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);
 }
Esempio n. 4
0
 /**
  * Construct a Matrix with all entries set to IntType(0)
  *
  * @param NumericTypeInterface $rows Number of required rows
  * @param NumericTypeInterface $cols Number of required columns
  *
  * @throws \InvalidArgumentException
  */
 public function __construct(NumericTypeInterface $rows, NumericTypeInterface $cols)
 {
     $comp = new Comparator();
     $one = TypeFactory::createInt(1);
     if ($comp->lt($rows, $one)) {
         throw new \InvalidArgumentException('$rows must be >= 1');
     }
     if ($comp->lt($cols, $one)) {
         throw new \InvalidArgumentException('$cols must be >= 1');
     }
     $f = function ($row, $col) {
         return TypeFactory::createInt(0);
     };
     parent::__construct($f, $rows, $cols);
 }
Esempio n. 5
0
 /**
  * Does the matrix exhibit this attribute
  *
  * @param Matrix $mA
  *
  * @return boolean
  */
 public function is(Matrix $mA)
 {
     try {
         $this->assertMatrixIsNumeric($mA)->assertMatrixIsSquare($mA);
     } catch (MatrixException $e) {
         return false;
     }
     //we've already assured it is square, now make sure we at least have a
     // cyclic probability
     if ($mA->rows() < 2 || $mA->columns() < 2) {
         return false;
     }
     $sumDerivative = new Sum();
     $firstRow = $mA('Rowslice', [1])->derive($sumDerivative);
     $comp = new Comparator();
     //check that each row has same sum
     foreach (range(2, $mA->rows()) as $row) {
         if ($comp->neq($firstRow, $mA('RowSlice', [$row])->derive($sumDerivative)) != 0) {
             return false;
         }
     }
     return true;
 }
 /**
  * Perform Guass Jordan Elimination on the two supplied matrices
  *
  * @param NumericMatrix $mA First matrix to act on - required
  * @param NumericMatrix $extra Second matrix to act upon - required
  *
  * @return \Chippyash\Math\Matrix\DecompositionAbstractDecomposition Fluent Interface
  *
  * @throws \Chippyash\Math\Matrix\Exceptions\SingularMatrixException
  */
 public function decompose(NumericMatrix $mA, $extra = null)
 {
     $this->assertParameterIsMatrix($extra, 'Parameter extra is not a matrix')->assertMatrixIsNumeric($extra, 'Parameter extra is not a numeric matrix')->assertMatrixIsSquare($mA, 'Parameter mA is not a square matrix')->assertMatrixRowsAreEqual($mA, $extra, 'mA->rows != extra->rows');
     $rows = $mA->rows();
     $dA = $mA->toArray();
     $dB = $extra->toArray();
     $zero = function () {
         return RationalTypeFactory::create(0, 1);
     };
     $one = function () {
         return RationalTypeFactory::create(1, 1);
     };
     $calc = new Calculator();
     $comp = new Comparator();
     $ipiv = array_fill(0, $rows, $zero());
     $indxr = array_fill(0, $rows, 0);
     $indxc = array_fill(0, $rows, 0);
     // find the pivot element by searching the entire matrix for its largest value, but excluding columns already reduced.
     $irow = $icol = 0;
     for ($i = 0; $i < $rows; $i++) {
         $big = $zero();
         for ($j = 0; $j < $rows; $j++) {
             if ($comp->neq($ipiv[$j], $one())) {
                 for ($k = 0; $k < $rows; $k++) {
                     if ($comp->eq($ipiv[$k], $zero())) {
                         $absVal = $dA[$j][$k]->abs();
                         if ($comp->gt($absVal, $big)) {
                             unset($big);
                             $big = clone $absVal;
                             $irow = $j;
                             $icol = $k;
                         }
                     } elseif ($comp->gt($ipiv[$k], $one())) {
                         throw new SingularMatrixException('GaussJordanElimination');
                     }
                 }
             }
         }
         //Now interchange row to move the pivot element to a diagonal
         $ipiv[$icol] = $calc->add($ipiv[$icol], $one());
         if ($irow != $icol) {
             $this->swapRows($dA, $irow, $icol);
             $this->swapRows($dB, $irow, $icol);
         }
         // Remember permutations to later
         $indxr[$i] = $irow;
         $indxc[$i] = $icol;
         if ($comp->eq($dA[$icol][$icol], $zero())) {
             throw new SingularMatrixException('GaussJordanElimination');
         }
         // Now divide the found row to make the pivot element 1
         // To maintain arithmetic integrity we use the reciprocal to multiply by
         $pivinv = $calc->reciprocal($dA[$icol][$icol]);
         $this->multRow($dA, $icol, $pivinv, $calc);
         $this->multRow($dB, $icol, $pivinv, $calc);
         // And reduce all other rows but the pivoted row with the value of the pivot row
         for ($ll = 0; $ll < $rows; $ll++) {
             if ($ll != $icol) {
                 $multiplier = clone $dA[$ll][$icol];
                 $multiplier->negate();
                 $this->addMultipleOfOtherRowToRow($dA, $multiplier, $icol, $ll, $calc);
                 $this->addMultipleOfOtherRowToRow($dB, $multiplier, $icol, $ll, $calc);
             }
         }
     }
     $this->set('left', $this->createCorrectMatrixType($mA, $dA));
     $this->set('right', $this->createCorrectMatrixType($extra, $dB));
     return clone $this;
 }
Esempio n. 7
0
 /**
  * Check equality of each matrix entry
  * Also check that matrices are same type if $strict
  *
  * @override ancestor
  *
  * @param \Chippyash\Matrix\Matrix $mB
  * @param boolean $strict
  *
  * @return boolean
  */
 protected function checkEntryEquality(Matrix $mB, $strict)
 {
     if ($strict) {
         if (get_class($this) !== get_class($mB)) {
             return false;
         }
     }
     $dA = $this->toArray();
     $dB = $mB->toArray();
     $m = $this->rows();
     $n = $this->columns();
     $comp = new Comparator();
     for ($i = 0; $i < $m; $i++) {
         for ($j = 0; $j < $n; $j++) {
             if ($strict) {
                 if ($dA[$i][$j] !== $dB[$i][$j]) {
                     return false;
                 }
             } else {
                 if ($comp->neq($dA[$i][$j], $dB[$i][$j])) {
                     return false;
                 }
             }
         }
     }
     return true;
 }
Esempio n. 8
0
 /**
  * Complex Pow - raise number to the exponent
  * Will return a ComplexType
  * Exponent must be non complex
  *
  * @param ComplexType $a operand
  * @param NI $exp Exponent
  *
  * @return ComplexType
  *
  * @throws \InvalidArgumentException If exponent is complex
  */
 public function complexPow(ComplexType $a, NI $exp)
 {
     if ($exp instanceof ComplexType) {
         $comp = new Comparator();
         $zero = new IntType(0);
         $real = 0;
         $imaginary = 0;
         if (!($comp->eq($a->r(), $zero) && $comp->eq($a->i(), $zero))) {
             list($real, $imaginary) = $this->getPowExponentPartsFromPolar($a, $exp);
         }
         return new ComplexType(RationalTypeFactory::fromFloat($real), RationalTypeFactory::fromFloat($imaginary));
     }
     //non complex
     //de moivres theorum
     //z^n = r^n(cos(n.theta) + sin(n.theta)i)
     //where z is a complex number, r is the radius
     $n = $exp();
     $nTheta = $n * $a->theta()->get();
     $pow = pow($a->modulus()->get(), $n);
     $real = cos($nTheta) * $pow;
     $imaginary = sin($nTheta) * $pow;
     return new ComplexType(RationalTypeFactory::fromFloat($real), RationalTypeFactory::fromFloat($imaginary));
 }
Esempio n. 9
0
 /**
  * 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));
 }