def __init__(self, natoms, minimiser, composition="default", labels=("X", ), pop_size=10, max_generation=10, selector=TournamentSelector(3), offspring=8, mutant_rate=0.1, remove_duplicates=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring = offspring self.pop_size = pop_size self.remove_duplicates = remove_duplicates self.selector = selector self.mutator = mutator self.crossover = crossover #Factory self.factory = ClusterFactory(natoms, minimiser, composition, labels) #PopulationList self.population = PopulationList(natoms, self.factory, pop_size) #Evolutionary progress self.mean_energy_series = [] self.min_energy_series = [] self.db = Database(db="mydatabase.sqlite") self.storage = self.db.minimum_adder()
def setUp(self): natoms = 10 minimiser = PeleMinimiser(lj.LJ()) factory = ClusterFactory(natoms, minimiser) self.population = PopulationList(natoms, factory, max_size=5) while len(self.population) < self.population.max_size: self.population.append(factory.get_random_cluster())
def test_population(self): natoms=3 minimiser=PeleMinimiser(LJCluster(natoms)) factory=ClusterFactory(natoms,minimiser) with open("restart.xyz",'r') as xyz_file: population=PopulationList(natoms,factory) population.read_xyz(xyz_file) self.assertEquals(-5.,population[0].get_energy()) self.assertEquals(-4.,population[1].get_energy())
def test_population(self): natoms = 3 minimiser = PeleMinimiser(LJCluster(natoms)) factory = ClusterFactory(natoms, minimiser) with open("restart.xyz", "r") as xyz_file: population = PopulationList(natoms, factory) population.read_xyz(xyz_file) self.assertEquals(-5.0, population[0].get_energy()) self.assertEquals(-4.0, population[1].get_energy())
def __init__(self,natoms,minimiser, composition="default",labels=("X",), pop_size=10,max_generation=10, selector=TournamentSelector(3), offspring=8,mutant_rate=0.1,remove_duplicates=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring=offspring self.pop_size=pop_size self.remove_duplicates=remove_duplicates self.selector=selector self.mutator = mutator self.crossover = crossover #Factory self.factory=ClusterFactory(natoms,minimiser,composition,labels) #PopulationList self.population = PopulationList(natoms,self.factory,pop_size) #Evolutionary progress self.mean_energy_series=[] self.min_energy_series=[] self.db = Database(db="mydatabase.sqlite") self.storage = self.db.minimum_adder()
def setUp(self): natoms=10 minimiser=PeleMinimiser(lj.LJ()) factory=ClusterFactory(natoms,minimiser) self.population=PopulationList(natoms,factory,max_size=5) while len(self.population) < self.population.max_size: self.population.append(factory.get_random_cluster())
def __init__(self, natoms, minimiser, composition="default", labels=("X", ), pop_size=10, max_generation=10, selector=TournamentSelector(3), offspring=8, mutant_rate=0.1, remove_duplicates=False, mass_extinction=False, epoch_thresh=1.e-6, restart=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring = offspring self.pop_size = pop_size self.remove_duplicates = remove_duplicates self.mass_extinction = mass_extinction self.epoch_thresh = epoch_thresh self.selector = selector self.mutator = mutator self.crossover = crossover #Factory self.factory = ClusterFactory(natoms, minimiser, composition, labels) #PopulationList self.population = PopulationList(natoms, self.factory, pop_size) if restart is False: while len(self.population) < self.population.max_size: self.population.append(self.factory.get_random_cluster()) self.population.sort_energy() else: with open("restart.xyz", 'r') as xyz_file: self.population.read_xyz(xyz_file) #Evolutionary progress self.mean_energy_series = [] self.mean_energy_series.append(self.population.get_mean_energy()) self.min_energy_series = [] self.min_energy_series.append(self.population.get_lowest_energy())
class ClusterTest(unittest.TestCase): def setUp(self): natoms = 10 minimiser = PeleMinimiser(lj.LJ()) factory = ClusterFactory(natoms, minimiser) self.population = PopulationList(natoms, factory, max_size=5) while len(self.population) < self.population.max_size: self.population.append(factory.get_random_cluster()) self.population.sort_energy() def test_tournament(self): selector = TournamentSelector(3) pair = selector.select(self.population) self.assertEquals(len(pair), 2) self.assertNotEqual(pair[0], pair[1]) def test_roulette(self): selector = RouletteSelector() for _ in range(0, 50): # Repeat for several random selections pair = selector.select(self.population) self.assertEquals(len(pair), 2) self.assertNotEqual(pair[0], pair[1])
class ClusterTest(unittest.TestCase): def setUp(self): natoms = 10 minimiser = PeleMinimiser(lj.LJ()) factory = ClusterFactory(natoms, minimiser) self.population = PopulationList(natoms, factory, max_size=5) while len(self.population) < self.population.max_size: self.population.append(factory.get_random_cluster()) self.population.sort_energy() def test_tournament(self): selector = TournamentSelector(3) pair = selector.select(self.population) self.assertEquals(len(pair), 2) self.assertNotEqual(pair[0], pair[1]) def test_roulette(self): selector = RouletteSelector() for _ in range(0, 50): #Repeat for several random selections pair = selector.select(self.population) self.assertEquals(len(pair), 2) self.assertNotEqual(pair[0], pair[1])
class ClusterTest(unittest.TestCase): def setUp(self): natoms=10 minimiser=PeleMinimiser(lj.LJ()) factory=ClusterFactory(natoms,minimiser) self.population=PopulationList(natoms,factory,max_size=5) while len(self.population) < self.population.max_size: self.population.append(factory.get_random_cluster()) def test_energy_sort(self): self.population.sort_energy() for i in range(1,self.population.max_size): self.assertGreater(self.population.get_energy(i), self.population.get_energy(i-1))
class ClusterTest(unittest.TestCase): def setUp(self): natoms = 10 minimiser = PeleMinimiser(lj.LJ()) factory = ClusterFactory(natoms, minimiser) self.population = PopulationList(natoms, factory, max_size=5) while len(self.population) < self.population.max_size: self.population.append(factory.get_random_cluster()) def test_energy_sort(self): self.population.sort_energy() for i in range(1, self.population.max_size): self.assertGreater(self.population.get_energy(i), self.population.get_energy(i - 1))
def __init__(self,natoms,minimiser, composition="default",labels=("X",), pop_size=10,max_generation=10, selector=TournamentSelector(3), offspring=8,mutant_rate=0.1,remove_duplicates=False, mass_extinction=False,epoch_thresh=1.e-6, restart=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring=offspring self.pop_size=pop_size self.remove_duplicates=remove_duplicates self.mass_extinction=mass_extinction self.epoch_thresh=epoch_thresh self.selector=selector self.mutator = mutator self.crossover = crossover #Factory self.factory=ClusterFactory(natoms,minimiser,composition,labels) #PopulationList self.population = PopulationList(natoms,self.factory,pop_size) if restart is False: while len(self.population) < self.population.max_size: self.population.append(self.factory.get_random_cluster()) self.population.sort_energy() else: with open("restart.xyz",'r') as xyz_file: self.population.read_xyz(xyz_file) #Evolutionary progress self.mean_energy_series=[] self.mean_energy_series.append(self.population.get_mean_energy()) self.min_energy_series=[] self.min_energy_series.append(self.population.get_lowest_energy())
class BatchGeneticAlgorithm(object): '''The Birmingham Cluster Genetic Algorithm. A new parallel version of the BCGA. The population is stored in a pele database and can be accessed by several processes simultaneously. Parameters: natoms- Number of atoms in cluster minimiser- See bcga.gpaw_interface Optional parameters: composition- A list containing the number of atoms of each type labels- A tuple orblist containing the names of each atom type (e.g. ["Au","Ag"] pop_size- Number of clusters in population max_generation- Number of generations to run GA selector- Selection method for choosing parents (see bcga.selector) offspring- Number of crossover operations in each generation mutant_rate- Probability of any cluster producing a mutant remove_duplicates- Remove identical clusters from population to prevent stagnation restart- Read population from restart.xyz and continue a search ''' def __init__(self,natoms,minimiser, composition="default",labels=("X",), pop_size=10,max_generation=10, selector=TournamentSelector(3), offspring=8,mutant_rate=0.1,remove_duplicates=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring=offspring self.pop_size=pop_size self.remove_duplicates=remove_duplicates self.selector=selector self.mutator = mutator self.crossover = crossover #Factory self.factory=ClusterFactory(natoms,minimiser,composition,labels) #PopulationList self.population = PopulationList(natoms,self.factory,pop_size) #Evolutionary progress self.mean_energy_series=[] self.min_energy_series=[] self.db = Database(db="mydatabase.sqlite") self.storage = self.db.minimum_adder() def write_xyz(self,file_name="cluster.xyz"): '''Open an xyz file and write the current population to it (non-blocking).''' try: with open(file_name,'w') as xyz_file: self.population.write_xyz(xyz_file) except IOError as err: print("File error: "+str(err)) def read_xyz(self,file_name="restart.xyz"): '''Read population from an xyz file (non-blocking for now).''' self.population.mass_extinction(0) try: with open(file_name) as xyz_file: self.population.read_xyz(xyz_file) except: print("No restart file available.") def run(self): '''Run the GA.''' for generation in range(1,self.max_generation+1): print ("Generation "+str(generation)) if self.db.number_of_minima() < self.population.max_size: cluster=self.factory.get_random_cluster() print("Filling population with random structure.") else: self.population.read_db(self.db) if np.random < self.mutant_rate: index=np.random.randint(0,len(self.population)) cluster=self.mutator.get_mutant(self.population[index]) print("Generating mutant of cluster "+str(index)) else: indices = self.selector.select(self.population) cluster=self.crossover.get_offspring(self.population[indices[0]], self.population[indices[1]]) print("Generating offpsring of clusters "+str(indices[0])+" and "+str(indices[1])) cluster.minimise() #self.read_xyz("restart.xyz") #self.population.append(cluster) self.storage(cluster.energy,cluster._coords.flatten())
class GeneticAlgorithm(object): '''The Birmingham Cluster Genetic Algorithm. This is based on the original serial version of the BCGA. Parameters: natoms- Number of atoms in cluster minimiser- See bcga.gpaw_interface Optional parameters: composition- A tuple or list containing the number of atoms of each type (e.g. ["Au","Ag"]) labels- A list containing the names of each atom type pop_size- Number of clusters in population max_generation- Number of generations to run GA selector- Selection method for choosing parents (see bcga.selector) offspring- Number of crossover operations in each generation mutant_rate- Probability of any cluster producing a mutant remove_duplicates- Remove identical clusters from population to prevent stagnation mass_extinction- Re-set population if population stagnates epoch_threshold- Mean population energy change that initiates mass extinction restart- Read population from restart.xyz and continue a search ''' def __init__(self,natoms,minimiser, composition="default",labels=("X",), pop_size=10,max_generation=10, selector=TournamentSelector(3), offspring=8,mutant_rate=0.1,remove_duplicates=False, mass_extinction=False,epoch_thresh=1.e-6, restart=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring=offspring self.pop_size=pop_size self.remove_duplicates=remove_duplicates self.mass_extinction=mass_extinction self.epoch_thresh=epoch_thresh self.selector=selector self.mutator = mutator self.crossover = crossover #Factory self.factory=ClusterFactory(natoms,minimiser,composition,labels) #PopulationList self.population = PopulationList(natoms,self.factory,pop_size) if restart is False: while len(self.population) < self.population.max_size: self.population.append(self.factory.get_random_cluster()) self.population.sort_energy() else: with open("restart.xyz",'r') as xyz_file: self.population.read_xyz(xyz_file) #Evolutionary progress self.mean_energy_series=[] self.mean_energy_series.append(self.population.get_mean_energy()) self.min_energy_series=[] self.min_energy_series.append(self.population.get_lowest_energy()) def make_offspring(self): '''Add offspring clusters to population''' for i in range(0, self.offspring): indices = self.selector.select(self.population) mycluster=self.crossover.get_offspring(self.population[indices[0]], self.population[indices[1]]) self.population.append(mycluster) def make_mutants(self): '''Add mutant clusters to population''' for mycluster in self.population: if np.random.uniform(0, 1) < self.mutant_rate: self.population.append(self.mutator.get_mutant(mycluster)) def write_xyz(self,filename="cluster.xyz"): '''Open an xyz file and write the current population to it''' try: with open(filename,'w') as xyz_file: self.population.write_xyz(xyz_file) except IOError as err: print("File error: "+str(err)) def run(self): '''Run the GA.''' for generation in range(1,self.max_generation+1): print ("Generation "+str(generation)) self.make_offspring() self.make_mutants() if self.remove_duplicates: self.population.remove_duplicates() self.population.truncate() #Update time series self.mean_energy_series.append(self.population.get_mean_energy()) self.min_energy_series.append(self.population.get_lowest_energy()) print("Lowest energy: "+str(self.population.get_lowest_energy())+" Mean energy: "+str(self.population.get_mean_energy())) if self.mass_extinction: diff = self.mean_energy_series[-2]-self.mean_energy_series[-1] if 0 < diff < self.epoch_thresh: print("New epoch. Energy change = "+str(diff)) self.population.mass_extinction() while len(self.population) < self.population.max_size: self.population.append(self.factory.get_random_cluster()) self.population.sort_energy() self.write_xyz("restart.xyz")
class BatchGeneticAlgorithm(object): '''The Birmingham Cluster Genetic Algorithm. A new parallel version of the BCGA. The population is stored in a pele database and can be accessed by several processes simultaneously. Parameters: natoms- Number of atoms in cluster minimiser- See bcga.gpaw_interface Optional parameters: composition- A list containing the number of atoms of each type labels- A tuple orblist containing the names of each atom type (e.g. ["Au","Ag"] pop_size- Number of clusters in population max_generation- Number of generations to run GA selector- Selection method for choosing parents (see bcga.selector) offspring- Number of crossover operations in each generation mutant_rate- Probability of any cluster producing a mutant remove_duplicates- Remove identical clusters from population to prevent stagnation restart- Read population from restart.xyz and continue a search ''' def __init__(self, natoms, minimiser, composition="default", labels=("X", ), pop_size=10, max_generation=10, selector=TournamentSelector(3), offspring=8, mutant_rate=0.1, remove_duplicates=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring = offspring self.pop_size = pop_size self.remove_duplicates = remove_duplicates self.selector = selector self.mutator = mutator self.crossover = crossover #Factory self.factory = ClusterFactory(natoms, minimiser, composition, labels) #PopulationList self.population = PopulationList(natoms, self.factory, pop_size) #Evolutionary progress self.mean_energy_series = [] self.min_energy_series = [] self.db = Database(db="mydatabase.sqlite") self.storage = self.db.minimum_adder() def write_xyz(self, file_name="cluster.xyz"): '''Open an xyz file and write the current population to it (non-blocking).''' try: with open(file_name, 'w') as xyz_file: self.population.write_xyz(xyz_file) except IOError as err: print("File error: " + str(err)) def read_xyz(self, file_name="restart.xyz"): '''Read population from an xyz file (non-blocking for now).''' self.population.mass_extinction(0) try: with open(file_name) as xyz_file: self.population.read_xyz(xyz_file) except: print("No restart file available.") def run(self): '''Run the GA.''' for generation in range(1, self.max_generation + 1): print("Generation " + str(generation)) if self.db.number_of_minima() < self.population.max_size: cluster = self.factory.get_random_cluster() print("Filling population with random structure.") else: self.population.read_db(self.db) if np.random < self.mutant_rate: index = np.random.randint(0, len(self.population)) cluster = self.mutator.get_mutant(self.population[index]) print("Generating mutant of cluster " + str(index)) else: indices = self.selector.select(self.population) cluster = self.crossover.get_offspring( self.population[indices[0]], self.population[indices[1]]) print("Generating offpsring of clusters " + str(indices[0]) + " and " + str(indices[1])) cluster.minimise() #self.read_xyz("restart.xyz") #self.population.append(cluster) self.storage(cluster.energy, cluster._coords.flatten())
class GeneticAlgorithm(object): '''The Birmingham Cluster Genetic Algorithm. This is based on the original serial version of the BCGA. Parameters: natoms- Number of atoms in cluster minimiser- See bcga.gpaw_interface Optional parameters: composition- A tuple or list containing the number of atoms of each type (e.g. ["Au","Ag"]) labels- A list containing the names of each atom type pop_size- Number of clusters in population max_generation- Number of generations to run GA selector- Selection method for choosing parents (see bcga.selector) offspring- Number of crossover operations in each generation mutant_rate- Probability of any cluster producing a mutant remove_duplicates- Remove identical clusters from population to prevent stagnation mass_extinction- Re-set population if population stagnates epoch_threshold- Mean population energy change that initiates mass extinction restart- Read population from restart.xyz and continue a search ''' def __init__(self, natoms, minimiser, composition="default", labels=("X", ), pop_size=10, max_generation=10, selector=TournamentSelector(3), offspring=8, mutant_rate=0.1, remove_duplicates=False, mass_extinction=False, epoch_thresh=1.e-6, restart=False, mutator=MutateReplace(), crossover=DeavenHo()): #Parameters self.max_generation = max_generation self.mutant_rate = mutant_rate self.offspring = offspring self.pop_size = pop_size self.remove_duplicates = remove_duplicates self.mass_extinction = mass_extinction self.epoch_thresh = epoch_thresh self.selector = selector self.mutator = mutator self.crossover = crossover #Factory self.factory = ClusterFactory(natoms, minimiser, composition, labels) #PopulationList self.population = PopulationList(natoms, self.factory, pop_size) if restart is False: while len(self.population) < self.population.max_size: self.population.append(self.factory.get_random_cluster()) self.population.sort_energy() else: with open("restart.xyz", 'r') as xyz_file: self.population.read_xyz(xyz_file) #Evolutionary progress self.mean_energy_series = [] self.mean_energy_series.append(self.population.get_mean_energy()) self.min_energy_series = [] self.min_energy_series.append(self.population.get_lowest_energy()) def make_offspring(self): '''Add offspring clusters to population''' for i in range(0, self.offspring): indices = self.selector.select(self.population) mycluster = self.crossover.get_offspring( self.population[indices[0]], self.population[indices[1]]) self.population.append(mycluster) def make_mutants(self): '''Add mutant clusters to population''' for mycluster in self.population: if np.random.uniform(0, 1) < self.mutant_rate: self.population.append(self.mutator.get_mutant(mycluster)) def write_xyz(self, filename="cluster.xyz"): '''Open an xyz file and write the current population to it''' try: with open(filename, 'w') as xyz_file: self.population.write_xyz(xyz_file) except IOError as err: print("File error: " + str(err)) def run(self): '''Run the GA.''' for generation in range(1, self.max_generation + 1): print("Generation " + str(generation)) self.make_offspring() self.make_mutants() if self.remove_duplicates: self.population.remove_duplicates() self.population.truncate() #Update time series self.mean_energy_series.append(self.population.get_mean_energy()) self.min_energy_series.append(self.population.get_lowest_energy()) print("Lowest energy: " + str(self.population.get_lowest_energy()) + " Mean energy: " + str(self.population.get_mean_energy())) if self.mass_extinction: diff = self.mean_energy_series[-2] - self.mean_energy_series[-1] if 0 < diff < self.epoch_thresh: print("New epoch. Energy change = " + str(diff)) self.population.mass_extinction() while len(self.population) < self.population.max_size: self.population.append( self.factory.get_random_cluster()) self.population.sort_energy() self.write_xyz("restart.xyz")