genetic-algorithm - How could I use a Genetic Algorithm to solve this placement optimization problem?
问题描述
I would like to use GA to solve the following problem:
- I have a white image with resolution 100*100 that has always 50 black pixels.
- I can choose which these 50 pixels could be.
- I already have a function f(image) that according to the position of these 50 black pixels, it returns a score (I do not know what the maximum score could be).
How can I find which set of 50 pixels is approximately the best one (without having to try all possible combinations)? I am new to GA and I would like to ask how should I approach/implement such an optimization?
解决方案
除了基于 50 分的简单评分之外,您是否有更多关于适应度函数性质的信息?如果不是,似乎没有任何理由通过尝试对您的编码施加更高阶的抽象来使问题复杂化。这限制了遗传算法的好处,但也大大降低了维度。下面的示例是在 Python 中。
个体只是坐标对的列表:
from random import SystemRandom
X_DIMENSION = 100
Y_DIMENSION = 100
N_PIXELS = 50
rng = SystemRandom()
def create_individual():
return [
(rng.randrange(X_DIMENSION), rng.randrange(Y_DIMENSION))
for i in range(N_PIXELS)
]
一个简单的交叉可以实现为两个个体的直接拼接和连接。
def crossover(a, b):
location = rng.randrange(1, N_PIXELS - 1)
return a[:location] + b[location:], b[:location] + a[location:]
这是另一个随机的幼稚实现,这次是为了变异。它只是用新坐标随机替换坐标。请记住,LOCATION_MUTATION_RATE 只是这种突变方法的产物,而不是一般个体的实际突变率(请参阅 MUTATION_RATE)。
LOCATION_MUTATION_RATE = .1
def mutate(a):
for i in range(N_PIXELS):
if rng.random() < LOCATION_MUTATION_RATE:
a[i] = (rng.randrange(X_DIMENSION), rng.randrange(Y_DIMENSION))
以下是最终实现的大致轮廓。这里的一些功能显然被省略了,但你可以得到要点。
POPULATION_SIZE = 10000
SELECTION_RATE = .8
CROSSOVER_RATE = .2
MUTATION_RATE = .03
def main():
population = [create_individual() for i in range(POPULATION_SIZE)]
normalized_fitnesses = normalize_fitnesses(calc_fitnesses(population))
print_stats(normalized_fitnesses)
while not completion_condition(normalized_fitnesses):
select(zip(population, normalized_fitnesses))
replace_dead(population)
crossover_all(population)
mutate_all(population)
normalized_fitnesses = normalize_fitnesses(calc_fitnesses(population))
print_stats(normalized_fitnesses)
def calc_fitnesses(population):
return [calc_fitness(individual) for individual in population]
编辑:
在了解到应用程序是射频传播之后,我想说唯一需要的大改变是变异函数绝对应该只是随机移动坐标而不是生成新点(因为选择已经完成了这一点)。假设某种渐变,它通常也可能更好。下面是一个基于 x 和 y 维度使用不同移动量的示例。它可能不直观,但想象一下,如果您使用的是 20 x 1000 或类似的东西。此外,我个人会在基本量 (MUTATION_MOVEMENT_FACTOR) 之外添加另一个因素,以根据个人相对于其他人的表现有多差(因此归一化的适应度)来增加运动量。
import math
LOCATION_MUTATION_RATE = .3
MUTATION_MOVEMENT_FACTOR = .05
MOVEMENT_X = math.ceil(X_DIMENSION * MUTATION_MOVEMENT_FACTOR)
MOVEMENT_Y = math.ceil(Y_DIMENSION * MUTATION_MOVEMENT_FACTOR)
def mutate(a):
for i in range(N_PIXELS):
if rng.random() < LOCATION_MUTATION_RATE:
a[i][0] += rng.randrange(-MOVEMENT_X, MOVEMENT_X)
a[i][1] += rng.randrange(-MOVEMENT_Y, MOVEMENT_Y)
考虑到这是射频传播,您可能可以在执行遗传操作后进行一些优化以避免浪费计算时间。将显然太靠近的点合并为一个点(平均),然后生成一个新点。
推荐阅读
- c++ - 使用 SDL2 时,'' 的左侧必须有类/结构/联合
- python - python中的Tkinter - 未找到
- python - 如何使 dockerized Flask 应用程序将输出写入文件?
- javascript - 如何从 NodeJS 连接到 PostgreSQL
- laravel - Laravel - 从控制器中的多个字段计算最小值
- html - 在 mvc razor 上的 href 中解析错误“/@”
- php - 如果用户的时区使用 PHP 更改,如何处理存储在数据库中的用户数据
- docker - Kibana Docker“这可能需要几分钟”但从不启动
- arrays - 将数组存储在数据库 Wordpress 中
- javascript - Javascript - 将分隔文本拆分为列