version 2.0

pull/13/head
kstaats 2018-04-12 16:50:23 -07:00
parent 29d4bf227d
commit 98cf28a2f5
5 changed files with 347 additions and 404 deletions

View File

@ -1,3 +1,36 @@
2018 04/12
1) Merged 'Karoo GP Server' and 'Karoo GP Main' into a single 'Karoo GP'. So, just one user script now that provides the
user interface (TUI) or scripting (comnand line). There are now 3 ways to run Karoo:
a) $ run karoo_gp.py
b) $ run karoo_gp.py [path/][dataset.csv]
c) $ run karoo_gp.py -fil [path/][dataset.csv] -[arg] [val] -[arg] [val] ... etc.
Where [arg][val] are the sysargs defined in the body of karoo_gp.py and the User Guide. Both (a) and (b) will auto-
run the Desktop interface, providing a user query for each entry and holding the user within the script until quit;
(c) will skip the user query and go directly into execution, dropping the user back to the command line at the end of
the run (for scripting).
2) Merged the 'menu' ranges into the while loops, directly (to reduce line count).
3) Added the 2**(tree_depth_base +1) - 1 to the tree_depth_min calculation (could have done this a long time ago).
4) Auto-calc the number of trees entered into the Tournament (was previously hard coded to 7 assuming a pop 100).
5) Added [-evr, -evp, -evb, -evc] to the sysargs to support a change in the balance of the genetic operators mid-run.
6) Merged fx_evolve_branch_top_copy with fx_evolve_branch_body_copy as they were alway called sequencially and required
the same input values.
7) Merged fx_evolve_tree_renum into fx_eval_generation as both are used only once, as the former was but 2 lines of code.
8) Finally finished commenting all "Called by: ___" statements in each function header.
I've been productive!
2018 04/01
Two major updates, as follows:

246
karoo_gp.py 100644
View File

@ -0,0 +1,246 @@
# Karoo GP (desktop + server combined)
# Use Genetic Programming for Classification and Symbolic Regression
# by Kai Staats, MSc; see LICENSE.md
# version 2.0
'''
A word to the newbie, expert, and brave--
Even if you are highly experienced in Genetic Programming, it is recommended that you review the 'Karoo User Guide'
before running this application. While your computer will not burst into flames nor will the sun collapse into a black
hole if you do not, you will likely find more enjoyment of this particular flavour of GP with a little understanding
of its intent and design.
Without any arguments, Karoo GP relies entirely upon the scripted settings and the datasets located in karoo_gp/files/.
$ python karoo_gp_main.py
(or from iPython)
$ run karoo_gp_main.py
If you include the path to an external dataset, it will auto-load at launch:
$ python karoo_gp_main.py /[path]/[to_your]/[filename].csv
You can include a one or more additional arguments, they will override the default values, as follows:
-ker [r,c,m] fitness function: (r)egression, (c)lassification, or (m)atching
-typ [f,g,r] Tree type: (f)ull, (g)row, or (r)amped half/half
-bas [3...10] maximum Tree depth for the initial population
-max [3...10] maximum Tree depth for the entire run
-min [3...100] minimum number of nodes
-pop [10...1000] maximum population
-gen [1...100] number of generations
-tor [1...100] number of trees selected for the tournament
-evr [0.0 ... 1.0] fraction percent of genetic operator Reproduction
-evp [0.0 ... 1.0] fraction percent of genetic operator Point Mutation
-evb [0.0 ... 1.0] fraction percent of genetic operator Branch Mutation
-evc [0.0 ... 1.0] fraction percent of genetic operator Crossover
If you include any of the above flags, then you *must* also include a flag to load an external dataset.
-fil [filename] an external dataset
An example is given, as follows:
$ python karoo_gp_server.py -ker c -typ r -bas 4 -fil /[path]/[to_your]/[filename].csv
'''
import os
import sys; #sys.path.append('modules/') # add directory 'modules' to the current path
import argparse
import karoo_gp_base_class; gp = karoo_gp_base_class.Base_GP()
os.system('clear')
print '\n\033[36m\033[1m'
print '\t ** ** ****** ***** ****** ****** ****** ******'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t **** ******** ****** ** ** ** ** ** *** *******'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ****** ****** ****** **'
print '\033[0;0m'
print '\t\033[36m Genetic Programming in Python - by Kai Staats, version 1.2\033[0;0m'
print ''
#++++++++++++++++++++++++++++++++++++++++++
# User Interface Configuation |
#++++++++++++++++++++++++++++++++++++++++++
if len(sys.argv) < 3: # either no command line argument (1) or the filename (2) was provided
# menu = ['c','r','m','p',''] # inserted all menus directly into while loops on 2018 05/07
while True:
try:
query = raw_input('\t Select (c)lassification, (r)egression, (m)atching, or (p)lay (default m): ')
if query not in ['c','r','m','p','']: raise ValueError()
kernel = query or 'm'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
if kernel == 'p':
while True:
try:
tree_type = raw_input('\t Select (f)ull or (g)row (default g): ')
if tree_type not in ['f','g','']: raise ValueError()
tree_type = tree_type or 'f'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
while True:
try:
tree_depth_base = raw_input('\t Enter the depth of the Tree (default 1): ')
if tree_depth_base not in str(range(1,11)) or tree_depth_base == '0': raise ValueError()
elif tree_depth_base == '': tree_depth_base = 1; break
tree_depth_base = int(tree_depth_base); break
except ValueError: print '\t\033[32m Enter a number from 1 including 10. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
tree_depth_max = tree_depth_base
tree_depth_min = 3
tree_pop_max = 1
generation_max = 1
tourn_size = 0
display = 'm'
# evolve_repro, evolve_point, evolve_branch, evolve_cross, tourn_size, precision, filename are not required
else: # if any other kernel is selected
while True:
try:
tree_type = raw_input('\t Select (f)ull, (g)row, or (r)amped 50/50 method (default r): ')
if tree_type not in ['f','g','r','']: raise ValueError()
tree_type = tree_type or 'r'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
while True:
try:
tree_depth_base = raw_input('\t Enter depth of the \033[3minitial\033[0;0m population of Trees (default 3): ')
if tree_depth_base not in str(range(1,11)) or tree_depth_base == '0': raise ValueError()
elif tree_depth_base == '': tree_depth_base = 3; break
tree_depth_base = int(tree_depth_base); break
except ValueError: print '\t\033[32m Enter a number from 1 including 10. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
if tree_type == 'f': tree_depth_max = tree_depth_base
else: # if type is Full, tree_depth_max is equal to tree_depth_base (initial pop setting)
while True:
try:
tree_depth_max = raw_input('\t Enter maximum Tree depth (default %i): ' %tree_depth_base)
if tree_depth_max not in str(range(tree_depth_base,11)): raise ValueError()
elif tree_depth_max == '': tree_depth_max = tree_depth_base
tree_depth_max = int(tree_depth_max)
if tree_depth_max < tree_depth_base: raise ValueError() # if max is set to < min 20170918
else: break
except ValueError: print '\t\033[32m Enter a number > or = the initial Tree depth. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
max_nodes = 2**(tree_depth_base +1) - 1 # auto calc the max number of nodes for the given depth
while True:
try:
tree_depth_min = raw_input('\t Enter minimum number of nodes for any given Tree (default 3; max %s): ' %str(max_nodes))
if tree_depth_min not in str(range(3,max_nodes)) or tree_depth_min == '0' or tree_depth_min == '1' or tree_depth_min == '2': raise ValueError()
elif tree_depth_min == '': tree_depth_min = 3
tree_depth_min = int(tree_depth_min); break
except ValueError: print '\t\033[32m Enter a number from 3 including %s. Try again ...\n\033[0;0m' %str(max_nodes)
except KeyboardInterrupt: sys.exit()
while True:
try:
tree_pop_max = raw_input('\t Enter number of Trees in each population (default 100): ')
if tree_pop_max not in str(range(1,1001)) or tree_pop_max == '0': raise ValueError()
elif tree_pop_max == '': tree_pop_max = 100
tree_pop_max = int(tree_pop_max); break
except ValueError: print '\t\033[32m Enter a number from 1 including 1000. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
tourn_size = int(tree_pop_max * 0.07) # default 7% can be changed by selecting Generation, 'ts', and then enter the run.
while True:
try:
generation_max = raw_input('\t Enter max number of generations (default 10): ')
if generation_max not in str(range(1,101)) or generation_max == '0': raise ValueError()
elif generation_max == '': generation_max = 10
generation_max = int(generation_max); break
except ValueError: print '\t\033[32m Enter a number from 1 including 100. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
while True:
try:
display = raw_input('\t Display (i)nteractive, (g)eneration, (m)iminal, (s)ilent, or (d)e(b)ug (default m): ')
if display not in ['i','g','m','s','db','']: raise ValueError()
display = display or 'm'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
evolve_repro = int(0.1 * tree_pop_max) # quantity of a population generated through Reproduction
evolve_point = int(0.0 * tree_pop_max) # quantity of a population generated through Point Mutation
evolve_branch = int(0.2 * tree_pop_max) # quantity of a population generated through Branch Mutation
evolve_cross = int(0.7 * tree_pop_max) # quantity of a population generated through Crossover
filename = '' # not required unless an external file is referenced
precision = 6 # number of floating points for the round function in 'fx_fitness_eval'
mode = 'm' # pause when complete, awaiting further user interaction
#++++++++++++++++++++++++++++++++++++++++++
# Command Line Configuation |
#++++++++++++++++++++++++++++++++++++++++++
else: # two or more command line argument were provided
ap = argparse.ArgumentParser(description = 'Karoo GP Server')
ap.add_argument('-ker', action = 'store', dest = 'kernel', default = 'c', help = '[c,r,m] fitness function: (r)egression, (c)lassification, or (m)atching')
ap.add_argument('-typ', action = 'store', dest = 'type', default = 'r', help = '[f,g,r] Tree type: (f)ull, (g)row, or (r)amped half/half')
ap.add_argument('-bas', action = 'store', dest = 'depth_base', default = 4, help = '[3...10] maximum Tree depth for the initial population')
ap.add_argument('-max', action = 'store', dest = 'depth_max', default = 4, help = '[3...10] maximum Tree depth for the entire run')
ap.add_argument('-min', action = 'store', dest = 'depth_min', default = 3, help = '[3...100] minimum number of nodes')
ap.add_argument('-pop', action = 'store', dest = 'pop_max', default = 100, help = '[10...1000] maximum population')
ap.add_argument('-gen', action = 'store', dest = 'gen_max', default = 10, help = '[1...100] number of generations')
ap.add_argument('-tor', action = 'store', dest = 'tor_size', default = 7, help = '[1...max pop] tournament size')
ap.add_argument('-evr', action = 'store', dest = 'evo_r', default = 0.1, help = '[0.0-1.0] fraction of pop generated through Reproduction')
ap.add_argument('-evp', action = 'store', dest = 'evo_p', default = 0.0, help = '[0.0-1.0] fraction of pop generated through Point Mutation')
ap.add_argument('-evb', action = 'store', dest = 'evo_b', default = 0.2, help = '[0.0-1.0] fraction of pop generated through Branch Mutation')
ap.add_argument('-evc', action = 'store', dest = 'evo_c', default = 0.7, help = '[0.0-1.0] fraction of pop generated through Crossover')
ap.add_argument('-fil', action = 'store', dest = 'filename', default = '', help = '/path/to_your/[data].csv')
args = ap.parse_args()
# pass the argparse defaults and/or user inputs to the required variables
kernel = str(args.kernel)
tree_type = str(args.type)
tree_depth_base = int(args.depth_base)
tree_depth_max = int(args.depth_max)
tree_depth_min = int(args.depth_min)
tree_pop_max = int(args.pop_max)
generation_max = int(args.gen_max)
tourn_size = int(args.tor_size)
evolve_repro = int(float(args.evo_r) * tree_pop_max) # quantity of each population generated through Reproduction
evolve_point = int(float(args.evo_p) * tree_pop_max) # quantity of each population generated through Point Mutation
evolve_branch = int(float(args.evo_b) * tree_pop_max) # quantity of each population generated through Branch Mutation
evolve_cross = int(float(args.evo_c) * tree_pop_max) # quantity of each population generated through Crossover
filename = str(args.filename)
display = 's' # display mode is set to (s)ilent
precision = 6 # number of floating points for the round function in 'fx_fitness_eval'
mode = 's' # drop back to the command line when complete
#++++++++++++++++++++++++++++++++++++++++++
# Pass all settings to the base_class |
#++++++++++++++++++++++++++++++++++++++++++
gp.fx_karoo_gp(kernel, tree_type, tree_depth_base, tree_depth_max, tree_depth_min, tree_pop_max, generation_max, tourn_size, filename, evolve_repro, evolve_point, evolve_branch, evolve_cross, display, precision, mode)
sys.exit()

View File

@ -2,7 +2,7 @@
# Define the methods and global variables used by Karoo GP
# by Kai Staats, MSc; see LICENSE.md
# Thanks to Emmanuel Dufourq and Arun Kumar for support during 2014-15 devel; TensorFlow support provided by Iurii Milovanov
# version 1.1
# version 2.0
'''
A NOTE TO THE NEWBIE, EXPERT, AND BRAVE
@ -134,7 +134,7 @@ class Base_GP(object):
# Methods to Run Karoo GP |
#+++++++++++++++++++++++++++++++++++++++++++++
def fx_karoo_gp(self, kernel, tree_type, tree_depth_base, tree_depth_max, tree_depth_min, tree_pop_max, generation_max, tourn_size, filename, evolve_repro, evolve_point, evolve_branch, evolve_cross, display, precision, app):
def fx_karoo_gp(self, kernel, tree_type, tree_depth_base, tree_depth_max, tree_depth_min, tree_pop_max, generation_max, tourn_size, filename, evolve_repro, evolve_point, evolve_branch, evolve_cross, display, precision, mode):
'''
This method enables the engagement of the entire Karoo GP application. It is used by both the desktop and server
@ -207,7 +207,7 @@ class Base_GP(object):
print ''
print '\033[3m Congrats!\033[0;0m Your Karoo GP run is complete.\n'
if app == 's': self.fx_data_params_write('Server')
if mode == 's': self.fx_data_params_write('Server')
else:
self.fx_data_params_write('Desktop')
print '\n\t\033[36m Type \033[1m?\033[0;0m\033[36m to review your options or \033[1mq\033[0;0m\033[36m to quit.\033[0;0m\n'
@ -319,9 +319,9 @@ class Base_GP(object):
while True:
try:
print '\n\t The current tournament size is:', self.tourn_size
query = raw_input('\t Adjust the tournament size (suggest 10): ')
query = raw_input('\t Adjust the tournament size (suggest 7): ')
if query not in str(menu) or query == '0' or query == '1': raise ValueError() # not ideal 20170918
elif query == '': break
elif query == '': break # retain the existing value
self.tourn_size = int(query); break
except ValueError: print '\n\t\033[32m Enter a number from 2 including', str(self.tree_pop_max) + ".", 'Try again ...\033[0;0m'
@ -333,7 +333,7 @@ class Base_GP(object):
print '\n\t The current minimum number of nodes is:', self.tree_depth_min
query = raw_input('\t Adjust the minimum number of nodes for all Trees (min 3): ')
if query not in str(menu) or query == '0' or query == '1' or query == '2': raise ValueError() # not ideal 20170918
elif query == '': break
elif query == '': break # retain the existing value
self.tree_depth_min = int(query); break
except ValueError: print '\n\t\033[32m Enter a number from 3 including 1000. Try again ...\033[0;0m'
@ -367,7 +367,7 @@ class Base_GP(object):
try:
query = raw_input('\t Enter quantity of Trees to be generated by Reproduction: ')
if query not in str(menu): raise ValueError()
elif query == '': break
elif query == '': break # retain the existing value
tmp_repro = int(query); break # replaced int(float(query)) 20170918
except ValueError: print '\n\t\033[32m Enter a number from 0 including 1000. Try again ...\033[0;0m'
@ -375,7 +375,7 @@ class Base_GP(object):
try:
query = raw_input('\t Enter quantity of Trees to be generated by Point Mutation: ')
if query not in str(menu): raise ValueError()
elif query == '': break
elif query == '': break # retain the existing value
tmp_point = int(query); break # replaced int(float(query)) 20170918
except ValueError: print '\n\t\033[32m Enter a number from 0 including 1000. Try again ...\033[0;0m'
@ -383,7 +383,7 @@ class Base_GP(object):
try:
query = raw_input('\t Enter quantity of Trees to be generated by Branch Mutation: ')
if query not in str(menu): raise ValueError()
elif query == '': break
elif query == '': break # retain the existing value
tmp_branch = int(query); break # replaced int(float(query)) 20170918
except ValueError: print '\n\t\033[32m Enter a number from 0 including 1000. Try again ...\033[0;0m'
@ -391,7 +391,7 @@ class Base_GP(object):
try:
query = raw_input('\t Enter quantity of Trees to be generated by Crossover: ')
if query not in str(menu): raise ValueError()
elif query == '': break
elif query == '': break # retain the existing value
tmp_cross = int(query); break # replaced int(float(query)) 20170918
except ValueError: print '\n\t\033[32m Enter a number from 0 including 1000. Try again ...\033[0;0m'
@ -648,6 +648,8 @@ class Base_GP(object):
This method is used to load a saved population of Trees, as invoked through the (pause) menu where population_s
replaces population_a in the /[path]/karoo_gp/runs/ directory.
Called by: fx_karoo_pause
Arguments required: population size
'''
@ -891,7 +893,7 @@ class Base_GP(object):
'tree_type' is either (f)ull or (g)row. Note, however, that when the user selects 'ramped 50/50' at launch,
it is still (f) or (g) which are passed to this method.
This method is called by: fx_init_construct, fx_evolve_crossover, fx_evolve_grow_mutate
Called by: fx_init_construct, fx_evolve_crossover, fx_evolve_grow_mutate
Arguments required: TREE_ID, tree_type, tree_depth_base
'''
@ -1203,7 +1205,7 @@ class Base_GP(object):
to the original variables listed across the top of each column of data.csv. Therefore, we must re-assign
the respective values for each subsequent row in the data .csv, for each Tree's unique expression.
Called by: fx_karoo_pause, fx_fitness_gym, fx_fitness_eval, fx_fitness_gene_pool, fx_display_tree
Called by: fx_karoo_pause, fx_data_params_write, fx_eval_label, fx_fitness_gym, fx_fitness_gene_pool, fx_display_tree
Arguments required: tree
'''
@ -1294,7 +1296,9 @@ class Base_GP(object):
print '\n Evaluate all Trees in Generation', self.generation_id
if self.display == 'i': self.fx_karoo_pause(0)
self.fx_evolve_tree_renum(self.population_b) # population renumber
for tree_id in range(1, len(self.population_b)): # renumber all Trees in given population - merged fx_evolve_tree_renum 2018 04/12
self.population_b[tree_id][0][1] = tree_id
self.fx_fitness_gym(self.population_b) # run 'fx_eval', 'fx_fitness', 'fx_fitness_store', and fitness record
self.fx_data_tree_write(self.population_b, 'a') # archive current population as foundation for next generation
@ -1325,7 +1329,7 @@ class Base_GP(object):
fitness for that generation. It is important to note that Part 3 does *not* in any way influence the Tournament
Selection which is a stand-alone process.
Called by:
Called by: fx_karoo_gp, fx_eval_generations
Arguments required: population
'''
@ -1412,7 +1416,7 @@ class Base_GP(object):
'pairwise_fitness' - an array of the element-wise results of applying corresponding fitness kernel function
'fitness' - aggregated scalar fitness score
Called by:
Called by: fx_karoo_pause, fx_data_params_write, fx_fitness_gym
Arguments required: expr, data
'''
@ -1456,10 +1460,6 @@ class Base_GP(object):
origin. At the time of this writing, an odd number of class labels will generate an extra bin on the positive
side of origin as it has not yet been determined the effect of enabling the middle bin to include both a
negative and positive result.
Called by:
Arguments required: result, solution
'''
# was breaking with upgrade from Tensorflow 1.1 to 1.3; fixed by Iurii by replacing [] with () as of 20171026
@ -1522,7 +1522,7 @@ class Base_GP(object):
'''
Extract expression tree from the string algo_sym and transform into TensorFlow (TF) graph.
Called by:
Called by: fx_fitness_eval
Arguments required: expr, tensors
'''
@ -1537,7 +1537,7 @@ class Base_GP(object):
'''
Chains a sequence of boolean operations (e.g. 'a and b and c') into a single TensorFlow (TF) sub graph.
Called by:
Called by: fx_fitness_node_parse
Arguments required: values, operation, tensors
'''
@ -1547,14 +1547,14 @@ class Base_GP(object):
return operation(x, self.fx_fitness_chain_bool(values[1:], operation, tensors))
else:
return x
def fx_fitness_chain_compare(self, comparators, ops, tensors):
'''
Chains a sequence of comparison operations (e.g. 'a > b < c') into a single TensorFlow (TF) sub graph.
Called by:
Called by: fx_fitness_node_parse
Arguments required: comparators, ops, tensors
'''
@ -1572,7 +1572,7 @@ class Base_GP(object):
'''
Recursively transforms parsed expression tree into TensorFlow (TF) graph.
Called by:
Called by: fx_fitness_expr_parse, fx_fitness_chain_bool, fx_fitness_chain_compare
Arguments required: node, tensors
'''
@ -1617,7 +1617,7 @@ class Base_GP(object):
elif solution - 1 - skew < result <= solution - skew; fitness = 1: # check for class bins between first and last
else: fitness = 0 # no class match
Called by:
Called by: fx_fitness_eval
Arguments required: result
'''
@ -1641,7 +1641,7 @@ class Base_GP(object):
be used to apply pressure to the evolutionary process to select from a set of trees with the same fitness function
the one(s) with the simplest (shortest) multivariate expression.
Called by:
Called by: fx_fitness_gym
Arguments required: tree, fitness
'''
@ -1670,7 +1670,7 @@ class Base_GP(object):
Stronger boundary parameters (a reduced gap between the min and max number of nodes) may invoke more compact
solutions, but also runs the risk of elitism, even total population die-off where a healthy population once existed.
Called by:
Called by: fx_nextgen_reproduce, fx_nextgen_point_mutate, fx_nextgen_branch_mutate, fx_nextgen_crossover
Arguments required: tourn_size
'''
@ -1767,7 +1767,7 @@ class Base_GP(object):
This method is automatically invoked with every Tournament Selection ('fx_fitness_tournament').
Called by:
Called by: fx_karoo_gp, fx_karoo_continue
Arguments required: none
'''
@ -1807,7 +1807,7 @@ class Base_GP(object):
y_pred = result, the predicted labels generated by Karoo GP
y_true = solution, the true labels associated with the data
Called by:
Called by: fx_karoo_pause
Arguments required: result
'''
@ -1827,7 +1827,7 @@ class Base_GP(object):
'''
Print the Fitness score and Mean Squared Error for a REGRESSION run against the test data.
Called by:
Called by: fx_karoo_pause
Arguments required: result
@ -1848,7 +1848,7 @@ class Base_GP(object):
'''
Print the accuracy for a MATCH kernel run against the test data.
Called by:
Called by: fx_karoo_pause
Arguments required: result
'''
@ -1951,7 +1951,7 @@ class Base_GP(object):
if self.display != 's':
if self.display == 'i': print ''
print ' Perform', self.evolve_branch, 'Full or Grow Mutations ...'
print ' Perform', self.evolve_branch, 'Branch Mutations ...'
if self.display == 'i': self.fx_karoo_pause(0)
for n in range(self.evolve_branch): # quantity of Trees to be generated through mutation
@ -2026,7 +2026,7 @@ class Base_GP(object):
'''
Mutate a single point in any Tree (Grow or Full).
Called by:
Called by: fx_nextgen_point_mutate
Arguments required: tree
'''
@ -2065,7 +2065,7 @@ class Base_GP(object):
shape of the Tree must remain identical, each node is mutated sequentially (copied from the new Tree to replace
the old, node for node), where functions remain functions and terminals remain terminals.
Called by:
Called by: fx_nextgen_branch_mutate
Arguments required: tree, branch
'''
@ -2115,7 +2115,7 @@ class Base_GP(object):
If however a function mutates into a terminal, the entire branch beneath the function is deleted from the array
and the entire array is updated, to fix parent/child links, associated arities, and node IDs.
Called by:
Called by: fx_nextgen_branch_mutate
Arguments required: tree, branch
'''
@ -2170,9 +2170,9 @@ class Base_GP(object):
if self.display == 'db': print '\n\033[36m This is the new Tree to be inserted at node\033[1m', branch_top, '\033[0;0m\033[36min tourn_winner:\033[0;0m\n', self.tree; self.fx_karoo_pause(0)
tree = self.fx_evolve_branch_insert(tree, branch) # insert new 'gp.tree' at point of mutation ('branch_top') in 'tree' ('tourn_winner')
# tree = self.fx_evolve_branch_body_copy(tree) # copy remaining nodes in new 'gp.tree' to 'tree' ('tourn_winner')
# because we already know the maximum depth to which this branch can grow, there is no need to prune after insertion
tree = self.fx_evolve_branch_top_copy(tree, branch) # copy root of new 'gp.tree' to point of mutation ('branch_top') in 'tree' ('tourn_winner')
tree = self.fx_evolve_branch_body_copy(tree) # copy remaining nodes in new 'gp.tree' to 'tree' ('tourn_winner')
tree = self.fx_evolve_fitness_wipe(tree) # wipe fitness data
@ -2190,7 +2190,7 @@ class Base_GP(object):
passed to 'offspring' which will receive 'branch_a'. With the second run, 'parent_a' is passed to 'offspring' which
will receive 'branch_b'.
Called by:
Called by: fx_nextgen_crossover
Arguments required: parent, branch_x, offspring, branch_y (parents_a / _b, branch_a / _b from 'fx_nextgen_crossover')
'''
@ -2233,8 +2233,8 @@ class Base_GP(object):
if self.display == 'db':
print '\n\033[36m ... and insert it into a copy of the second parent in place of the selected branch\033[1m', branch_y,':\033[0;0m\n', offspring; self.fx_karoo_pause(0)
offspring = self.fx_evolve_branch_top_copy(offspring, branch_y) # copy root of 'branch_y' ('gp.tree') to 'offspring'
offspring = self.fx_evolve_branch_body_copy(offspring) # copy remaining nodes in 'branch_y' ('gp.tree') to 'offspring'
offspring = self.fx_evolve_branch_insert(offspring, branch_y) # insert new 'branch_y' ('gp.tree') at point of mutation ('branch_top') in 'offspring' ('tourn_winner')
# offspring = self.fx_evolve_branch_body_copy(offspring) # copy remaining nodes in 'branch_y' ('gp.tree') to 'offspring'
offspring = self.fx_evolve_tree_prune(offspring, self.tree_depth_max) # prune to the max Tree depth + adjustment - tested 2016 07/10
offspring = self.fx_evolve_fitness_wipe(offspring) # wipe fitness data
@ -2251,7 +2251,7 @@ class Base_GP(object):
method to select a region of the 'tourn_winner' which is then converted to a stand-alone tree. As such, it is
imperative that the nodes be in the correct order, else all kinds of bad things happen.
Called by:
Called by: fx_nextgen_branch, fx_nextgen_crossover
Arguments required: tree
'''
@ -2269,58 +2269,42 @@ class Base_GP(object):
return branch
def fx_evolve_branch_top_copy(self, tree, branch):
def fx_evolve_branch_insert(self, tree, branch):
'''
Copy the point of mutation ('branch_top') from 'gp.tree' to 'tree'.
This method enables the insertion of Tree in place of a branch. It works with 3 inputs: local 'tree' is being
modified; local 'branch' is a section of 'tree' which will be removed; and the global 'gp.tree' (recycling this
variable from initial population generation) is the new Tree to be insertd into 'tree', replacing 'branch'.
This method works with 3 inputs: local 'tree' is being modified; local 'branch' is a section of 'tree' which
will be removed; and global 'gp.tree' (recycling from initial population generation) is the new Tree to be
copied into 'tree', replacing 'branch'.
The end result is a Tree with a mutated branch. Pretty cool, huh?
This method is used in both Grow Mutation and Crossover.
Called by:
Called by: fx_evolve_grow_mutate, fx_evolve_grow_crossover
Arguments required: tree, branch
'''
### insert branch_top from 'gp.tree' into 'tree' ### *_branch_top_copy merged with *_body_copy 2018 04/12
branch_top = int(branch[0])
tree[5][branch_top] = 'func' # update type ('func' to 'term' or 'term' to 'term'); this modifies gp.tree[5[1] from 'root' to 'func'
tree[5][branch_top] = 'func' # update type ('func' to 'term' or 'term' to 'term'); this modifies gp.tree[5][1] from 'root' to 'func'
tree[6][branch_top] = self.tree[6][1] # copy node_label from new tree
tree[8][branch_top] = self.tree[8][1] # copy node_arity from new tree
tree = np.delete(tree, branch[1:], axis = 1) # delete all nodes beneath point of mutation ('branch_top')
c_buffer = self.fx_evolve_c_buffer(tree, branch_top) # generate c_buffer for point of mutation ('branch_top')
tree = self.fx_evolve_child_insert(tree, branch_top, c_buffer) # insert new nodes
tree = self.fx_evolve_child_insert(tree, branch_top, c_buffer) # insert a single new node ('branch_top')
tree = self.fx_evolve_node_renum(tree) # renumber all 'NODE_ID's
if self.display == 'db':
print '\n\t ... inserted node 1 of', len(self.tree[3])-1
print '\n\033[36m This is the Tree after a new node is inserted:\033[0;0m\n', tree; self.fx_karoo_pause(0)
return tree
def fx_evolve_branch_body_copy(self, tree):
'''
Copy the body of 'gp.tree' to 'tree', one node at a time.
### insert branch_body from 'gp.tree' into 'tree' ### *_branch_top_copy merged with *_body_copy 2018 04/12
This method works with 3 inputs: local 'tree' is being modified; local 'branch' is a section of 'tree' which
will be removed; and global 'gp.tree' (recycling from initial population generation) is the new Tree to be
copied into 'tree', replacing 'branch'.
This method is used in both Grow Mutation and Crossover.
Called by:
Arguments required: tree
'''
node_count = 2 # set node count for 'gp.tree' to 2 as the new root has already replaced 'branch_top' in 'fx_evolve_branch_top_copy'
node_count = 2 # set node count for 'gp.tree' to 2 as the new root has already replaced 'branch_top' (above)
while node_count < len(self.tree[3]): # increment through all nodes in the new Tree ('gp.tree'), starting with node 2
@ -2357,9 +2341,7 @@ class Base_GP(object):
'''
This method prepares a stand-alone Tree as a copy of the given branch.
This method is used with Crossover.
Called by:
Called by: fx_evolve_crossover
Arguments required: tree, branch
'''
@ -2407,7 +2389,7 @@ class Base_GP(object):
This method is currently called from the evolution methods, but will soon (I hope) be called from the first
generation Tree generation methods (above) such that the same method may be used repeatedly.
Called by:
Called by: fx_evolve_child_link_fix, fx_evolve_banch_top_copy, fx_evolve_branch_body_copy
Arguments required: tree, node
'''
@ -2435,7 +2417,7 @@ class Base_GP(object):
'''
Link each parent node to its children.
Called by:
Called by: fx_evolve_child_link_fix
Arguments required: tree, node, c_buffer
'''
@ -2476,7 +2458,7 @@ class Base_GP(object):
This is required anytime the size of the array 'gp.tree' has been modified, as with both Grow and Full mutation.
Called by:
Called by: fx_evolve_grow_mutate, fx_evolve_crossover, fx_evolve_branch_body_copy, fx_evolve_branch_copy
Arguments required: tree
'''
@ -2495,7 +2477,7 @@ class Base_GP(object):
'''
Insert child nodes.
Called by:
Called by: fx_evolve_branch_insert
Arguments required: tree, node, c_buffer
'''
@ -2553,7 +2535,7 @@ class Base_GP(object):
of whack and the expression will work perfectly. This is maintained for the sole purpose of granting the user
a friendly, makes-sense interface which can be read in both directions.
Called by:
Called by: fx_evolve_branch_copy
Arguments required: tree
'''
@ -2586,7 +2568,7 @@ class Base_GP(object):
This is required after a function has been replaced by a terminal, as may occur with both Grow mutation and
Crossover.
Called by:
Called by: fx_evolve_grow_mutate, fx_evolve_tree_prune
Arguments required: tree
'''
@ -2611,7 +2593,7 @@ class Base_GP(object):
This is required after a new generation is evolved as the NODE_ID numbers are carried forward from the previous
generation but are no longer in order.
Called by:
Called by: fx_evolve_grow_mutate, fx_evolve_crossover, fx_evolve_branch_insert, fx_evolve_branch_copy
Arguments required: tree
'''
@ -2631,7 +2613,7 @@ class Base_GP(object):
This is required after a new generation is evolved as the fitness of the same Tree prior to its mutation will
no longer apply.
Called by:
Called by: fx_nextgen_reproduce, fx_nextgen_point_mutate, fx_nextgen_full_mutate, fx_nextgen_grow_mutate, fx_nextgen_crossover
Arguments required: tree
'''
@ -2648,7 +2630,7 @@ class Base_GP(object):
(branch) or a full tree, and it will operate correctly. The input value 'depth' becomes the new maximum depth,
where depth is defined as the local maximum + the user defined adjustment.
Called by:
Called by: fx_evolve_crossover
Arguments required: tree, depth
'''
@ -2673,26 +2655,6 @@ class Base_GP(object):
return tree
def fx_evolve_tree_renum(self, population):
'''
Renumber all 'TREE_ID' in a given population.
This is required after a new generation is evolved as the TREE_ID numbers are carried forward from the previous
generation but are no longer in order.
Called by:
Arguments required: population
'''
for tree_id in range(1, len(population)):
population[tree_id][0][1] = tree_id # renumber all Trees in given population
return population
def fx_evolve_pop_copy(self, pop_a, title):
@ -2702,7 +2664,7 @@ class Base_GP(object):
Simply copying a list of arrays generates a pointer to the original list. Therefore we must append each array
to a new, empty array and then build a list of those new arrays.
Called by:
Called by: fx_karoo_gp, fx_karoo_continue
Arguments required: pop_a, title
'''
@ -2728,7 +2690,7 @@ class Base_GP(object):
This method displays all sequential node_ids from 'start' node through bottom, within the given tree.
Called by:
Called by: fx_karoo_gp, fx_karoo_pause
Arguments required: tree
'''
@ -2737,7 +2699,7 @@ class Base_GP(object):
print '\n\033[1m\033[36m Tree ID', int(tree[0][1]), '\033[0;0m'
for depth in range(0, self.tree_depth_max + 1): # increment through all possible Tree depths - tested 2016 07/09
print '\n', ind,'\033[36m Tree Depth:', depth, 'of', tree[2][1], '\033[0;0m'
print '\n', ind,'\033[36m Tree Depth:', depth, 'of', tree[2][1], '\033[0`;0m'
for node in range(1, len(tree[3])): # increment through all nodes (redundant, I know)
if int(tree[4][node]) == depth:
@ -2764,9 +2726,7 @@ class Base_GP(object):
This method displays all sequential node_ids from 'start' node through bottom, within the given branch.
This method is not used by Karoo GP at this time.
Called by:
Called by: This method is not used by Karoo GP at this time.
Arguments required: tree, start
'''

View File

@ -1,187 +0,0 @@
# Karoo GP Main (desktop)
# Use Genetic Programming for Classification and Symbolic Regression
# by Kai Staats, MSc; see LICENSE.md
# version 1.1
'''
A word to the newbie, expert, and brave--
Even if you are highly experienced in Genetic Programming, it is recommended that you review the 'Karoo User Guide'
before running this application. While your computer will not burst into flames nor will the sun collapse into a black
hole if you do not, you will likely find more enjoyment of this particular flavour of GP with a little understanding
of its intent and design.
KAROO GP DESKTOP
This is the Karoo GP desktop application. It presents a simple yet functional user interface for configuring each
Karoo GP run. While this can be launched on a remote server, you may find that once you get the hang of using Karoo,
and are in more of a production mode than one of experimentation, using karoo_gp_server.py is more to your liking as
it provides both a scripted and/or command-line launch vehicle.
To launch Karoo GP desktop:
$ python karoo_gp_main.py
(or from iPython)
$ run karoo_gp_main.py
If you include the path to an external dataset, it will auto-load at launch:
$ python karoo_gp_main.py /[path]/[to_your]/[filename].csv
'''
import sys; sys.path.append('modules/') # add directory 'modules' to the current path
import os
import karoo_gp_base_class; gp = karoo_gp_base_class.Base_GP()
os.system('clear')
print '\n\033[36m\033[1m'
print '\t ** ** ****** ***** ****** ****** ****** ******'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t **** ******** ****** ** ** ** ** ** *** *******'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ****** ****** ****** **'
print '\033[0;0m'
print '\t\033[36m Genetic Programming in Python - by Kai Staats, version 1.1\033[0;0m'
print ''
#++++++++++++++++++++++++++++++++++++++++++
# User Defined Configuration |
#++++++++++++++++++++++++++++++++++++++++++
'''
Karoo GP queries the user for key parameters, some of which may be adjusted during run-time at user invoked pauses.
See the User Guide for meaning and value of each of the following parameters. The server version of Karoo enables
all parameters to be configured via command-line arguments.
'''
menu = ['c','r','m','p','']
while True:
try:
kernel = raw_input('\t Select (c)lassification, (r)egression, (m)atching, or (p)lay (default m): ')
if kernel not in menu: raise ValueError()
kernel = kernel or 'm'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
if kernel == 'p':
menu = ['f','g','']
while True:
try:
tree_type = raw_input('\t Select (f)ull or (g)row method (default f): ')
if tree_type not in menu: raise ValueError()
tree_type = tree_type or 'f'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
else:
menu = ['f','g','r','']
while True:
try:
tree_type = raw_input('\t Select (f)ull, (g)row, or (r)amped 50/50 method (default r): ')
if tree_type not in menu: raise ValueError()
tree_type = tree_type or 'r'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
menu = range(1,11)
while True:
try:
tree_depth_base = raw_input('\t Enter depth of the \033[3minitial\033[0;0m population of Trees (default 3): ')
if tree_depth_base not in str(menu) or tree_depth_base == '0': raise ValueError()
elif tree_depth_base == '': tree_depth_base = 3; break
tree_depth_base = int(tree_depth_base); break
except ValueError: print '\t\033[32m Enter a number from 1 including 10. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
if kernel == 'p': # if the Play kernel is selected
tree_depth_max = tree_depth_base
tree_depth_min = 0
tree_pop_max = 1
generation_max = 1
display = 'm'
# evolve_repro = evolve_point = evolve_branch = evolve_cross = ''
# tourn_size = ''
# precision = ''
# filename = ''
else: # if any other kernel is selected
if tree_type == 'f': tree_depth_max = tree_depth_base
else: # if type is Full, the maximum Tree depth for the full run is equal to the initial population
menu = range(tree_depth_base,11)
while True:
try:
tree_depth_max = raw_input('\t Enter maximum Tree depth (default %i): ' %tree_depth_base)
if tree_depth_max not in str(menu): raise ValueError()
elif tree_depth_max == '': tree_depth_max = tree_depth_base
tree_depth_max = int(tree_depth_max)
if tree_depth_max < tree_depth_base: raise ValueError() # an ugly exception to the norm 20170918
else: break
except ValueError: print '\t\033[32m Enter a number >= the initial Tree depth. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
menu = range(3,101)
while True:
try:
tree_depth_min = raw_input('\t Enter minimum number of nodes for any given Tree (default 3): ')
if tree_depth_min not in str(menu) or tree_depth_min == '0': raise ValueError()
elif tree_depth_min == '': tree_depth_min = 3
tree_depth_min = int(tree_depth_min); break
except ValueError: print '\t\033[32m Enter a number from 3 to 2^(depth + 1) - 1 including 100. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
menu = range(10,1001)
while True:
try:
tree_pop_max = raw_input('\t Enter number of Trees in each population (default 100): ')
if tree_pop_max not in str(menu) or tree_pop_max == '0': raise ValueError()
elif tree_pop_max == '': tree_pop_max = 100
tree_pop_max = int(tree_pop_max); break
except ValueError: print '\t\033[32m Enter a number from 10 including 1000. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
menu = range(1,101)
while True:
try:
generation_max = raw_input('\t Enter max number of generations (default 10): ')
if generation_max not in str(menu) or generation_max == '0': raise ValueError()
elif generation_max == '': generation_max = 10
generation_max = int(generation_max); break
except ValueError: print '\t\033[32m Enter a number from 1 including 100. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
menu = ['i','g','m','s','db','']
while True:
try:
display = raw_input('\t Display (i)nteractive, (g)eneration, (m)iminal, (s)ilent, or (d)e(b)ug (default m): ')
if display not in menu: raise ValueError()
display = display or 'm'; break
except ValueError: print '\t\033[32m Select from the options given. Try again ...\n\033[0;0m'
except KeyboardInterrupt: sys.exit()
# define the ratio between types of mutation, where all sum to 1.0; can be adjusted in 'i'nteractive mode
evolve_repro = int(0.1 * tree_pop_max) # quantity of a population generated through Reproduction
evolve_point = int(0.0 * tree_pop_max) # quantity of a population generated through Point Mutation
evolve_branch = int(0.2 * tree_pop_max) # quantity of a population generated through Branch Mutation
evolve_cross = int(0.7 * tree_pop_max) # quantity of a population generated through Crossover
tourn_size = 7 # qty of individuals entered into each tournament (standard = 7%); can be adjusted in 'i'nteractive mode
precision = 6 # the number of floating points for the round function in 'fx_fitness_eval'; hard coded
filename = '' # not required unless an external file is referenced
# pass all user defined settings to the base_class and launch Karoo GP
gp.fx_karoo_gp(kernel, tree_type, tree_depth_base, tree_depth_max, tree_depth_min, tree_pop_max, generation_max, tourn_size, filename, evolve_repro, evolve_point, evolve_branch, evolve_cross, display, precision, 'm')
print 'You seem to have found your way back to the Desktop. Huh.'
sys.exit()

