201871030137-杨钦颖 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

201871030137-杨钦颖 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

项目 内容
课程班级博客链接 班级连接
这个作业要求链接 作业连接
我的课程学习目标 1、掌握软件项目个人开发流程。
2、掌握Github发布软件项目的操作方法。
这个作业在哪些方面帮助我实现学习目标 1、实战使用了Github项目仓库,更加熟悉了Github的使用方法。
2、基本完成了个人项目的开发,掌握了项目开发流程。
结对方学号-姓名 201871030138-杨蕊媛
结对方本次博客作业链接 结对方作业连接
本项目Github的仓库链接地址 仓库连接

任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念

  • 已完成阅读,相关概念如下:
  • 代码风格规范
    • 代码风格的原则是:简明,易读,无二义性。
    • 缩进:4个空格,不用Tab键是因为在不同的情况下显示的长度可能不一样。
    • 行宽:限定为100字符。
    • 括号:在复杂的条件表达式中,可以清晰地表示逻辑优先级。
    • 断行与空白的{}行:断行在程序调试时可以清晰的表达变量的变化情况,{}来判断程序的结构。
    • 分行:不要把多个变量定义在一行上。
    • 命名:
      • 在变量名中不要提到类型或其他语法方面的描述。
      • 避免过多的描述。
      • 如果信息可以从上下文中得到,那么此类信息就不必写在变量名中。
      • 避免可要可不要的修饰词。
    • 下划线:用来分割变量名字中的作用域标注和变量的语义。
    • 大小写:
      • 所有类型/类/函数名都用Pascal形式(所有单词第一个字母都大写)。
      • 所有变量都用Camel形式(第一个单词全部小写,随后单词用Pascal形式)。
      • 类/类型/变量:名词或组合名词。
      • 函数则用动词或动宾组合词来表示。
    • 注释:注释是为了解释程序做什么(What),为什么这样做(Why)以及要特别注意的地方。
  • 代码设计规范
    • 概念:代码设计规范不光是程序书写的格式问题,而且涉及到程序设计、模块之间的关系、设计模式等方方面面,又有不少内容与具体程序设计语言息息相关(如C,C++,JAVA,C#),但是也有通用的原则。
    • 函数:原则:只做一件事,并且要做好。
    • goto:函数最好有单一出口,为了达到这一目的,可以使用goto。
    • 错误处理:
      • 参数处理:在Debug版本中,所有的参数都要验证其正确性,在正式版本中,对从外部(用户或别的模块)传递过来的参数,要验证其正确性。
      • 断言:验证正确性就要用断言。
    • 如何处理C++中的类
      • 类:
        • 使用类来封装面向对象的概念和多态。
        • 避免传递类型实体的值,应该用指针传递。换句话说,对于简单的数据类型,没有必要要用类来实现。
        • 对于有显示的构造和析构的类,不要建立全局的实体,因为不知道它们在何时创建和消除。
        • 仅在有必要时,才是用“类”。
      • class vs.struct:如果只是数据的封装,用struct即可。
      • 公共/保护/私有成员:按照这样的次序来说明类中的成员。
      • 数据成员:
        • 数据类型的成员用m_name说明。
        • 不要使用公共的数据成员,要用inline访问函数,这样可兼顾封装和效率。
      • 虚函数
        • 使用虚函数来实现多态。
        • 仅在很有必要时,才使用虚函数。
        • 如果一个类型要实现多态,在基类中的析构函数应该是虚函数。
      • 构造函数
        • 不要在构造函数中做复杂的操作,简单初始化所有成员即可。
        • 构造函数不应该返回错误。
      • 析构函数
        • 把所有的清理工作都放在析构函数中。如果有些析构函数在之前就释放了,要重置这些成员为0或NULL。
        • 析构函数也不应该出错。
      • new和delete
        • 如果可能,实现自己的new/delete,这样可以方便地加上自己的跟踪和管理机制。自己的new/delete可以包装系统提供的new/delete。
        • 检查new的返回值。new不一定都成功。
        • 释放指针时不用检查NULL。
      • 运算符
        • 在理想情况下,我们定义的类不需要自定义操作符。确有必要时,才会自定义操作符。
        • 运算符不要做标准语义之外的任何动作。
        • 运算符的实现必须非常有效率,如果有复杂的操作,应定义一个单独的函数。
        • 当拿不定注意时,用成员函数,不要用运算符。
      • 异常
        • 不要用异常作为逻辑控制来处理程序的主要流程。
        • 当使用异常时,要注意在什么地方清理数据。
        • 异常不能跨过DLL或进程的边界来传递消息,所以异常不是万能的。
      • 类型继承
        • 仅在有必要时,才使用类型继承。
        • 用const标注只读的参数。
        • 用const标注不改变数据的函数。
  • 代码复审:看代码是否在代码规范的框架内正确的解决了问题。代码复审的形式包括:自我复审、同伴复审、团队复审。
  • 结对编程:结对编程中有两个角色:领航员和驾驶员。在个人编写的过程中,很多人喜欢根据个人喜好来规定代码规范,而且存在的bug自己难以发现,因此,在结对编程时,我们可以互换角色,在开始写代码之前,规定两个人都认可的一套代码规范,并且不间断地进行复审,以减少软件中存在的问题,修复bug,提高软件质量。

任务2:评价对结对方《实验二 软件工程个人项目》的项目成果

  • 结对方实验二博客连接

  • 克隆结对方项目源码到本地机器,阅读并测试运行代码,参照《现代软件工程—构建之法》4.4.3节核查表复审同伴项目代码并记录。

    • 概要部分

      • 代码能符合需求和规格说明么?

        代码符合要求与规格说明

      • 代码设计是否有周全的考虑?

        有较为周全的考虑

      • 代码可读性如何?

        代码可读性强

      • 代码容易维护么?

        容易维护

    • 设计规范部分

      • 设计是否遵从已知的设计模式或项目中常用的模式?

        遵从

      • 有没有硬编码或字符串/数字等存在?

        没有

      • 代码有没有依赖于某一平台,是否会影响将来的移植(如Win32到Win64)?

        不会影响移植

      • 在本项目中是否存在类似的功能可以调用而不用全部重新实现?

        没有

      • 有没有无用的代码可以清除?

        没有

    • 代码规范部分

      • 修改的部分符合代码标准和风格么(详细条文略)?

        符合

    • 具体代码部分

      • 有没有可能导致资源泄露(内存、文件、各种GUI资源、数据库访问的连接,等等)?有没有可能优化?

        不会导致资源泄露;还有优化的可能性

      • 数据结构中是否有无用的元素?

        没有

    • 效能

      • 代码的效能(Performance)如何?最坏的情况是怎样的?

        达到了部分任务要求

      • 代码中,特别是循环中是否有明显可优化的部分?

        没有

    • 可测试性

      • 代码是否需要更新或创建新的单元测试?

        可以继续开发

  • 依据复审结果尝试利用github的Fork、Clone、Push、Pull request、Merge pull request等操作对同伴个人项目仓库的源码进行合作修改。

    结对方仓库链接

任务3:采用两人结对编程方式,设计开发一款D{0-1}KP 实例数据集算法实验平台,使之具有以下功能

功能设计

  • 平台基础功能:实验二 任务3;
  • D{0-1}KP 实例数据集需存储在数据库;
  • 平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据;
  • 人机交互界面要求为GUI界面(WEB页面、APP页面都可);
  • 查阅资料,设计遗传算法求解D{0-1}KP,并利用此算法测试要求(3);

设计实现

  • 在实验二的基础上添加GUI界面
  • 学习并添加遗传算法

测试运行

  • 选择需要读取的文件

  • 选择需要读取第几组数据

  • 散点图

  • 遗传算法运行结果图

  • 数据库中导入结果

  • 有效数据的展示,其中包含选定数据的价值重量、第三项价值:重量比的排序、利用动态规划算法、遗传算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位)

  • 在.txt文件中存储的运行结果

代码展示

  • 导入数据库

    # 创建数据库
    def CreateDataBase(self):
        global i
        global d
        global cubage
        global profit
        global weight
        global pw
        conn = sqlite3.connect('mrsoft.db')
        cursor = conn.cursor()
        cursor.execute('DROP TABLE IF EXISTS user')
        cursor.execute('create table if not exists user (num int(10) primary key,profit int(20), weight int(20))')
        cubage[i] = max(list(map(int,re.findall(r'\d+',line[i*8+3]))))
        profit[i] = list(map(int,re.findall(r'\d+',line[i*8+5])))
        weight[i] = list(map(int,re.findall(r'\d+',line[i*8+7])))
        pw[i] = list(map(lambda x:x[0]/x[1],zip(profit[i],weight[i])))
        for j in range(0,d):
            cursor.execute('insert into user (num,profit,weight) values ("%d","%d","%d")'%(j,profit[i][j],weight[i][j]))
        cursor.execute('select * from user')
        result=cursor.fetchall()
        cursor.close()
        conn.commit()
        conn.close()
        return result
    
  • 遗传算法

        ##初始化,N为种群规模,n为染色体长度
      def init(self,N,n):
          C = []
          for i in range(N):
              c = []
              for j in range(n):
                  a = np.random.randint(0,2)
                  c.append(a)
              C.append(c)
          return C
    
    
      ##评估函数
      # x(i)取值为1表示被选中,取值为0表示未被选中
      # w(i)表示各个分量的重量,v(i)表示各个分量的价值,w表示最大承受重量
      def fitness(self,C,N,n,W,V,w):
          S = []##用于存储被选中的下标
          F = []## 用于存放当前该个体的最大价值
          for i in range(N):
              s = []
              h = 0  # 重量
              f = 0  # 价值
              for j in range(n):
                  if C[i][j]==1:
                      if h+W[j]<=w:
                          h=h+W[j]
                          f = f+V[j]
                          s.append(j)
              S.append(s)
              F.append(f)
          return S,F
    
      ## 适应值函数,B位返回的种族的基因下标,y为返回的最大值
      def best_x(self,F,S,N):
          y = 0
          x = 0
          B = [0]*N
          for i in range(N):
              if y<F[i]:
                  x = i
              y = F[x]
              B = S[x]
          return B,y
    
      ## 计算比率
      def rate(self,x):
          p = [0] * len(x)
          s = 0
          for i in x:
              s += i
          for i in range(len(x)):
              p[i] = x[i] / s
          return p
    
      ## 选择
      def chose(self,p, X, m, n):
          X1 = X
          r = np.random.rand(m)
          for i in range(m):
              k = 0
              for j in range(n):
                  k = k + p[j]
                  if r[i] <= k:
                      X1[i] = X[j]
                      break
          return X1
    
      ## 交配
      def match(self,X, m, n, p):
          r = np.random.rand(m)
          k = [0] * m
          for i in range(m):
              if r[i] < p:
                  k[i] = 1
          u = v = 0
          k[0] = k[0] = 0
          for i in range(m):
              if k[i]:
                  if k[u] == 0:
                      u = i
                  elif k[v] == 0:
                      v = i
              if k[u] and k[v]:
                  # print(u,v)
                  q = np.random.randint(n - 1)
                  # print(q)
                  for i in range(q + 1, n):
                      X[u][i], X[v][i] = X[v][i], X[u][i]
                  k[u] = 0
                  k[v] = 0
          return X
    
      ## 变异
      def vari(self,X, m, n, p):
          for i in range(m):
             for j in range(n):
                  q = np.random.rand()
                  if q < p:
                      X[i][j] = np.random.randint(0,2)
          return X
    

