gpt4 book ai didi

c# - 使用具有可分配 Func 委托(delegate)的对象的基于树的数学表达式

转载 作者:太空狗 更新时间:2023-10-30 01:06:31 24 4
gpt4 key购买 nike

我想在 C# 中实现一个具有类 Tree<E> 的通用树数据结构它引用了根 TreeNode<E>对象包含子链表和相同节点类型的单个父节点。这是一个基本的树结构,实现这部分我真的没有任何问题。

我想扩展这个树结构来创建Function , 它扩展了 Tree<double> ,连同它的恭维节点类型 Expression适本地扩展了TreeNode<double> .我想使用此结构来表示可以使用函数的适当变量进行评估的数学函数。

我目前正处于这个项目的设计阶段,所以有很多方法可以实现这个,但我正在寻找具有适当抽象级别的设计,以涵盖所有类型的功能,同时仍保持其参数签名密闭。例如,我应该能够创建一个 Function在数学函数的运行时:

f() = 42 , f(x) = x^2 , f(x, y) = x/y + 5

如果每个 Expression有自己的子列表(子表达式分解为给定参数定义函数的过程),然后 Expression应该使用某种评估方法,其中包含 double值并吐出它们的标量值(或者如果可能,将其提取到向量级别)。

我对像 LINQ 这样的函数式语言没有太多经验,但如果有人有经验,是否有一种简单而强大的方法来实现我计划使用它的东西?如果我不必为每一种基本操作(比如 SinExpression(X)AdditionExpression(X,Y) )创建具体的类,而是能够动态定义可能存储在字典,前提是所有变量要么是其他表达式,要么归结为浮点值。那时,如果我只需要在基本构造函数中定义评估函数,具体函数类可以扩展这些抽象类。

我还想指出,维护树结构很重要,因为我计划在一个单独的程序中使用这些表达式,该程序将直接更改函数的表达式树(更改节点、删除分支等)。

谁能指出我正确的方向?我将不胜感激。

最佳答案

已经有一个 API 将复杂的操作表示为节点树; LINQ 表达式 API。对于一个简单的示例,您可以让编译器为您构建树 - 例如:

Expression<Func<double,double,double>> f = (x,y) => Math.Sin(x/y) + 5;

这可用于通过调用 Compile()评估事物,即

var func = f.Compile(); // this is a Func<double,double,double>
Console.WriteLine(func(12,5));
Console.WriteLine(func(23,4));

但是表达式树比较复杂,可以任意检查。此外,您可以使用 ExpressionVisitor 来交换片段。例如,假设我们想将“x”替换为“ln(x)”作为随机基因突变的一部分:

// swap x for ln(x)
var munged = SwapExpressionVisitor.Swap(
f, // the lambda to rewrite
f.Parameters[0], // "x"
Expression.Call(typeof(Math), "Log", null, f.Parameters[0]) // ln(x)
); // (x, y) => (Sin((Log(x) / y)) + 5)

func = munged.Compile();
Console.WriteLine(func(12, 5));
Console.WriteLine(func(23, 4));

使用像这样的实用程序:

class SwapExpressionVisitor : ExpressionVisitor
{
public static Expression<T> Swap<T>(Expression<T> lambda,
Expression from, Expression to)
{
return Expression.Lambda<T>(
Swap(lambda.Body, from, to), lambda.Parameters);
}
public static Expression Swap(
Expression body, Expression from, Expression to)
{
return new SwapExpressionVisitor(from, to).Visit(body);
}
private readonly Expression from, to;
public SwapExpressionVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}

关于c# - 使用具有可分配 Func 委托(delegate)的对象的基于树的数学表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15291667/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com