markrogoyski / math-php

Powerful modern math library for PHP: Features descriptive statistics and regressions; Continuous and discrete probability distributions; Linear algebra with matrices and vectors, Numerical analysis; special mathematical functions; Algebra
MIT License
2.33k stars 240 forks source link

Function Matrix and OOP #61

Open Beakerboy opened 8 years ago

Beakerboy commented 8 years ago

Thinking about the new FunctionMatrix...Some of the parent functions will not work on it unless it's been evaluated into a determined form. It's almost as if the standard matrix should be a child of a Function matrix...where each of the functions is only a scaler.

Mull this over and let me know if you have any ideas on how this should be resolved.

markrogoyski commented 8 years ago

Rather than complicate regular matrices of numbers, it will probably be most straight forward to just override the methods in the child FunctionMatrix class where applicable.

Beakerboy commented 8 years ago

Maybe this, rather than complicate the "base" matrix class. There could be a MasterMatrix which contains descriptive functions, like isSquare(), and getRow(). The existing Matrix class could extend this and add numerical methods, like determinant(). The FunctionMatrix could also extend the MasterMatrix and add any of the functional methods. When the FunctionMatrix is evaluated, it would return a Matrix object.

The way things are designed currently, someone could run FunctionMatrix->inverse(), and I'm assuming all kinds of errors would be produced. In the proposed design, the inverse method wouldn't even be available until it's evaluated.

markrogoyski commented 8 years ago

The FunctionMatrix could just override the inverse method (and others) and define it like something like this:

public function inverse(): Matrix
{
    return $this->evaluate()->inverse();
}

The base Matrix interface is defined in the 'master' base Matrix class, and any child just overrides any calculation that is different, while maintaining the interface.

markrogoyski commented 8 years ago

Actually, that won't work as is because evaluate takes parameters.

markrogoyski commented 8 years ago

In the case of the FunctionMatrix inverse, since it needs to be evaluated first, it seems like there are two reasonable options: 1) It is on the user or calling class to know to evaluate it with parameters first, in which case, it will return a regular Matrix which normal functions like inverse will now work as expected.

$A⁻¹ = $A->evaluate(5)->inverse();

In this case, the FunctionMatrix would probably overload all those methods like inverse and just throw an exception, since the inverse would always happen on the regular matrix that is returned from evaluate.

2) Another way to do this would be for the parent Matrix class to define inverse like this:

public function inverse(...$params): Matrix

Even though it won't use the parameters, it then allows the inheriting FunctionMatrix to make use of those parameters to evaluate itself first to return a matrix where inverse does work:

public function inverse(...$params): Matrix
{
    return $this->evaluate($params)->inverse();
}

Option 1 seems like the way I'd want to go though. Thoughts?