SHARE
TWEET

Untitled

a guest Jan 20th, 2020 71 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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}')
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top