예제 #1
0
 /**
  * Return the modulus, also known as absolute value or magnitude of this number
  * = sqrt(r^2 + i^2);
  *
  * @return \Chippyash\Type\Number\Rational\GMPRationalType
  */
 public function modulus()
 {
     if ($this->isReal()) {
         //sqrt(r^2 + 0^2) = sqrt(r^2) = abs(r)
         /** @noinspection PhpUndefinedMethodInspection */
         return $this->value['real']->abs();
     }
     //get r^2 and i^2
     $sqrR = array('n' => gmp_pow($this->value['real']->numerator()->gmp(), 2), 'd' => gmp_pow($this->value['real']->denominator()->gmp(), 2));
     $sqrI = array('n' => gmp_pow($this->value['imaginary']->numerator()->gmp(), 2), 'd' => gmp_pow($this->value['imaginary']->denominator()->gmp(), 2));
     //r^2 + i^2
     $den = $this->lcm($sqrR['d'], $sqrI['d']);
     $numRaw = gmp_strval(gmp_add(gmp_div_q(gmp_mul($sqrR['n'], $den), $sqrR['d']), gmp_div_q(gmp_mul($sqrI['n'], $den), $sqrI['d'])));
     $num = TypeFactory::createInt($numRaw);
     //sqrt(num/den) = sqrt(num)/sqrt(den)
     //now this a fudge - we ought to be able to get a proper square root using
     //factors etc but what we do instead is to do an approximation by converting
     //to intermediate rationals using as much precision as we can i.e.
     // rNum = GMPRationaType(sqrt(num))
     // rDen = GMPRationalType(sqrt(den))
     // mod = rN/1 * 1/rD
     $rNum = RationalTypeFactory::fromFloat(sqrt($num()));
     $rDen = RationalTypeFactory::fromFloat(sqrt(gmp_strval($den)));
     $modN = gmp_mul($rNum->numerator()->gmp(), $rDen->denominator()->gmp());
     $modD = gmp_mul($rNum->denominator()->gmp(), $rDen->numerator()->gmp());
     return RationalTypeFactory::create((int) gmp_strval($modN), (int) gmp_strval($modD));
 }
 public function testInvokeProxiesToDerive()
 {
     $f = $this->object;
     $m = new NumericMatrix([]);
     $this->assertInstanceOf('Chippyash\\Math\\Matrix\\NumericMatrix', $f($m));
     $this->assertEquals([[TypeFactory::createInt(2)]], $f($m)->toArray());
 }
예제 #3
0
 /**
  * @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);
 }
 /**
  * Convert if possible a supplied argument to a strong numeric type
  *
  * @param int|float|string|NumericTypeInterface $numerator
  * @return Chippyash\Type\Interfaces\NumericTypeInterface
  * @throws UndefinedComputationException
  */
 protected function convertNumberToNumeric($value)
 {
     switch (gettype($value)) {
         case 'integer':
             return TypeFactory::createInt($value);
         case 'double':
             return TypeFactory::createRational($value);
         case 'string':
             try {
                 if (is_numeric($value)) {
                     $value = floatval($value);
                 }
                 return TypeFactory::createRational($value);
             } catch (\Exception $e) {
                 try {
                     return TypeFactory::createComplex($value);
                 } catch (\Exception $ex) {
                     throw new MatrixException("The string representation of the number ('{$value}') is invalid for a complex");
                 }
             }
         case 'object':
             if ($value instanceof NumericTypeInterface) {
                 return $value;
             } else {
                 throw new MatrixException('NumberToNumeric expects int, float, string or Rational value');
             }
         case 'NULL':
             return TypeFactory::createInt(0);
         case 'boolean':
             return TypeFactory::createInt($value ? 1 : 0);
         default:
             throw new MatrixException('NumberToNumeric expects int, float, string or Rational ');
     }
 }
 public function testInvokeProxiesToCompute()
 {
     $this->object->expects($this->exactly(2))->method('compute')->will($this->returnValue(new NumericMatrix([[2]])));
     $f = $this->object;
     $m = new NumericMatrix(array());
     $this->assertInstanceOf('Chippyash\\Math\\Matrix\\NumericMatrix', $f($m));
     $this->assertEquals([[TypeFactory::createInt(2)]], $f($m)->toArray());
 }
