import numpy as np from random import randint def generate_function(X,Y, voc, max_try=1000000, max_chars=10): ''' find the analytic form that describes Y on X ''' tries = [] for n in xrange(max_try): ## make some random function using the vocabulary thefunc = "".join([voc[randint(0,len(voc)-1)] for x in range(randint(1,max_chars))]) ## construct the python statement, declaring the lambda function and evaluating it on X mylam = "y = lambda x: " + thefunc + "\n" mylam += "rez = y(X)" try: ## this may be volitile so be warned! ## Couch everything in error statements, and ## simply throw away functions that aren't reasonable exec(mylam) except: continue try: tries.append( ( (abs(rez - Y).sum()) ,thefunc)) if (abs(rez - Y)).sum() < 0.0001: ## we got something really close break except: pass del rez del y ### numpy arrays handle NaN and INF gracefully, so we put ### answer into an array before sorting a = np.array(tries,dtype=[('rez','f'),("func",'|S10')]) a.sort() if a[0]["rez"] < 0.001: print "took us ntries = {0}, but we eventually found that '{1}' is functionally equivalent to f(X)".format(n,a[0]["func"]) else: print "after ntries = {0}, we found that '{1}' is close to f(x) (metric = {2})".format(n,a[0]["func"],a[0]["rez"]) return a[0] voc = ["x","x"," ","+","-","*","/","1","2","3"] x_array = np.arange(-3,3,0.4) real_function = x_array**2 + x_array generate_function(x_array, real_function, voc, 100)