201871030118-雷云云 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

项目 内容
课程班级博客 班级链接
这个作业要求链接 作业链接
我的课程学习目标 (1)体验软件项目开发中的两人合作,练习结对编程
(2)掌握Github协作开发程序的操作方法
(3)学习遗传算法
这个作业在哪些方面帮助我实现学习目标 通过阅读《现代软件工程—构建之法》第3-4章内容,让我理解了结对编程的意义;理解并掌握了代码规范。其次,通过此次作业,我对GitHub的使用更加熟悉和掌握。
结对方学号-姓名 208171030140-朱婷婷
结对方本次博客作业链接 结对方博客链接
本项目Github的仓库链接地址 仓库链接

任务1.阅读《现代软件工程—构建之法》第3-4章内容,理解并掌握代码风格规范、代码设计规范、代码复审、结对编程概念

  • 代码规范的意义
    • 修改方便
    • 可读性好
  • 代码风格规范原则:简明、易读、无二义性;注意事项

    • 缩进;4个空格的距离从可读性来说,刚好。Tab键在不同的情况下会显示不同的长度,严重干扰阅读体验
    • 行宽;行宽必须限制,但是以前有些文档规定的80字符行宽太小了(以前的计算机/打字 机显示行宽为80字符),现在时代不同了,可以限定为100字符。
    • 括号;在复杂的条件表达式中,用括号会清楚地表示逻辑优先级
    • 断行和与{};为了代码的可读性更好,一般情况下会“{”和“}”都会单独占一行。
    • 分行;不要把多条语句放在一行,尽量一条语句占一行。
    • 命名
    • 下划线;下划线用来分隔变量名字中的作用域标注和变量的语义。
    • 大小写;由多个单词组成的变量名,如果全部都是小写,很不易读,一个简单的解决方案就是用大小写区分它们。
    • 注释;注释是为了解释程序做什么(What),为什么这样做(Why),以及要特别注意的地方。另外,注释(包括所有源代码)应该只用ASCII字符,不要用中文或其他特殊字符,否则会极大地影响程序的可移植性。还有,注释也要随着程序的修改而不断更新,一个误导的(Misleading)注释往往比没有注释更糟糕。
  • 代码设计规范

    代码设计规范不光是程序书写的格式问题,而且牵涉到程序设计、模块之间的关系、设计模式等方方面面,这里又有不少内容与具体程序设计语言息息相关(如 C、C++、Java、C#),但是也有通用的原则。原则如下:

    • 函数;遵循一个函数只做好一件事。
    • goto;使用goto可以使得函数有一个出口。
    • 错误处理;程序完成主要功能后,应该还需要一些错误处理的功能,如:参数处理在Debug版中,所有的参数都要验证其正确性;其次,断言如何验证正确性?那就要用断言(Assert)。断言和错误处理是什么关系?当你觉得某事肯定如何时,就可以用断言。
    • 如何处理C++中的类
  • 代码复审

    • 代码复审的定义:看代码是否在“代码规范”的框架内正确地解决了问题。

    • 代码复审的形式

      名称 形式 目的
      自我复审 自己 vs 自己 用同伴复审的标准来要求自己。
      不一定最有效,因为开发者对自己总是过于自信。如果能持之以恒,则对个人有很大好处。
      同伴复审 复审者 vs 开发者 简便易行
      团队复审 团队 vs 开发者 有比较严格的规定和流程,适用于关键的代码,以及复审后不再更行代码
      覆盖率高—有很多双眼睛盯着程序,但效率可能不高(全体人员都要到会)
    • 代码复审的目的

      • 找出代码错误
      • 发现逻辑错误
      • 发现算法错误
      • 发现可能需要改进的错误
      • 教育(互相教育)开发人员,传授经验,让更多的成员熟悉项目各部分的代码,同时熟悉和应用领域相关的实际知识。
    • 代码复审的意义

      • 代码复审也还有“教育”和“传播知识”的作用。更重要的是,不管多么厉害的开发者都会或多或少地犯一些错误,有欠考虑的地方,如果有问题的代码已签入到产品代码中,再要把所有的问题找出来就更困难了。大家学习软件工程都知道,越是项目后期发现的问题,修复的代价越大。代码复审正是要在早期发现并修复这些问题。另外,在代码复审中的提问与回应能帮助团队成员互相了解,就像练武之人互相观摩点评一样。团队中有新成员加入时,代码复审能非常有效地帮助新成员了解团队的开发策略、编程风格及工作流程。
  • 结对编程

    • 结对编程让两个人所写的代码不断地处于“复审”的过程,程序员们能够不断地审核,提高设计和编码质量,可以及时发现并解决问题,避免把问题拖到后面的阶段去。
    • 结对编程是个渐进的过程——有效率的结对编程不是一天就能做到的。结对编程是一个相互学习、相互磨合的渐进过程。开发人员需要时间来适应这种新的开发模式。一开始,结对编程很可能不比单独开发效率更高,但是在度过了学习阶段后,结对编程小组的开发质量、开发时间通常比两人单独开发有明显的改善。
    • 两人合作的各个阶段:萌芽阶段 → 磨合阶段 → 规范阶段 → 创造阶段 → 解体阶段。

任务2.两两自由结对,对结对方《实验二 软件工程个人项目》的项目成果进行评价

1.博客评论链接

点评链接

2.代码复审

  • 结对方的代码符合代码规范;每个函数之间有空行,代码可读性高;

  • 代码的每一行都检查过了

  • 设计遵从已知的设计模式,代码依赖于python的集成开发环境;

  • 在本项目中是存在类似的功能可以调用而不用全部重新实现,且无无用的代码;

  • 测试:未输出选取的物品有哪些

  • 3.对结对伙伴源码修改

    源代码除了没有实现的功能外,已有代码不需要修改。

  • 对结对方代码进行fork

  • 对结对方代码进行pull request

任务三.采用两人结对编程方式,设计开发一款D{0-1}KP 实例数据集算法实验平台,使之具有以下功能:

1.平台基础功能:实验二 任务3;

2.D{0-1}KP 实例数据集需存储在数据库;

3.平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据;

4.人机交互界面要求为GUI界面(WEB页面、APP页面都可);

5.查阅资料,设计遗传算法求解D{0-1}KP,并利用此算法测试要求(3);

6.附加功能:除(1)-(5)外的任意有效平台功能实现。

1.需求分析陈述

继个人项目后,主要的需求分析在人机交互的界面和遗传算法。

  • 平台基础功能:实验二中的任务3

  • D{0-1}KP实例数据集存储到数据库:

  • 平台可动态嵌入任何一个有效的D{0-1}KP 实例求解算法,并保存算法实验日志数据:

  • 人机交互界面要求为GUI界面:

  • 设计遗传算法求解D{0-1}KP:

2.软件设计说明

  • GUI界面,主要提供选择算法解决D{0-1}KP问题,以及显示结果。

  • 在个人项目基础上,把没有实现的回溯算法和将结果保存到txt文档中,在本次实验中实现了。

  • 遗传算法:

    • 介绍:是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。该算法通过数学的方式,利用计算机仿真运算,将问题的求解过程转换成类似生物进化中的染色体基因的交叉、变异等过程。是一种近似算法。

    • 基本框架:编码—适应度函数—初始群体选取

      • 编码:由于遗传算法不能直接处理问题空间的参数,因此必须通过编码将要求解的问题表示成遗传空间的染色体或者个体。这一转换操作就叫做编码,也可以称作(问题的)表示

        评估编码策略常采用以下3个规范:

        1.完备性

        2.健全性

        3.非冗余性

      • 适应度函数:进化论中的适应度,是表示某一个体对环境的适应能力,也表示该个体繁殖后代的能力。遗传算法的适应度函数也叫评价函数,是用来判断群体中的个体的优劣程度的指标,它是根据所求问题的目标函数来进行评估的。

        适应度函数的设计主要满足以下条件:

        1.单值、连续、非负、最大化

        2.合理、一致性

        3.计算量小

        4.通用性强。

      • 初始群体选择:遗传算法中初始群体中的个体是随机产生的。一般来讲,初始群体的设定可采取如下的策略:

        1).根据问题固有知识,设法把握最优解所占空间在整个问题空间中的分布范围,然后,在此分布范围内设定初始群体。

        2).先随机生成一定数目的个体,然后从中挑出最好的个体加到初始群体中。这种过程不断迭代,直到初始群体中个体数达到了预先确定的规模。

    • 应用领域

      • 函数优化
      • 组合优化
      • 车间调度

