201871010133-赵永军 实验二 D{0-1}背包问题项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | 18计师班 |
这个作业要求链接 | 作业要求 |
我的课程学习目标 | 1、掌握软件项目个人开发流程; 2、掌握Github发布软件项目的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | 1、总结《构建之法》第1章、第2章,掌握PSP流程; 2、开发个人项目,并掌握背包问题。 |
项目Github的仓库链接地址 | Github地址 |
任务1:阅读教师博客“常用源代码管理工具与开发工具”内容要求,点评班级博客中已提交相关至少3份作业。
博客发布人 | 链接 |
---|---|
周学铭 | 点评链接 |
郑文潇 | 点评链接 |
魏娜娜 | 点评链接 |
任务2:总结详细阅读《构建之法》第1章、第2章,掌握PSP流程。
第1章
1.1 软件=程序+软件工程
- 程序=数据结构+算法
- 简单的应用程序--->满足这种功能的应用软件--->保证服务质量的软件服务
- 软件工程的要求质量保证、用户体验、国际化和本地化
- 软件工程的工作有源代码管理、配置管理、软件项目的管理、需求分析、软件测试、程序理解、软件维护/服务维护
- 软件企业 = 软件 + 商业模式
- 软件开发的不同阶段
- 玩具阶段
- 业余爱好阶段
- 探索阶段
- 商业软件vs爱好者写的程序
1.2软件工程是什么
软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上的过程。
软件工程包括下列领域: 软件需求分析、软件设计、软件构建、软件测试和软件维护。
软件工程和下列的学科相关: 计算机科学、计算机工程、管理学、数学、项目管理学、质量管理、软件人体工学、系统工程、工业设计和用户界面设计。
1.2.1 软件的特殊性
- 复杂性
- 不可见性
- 易变性
- 服从性
- 非连续性
1.2.2 软件工程与计算机科学的关系
- 计算机科学中偏理论的领域,大多与数学、离散数学、数理逻辑密切相关。
- 计算机科学中偏实践的领域,大多和数据以及其他学科发生关系。
- 软件工程和人的行为、现实社会的需求息息相关。
1.2.3 软件工程的目标——创造“足够好”的软件
- 用户满意度
- 可靠性
- 软件流程的质量
- 可维护性
第2章
软件是由多人合作完成的,不同人员的工作相互有依赖关系。例如,一个人写的模块被其他人写得模块调用。软件的很多错误都来源于程序员对模块功能的误解、疏忽或不了解模块的变化。如何能让自己负责的模块功能定义尽量明确,模块内部的改变不会影响其他模块,而且模块的质量能得到稳定的、量化的保证?单元测试就是一个很有效的解决方法。
2.1单元测试
2.1.1 用VSTS写单元测试
2.1.2 好的单元测试的标准
- 单元测试应该在最基本的功能/参数上验证程序的正确性。
- 单元测试必须由最熟悉代码的人(程序的作者)来写。
- 单元测试过后,机器状态保持不变。
- 单元测试要快(一个测试的运行时间是几秒钟,而不是几分钟)。
- 单元测试应该产生可重复、一致的结果。
- 独立性——单元测试的运行/通过/失败不依赖于别的测试,可以人为构造数据,以保持单元测试的独立性。
- 单元测试应该覆盖所有代码路径。
- 单元测试应该集成到自动测试的框架中。
- 单元测试必须和产品代码一起保存和维护。
2.1.3 回归测试
- 针对一个Bug Fix,我们也要做Regression Test。目的是:
1.验证新的代码的确改正了缺陷
2.同时要验证新的代码有没有破坏模块现有的功能,有没有Regression
2.2效能分析工具
- 两种分析方法:
1.抽样
2.代码注入
2.3个人开发流程
PSP2.1 | |
---|---|
Planning | 计划 |
· Estimate | *估计这个任务需要多少时间 |
Development | 开发 |
· Analysis | *分析需求 |
· Design Spec | *生成设计文档 |
· Design Review | *设计复审(和同事审核设计文档) |
· Coding Standard | *代码规范(为目前的开发制定合适的规范) |
· Design | *具体设计 |
· Coding | *具体编码 |
· Code Review | *代码复审 |
· Test | *测试(包括自测,修改代码,提交修改) |
Record Time Spent | 记录用时 |
Test Report | 测试报告 |
Size Measurement | 计算工作量 |
Postmortem | 事后总结 |
Process Improvement Plan | 提出过程改进计划 |
2.4实践
2.4.1 基本作业:从Hello World开始
2.4.2 实践最简单的项目:WC
- 实现一个简单而完整的软件工具(源程序特征统计程序)
- 进行单元测试、回归测试、效能测试,在实现上述程序的过程中使用相关的工具
- 进行个人软件过程(PSP)的实践,逐步记录自己在每个软件工程环节花费的时间。
- 使用项目管理系统,练习使用其中的事件跟踪系统。(选用TFS,Bugzilla或者Trac,了解原理)
2.4.2.1 WC项目要求
- 程序处理用户需求的模式为:
wc.exe[parament][file_name] - 各个参数的意义:
- 基本功能列表:
wc.exe-c file.c: char count
wc.exe-w file.c: word count
wc.exe-l file.c: line count
2.4.2.2 工作的细分
- 罗马不是一天建成的。三个估计时间。
2.4.2.3 如何保证质量——回归测试
- 手动测试,手工比较。
- 要做到不断地测试,可以把WC的主要功能封装成一个类,然后测试程序调用这个类的主要函数,得出结果并与标准做比较。
- 更进一步,把测试文件和正确的测试结果保存在文件中,测试驱动程序只要比较测试的输出和标准结果就能得出答案。
- 再进一步,把自动构建脚本和构建验证测试结合起来。每一次构建之后,就自动运行测试,然后记录出现的Bug。
2.4.2.4 标准测试集,正确性和速度评比
- 记录实际时间和时间分配。
任务3:个人项目开发
3.1需求分析
- 本次题目主要是通过动态规划算法和回溯算法来求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位),而0/1背包问题对于物品的选择只有两种:装入或者不装入背包。那么如何选择装入背包的物品,使得包中物品的总价值最大?我将使用动态规划算法分以下三步来实现:
- 确定动态规划函数:根据子问题之间的重叠关系找到子问题满足的递推关系式(即动态规划函数),这是动态规划算法的关键。
- 实现对于已有数据集的.txt文件的读取以及对于字符流的处理,使它能够变成我们所能够使用的数据。
3.2功能设计
- 读取文件数据:可正确读入实验数据文件的有效D{0-1}KP数据;
- 绘制散点图:绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
- 排序:对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
- 求解最优解和时间:求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
- 将数据结果保存为txt文件:将一组D{0-1} KP数据的最优解、求解时间和解向量保存为txt文件;
3.3设计实现
- 本次实验设计主要针对5个功能的实现来设计的
- 第一个模块是正确读入数据,用python按行读取;
- 第二个模块则是利用python的matplotlib库中scatter函数轻松实现;
- 第三个模块先是使用dict(zip(list1,list2))生成字典实现价值重量比和物品的对于关系;
- 第四个模块是用动态规划算法;
- 第五个模块是将结果保存在txt文件中。
3.4测试运行
1.读取相应的文件,选择文件中的数据进行图表的绘制
2.在读取的数据中选择某一项数进行按照重量比进行非递增排序
3.分别对于一组数据进行回溯算法和动态规划算法进行计算最优解,并将其结果保存至文件中
3.5代码片段
- 读入数据
def getData():
# -------打开指定文件,读入数据-------
fileName = str(input('请输入文件名'))
file = open(fileName, 'r')
line = file.readline()
while (line):
# 读入一行数据
line = file.readline()
# 如果匹配到profit关键字,则读入下一行的价值信息
if line.__contains__("profit"):
# 去除结尾的换行符,逗号,原点,便于分割
line = file.readline().strip('\n').strip('.').strip(',')
# 将该行数据存入列表
profitData.append(line)
# 如果匹配到weight关键字,则读入下一行的重量信息
elif line.__contains__("weight"):
# 去除结尾的换行符,逗号,原点,便于分割
line = file.readline().strip('\n').strip('.').strip(',')
# 将该行数据存入列表
weightData.append(line)
- 项集第三项的价值:重量比的非递增排序代码如下:
Ratio = [] #项集所有项比值
Ratio_1 = [] #第三项比值排序
n = len(x)
for i in range(n): #将项集的所有项比值存入Ratio
ratio = y[i]/x[i]
Ratio.append(ratio)
for i in range(2, len(Ratio), 3): #将第三项的比值存入Ratio_1
ratio_1 = Ratio[i]
Ratio_1.append(ratio_1)
Ratio_1.sort(reverse=True) #排序
print('排序结果为:',Ratio_1)
- 绘制散点图
#导入必要的模块
import numpy as np
import matplotlib.pyplot as plt
del W[-1]
del V[-1]
x = list(map(int, W)) #将字符型转换为整形
y = list(map(int, V))
plt.scatter(x, y) #画散点图
plt.show()
- 动态规划算法
def pack(w, v, n, c):
dp = [0 for _ in range(c+1)]
for i in range(1, len(w)+1):
for j in reversed(range(1, c+1)):
for k in range(3):
if j-w[i-1][k] >= 0:
# print(dp[j])
dp[j] = max(dp[j], dp[j-w[i-1][k]] + v[i-1][k])
# print(dp)
print(dp[c])
- 保存数据到txt文件
if __name__ == '__main__':
fw = open("result.txt", 'w') # 将要输出保存的文件地址
for line in open("result.txt"): # 读取的文件
fw.write(result)
fw.write("\n") # 换行
- 菜单函数
def menu():
print("1.绘制散点图")
print("2.排序")
print("3.算法实现")
print("4.退出")
task = raw_input("请输入选项进行对应操作")
if task == '1':
user_dict = creating_dictionary()
elif task == '2':
updating_dictionary(user_dict)
elif task == '3':
sorting_dictionary(user_dict)
elif task == '4':
break
3.6总结
- 本次实验我的“模块化”实际上还是一个大程序,一是因为使用Python相比其他语言来说代码少,对于完成本次实验的调试影响不大;二是在实验前我花了大量的时间去分析设计实验;三是由于没有很好的利用好PSP,时间安排出现紧张而最后的时间里仍然坚持自己完成,为节约时间便没有设计独立模块,而是根据自己分析的结果使用大程序里的“模块化”来完成实验,这是我未来要改正的错误,值得总结出来并反思。
3.7通过阅读了解到了个人项目在实施的过程中,PSP的思想及重要性,下面表格为展示的 本次个人项目中的PSP项目规划表格。
PSP 各个阶段 | 自己预估的时间(分钟) | 实际的记录(分钟) |
---|---|---|
计划: 明确需求和其他因素,估计以下的各个任务需要多少时间 | 2*60 | 3*60 |
开发 (包括下面 8 项子任务) | 37*60 | 41*60 |
· 需求分析 (包括学习新技术、新工具的时间) | 3*60 | 3*60 |
· 生成设计文档 (整体框架的设计,各模块的接口,用时序图,快速原型等方法) | 2*60 | 2*60 |
· 设计复审 (和同事审核设计文档,或者自己复审) | 1*60 | 1*60 |
· 代码规范 (为目前的开发制定或选择合适的规范) | 1*60 | 1*60 |
· 具体设计(用伪代码,流程图等方法来设计具体模块) | 3*60 | 4*60 |
· 具体编码 | 25*60 | 25*60 |
· 代码复审 | 1*60 | 2*60 |
· 测试(自我测试,修改代码,提交修改) | 1*60 | 3*60 |
报告 | 1*60 | 2*60 |
测试报告 | 1*60 | 2*60 |
计算工作量 (多少行代码,多少次签入,多少测试用例,其他工作量) | 1*60 | 2*60 |
事后总结, 并提出改进计划 (包括写文档、博客的时间) | 2*60 | 3*60 |
总共花费的时间 (分钟) | 44*60 | 53*60 |
- 本次设计的PSP各个阶段是以小时为单位来估计的,可能存在误差,并且没有记录这些阶段是哪天完成的,导致自己在项目初期没有认真去做,到最后时间才完成了项目,所以我认为在项目开始应该把PSP中各个阶段的具体时间写进去。
- 通过计划与实际的时间来对比,我发现我的编程能力还有待提高,导致我在编码过程中不仅慢,而且还出现了很多问题,导致计划时间与实际时间不相符。
任务4:本次项目提交Github
- 截图