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