201871030140-朱婷婷 实验二 个人项目—《折扣背包问题》项目报告

项目 内容
课程班级博客连接 班级博客
这个作业要求链接 实验二 软件工程个人项目
我的课程学习目标 1. 掌握软件项目个人开发流程;
2. 掌握GitHub发布软件项目的操作方法。
这个作业在哪些方面帮助我实现学习目标 1.掌握了个人软件项目的开发流程;
2.了解了制定编码规范的方法和作用;
3.进一步熟悉了GitHub发布软件项目的操作。
项目GitHub的仓库链接地址 我的GitHub仓库

任务1:点评博客

任务2:详细阅读《构建之法》并掌握PSP流程

  邹欣老师的《构建之法》第一章介绍了软件和软件工程的概念,第二章主要讲解了个人技术和流程,第二章是我们要重点掌握的内容。通过详细阅读,我学习到了以下的知识点:

  • 软件工程

    软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上的过程,它包括下列领域:软件需求分析、软件设计、软件构建、软件测试和软件维护。

  • 软件的特性

    软件具有复杂性、不可见性、易变性、服从性、非连续性,这些特性是由软件的本质所决定的,它还有其他特性:

    1. 有许多不同的程序设计语言、软件工具和软件开发平台;
    2. 存在许多不同的软件开发流程 ;
    3. 软件团队中存在许多不同的角色 ;
    4. 软件通常既可以存储在磁带上,也可以存储在。
  • 通过理论学习和具体项目的练习要做到三点

    1. 研发出符合用户需求的软件说明;
    2. 通过一定的软件流程,在预计的时间内发布“足够好”的软件说明;
    3. 并通过数据和其他方式展现所开发的软件是可以维护和继续发展的说明。
  • 个人软件开发流程PSP

     PSP包括计划、开发和报告三个阶段,每个阶段又包含了多个任务。

    1. 计划:估计这个任务需要多少时间,并规划大致步骤;
    2. 开发:需求分析、生成设计文档、设计复审、代码规范、具体设计、具体编码、代码复审、测试;
    3. 报告:测试报告、计算工作量、事后总结并提出过程改进计划。
  • PSP的特点

    1. 不局限于某一种软件技术(如编程语言),而是着眼于软件开发的流程,这样,开发不同应用的软件工程师可以互相比较。
    2. 不依赖于考试,而主要靠工程师自己收集数据,然后分析,提高。
    3. 在小型、初创的团队中,很难找到高质量的项目需求,这意味着给程序员的输入质量不高。在这种情况下,程序员的输出(程序/软件)往往质量也不高,然而这并不能全部由程序员负责。
    4. PSP依赖于数据。
    5. 需要工程师输入数据,记录工程师的各项活动,这本身就需要不小的时间代价。
    6. PSP的目的是记录工程师如何实现需求的效率,而不是记录顾客对产品的满意度。

