simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

symbolicEqual.js (3101B)


      1 import { isConstantNode } from '../../utils/is.js';
      2 import { factory } from '../../utils/factory.js';
      3 var name = 'symbolicEqual';
      4 var dependencies = ['parse', 'simplify', 'typed', 'OperatorNode'];
      5 export var createSymbolicEqual = /* #__PURE__ */factory(name, dependencies, _ref => {
      6   var {
      7     parse,
      8     simplify,
      9     typed,
     10     OperatorNode
     11   } = _ref;
     12 
     13   /**
     14    * Attempts to determine if two expressions are symbolically equal, i.e.
     15    * one is the result of valid algebraic manipulations on the other.
     16    * Currently, this simply checks if the difference of the two expressions
     17    * simplifies down to 0. So there are two important caveats:
     18    * 1. whether two expressions are symbolically equal depends on the
     19    *     manipulations allowed. Therefore, this function takes an optional
     20    *     third argument, which are the options that control the behavior
     21    *     as documented for the `simplify()` function.
     22    * 2. it is in general intractable to find the minimal simplification of
     23    *     an arbitrarily complicated expression. So while a `true` value
     24    *     of `symbolicEqual` ensures that the two expressions can be manipulated
     25    *     to match each other, a `false` value does not absolutely rule this out.
     26    *
     27    * Syntax:
     28    *
     29    *    symbolicEqual(expr1, expr2)
     30    *    symbolicEqual(expr1, expr2, options)
     31    *
     32    * Examples:
     33    *
     34    *    symbolicEqual('x*y', 'y*x') // true
     35    *    symbolicEqual('x*y', 'y*x', {context: {multiply: {commutative: false}}})
     36    *        //false
     37    *    symbolicEqual('x/y', '(y*x^(-1))^(-1)') // true
     38    *    symbolicEqual('abs(x)','x') // false
     39    *    symbolicEqual('abs(x)','x', simplify.positiveContext) // true
     40    *
     41    * See also:
     42    *
     43    *    simplify, evaluate
     44    *
     45    * @param {Node|string} expr1  The first expression to compare
     46    * @param {Node|string} expr2  The second expression to compare
     47    * @param {Object} [options] Optional option object, passed to simplify
     48    * @returns {boolean}
     49    *     Returns true if a valid manipulation making the expressions equal
     50    *     is found.
     51    */
     52   return typed(name, {
     53     'string, string': function stringString(s1, s2) {
     54       return this(parse(s1), parse(s2), {});
     55     },
     56     'string, string, Object': function stringStringObject(s1, s2, options) {
     57       return this(parse(s1), parse(s2), options);
     58     },
     59     'Node, string': function NodeString(e1, s2) {
     60       return this(e1, parse(s2), {});
     61     },
     62     'Node, string, Object': function NodeStringObject(e1, s2, options) {
     63       return this(e1, parse(s2), options);
     64     },
     65     'string, Node': function stringNode(s1, e2) {
     66       return this(parse(s1), e2, {});
     67     },
     68     'string, Node, Object': function stringNodeObject(s1, e2, options) {
     69       return this(parse(s1), e2, options);
     70     },
     71     'Node, Node': function NodeNode(e1, e2) {
     72       return this(e1, e2, {});
     73     },
     74     'Node, Node, Object': function NodeNodeObject(e1, e2, options) {
     75       var diff = new OperatorNode('-', 'subtract', [e1, e2]);
     76       var simplified = simplify(diff, {}, options);
     77       return isConstantNode(simplified) && !simplified.value;
     78     }
     79   });
     80 });