201971010237-尚洁 实验三 结对项目—《{0-1}KP 实例数据集算法实验平台》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | 2019级卓越工程师班 |
这个作业要求链接 | 实验三 软件工程结对项目 |
我的课程学习目标 | (1)体验软件项目开发中的两人合作,练习结对编程 (2)掌握Github协作开发程序的操作方法。 (3)使用Java编写D{0-1}KP 实例数据集算法实验平台 |
这个作业在哪些方面帮助我实现学习目标 | (1)自学《构建之法》第3-4章内容,学习本次作业相关概念。 (2)结对编程,评价对方《实验二 软件工程个人项目》并学习对方优点。 (3)合作开发设计D{0-1}KP 实例数据集算法实验平台。 (4)查阅资料设计遗传算法解决D{0-1}KP。 |
结对方学号-姓名 | 201971010216-李斌 |
结对方本次博客作业链接 | https://www.cnblogs.com/1810067010LB/p/16099849.html |
本项目Github的仓库链接地址 | https://github.com/sj319134578/SJ |
正文:
任务1:阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念
-
代码风格规范:简明,易读,无二义性。
- 缩进:4个空格
- 行宽:100字符
- 括号:复杂的条件表达式中,用括号清楚表示优先级
- 分行:不把多条语句放在一行上,不把多个变量定义在一行上
- 命名:尽量简洁规范
- 下划线:下划线用来分隔变量名字中的作用域标注和变量的语义,如:一个类型的成员变量通常用m.来表示,或者简单地用一个下划线“_”来做前缀。移山公司规定下划线一般不用在其他方面。
- 大小写:所有的类型/类/函数名都用Pascal 形式,所有的变量都用Camel形式类/类型/变量:名词或组合名词,如 Member、ProductInfo 等。函数则用动词或动宾组合词来表示,如 get/set、RenderPage( )。
-
注释:适当注释
-
代码设计规范:函数,goto,错误处理以及如何处理C++中的类。
-
代码复审:看代码是否在“代码规范”的框架内正确地解决了问题。主要有自我复审,团队复审以及同伴复审三种方式。
-
结对编程:两人结对编程,一对程序员肩并肩,平等地,互补地进行开发工作。
任务2:两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价
项目 | 内容 |
---|---|
结对方博客链接 | 201971010216-李斌-实验二 软件工程 个人项目 - 用所学知识解决0/1背包问题 |
结对方Github项目仓库链接 | 仓库 |
-
对结对方的博客评论:
- 博文结构:
整体结构比较简洁,但是排版太乱,后面可以注意一下。 - 博文内容:
完成了大部分实验要求的内容,功能设计模块使用图片示意,较为清晰,详细讲解了各个算法的实现。 - 博文结构与PSP中“任务内容”列的关系:
博文结构与“内容任务”列并非完全对应 - PSP中“计划共完成需要的时间”与“实际完成需要的时间”两列数据的差异化分析与原因探究:
博主提到代码整合到一起回溯有巨大的问题,散点图的相关C++代码也有问题,无法显示,且对github平台的使用不够熟悉,导致实际完成时间与计划共需要的时间不一致。
- 博文结构:
-
克隆项目,阅读并测试
克隆项目至本地文件夹:
将项目导入进行测试
观察到结对方没有完成全部所要求的功能,并未完成数据读取、算法求解部分,和绘制散点图等功能。 -
代码核查表:
项目 | 内容 |
---|---|
概要部分 | |
代码符合需求和规格说明么? | 否,并未完成全部功能 |
代码设计是否考虑周全? | 否 |
代码可读性如何? | 较好 |
代码容易维护么? | 易维护 |
代码的每一行都执行并检查过了吗? | 是 |
设计规范部分 | |
设计是否遵从已知的设计模式或项目中常用的模式? | 是 |
有没有硬编码或字符串/数字等存在? | 有 |
代码有没有依赖于某一平台,是否会影响将来的移植? | 对移植影响较小 |
开发者新写的代码是否用已有的Library/SDK/Framework中的功能实现? | 是 |
在本项目中是否存在类似的功能可以通过调用而不用全部重新实现? | 是 |
有没有无用的代码可以清除? | 有 |
代码规范部分 | |
修改的部分符合代码标准和风格么? | 符合 |
具体代码部分 | |
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常? | 已处理 |
参数传递有无错误,字符串的长度是字节的长度还是字符的长度,是从0开始计数还是从1开始计数 | 无错误;字符的长度;从0开始 |
边界条件是如何处理的?switch语句和default分支是如何处理的?循环有没有可能出现死循环? | 前提分析推导边界条件;无switch语句和default分支;有 |
有没有使用断言来保证我们认为不变的条件真的得到满足? | 没有 |
对资源的利用,是在哪里申请,在哪里释放的?有无可能存在资源泄露?有没有优化的空间? | 有;不存在;有 |
数据结构中有没有用不到的元素? | 有 |
效能 | |
代码的效能如何?最坏的情况是怎么样的? | 效能一般 |
代码中,特别是循环中是否有明显可优化的部分? | 有 |
对于系统和网络的调用是否会超时?如何处理? | 否 |
可读性 | |
代码可读性如何?有没有足够的注释? | 可读性较好 |
可测试性 | |
代码是否需要更新或创建新的单元测试? | 是 |
- 结对方项目仓库中的日志数据
Commits数据:如图所示,帮助结对方完成了背包数据读取与选择的功能,并上传至Github。
- Forks数据:如图所示,对结对方的项目进行了Fork操作
- 将修改提交到指定一方的仓库中
任务3:采用两人结对编程方式,设计开发一款{0-1}KP 实例数据集算法实验平台,使之具有以下功能:
-
需求分析
从若干具有价值系数与重量系数的物品(或项)中,选择若干个装入一个具有载重限制的背包,并使装入物品的重量系数之和在不超过背包载重前提下价值系数之和达到最大。
-
功能分析
1、可读取实验数据,有效呈现所有数据;
2、用读取的数据绘制出以重量为横轴、价值为纵轴的数据散点图;
3、将数据按项集第三项的价值:重量比进行非递增排序;
4、用户能够自主选择动态规划算法、回溯算法求解数据的最优解和求解时间;
5、数据的最优解、求解时间和解向量可保存为txt文件 -
软件设计
1、D{0-1}KP 实例数据集需存储在数据库;
2、平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据;
3、人机交互界面要求为GUI界面;
4、查阅资料,设计遗传算法求解D{0-1}KP,并利用此算法测试要求(3); -
遗传算法
遗传算法(Genetic>遗传算法(Genetic Algorithm,GA)是进化计算的一部分,是模拟达尔文的遗传选择和自然淘汰的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。该算法简单、通用,鲁棒性强,适于并行处理。- 遗传算法的基本步骤是:
(1)初始化:设置进化代数计数器t=0,设置最大进化代数T,随机生成M个个体作为初始群体P(0)。
(2)个体评价:计算群体P(t)中各个个体的适应度。
(3)选择运算:将选择算子作用于群体。选择的目的是把优化的个体直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。选择操作是建立在群体中个体的适应度评估基础上的。
(4)交叉运算:将交叉算子作用于群体。遗传算法中起核心作用的就是交叉算子。
(5)变异运算:将变异算子作用于群体。即是对群体中的个体串的某些基因座上的基因值作变动。群体P(t)经过选择、交叉、变异运算之后得到下一代群体P(t+1)。
(6)终止条件判断:若t=T,则以进化过程中所得到的具有最大适应度个体作为最优解输出,终止计算。- 参考文献:
[1]吴聪聪,贺毅朝,赵建立.求解折扣{0-1}背包问题的新遗传算法[J].计算机工程与应用,2020,56(07):57-66.
[2]杨洋,潘大志,刘益,谭代伦.折扣{0-1}背包问题的简化新模型及遗传算法求解[J].计算机应用,2019,39(03):656-662.
遗传算法伪代码,如下图所示。
- 软件实现及核心功能代码展示
- 连接数据库相关代码(本项目使用了sql server连接数据库)
//函数6:建立数据库连接
public static Connection getConnection() {
Statement stmt;
ResultSet rs;
Connection con = null;
PreparedStatement ps = null ;
try {
out.println("begin connection...");
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=bag","sj","root");
// 建立Statement对象
stmt = con.createStatement();
/**
* Statement createStatement() 创建一个 Statement 对象来将 SQL 语句发送到数据库。
*/
//每次执行插入语句前先删除之前存入的数据
String sql="delete from data ";
//执行SQL删除语句
stmt.executeUpdate(sql);
out.println("已删除之前的数据!\n\n");
//将背包数据插入数据库
out.println("开始插入背包数据...");
int t=0;
for(int i=0; i<n; i++)
{
sql = "insert into data(weight,value) values (?,?)";
ps = con.prepareStatement(sql);
ps.setInt(1, w[i]);
ps.setInt(2, v[i]);
// 执行数据库插入语句
ps.executeUpdate() ;
//stmt.executeUpdate(sql);
t++;
}
out.println("成功插入"+t+"条记录!");
//查询数据库中插入的记录
out.println("查询记录如下:");
sql = "select * from data" ;
/**
* ResultSet executeQuery(String sql) throws SQLException 执行给定的 SQL
* 语句,该语句返回单个 ResultSet 对象
*/
rs = stmt.executeQuery(sql) ;
int w1,v1;
while(rs.next())
{
w1 = rs.getInt(1);
v1 = rs.getInt(2);
out.println("重量" + w1 +" 价值" + v1);
}
out.println("end.");
}
catch (Exception e) {
out.println(e);
}
return con;
}
-
数据库保存部分实现:
-
后台显示记录:
-
保存日志相关关键部分代码
try{
PrintStream mytxt=new PrintStream("./log.txt");
//保存输出日志信息
PrintStream out=System.out;
System.setOut(mytxt);
System.out.println("文档执行的日期是:"+new Date());
// 记录输入输出的记录
System.setOut(out);
mytxt.close();
System.out.println("日期保存完毕(算法结果已保存至log文件)");
}catch(FileNotFoundException e){
e.printStackTrace();
}
-
保存日志文件如下:
-
散点图绘制:
-
前端页面:
- 提供两人在讨论、细化和编程时的结对照片。
- 提供此次结对作业的PSP
任务内容 | 计划共完成需要的时间/分钟 | 实际完成需要的时间/分钟 |
---|---|---|
阅读《现代软件工程—构建之法》第3-4章 | 50 | 55 |
对项目博文作业进行阅读并进行评论 | 20 | 20 |
克隆结对方项目源码到本地机器,阅读并测试运行代码 | 100 | 120 |
依据复审结果用github的Fork、Clone、Push等操作对同伴个人项目仓库的源码进行合作修改 | 90 | 90 |
D{0-1}KP 实例数据集存储在数据库 | 40 | 60 |
将数据库数据读取出来 | 40 | 70 |
用读出来的数据绘制散点图并显示在人机交互页面 | 60 | 270 |
动态规划算法结果显示在前端 | 60 | 120 |
回溯算法结果显示 | 40 | 75 |
将数据项显示在前端,按其第三项进行排序并显示 | 80 | 100 |
平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据 | 100 | 120 |
人机交互界面要求为GUI界面 | 40 | 50 |
查阅资料,设计遗传算法求解D{0-1}KP,并利用此算法测试要求 | 200 | 450 |
- 小结感受
两人合作真的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会。
两人进行合作要比一人进行容易得多。经过这次实验,我发现在真正的结对的情况下,确实会产生1+1>2的情况,因为另一方会从另外一个角度思考,发现对方代码的不足并及时指正。但也存在双方工作没办法平均分配,双方各有擅长的方面,所以在合作时更多的是取长补短,发会合作的优势。