总结

PSP展示

PSP2.1 任务内容 计划共完成需要的时间(min) 实际完成需要的时间(min)
Planning 计划 20 20
Estimate 估计这个任务需要多少时间,并规划大致工作步骤 20 20
Development 开发 1090 1200
Analysis 需求分析 (包括学习新技术) 120 155
Design Spec 生成设计文档 30 20
Design Review 设计复审 (和同事审核设计文档) 20 20
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 35
Design 具体设计 60 50
Coding 具体编码 600 650
Code Review 代码复审 30 30
Test 测试(自我测试,修改代码,提交修改) 200 240
Reporting 报告 100 100
Test Report 测试报告 30 40
Size Measurement 计算工作量 40 30
Postmortem & Process Improvement Plan 事后总结 ,并提出过程改进计划 30 30

commit记录

GitHub项目仓库连接

仓库连接

任务4:完成个人项目报告博文作业

  • 已完成博客

写在后面

  本次实验项目在实验二的基础上新添加了数据库的导入、GUI界面以及遗传算法等要求。为实现这些功能我们一起学习了如何在python中添加数据库和GUI界面,这些知识虽然之前学过但都只是皮毛,通过本次实验强化了我对相关知识的理解与运用。除此之外对我们来说最难的就是怎样使用遗传算法实现D{0-1}KP 背包问题,经过查阅学习资料与编码测试我们发现:使用遗传算法进行测试,最后产生的结果不一定是问题的最优解,甚至会出现结果不一致。最后通过查阅相关资料证实了我们的发现是符合遗传算法的。

  在本次实验中我与我的结对对象是舍友,这大大方便了我们的沟通与交流,但这也使我们没有保留交流、编程时的结对图片。但在结对合作中我体会到了“1+1>2”的效果。每个人都题出自己的理解与想法,同时又会碰撞出更多更好的编程思路,提高了项目完成效率。

  不足之处:未设置滚动条,当数据较多时无法看到后面的数据

posted @ 2021-04-13 23:43  201871030137-杨钦颖  阅读(93)  评论(4编辑  收藏  举报