예제 #6
0
 public function setUp()
 {
     RequiredType::getInstance()->set(RequiredType::TYPE_NATIVE);
     $this->object = new AsciiNumeric();
     $this->rationalOne = TypeFactory::createRational(TypeFactory::createInt(1), TypeFactory::createInt(1));
     $this->rationalHalf = TypeFactory::createRational(TypeFactory::createInt(1), TypeFactory::createInt(2));
     $this->complexTwo = TypeFactory::createComplex(TypeFactory::createRational(TypeFactory::createInt(2), TypeFactory::createInt(1)), TypeFactory::createRational(TypeFactory::createInt(0), TypeFactory::createInt(1)));
     $this->complexThree = TypeFactory::createComplex(TypeFactory::createRational(TypeFactory::createInt(3), TypeFactory::createInt(1)), TypeFactory::createRational(TypeFactory::createInt(-3), TypeFactory::createInt(2)));
 }
function createMatrix($size)
{
    $c = 0;
    $fn = function ($r, $c) use(&$c) {
        return RationalTypeFactory::create($c++, 1);
    };
    $iSize = TypeFactory::createInt($size);
    return MatrixFactory::createFromFunction($fn, $iSize, $iSize, new StringType('rational'));
}
예제 #8
0
 private function toStrongType(array $values)
 {
     $ret = [];
     foreach ($values as $r => $row) {
         foreach ($row as $c => $item) {
             $ret[$r][$c] = TypeFactory::createInt($item);
         }
     }
     return $ret;
 }
 public function testYouCanPickTheNextLinkInAChain()
 {
     $chain = new NumericMatrix([[2, 0, 6, 2], [0, 0, 6, 4], [8, 1, 1, 0], [0, 5, 0, 5]]);
     $res = [2 => 0, 3 => 0];
     for ($x = 0; $x < 100; $x++) {
         $test = $this->sut->derive($chain, TypeFactory::createInt(2));
         $res[$test() - 1]++;
     }
     $this->assertEquals(100, array_sum($res));
 }
예제 #10
0
 public function testConstructGivesExpectedOutput()
 {
     $expected = [[TypeFactory::createInt(0), TypeFactory::createInt(-1), TypeFactory::createInt(-2)], [TypeFactory::createInt(1), TypeFactory::createInt(0), TypeFactory::createInt(-1)], [TypeFactory::createInt(2), TypeFactory::createInt(1), TypeFactory::createInt(0)]];
     $this->object = new FunctionMatrix($this->function, TypeFactory::createInt(3), TypeFactory::createInt(3));
     $this->assertEquals($expected, $this->object->toArray());
     $this->assertTrue($this->object->is('Complete'));
     $this->assertTrue($this->object->is('Square'));
     $this->assertFalse($this->object->is('Empty'));
     $this->assertFalse($this->object->is('RowVector'));
     $this->assertFalse($this->object->is('ColumnVector'));
 }
 /**
  * Create a new scalar based on type of original matrix
  *
  * @param \Chippyash\Math\Matrix\NumericMatrix $originalMatrix
  * @param scalar $scalar
  * @return Chippyash\Type\Interfaces\NumericTypeInterface
  *
  */
 protected function createCorrectScalarType(NumericMatrix $originalMatrix, $scalar)
 {
     if ($scalar instanceof NumericTypeInterface) {
         if ($originalMatrix instanceof RationalMatrix) {
             return $scalar->asRational();
         }
         if ($originalMatrix instanceof ComplexMatrix) {
             return $scalar->asComplex();
         }
         return $scalar;
     }
     if ($originalMatrix instanceof ComplexMatrix) {
         if (is_numeric($scalar)) {
             return ComplexTypeFactory::create($scalar, 0);
         }
         if (is_string($scalar)) {
             try {
                 return RationalTypeFactory::create($scalar)->asComplex();
             } catch (\Exception $e) {
                 //do nothing
             }
         }
         if (is_bool($scalar)) {
             return ComplexTypeFactory::create($scalar ? 1 : 0, 0);
         }
         return ComplexTypeFactory::create($scalar);
     }
     if ($originalMatrix instanceof RationalMatrix) {
         if (is_bool($scalar)) {
             $scalar = $scalar ? 1 : 0;
         }
         return RationalTypeFactory::create($scalar);
     }
     //handling for NumericMatrix
     if (is_int($scalar)) {
         return TypeFactory::createInt($scalar);
     } elseif (is_float($scalar)) {
         return TypeFactory::createRational($scalar);
     } elseif (is_bool($scalar)) {
         return TypeFactory::createInt($scalar ? 1 : 0);
     } elseif (is_string($scalar)) {
         try {
             return TypeFactory::createRational($scalar);
         } catch (\InvalidArgumentException $e) {
             try {
                 return ComplexTypeFactory::create($scalar);
             } catch (\InvalidArgumentException $e) {
                 //do nothing
             }
         }
     }
     throw new ComputationException('Scalar parameter is not a supported type for numeric matrices: ' . getType($scalar));
 }
