我试图为一个生物模拟器创建一个非常简单的进化算法,我想要的是,这两种生物都有一个特性和一个优势水平,都是由国家统计局注意到的。他们的孩子的特征将是一个随机数之间的生物A和生物的特征,然后倾斜到更占优势的。因此,如果A的性状为5,优势为2,B为10,优势为7,则偏斜为-5,因此它更倾向于B。他们的孩子更可能有8而不是6。有什么好的方法可以做到这一点呢?我把它想象成这样:A5-6--7--8-9-10B
在我能够测试结果之前,我不知道这个斜率应该有多大,所以暂时它是任意的。
谢谢大家抽出时间来帮助我。
发布于 2013-03-07 23:21:40
我的解决方案会让你更倾向于更大的优势差异:
它使用的事实是,将一个值在0到1之间提高到一个正幂会使结果在相同的范围内倾斜。
如你所愿,设置微调。
import random
a_trait = 5
a_dominance = 2
b_trait = 10
b_dominance = 7
target = random.random()
skew = abs(a_dominance - b_dominance) + 1
fine_tuning_multiplier = 0.3
skewed_target = target ** (skew * fine_tuning_multiplier)
trait_delta = abs(a_trait - b_trait)
target_trait = trait_delta * (1 - skewed_target)
if a_dominance > b_dominance:
val = b_trait - target_trait
else:
val = a_trait + target_trait
print "val:", int(round(val))请注意,在此解决方案中,必须对特征进行排序。(即a_trait < b_trait)
连续40次跑步,结果是:
8 8 9 8 9 10 6 7 7 10 8 8 9 9 10 9 9 7 10 6 10 7 10 9 10 10 7 8 8 7 10 5 6 6 9 9 10 10 6 6
发布于 2013-03-07 21:23:25
当然,这很简单。
只需取两个主导值之和,并取这些值的random.randrange()值。
如果该值低于父本A的优势值,则您选择了该父母亲的性状,否则它就是您选择的父本B的性状:
import random
if random.randrange(parentA.dominance + parentB.dominance) < parentA.dominance:
trait = parentA.trait
else:
trait = parentB.trait换句话说,这是两个选项之间非常简单的加权随机选择。
对于您的具体示例,优势的总和为9,因此randrange()值为0到8之间的值;如果选择0或1,则选择父A的特征,如果选择2、3、4、5、6、7或8,则选择父B的特征。
如果你说的是从父母A的特征值到父母B的特征值,然后将特征作为一个范围来处理,那么你的优势值就会被用来“拉”一个或另一个父母的性状值。
基本上可以归结为父母之间的拔河。在平衡优势的情况下,平均而言,选择的性状可以归结为这两个性状的平均值。但是,当父母一方主宰另一方时,特质价值就会选择“转移”给占主导地位的父母。
这意味着,中点以下的值是为父A有机会在(parentA.dominance + parentB.dominance)中选择的,而中点以上的值有可能被选择为parentB.dominance in (parentA.dominance + parentB.dominance)。
import random
pick = random.random()
# sort parents by trait; smallest trait first
parents = sorted((parentA, parentB), key=attrgetter('trait'))
average = (parents[0].trait + parents[1].trait) / 2.0
weights = []
slots = (parents[1].trait - parents[0].trait + 1.0) * (parents[0].dominance + parents[1].dominance)
for i in range(parents[0].trait, parents[1].trait + 1):
if i <= average:
weights.append(sum(weights) + (parents[0].dominance / slots))
else:
weights.append(sum(weights) + (parents[1].dominance / slots))
if weights[-1] > pick:
return i利用上面的计算,在父母A和父母B之间进行快速的特征选择:
>>> for i in range(40): print pickTrait(),
...
9 9 9 10 6 9 8 10 7 9 9 8 8 8 9 8 9 9 7 5 8 8 9 5 9 9 10 10 10 10 5 5 9 9 8 9 10 7 8 9发布于 2013-03-07 22:15:38
据我所见,您需要一个加权随机选择,来自range(parent_a.trait, parent_b.trait)。
要线性地分配权重,最简单的方法是构造一个浮动范围,使范围的sum()为1.0,而每一步都表示选择这一步的概率。
示例:
trait_delta = abs(pacent_a.trait - trait_b.trait)
trait_delta_sum = trait_delta * (trait_delta+1.) / 2.
weights = [x/trait_delta_sum for x in range(1, trait_delta+1)]正如我前面所说,权重之和应等于1:
assert sum(weights) == 1.然后生成权重的累积和:
cumulative_weihts = [sum(weights[:x]) for x in range(trait_delta)]现在只需选择一个随机数,并找到比所述随机数小的最大数的索引:
rand = random.random()
shift = sum[-1 for x in cumulative_weightn if r<x])最后,将倾斜作为与具有较大优势的性状的抵消:
if parent_a.dominance > parent_b.dominance:
trait = parent_a.dominance + skew
else:
trait = parent_b.dominance + skewhttps://softwareengineering.stackexchange.com/questions/189663
复制相似问题