/// <summary>Метод определения значения</summary> /// <returns>Численное значение элемента выражения</returns> public override double GetValue(MathExpression ParametersExpression, MathExpression Function) { var x = ParametersExpression.Variable[0]; var x_node = ParametersExpression.Tree .OfType <VariableValueNode>() .First(n => ReferenceEquals(x, n.Variable)); var interval = (IntervalNode)x_node.Parent.Right ?? throw new InvalidOperationException("Правый узел дерева не определён - невозможно рассчитать интервал значений интегрирования"); var min_node = (ComputedNode)interval.Left ?? throw new InvalidOperationException("В левом поддереве интервала значений отсутствует элемент - невозможно определить минимальное значение интервала"); var max_node = (ComputedNode)interval.Right ?? throw new InvalidOperationException("В правом поддереве интервала значений отсутствует элемент - невозможно определить максимальное значение интервала");; var min = min_node.Compute(); var max = max_node.Compute(); Func <double, double> f = xx => { x.Value = xx; return(Function.Compute()); }; if (_IsAdaptive) { return(f.GetIntegralValue_Adaptive(min, max)); } var dx = ParametersExpression.Variable[$"d{x_node.Variable.Name}"]; var dx_node = ParametersExpression.Tree .OfType <VariableValueNode>() .First(n => ReferenceEquals(dx, n.Variable)); var dx_value_node = (ConstValueNode)dx_node.Parent.Right ?? throw new InvalidOperationException("Отсутствует правое поддерево у родительского элемента dx - невозможно рассчитать шаг интегрирования"); dx.Value = dx_value_node.Value; return(f.GetIntegralValue(min, max, dx.GetValue())); }
/// <summary>Метод определения значения</summary> /// <returns>Численное значение элемента выражения</returns> public override double GetValue(MathExpression ParametersExpression, MathExpression Function) { var parameters_root = ParametersExpression.Tree.Root; var iterator = ((VariableValueNode)parameters_root.Left)?.Variable ?? throw new InvalidOperationException("Не определён узел дерева с итератором суммы"); var interval = (IntervalNode)parameters_root.Right ?? throw new InvalidOperationException("Не определён узел дерева с интервалом значений суммы"); var min_node = (ComputedNode)interval.Min ?? throw new InvalidOperationException("Не определён узел дерева с минимальным значением интервала суммы"); var max_node = (ComputedNode)interval.Max ?? throw new InvalidOperationException("Не определён узел дерева с максимальным значением интервала суммы");; var min = min_node.Compute(); var max = max_node.Compute(); var sum = 0.0; if (min < max) { for (int i = (int)min, Max = (int)max; i < Max; i++) { iterator.Value = i; sum += Function.Compute(); } } else { for (int i = (int)min, Min = (int)max - 1; i >= Min; i--) { iterator.Value = i; sum += Function.Compute(); } } return(sum); }
/// <summary>Инициализация оператора</summary> /// <param name="Parameters">Блок параметров</param> /// <param name="Function">Блок ядра функции</param> /// <param name="Parser">Парсер</param> /// <param name="Expression">Внешнее выражение</param> public override void Initialize ( MathExpression Parameters, MathExpression Function, ExpressionParser Parser, MathExpression Expression ) { base.Initialize(Parameters, Function, Parser, Expression); var iterator_var = Parameters.Tree .OfType <VariableValueNode>() .Where(n => n.Parent is EqualityOperatorNode) .Select(n => n.Variable) .FirstOrDefault(); if (iterator_var is null) { throw new FormatException(); } var iterator_var_name = iterator_var.Name; var iterator_node = Parameters.Tree .OfType <VariableValueNode>() .FirstOrDefault(n => n.Parent is EqualityOperatorNode && n.Variable.Name == $"d{iterator_var_name}"); var iterator_diff_var = iterator_node?.Variable; _IsAdaptive = iterator_diff_var is null; Function.Variable.ClearCollection(); Function.Variable.Add(iterator_var); Function.Tree .OfType <VariableValueNode>() .Where(n => !ReferenceEquals(n.Variable, iterator_var)) .Foreach(Function, Expression, (n, func, expr) => func.Variable.Add(n.Variable = expr.Variable[n.Variable.Name])); Parameters.Variable.ClearCollection(); Parameters.Variable.Add(iterator_var); if (!_IsAdaptive) { Debug.Assert(iterator_diff_var != null, "iterator_diff_var != null"); Parameters.Variable.Add(iterator_diff_var); if (iterator_node.Parent.Parent.IsLeftSubtree) { iterator_node.Parent.Parent.Parent.Left = null; } else { iterator_node.Parent.Parent.Parent.Right = null; } iterator_node.Parent.Parent = null; Parameters.Tree.Root = new FunctionArgumentNode("Domain", Parameters.Tree.Root) { Right = new FunctionArgumentNode("step", iterator_node.Parent) }; } Parameters.Tree .OfType <VariableValueNode>() .Where(n => !ReferenceEquals(n.Variable, iterator_var) && !ReferenceEquals(n.Variable, iterator_diff_var)) .Foreach(Parameters, Expression, (n, pp, expr) => pp.Variable.Add(n.Variable = expr.Variable[n.Variable.Name])); }
/// <summary>Скомпилировать в выражение</summary> /// <param name="Function">Ядро функции</param> /// <param name="Parameters">Массив параметров</param> /// <param name="ParametersExpression">Выражение параметров</param> /// <returns>Скомпилированное выражение System.Linq.Expressions</returns> public override Expression Compile(MathExpression ParametersExpression, MathExpression Function, ParameterExpression[] Parameters) { var parameters_root = ParametersExpression.Tree.Root; var iterator = ((VariableValueNode)parameters_root.Left)?.Variable ?? throw new InvalidOperationException("Не определён узел дерева с итератором суммы"); var interval_node = parameters_root.Right ?? throw new InvalidOperationException("Не определён узел дерева с интервалом суммы"); var min_node = (ComputedNode)interval_node.Left ?? throw new InvalidOperationException("Не определён узел дерева с минимумом интервала суммы"); var max_node = (ComputedNode)interval_node.Right ?? throw new InvalidOperationException("Не определён узел дерева с минимумом интервала суммы"); var min = min_node.Compile(); var max = max_node.Compile(); var iterator_parameter = Expression.Parameter(typeof(double), iterator.Name); var parameters = Parameters.AppendFirst(iterator_parameter).ToArray(); var body = ((ComputedNode)Function.Tree.Root).Compile(parameters); var expr = Expression.Lambda(body, parameters).Compile(); var expr_p = new[] { Expression.Constant(expr), min, max, Expression.NewArrayInit(typeof(double), Parameters.Cast <Expression>().ToArray()) }; return(Expression.Call(new SumDelegate(GetSum).Method, expr_p)); }
/// <summary>Инициализация оператора</summary> /// <param name="Parameters">Блок параметров</param> /// <param name="Function">Блок ядра функции</param> /// <param name="Parser">Парсер мат.выражения</param> /// <param name="Expression">Внешнее мат.выражение</param> public virtual void Initialize ( [NotNull] MathExpression Parameters, [NotNull] MathExpression Function, [NotNull] ExpressionParser Parser, [NotNull] MathExpression Expression ) { }
/// <summary>Инициализация оператора</summary> /// <param name="Parameters">Блок параметров</param> /// <param name="Function">Блок ядра функции</param> /// <param name="Parser">Парсер мат.выражения</param> /// <param name="Expression">Внешнее мат.выражение</param> public override void Initialize ( MathExpression Parameters, MathExpression Function, ExpressionParser Parser, MathExpression Expression ) { base.Initialize(Parameters, Function, Parser, Expression); var iterator_var = Parameters.Tree .Where(n => n is VariableValueNode && n.Parent is EqualityOperatorNode) .Select(n => ((VariableValueNode)n).Variable) .FirstOrDefault(); Function.Variable.ClearCollection(); if (iterator_var != null) { Function.Variable.Add(iterator_var); } var iterator_variables = Function.Tree .OfType <VariableValueNode>() .Where(n => !ReferenceEquals(n.Variable, iterator_var)); foreach (var n in iterator_variables) { Function.Variable.Add(n.Variable = Expression.Variable[n.Variable.Name]); } //Function.Tree // .Where(n => n is VariableValueNode) // .Cast<VariableValueNode>() // .Where(n => !ReferenceEquals(n.Variable, iterator_var)) // .Foreach(Expression, Function, (n, i, expr, f) => f.Variable.Add(n.Variable = expr.Variable[n.Variable.Name])); Parameters.Variable.ClearCollection(); var variable_nodes = Parameters.Tree .OfType <VariableValueNode>() .Where(n => !ReferenceEquals(n.Variable, iterator_var)); foreach (var variable_node in variable_nodes) { var variable = Expression.Variable[variable_node.Variable.Name]; variable_node.Variable = variable; Parameters.Variable.Add(variable); } //Parameters.Tree // .Where(n => n is VariableValueNode) // .Cast<VariableValueNode>() // .Where(n => !ReferenceEquals(n.Variable, iterator_var)) // .Foreach(Expression, Function, (n, i, expr, f) => f.Variable.Add(n.Variable = expr.Variable[n.Variable.Name])); }
/// <summary>Скомпилировать в выражение</summary> /// <param name="Function">Ядро функции</param> /// <param name="Parameters">Массив параметров</param> /// <param name="ParametersExpression">Выражение параметров</param> /// <returns>Скомпилированное выражение <see cref="System.Linq.Expressions"/></returns> public override Expression Compile ( MathExpression ParametersExpression, MathExpression Function, ParameterExpression[] Parameters ) { var iterator = ParametersExpression.Variable[0]; var x_node = ParametersExpression.Tree .Where(n => n is VariableValueNode) .Cast <VariableValueNode>() .First(n => ReferenceEquals(iterator, n.Variable)); var interval = (IntervalNode)x_node.Parent.Right ?? throw new InvalidOperationException("Отсутствует правое поддерево у родительского узла"); var interval_left = (ComputedNode)interval.Left ?? throw new InvalidOperationException("Отсутствует левое поддерево"); var interval_right = (ComputedNode)interval.Right ?? throw new InvalidOperationException("Отсутствует правое поддерево"); var min = interval_left.Compile(); var max = interval_right.Compile(); var iterator_parameter = Expression.Parameter(typeof(double), iterator.Name); var parameters = new[] { iterator_parameter }; var body = ((ComputedNode)Function.Tree.Root).Compile(parameters); var function = Expression.Lambda(body, parameters).Compile(); if (_IsAdaptive) { return(Expression.Call(new AdaptiveIntegralDelegate(GetAdaptiveIntegral).Method, new[] { function.ToExpression(), min, max, Expression.NewArrayInit(typeof(double)) })); } var dx_var = ParametersExpression.Variable[1]; var dx_node = ParametersExpression.Tree .Where(n => n is VariableValueNode) .Cast <VariableValueNode>() .First(n => ReferenceEquals(dx_var, n.Variable)); var dx = dx_node.Compile(); return(Expression.Call(new IntegralDelegate(GetIntegral).Method, new[] { function.ToExpression(), min, max, Expression.NewArrayInit(typeof(double), Parameters.Cast <Expression>().ToArray()), dx })); }
/// <summary>Получить корень поддерева выражений</summary> /// <param name="Parser">Парсер выражения</param> /// <param name="Expression">Математическое выражение</param> /// <returns>Корень поддерева</returns> public override ExpressionTreeNode GetSubTree(ExpressionParser Parser, MathExpression Expression) { var separator = Parser.ExpressionSeparator; // фиксируем символ-разделитель выражений // Разбиваем последовательность элементов выражения на группы, разделённые символом-разделителем // Извлекаем из каждой группы корень дерева выражений и складываем их в массив var roots = Terms .Split(t => t is CharTerm term && term.Value == separator) .Select(g => Parser.GetRoot(g, Expression)).ToArray(); if (roots.Length == 1) { return(roots[0]); // Если найден только один корень, то возвращаем его } // Иначе корней найдено много ExpressionTreeNode argument = null; // объявляем ссылку на аргумент // проходим по всем найденным корням foreach (var root in roots) { var arg = root switch { FunctionArgumentNode => root, FunctionArgumentNameNode name_node => new FunctionArgumentNode(name_node), VariantOperatorNode when root.Left is VariableValueNode value_node => new FunctionArgumentNode(value_node.Name, root.Right), _ => new FunctionArgumentNode(string.Empty, root) }; argument = argument is null ? arg // Если аргумент не был указан, то сохраняем полученный узел, как аргумент : argument.Right = arg; // сохраняем полученный узел в правое поддерево аргумента } // Если аргумент не был выделен, то что-то пошло не так - ошибка формата if (argument is null) { throw new FormatException("Не определён аргумент функции"); } return(argument.Root); // Вернуть корень аргумента } }
/// <summary>Получить поддерево</summary> /// <param name="Parser">Парсер мат.выражения</param> /// <param name="Expression">Математическое выражение</param> /// <returns>Результат вызова метода Parser.GetOperatorNode(Value)</returns> public override ExpressionTreeNode GetSubTree(ExpressionParser Parser, MathExpression Expression) => Parser.GetOperatorNode(Value);
public abstract Expression Compile ( [NotNull] MathExpression ParametersExpression, [NotNull] MathExpression Function, [NotNull] ParameterExpression[] Parameters );
/// <summary>Метод определения значения</summary> /// <param name="ParametersExpression">Выражение параметров</param> /// <param name="Function">Ядро функционала</param> /// <returns>Численное значение вычисленного выражения</returns> public abstract double GetValue([NotNull] MathExpression ParametersExpression, [NotNull] MathExpression Function);
/// <summary>Поддерево элемента, состоящее из узла-переменной</summary> /// <param name="Parser">Парсер</param> /// <param name="Expression">Математическое выражение</param> /// <returns>Узел дерева с переменной, полученной из Expression.Variable[Name]</returns> public override ExpressionTreeNode GetSubTree(ExpressionParser Parser, MathExpression Expression) => new VariableValueNode(Expression.Variable[Name]);
/// <inheritdoc /> public override Expression Compile(MathExpression ParametersExpression, MathExpression Function, ParameterExpression[] Parameters) => throw new NotImplementedException();
/// <inheritdoc /> public override double GetValue(MathExpression ParametersExpression, MathExpression Function) => throw new NotImplementedException();