201971010140-魏瑾川 实验二 软件工程个人项目—01背包问题项目报告

前文

项目 内容
课程班级博客链接 2019级卓越工程师班
这个作业要求链接 实验二 软件工程个人项目
我的课程学习目标
  • 调研常用源代码管理工具和开发工具
  • 使用Github来管理源代码
  • 掌握软件工程的发布流程
这个作业在哪些方面帮助我实现学习目标
  • 通过D{0-1}问题这一项目,对软件项目个人开发流程进行实战
  • 通过将完成的D{0-1}问题项目上传至Github,对发布软件项目的方法进行掌握
项目Github的仓库链接地址 仓库链接

任务1:阅读教师博客,点评班级博客中相关作业

任务2:总结详细阅读《构建之法》第1章、第2章,掌握PSP流程

  1. 第一章:主要详细讲解了什么是软件工程

    • 软件 = 程序 + 软件工程:
      邹欣老师首先解释了什么是“软件”,什么是“程序”,为我们介绍了软件工程的概念。最后讲述了软件开发的不同阶段,引出了什么是软件工程这个问题。

    • 软件工程的定义:
      软件工程的特殊性:复杂性,不可见性,易变性,服从性,非连续性;
      软件工程的知识领域、软件工程的三大类基础知识领域:计算基础,数学基础和工程基础;
      软件工程的目标:用户满意度,可靠性,软件流程的质量,可维护性。

  2. 第二章:主要讲解了PSP(个人软件开发流程)

    • PSP特点:
      • 不局限于某一种软件技术,而是着眼于软件开发的流程。
      • 不依赖于考试,而是依赖工程师自己收集数据,然后分析,提高。
      • 依赖于数据
    • PSP作用:
      PSP可以帮助软件工程师在个人的基础上运用过程的原则,借助于PSP提供的一些度量和分析工具,了解自己的技能水平,控制和管理自己的工作方式,使自己日常工作的评估、计划和预测更加准确、更加有效,进而改进个人的工作表现,提高个人的工作质量和产量,积极而有效地参与高级管理人员和过程人员推动的组织范围的软件工程过程改进。
  3. 该项目的PSP

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

任务3:项目开发

  1. 项目内容:

    从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,如何选择才能使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大?

  2. 需求分析:

    通过对需求文档进行分析,得到系统有如下功能:

    • 用户可以正确读入实验数据文件;
    • 需要能以画出任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
    • 能够对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
    • 用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
    • 任意一组D{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件并且导出;
  3. 功能设计:

    根据需求分析,该软件的功能设计图如下:

    功能设计图

    各功能主要内容如下:

    • 数据输入与处理 :用户可以选择任意一组数据进行处理,并且可以选择自己想要的算法;
    • 排序:主要使用快速排序实现,算法的时间复杂度为\(O(nlogn)\)
    • 散点图绘制 :散点图绘制主要使用 Python 中的 Matplotlib库 来进行绘制;
    • 文件保存:可以将运行结果保存为txt文件;
    • 算法:
      • 动态规划: 求出动态转移方程,并优化为一维,算法的时间复杂度为\(O(nm)\)
      • 贪心算法: 按照 价值/重量 进行排序,依次装入性价比最高的物品,算法的时间复杂度为\(O(n)\)
      • 回溯算法: 将物品看作不同的二进制数来进行枚举搜素,算法的时间复杂度为\(O(n!)\)
  4. 设计实现:

    该系统运行过程如下:

    流程图

    • Main函数 :程序主函数;

    • DP函数:动态规划函数,将传入的数据按照动态规划算法来运行出结果;

    • Greed函数 :贪心算法函数,将传入的数据按照贪心算法来运行出结果;

    • DFS函数 :回溯算法函数,将传入的数据按照回溯算法来运行出结果;

  5. 代码规范:

    项目 规则
    缩进 使用 tab 作为缩进
    变量命名 (1). 均不能以下划线开始,也不能以下划线结束; (2). 禁止英文与拼音混用,仅允许纯拼音或纯英文; (3). 采用类驼峰形式,命名首字母可小写,如 getMaxWeightWriteFile; (4). 允许单个小写英文字母的命名; (5). 允许纯大写英文字母的命名
    每行最多字符数 单行字符数限制不超过256个
    函数最大行数 单个函数行数限制不超过120行
    函数、类命名 (1). 均不能以下划线开始,也不能以下划线结束; (2). 禁止英文与拼音混用,仅允许纯拼音或纯英文; (3). 采用类驼峰形式,命名首字母可小写,如 getMaxWeightWriteFile; (4). 允许纯大写英文字母的命名
    常量 同变量命名规则
    空行规则 (1). 引入头文件其间部分不允许空行; (2). 静态变量/常量定义后跟一空行; (3). 每个函数后跟一空行,除非是最后一个函数; (4). 若函数为空,中间包含一空行; (5). 其余除为了代码美观的空行,均不允许空行出现
    注释规则 (1). 行内注释可使用#...形式; (2). 函数前部注释需使用## 内容 ##形式
    操作符前后空格 (1). if/for/while/switch/do等保留字与左右括号之间都必须加空格; (2). 其余运算符左右均不加空格
    其他规则 (1). 左大括号前不换行; (2). 右大括号前换行
  6. 代码展示:

    • 动态规划算法代码展示:

      def dp(N, V, v, w):
          # 程序开始运行时间计算
          start = time.time()
      
          # 动态规划
          f = [0] * (V + 1)
          for i in range(1, N+1):
              for j in range(V, v[i]-1,-1):
                  f[j] = max(f[j], f[j-v[i]]+w[i])
      
          # 程序结束运行时间计算
          end = time.time()
      
          print("使用动态规划算法所得的最高价值为{:d},运行时间为{:f}s;".format(f[V], (end - start)))
      
    • 贪心算法代码展示:

      def greed(N, V, v, w):
          # 程序运行时间
          start = time.time()
      
          # 贪心算法
          r = [0] * (N+1)
          for i in range(1, N+1):
              r[i] = w[i] / v[i]
      
          for i in range(1, N):
              for j in range(i+1, N+1):
                  if r[i] < r[j]:
                      tmp_v = v[i]
                      tmp_w = w[i]
                      tmp_r = r[i]
                      v[i] = v[j]
                      w[i] = w[j]
                      r[i] = r[j]
                      v[j] = tmp_v
                      w[j] = tmp_w
                      r[j] = tmp_r
      
          res = 0
          for i in range(N, 0, -1):
              if v[i] <= V:
                  res = res + int(r[i]*v[i])
                  V -= v[i]
      
          # 程序结束运行时间计算
          end = time.time()
      
          print("使用贪心算法所得的最高价值为{:d},运行时间为{:f}s;".format(res, end - start))
      
    • 回溯算法代码展示:

      def backtrack(v, w, c, n, x, i):
          global bestV, currV, currW
          if i>= n:
              if bestV < currV:
                  bestV = currV
          else:
              if currW+w[i] <= c:
                  x[i]=1
                  currW += w[i]
                  currV += v[i]
                  backtrack(v, w, c, n, x, i+1)
                  currW -= w[i]
                  currV -= v[i]
              x[i] = 0
              backtrack(v, w, c, n, x, i+1)
      
    • 散点图代码展示:

      # 绘制散点图
      plt.style.use('seaborn')
      fig, ax = plt.subplots()
      ax.scatter(v, w, s=10)
      plt.xlabel('体积', fontproperties='KaiTi')
      plt.ylabel('价值', fontproperties='KaiTi')
      plt.title('体积与价值变量散点图', fontproperties='KaiTi')
      plt.show()
      
    • 导出txt文件代码展示:

      # 写入txt文件
      s = "使用回溯算法所得的最高价值为{:d},运行时间为{:f}s;".format(f[V], end - start) + "\n"
      file = open('data/txt/dfs.txt', 'w')
      file.write(s)
      file.close()
          
      s = "使用动态规划算法所得的最高价值为{:d},运行时间为{:f}s;".format(f[V], (end - start)) + "\n"
      file = open('data/txt/dp.txt', 'w')
      file.write(s)
      file.close()
      
      for i in range(1, len(lines)):
      s = "第{:d}个物品的价值比为:{:.6f};".format(i,r[i])
          file.write(s + "\n")
          print(s)
      
  7. 测试运行:

    以第二组测试数据为例:

    • 动态规划算法结果:

      动态规划

    • 贪心算法结果:

      贪心算法

    • 回溯算法结果:

      回溯算法

    • 散点图绘制:

      散点图

    • 文件保存:

      文件保存

  8. 项目总结

    本次软件工程项目可谓是收获满满,不但对已有的知识进行了温习,也对软件工程的这门课有了更新的理解和认识,在此次项目中,最让我印象深刻的是如何将数据在准确的情况下又能增长其观赏性,无奈水平有限,可能最后实现的效果不是更好,期待在以后的学习生活中学习到更多的知识,完善此次项目,让自己的能力得到增长。

任务4:完成任务3的程序开发并将项目Github账号的项目仓库中

  • 创建Github仓库:登录Github网站,创建一个新的Github仓库来存放代码(PS:Github上网特别慢,大家有条件的可以FQ,或者创建国内链接方式)。

    Git1

  • 本地初始化Github仓库,并配置信息,创建仓库成功后,Github会出现初始配置的命令,统统复制粘贴到我们的终端里,由于我使用的Pycharm有Git的插件,所以填写密码的时候会自动激活,编辑器本身会帮你把密码保存下来,如果只采用终端来配置还会多加一步配置密码。

    Git2

    Git3

  • 每次编辑代码后,我们可以使用git status来查看本地仓库的状态。

    Git4

  • 查看完状态后我们使用git add .来把修改的部分加入到本地文件夹,此时我们再使用git status命令来查看就会发现变化出现了。

    Git5

  • 接下来我们使用git commit -m"给你自己看的信息"来将暂存区的内容提交到当前分支。

    Git6

  • 最后我们使用git push来提交我们暂存区的内容,然后我们就能惊喜的发现,超时了!!! 所以我们要多试几次,因为Github服务器在国外。FQ情况下多试几次就好了!如果试了好几次都没反应,那么就用git push -u命令!(-u一般是第一次push需要添加,后面不添加也可以,但是不知道为啥push三次后再加-u成功率特别高,可能科学的尽头就是玄学吧=^=)

    Git7

    Git8

  • 提交成功后就你的代码就保存到Github里面了!以下是我在本次项目中的一些记录:

    • 此次项目总共使用了12次commit

      Git9

    • 此次项目总共发布了两条issues

    Git10

posted @ 2022-03-19 10:12  喝粥不吃枣  阅读(191)  评论(2编辑  收藏  举报