3.软件实现及核心功能代码展示:软件包括哪些类,这些类分别负责什么功能,他们之间的关系怎样?类内有哪些重要的方法,关键的方法是否需要画出流程图?

1).软件共包括两个类,一个是写动态规划算法,另一个是回溯算法;每个类里面就是写各个算法的实现功能。
2).软件核心代码展示

  • 选择算法
print('选择动态规划解决请按 1 :')
print('选择回溯法解决请按 2 :')
print('请输入你的选项:')
x=input()
if x=='1':
    #选择动态规划算法解决0-1背包问题
elif x=='2':
    #选择回溯算法解决0-1背包问题
else:
    print("输入错误!")
  • 动态规划算法
    def __init__(self, w, v, c):
        self.w = w
        self.v = v
        self.c = c

    def dynamic_programming(self):
        self.v = np.array(self.v)
        self.w = np.array(self.w)
        num = self.v.size   #物体数量
        values = np.zeros([num+1, self.c+1])
        for i in range(values.shape[0]):
            values[i, 0] = 0
        for i in range(values.shape[1]):
            values[0, i] = 0

        for i in range(1, values.shape[0], 1):
            for j in range(1, values.shape[1], 1):
                if(self.w[i - 1] > j):   #如果物体重量大于包当前重量,不装进去
                    values[i,j] = values[i-1, j]
                else:
                    if(values[i-1, j] > values[i-1, j-self.w[i - 1]] + self.v[i - 1]):
                        values[i,j] = values[i-1, j]
                    else:
                        values[i,j] = values[i-1, j-self.w[i - 1]] + self.v[i - 1]
        return values

    def load_which(self, values):
        h = values.shape[0]

        c = self.c
        which = []

        for i in range(h-1, 0, -1):
            if(values[i,c] == values[i-1,c]):
                continue
            else:
                which.append(i)
                c = c - self.w[i - 1]
        which.reverse()
        return which, values[values.shape[0]-1, values.shape[1]-1]
  • 回溯算法
