在我的工作中,我经常遇到相互依赖的方程组。我设计了一个玩具例子,如下所示。给出了终端值w
、x
、y
和z
:
e(y) = A+B
A(y) = x*log(y)+y^z
B(y) = alpha*y
alpha(y) = x*y+w
然后,我们可以将函数e(y)
看作具有以下继承性的算术树的根:
以前,在python中,我会这样做来评估结果:
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))
这会给我正确的结果,但我已经开始鄙视这种做事的方式了。它要求我跟踪每个函数需要哪些参数,以及树本身是如何构建的。另外,假设我想通过添加树枝和树叶来修改树本身。例如,假设我想用新变量alpha
将v+x+y
重新定义为v
。我需要做一个新的函数和一个新的调用,这不是很有效率,因为我有时需要进行大量的普遍更改。
我尝试了不同的方法来解决这个问题,正如这个问题和这个问题所概述的那样。
我偶然发现了几个看起来很有前途的想法,即功能对象和解释器模式。然而,我对解释器的模式感到失望。假设我没有创建一个解析器,直接使用底层的复合体系结构,难道我还必须这样做吗?
root = root_obj(B_obj(alpha_obj(x_obj,y_obj,w_obj),y_obj), A(x_obj,y_obj,z_obj))
root.interpret()
以上所述将需要大量增加的复杂性,而不需要任何附加价值。我的问题如下:什么是简单而有用的面向对象的范例,我可以用动态的方式来定义、修改和评估数学上的继承性?
下面是我想要达到的目标的一个例子:
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()
是的,这不是那么“紧凑”,但它要灵活得多。具有删除和添加新边缘的方法的成像。替换节点上的定义并重新评估结果。我在找这样的东西。
发布于 2019-10-23 10:59:19
这似乎是你上一个问题的延续。在本答复中提出的建议仍然有效。但也许我还不够清楚。
我不太懂python,但是:
AbstractExpression
。Function_e
、Function_A
、Function_B
、Function_Alpha
。这些类的实例将对应于您的橙色框。Variable
,并设想这个类的每个实例都有一个名称。这个类的实例将对应于您的绿色圆圈。eval(context)
而不是interpret(context)
来使用这个模式现在到了我还不够清楚的地步:
Function_e
的S构造函数会构造一个名为fA
的Function_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
字典中的变量名相关联的值。如果我坚持没有语法分析,很抱歉。但是,许多网站提供了解释器模式的示例,而不了解实际的用例。所以它们都是关于解析的,这会造成很大的混乱。这里有一个完美的用法示例:-)
https://softwareengineering.stackexchange.com/questions/400040
复制相似问题