201871030125-王芬 实验二 个人项目-《D{0-1}问题》软件项目报告
实验二 个人项目-《D{0-1}问题》软件项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | https://edu.cnblogs.com/campus/xbsf/2018CST |
这个作业要求链接 | https://www.cnblogs.com/nwnu-daizh/p/14552393.html |
我的课程学习目标 | (1)掌握软件项目个人开发流程;(2)掌握Github发布软件项目的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | (1)更加熟练git的相关操作;(2)巩固算法设计的思想;(3)进一步加深对可视化的认识。 |
项目Github的仓库链接地址 | https://github.com/wangfen123325/DP_res |
任务1:阅读教师博客“常用源代码管理工具与开发工具”内容要求,点评班级博客中已提交相关至少3份作业。
任务2:详细阅读《构建之法》第1章、第2章,掌握PSP流程。实际完成需要的时间
PSP参考:https://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html
-
个人软件过程(Personal Software Process,PSP)是一种可用于控制、管理和改进个人工作方式的自我持续改进过程,是一个包括软件开发表格、指南和规程的结构化框架。PSP与具体的技术(程序设计语言、工具或者设计方法)相对独立,其原则能够应用到几乎任何的软件工程任务之中。PSP能够说明个体软件过程的原则; 帮助软件工程师作出准确的计划;确定软件工程师为改善产品质量要采取的步骤;建立度量个体软件过程改善的基准;确定过程的改变对软件工程师能力的影响。
-
按照PSP规程,改进软件过程的步骤首先需要明确质量目标,也就是软件将要在功能和性能上满足的要求和用户潜在的需求。接着就是度量产品质量,有了目标还 不行,目标只是一个原则性的东西,还不便于实际操作和判断,因此,必须对目标进行分解和度量,使软件质量能够"测量"。然后就是理解当前过程,查找问题, 并对过程进行调整。最后应用调整后的过程,度量实践结果,将结果与目标做比较,找出差距,分析原因,对软件过程进行持续改进。
任务3:项目开发
-
开发背景:背包问题(Knapsack Problem,KP)是NP Complete问题,也是一个经典的组合优化问题,有着广泛而重要的应用背景。{0-1}背包问题({0-1 }Knapsack Problem,{0-1}KP)是最基本的KP问题形式,它的一般描述为:从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,如何选择才能使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大?
-
D{0-1} KP 是经典{ 0-1}背包问题的一个拓展形式,用以对实际商业活动中折扣销售、捆绑销售等现象进行最优化求解,达到获利最大化。D{0-1}KP数据集由一组项集组成,每个项集有3项物品可供背包装入选择,其中第三项价值是前两项之和,第三项的重量小于其他两项之和,算法求解过程中,如果选择了某个项集,则需要确定选择项集的哪个物品,每个项集的三个项中至多有一个可以被选择装入背包,D{0-1} KP问题要求计算在不超过背包载重量 的条件下,从给定的一组项集中选择满足要求装入背包的项,使得装入背包所有项的价值系数之和达到最大;D{0-1}KP instances数据集是研究D{0-1}背包问题时,用于评测和观察设计算法性能的标准数据集;动态规划算法、回溯算法是求解D{0-1}背包问题的经典算法。查阅相关资料,设计一个采用动态规划算法、回溯算法求解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文件。
-
一、需求分析
-
0/1背包问题,动态规划算法,回溯算法;
-
从定的文件中读取出正确的数据并保存;
-
读取数据并对数据进行处理,需要用到数据的切片技术;
-
绘制数据散点图要用到数据的可视化技术;
-
将求解出的数据保存或导出文件。
二、功能设计
-
绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
-
对任意一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
-
用户能够自主选择动态规划算法、回溯算法求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
-
任意一组D{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件
三、设计实现
-
在实验过程中,此次实验要求的技术与我在此之前的掌握的技术有一定差距。所以我复习了大学三年级第一学期在《算法设计与分析》课程中学习到的动态规划算法与回溯算法求解0/1背包问题的内容,循序渐进,推进实验的进程。
-
0/1背包问题是给定n个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn}的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。
-
在0/1背包问题中,物品i或者被装入背包,或者不被装入背包,设xi表示物品i装入背包的情况,则当xi=0时,表示物品i没有被装入背包,xi=1时,表示物品i被装入背包。0/1背包问题可以看作是决策一个序列(x1, x2, …, xn),对任一变量xi的决策是决定xi=1还是xi=0。在对xi-1决策后,已确定了(x1, …, xi-1),在决策xi时,问题处于下列两种状态之一:(1)背包容量不足以装入物品i,则xi=0,背包不增加价值;(2)背包容量可以装入物品i,则xi=1,背包的价值增加了vi。 这两种情况下背包价值的最大者应该是对xi决策后的背包价值。
1.动态规划算法求解0/1背包问题
-
动态规划算法的核心思想是:
- 将大问题划分为小问题进行解决,从而一步一步获得最优解的处理算法。
- 动态规划算法与分治算法类似,其基本思想也是将代求问题分解成若干子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
- 与分治算法不同的是,适合于动态规划求解的问题,经分解得到的子问题往往不是互相独立的,即下一个子阶段的求解过程是建立在上一个子阶段的解的基础上,进行进一步的求解。
-
问题举例:
有一个背包,容量为4,现有以下物品
物品 | 重量 | 价值 |
---|---|---|
A | 1 | 1500 |
B | 4 | 3000 |
C | 3 | 20 |
-
关键是掌握动态规划法求解问题时的分析方法,如何从问题导出 解的递推式。 实际上,当导出背包问题的递归式后,后来的工作就简单多了,如何分析背包问题,导出其最优解的递推式,我觉得,这才是最关键的地方!问题分析很重要!
-
要求在不超过容量的前提下使装入背包的物品价值总和最大,且放入的物品不重复。
-
(1)首先我们对问题中的几个变量进行抽象:V a l i {Val_i}Vali表示第i个物品的价值,W i {W_i}Wi表示第i个物品的重量,V(i,j)表示当前背包容量为j,前i个物品最佳组合的价值
-
(2)寻找递推关系:具有两种情况:
包的容量比当前待装入物品重量小,装不下,故此时的价值与前i-1个物品的价值是一样的,即V(i,j)=V(i-1,j);
包的容量足够装入当前待装入物品,需要判断装入后是否达到最大价值,进而决定是否装入,即V(i,j)=max{V(i-1,j),V(i-1,j-W(i))+Val(i))}。其中V(i-1,j)表示不装入,V(i-1,j-W(i))+Val(i))表示装了第i个商品,背包容量减少w(i)但价值增加了Val(i)
- 由以上两条可推出:
- (1) j<W(i) V(i,j)=V(i-1,j)
- (2) j>=W(i) V(i,j)=max{ V(i-1,j),V(i-1,j-W(i))+Val(i) }
先将表格初始化(第一列和第一行元素均为0)
再按照上面的递推式依次进行填表
如:
i=1,j=1,W(1)=1,Val(1)=1500,因为j=W(1),可以装得下,所以V(i,j)=max{V(i-1,j),V(i-1,j-W(i))+Val(i)}=max{0,1500}=1500
i=2,j=2,W(2)=4,Val(2)=3000,因为j<W(2),装不下,所以V(i,j)=1500
i=3,j=4,W(3)=3,Val(3)=2000,因为j>W(3),可以装得下,所以V(i,j)=max{V(i-1,j),V(i-1,j-W(i))+Val(i)}=max{3000,1500+2000}=3500如此重复直到填表完成
物品/重量 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 |
A(1) | 0 | 1500 | 1500 | 1500 | 1500 |
B(2) | 0 | 1500 | 1500 | 1500 | 2000 |
C(3) | 0 | 1500 | 1500 | 2000 | 3500 |
通过观察表格,我们可以发现,价值达到最大的方案即装入1和3,总价值为3500。
2.回溯算法求解0/1背包问题
-
顾名思义,回溯法一个很显著的特征就是回溯,即在处理完某种情况或出现不能继续进行的情况时,要退回到之前的某个“交叉口”,处理另一种可能。
-
回溯法是一种非常有效的方法,有“通用的解题法”之称。它有点像穷举法,但是更带有跳跃性和系统性,他可以系统性的搜索一个问题的所有的解和任一解。回溯法采用的是深度优先策略。通常,回溯法会定义一个解空间,这个解空间通常是以图或树的形式呈现出来的。背包问题的解空间是树的形式,属于深度优先搜索。
-
回溯法在确定了解空间的结构后,从根结点出发,以深度优先的方式搜索整个解空间,此时根结点成为一个活结点,并且成为当前的扩展结点。每次都从扩展结点向纵向搜索新的结点,当算法搜索到了解空间的任一结点,先判断该结点是否肯定不包含问题的解(是否还能或者还有必要继续往下搜索),如果确定不包含问题的解,就逐层回溯;否则,进入子树,继续按照深度优先的策略进行搜索。当回溯到根结点时,说明搜索结束了,此时已经得到了一系列的解,根据需要选择其中的一个或者多个解即可。
-
回溯法解决问题一般分为三个步骤:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先的方式搜索解空间。
-
问题举例:
有一个背包,容量为30,现有以下物品
物品 | 重量 | 价值 |
---|---|---|
A | 0 | 0 |
B | 15 | 10 |
C | 25 | 5 |
D | 40 | 20 |
E | 20 | 2 |
F | 15 | 14 |
G | 24 | 23 |
我们可以发现,价值达到最大的方案即装入2和7,总价值为24
四、测试运行
1.动态规划算法
2.回溯算法
3.DP_01问题
五、代码展示
1.动态规划算法
for (int i = 1; i < v.length; i++) {//从i=1开始
for (int j = 1; j < v[0].length; j++) {//从j=1开始
if (w[i - 1] > j) {
v[i][j] = v[i - 1][j];
} else {
v[i][j] = Math.max(v[i - 1][j], val[i-1] + v[i - 1][j - w[i-1]]);
if (v[i - 1][j] < val[i - 1] + v[i - 1][j - w[i - 1]]) {
v[i][j] = val[i - 1] + v[i - 1][j - w[i - 1]];
path[i][j] = 1;
} else {
v[i][j] = v[i - 1][j];
}
}
}
}
2.回溯算法
public static void BackTrack(int t) {
if(t>count) {//到达叶结点
if(cp>bestp) {
for(int i = 1;i<=count;i++) {
bestx[i] = cx[i];
}
bestp = cp;
}
return;
}
r -= p[t];
if(cw + w[t] <= c) {//搜索左子树
cx[t] = 1;
cp += p[t];
cw += w[t];
BackTrack(t+1);
cp -= p[t];//恢复现场
cw -= w[t];//恢复现场
}
if(cp + r >bestp) {//剪枝操作
cx[t] = 0;//搜索右子树
BackTrack(t+1);
}
r += p[t];//恢复现场
}
3.D{0-1}问题
with open('C://Users//WANGFEN//Desktop//123.txt') as f:
file = f.read()
pattern=re.compile('408.+1948')
result=pattern.findall(file)
#将txt文件转换成数组形式保存
for fields in result:
fields=fields.strip();#fields.strip()用来删除字符串两端的空白字符。
fields=fields.strip("\n"); # fields.strip("[]")用来删除字符串两端方括号。
fields=fields.split(","); # fields.split(",")的作用是以逗号为分隔符,将字符串进行分隔。
print(fields)
lists.append(fields)
tracks = np.array(lists)
boxes = tracks[:,2:6]#读入边界框坐标
print(boxes)
六、总结
- 这次实验要用到动态规划算法、回溯算法、数据切片技术以及可视化技术。我在大学三年级第一学期在《算法设计与分析》课程中学习过动态规划算法与回溯算法,所以这部分内容相对来说较为熟悉。而可视化技术在之前的项目中接触较少,所以较为陌生,上网查阅资料对其有了一定的了解。
- 可视化(Visualization)是利用计算机图形学和图像处理技术,将数据转换成图形或图像在屏幕上显示出来,并进行交互处理的理论、方法和技术。它涉及到计算机图形学、图像处理、计算机视觉、计算机辅助设计等多个领域,成为研究数据表示、数据处理、决策分析等一系列问题的综合技术。目前正在飞速发展的虚拟现实技术也是以图形图像的可视化技术为依托的。
- 可视化技术最早运用于计算机科学中,并形成了可视化技术的一个重要分支——科学计算可视化(Visualization in Scientific Computing)。科学计算可视化能够把科学数据,包括测量获得的数值、图像或是计算中涉及、产生的数字信息变为直观的、以图形图像信息表示的、随时间和空间变化的物理现象或物理量呈现在研究者面前,使他们能够观察、模拟和计算。
七、PSP流程
PSP2.1 | 任务内容 | 计划完成所需要的时间(min) | 实际完成所需要的时间(min) |
---|---|---|---|
Planning | 计划 | 30 | 27 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 27 |
Development | 开发 | 830 | 1035 |
Analysis | 需求分析(包括学习新技术) | 120 | 120 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 (和同事审核设计文档) | 10 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 15 |
Design | 具体设计 | 240 | 180 |
Coding | 具体编码 | 300 | 480 |
Code Review | 代码复审 | 60 | 50 |
Test | 测试(自我测试,修改代码,提交修改 | 60 | 150 |
Reporting | 报告 | 120 | 130 |
Test Report | 测试报告 | 40 | 40 |
Size Measurement | 计算工作量 | 40 | 30 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 40 | 60 |
Planning | 计划 | 30 | 27 |
Planning | 计划 | 30 | 27 |
Planning | 计划 | 30 | 27 |
Planning | 计划 | 30 | 27 |
任务4:完成任务3的程序开发,将项目源码的完整工程文件提交到你注册Github账号的项目仓库中。(50分)
总结:
-
通过任务一对其他同学博客的评论以及其他同学对我的博客的评论,使我清楚地了解到我的博客中存在的问题,以及需要改正的地方。
-
这次实验,虽然没有将实验要求的所有内容都实现。但是,我在此过程中复习巩固了动态规划算法和回溯算法,对数据切片技术也有了较为深刻的理解,并且对可视化技术有了更进一步的学习掌握。动态规划问题关键是掌握动态规划法求解问题时的分析方法,如何从问题导出 解的递推式。 实际上,当导出背包问题的递归式后,后来的工作就简单多了,如何分析背包问题,导出其最优解的递推式,我觉得,这才是最关键的地方!问题分析很重要!
-
熟练git的相关操作; 熟练markdown编辑器的使用方法。
-
总的来说,这次实验让我学到了很多知识,使我更加的充实。但是部分实验内容没有完成,自身的能力还需要提升。