首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >以紧凑的方式用软件表示数学树结构

以紧凑的方式用软件表示数学树结构
EN

Software Engineering用户
提问于 2019-10-23 12:57:32
回答 1查看 179关注 0票数 1

在我的工作中,我经常遇到相互依赖的方程组。我设计了一个玩具例子,如下所示。给出了终端值wxyz

e(y) = A+B

A(y) = x*log(y)+y^z

B(y) = alpha*y

alpha(y) = x*y+w

然后,我们可以将函数e(y)看作具有以下继承性的算术树的根:

以前,在python中,我会这样做来评估结果:

代码语言:javascript
运行
复制
import numpy as np

def root(B, A):
    return B+A

def A(x,y,z):
    return x*np.log(y)+y**z

def B(alpha, y):
    return alpha*y

def alpha(x,y,w):
    return x*y+w

if __name__=='__main__':

    x,y,z,w = 1,2,3,4
    result = root(B(alpha(x,y,w),y), A(x,y,z))

这会给我正确的结果,但我已经开始鄙视这种做事的方式了。它要求我跟踪每个函数需要哪些参数,以及树本身是如何构建的。另外,假设我想通过添加树枝和树叶来修改树本身。例如,假设我想用新变量alphav+x+y重新定义为v。我需要做一个新的函数和一个新的调用,这不是很有效率,因为我有时需要进行大量的普遍更改。

我尝试了不同的方法来解决这个问题,正如这个问题这个问题所概述的那样。

我偶然发现了几个看起来很有前途的想法,即功能对象解释器模式。然而,我对解释器的模式感到失望。假设我没有创建一个解析器,直接使用底层的复合体系结构,难道我还必须这样做吗?

代码语言:javascript
运行
复制
root = root_obj(B_obj(alpha_obj(x_obj,y_obj,w_obj),y_obj), A(x_obj,y_obj,z_obj))
root.interpret()

以上所述将需要大量增加的复杂性,而不需要任何附加价值。我的问题如下:什么是简单而有用的面向对象的范例,我可以用动态的方式来定义、修改和评估数学上的继承性?

编辑

下面是我想要达到的目标的一个例子:

代码语言:javascript
运行
复制
tree = FunctionTree()
tree.add_nodes(root, A, B, alpha, w, x, y, z)
tree.add_edge(root, [A, B])
tree.add_edge(root, A)
tree.add_edge(A, [x,y,z])
tree.add_edge(B, [alpha, y])
tree.add_edge(alpha, [x, y, w])
tree.evaluate()

是的,这不是那么“紧凑”,但它要灵活得多。具有删除和添加新边缘的方法的成像。替换节点上的定义并重新评估结果。我在找这样的东西。

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2019-10-23 18:59:19

这似乎是你上一个问题的延续。在本答复中提出的建议仍然有效。但也许我还不够清楚。

我不太懂python,但是:

  • 创建一个类AbstractExpression
  • 为您拥有的每个特定函数创建一个具体的专门化类:Function_eFunction_AFunction_BFunction_Alpha。这些类的实例将对应于您的橙色框。
  • 为终端表达式创建一个具体的类。将其称为Variable,并设想这个类的每个实例都有一个名称。这个类的实例将对应于您的绿色圆圈。
  • 为了清晰起见,让我们用一个函数eval(context)而不是interpret(context)来使用这个模式

现在到了我还不够清楚的地步:

  • 当然,Function_e的S构造函数会构造一个名为fAFunction_A实例和一个Function_B实例。这里绝对不需要解析!
  • 当然,Function_A会创建Variable实例,vy的名称为"y",vz的名称为"z“,vx的名称为"x”。同样,不需要解析:类构造函数构造所需的对象(编写代码)。
  • Function_e's eval()会做它需要做的事情,在公式中需要这个函数的结果时调用fA.eval()。我坚持:这里绝对不进行解析!调用实现A的方法是e的实现
  • fA.eval()的实现中,您将在公式中调用vy.eval()vz.eval()vx.eval(),其中需要每个变量。

现在,我们已经构建了一个与您的系统相对应的解释器(没有任何解析),如果只有Variable.eval()能够知道这些参数的值,那么它就能够计算结果。下面是context

  • context将是为变量名称分配固定值的字典。
  • context通过上面解释的所有eval()调用作为单个参数转发。
  • 最后一个需要的实现是用于eval()Variable。这将只返回与context字典中的变量名相关联的值。

如果我坚持没有语法分析,很抱歉。但是,许多网站提供了解释器模式的示例,而不了解实际的用例。所以它们都是关于解析的,这会造成很大的混乱。这里有一个完美的用法示例:-)

票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/400040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档