Code Monkey home page Code Monkey logo

linearalgebra's Introduction

Matrix

Build Status Code Climate Code Coverage

Stand-alone Linear Algebra Library for PHP

Installation

composer require mcordingley/LinearAlgebra

Alternately, include this in your composer.json and then update:

"mcordingley/linearalgebra": "^3.0.0"

If Composer isn't an option for you, clone this repository and run build-phar.php to generate a phar archive that you can include into your project. PHP will autoload classes from inside the archive as needed.

Usage

Matrix

Start with a use statement for the class:

use MCordingley\LinearAlgebra\Matrix;

Then, instantiate a new instance of the matrix class like so:

$matrix = new Matrix([
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8]
]);

You can also generate an identity matrix with the identity factory function:

$threeByThreeIdentityMatrix = Matrix::identity(3);

With the matrix instance, you can retrieve individual elements with get using the zero-based indices of the row and column that you want:

$element = $matrix->get($row, $column);

It's also possible to find out how large the matrix is with getRowCount() and getColumnCount():

$rows = $matrix->getRowCount();
$columns = $matrix->getColumnCount();

You can also add, subtract, and multiply the matrix with scalar values and other matrices. All operations return a new Matrix and do not modify the underlying matrix:

$addedScalar = $matrix->addScalar(3);
$addedMatrix = $matrix->addMatrix($anotherMatrix);
$subtractedScalar = $matrix->subtractScalar(2);
$subtractedMatrix = $matrix->subtractMatrix($anotherMatrix);
$multipliedByScalar = $matrix->multiplyScalar(4);
$multipliedByMatrix = $matrix->multiplyMatrix($anotherMatrix);

Matrices can be compared with equals to see if they're equal:

if ($matrix1->equals($matrix2)) {
    // Equality for all!
}

In addition to these basic operations, the Matrix class offers other common matrix operations:

$matrix->inverse()
$matrix->adjugate()
$matrix->determinant()
$matrix->trace()
$matrix->transpose()

You can get the upper and lower triangular matrices by calling upper(bool) and lower(bool). The lone argument tells whether the main diagonal of the triangular matrix should be set to ones (true) or the value of the parent matrix (false).

It's also possible to run a map over the matrix:

$squaredElements = $matrix->map(function($element, $row, $column, $matrix) {
    return $element * $element
});

Submatrices may be extracted with sliceColumns($offset, $length) and sliceRows($offset, $length). The semantics of the arguments are the same as PHP's array_slice.

Similarly, spliceColumns($offset, $length, $replacement) and spliceRows($offset, $length, $replacement) can be used to create new matrices with specific rows or columns removed or replaced. Unlike the native PHP array_splice, these operations do not modify the matrix in place and return the removed elements, but instead return a new matrix with the splice applied.

If you need to combine together matrices, you can do so by calling the concatenation methods:

$m1 = new Matrix([
  [1,2,3],
  [4,5,6],
]);

$m2 = new Matrix([
  [7],
  [8],
]);

$m3 = new Matrix([[3,2,1]]);

$m4 = $m1->concatenateRight($m2);
//  [
//      [1,2,3,7],
//      [4,5,6,8],
//  ]

$m5 = $m1->concatenateBottom($m3);
// [
//     [1,2,3],
//     [4,5,6],
//     [3,2,1],
// ]

LU and LUP decomposition methods are available as separate classes and both expose lower() and upper() for the L and U portions of the decompositions, respectively. The LUP decomposition additionally exposes permutationMatrix and permutationArray to fetch the P component of the decomposition as well as parity to return the total number of pivots performed.

Vector

As with Matrix, import the class into your current namespace:

use MCordingley\LinearAlgebra\Vector;

Since a Vector is a special case of a Matrix, Vector inherits from Matrix. As such, every method available on Matrix is also available on Vector. Vector also exposes additional methods specific to working with vectors.

Creating a Vector differs from creating a Matrix only in that the constructor takes an array of scalars, rather than an array of arrays:

$vector = new Vector([1, 2, 3, 4]);

Note that Vector instances are all row vectors. If you need a column vector, transpose() the vector to get a Matrix with a single column.

