mathjs icon indicating copy to clipboard operation
mathjs copied to clipboard

Simplify not working with matrix multiplication?

Open filonik opened this issue 2 years ago • 3 comments

Shouldn't the following produce the same result?

import * as math from 'mathjs'

let scope = {
  A: math.matrix([
    [1, 2],
    [3, 4],
  ]),
  v: math.matrix([5, 6]),
}

const r0 = math.evaluate('A * v', scope)
console.log('Evaluate:', r0) // Evaluate: DenseMatrix {_data: [17, 39]}

//const A = new math.SymbolNode('A')
//const v = new math.SymbolNode('v')
//const expr = new math.OperatorNode('*', 'multiply', [A, v])
const expr = math.parse('A * v')

const r1 = math.simplify(expr, scope)
console.log('Simplify:', r1) // Simplify: ConstantNode {value: 0}

When I run the code, evaluate produces the expected output ([17, 39]), but simplify does not (it instead produces 0 which doesn't seem right).

filonik avatar Jul 01 '22 17:07 filonik

Thanks for reporting, that sounds like a bug, 0 is indeed a wrong result for that expression.

Anyone able to help debugging/fixing this issue in simplify? Help would be welcome.

josdejong avatar Jul 04 '22 08:07 josdejong

I took a look at this as it appears the issue still occurs. The reason for 0 being returned lies in the simplifyCore.js logic that executes as part of the simplification rule set:

https://github.com/josdejong/mathjs/blob/4a26b068d8803cfde6495552d1c8dc410e0cbe07/src/function/algebra/simplifyCore.js#L205-L223

In this logic, both the matrix nodes are considered ConstantNode and isZero is also truthy for the DenseMatrix node values. The reason isZero is truthy in this case is because the return for a matrix argument to isZero is itself a matrix of booleans resulting from an element wise execution of isZero. In this context, simplifyCore simplifies the whole expression to 0.

Skipping that one condition wouldn't be enough though. It seems that most the simplification rules are for use in a one-dimensional algebraic context in which there can be unknowns and are thus not needed for constant matrix simplification. Instead it seems to me that we would need a new, separate set of logic specifically for matrix simplification and evaluation.

soleilcot avatar Oct 18 '23 03:10 soleilcot

Thanks for debugging this @soleilcot , this makes sense indeed.

So as a first step we may need to add a check on whether the value we're operating on is a numeric value and not a Matrix or something else I think? Like adding a check isNumeric(a0).value?

josdejong avatar Oct 18 '23 09:10 josdejong