# local fitness functions f_K for K = 0, 1, 2 (Table in TP)
f = {
0: {
'0': 2,
'1': 1
},
1: {
'00': 2,
'01': 3,
'10': 2,
'11': 0
},
2: {
'000': 0,
'001': 1,
'010': 1,
'011': 0,
'100': 2,
'101': 0,
'110': 0,
'111': 0
}
} def generate_sequence(N):
# TODO
'''
generates an N random bits (0, 1) sequence
Parameters:
-----------
N : number of bits in the sequence
Returns:
--------
sequence: sequence of N bits
'''
return np.random.randint(0, 2, N)
def compute_fitness(sequence, K):
# TODO
'''
computes the fitness of sequence, with respect to K, according to table f
Parameters:
-----------
sequence : N-bits sequence
K : parameter K (0, 1, or 2)
Returns:
--------
fitness: fitness value of sequence
'''
seq = str(sequence)
N = len(seq)
fitness = 0
if K == 0:
# f0: 0->2, 1->1
for bit in seq:
fitness += 2 if bit == '0' else 1
elif K == 1:
# f1: 00->2, 01->3, 10->2, 11->0
for i in range(N):
pair = seq[i] + seq[(i+1) % N]
if pair == '00': fitness += 2
elif pair == '01': fitness += 3
elif pair == '10': fitness += 2
elif K == 2:
# f2: 000->0 001->1 010->1 011->0 100->2 101->0 110->0 111->0
for i in range(N):
triple = seq[i] + seq[(i+1) % N] + seq[(i+2) % N]
if triple == '001' or triple == '010': fitness += 1
elif triple == '100': fitness += 2
return fitness
def neighbors(sequence):
'''
returns all neighbors of sequence ()
Parameters:
-----------
sequence : N-bits sequence
Returns:
--------
generator of neighbors of sequence
'''
# generate all neighbors that differ in 1 bit
for i in range(len(sequence)):
if sequence[i] == '0':
new = '1'
else: new = '0'
yield (sequence[:i] + new + sequence[i + 1:])
def mean_steps(samples):
'''
returns mean of steps taken to find solution (for deterministic)
Parameters:
-----------
samples : samples of deterministic_hillclimb runs
Returns:
--------
mean steps
'''
# get mean of steps needed to find solution (sum of samples' steps/number of samples)
return sum(x[2] for x in samples)/len(samples)
def generate_samples(hillclimb_method, K):
'''
generates 50 samples (solutions) for the hillclimb method (deterministic/probabilistic)
Parameters:
-----------
hillclimb_method : deterministic_hillclimb/probabilistic_hillclimb
K : parameter K (0, 1, or 2)
Returns:
--------
generator of samples/solutions (sequence, fitness, number of steps)
'''
if K not in [0, 1, 2]:
raise Exception("Invalid K")
# run for 50 times to get 50 samples/solutions
for i in range(50):
# generate initial sequence
initial_sequence = generate_sequence(N=21)
# get solution, its fitness, number of steps taken to find solution
x, f_x, s = hillclimb_method(initial_sequence, K)
yield (x, f_x, s) def deterministic_hillclimb(sequence, K):
# TODO
'''
performs deterministic_hillclimb
Parameters:
-----------
sequence : N-bits sequence
K : parameter K (0, 1, or 2)
Returns:
--------
sequence : optimal/fittest sequence found
max_fitness : fitness value of sequence
steps: steps it took to reach optimum
'''
current_sequence = sequence
current_fitness = compute_fitness(current_sequence, K)
steps = 0
while True:
best_neighbor = None
best_fitness = current_fitness
for neighbor in neighbors(current_sequence):
neighbor_fitness = compute_fitness(neighbor, K)
if neighbor_fitness > best_fitness:
best_fitness = neighbor_fitness
best_neighbor = neighbor
if best_neighbor is None:
break
current_sequence = best_neighbor
current_fitness = best_fitness
steps += 1
return current_sequence, current_fitness, steps
# dictionary to save deterministic_hillclimb samples (sequence, max_fitness, steps)
deterministic_samples = {}
# dictionary to save number of steps to perform probabilistic hillclimb
probabilistic_steps = {}
# run deterministic_hillclimb, get mean steps
for K in [0, 1, 2]:
# for each K, generate 50 deterministic_hillclimb solutions, and save them
deterministic_samples[K] = list(generate_samples(deterministic_hillclimb, K))
# for each K, save the number of steps to take (10*mean steps taken for deterministic_hillclimb)
probabilistic_steps[K] = 10*round(mean_steps(deterministic_samples[K]))
def probabilistic_hillclimb(sequence, K):
# TODO
'''
performs probabilistic_hillclimb
Parameters:
-----------
sequence : N-bits sequence
K : parameter K (0, 1, or 2)
Returns:
--------
sequence : optimal/fittest sequence found
max_fitness : fitness value of sequence
steps: steps corresponding to parameter K
'''
current_sequence = sequence
current_fitness = evaluate_sequence(current_sequence, K)
steps = 0
while True:
neighbor_list = list(neighbors(current_sequence))
random.shuffle(neighbor_list)
found_better = False
for neighbor in neighbor_list:
neighbor_fitness = evaluate_sequence(neighbor, K)
if neighbor_fitness > current_fitness or random.random() < 0.1:
current_sequence = neighbor
current_fitness = neighbor_fitness
steps += 1
found_better = True
break
if not found_better:
break
return current_sequence, current_fitness, steps
# dictionary to save probabilistic_hillclimb samples (sequence, max_fitness, steps)
probabilistic_samples = {}
# run probabilistic_hillclimb
for K in [0, 1, 2]:
# for each K, generate 50 probabilistic_hillclimb solutions, and save them
probabilistic_samples[K] = list(generate_samples(probabilistic_hillclimb, K))这是我的所有代码,可以帮我修改一下吗
最新发布