Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.22 KB | None | 0 0
  1. from math import copysign, fabs, floor, isfinite, modf, cos, trunc
  2. import numpy as np
  3. import random
  4.  
  5.  
  6. def function(x):
  7.     return 1 - 0.5 * cos(1.5 * (10 * x - 0.3)) * cos(31.4 * x) + 0.5 * cos(pow(5, 0.5) * 10 * x) * cos(35 * x)
  8.  
  9.  
  10. # Перевод вещественного числа в двоичную СС
  11. def float_to_bin(f):
  12.     sign = '-' * (copysign(1.0, f) < 0)
  13.     frac, fint = modf(fabs(f))  # split on fractional, integer parts
  14.     n, d = frac.as_integer_ratio()  # frac = numerator / denominator
  15.     assert d & (d - 1) == 0  # power of two
  16.     return f'{sign}{floor(fint):b}.{n:0{d.bit_length() - 1}b}'
  17.  
  18.  
  19. # Перевод двоичного вещественного числа в десятичную СС
  20. def bin_to_float(f):
  21.     p = f.split(".")
  22.     # Переводим целую часть в 10ую СС пока без знака
  23.     int_part = int(p[0][1:])
  24.     real_part = 0
  25.     # Стандартный перевод в 10ую СС дробной части
  26.     for i in range(len(p[1])):
  27.         if p[1][i] == '1':
  28.             real_part += pow(2, -(i + 1))
  29.     # Если 1ый бит в целой части 1, значит отриц число
  30.     if p[0][0] == '1':
  31.         return f'-{int_part + real_part}'
  32.     else:
  33.         return f'{int_part + real_part}'
  34.  
  35.  
  36. def first_population(interval, size_population):
  37.     p = []
  38.     i = interval[0]
  39.     step = abs(interval[0] - interval[1]) / size_population
  40.     while i < interval[1]:
  41.         p.append(round(i, 4))
  42.         i += step
  43.     # random.shuffle(p)
  44.     return p
  45.  
  46.  
  47. # Чтобы кол-во бит в целой и дробной части было одинаково для каждого числа
  48. def normalize(f, len_int):
  49.     # Разбиваем на целую и дробную
  50.     temp = f.split('.')
  51.     # Дополняем 0 целую часть
  52.     temp[0] = temp[0].zfill(len_int)
  53.     # Если число отриц., то в бит знака записываем 1
  54.     if temp[0][0] == '-':
  55.         temp[0] = '1' + temp[0][1:]
  56.     if len(temp[1]) < 8:
  57.         while len(temp[1]) < 16:
  58.             temp[1] = str(temp[1]) + '0'
  59.     else:
  60.         temp[1] = temp[1][:16]
  61.     return temp[0] + '.' + temp[1]
  62.  
  63.  
  64. # Сколько бит нужно для целой части
  65. def len_int_part(interval):
  66.     # Ищем самое большое число по модулю
  67.     max_abs = max(interval, key=abs)
  68.     # Переводим в 2ю СС без знака
  69.     if max_abs < 0:
  70.         num_byte = len(str(bin(max_abs))[3:])
  71.     else:
  72.         num_byte = len(str(bin(max_abs))[2:])
  73.     # Возвращаем длину в 2ой СС + бит для знака и длина должна быть четна
  74.     if num_byte % 2 == 0:
  75.         return num_byte + 2
  76.     else:
  77.         return num_byte + 1
  78.  
  79.  
  80. # Выбираем рандомный ген и меняем его на противоположный
  81. def simp_mutation(child):
  82.     gen_mut = random.randint(0, len(child))
  83.     gen_child = ""
  84.     for i in range(len(child)):
  85.         if i == gen_mut:
  86.             if child[i] == '1':
  87.                 gen_child += '0'
  88.             elif child[i] == '0':
  89.                 gen_child += '1'
  90.             else:
  91.                 gen_child += '.'
  92.         else:
  93.             gen_child += child[i]
  94.     return gen_child
  95.  
  96.  
  97. # Меняем каждый ген на противоположный
  98. def reverse_mutation(child):
  99.     gen_child = ""
  100.     for i in range(len(child)):
  101.         if child[i] == '1':
  102.             gen_child += '0'
  103.         elif child[i] == '0':
  104.             gen_child += '1'
  105.         else:
  106.             gen_child += '.'
  107.     return gen_child
  108.  
  109.  
  110. # Выбираем рандомную точку для скрещивания и создаем 2 потомка
  111. def createChildOnePoint(parent1, parent2, mutation):
  112.     parent1 = parent1.split('.')
  113.     parent2 = parent2.split('.')
  114.     len_int = len(parent1[0])
  115.     len_real = len(parent1[1])
  116.     point_real = random.randint(1, len_real - 1)
  117.     child = [0, 0]
  118.     # Берем сначала левую часть до точки первого родителя и правую второго
  119.     child[0] = parent1[0][:len_int] + parent2[0][len_int:] + '.' + \
  120.             parent1[1][:point_real] + parent2[1][point_real:]
  121.     # Теперь наоборот
  122.     child[1] = parent2[0][:len_int] + parent1[0][len_int:] + '.' + \
  123.             parent2[1][:point_real] + parent1[1][point_real:]
  124.     for elem in child:
  125.         if decisionMut(mutation):
  126.             simp_mutation(elem)
  127.     return child
  128.  
  129.  
  130. def createChildTwoPoint(parent1, parent2, mutation):
  131.     parent1 = parent1.split('.')
  132.     parent2 = parent2.split('.')
  133.     len_int = len(parent1[0])
  134.     len_real = len(parent1[1])
  135.     point_real1 = random.randint(1, len_real - 1)
  136.     point_real2 = random.randint(1, len_real - 1)
  137.     while point_real2 == point_real1:
  138.         point_real2 = random.randint(1, len_real - 1)
  139.     child = [0, 0]
  140.     child[0] = parent1[0][:len_int] + parent2[0][len_int:] + '.' + \
  141.                parent1[1][:point_real1] + parent2[1][point_real1:point_real2] + parent1[1][point_real2:]
  142.     child[1] = parent2[0][:len_int] + parent1[0][len_int:] + '.' + \
  143.                parent2[1][:point_real1] + parent1[1][point_real1:point_real2] + parent2[1][point_real2:]
  144.     for elem in child:
  145.         if decisionMut(mutation):
  146.             elem = simp_mutation(elem)
  147.     return child
  148.  
  149.  
  150. # Вернет True, если мутация у потомка должна быть
  151. def decisionMut(mutation):
  152.     mut = random.random()
  153.     return True if mut < mutation else False
  154.  
  155.  
  156. def createChild(popul, count_child, mutation):
  157.     count = count_child
  158.     while count != 0:
  159.         parent1 = random.randint(0, size_population - 1)
  160.         parent2 = random.randint(0, size_population - 1)
  161.         child = createChildTwoPoint(popul[parent1], popul[parent2], mutation)
  162.         popul.append(child[0])
  163.         popul.append(child[1])
  164.         count -= 2
  165.  
  166.  
  167. def selection(popul, size_population):
  168.     select_popul = []
  169.     d = {popul[a]: function(float(bin_to_float(popul[a]))) for a in range(len(popul))}
  170.     list_d = list(d.items())
  171.     list_d.sort(key=lambda i: i[1])
  172.     for i in range(size_population):
  173.         select_popul.append(list_d[i][0])
  174.     return select_popul
  175.  
  176.  
  177. def check(best_individ, accuracy):
  178.     best = float(bin_to_float(best_individ))
  179.     if abs(function(best)) <= accuracy:
  180.         print(f'{best} - {function(best)}')
  181.         return False
  182.     else:
  183.         return True
  184.  
  185.  
  186. interval = [-1, 1]
  187. size_population = 100
  188. mutation = 0.5
  189. count_child = 100
  190. accuary = 0.1527
  191.  
  192. len_int = len_int_part(interval)
  193. popul = first_population(interval, size_population)
  194.  
  195. for i in range(len(popul)):
  196.     popul[i] = float_to_bin(popul[i])
  197.     popul[i] = normalize(str(popul[i]), len_int)
  198.  
  199. k = 0
  200. flag = True
  201. while flag:
  202.     k += 1
  203.     createChild(popul, count_child, mutation)
  204.     popul = selection(popul, size_population)
  205.     flag = check(popul[0], accuary)
  206. print(f'Точка: {bin_to_float(popul[0])}\nЗначение функции: {function(float(bin_to_float(popul[0])))}'
  207.       f'\nДвоичный код точки: {popul[0]}')
  208. print(f'Количество эпох: {k}')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement