pocketpy/tests/dna2.py
blueloveTH 229a836444 up
2022-12-10 19:26:30 +08:00

186 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import random
def f(x):
if x >= 5 :
return x+5
else :
return -x+5
def create_init_DNA(min,max):
# out: DNA(['0','1',....])
ret = random.randint(min,max)
return int_to_bin(ret)
def int_to_bin(x):
# in: int_DNA(int)
# out: DNA
ret = []
if x >= 0:
ret.append(0)
else:
ret.append(1)
x = -x
for i in [32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1] :
if x>=i :
ret.append(1)
x -= i
else :
ret.append(0)
return ret
def bin_to_int(x):
# in: DNA
# out: int_DNA(int)
ret = 0
new_x = x[:]
flag = -(int(new_x[0])*2-1)
mul = 1
new_x = reversed(new_x)
new_x.pop()
for i in new_x :
ret += flag * int(i) * mul
mul *= 2
return ret
def reversed(x):
ret = []
for i in range(0,len(x)):
ret.append(x[-i-1])
return ret
def create_DNAs(num,min,max):
# in: num(int)
# out: DNAs([DNA,DNA,...])
ret = []
for i in range(num):
ret.append(create_init_DNA(min,max))
return ret
def bins_to_ints(x):
# in: DNAs
# out: int_DNAs([int,int,...])
ret = []
for i in x:
ret.append(bin_to_int(i))
return ret
def ints_to_bins(x):
# in: int_DNAs
# out: DNAs
ret = []
for i in x:
ret.append(int_to_bin(i))
return ret
def create_probabilitys(x):
# in: DNAs
# out: probabilitys([float,float...])
scores = survival_scores(x)
mid = []
ret = []
sum = 0
for i in scores:
sum+=i
for i in scores:
mid.append(1/(i+0.0/sum))
sum = 0
for i in mid:
sum+=i
for i in mid:
ret.append(i/sum)
return ret
def survival_scores(x):
# in: DNAs
# out: survival_scores[f(int_DNA),...]
ret = []
for i in x:
ret.append(f(bin_to_int(i)/100))
return ret
def choose_DNA(DNAs,probabilitys):
# in: DNAs,probabilitys
# out: choosen_DNA(DNA)
# probabilitys是由若干(01)之间的浮点数组成的数组这些浮点数的和为1
i = 0 # i记录取出元素的位置
ran = random.random()
max_sum = 0
for max in probabilitys :
max_sum += max
if i != 0 :
min_sum += probabilitys[i-1]
else :
min_sum = 0
if (ran < max_sum) and (ran >= min_sum) :
return DNAs[i]
i += 1
def mating_DNAs(DNAs,num=None):
# in: DNAs,num(int)交配组DNA数量
# out: mating_DNAs(DNAs)交配组
num = num or len(DNAs)
ret = []
for i in range(num) :
ret.append(choose_DNA(DNAs,create_probabilitys(DNAs)))
return ret
def son_DNA(DNAs):
# in: mating_DNAs(DNAs)交配组
# out: son_DNA(DNA)交叉互换后产生的子代
father = DNAs[random.randint(0,len(DNAs)-1)]
mother = DNAs[random.randint(0,len(DNAs)-1)]
pos = random.randint(0,len(DNAs[0])-1)
son_DNA = []
son_DNA += father[0:pos]
son_DNA += mother[pos+1:-1]
return son_DNA
def mutation(DNA,part_rate):
# in: son_DNA(DNA)交叉互换后的子代,part_rate(float)碱基对变异概率
# out: mut_DNA(DNA)变异后的子代
ret = DNA[:]
for i in range(len(ret)):
k = random.random()
if k < part_rate :
ret[i] = str(-int(ret[i])+1)
return ret
def next_DNAs(DNAs,father_rate,part_rate,mut_rate,num):
# in: mating_DNAs(DNAs),father_rate(float)父代保留占比,part_rate(float)碱基对突变概率,mut_rate(float)生物变异概率,num(int)下一代数量
# out: next_DNAs(DNAs)
ret = []
pro_DNAs = create_probabilitys(DNAs)
father_num = int(father_rate*num+0.5)
son_num = num - father_num
i = 1
for pro in reversed(sorted(pro_DNAs)):
if i > father_num:
break
ret.append(DNAs[pro_DNAs.index(pro)])
i += 1
for s in range(son_num):
k = random.random()
son_DNA=(mating_DNAs(DNAs)[0])
if k < mut_rate :
son_DNA = mutation(son_DNA,part_rate)
ret.append(son_DNA)
return ret
def iterate(DNAs,father_rate,part_rate,mut_rate,iter_num,population):
# in: DNAs父代,father_rate(float)每一次迭代保留父代的占比, num(int)迭代次数,population(int)种群数量
# out: DNAs子代
ret = eval(repr(DNAs))
for i in range(iter_num):
ret = next_DNAs(ret,father_rate,part_rate,mut_rate,population)
return ret
def 百分比化(a):
b = str(a*100)[0:5]
return f'{b}%'
a = create_DNAs(5,-9999,9999)