ast.NodeTransformer的示例,用于修改等式

19
这是我上一个问题的延续。我想解析一个方程并处理得到的ast。我的目的是随机打乱它,以获得一个新的方程,该方程也必须是有效的函数。这将用于遗传算法。
以下是我的起点:
class Py2do(ast.NodeTransformer):
def __init__(self):
  self.tree=[]
def generic_visit(self, node):
    print type(node).__name__
    self.tree.append(type(node).__name__)
    ast.NodeVisitor.generic_visit(self, node)
    depth=3
    s = node.__dict__.items()
    s = "    ".join("%s %r" % x for x in sorted(node.__dict__.items()))
    print( "%s%s\t%s" % (depth, str(type(node)), s) )
    for x in ast.iter_child_nodes(node):
      print (x, depth)

def visit_Name(self, node):
    # print 'Name :', node.id
    pass

def visit_Num(self, node):
    print 'Num :', node.__dict__['n']

def visit_Str(self, node):
    print "Str :", node.s

def visit_Print(self, node):
    print "Print :"
    ast.NodeVisitor.generic_visit(self, node)

def visit_Assign(self, node):
    print "Assign :"
    ast.NodeVisitor.generic_visit(self, node)

def visit_Expr(self, node):
    print "Expr :"
    ast.NodeVisitor.generic_visit(self, node)





if __name__ == '__main__':
    node = ast.parse("res= e**(((-0.5*one)*((delta_w*one/delta*one)**2)))")
    import ast_pretty
    print ast.dump(node)
    pprintAst(node)
    v = Py2do()
    v.visit(node)
    print v.tree

我想得到的是这样的结果:

res= e**(delta*((one/delta_w*one)**2)))

或者其他有效的随机方程。这将用于Fortran程序,因此如果生成的方程也能转换为Fortran,则更好。请注释您的代码并提供一个测试样例/单元测试。


我认为你应该用它们的正确类型标记表达式节点,例如关联、二元、一元等。然后,你可以根据运算符的类型来混淆树以保持连贯性。 - Chiguireitor
访问树的节点并不那么容易。如果我有这个能力,那将是一个重大的进步。 - tarrasch
但是你已经在那里使用了“访问者”模式...你可以克隆树,然后相应地进行变异。 - Chiguireitor
好的,这意味着需要设置一个次要数据结构,然后进行变异。我认为这不是很难。但是回转换怎么办?最终我需要一个有效的表达式... - tarrasch
你只需要按深度优先顺序遍历生成的树;在叶子节点上打印值/变量;当从二元操作符的叶子节点返回时,在每个兄弟节点之间放置运算符;当从节点返回到组合操作符(括号)时,将表达式包裹在其中。类似于Lambda演算的工作方式 ;) - Chiguireitor
显示剩余2条评论
2个回答

1

所以输入和输出是Fortran代码?您想使用任意的Fortran表达式/语句吗?(包括数组切片等?)Fortran是一种相当复杂的语言;阅读它需要几乎完整的解析器。

也许您想使用一个可以直接操作Fortran的程序转换工具。这样的工具将读取Fortran代码,构建AST,让您使用一组随机选择的转换“随机化”它,然后重新生成有效的Fortran代码。

我们的DMS软件重构工具包及其Fortran前端可直接用于此。

编辑于2011年8月26日:楼主确认他想要“演变”(转换)真正的Fortran代码。值得注意的是,构建一个真正的Fortran解析器(就像为任何其他真实语言构建解析器一样)非常困难;我们花了数月时间,而我们的工具在定义解析器方面非常出色(我们使用DMS完成了大约40种语言和各种方言)。如果他想继续生活或完成实际任务,他可能不应该建立自己的真正的Fortran解析器。

对于楼主来说,将Fortran代码限制为非常受限的子集,并为其构建解析器可能是可行的。


实际上,是的,那就是我最终想要做的。但首先我只是在努力转换表达式。有没有测试你的软件的方法? - tarrasch
DMS的前端可以解析完整的f77/f95并进行转换。但是DMS非常复杂(因为操作代码非常复杂),需要一些学习的努力。因此,我们不提供仅下载和试用的版本,因为那些认为他们会在一个下午取得巨大进展的人通常会感到失望。他们在一个月或两个月内所能做到的可能非常壮观。通常,我们会经过一系列建立信心的步骤,以说服双方进行更长时间的实验。第一步是直接与您进行讨论;我建议您通过我们的网站与我们联系。 - Ira Baxter

-1
你想做什么?寻找方程的正确排列可能很容易但是耗时(n!种可能性),但使用遗传算法生成并优化新方程是不可能的,因为这不是一个优化问题...例如x^0.00和x^0.01是根本不同的。而且,您无法为正确的运算符进行优化,那样行不通。抱歉。
虽然情况并不那么糟糕。寻找正确的函数是一项极其常见的任务。我现在假设您不知道该函数,但是您知道来自测量的几个点(您需要这些来计算遗传算法中的适应度,不是吗?)。您现在可以使用Lagrange得到通过这些给定点的多项式。维基百科文章中有两个很好的例子,而拉格朗日方法非常容易实现(我猜不到10行代码)。此外,请注意您可以通过添加更多的参考点来提高多项式的精度。

我认为他是在要求根据输入生成方程,然后将这些方程输入到一个独立/已经完成的遗传算法系统中。 - Colin Valliant
实际上,我想生成随机方程,只是有效的代码。我知道方程应该长什么样子,并希望算法在我已有的遗传框架内尝试很多可能性。 - tarrasch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接