class backTrackingMethod:
    def __init__(self, w, v, c, cw, cp, bestp):
        self.w = np.array(w)
        self.v = np.array(v)
        self.c = c
        self.cw = cw
        self.cp = cp
        self.bestp = bestp

    def value_per(self):
        per = self.v / self.w
        sor = np.sort(per)
        index = np.argsort(per)

        list = []
        for i in sor:
            list.append(i)
        list.reverse()

        list1 = []
        for i in index:
            list1.append(i)
        list1.reverse()
        index = np.array(list1)


        a = self.v.copy()
        b = self.w.copy()
        for i in range(self.v.size):
            a[i] = self.v[index[i]]
            b[i] = self.w[index[i]]

        self.v = a.copy()
        self.w = b.copy()

        return self.v, self.w, index

    def bound(self, i):
        leftw = self.c - self.cw
        bestbound = self.cp
        while (i < self.v.size):
            if (self.w[i] <= leftw):
                bestbound = bestbound + self.v[i]
                leftw = leftw - self.w[i]
                i += 1
            else:
                bestbound = bestbound + self.v[i] / self.w[i] * leftw
                break
        return bestbound

    def back_tracking(self, i, visit):

        if(i > self.v.size-1):
            self.bestp = self.cp
            return

        if(self.cw + self.w[i] < self.c):
            self.cw += self.w[i]
            self.cp += self.v[i]
            visit[i] = 1
            self.back_tracking(i+1, visit)
            self.cw -= self.w[i]
            self.cp -= self.v[i]
        else:
            visit[i] = 0

        if(self.bound(i+1) >= self.bestp):
            self.back_tracking(i+1, visit)
        return visit, self.bestp

4.程序运行:程序运行时每个功能界面截图。扩展功能实现可得附加分5分。

  • 选择动态规划法



  • 选择回溯法



5.描述结对的过程,提供两人在讨论、细化和编程时的结对照片(非摆拍)。


6.提供此次结对作业的PSP。

PSP各阶段 预计完成时间(h) 实际完成时间(h)
计划 0.5 0.5
开发 64.5 74
-需求分析 1 1.5
-生成设计文档 2 2
-设计复审 3 3.5
-代码规范 1 2
-具体设计 2.5 3
-具体编码 35 40
-代码复审 8 7
-测试 12 15
报告 1.9 2.6
-测试报告 0.3 0.5
-计算工作量 0.6 0.6
-事后总结,并提出改进计划 1 1.5

7.小结感受:两人合作真的能够带来1+1>2的效果吗?通过这次结对合作,请谈谈你的感受和体会。

1.通过这次的结对作业,明显感觉比个人项目完成的情况好许多。我觉得两人合作是能够带来1+1>2的效果的,因为在软件开发过程中,每个人都有明确的任务。

2.在此次合作中,我们在相互交流、相互学习,结对编程对于我而言,就是一个学习和自我认知提高的过程。

3.虽然没有完成遗传算法的编写,但是也通过此次实验,对遗传算法有了了解及认识。

4.遇到问题时,比一个人的时候更容易解决,毕竟三个臭皮匠顶过诸葛亮嘛。

5.在本次实验中,web页面和数据库部分没有完成,还需要进一步学习和完善。同时,这也体现了自己在很多方面的不足,需要进一步的学习和实践。

posted @ 2021-04-14 08:27  201871030118-雷云云  阅读(216)  评论(1编辑  收藏  举报