예제 #12
0
 /**
  * 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);
 }
예제 #13
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');
 }
예제 #14
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);
 }
예제 #15
0
 /**
  * @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));
 }
예제 #16
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);
 }
예제 #17
0
 /**
  * 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');
     }
 }
예제 #18
0
 /**
  * @param RationalType $radius
  * @param RationalType $sin
  *
  * @return array
  *
  * @throws InvalidTypeException
  */
 private static function getImaginaryPartsFromRadiusAndSin(RationalType $radius, RationalType $sin)
 {
     return array(TypeFactory::create('int', $radius->numerator()->get() * $sin->numerator()->get()), TypeFactory::create('int', $radius->denominator()->get() * $sin->denominator()->get()));
 }
예제 #19
0
 public function testYouCanPlaceALimitOnTheWalk()
 {
     $chain = new NumericMatrix($this->chainData());
     $res = $this->sut->transform($chain, array('start' => TypeFactory::createInt(4), 'target' => TypeFactory::createInt(2), 'limit' => TypeFactory::createInt(2)));
     $this->assertEquals(2, $res->columns());
     $this->assertEquals(1, $res->rows());
 }
예제 #20
0
 /**
  * @expectedException InvalidArgumentException
  * @expectedExceptionMessage $cols must be >= 1
  */
 public function testConstructingWithColsLessThanOneThrowsException()
 {
     $zero = TypeFactory::createInt(0);
     $one = TypeFactory::createInt(1);
     new ZeroMatrix($one, $zero);
 }
예제 #21
0
 public function computeMatrices()
 {
     //set required type as data is generated before tests
     RequiredType::getInstance()->set(RequiredType::TYPE_NATIVE);
     return [[[[1, 2, 3], [3, 2, 1], [2, 1, 3]], [[TypeFactory::createInt(2), TypeFactory::createInt(4), TypeFactory::createInt(6)], [TypeFactory::createInt(6), TypeFactory::createInt(4), TypeFactory::createInt(2)], [TypeFactory::createInt(4), TypeFactory::createInt(2), TypeFactory::createInt(6)]], 2], [[[1, 2, 3]], [[RationalTypeFactory::create(2.5), RationalTypeFactory::create(5.0), RationalTypeFactory::create(7.5)]], 2.5], [[[1.5, 2.5, 3.5]], [[RationalTypeFactory::create(3.0), RationalTypeFactory::create(5.0), RationalTypeFactory::create(7.0)]], 2], [[[1.12, 2.12, 3.12]], [[RationalTypeFactory::create(1.12), RationalTypeFactory::create(2.12), RationalTypeFactory::create(3.12)]], 1.0], [[[1, 2, 3]], [[TypeFactory::createInt(1), TypeFactory::createInt(2), TypeFactory::createInt(3)]], true], [[[1, 2, 3]], [[TypeFactory::createInt(0), TypeFactory::createInt(0), TypeFactory::createInt(0)]], false], [[[true, false]], [[TypeFactory::createInt(1), TypeFactory::createInt(0)]], true], [[[true, false]], [[TypeFactory::createInt(0), TypeFactory::createInt(0)]], false]];
 }
 public function testSetNumberTypeToDefaultWillSetGmpIfAvailable()
 {
     RequiredType::getInstance()->set(RequiredType::TYPE_DEFAULT);
     $this->assertInstanceOf('Chippyash\\Type\\Number\\Rational\\GMPRationalType', TypeFactory::create('rational', 2));
 }
