UNPKG

herta

Version:

Advanced mathematics framework for scientific, engineering, and financial applications

262 lines (227 loc) 9.21 kB
/** * Symbolic mathematics module for herta.js * Provides methods for symbolic integration, differentiation, and equation solving */ const utils = require('../utils/utils'); // Symbolic mathematics module const symbolic = {}; /** * Represents a symbolic expression * @param {string} expr - The expression string * @returns {Object} - Symbolic expression object */ symbolic.expression = function (expr) { if (typeof expr !== 'string') { throw new Error('Expression must be a string'); } return { expr, /** * Convert the expression to a string * @returns {string} - String representation */ toString() { return this.expr; }, /** * Substitute a variable with a value or another expression * @param {string} variable - The variable to substitute * @param {string|number} value - The value or expression to substitute with * @returns {Object} - New symbolic expression */ substitute(variable, value) { // Simple substitution implementation // In a real implementation, this would use a proper parser const valueStr = typeof value === 'number' ? value.toString() : value; const pattern = new RegExp(`\\b${variable}\\b`, 'g'); const newExpr = this.expr.replace(pattern, `(${valueStr})`); return symbolic.expression(newExpr); }, /** * Add another expression to this one * @param {Object|string|number} other - The expression to add * @returns {Object} - New symbolic expression */ add(other) { const otherExpr = typeof other === 'object' ? other.expr : other.toString(); return symbolic.expression(`(${this.expr}) + (${otherExpr})`); }, /** * Subtract another expression from this one * @param {Object|string|number} other - The expression to subtract * @returns {Object} - New symbolic expression */ subtract(other) { const otherExpr = typeof other === 'object' ? other.expr : other.toString(); return symbolic.expression(`(${this.expr}) - (${otherExpr})`); }, /** * Multiply this expression by another * @param {Object|string|number} other - The expression to multiply by * @returns {Object} - New symbolic expression */ multiply(other) { const otherExpr = typeof other === 'object' ? other.expr : other.toString(); return symbolic.expression(`(${this.expr}) * (${otherExpr})`); }, /** * Divide this expression by another * @param {Object|string|number} other - The expression to divide by * @returns {Object} - New symbolic expression */ divide(other) { const otherExpr = typeof other === 'object' ? other.expr : other.toString(); return symbolic.expression(`(${this.expr}) / (${otherExpr})`); }, /** * Raise this expression to a power * @param {Object|string|number} power - The power to raise to * @returns {Object} - New symbolic expression */ pow(power) { const powerExpr = typeof power === 'object' ? power.expr : power.toString(); return symbolic.expression(`(${this.expr}) ^ (${powerExpr})`); }, /** * Differentiate the expression with respect to a variable * @param {string} variable - The variable to differentiate with respect to * @returns {Object} - New symbolic expression representing the derivative */ differentiate(variable) { return symbolic.differentiate(this.expr, variable); }, /** * Integrate the expression with respect to a variable * @param {string} variable - The variable to integrate with respect to * @returns {Object} - New symbolic expression representing the integral */ integrate(variable) { return symbolic.integrate(this.expr, variable); }, /** * Evaluate the expression by substituting all variables with values * @param {Object} scope - Object mapping variable names to values * @returns {number} - The evaluated result */ evaluate(scope = {}) { // This would use a proper expression evaluator // For now, we'll use a simple approach with Function constructor // Note: This is not safe for untrusted input try { const variables = Object.keys(scope); const values = variables.map((v) => scope[v]); const func = new Function(...variables, `return ${this.expr};`); return func(...values); } catch (error) { throw new Error(`Error evaluating expression: ${error.message}`); } } }; }; /** * Differentiate an expression symbolically * @param {string|Object} expr - The expression to differentiate * @param {string} variable - The variable to differentiate with respect to * @returns {Object} - Symbolic expression representing the derivative */ symbolic.differentiate = function (expr, variable) { const exprStr = typeof expr === 'object' ? expr.expr : expr.toString(); // This would implement symbolic differentiation rules // For now, we'll return a placeholder return symbolic.expression(`d/d${variable}(${exprStr})`); }; /** * Integrate an expression symbolically * @param {string|Object} expr - The expression to integrate * @param {string} variable - The variable to integrate with respect to * @returns {Object} - Symbolic expression representing the integral */ symbolic.integrate = function (expr, variable) { const exprStr = typeof expr === 'object' ? expr.expr : expr.toString(); // Parse the expression to identify its structure // This is a simplified implementation that handles basic cases // Check for simple power functions: x^n const powerMatch = exprStr.match(new RegExp(`\\b${variable}\\^(\\d+)\\b`)); if (powerMatch) { const power = parseInt(powerMatch[1]); const newPower = power + 1; const coefficient = 1 / newPower; return symbolic.expression(`${coefficient} * ${variable}^${newPower} + C`); } // Check for simple polynomial terms: a*x const linearMatch = exprStr.match(new RegExp(`(\\d*\.?\\d*)\\s*\\*?\\s*\\b${variable}\\b`)); if (linearMatch) { const coefficient = linearMatch[1] ? parseFloat(linearMatch[1]) : 1; return symbolic.expression(`${coefficient / 2} * ${variable}^2 + C`); } // Check for constants const constantMatch = exprStr.match(/^\s*(\d+\.?\d*)\s*$/); if (constantMatch) { const constant = parseFloat(constantMatch[1]); return symbolic.expression(`${constant} * ${variable} + C`); } // For more complex expressions, return a placeholder return symbolic.expression(`∫(${exprStr})d${variable}`); }; /** * Solve an equation symbolically * @param {string|Object} lhs - Left-hand side of the equation * @param {string|Object} rhs - Right-hand side of the equation * @param {string} variable - The variable to solve for * @returns {Array<Object>} - Array of symbolic expressions representing solutions */ symbolic.solve = function (lhs, rhs, variable) { const lhsExpr = typeof lhs === 'object' ? lhs.expr : lhs.toString(); const rhsExpr = typeof rhs === 'object' ? rhs.expr : rhs.toString(); // This would implement symbolic equation solving // For now, we'll return a placeholder return [symbolic.expression(`${variable} = solution(${lhsExpr} = ${rhsExpr})`)]; }; /** * Expand an expression (distribute multiplication over addition) * @param {string|Object} expr - The expression to expand * @returns {Object} - Expanded symbolic expression */ symbolic.expand = function (expr) { const exprStr = typeof expr === 'object' ? expr.expr : expr.toString(); // This would implement algebraic expansion // For now, we'll return a placeholder return symbolic.expression(`expand(${exprStr})`); }; /** * Factor an expression * @param {string|Object} expr - The expression to factor * @returns {Object} - Factored symbolic expression */ symbolic.factor = function (expr) { const exprStr = typeof expr === 'object' ? expr.expr : expr.toString(); // This would implement algebraic factorization // For now, we'll return a placeholder return symbolic.expression(`factor(${exprStr})`); }; /** * Simplify an expression * @param {string|Object} expr - The expression to simplify * @returns {Object} - Simplified symbolic expression */ symbolic.simplify = function (expr) { const exprStr = typeof expr === 'object' ? expr.expr : expr.toString(); // This would implement algebraic simplification rules // For now, we'll return a placeholder return symbolic.expression(`simplify(${exprStr})`); }; /** * Compute the limit of an expression as a variable approaches a value * @param {string|Object} expr - The expression * @param {string} variable - The variable * @param {number|string} value - The value the variable approaches * @returns {Object} - Symbolic expression representing the limit */ symbolic.limit = function (expr, variable, value) { const exprStr = typeof expr === 'object' ? expr.expr : expr.toString(); const valueStr = value.toString(); // This would implement limit calculation // For now, we'll return a placeholder return symbolic.expression(`limit(${exprStr}, ${variable} -> ${valueStr})`); }; module.exports = symbolic;