Sztuczna_Inteligencja_Gr16/algorytmy_genetyczne.py

375 lines
12 KiB
Python
Raw Normal View History

2022-06-08 21:56:45 +02:00
import numpy as np
from .decay import GeomDecay
def hill_climb(problem, max_iters=np.inf, restarts=0, init_state=None,
curve=False, random_state=None):
"""
best_state array containing state that optimizes the fitness function.
best_fitness Value of fitness function at best state.
fitness_curve array containing the fitness at every iteration.
"""
if (not isinstance(max_iters, int) and max_iters != np.inf
and not max_iters.is_integer()) or (max_iters < 0):
raise Exception("""max_iters must be a positive integer.""")
if (not isinstance(restarts, int) and not restarts.is_integer()) \
or (restarts < 0):
raise Exception("""restarts must be a positive integer.""")
if init_state is not None and len(init_state) != problem.get_length():
raise Exception("""init_state must have same length as problem.""")
# Set random seed
if isinstance(random_state, int) and random_state > 0:
np.random.seed(random_state)
best_fitness = -1*np.inf
best_state = None
if curve:
fitness_curve = []
for _ in range(restarts + 1):
# Initialize optimization problem
if init_state is None:
problem.reset()
else:
problem.set_state(init_state)
iters = 0
while iters < max_iters:
iters += 1
# Find neighbors and determine best neighbor
problem.find_neighbors()
next_state = problem.best_neighbor()
next_fitness = problem.eval_fitness(next_state)
# If best neighbor is an improvement, move to that state
if next_fitness > problem.get_fitness():
problem.set_state(next_state)
else:
break
if curve:
fitness_curve.append(problem.get_fitness())
# Update best state and best fitness
if problem.get_fitness() > best_fitness:
best_fitness = problem.get_fitness()
best_state = problem.get_state()
best_fitness = problem.get_maximize()*best_fitness
if curve:
return best_state, best_fitness, np.asarray(fitness_curve)
return best_state, best_fitness
def random_hill_climb(problem, max_attempts=10, max_iters=np.inf, restarts=0,
init_state=None, curve=False, random_state=None):
if (not isinstance(max_attempts, int) and not max_attempts.is_integer()) \
or (max_attempts < 0):
raise Exception("""max_attempts must be a positive integer.""")
if (not isinstance(max_iters, int) and max_iters != np.inf
and not max_iters.is_integer()) or (max_iters < 0):
raise Exception("""max_iters must be a positive integer.""")
if (not isinstance(restarts, int) and not restarts.is_integer()) \
or (restarts < 0):
raise Exception("""restarts must be a positive integer.""")
if init_state is not None and len(init_state) != problem.get_length():
raise Exception("""init_state must have same length as problem.""")
# Set random seed
if isinstance(random_state, int) and random_state > 0:
np.random.seed(random_state)
best_fitness = -1*np.inf
best_state = None
if curve:
fitness_curve = []
for _ in range(restarts + 1):
# Initialize optimization problem and attempts counter
if init_state is None:
problem.reset()
else:
problem.set_state(init_state)
attempts = 0
iters = 0
while (attempts < max_attempts) and (iters < max_iters):
iters += 1
# Find random neighbor and evaluate fitness
next_state = problem.random_neighbor()
next_fitness = problem.eval_fitness(next_state)
# If best neighbor is an improvement,
# move to that state and reset attempts counter
if next_fitness > problem.get_fitness():
problem.set_state(next_state)
attempts = 0
else:
attempts += 1
if curve:
fitness_curve.append(problem.get_fitness())
# Update best state and best fitness
if problem.get_fitness() > best_fitness:
best_fitness = problem.get_fitness()
best_state = problem.get_state()
best_fitness = problem.get_maximize()*best_fitness
if curve:
return best_state, best_fitness, np.asarray(fitness_curve)
return best_state, best_fitness
def simulated_annealing(problem, schedule=GeomDecay(), max_attempts=10,
max_iters=np.inf, init_state=None, curve=False,
random_state=None):
if (not isinstance(max_attempts, int) and not max_attempts.is_integer()) \
or (max_attempts < 0):
raise Exception("""max_attempts must be a positive integer.""")
if (not isinstance(max_iters, int) and max_iters != np.inf
and not max_iters.is_integer()) or (max_iters < 0):
raise Exception("""max_iters must be a positive integer.""")
if init_state is not None and len(init_state) != problem.get_length():
raise Exception("""init_state must have same length as problem.""")
# Set random seed
if isinstance(random_state, int) and random_state > 0:
np.random.seed(random_state)
# Initialize problem, time and attempts counter
if init_state is None:
problem.reset()
else:
problem.set_state(init_state)
if curve:
fitness_curve = []
attempts = 0
iters = 0
while (attempts < max_attempts) and (iters < max_iters):
temp = schedule.evaluate(iters)
iters += 1
if temp == 0:
break
else:
# Find random neighbor and evaluate fitness
next_state = problem.random_neighbor()
next_fitness = problem.eval_fitness(next_state)
# Calculate delta E and change prob
delta_e = next_fitness - problem.get_fitness()
prob = np.exp(delta_e/temp)
# If best neighbor is an improvement or random value is less
# than prob, move to that state and reset attempts counter
if (delta_e > 0) or (np.random.uniform() < prob):
problem.set_state(next_state)
attempts = 0
else:
attempts += 1
if curve:
fitness_curve.append(problem.get_fitness())
best_fitness = problem.get_maximize()*problem.get_fitness()
best_state = problem.get_state()
if curve:
return best_state, best_fitness, np.asarray(fitness_curve)
return best_state, best_fitness
def genetic_alg(problem, pop_size=200, mutation_prob=0.1, max_attempts=10,
max_iters=np.inf, curve=False, random_state=None):
if pop_size < 0:
raise Exception("""pop_size must be a positive integer.""")
elif not isinstance(pop_size, int):
if pop_size.is_integer():
pop_size = int(pop_size)
else:
raise Exception("""pop_size must be a positive integer.""")
if (mutation_prob < 0) or (mutation_prob > 1):
raise Exception("""mutation_prob must be between 0 and 1.""")
if (not isinstance(max_attempts, int) and not max_attempts.is_integer()) \
or (max_attempts < 0):
raise Exception("""max_attempts must be a positive integer.""")
if (not isinstance(max_iters, int) and max_iters != np.inf
and not max_iters.is_integer()) or (max_iters < 0):
raise Exception("""max_iters must be a positive integer.""")
# Set random seed
if isinstance(random_state, int) and random_state > 0:
np.random.seed(random_state)
if curve:
fitness_curve = []
# Initialize problem, population and attempts counter
problem.reset()
problem.random_pop(pop_size)
attempts = 0
iters = 0
while (attempts < max_attempts) and (iters < max_iters):
iters += 1
# Calculate breeding probabilities
problem.eval_mate_probs()
# Create next generation of population
next_gen = []
for _ in range(pop_size):
# Select parents
selected = np.random.choice(pop_size, size=2,
p=problem.get_mate_probs())
parent_1 = problem.get_population()[selected[0]]
parent_2 = problem.get_population()[selected[1]]
# Create offspring
child = problem.reproduce(parent_1, parent_2, mutation_prob)
next_gen.append(child)
next_gen = np.array(next_gen)
problem.set_population(next_gen)
next_state = problem.best_child()
next_fitness = problem.eval_fitness(next_state)
# If best child is an improvement,
# move to that state and reset attempts counter
if next_fitness > problem.get_fitness():
problem.set_state(next_state)
attempts = 0
else:
attempts += 1
if curve:
fitness_curve.append(problem.get_fitness())
best_fitness = problem.get_maximize()*problem.get_fitness()
best_state = problem.get_state()
if curve:
return best_state, best_fitness, np.asarray(fitness_curve)
return best_state, best_fitness
def mimic(problem, pop_size=200, keep_pct=0.2, max_attempts=10,
max_iters=np.inf, curve=False, random_state=None, fast_mimic=False):
"""Use MIMIC to find the optimum for a given optimization problem.
"""
if problem.get_prob_type() == 'continuous':
raise Exception("""problem type must be discrete or tsp.""")
if pop_size < 0:
raise Exception("""pop_size must be a positive integer.""")
elif not isinstance(pop_size, int):
if pop_size.is_integer():
pop_size = int(pop_size)
else:
raise Exception("""pop_size must be a positive integer.""")
if (keep_pct < 0) or (keep_pct > 1):
raise Exception("""keep_pct must be between 0 and 1.""")
if (not isinstance(max_attempts, int) and not max_attempts.is_integer()) \
or (max_attempts < 0):
raise Exception("""max_attempts must be a positive integer.""")
if (not isinstance(max_iters, int) and max_iters != np.inf
and not max_iters.is_integer()) or (max_iters < 0):
raise Exception("""max_iters must be a positive integer.""")
# Set random seed
if isinstance(random_state, int) and random_state > 0:
np.random.seed(random_state)
if curve:
fitness_curve = []
if fast_mimic not in (True, False):
raise Exception("""fast_mimic mode must be a boolean.""")
else:
problem.mimic_speed = fast_mimic
# Initialize problem, population and attempts counter
problem.reset()
problem.random_pop(pop_size)
attempts = 0
iters = 0
while (attempts < max_attempts) and (iters < max_iters):
iters += 1
# Get top n percent of population
problem.find_top_pct(keep_pct)
# Update probability estimates
problem.eval_node_probs()
# Generate new sample
new_sample = problem.sample_pop(pop_size)
problem.set_population(new_sample)
next_state = problem.best_child()
next_fitness = problem.eval_fitness(next_state)
# If best child is an improvement,
# move to that state and reset attempts counter
if next_fitness > problem.get_fitness():
problem.set_state(next_state)
attempts = 0
else:
attempts += 1
if curve:
fitness_curve.append(problem.get_fitness())
best_fitness = problem.get_maximize()*problem.get_fitness()
best_state = problem.get_state().astype(int)
if curve:
return best_state, best_fitness, np.asarray(fitness_curve)
return best_state, best_fitness