Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from math import copysign, fabs, floor, isfinite, modf, cos, trunc
- import numpy as np
- import random
- def function(x):
- 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)
- # Перевод вещественного числа в двоичную СС
- def float_to_bin(f):
- sign = '-' * (copysign(1.0, f) < 0)
- frac, fint = modf(fabs(f)) # split on fractional, integer parts
- n, d = frac.as_integer_ratio() # frac = numerator / denominator
- assert d & (d - 1) == 0 # power of two
- return f'{sign}{floor(fint):b}.{n:0{d.bit_length() - 1}b}'
- # Перевод двоичного вещественного числа в десятичную СС
- def bin_to_float(f):
- p = f.split(".")
- # Переводим целую часть в 10ую СС пока без знака
- int_part = int(p[0][1:])
- real_part = 0
- # Стандартный перевод в 10ую СС дробной части
- for i in range(len(p[1])):
- if p[1][i] == '1':
- real_part += pow(2, -(i + 1))
- # Если 1ый бит в целой части 1, значит отриц число
- if p[0][0] == '1':
- return f'-{int_part + real_part}'
- else:
- return f'{int_part + real_part}'
- def first_population(interval, size_population):
- p = []
- i = interval[0]
- step = abs(interval[0] - interval[1]) / size_population
- while i < interval[1]:
- p.append(round(i, 4))
- i += step
- # random.shuffle(p)
- return p
- # Чтобы кол-во бит в целой и дробной части было одинаково для каждого числа
- def normalize(f, len_int):
- # Разбиваем на целую и дробную
- temp = f.split('.')
- # Дополняем 0 целую часть
- temp[0] = temp[0].zfill(len_int)
- # Если число отриц., то в бит знака записываем 1
- if temp[0][0] == '-':
- temp[0] = '1' + temp[0][1:]
- if len(temp[1]) < 8:
- while len(temp[1]) < 16:
- temp[1] = str(temp[1]) + '0'
- else:
- temp[1] = temp[1][:16]
- return temp[0] + '.' + temp[1]
- # Сколько бит нужно для целой части
- def len_int_part(interval):
- # Ищем самое большое число по модулю
- max_abs = max(interval, key=abs)
- # Переводим в 2ю СС без знака
- if max_abs < 0:
- num_byte = len(str(bin(max_abs))[3:])
- else:
- num_byte = len(str(bin(max_abs))[2:])
- # Возвращаем длину в 2ой СС + бит для знака и длина должна быть четна
- if num_byte % 2 == 0:
- return num_byte + 2
- else:
- return num_byte + 1
- # Выбираем рандомный ген и меняем его на противоположный
- def simp_mutation(child):
- gen_mut = random.randint(0, len(child))
- gen_child = ""
- for i in range(len(child)):
- if i == gen_mut:
- if child[i] == '1':
- gen_child += '0'
- elif child[i] == '0':
- gen_child += '1'
- else:
- gen_child += '.'
- else:
- gen_child += child[i]
- return gen_child
- # Меняем каждый ген на противоположный
- def reverse_mutation(child):
- gen_child = ""
- for i in range(len(child)):
- if child[i] == '1':
- gen_child += '0'
- elif child[i] == '0':
- gen_child += '1'
- else:
- gen_child += '.'
- return gen_child
- # Выбираем рандомную точку для скрещивания и создаем 2 потомка
- def createChildOnePoint(parent1, parent2, mutation):
- parent1 = parent1.split('.')
- parent2 = parent2.split('.')
- len_int = len(parent1[0])
- len_real = len(parent1[1])
- point_real = random.randint(1, len_real - 1)
- child = [0, 0]
- # Берем сначала левую часть до точки первого родителя и правую второго
- child[0] = parent1[0][:len_int] + parent2[0][len_int:] + '.' + \
- parent1[1][:point_real] + parent2[1][point_real:]
- # Теперь наоборот
- child[1] = parent2[0][:len_int] + parent1[0][len_int:] + '.' + \
- parent2[1][:point_real] + parent1[1][point_real:]
- for elem in child:
- if decisionMut(mutation):
- simp_mutation(elem)
- return child
- def createChildTwoPoint(parent1, parent2, mutation):
- parent1 = parent1.split('.')
- parent2 = parent2.split('.')
- len_int = len(parent1[0])
- len_real = len(parent1[1])
- point_real1 = random.randint(1, len_real - 1)
- point_real2 = random.randint(1, len_real - 1)
- while point_real2 == point_real1:
- point_real2 = random.randint(1, len_real - 1)
- child = [0, 0]
- child[0] = parent1[0][:len_int] + parent2[0][len_int:] + '.' + \
- parent1[1][:point_real1] + parent2[1][point_real1:point_real2] + parent1[1][point_real2:]
- child[1] = parent2[0][:len_int] + parent1[0][len_int:] + '.' + \
- parent2[1][:point_real1] + parent1[1][point_real1:point_real2] + parent2[1][point_real2:]
- for elem in child:
- if decisionMut(mutation):
- elem = simp_mutation(elem)
- return child
- # Вернет True, если мутация у потомка должна быть
- def decisionMut(mutation):
- mut = random.random()
- return True if mut < mutation else False
- def createChild(popul, count_child, mutation):
- count = count_child
- while count != 0:
- parent1 = random.randint(0, size_population - 1)
- parent2 = random.randint(0, size_population - 1)
- child = createChildTwoPoint(popul[parent1], popul[parent2], mutation)
- popul.append(child[0])
- popul.append(child[1])
- count -= 2
- def selection(popul, size_population):
- select_popul = []
- d = {popul[a]: function(float(bin_to_float(popul[a]))) for a in range(len(popul))}
- list_d = list(d.items())
- list_d.sort(key=lambda i: i[1])
- for i in range(size_population):
- select_popul.append(list_d[i][0])
- return select_popul
- def check(best_individ, accuracy):
- best = float(bin_to_float(best_individ))
- if abs(function(best)) <= accuracy:
- print(f'{best} - {function(best)}')
- return False
- else:
- return True
- interval = [-1, 1]
- size_population = 100
- mutation = 0.5
- count_child = 100
- accuary = 0.1527
- len_int = len_int_part(interval)
- popul = first_population(interval, size_population)
- for i in range(len(popul)):
- popul[i] = float_to_bin(popul[i])
- popul[i] = normalize(str(popul[i]), len_int)
- k = 0
- flag = True
- while flag:
- k += 1
- createChild(popul, count_child, mutation)
- popul = selection(popul, size_population)
- flag = check(popul[0], accuary)
- print(f'Точка: {bin_to_float(popul[0])}\nЗначение функции: {function(float(bin_to_float(popul[0])))}'
- f'\nДвоичный код точки: {popul[0]}')
- print(f'Количество эпох: {k}')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement