Skip to content

Instantly share code, notes, and snippets.

@lukehorvat
Created January 15, 2013 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukehorvat/4537835 to your computer and use it in GitHub Desktop.
Save lukehorvat/4537835 to your computer and use it in GitHub Desktop.
An introduction to genetic programming with esec demonstrating decision tree induction.
from esec import esdl_eval
from esec.species.tgp import Instruction, DecisionInstructionWithState
from esec.landscape.tgp import TGPFitness
#define the attributes of a Saturday morning
OUTLOOK = ('SUNNY', 'OVERCAST', 'RAIN')
HUMIDITY = ('HIGH', 'NORMAL')
WINDY = (True, False)
#define the state object to store attributes of a Saturday morning
class SaturdayMorning(object):
def __init__(self, outlook, humidity, windy):
self.outlook = outlook
self.humidity = humidity
self.windy = windy
def classification(self):
if self.outlook == 'SUNNY':
return 0 if self.humidity == 'HIGH' else 1
elif self.outlook == 'OVERCAST':
return 1
elif self.outlook == 'RAIN':
return 0 if self.windy else 1
#define the fitness cases
fitness_cases = [SaturdayMorning(outlook, humidity, windy) for outlook in OUTLOOK for humidity in HUMIDITY for windy in WINDY]
#define the fitness evaluator for individuals
@esdl_eval
def decision_tree_induction(indiv):
score = 0
for fitness_case in fitness_cases:
if indiv.evaluate(indiv, state=fitness_case, terminals=[0, 1]) == fitness_case.classification():
score += 1
return TGPFitness([score, len(indiv[0])])
#define the instruction set
instructions = [
# evaluate the 1st, 2nd or 3rd parameter based on the conditions
DecisionInstructionWithState(lambda fitness_case: 1 if fitness_case.outlook == 'SUNNY' else (2 if fitness_case.outlook == 'OVERCAST' else 3), param_count=3, name='OUT'),
DecisionInstructionWithState(lambda fitness_case: 1 if fitness_case.humidity == 'HIGH' else 2, param_count=2, name='HUM'),
DecisionInstructionWithState(lambda fitness_case: 1 if fitness_case.windy else 2, param_count=2, name='WIND'),
]
#define the system definition
esdl_system_definition = r'''
FROM random_tgp(instructions=instructions, terminals=2, deepest=4) SELECT (size) population
YIELD population
BEGIN generation
FROM population \
SELECT (0.9*size) to_cross, (0.02*size) to_mutate, (0.08*size) to_reproduce \
USING fitness_proportional
FROM to_cross SELECT offspring1 USING crossover_one(deepest_result, terminal_prob=0.1)
FROM to_mutate SELECT offspring2 USING mutate_random(deepest_result)
FROM offspring1, offspring2, to_reproduce SELECT (size) population
YIELD population
END generation
'''
#define the experiment configuration
config = {
'landscape': decision_tree_induction,
'system': {
'instructions': instructions,
'definition': esdl_system_definition,
'size': 500,
'deepest_result': 17,
},
'monitor': {
'report': 'gen+births+best+local+best_length+time_delta+best_genome',
'summary': 'status+best+best_length+best_phenome',
'limits': {
'iterations': 50,
'fitness': TGPFitness([len(fitness_cases), 0]),
}
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment