Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
we446 committed Apr 13, 2021
0 parents commit 4768834
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 0 deletions.
129 changes: 129 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BSD 3-Clause License

Copyright (c) 2021, we446
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# 222

1 comment on commit 4768834

@we446
Copy link
Owner Author

@we446 we446 commented on 4768834 Apr 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import numpy
import matplotlib.pyplot as plt

data = numpy.array([[77, 92],
[22, 22],
[29, 87],
[50, 46],
[99, 90]])

class GA(object):
"""
遗传算法解决0-1背包问题
"""

  def __init__(self, length, number, iter_number):
      """
      参数初始化
      :param length: 5
      :param number: 300
      :param iter_number: 300
      """
      self.length = length  # 确定染色体编码长度
      self.number = number  # 确定初始化种群数量
      self.iteration = iter_number  # 设置迭代次数
      self.bag_capacity = 100  # 背包容量

      self.retain_rate = 0.2  # 每一代精英选择出前20%
      self.random_selection_rate = 0.5  # 对于不是前20%的,有0.5的概率可以进行繁殖
      self.mutation_rate = 0.01  # 变异概率0.01

  def initial_population(self):
      """
      种群初始化,

      :return: 返回种群集合
      """
      init_population = numpy.random.randint(low=0, high=2, size=[self.length, self.number], dtype=numpy.int16)
      return init_population

  def weight_price(self, chromosome):
      """
      计算累计重量和累计价格
      :param chromosome:
      :return:返回每一个个体的累计重量和价格
      """
      w_accumulation = 0
      p_accumulation = 0
      for i in range(len(chromosome)):

          w = chromosome[i]*data[i][0]
          p = chromosome[i]*data[i][1]
          w_accumulation = w + w_accumulation
          p_accumulation = p + p_accumulation

      return w_accumulation, p_accumulation

  def fitness_function(self, chromosome):
      """
      计算适应度函数,一般来说,背包的价值越高越好,但是
      当重量超过100时,适应度函数=0
      :param chromosome:
      :return:
      """

      weight, price = self.weight_price(chromosome)
      if weight > self.bag_capacity:
          fitness = 0
      else:
          fitness = price

      return fitness

  def fitness_average(self, init_population):
      """
      求出这个种群的平均适应度,才能知道种群已经进化好了
      :return:返回的是一个种群的平均适应度
      """
      f_accumulation = 0
      for z in range(init_population.shape[1]):
          f_tem = self.fitness_function(init_population[:, z])
          f_accumulation = f_accumulation + f_tem
      f_accumulation = f_accumulation/init_population.shape[1]
      return f_accumulation

  def selection(self, init_population):
      """
      选择
      :param init_population:
      :return: 返回选择后的父代,数量是不定的
      """
      sort_population = numpy.array([[], [], [], [], [], []])  # 生成一个排序后的种群列表,暂时为空
      for i in range(init_population.shape[1]):

          x1 = init_population[:, i]
          # print('打印x1', x1)
          x2 = self.fitness_function(x1)
          x = numpy.r_[x1, x2]
         # print('打印x', x)
          sort_population = numpy.c_[sort_population, x]

      sort_population = sort_population.T[numpy.lexsort(sort_population)].T  #联合排序,从小到大排列
      # print('排序后长度', sort_population.shape[1])
      print(sort_population)

      # 选出适应性强的个体,精英选择
      retain_length = sort_population.shape[1]*self.retain_rate
      
      parents = numpy.array([[], [], [], [], [], []])  # 生成一个父代列表,暂时为空
      for j in range(int(retain_length)):
          y1 = sort_population[:, -(j+1)]
          parents = numpy.c_[parents, y1]
     # print(parents.shape[1])

      rest = sort_population.shape[1] - retain_length  # 精英选择后剩下的个体数
      for q in range(int(rest)):

          if numpy.random.random() < self.random_selection_rate:
              y2 = sort_population[:, q]
              parents = numpy.c_[parents, y2]

      parents = numpy.delete(parents, -1, axis=0)  # 删除最后一行,删除了f值
      # print('打印选择后的个体数')
      # print(parents.shape[0])

      parents = numpy.array(parents, dtype=numpy.int16)

      return parents

  def crossover(self, parents):
      """
      交叉生成子代,和初始化的种群数量一致
      :param parents:
      :return:返回子代
      """
      children = numpy.array([[], [], [], [], []])  # 子列表初始化

      while children.shape[1] < self.number:
          father = numpy.random.randint(0, parents.shape[1] - 1)
          mother = numpy.random.randint(0, parents.shape[1] - 1)
          if father != mother:
              # 随机选取交叉点
              cross_point = numpy.random.randint(0, self.length)
              # 生成掩码,方便位操作
              mark = 0
              for i in range(cross_point):
                  mark |= (1 << i)

              father = parents[:, father]
              # print(father)
              mother = parents[:, mother]

              # 子代将获得父亲在交叉点前的基因和母亲在交叉点后(包括交叉点)的基因
              child = ((father & mark) | (mother & ~mark)) & ((1 << self.length) - 1)

              children = numpy.c_[children, child]

              # 经过繁殖后,子代的数量与原始种群数量相等,在这里可以更新种群。
              # print('子代数量', children.shape[1])
      # print(children.dtype)
      children = numpy.array(children, dtype=numpy.int16)
      return children

  def mutation(self, children):
      """
      变异

     :return:
      """
      for i in range(children.shape[1]):

          if numpy.random.random() < self.mutation_rate:
              j = numpy.random.randint(0, self.length - 1)  # s随机产生变异位置
              children[:, i] ^= 1 << j  # 产生变异
      children = numpy.array(children, dtype=numpy.int16)
      return children

  def plot_figure(self, iter_plot, f_plot, f_set_plot):
      """
      画出迭代次数和平均适应度曲线图
      画出迭代次数和每一步迭代最大值图
      :return:
      """
      plt.figure()

      ax1 = plt.subplot(121)
      ax2 = plt.subplot(122)

      plt.sca(ax1)
      plt.plot(iter_plot, f_plot)
      plt.ylim(0, 140)  # 设置y轴范围

      plt.sca(ax2)
      plt.plot(iter_plot, f_set_plot)
      plt.ylim(0, 140)  # 设置y轴范围
      plt.show()

  def main(self):
      """
      main函数,用来进化
       对当前种群依次进行选择、交叉并生成新一代种群,然后对新一代种群进行变异
     :return:
     """
      init_population = self.initial_population()
      # print(init_population)

      iter_plot = []
      f_plot = []
      iteration = 0

      f_set_plot = []

      while iteration < self.iteration:  # 设置迭代次数300

          parents = self.selection(init_population)  # 选择后的父代
          children = self.crossover(parents)
          mutation_children = self.mutation(children)

          init_population = mutation_children

          f_set = []  # 求出每一步迭代的最大值
          for init in range(init_population.shape[1]):
              f_set_tem = self.fitness_function(init_population[:, init])
              f_set.append(f_set_tem)

          f_set = max(f_set)

          f_set_plot.append(f_set)

          iter_plot.append(iteration)
          iteration = iteration+1
          print("第%s进化得如何******************************************" % iteration)
          f_average = self.fitness_average(init_population)
          f_plot.append(f_average)
          print(f_set)
          # f_accumulation = f_accumulation + f
          # f_print = f_accumulation/(iteration + 1)
          # print(f_print)
      self.plot_figure(iter_plot, f_plot, f_set_plot)

if name == 'main':
g1 = GA(5, 300, 100)
g1.main()
import tkinter as tk
import tkinter.messagebox
import pickle
#窗口
window=tk.Tk()
window.title('欢迎进入学习系统')
window.geometry('450x300')
#画布放置图片
canvas=tk.Canvas(window,height=300,width=500)
imagefile=tk.PhotoImage(file='qm.png')
image=canvas.create_image(0,0,anchor='nw',image=imagefile)
canvas.pack(side='top')
#标签 用户名密码
tk.Label(window,text='用户名:').place(x=100,y=150)
tk.Label(window,text='密码:').place(x=100,y=190)
#用户名输入框
var_usr_name=tk.StringVar()
entry_usr_name=tk.Entry(window,textvariable=var_usr_name)
entry_usr_name.place(x=160,y=150)
#密码输入框
var_usr_pwd=tk.StringVar()
entry_usr_pwd=tk.Entry(window,textvariable=var_usr_pwd,show='*')
entry_usr_pwd.place(x=160,y=190)

#登录函数
def usr_log_in():
#输入框获取用户名密码
usr_name=var_usr_name.get()
usr_pwd=var_usr_pwd.get()
#从本地字典获取用户信息,如果没有则新建本地数据库
try:
with open('usr_info.pickle','rb') as usr_file:
usrs_info=pickle.load(usr_file)
except FileNotFoundError:
with open('usr_info.pickle','wb') as usr_file:
usrs_info={'admin':'admin'}
pickle.dump(usrs_info,usr_file)
#判断用户名和密码是否匹配
if usr_name in usrs_info:
if usr_pwd == usrs_info[usr_name]:
tk.messagebox.showinfo(title='welcome',
message='欢迎您:'+usr_name)
else:
tk.messagebox.showerror(message='密码错误')
#用户名密码不能为空
elif usr_name=='' or usr_pwd=='' :
tk.messagebox.showerror(message='用户名或密码为空')
#不在数据库中弹出是否注册的框
else:
is_signup=tk.messagebox.askyesno('欢迎','您还没有注册,是否现在注册')
if is_signup:
usr_sign_up()
#注册函数
def usr_sign_up():
#确认注册时的相应函数
def signtowcg():
#获取输入框内的内容
nn=new_name.get()
np=new_pwd.get()
npf=new_pwd_confirm.get()

    #本地加载已有用户信息,如果没有则已有用户信息为空
    try:
        with open('usr_info.pickle','rb') as usr_file:
            exist_usr_info=pickle.load(usr_file)
    except FileNotFoundError:
        exist_usr_info={}           
        
    #检查用户名存在、密码为空、密码前后不一致
    if nn in exist_usr_info:
        tk.messagebox.showerror('错误','用户名已存在')
    elif np =='' or nn=='':
        tk.messagebox.showerror('错误','用户名或密码为空')
    elif np !=npf:
        tk.messagebox.showerror('错误','密码前后不一致')
    #注册信息没有问题则将用户名密码写入数据库
    else:
        exist_usr_info[nn]=np
        with open('usr_info.pickle','wb') as usr_file:
            pickle.dump(exist_usr_info,usr_file)
        tk.messagebox.showinfo('欢迎','注册成功')
        #注册成功关闭注册框
        window_sign_up.destroy()