예제 #23
0
 /**
  * Create and return a Numeric Identity Matrix with IntType entries
  *
  * @param \Chippyash\Type\Number\IntType $size
  * @return \Chippyash\Math\Matrix\NumericMatrix
  */
 public static function numericIdentity(IntType $size)
 {
     return new self($size, TypeFactory::createInt(self::IDM_TYPE_INT));
 }
예제 #24
0
 /**
  * @requires extension gmp
  * @runInSeparateProcess
  */
 public function testCreatingFloatsViaTypeFactoryUnderGmpWillReturnGMPRationalType()
 {
     RequiredType::getInstance()->set(RequiredType::TYPE_GMP);
     $this->assertInstanceOf('Chippyash\\Type\\Number\\Rational\\GMPRationalType', TypeFactory::create('float', 2 / 3));
 }
예제 #25
0
 /**
  * Return number as a FloatType number.
  *
  * @return \Chippyash\Type\Number\FloatType
  * @throws NotRealComplexException
  */
 public function asFloatType()
 {
     if ($this->isReal()) {
         return TypeFactory::create('float', $this->value['real']->get());
     } else {
         throw new NotRealComplexException();
     }
 }
 public function validNumerics()
 {
     return [[2], [2.5], ['12.45'], ['2/5'], [true], [false], ['2+3i'], [TypeFactory::createComplex(2)], [TypeFactory::createInt(2)], [TypeFactory::createFloat(2)], [TypeFactory::createRational(2)], [null]];
 }
        } else {
            echo "{$op}({$tA}({$p1})) = {$tR}({$res})" . PHP_EOL;
        }
    } catch (InvalidTypeException $e) {
        $msg = $e->getMessage();
        echo "{$tA}({$p1}) {$op} {$tB}({$p2}) is invalid: {$msg}" . PHP_EOL;
    }
}
$iphp = 19;
$fphp = 13.27;
$i = F::create('int', 6);
$w = F::create('whole', 21);
$n = F::create('natural', 13);
$f = F::create('float', 2.26);
$r = F::Create('rational', '2/3');
$c = F::create('complex', '2+6i');
$items = [$iphp, $i, $w, $n, $fphp, $f, $r, $c];
echo "Library supported arithmetic operations and return types\n";
echo "Non complex numbers\n";
echo "Addition\n\n";
foreach ($items as $a) {
    foreach ($items as $b) {
        display('add', $a, $b);
    }
}
echo "\nSubtraction\n\n";
foreach ($items as $a) {
    foreach ($items as $b) {
        display('sub', $a, $b);
    }
}
예제 #28
0
 public function mixedMatrices()
 {
     return [[[[1, 2, 3]], TypeFactory::createInt(6)], [[[1], [2], [3]], TypeFactory::createInt(6)], [[[1, 2, 3], [1, 2, 3]], TypeFactory::createInt(12)], [[[1.1, 2, 3], [1, 2.2, 3]], RationalTypeFactory::fromFloat(12.3)], [[[0.5, 0.5]], RationalTypeFactory::create(1)]];
 }
예제 #29
0
 * we get into an overflow situation.
 *
 * Setting tolerance to a lower number, say 1e-6, will compute faster but at the
 * expense of accuracy
 */
RationalTypeFactory::setDefaultFromFloatTolerance(1.0E-15);
/**
 * Set the required number type.  System will automatically use GMP if
 * it is available.  You can force it to use native PHP thus:
 */
RequiredType::getInstance()->set(RequiredType::TYPE_NATIVE);
//now create 10000 numbers for the test
//try playing with this figure to see the results
$numbers = [];
for ($x = 1; $x < 10001; $x++) {
    $numbers[$x] = TypeFactory::create('int', $x);
}
//create primes
$primes = [];
$start = microtime(true);
foreach ($numbers as $key => $number) {
    $primes[$key] = $number->primeFactors();
}
$end = microtime(true);
$time = $end - $start;
echo "{$time} secs.\n";
echo "And the results were:\n";
foreach ($primes as $key => $res) {
    $p = array_keys($res);
    $e = array_values($res);
    $factors = "{$key}=>";
 /**
  * Exception to non commutative rule
  */
 public function testMultiplicationByAnIdentityMatrixIsCommmutative()
 {
     $mA = $this->square;
     $mB = new IdentityMatrix(TypeFactory::createInt($mA->rows()));
     $this->assertEquals($this->object->compute($mA, $mB), $this->object->compute($mB, $mA));
 }