Skip to content

Commit

Permalink
Refactor/simplify core cleanup (#2490)
Browse files Browse the repository at this point in the history
* refactor: don't simplify constants in simplifyCore

  Keeps the operation of simplifyCore cleanly separate from
  simplifyConstant.

* fix; handle multiple consecutive operations in simplifyCore()

   Also adds support for logical operators.
   Resolves #2484.

* feat: export simplifyConstant

  Now that simplifyCore does not do any constant folding, clients may
  wish to access that behavior via simplifyConstant. Moreover, exporting it
  makes it easier to use in custom rule lists for simplify().

  Also adds docs, embedded docs, and tests for simplifyConstant().

  Also fixes simplifyCore() on logical functions (they always return boolean,
  rather than "short-circuiting").

  Resolves #2459.
  • Loading branch information
gwhitney committed Apr 13, 2022
1 parent b7d79e0 commit 851e900
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 139 deletions.
2 changes: 2 additions & 0 deletions src/expression/embeddedDocs/embeddedDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { qrDocs } from './function/algebra/qr.js'
import { rationalizeDocs } from './function/algebra/rationalize.js'
import { resolveDocs } from './function/algebra/resolve.js'
import { simplifyDocs } from './function/algebra/simplify.js'
import { simplifyConstantDocs } from './function/algebra/simplifyConstant.js'
import { simplifyCoreDocs } from './function/algebra/simplifyCore.js'
import { sluDocs } from './function/algebra/slu.js'
import { symbolicEqualDocs } from './function/algebra/symbolicEqual.js'
Expand Down Expand Up @@ -335,6 +336,7 @@ export const embeddedDocs = {
leafCount: leafCountDocs,
resolve: resolveDocs,
simplify: simplifyDocs,
simplifyConstant: simplifyConstantDocs,
simplifyCore: simplifyCoreDocs,
symbolicEqual: symbolicEqualDocs,
rationalize: rationalizeDocs,
Expand Down
16 changes: 16 additions & 0 deletions src/expression/embeddedDocs/function/algebra/simplifyConstant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const simplifyConstantDocs = {
name: 'simplifyConstant',
category: 'Algebra',
syntax: [
'simplifyConstant(expr)',
'simplifyConstant(expr, options)'
],
description: 'Replace constant subexpressions of node with their values.',
examples: [
'simplifyConatant("(3-3)*x")',
'simplifyConstant(parse("z-cos(tau/8)"))'
],
seealso: [
'simplify', 'simplifyCore', 'evaluate'
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export const simplifyCoreDocs = {
'simplifyCore(parse("(x+0)*2"))'
],
seealso: [
'simplify', 'evaluate'
'simplify', 'simplifyConstant', 'evaluate'
]
}
1 change: 1 addition & 0 deletions src/factoriesAny.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ export { createCatalan } from './function/combinatorics/catalan.js'
export { createComposition } from './function/combinatorics/composition.js'
export { createLeafCount } from './function/algebra/leafCount.js'
export { createSimplify } from './function/algebra/simplify.js'
export { createSimplifyConstant } from './function/algebra/simplifyConstant.js'
export { createSimplifyCore } from './function/algebra/simplifyCore.js'
export { createResolve } from './function/algebra/resolve.js'
export { createSymbolicEqual } from './function/algebra/symbolicEqual.js'
Expand Down
1 change: 1 addition & 0 deletions src/factoriesNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export { createChain } from './type/chain/function/chain.js'
// algebra
export { createResolve } from './function/algebra/resolve.js'
export { createSimplify } from './function/algebra/simplify.js'
export { createSimplifyConstant } from './function/algebra/simplifyConstant.js'
export { createSimplifyCore } from './function/algebra/simplifyCore.js'
export { createDerivative } from './function/algebra/derivative.js'
export { createRationalize } from './function/algebra/rationalize.js'
Expand Down
20 changes: 2 additions & 18 deletions src/function/algebra/rationalize.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { isInteger } from '../../utils/number.js'
import { factory } from '../../utils/factory.js'
import { createSimplifyConstant } from './simplify/simplifyConstant.js'

const name = 'rationalize'
const dependencies = [
Expand All @@ -14,6 +13,7 @@ const dependencies = [
'divide',
'pow',
'parse',
'simplifyConstant',
'simplifyCore',
'simplify',
'?bignumber',
Expand Down Expand Up @@ -42,6 +42,7 @@ export const createRationalize = /* #__PURE__ */ factory(name, dependencies, ({
divide,
pow,
parse,
simplifyConstant,
simplifyCore,
simplify,
fraction,
Expand All @@ -58,23 +59,6 @@ export const createRationalize = /* #__PURE__ */ factory(name, dependencies, ({
SymbolNode,
ParenthesisNode
}) => {
const simplifyConstant = createSimplifyConstant({
typed,
config,
mathWithTransform,
matrix,
fraction,
bignumber,
AccessorNode,
ArrayNode,
ConstantNode,
FunctionNode,
IndexNode,
ObjectNode,
OperatorNode,
SymbolNode
})

/**
* Transform a rationalizable expression in a rational fraction.
* If rational fraction is one variable polynomial then converts
Expand Down
20 changes: 2 additions & 18 deletions src/function/algebra/simplify.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { isConstantNode, isParenthesisNode } from '../../utils/is.js'
import { factory } from '../../utils/factory.js'
import { createUtil } from './simplify/util.js'
import { createSimplifyConstant } from './simplify/simplifyConstant.js'
import { hasOwnProperty } from '../../utils/object.js'
import { createEmptyMap, createMap } from '../../utils/map.js'

Expand All @@ -18,6 +17,7 @@ const dependencies = [
'isZero',
'equal',
'resolve',
'simplifyConstant',
'simplifyCore',
'?fraction',
'?bignumber',
Expand Down Expand Up @@ -47,6 +47,7 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
isZero,
equal,
resolve,
simplifyConstant,
simplifyCore,
fraction,
bignumber,
Expand All @@ -63,23 +64,6 @@ export const createSimplify = /* #__PURE__ */ factory(name, dependencies, (
SymbolNode
}
) => {
const simplifyConstant = createSimplifyConstant({
typed,
config,
mathWithTransform,
matrix,
fraction,
bignumber,
AccessorNode,
ArrayNode,
ConstantNode,
FunctionNode,
IndexNode,
ObjectNode,
OperatorNode,
SymbolNode
})

const { hasProperty, isCommutative, isAssociative, mergeContext, flatten, unflattenr, unflattenl, createMakeNodeFunction, defaultContext, realContext, positiveContext } =
createUtil({ FunctionNode, OperatorNode, SymbolNode })

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// TODO this could be improved by simplifying seperated constants under associative and commutative operators
import { isFraction, isMatrix, isNode, isArrayNode, isConstantNode, isIndexNode, isObjectNode, isOperatorNode } from '../../../utils/is.js'
import { factory } from '../../../utils/factory.js'
import { createUtil } from './util.js'
import { noBignumber, noFraction } from '../../../utils/noop.js'
import { isFraction, isMatrix, isNode, isArrayNode, isConstantNode, isIndexNode, isObjectNode, isOperatorNode } from '../../utils/is.js'
import { factory } from '../../utils/factory.js'
import { createUtil } from './simplify/util.js'
import { noBignumber, noFraction } from '../../utils/noop.js'

const name = 'simplifyConstant'
const dependencies = [
'typed',
'parse',
'config',
'mathWithTransform',
'matrix',
Expand All @@ -24,6 +24,7 @@ const dependencies = [

export const createSimplifyConstant = /* #__PURE__ */ factory(name, dependencies, ({
typed,
parse,
config,
mathWithTransform,
matrix,
Expand All @@ -41,9 +42,50 @@ export const createSimplifyConstant = /* #__PURE__ */ factory(name, dependencies
const { isCommutative, isAssociative, allChildren, createMakeNodeFunction } =
createUtil({ FunctionNode, OperatorNode, SymbolNode })

function simplifyConstant (expr, options) {
return _ensureNode(foldFraction(expr, options))
}
/**
* simplifyConstant() takes a mathjs expression (either a Node representing
* a parse tree or a string which it parses to produce a node), and replaces
* any subexpression of it consisting entirely of constants with the computed
* value of that subexpression.
*
* Syntax:
*
* simplifyConstant(expr)
* simplifyConstant(expr, options)
*
* Examples:
*
* math.simplifyConstant('x + 4*3/6') // Node "x + 2"
* math.simplifyConstant('z cos(0)') // Node "z 1"
* math.simplifyConstant('(5.2 + 1.08)t', {exactFractions: false}) // Node "6.28 t"
*
* See also:
*
* simplify, simplifyCore, resolve, derivative
*
* @param {Node | string} node
* The expression to be simplified
* @param {Object} options
* Simplification options, as per simplify()
* @return {Node} Returns expression with constant subexpressions evaluated
*/
const simplifyConstant = typed('simplifyConstant', {
string: function (expr) {
return this(parse(expr), {})
},

'string, Object': function (expr, options) {
return this(parse(expr), options)
},

Node: function (node) {
return this(node, {})
},

'Node, Object': function (expr, options) {
return _ensureNode(foldFraction(expr, options))
}
})

function _removeFractions (thing) {
if (isFraction(thing)) {
Expand Down

0 comments on commit 851e900

Please sign in to comment.