Python實(shí)現(xiàn)遺傳算法(虛擬機(jī)中運(yùn)行)
(一)問(wèn)題
遺傳算法求解正方形拼圖游戲
(二)代碼
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PIL import Image, ImageDraw
import os
import gc
import random as r
import minpy.numpy as np
class Color(object):
'''
定義顏色的類(lèi),這個(gè)類(lèi)包含r,g,b,a表示顏色屬性
'''
def __init__(self):
self.r = r.randint(0, 255)
self.g = r.randint(0, 255)
self.b = r.randint(0, 255)
self.a = r.randint(95, 115)
def mutate_or_not(rate):
'''
生成隨機(jī)數(shù),判斷是否需要變異
'''
return True if rate > r.random() else False
class Triangle(object):
'''
定義三角形的類(lèi)
屬性:
ax,ay,bx,by,cx,cy:表示每個(gè)三角形三個(gè)頂點(diǎn)的坐標(biāo)
color : 表示三角形的顏色
img_t : 三角形繪制成的圖,用于合成圖片
方法:
mutate_from(self, parent): 從父代三角形變異
draw_it(self, size=(256, 256)): 繪制三角形
'''
max_mutate_rate = 0.08
mid_mutate_rate = 0.3
min_mutate_rate = 0.8
def __init__(self, size=(255, 255)):
t = r.randint(0, size[0])
self.ax = r.randint(0, size[0])
self.ay = r.randint(0, size[1])
self.bx = self.ax+t
self.by = self.ay
self.cx = self.ax+t
self.cy = self.ay-t
self.dx = self.ax
self.dy = self.ay-t
self.color = Color()
self.img_t = None
def mutate_from(self, parent):
if mutate_or_not(self.max_mutate_rate):
t = r.randint(0, 255)
self.ax = r.randint(0, 255)
self.ay = r.randint(0, 255)
self.bx = self.ax + t
self.by = self.ay
self.dx = self.ax
self.dy = self.ay - t
self.cx = self.ax + t
self.cy = self.ay - t
if mutate_or_not(self.mid_mutate_rate):
t = min(max(0, parent.ax + r.randint(-15, 15)), 255)
self.ax = min(max(0, parent.ax + r.randint(-15, 15)), 255)
self.ay = min(max(0, parent.ay + r.randint(-15, 15)), 255)
self.bx = self.ax + t
self.by = self.ay
self.dx = self.ax
self.dy = self.ay - t
self.cx = self.ax + t
self.cy = self.ay - t
if mutate_or_not(self.min_mutate_rate):
t = min(max(0, parent.ax + r.randint(-3, 3)), 255)
self.ax = min(max(0, parent.ax + r.randint(-3, 3)), 255)
self.ay = min(max(0, parent.ay + r.randint(-3, 3)), 255)
self.bx = self.ax + t
self.by = self.ay
self.dx = self.ax
self.dy = self.ay - t
self.cx = self.ax + t
self.cy = self.ay - t
# color
if mutate_or_not(self.max_mutate_rate):
self.color.r = r.randint(0, 255)
if mutate_or_not(self.mid_mutate_rate):
self.color.r = min(max(0, parent.color.r + r.randint(-30, 30)), 255)
if mutate_or_not(self.min_mutate_rate):
self.color.r = min(max(0, parent.color.r + r.randint(-10, 10)), 255)
if mutate_or_not(self.max_mutate_rate):
self.color.g = r.randint(0, 255)
if mutate_or_not(self.mid_mutate_rate):
self.color.g = min(max(0, parent.color.g + r.randint(-30, 30)), 255)
if mutate_or_not(self.min_mutate_rate):
self.color.g = min(max(0, parent.color.g + r.randint(-10, 10)), 255)
if mutate_or_not(self.max_mutate_rate):
self.color.b = r.randint(0, 255)
if mutate_or_not(self.mid_mutate_rate):
self.color.b = min(max(0, parent.color.b + r.randint(-30, 30)), 255)
if mutate_or_not(self.min_mutate_rate):
self.color.b = min(max(0, parent.color.b + r.randint(-10, 10)), 255)
# alpha
if mutate_or_not(self.mid_mutate_rate):
self.color.a = r.randint(95, 115)
# if mutate_or_not(self.mid_mutate_rate):
# self.color.a = min(max(0, parent.color.a + r.randint(-30, 30)), 255)
# if mutate_or_not(self.min_mutate_rate):
# self.color.a = min(max(0, parent.color.a + r.randint(-10, 10)), 255)
def draw_it(self, size=(256, 256)):
self.img_t = Image.new('RGBA', size)
draw = ImageDraw.Draw(self.img_t)
draw.polygon([(self.ax, self.ay),
(self.bx, self.by),
(self.cx, self.cy),
(self.dx, self.dy)],
fill=(self.color.r, self.color.g, self.color.b, self.color.a))
return self.img_t
class Canvas(object):
'''
定義每一張圖片的類(lèi)
屬性:
mutate_rate : 變異概率
size : 圖片大小
target_pixels: 目標(biāo)圖片像素值
方法:
add_triangles(self, num=1) : 在圖片類(lèi)中生成num個(gè)三角形
mutate_from_parent(self, parent): 從父代圖片對(duì)象進(jìn)行變異
calc_match_rate(self) : 計(jì)算環(huán)境適應(yīng)度
draw_it(self, i) : 保存圖片
'''
mutate_rate = 0.01
size = (256, 256)
target_pixels = []
def __init__(self):
self.triangles = []
self.match_rate = 0
self.img = None
def add_triangles(self, num=1):
for i in range(0, num):
triangle = Triangle()
self.triangles.append(triangle)
def mutate_from_parent(self, parent):
flag = False
for triangle in parent.triangles:
t = triangle
if mutate_or_not(self.mutate_rate):
flag = True
a = Triangle()
a.mutate_from(t)
self.triangles.append(a)
continue
self.triangles.append(t)
if not flag:
self.triangles.pop()
t = parent.triangles[r.randint(0, len(parent.triangles) - 1)]
a = Triangle()
a.mutate_from(t)
self.triangles.append(a)
def calc_match_rate(self):
if self.match_rate > 0:
return self.match_rate
self.match_rate = 0
self.img = Image.new('RGBA', self.size)
draw = ImageDraw.Draw(self.img)
draw.polygon([(0, 0), (0, 255), (255, 255), (255, 0)], fill=(255, 255, 255, 255))
for triangle in self.triangles:
self.img = Image.alpha_composite(self.img, triangle.img_t or triangle.draw_it(self.size))
# 與下方代碼功能相同,此版本便于理解但效率低
# pixels = [self.img.getpixel((x, y)) for x in range(0, self.size[0], 2) for y in range(0, self.size[1], 2)]
# for i in range(0, min(len(pixels), len(self.target_pixels))):
# delta_red = pixels[i][0] - self.target_pixels[i][0]
# delta_green = pixels[i][1] - self.target_pixels[i][1]
# delta_blue = pixels[i][2] - self.target_pixels[i][2]
# self.match_rate += delta_red * delta_red + \
# delta_green * delta_green + \
# delta_blue * delta_blue
arrs = [np.array(x) for x in list(self.img.split())] # 分解為RGBA四通道
for i in range(3): # 對(duì)RGB通道三個(gè)矩陣分別與目標(biāo)圖片相應(yīng)通道作差取平方加和評(píng)估相似度
self.match_rate += np.sum(np.square(arrs[i]-self.target_pixels[i]))[0]
def draw_it(self, i):
#self.img.save(os.path.join(PATH, "%s_%d_%d_%d.png" % (PREFIX, len(self.triangles), i, self.match_rate)))
self.img.save(os.path.join(PATH, "%d.png" % (i)))
def main():
global LOOP, PREFIX, PATH, TARGET, TRIANGLE_NUM
# 聲明全局變量
img = Image.open(TARGET).resize((256, 256)).convert('RGBA')
size = (256, 256)
Canvas.target_pixels = [np.array(x) for x in list(img.split())]
# 生成一系列的圖片作為父本,選擇其中最好的一個(gè)進(jìn)行遺傳
parentList = []
for i in range(20):
print('正在生成第%d個(gè)初代個(gè)體' % (i))
parentList.append(Canvas())
parentList[i].add_triangles(TRIANGLE_NUM)
parentList[i].calc_match_rate()
parent = sorted(parentList, key=lambda x: x.match_rate)[0]
del parentList
gc.collect()
# 進(jìn)入遺傳算法的循環(huán)
i = 0
while i < 30000:
childList = []
# 每一代從父代中變異出10個(gè)個(gè)體
for j in range(10):
childList.append(Canvas())
childList[j].mutate_from_parent(parent)
childList[j].calc_match_rate()
child = sorted(childList, key=lambda x: x.match_rate)[0]
# 選擇其中適應(yīng)度最好的一個(gè)個(gè)體
del childList
gc.collect()
parent.calc_match_rate()
if i % LOOP == 0:
print ('%10d parent rate %11d \t child1 rate %11d' % (i, parent.match_rate, child.match_rate))
parent = parent if parent.match_rate < child.match_rate else child
# 如果子代比父代更適應(yīng)環(huán)境,那么子代成為新的父代
# 否則保持原樣
child = None
if i % LOOP == 0:
# 每隔LOOP代保存一次圖片
parent.draw_it(i)
#print(parent.match_rate)
#print ('%10d parent rate %11d \t child1 rate %11d' % (i, parent.match_rate, child.match_rate))
i += 1
'''
定義全局變量,獲取待處理的圖片名
'''
NAME = input('請(qǐng)輸入原圖片文件名:')
LOOP = 100
PREFIX = NAME.split('/')[-1].split('.')[0] # 取文件名
PATH = os.path.abspath('.') # 取當(dāng)前路徑
PATH = os.path.join(PATH,'results')
TARGET = NAME # 源圖片文件名
TRIANGLE_NUM = 256 # 三角形個(gè)數(shù)
if __name__ == '__main__':
#print('開(kāi)始進(jìn)行遺傳算法')
main()
(三)運(yùn)行結(jié)果

(四)結(jié)果描述
? 代碼是在遺傳算法求解三角形火狐拼圖改進(jìn)而來(lái),遺傳算法求解正方形拼圖游戲只需隨機(jī)生成一個(gè)坐標(biāo)和一個(gè)常數(shù)值(作為正方形的邊長(zhǎng)),通過(guò)正方形的性質(zhì),可以寫(xiě)出正方形其他三個(gè)點(diǎn)的坐標(biāo),確定了四個(gè)點(diǎn)的坐標(biāo)之后,進(jìn)行遺傳和變異。
到此這篇關(guān)于Python實(shí)現(xiàn)遺傳算法(虛擬機(jī)中運(yùn)行)的文章就介紹到這了,更多相關(guān)Python 遺傳算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python腳本判斷 Linux 是否運(yùn)行在虛擬機(jī)上
- Windows下Pycharm遠(yuǎn)程連接虛擬機(jī)中Centos下的Python環(huán)境(圖文教程詳解)
- Python使用oslo.vmware管理ESXI虛擬機(jī)的示例參考
- python虛擬機(jī)解釋器及運(yùn)行過(guò)程
- Python動(dòng)態(tài)規(guī)劃實(shí)現(xiàn)虛擬機(jī)部署的算法思想
- 虛擬機(jī)下載python是否需要聯(lián)網(wǎng)
- 深入理解Python虛擬機(jī)中元組(tuple)的實(shí)現(xiàn)原理及源碼
- Python虛擬機(jī)棧幀對(duì)象及獲取源碼學(xué)習(xí)
- 深入理解?python?虛擬機(jī)
相關(guān)文章
PyQt5實(shí)現(xiàn)類(lèi)似別踩白塊游戲
這篇文章主要為大家詳細(xì)介紹了PyQt5實(shí)現(xiàn)類(lèi)似別踩白塊游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Python實(shí)現(xiàn)復(fù)制文件從一個(gè)目錄到另外一個(gè)目錄
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)復(fù)制文件從一個(gè)目錄到另外一個(gè)目錄,文中的示例代碼簡(jiǎn)潔易懂,有需要的小伙伴可以參考一下2025-01-01
Python調(diào)用C++,通過(guò)Pybind11制作Python接口
今天小編就為大家分享一篇關(guān)于Python調(diào)用C++,通過(guò)Pybind11制作Python接口,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10
解決django后臺(tái)管理界面添加中文內(nèi)容亂碼問(wèn)題
今天小編就為大家分享一篇解決django后臺(tái)管理界面添加中文內(nèi)容亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
TensorFlow基本的常量、變量和運(yùn)算操作詳解
今天小編就為大家分享一篇TensorFlow基本的常量、變量和運(yùn)算操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
python使用numpy計(jì)算兩個(gè)框的iou方法示例
這篇文章主要介紹了python使用numpy計(jì)算兩個(gè)框的iou方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
python使用matplotlib庫(kù)生成隨機(jī)漫步圖
這篇文章主要為大家詳細(xì)介紹了使用Python的matplotlib庫(kù)生成隨機(jī)漫步圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
Python詳細(xì)對(duì)比講解break和continue區(qū)別
這篇文章主要介紹了python循環(huán)控制語(yǔ)句 break 與 continue,break就像是終止按鍵,不管執(zhí)行到哪一步,只要遇到break,不管什么后續(xù)步驟,直接跳出當(dāng)前循環(huán)2022-06-06