If you need to cast a Matrix into a Vector, call the factory method fromMatrix():

$vector = Vector::fromMatrix($matrix);

toArray() is overridden to return an array of scalars to mirror how the constructor works. It is equivalent to calling $matrix->toArray()[0] on a Matrix instance.

getSize() is provided as an alias for getColumnCount(). sum() will return the sum of the Vector elements, while dotProduct($otherVector) will return the sum of the pair-wise products of $vector and $otherVector, and is also availabe aliased as innerProduct($otherVector). outerProduct($otherVector) will return a new Matrix representing the outer product of the two vectors. crossProduct($otherVector) is also available. Vectors may be normalized with normalize(). They may also be projected onto other vectors with project($otherVector). The Euclidean distance may also be calculated between two vectors with euclideanDistance($otherVector).

For measures of vector magnitude, l1Norm(), l2Norm(), and maxNorm() are all available, with length() as an alias for l2Norm().

Links to relevant Wikipedia articles are provided in the function documentation for additional detail.

Change-log

  • 3.0.0

    • Update to PHP 8 to start taking advantage of new features.
    • Adds some previously-missing type assertions enabled by PHP 8.
    • Adds euclideanDistance to Vector.
  • 2.2.0

    • Implement the ArrayAccess interface on Matrix to return row vectors.
    • Implement the ArrayAccess interface on Vector to return scalars.
    • Add addVector() and subtractVector() to Vector
    • Add magnitude() as an alias to length() on Vector
  • 2.1.1

    • Fix a bug involving inheritance with map() on Vector.
  • 2.1.0

    • Add Vector as a subclass of Matrix. Thanks to battlecook for this contribution.
  • 2.0.0

    • Drop support for PHP 5.x
    • Introduce strict scalar type hints
    • Drop deprecated functions and properties.
    • Tighten up interface with the final and private keywords.
    • diagonal() now returns a full matrix, not a vector.
    • Rename adjoint() to adjugate() for clarity.
    • Add entrywise() to compute the Hadamard product.
    • Add upper() and lower()
    • Add sliceColumns() and sliceRows()
    • Add spliceColumns() and spliceRows()
    • Add LU and LUP decompositions as classes.
  • 1.3.2

    • Deprecate __toString() magic method.
    • Deprecate isSymmetric().
  • 1.3.1

    • Deprecate use of the ArrayAccess interface.
    • More internal code style fixes.
  • 1.3.0

    • Fix typo in names of concatenateRight() and concatenateBottom()
    • Remove generated Phar file. Users who need it should use the build-phar.php script to generate one.
    • Refactor LUDecomposition to have a less awkward constructor.
    • Split add() into addMatrix() and addScalar(). Deprecate add().
    • Split subtract() into subtractMatrix() and subtractScalar(). Deprecate subtract().
    • Split multiply() into multiplyMatrix() and multiplyScalar(). Deprecate multiply().
    • Add getRowCount() and getColumnCount() accessors.
    • Deprecate rows and columns properties.
  • 1.2.0

    • Added concatenateBottom($other)
    • Added concatencateRight($other)
  • 1.1.0

    • Added diagonal().
  • 1.0.0

    • Switch to PSR-4 from PSR-0.
    • Take isSymmetric() public.
    • Rearrange source in Matrix.php to be more readable and PSR-compliant.
  • 0.9.1

    • Fix several bugs with the Cholesky decomposition and inverse.
  • 0.9.0

    • Bump version up to represent that this is close to it's final form.
    • Merged PR for faster inverse calculations
    • KISS Vector class good-bye.
    • Renamed eq to equals.
    • Removed set function, so instantiated objects are immutable.
  • 0.3.0

    • Added the identity factory function
    • Using Cholesky decomposition for faster matrix inversions for applicable matrices
    • Added eq function to test equality of matrices
    • Implemented the ArrayAccess interface
  • 0.2.0

    • Created the Vector type
    • \MCordingley namespace is now \mcordingley
    • Matrix functions that return a new Matrix now return a new instance of the called class
  • 0.1.0

    • Created the Matrix type
    • Scalar Addition
    • Scalar Subtraction
    • Scalar Multiplication
    • Matrix Addition
    • Matrix Subtraction
    • Matrix Multiplication
    • Inverse
    • Adjoint
    • Determinant
    • Trace
    • Transpose
    • Submatrix
    • Map

linearalgebra's People

Contributors

battlecook avatar brad-jones avatar mcordingley avatar rreynier avatar thominj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

linearalgebra's Issues

map function in matrix class have bug.

map function return "new static()"

but vector and matrix construct is different.

if vector class use map function, internal variable is wrapped by array one more.

for example, following test case is failed

public function testGetAfterUseMatrixFunction()
{
$vector1 = new Vector([1, 1]);
$vector2 = new Vector([3, 2]);
$this->assertEquals(4, $vector1->addMatrix($vector2)->get(0,0));
}

Odd Behavior on Inverse Using Cholesky Decomp

Something's awry with the Matrix::choleskyDecomposition() function. Running the below code produces a rapid series of notices complaining about undefined indices.

use mcordingley\LinearAlgebra\Matrix;

$matrix = new Matrix([
    [1, 400],
    [1, 600],
    [1, 800],
    [1, 1200],
    [1, 1600],
    [1, 2400],
    [1, 3200],
    [1, 4800],
    [1, 6400],
    [1, 9600],
    [1, 12800],
    [1, 19200],
    [1, 25600],
    [1, 38400],
    [1, 51200],
    [1, 76800],
    [1, 102400],
    [1, 153600],
    [1, 204800],
    [1, 307200],
    [1, 409600],
    [1, 614400],
    [1, 819200],
    [1, 1228800],
    [1, 1638400],
]);

$matrix->transpose()->multiply($matrix)->inverse();

One sample notice:

PHP Notice:  Undefined offset: 591 in /home/michael/projects/LinearAlgebra/src/mcordingley/LinearAlgebra/Matrix.php on line 541
PHP Stack trace:
PHP   1. {main}() /home/michael/projects/LinearAlgebra/harness.php:0
PHP   2. mcordingley\LinearAlgebra\Matrix->inverse() /home/michael/projects/LinearAlgebra/harness.php:35
PHP   3. mcordingley\LinearAlgebra\Matrix->choleskyInverse() /home/michael/projects/LinearAlgebra/src/mcordingley/LinearAlgebra/Matrix.php:339
PHP   4. mcordingley\LinearAlgebra\Matrix::choleskyDecomposition() /home/michael/projects/LinearAlgebra/src/mcordingley/LinearAlgebra/Matrix.php:353

Notice: Undefined offset: 591 in /home/michael/projects/LinearAlgebra/src/mcordingley/LinearAlgebra/Matrix.php on line 541

Call Stack:
    0.0002     236088   1. {main}() /home/michael/projects/LinearAlgebra/harness.php:0
    0.0078     610032   2. mcordingley\LinearAlgebra\Matrix->inverse() /home/michael/projects/LinearAlgebra/harness.php:35
    0.0091     668728   3. mcordingley\LinearAlgebra\Matrix->choleskyInverse() /home/michael/projects/LinearAlgebra/src/mcordingley/LinearAlgebra/Matrix.php:339
    0.0091     668840   4. mcordingley\LinearAlgebra\Matrix::choleskyDecomposition() /home/michael/projects/LinearAlgebra/src/mcordingley/LinearAlgebra/Matrix.php:353

map function

Be able to run a map operation over a matrix, returning a new matrix.

Possible usage example:
$newMatrix = $matrix->map(function($element) {
return $element * $element;
});

Matrix Concatination

It would be nice to have two concatenation methods, one to add additional columns, and one to add additional rows.

$M1 = new Matrix ([
  [1,2,3],
  [4,5,6],
];

$M2 = new Matrix{[
  [7],
  [8],
];
$M3 = new Matrix([[3,2,1]]);

$M4 = $M1->concatinateRight($M2);
 //[[1,2,3,7],
//  [4,5,6,8]]

$M5 = $M1->concatinateBottom($M3);
  //[[1,2,3],
  // [4,5,6],
  // [3,2,1]]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.