修改方程的ast.NodeTransformer示例
这是我上一个问题的延续。我想解析一个方程,并对得到的抽象语法树(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格式就更好了。请在你的代码中添加注释,并提供一个测试样例或单元测试。
2 个回答
你想做什么呢?寻找一个方程的正确排列可能看起来简单,但实际上可能会花费很多时间(因为有n!种可能性)。而用遗传算法生成新的排列并进行优化,我觉得几乎是不可能的,因为这并不是一个优化问题……举个例子,x^0.00和x^0.01是根本不同的。此外,你也不能优化出正确的运算符,这样是行不通的。抱歉。
不过,情况并没有那么糟糕。寻找正确的函数是一个非常常见的任务。我假设你不知道这个函数,但你知道一些测量得到的点(你本来就需要这些点来计算遗传算法中的适应度,对吧?)。现在你可以使用拉格朗日插值法来得到一个经过这些给定点的多项式。维基百科文章中间有两个很好的例子,而且拉格朗日法的实现相当简单(我想不到10行代码就能搞定)。另外,值得注意的是,你可以通过添加更多的参考点来提高多项式的准确性。
所以说,输入和输出都是Fortran代码吗?你想用任意的Fortran表达式或语句吗?(包括数组切片之类的?)Fortran是一种相对复杂的语言,理解它需要一个完整的解析器。
也许你想用一个可以直接处理Fortran的程序转换工具。这样的工具可以读取Fortran代码,构建一个抽象语法树(AST),让你用一组随机选择的转换来“随机化”它,然后再生成有效的Fortran代码。
我们的DMS软件重构工具包,配合它的Fortran前端,可以直接用于这个目的。
编辑于2011年8月26日:提问者确认他想要“演变”(转换)真实的Fortran代码。值得注意的是,构建一个真正的Fortran解析器(就像为其他真实语言构建解析器一样)是相当困难的;我们花了几个月的时间,而我们的工具在定义解析器方面真的很强(我们用DMS做过大约40种语言和各种方言)。如果他想继续自己的生活或实际任务,自己构建一个真正的Fortran解析器可能不是个好主意。
提问者可能可以将Fortran代码限制在一个非常小的子集内,然后为这个子集构建一个解析器。