Skip to content

Commit

Permalink
Merge branch 'master' into pep8
Browse files Browse the repository at this point in the history
  • Loading branch information
jmmcd authored Oct 17, 2021
2 parents d4eb17d + 6a55a2b commit e144bee
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 51 deletions.
6 changes: 6 additions & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Michael Fenton
David Fagan
James McDermott
Stefan Forstenlechner
Erik Hemberg
Michael O'Neill
8 changes: 8 additions & 0 deletions src/algorithm/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ def set_params(command_line_args, create_files=True):
params['GENERATION_SIZE'] = params['POPULATION_SIZE'] - \
params['ELITE_SIZE']

if (params['MUTATION_PROBABILITY'] is not None and
params['MUTATION_EVENTS'] != 1):
s = "operators.mutation.int_flip_per_codon\n" \
"Error: mutually exclusive parameters 'MUTATION_PROBABILITY'" \
"and 'MUTATION_EVENTS' have been explicitly set.\n" \
"Only one of these parameters can be used at a time."
raise Exception(s)

# Initialise run lists and folders before we set imports.r
initialise_run_params(create_files)

Expand Down
11 changes: 5 additions & 6 deletions src/fitness/progsys.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import json
import subprocess
import sys
from subprocess import Popen, PIPE
from sys import maxsize, executable
from os import path

from algorithm.parameters import params
from fitness.base_ff_classes.base_ff import base_ff



class progsys(base_ff):
"""Fitness function for program synthesis problems. Grammars and datasets
for 29 benchmark problems from doi.org/10.1145/2739480.2754769 are
Expand Down Expand Up @@ -66,10 +67,8 @@ def evaluate(self, ind, **kwargs):
@staticmethod
def create_eval_process():
"""create separate python process for evaluation"""
return subprocess.Popen(['python',
'scripts/python_script_evaluation.py'],
stdout=subprocess.PIPE,
stdin=subprocess.PIPE)
return Popen([sys.executable, 'scripts/python_script_evaluation.py'],
stdout=PIPE, stdin=PIPE)

def format_program(self, individual, header, footer):
"""formats the program by formatting the individual and adding
Expand Down
16 changes: 4 additions & 12 deletions src/operators/mutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,12 @@ def int_flip_per_codon(ind):
# Linear mutation cannot be performed on this individual.
return ind

# Set mutation probability. Default is 1 over the length of the genome.
if params['MUTATION_PROBABILITY'] and params['MUTATION_EVENTS'] == 1:
# Set mutation probability.
if params['MUTATION_PROBABILITY'] is not None:
p_mut = params['MUTATION_PROBABILITY']
elif params['MUTATION_PROBABILITY'] and params['MUTATION_EVENTS'] > 1:
s = "operators.mutation.int_flip_per_codon\n" \
"Error: mutually exclusive parameters for 'MUTATION_PROBABILITY'" \
"and 'MUTATION_EVENTS' have been explicitly set.\n" \
" Only one of these parameters can be used at a time with" \
"int_flip_per_codon mutation."
raise Exception(s)
else:
# Default mutation events per individual is 1. Raising this number
# will influence the mutation probability for each codon.
p_mut = params['MUTATION_EVENTS'] / eff_length
# Default is 1 divided by genome length.
p_mut = 1.0 / eff_length