View File

@ -1,109 +0,0 @@
# Karoo GP Server
# Use Genetic Programming for Classification and Symbolic Regression
# by Kai Staats, MSc; see LICENSE.md
# version 1.1
'''
A word to the newbie, expert, and brave--
Even if you are highly experienced in Genetic Programming, it is recommended that you review the 'Karoo User Guide'
before running this application. While your computer will not burst into flames nor will the sun collapse into a black
hole if you do not, you will likely find more enjoyment of this particular flavour of GP with a little understanding
of its intent and design.
KAROO GP SERVER
This is the Karoo GP server application. It can be internally scripted, fully command-line configured, or a combination
of both. If this is your first time using Karoo GP, please run the desktop application karoo_gp_main.py first in order
that you come to understand the full functionality of this particular Genetic Programming platform.
To launch Karoo GP server:
$ python karoo_gp_server.py
(or from iPython)
$ run karoo_gp_server.py
Without any arguments, Karoo GP relies entirely upon the scripted settings and the datasets located in karoo_gp/files/.
If you include the path to an external dataset, it will auto-load at launch:
$ python karoo_gp_server.py /[path]/[to_your]/[filename].csv
You can include a number of additional arguments which override the default values, as follows:
-ker [r,c,m] fitness function: (r)egression, (c)lassification, or (m)atching
-typ [f,g,r] Tree type: (f)ull, (g)row, or (r)amped half/half
-bas [3...10] maximum Tree depth for the initial population
-max [3...10] maximum Tree depth for the entire run
-min [3...100] minimum number of nodes
-pop [10...1000] maximum population
-gen [1...100] number of generations
-tor [1...100] number of trees selected for the tournament
-fil [filename] an external dataset
Note that if you include any of the above flags, then you must also include a flag to load an external dataset.
An example is given, as follows:
$ python karoo_gp_server.py -ker c -typ r -bas 4 -fil /[path]/[to_your]/[filename].csv
'''
import sys; sys.path.append('modules/') # to add the directory 'modules' to the current path
import os
import argparse
import karoo_gp_base_class; gp = karoo_gp_base_class.Base_GP()
os.system('clear')
print '\n\033[36m\033[1m'
print '\t ** ** ****** ***** ****** ****** ****** ******'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t **** ******** ****** ** ** ** ** ** *** *******'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ** ** ** ** ** ** **'
print '\t ** ** ** ** ** ** ****** ****** ****** **'
print '\033[0;0m'
print '\t\033[36m Genetic Programming in Python - by Kai Staats, version 1.1\033[0;0m'
print ''
ap = argparse.ArgumentParser(description = 'Karoo GP Server')
ap.add_argument('-ker', action = 'store', dest = 'kernel', default = 'c', help = '[c,r,m] fitness function: (r)egression, (c)lassification, or (m)atching')
ap.add_argument('-typ', action = 'store', dest = 'type', default = 'r', help = '[f,g,r] Tree type: (f)ull, (g)row, or (r)amped half/half')
ap.add_argument('-bas', action = 'store', dest = 'depth_base', default = 3, help = '[3...10] maximum Tree depth for the initial population')
ap.add_argument('-max', action = 'store', dest = 'depth_max', default = 5, help = '[3...10] maximum Tree depth for the entire run')
ap.add_argument('-min', action = 'store', dest = 'depth_min', default = 3, help = '[3...100] minimum number of nodes')
ap.add_argument('-pop', action = 'store', dest = 'pop_max', default = 100, help = '[10...1000] maximum population')
ap.add_argument('-gen', action = 'store', dest = 'gen_max', default = 10, help = '[1...100] number of generations')
ap.add_argument('-tor', action = 'store', dest = 'tor_size', default = 7, help = '[1...max pop] tournament size')
ap.add_argument('-fil', action = 'store', dest = 'filename', default = '', help = '/path/to_your/[data].csv')
args = ap.parse_args()
# pass the argparse defaults and/or user inputs to the required variables
kernel = str(args.kernel)
tree_type = str(args.type)
tree_depth_base = int(args.depth_base)
tree_depth_max = int(args.depth_max)
tree_depth_min = int(args.depth_min)
tree_pop_max = int(args.pop_max)
generation_max = int(args.gen_max)
tourn_size = int(args.tor_size)
filename = str(args.filename)
evolve_repro = int(0.1 * tree_pop_max) # quantity of a population generated through Reproduction
evolve_point = int(0.0 * tree_pop_max) # quantity of a population generated through Point Mutation
evolve_branch = int(0.2 * tree_pop_max) # quantity of a population generated through Branch Mutation
evolve_cross = int(0.7 * tree_pop_max) # quantity of a population generated through Crossover
display = 's' # display mode is set to (s)ilent
precision = 6 # the number of floating points for the round function in 'fx_fitness_eval'
# pass all user defined settings to the base_class and launch Karoo GP
gp.fx_karoo_gp(kernel, tree_type, tree_depth_base, tree_depth_max, tree_depth_min, tree_pop_max, generation_max, tourn_size, filename, evolve_repro, evolve_point, evolve_branch, evolve_cross, display, precision, 's')
sys.exit()