version 2.0
parent
29d4bf227d
commit
98cf28a2f5
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
@ -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
|
||||
'''
|
||||
|
|
187
karoo_gp_main.py
187
karoo_gp_main.py
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
Loading…
Reference in New Issue