'use strict'; function factory (type, config, load, typed) { var parse = load(require('../../expression/parse')); var ConstantNode = load(require('../../expression/node/ConstantNode')); var FunctionNode = load(require('../../expression/node/FunctionNode')); var OperatorNode = load(require('../../expression/node/OperatorNode')); var ParenthesisNode = load(require('../../expression/node/ParenthesisNode')); var SymbolNode = load(require('../../expression/node/SymbolNode')); /** * Returns a simplified expression tree. * * For more details on the theory: * http://stackoverflow.com/questions/7540227/strategies-for-simplifying-math-expressions * https://en.wikipedia.org/wiki/Symbolic_computation#Simplification * * Syntax: * * simplify(expr) * * Usage: * * math.eval('simplify(2 * 1 * x ^ (2 - 1))') * * @param {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} expr * @return {ConstantNode | SymbolNode | ParenthesisNode | FunctionNode | OperatorNode} The simplified form of `expr` */ var simplify = typed('simplify', { 'Node': function (expr) { var res = removeParens(expr); var after = 'foo'; var before = 'bar'; while(before != after) { var before = after; res = _simplify(res); var after = res.toString({paranthesis: 'all'}); } console.log("Returning " + after + " from simplify"); return res; } }); function removeParens(node) { return node.transform(function(node, path, parent) { if(node.isParenthesisNode) { return node.content; } else { return node; } }); } // Array of rules to be used to simplify expressions var ruleSet = []; // Array of strings, used to build the ruleSet. // Each l (left side) and r (right side) are parsed by // the expression parser into a node tree. // Left hand sides are matched to subtrees within the // expression to be parsed and replaced with the right // hand side. // TODO: Add support for constraints on constants (either in the form of a '=' expression or a callback [callback allows things like comparing symbols alphabetically]) // To evaluate lhs constants for rhs constants, use: { l: "c1+c2", r: "c3", evaluate: "c3 = c1 + c2" }. Multiple assignments are separated by ';' in block format. var rules = [ { l: "v*c", r: "c*v" }, { l: "0*n", r: "0" }, { l: "c1+c2", r: "c3", evaluate: "c3 = c1 + c2" }, { l: "c1-c2", r: "c3", evaluate: "c3 = c1 - c2" }, { l: "c1*c2", r: "c3", evaluate: "c3 = c1 * c2" }, { l: "n^1", r: "n"}, { l: "c1*(c2*n3)", r: "(c1*c2)*n3" }, { l: "(c1*n2)*n3", r: "c1*(n2*n3)" }, { l: "1*n", r: "n" }, { l: "n/n", r: "1" }, { l: "n+n", r: "2*n" }, { l: "n*n", r: "n^2" }, { l: "n1*n2 + n2", r: "(n1+1)*n2" }, { l: "n^n1 * n^n2", r: "n^(n1+n2)" }, { l: "n^n1 * n", r: "n^(n1+1)" }, { l: "n * n^n1", r: "n^(n1+1)" }, ]; /** * Parse the string array of rules into nodes * * Example syntax for rules: * * Position constants to the left in a product: * { l: "n1 * c1", r: "c1 * n1" } * n1 is any Node, and c1 is a ConstantNode. * * Apply difference of squares formula: * { l: "(n1 - n2) * (n1 + n2)", r: "n1^2 - n2^2" } * n1, n2 mean any Node. */ function _buildRules() { for(var i=0; i