# Mutation probability works per-codon over the portion of the
# genome as defined by the within_used flag.
Expand Down
60 changes: 33 additions & 27 deletions src/representation/derivation.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,10 @@ def generate_tree(tree, genome, output, method, nodes, depth, max_depth,
available = legal_productions(method, remaining_depth, tree.root,
productions['choices'])

# Randomly pick a production choice.
# Randomly pick a production choice and make a codon with it.
chosen_prod = choice(available)

# Find the index of the chosen production and set a matching codon based
# on that index.
prod_index = productions['choices'].index(chosen_prod)
codon = randrange(productions['no_choices'],
params['BNF_GRAMMAR'].codon_size,
productions['no_choices']) + prod_index

codon = generate_codon(chosen_prod, productions)

# Set the codon for the current node and append codon to the genome.
tree.codon = codon
genome.append(codon)
Expand Down Expand Up @@ -93,6 +87,30 @@ def generate_tree(tree, genome, output, method, nodes, depth, max_depth,
return genome, output, nodes, depth, max_depth


def generate_codon(chosen_prod, productions):
"""
Generate a single codon
:param chosen_prod: the specific production to build a codon for
:param productions: productions possible from the current root
:return: a codon integer
"""

# Find the index of the chosen production
production_index = productions['choices'].index(chosen_prod)

# Choose a random offset with guarantee that (offset + production_index) < codon_size
offset = randrange(
start=0,
stop=params['BNF_GRAMMAR'].codon_size - productions['no_choices'] + 1,
step=productions['no_choices']
)

codon = offset + production_index
return codon


def legal_productions(method, depth_limit, root, productions):
"""
Returns the available production choices for a node given a specific
Expand All @@ -114,8 +132,8 @@ def legal_productions(method, depth_limit, root, productions):

if method == "random":
# Randomly build a tree.

if not depth_limit:
if depth_limit is None:
# There is no depth limit, any production choice can be used.
available = productions

Expand Down Expand Up @@ -224,15 +242,9 @@ def pi_random_derivation(tree, max_depth):
available = legal_productions("random", remaining_depth, node.root,
productions['choices'])

# Randomly pick a production choice.
# Randomly pick a production choice and make a codon with it.
chosen_prod = choice(available)

# Find the index of the chosen production and set a matching codon
# based on that index.
prod_index = productions['choices'].index(chosen_prod)
codon = randrange(productions['no_choices'],
params['BNF_GRAMMAR'].codon_size,
productions['no_choices']) + prod_index
codon = generate_codon(chosen_prod, productions)

# Set the codon for the current node and append codon to the genome.
node.codon = codon
Expand Down Expand Up @@ -333,15 +345,9 @@ def pi_grow(tree, max_depth):
available = legal_productions("random", remaining_depth, node.root,
productions['choices'])

# Randomly pick a production choice.
# Randomly pick a production choice and make a codon with it.
chosen_prod = choice(available)

# Find the index of the chosen production and set a matching codon
# based on that index.
prod_index = productions['choices'].index(chosen_prod)
codon = randrange(productions['no_choices'],
params['BNF_GRAMMAR'].codon_size,
productions['no_choices']) + prod_index
codon = generate_codon(chosen_prod, productions)

# Set the codon for the current node and append codon to the genome.
node.codon = codon
Expand Down
4 changes: 2 additions & 2 deletions src/scripts/experiment_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
Copyright (c) 2014 Michael Fenton
Hereby licensed under the GNU GPL v3."""
from sys import path

from sys import path, executable
path.append("../src")

from utilities.algorithm.general import check_python_version
Expand All @@ -26,7 +26,7 @@ def execute_run(seed):
:return: Nothing.
"""

exec_str = "python3 ponyge.py " \
exec_str = executable + " ponyge.py " \
"--random_seed " + str(seed) + " " + " ".join(sys.argv[1:])

call(exec_str, shell=True)
Expand Down
2 changes: 1 addition & 1 deletion src/utilities/fitness/error_metric.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import warnings

import numpy as np
from sklearn.metrics.classification import f1_score as sklearn_f1_score
from sklearn.metrics import f1_score as sklearn_f1_score


def mae(y, yhat):
Expand Down
6 changes: 3 additions & 3 deletions src/utilities/stats/file_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def generate_folders_and_files():

if not path.isdir(path_1):
# Create results folder.
makedirs(path_1)
makedirs(path_1, exist_ok=True)

# Set file path to include experiment name.
params['FILE_PATH'] = path.join(path_1, params['EXPERIMENT_NAME'])
Expand All @@ -136,12 +136,12 @@ def generate_folders_and_files():

# Generate save folders
if not path.isdir(params['FILE_PATH']):
makedirs(params['FILE_PATH'])
makedirs(params['FILE_PATH'], exist_ok=True)

if not path.isdir(path.join(params['FILE_PATH'],
str(params['TIME_STAMP']))):
makedirs(path.join(params['FILE_PATH'],
str(params['TIME_STAMP'])))
str(params['TIME_STAMP'])), exist_ok=True)

params['FILE_PATH'] = path.join(params['FILE_PATH'],
str(params['TIME_STAMP']))
Expand Down

0 comments on commit e144bee

Please sign in to comment.