任务3:个人项目开发——背包问题

  • 需求分析

      背包问题是一种组合优化的NP完全问题。问题描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学、计算复杂性理论、密码学和应用数学等领域中。

      D{0-1} KP 是经典{ 0-1}背包问题的一个拓展形式,用以对实际商业活动中折扣销售、捆绑销售等现象进行最优化求解,达到获利最大化。D{0-1}KP数据集由一组项集组成,每个项集有3项物品可供背包装入选择,其中第三项价值是前两项之和,第三项的重量小于其他两项之和,算法求解过程中,如果选择了某个项集,则需要确定选择项集的哪个物品,每个项集的三个项中至多有一个可以被选择装入背包,D{0-1} KP问题要求计算在不超过背包载重量 的条件下,从给定的一组项集中选择满足要求装入背包的项,使得装入背包所有项的价值系数之和达到最大。

  • 功能设计

    • 本项目要求设计一个采用动态规划算法、回溯算法求解D{0-1}背包问题的程序,程序基本功能要求如下:
      1. 可正确读入实验数据文件的有效D{0-1}KP数据;
      2. 能够绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
      3. 能够对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
      4. 用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间;
      5. 任意一组D{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件。
    • 个人项目中,针对其中的一组重量和价值数据实现的功能如下:
      1. 对测试数据中的一组数据进行散点图的绘制;
      2. 计算出价值与重量的比值,并对其进行非递增排序;
      3. 用动态规划算法求出这组数据的最优解;
      4. 计算用动态规划算法求解问题的时间。
  • 设计实现

    • 绘制散点图

      1. 用scatter函数来绘制散点图:

      在使用scatter函数之前需要导入必要的模块:

      import matplotlib.pyplot as plt
      import numpy as np
      

      plt.scatter(weight,profit,s=20)表示横坐标取列表weight中的数据,纵坐标取列表profit中的数据,即表示的点为(重量,价值);s=20表示点的大小。

      2. 设置标签:

      横坐标和纵坐标的标签设置为“Weight”和“Profit”,字体大小为12,颜色是红色。

      plt.xlabel("Weight", fontsize=12,color="r")
      plt.ylabel("Profit",fontsize=12, color='r')
      

      3. 显示散点图:

      plt.show()
      
    • 非递增排序

      调用sorted函数对价值与重量的比值进行排序。

    • 动态规划算法

      1. backpack函数

      capacity表示背包能容纳的商品最大重量,number 表示商品数量,w 数组和 v 数组表示每件商品的重量以及对应的价值。首先初始化二维数组为 0,最后循环将数组中的每个元素进行填充:如果当前背包可容纳的重量小于当前商品的重量,那么背包中的总价值不会变化,否则,可以选择装下当前这件物品或者不装下这件物品,这就可以得到两个价值,那么其中最高的价值就是当前情况下背包能获得的最大价值。

      2. main 函数中的两个for循环(用于找到选择的物品)

      首先初始化一个item数组并全初始化为0,然后循环遍历动态规划得到的数组。如果 result[i] [j]> result[i-1] [j],那么说明第 i-1件物品肯定被选择了,那么就将 item[i-1]设置为1,循环结束后将item中为1的索引输出即可。

    • 求解时间

      start = time.time()
      #running
      end = time.time()
      print end-start 
      

      time.time()获取当前时间,以秒为单位,如果系统时钟提供它们,则可能存在秒的分数,所以这个地方返回的是一个浮点型类型。这里获取的也是程序的执行时间。

  • 测试运行

    • 散点图:

      对idkp1-10.txt文件中的第一组数据IDKP0绘制散点图。初始化背包容量capacity=10149,物品的个数number=30,将第一组数据存放在列表weight和profit中。

      绘制出的散点图如下图所示:

    • 排序:

      先计算出价值与重量的比值:

      然后输出排序后的结果:

    • 动态规划法的求解结果:

      能获取的最大价值是10453,所选取的物品为:第1、2、3、4、5、6、7、12、13、18、22 个物品;所花费的时间是0.3000001907348633s。

  • 代码片段

    • 绘制散点图:

      plt.figure(figsize=(8,6), dpi=80)
      plt.scatter(weight,profit,s=20)
      plt.xlabel("Weight", fontsize=12,color="r")
      plt.ylabel("Profit",fontsize=12, color='r')
      plt.show()
      
    • 动态规划法:

      动态规划算法求解0-1背包问题的最优解:

      def backpack(number, capacity, w, v):
          result = [[0 for i in range(capacity+1)]for i in range(number+1)]
          for i in range(1, number+1):
              for j in range(1, capacity+1):
                  if j < w[i-1]:
                      result[i][j] = result[i-1][j]
                  else:
                      result[i][j] = max(result[i-1][j], result[i-1][j-w[i-1]]+v[i-1])
          return result
      

      在main()函数中循环遍历动态规划得到的数组,找到选择的物品:

      item = [0 for i in range(number+1)]
          j = capacity
          for i in range(1, number+1):
              if result[i][j] > result[i-1][j]:
                  item[i-1] = 1
                  j -= weight[i-1]
          for i in range(number):
              if item[i] == 1:
                  print(str(i+1), end=" ")
      
  • 总结

    1. 自主学习并了解了读取文件的方法,但是本项目要求读取出txt文件中有效的一部分数据,经过很多次尝试也没有实现这个功能,所以实现了针对其中的一组数据的功能设计。
    2. 掌握了绘制散点图的方法,了解了相关的函数;能够计算出价值与重量的比值并进行排序。
    3. 项目要求对价值与重量之比进行非递增排序,我完成了对比值的递减排序,忽略了递减排序与非递增排序之间的区别,通过进一步学习知道了它们的不同之处。
    4. 实现了用动态规划法求解出0-1背包问题的最优解,计算出了求解问题所花费的时间,对最后的结果没有保存在txt文件中;根据对回溯法的理解尝试实现回溯法求解此问题,但是没有求解出最后的结果。
    5. 通过完成这次的个人项目,掌握了PSP流程,但任务三对于我来说难度太大,没有实现项目要求的所有功能。在完成项目任务的过程中,我感受到了我与其他同学之间的差距,自身能力还有很大的欠缺。
  • PSP

    在整个过程中,我的实际时间大多数大于计划时间,有很多任务没有在计划时间之内完成,而且在开发阶段耗时最多。

    任务内容 计划共完成需要的时间(min) 实际完成需要的时间(min)
    计划 15 10
    • 估计这个任务需要多少时间 15 10
    开发 645 695
    • 需求分析 30 30
    • 生成设计文档 25 20
    • 设计复审 40 50
    • 代码规范 20 25
    • 具体设计 70 75
    • 具体编码 320 350
    • 代码复审 120 125
    • 测试 20 20
    报告 85 105
    • 测试报告 20 30
    • 计算工作量 25 25
    • 事后总结及过程改进计划 40 50
posted on 2021-03-31 10:02  Rairy  阅读(129)  评论(1编辑  收藏  举报