def main(args=sys.argv[1:]): """Runs the main GASTOp script, from the command line. Reads and parses user input from command line, runs the code, and prints and plots the resulting best truss. """ args = parse_args(args) config = utilities.init_file_parser(args.config_path) if args.display: progress_fitness = True progress_truss = True elif args.quiet: progress_fitness = False progress_truss = False else: progress_fitness = config['monitor_params']['progress_fitness'] progress_truss = config['monitor_params']['progress_truss'] if args.num_threads: num_threads = args.num_threads else: num_threads = config['ga_params']['num_threads'] if args.num_gens: num_generations = args.num_gens else: num_generations = config['ga_params']['num_generations'] if args.pop_size: pop_size = args.pop_size else: pop_size = config['ga_params']['pop_size'] # Create the Genetic Algorithm Object ga = GenAlg(config) ga.initialize_population(pop_size) best, progress_history = ga.run(num_generations=num_generations, progress_fitness=progress_fitness, progress_truss=progress_truss, num_threads=num_threads) print(best) if args.output: utilities.save_progress_history(progress_history, path_progress_history=args.output) if progress_fitness or progress_truss: best.plot( domain=config['random_params']['domain'], loads=config['evaluator_params']['boundary_conditions']['loads'], fixtures=config['evaluator_params']['boundary_conditions'] ['fixtures'], deflection=True)
def testInvalidCrossover(self): """Tests genalg when % crossover + % mutation >1""" config = utilities.init_file_parser(init_file_path) config['ga_params']['percent_crossover'] = .6 config['ga_params']['percent_mutation'] = .6 ga = GenAlg(config) ga.initialize_population(100) for t in ga.population: t.fitness_score = np.random.random() self.assertRaises(RuntimeError, ga.update_population) bad_path = 'gastop-config/error_config.txt' self.assertRaises(RuntimeError, utilities.init_file_parser, bad_path)
def testSaveLoadPopProgress(self): '''Tests that the pop_progress dictionary is correctly saved to and loaded from a JSON file. ''' # Parse input paramters from init.txt file init_file_path = 'gastop-config/struct_making_test_init.txt' config = utilities.init_file_parser(init_file_path) progress_fitness = False progress_truss = False num_threads = 1 num_generations = 3 pop_size = 5 # Create the Genetic Algorithm Object ga = GenAlg(config) ga.initialize_population(pop_size) best, progress_history = ga.run(num_generations=num_generations, progress_fitness=progress_fitness, progress_truss=progress_truss, num_threads=num_threads) # Save and load pop_progress to/from JSON file utilities.save_progress_history(progress_history) loaded_progress_history = utilities.load_progress_history() print(loaded_progress_history) for gen in loaded_progress_history.keys(): self.assertTrue( isinstance(loaded_progress_history[gen]['Generation'], int)) self.assertTrue( isinstance(loaded_progress_history[gen]['Best Truss'], Truss)) self.assertTrue( isinstance(loaded_progress_history[gen]['Best Fitness Score'], float)) self.assertTrue( isinstance( loaded_progress_history[gen] ['Population Median Fitness Score'], float)) self.assertTrue( isinstance( loaded_progress_history[gen] ['Population Fitness Score Range'], float))
def __init__(self, config): """Creates a GenAlg object Once created, the object will store all of the relavant information about a population. The object also contains the necessary functions to modify itself, evaluate its 'goodness', and then create new members for the next generation. Args: Either: config (dict): Configuration dictionary with parameters, such as one created by :meth:`gastop.utilities.init_file_parser` config (str): File path to config file to be parsed. Used instead of passing config dictionary directly. Returns: GenAlg callable object """ if isinstance(config, str): config = utilities.init_file_parser(config) self.config = config self.ga_params = config['ga_params'] self.mutator_params = config['mutator_params'] self.random_params = config['random_params'] self.crossover_params = config['crossover_params'] self.selector_params = config['selector_params'] self.population = [] self.evaluator = Evaluator(**config['evaluator_params']) self.fitness_function = FitnessFunction(**config['fitness_params']) # progress monitor stuff self.pop_progress = [] # initialize as empty array, DELETE? # self.progress_display = progress_display #type of progress display # [0,1,2] = [no display, terminal display, plot display], change to text later if isinstance(self.random_params['rng_seed'], tuple): np.random.set_state(self.random_params['rng_seed']) elif isinstance(self.random_params['rng_seed'], int): np.random.seed(self.random_params['rng_seed']) else: np.random.seed(1729)
def testOddNumCrossover(self): """Tests genalg when crossover number is odd to make sure it still return the correct population size """ config = utilities.init_file_parser(init_file_path) config['ga_params']['percent_crossover'] = 1 config['ga_params']['percent_mutation'] = 0 config['ga_params']['num_elite'] = 5 ga = GenAlg(config) ga.initialize_population(100) ga.run(num_generations=2) self.assertAlmostEqual(len(ga.population), 100) # test zero crossover config['ga_params']['percent_crossover'] = 0 config['ga_params']['percent_mutation'] = 1 ga = GenAlg(config) ga.initialize_population(100) ga.run(num_generations=2) self.assertAlmostEqual(len(ga.population), 100)
def testSaveLoadState(self): '''Tests that config and population can be saved to and loaded from JSON files. ''' # Parse input parameters from init file init_file_path = 'gastop-config/struct_making_test_init.txt' config = utilities.init_file_parser(init_file_path) # Create GenAlg object pop_size = int(1e4) ga = GenAlg(config) ga.initialize_population(pop_size) # Save and reload ga.save_state() ga_loaded = ga.load_state() config = ga_loaded.config population = ga_loaded.population # Test config self.assertTrue(isinstance(config['ga_params']['num_elite'], int)) self.assertTrue( isinstance(config['ga_params']['percent_crossover'], float)) self.assertTrue( type(config['mutator_params']['node_mutator_params']['boundaries']) is type(np.array([1, 1]))) self.assertTrue( isinstance( config['mutator_params']['node_mutator_params']['int_flag'], bool)) # Test population for truss in population: self.assertTrue(isinstance(truss, Truss)) self.assertTrue(isinstance(truss.user_spec_nodes, np.ndarray)) self.assertTrue(isinstance(truss.rand_nodes, np.ndarray)) self.assertTrue(isinstance(truss.edges, np.ndarray)) self.assertTrue(isinstance(truss.properties, np.ndarray))
def testInitFileParser(self): """Tests that the init file is parsed correctly""" init_file_path = 'gastop-config/boolean_parse_test_init.txt' config = utilities.init_file_parser(init_file_path) self.assertTrue(isinstance(config['ga_params']['num_elite'], int)) self.assertTrue( isinstance(config['ga_params']['percent_crossover'], float)) self.assertTrue( type(config['mutator_params']['node_mutator_params']['boundaries']) is type(np.array([1, 1]))) self.assertTrue( isinstance( config['mutator_params']['node_mutator_params']['int_flag'], bool)) self.assertTrue(config['general']['bool0'] is False) self.assertTrue(config['general']['bool1'] is True) self.assertTrue(config['general']['boolnone'] is None) self.assertEqual(config['ga_params']['config_save_name'], 'config.json') self.assertEqual(config['ga_params']['pop_save_name'], 'population.json') self.assertEqual(config['ga_params']['save_frequency'], 0)
import cProfile import unittest import numpy as np import numpy.testing as npt import matplotlib.pyplot as plt from matplotlib import style import json import sys sys.path.append('.') from gastop import GenAlg, Truss, Evaluator, FitnessFunction, utilities # Parse input paramters from init.txt file init_file_path = 'gastop-config/struct_making_test_init.txt' config = utilities.init_file_parser(init_file_path) ga_params = config['ga_params'] random_params = config['random_params'] crossover_params = config['crossover_params'] mutator_params = config['mutator_params'] selector_params = config['selector_params'] evaluator_params = config['evaluator_params'] fitness_params = config['fitness_params'] # properties_df = 0 evaluator = 0 pop_size = int(1e6) num_gens = int(1e2)