紀錄與電腦模擬相關內容與紀錄, 使用工具 Python3, RoboDK (RoboDK API)
PyQt5
pyqt5 程式 http://projects.skylogic.ca/blog/how-to-install-pyqt5-and-build-your-first-gui-in-python-3-4/
run.py, 自行編寫用從 core/main.py 中導入 MainWindow 類別建立案例後執行
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
from core.main import MainWindow
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
core/main.py, 以 main.ui 滑鼠右鍵 generate Dialog Code 產生
# -*- coding: utf-8 -*-
"""
Module implementing MainWindow.
"""
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import QLineF
from PyQt5.QtWidgets import QFrame
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsEllipseItem
from .Ui_main import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
"""
Class documentation goes here.
"""
def __init__(self, parent=None):
"""
Constructor
@param parent reference to the parent widget
@type QWidget
"""
super(MainWindow, self).__init__(parent)
self.setupUi(self)
@pyqtSlot()
def on_actionAbout_triggered(self):
"""
Slot documentation goes here.
"""
# TODO: not implemented yet
#raise NotImplementedError
#建立景物
scene = QGraphicsScene(-200, -200, 400, 400)
# Create Ellipse Item
item = QGraphicsEllipseItem(-150, -100, 300, 300)
# Add item
scene.addItem(item)
# 納入繪圖物件
scene.addText("終於可以!")
scene.addLine(QLineF(0, 0, 200, 200))
# set no frame to graphicsView
self.graphicsView.setFrameShape(QFrame.NoFrame)
# 在既有的 graphicsView 中設定景物
# graphicsView in a layout and set layout to the grid to fit the size of window
self.graphicsView.setScene(scene)
# 顯示
self.graphicsView.show()
@pyqtSlot()
def on_actionQuit_triggered(self):
"""
Slot documentation goes here.
"""
# TODO: not implemented yet
#raise NotImplementedError
self.close()
core/Ui_main.py, 利用 main.ui 以 compile form 產生
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Y:\tmp\pyqt5_vault\ex3\core\main.ui'
#
# Created by: PyQt5 UI code generator 5.8.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.graphicsView = QtWidgets.QGraphicsView(self.centralWidget)
self.graphicsView.setGeometry(QtCore.QRect(-15, -29, 871, 581))
self.graphicsView.setObjectName("graphicsView")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menuBar.setObjectName("menuBar")
self.menuFile = QtWidgets.QMenu(self.menuBar)
self.menuFile.setObjectName("menuFile")
MainWindow.setMenuBar(self.menuBar)
self.actionAbout = QtWidgets.QAction(MainWindow)
self.actionAbout.setObjectName("actionAbout")
self.actionQuit = QtWidgets.QAction(MainWindow)
self.actionQuit.setObjectName("actionQuit")
self.menuFile.addAction(self.actionAbout)
self.menuFile.addAction(self.actionQuit)
self.menuBar.addAction(self.menuFile.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.actionAbout.setText(_translate("MainWindow", "About"))
self.actionQuit.setText(_translate("MainWindow", "Quit"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
main.ui
MainWindow 0 0 800 600 MainWindow -15 -29 871 581 0 0 800 22 File About Quit
Binary Genetic Algorithm
#encoding=utf8
# genetic.py
#
import random
import operator
# for Intersect
from math import *
MAXIMIZE, MINIMIZE = 11, 22
class Individual:
# 染色體先設為 None
chromosome = None
# 得分也先設為 None
score = None
# Here the size of var depends on var_number print
# var 變數的元素個數取決於 var_number 的個數 (即變數個數)
var = []
# 表示適應值變數個數有兩個
var_number = 2
#先將 var 數列中元素都設為 0
for i in range(var_number):
var.append(0)
# 等位基因表示各基因可選的內容, 這裡表示不是 0 就是 1
alleles = (0,1)
# 2**10 = 32*32 = 1024, 表示若用十個 binary 位數來表示整數, 可以表示從 0 到 1023 的數值大小
# 若也用另外 十個 binary 位數來表示小數值, 則也是 0 到 1023 的數值表示能力,
# 而再加一個表示正負的代表 binary 位數, 每一個變數需要 21 個 binary numbers
# 以下為參數可負數時的編碼考量
#前10為小數,後10為整數,第21則為正負號
#0~9表示小數,10~19表示整數,而指標第20則表示第一數的正號或負號,若為0則表示正,若為1表示負號.
#21~30表示第二數的小數部分,31~40則表示第二數的整數部分,第41指標則表示第二數的正號或負號
#42~51表示第三數的小數部分,52~61則表示第二數的整數部分,第62指標則表示第三數的正號或負號
# -1023 ~ 1023
#length = 21*var_number,若接受負數參數,則必須同步修改 20->21
# 因為這裡只接受正的變數值, 所以每一個變數需要 20 個 binary 位數
length = 20*var_number
seperator = ''
optimization = MINIMIZE
def __init__(self, chromosome=None):
self.chromosome = chromosome or self._makechromosome()
self.score = None # set during evaluation
'''
bitwise operators (binary left shift): The left operands value is moved left by the number of bits specified by the right operand.
x << y
Returns x with the bits shifted to the left by y places (and new bits on the right-hand-side are zeros). This is the same as multiplying x by 2**y.
'''
# 根據染色體各位元的值轉為 10 進位值
def _getvar(self, chromosome=None):
# x 起始值設為 0
x = 0
for i in range(0, self.var_number):
# 先根據前 20 個位元值, 透過 binary left shift 轉為 10 進位之後, 再轉為對應小數
for j in range(i*20, i*20+10):
x += self.chromosome[j]<<(j-(i*20))
# 因為前 20 個 binary 數, 負責 10 進位數的小數點後 3 個位數, 只要轉為 10 進位值之後, 若大於 999, 則僅取 999,
# 再除以 1000, 可以得到 .999 表示 .999 為最大的小數表示數, 不要因為大於 1000 後若除以 1000 將進位到整數, 會與整數有交互影響
if (x>999):
x = 999
x /= 1000.
# 整數部份 0 ~ 1023 的表示範圍則沒有問題, 利用 bitwise 轉換後, 直接取整數值
for j in range(i*20+10, i*20+20):
x += self.chromosome[j]<<(j-(i*20+10))
self.var[i] = x
return self.var
''' for -1023 ~ 1023,當設計變數可以接受負值時使用,每一變數使用21個 bit strings
#for design variable -1023 ~1023
for i in range(self.var_number):
x = 0
for j in range(i*21, i*21+10):
x += self.chromosome[j]<<(j-(i*21))
if (x>999):
x = 999
x /= 1000.
for j in range(i*(21)+10, i*(21)+20):
x += self.chromosome[j]<<(j-(i*21+10))
# 各變數範圍第 21 位數若為 1, 則表示該數為負數
if(self.chromosome[i*(21)+20] == 1):
self.var[i] = -x
else:
self.var[i] = x
# 讓 x 再設回原值 0 表示內定各變數為正數
x = 0
return self.var
'''
# 建立染色體
def _makechromosome(self):
"makes a chromosome from randomly selected alleles."
return [random.choice(self.alleles) for gene in range(self.length)]
# 計算適應值
def evaluate(self, optimum=None):
"this method MUST be overridden to evaluate individual fitness score."
pass
# 交配方法
def crossover(self, other):
"override this method to use your preferred crossover method."
return self._twopoint(other)
# 突變方法
def mutate(self, gene):
"override this method to use your preferred mutation method."
self._pick(gene)
# sample mutation method
def _pick(self, gene):
"chooses a random allele to replace this gene's allele."
self.chromosome[gene] = random.choice(self.alleles)
# sample crossover method
def _twopoint(self, other):
"creates offspring via two-point crossover between mates."
left, right = self._pickpivots()
def mate(p0, p1):
chromosome = p0.chromosome[:] # 交配時,以p0的基因為基礎(複製整個 p0 的染色體內容
chromosome[left:right] = p1.chromosome[left:right] # 接續上一個 p0 的染色體內容,將索引 left 至 right 的內容,替換成 p1 的基因
child = p0.__class__(chromosome)
child._repair(p0, p1)
return child
return mate(self, other), mate(other, self)
# some crossover helpers ...
def _repair(self, parent1, parent2):
"override this method, if necessary, to fix duplicated genes."
pass
def _pickpivots(self):
left = random.randrange(1, self.length-2)
right = random.randrange(left, self.length-1)
return left, right
#
# other methods
#
def __repr__(self):
"returns string representation of self"
'''
return '<%s chromosome="%s" score=%s var=%s>' % \
(self.__class__.__name__,
self.seperator.join(map(str,self.chromosome)), self.score,self._getvar(self.chromosome))
'''
return '<%s score=%s var=%s>' % \
(self.__class__.__name__,self.score,self._getvar(self.chromosome))
# since the __cmp__ special function is gone use the __lt__ in stead
# use the expression (a > b) - (a < b) as the equivalent for cmp(a, b)
#def __cmp__(self, other):
# these are for python 3
def __cmp__(self, other):
if self.optimization == MINIMIZE:
#return cmp(self.score, other.score)
return (self.score > other.score) - (self.score < other.score)
else: # MAXIMIZE
#return cmp(other.score, self.score)
return (other.score > self.score) - (other.score < self.score)
def __lt__(self, other):
return self.__cmp__(other) < 0
def __le__(self, other):
return self.__cmp__(other) <= 0
def __gt__(self, other):
return self.__cmp__(other) > 0
def __ge__(self, other):
return self.__cmp__(other) >= 0
def copy(self):
twin = self.__class__(self.chromosome[:])
twin.score = self.score
return twin
class Environment(object):
x = [0]
y = [0]
def __init__(self, kind, population=None, size=100, maxgenerations=100,
crossover_rate=0.90, mutation_rate=0.07, optimum=None):
self.kind = kind
self.size = size
self.optimum = optimum
self.population = population or self._makepopulation()
for individual in self.population:
individual.evaluate(self.optimum)
self.crossover_rate = crossover_rate
self.mutation_rate = mutation_rate
self.maxgenerations = maxgenerations
self.generation = 0
self.report()
def _makepopulation(self):
return [self.kind() for individual in range(self.size)]
def run(self):
while not self._goal():
self.step()
def _goal(self):
return self.generation > self.maxgenerations or \
self.best.score == self.optimum
def step(self):
# this sort is not working with python 3.0, modification is needed
self.population.sort()
self._crossover()
self.generation += 1
self.report()
self.x.append(self.generation)
# 設定為只附加所選定範圍的值,這裡只取大於或等於 0 的 score 值
if self.best.score <=5:
self.y.append(self.best.score)
else:
self.y.append(5)
def _crossover(self):
next_population = [self.best.copy()]
while len(next_population) < self.size:
mate1 = self._select()
if random.random() < self.crossover_rate:
mate2 = self._select()
offspring = mate1.crossover(mate2)
else:
offspring = [mate1.copy()]
for individual in offspring:
self._mutate(individual)
individual.evaluate(self.optimum)
next_population.append(individual)
self.population = next_population[:self.size]
def _select(self):
"override this to use your preferred selection method"
return self._tournament()
def _mutate(self, individual):
for gene in range(individual.length):
if random.random() < self.mutation_rate:
individual.mutate(gene)
#
# sample selection method
#
def _tournament(self, size=8, choosebest=0.90):
competitors = [random.choice(self.population) for i in range(size)]
competitors.sort()
if random.random() < choosebest:
return competitors[0]
else:
return random.choice(competitors[1:])
def best():
doc = "individual with best fitness score in population."
def fget(self):
return self.population[0]
return locals()
best = property(**best())
def report(self):
try:
print ("="*70)
print ("generation: ", self.generation)
print ("best: ", self.best)
except:
g.es ("="*70)
g.es ("generation: ", self.generation)
g.es ("best: ", self.best)
# 以上為 genetic.py 目前將兩者結合在一起
#encoding=utf8
# volume.py - useage example
#
# the fittest individual will have a chromosome consisting of 40 '1's
#
#
#import genetic
class Volume(Individual):
optimization = MAXIMIZE
def evaluate(self, optimum=None):
SURFACE = 80
# self.score is the fitness value
self._getvar(self.chromosome)
x = self.var[0]
y = self.var[1]
z=(SURFACE - x*y)/(2.*(x+y))
fitness_value = x*y*z
self.score = fitness_value
def mutate(self, gene):
self.chromosome[gene] = not self.chromosome[gene] # bit flip
class Intersect(Individual):
optimization = MINIMIZE
def evaluate(self, optimum=None):
# self.score is the fitness value
self._getvar(self.chromosome)
t = self.var[0]
deg = pi/180
theta = self.var[1]*deg
xtarget = 0.75/2
ytarget = 0.5
x = t*sqrt(-225*sin(theta)**2 + 529)/10 - sqrt(-225*sin(theta)**2 + 529)/92 + 3*cos(theta)/2
y = (-3*t/2 + 123/92)*sin(theta)
# 適應值
fitness_value = pow(x-xtarget, 8)+pow(y-ytarget, 8)
# 指定 t 的範圍, 小於 1 大於 0, 否則給予處罰
if t > 1:
fitness_value += 1000
if t < 0:
fitness_value += 1000
# 指定 theta 的範圍, 小於 2pi 大於 0, 否則給予處罰
if theta > 2*pi:
fitness_value += 1000
if theta < 0:
fitness_value += 1000
self.score = fitness_value
def mutate(self, gene):
self.chromosome[gene] = not self.chromosome[gene] # bit flip
if __name__ == "__main__":
env = Environment(Volume, size=500, maxgenerations=100)
#env = Environment(Intersect, size=500, maxgenerations=100)
env.run()
Deap 與 Scoop
Deap: https://github.com/DEAP/deap
Scoop: https://en.wikipedia.org/wiki/Python_SCOOP_(software)
https://groups.google.com/forum/#!topic/deap-users/v3wbky0EUf0
https://groups.google.com/forum/m/#!msg/deap-users/P4IkiE-Bvbg/xSoMDphbMR4J
平行運算
http://research.cs.wisc.edu/htcondor/
https://github.com/J-Robinson/GridGA
利用 Blender 製作