#新建注册界面
window_sign_up=tk.Toplevel(window)
window_sign_up.geometry('350x200')
window_sign_up.title('注册')
#用户名变量及标签、输入框
new_name=tk.StringVar()
tk.Label(window_sign_up,text='用户名:').place(x=10,y=10)
tk.Entry(window_sign_up,textvariable=new_name).place(x=150,y=10)
#密码变量及标签、输入框
new_pwd=tk.StringVar()
tk.Label(window_sign_up,text='请输入密码:').place(x=10,y=50)
tk.Entry(window_sign_up,textvariable=new_pwd,show='*').place(x=150,y=50)    
#重复密码变量及标签、输入框
new_pwd_confirm=tk.StringVar()
tk.Label(window_sign_up,text='请再次输入密码:').place(x=10,y=90)
tk.Entry(window_sign_up,textvariable=new_pwd_confirm,show='*').place(x=150,y=90)    
#确认注册按钮及位置
bt_confirm_sign_up=tk.Button(window_sign_up,text='确认注册',
                             command=signtowcg)
bt_confirm_sign_up.place(x=150,y=130)

#退出的函数
def usr_sign_quit():
window.destroy()
#登录 注册按钮
bt_login=tk.Button(window,text='登录',command=usr_log_in)
bt_login.place(x=140,y=230)
bt_logup=tk.Button(window,text='注册',command=usr_sign_up)
bt_logup.place(x=210,y=230)
bt_logquit=tk.Button(window,text='退出',command=usr_sign_quit)
bt_logquit.place(x=280,y=230)

Please sign in to comment.