201971010146-杨凯 实验三 结对项目—《{0-1}KP 实例数据集算法实验平台》项目报告

201971010146-杨凯 实验三 软件工程结对项目:

项目 内容
课程班级博客链接 2022年春软件工程课程班(2019级计算机科学与技术)
这个作业要求链接 实验三 软件工程结对项目
我的课程学习目标 1. 体验软件项目开发中的两人合作,联系结对编程(Pair programming)
2. 掌握Github协作开发软件的操作方法
作业帮助我实现学习目标 1. 体会到了软件工程中项目开发的结对编程
2. 学习了github的基本写作开发操作
结对方学号-姓名 201971010235-阮凯
结对方本次博客作业链接 https://www.cnblogs.com/RuanKaio/p/16043732.html
本项目Github的仓库链接地址 dakeb/KpProjectGui (github.com)

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

  1. 风格规范:代码风格的原则是:简明,易读,无二义性。需要注意所经,行款,括号,断行与空白的{}行,分行,命名,下划线,大小写,注释。

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

    • 函数:现代程序设计语言中的绝大部分功能,都在程序的函数(Function、Method)中实现。关于函数,
      最重要的原则是:只做一件事,并且要做好。
    • goto:函数最好有单一的出口,为了达到这一目的,可以使用goto。只要以后住于程序逻辑的清晰体现。
  3. 代码复审:代码复审就是看代码是否在代码规范的框架内正确地解决了问题。包括:

    • 自我复审
    • 同伴复审(最基本的复审手段)
    • 团队复审
  4. 结对编程概念:在阅读文档后,我认为结对编程就是合作编程,达到1+1>2的目的。

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

项目 内容
结对方 阮凯(201971010235)
结对方实验二博客链接 201971010235-阮凯 实验二 软件工程个人项目 《0-1背包问题》
结对方Github项目仓库链接 dp

项目博文作业评论

  1. 博文结构:博文结构清晰,排版整洁。
  2. 博文内容:博文内容充实,基本完成了各个任务,条理清晰。
  3. 博文结构与PSP中“任务内容”列的关系:博文内容并没有与PSP“任务内容”完全对应,但大致的顺序结构相差无几,基本遵循了PSP过程。
  4. PSP中“计划共完成需要的时间”与“实际完成需要的时间”两列数据的差异化分析与原因探究:结对方在Planning、Reporting部分计划与实际所用时间相差不大,相差最大的部分体验在Development部分,该部分的开发实际时间与具体编码时间远远超过了计划所用的时间,由此可见,该同学在代码上的功底还是有些欠缺,在对算法的掌握和应用上也有所欠缺。

克隆结对方项目源码,测试运行:

  1. 克隆项目:
克隆项目
  1. 测试运行:

    结对方的项目在细节上还是有些欠缺,该同学虽然完成了各个部分,排序、算法求解、以及画散点图只能单独运行,但是没有将其整合,在其基础上进行了修改效果如下:

run1

run2



request
  1. 核查表复审:
项目 内容
1. 概要部分
代码符合需求和规格说明吗 完全符合
代码设计是否考虑周全
代码可读性如何 较好
代码容易维护吗 容易
代码的每一行都运行并检查过了吗 已检查
2. 设计规范部分
设计是否遵从从一直的设计模式中常用的模式
有没有硬编码或字符串/数字等的存在
开发者新写的代码能都用已有的Library/SDK/Framework中的功能实现?在本项目中是都存在类似的功能可以调用而不全部重新实现?
有没有无用代码可以清除?
3. 代码规范部分
修改的部分符合代码标准和风格嘛 符合
4. 具体代码部分
有没有对错误进行处理?对于调用的外部函数,是否检查了返回值或处理了异常
参数传递有无错误,字符串的长度是字节的长度还是字符的长度,是以0开始计数还是以1开始计数 无错误,字符长度,从0开始
边界条件是如何处理的?switch语句的default分支是如何处理的?循环有没有可能出现死循环? 未使用switch语句,不会出现死循环
有没有使用断言(Assert)来保证我们认为不变的条件真的得到满足?
对资源的利用,是在哪里申请,在哪里释放的,有无可能存在资源泄露(内存、文件、各种GUI资源、数据库访问链接等)?有无优化的空间。 有相应的申请释放,没有资源泄露
数据结构中有没有用不到的元素
5. 效能
代码的效能如何?最坏情况是怎样的? 代码效能优秀,最坏情况就是无解的情况下,回溯法依旧会考虑所有解
代码中,特别是循环中是否有明显的可优化的部分(C++中反复创建类,C#中string的操作是否能用StringBuilder来优化)
对于系统和网络的调用是否会超时?如何处理? 不会超时
6. 可读性
代码可读性如何?有没有足够的注释? 代码可读性较好,注释较少
7. 可测试性
代码是否需要更新或创建新的单元测试?针对特定领域的开发(如数据库、网页、多线程等),可以整理专门的核查表 不需要

任务三:采用两人结对编程方式,设计开发一款{0-1}KP 实例数据集算法实验平台

一、PSP:
PSP2.1 任务内容 计划共完成需要的时间(min) 实际共完成需要的时间(min)
planning 计划 10 15
Estimate 估计这个任务需要多少时间,并规划大致步骤 10 15
Development 开发 575 825
Analysis 需求分析(包括学习新技术) 30 50
Design Spec 生成设计文档 20 35
Design Review 设计复审(和同事核审设计文档) 30 20
Coding Standard 代码规范(为目前的开发制定合适的规范) 10 30
Design 具体设计 50 40
Coding 具体编码 200 280
Code Review 代码复审 50 40
Test 测试(自我测试,修改代码,提交修改) 60 120
Reporting 报告 60 120
Test Report 测试报告 35 30
Size Measurement 计算工作量 10 15
Postmortem &Process
Improvement Plan
事后总结,并提出过程改进计划 20 35
二、需求分析
  1. 开发人机交互平台,要求为GUI界面(Web界面,APP界面)
  2. 平台基础功能:实验二 任务3
  3. {0-1}KP实例数据集需存储在数据库
  4. 平台可动态嵌入任何一个有效的{0-1}KP实例求解算法,并保存实验算法实验日志数据
  5. 查阅资料,设计遗传算法求解{0-1}KP,并利用此算法 测试要求(4)
  6. 附加功能:除(1)-(5)外的任意有效平台功能实现
三、功能设计
graph LR; 功能设计-->选择文件 功能设计-->选择算法 选择算法-->贪心算法 选择算法-->动态规划 选择算法-->回溯法 选择算法-->遗传算法 功能设计-->画散点图 功能设计-->排序 功能设计-->获取当地时间-->动态打印数据 功能设计-->连接数据库
四、设计实现:
1. 概述
  • 使用python进行开发
  • 界面为python GUI界面
  • 数据库:sql server
2. 详细实现:
graph LR A(开始) B["fileopen(),打开文件,返回文件名"] C["fileoperate(),读文件"] D["goes(), 算法选择"] E["GreedyAlgo(), 贪心算法"] F["Dp(), 动态规划算法"] G["Backtracking(), 回溯法"] H["best_x, 遗传算法"] I["painter()"] J["sort()"] K["get_current_time"] L["write_log_to_Text"] M["db数据库"] A-->B-->C C-->I C-->J C-->K C-->L C-->M C-->D-->E D-->F D-->G D-->H
  1. fileopen():

    使用了askopenfilename()python库函数,可以直接访问计算机的文件夹,并返回文件夹路径。

def fileopen():
    file_sql = askopenfilename()
    if file_sql:
        filename.set(file_sql)
    return filename

  1. fileoperate():

​  该函数分别读取了文件第一行的数据和文件除了第一行的数据并返回,当一个python函数有两个返回值时,是以元组的方式存放的,当运行该函数,fileoperate[0]、fileoperate[1]两个值为函数运行后的值。

def fileoperate():
    # 读取第一行之后的数据
    f = open(filename.get(), 'r')
    res = f.readlines()[1:]
    res = [line.strip("\n") for line in res]
    f1 = open(filename.get(), 'r')
    res1 = f1.readlines()[:1]
    res1 = [line.strip("\n") for line in res1]
    f.close()
    f1.close()
    return res, res1
  1. goes():

  该函数是绑定到Combobox控件的函数,当Combobox做出相应的选择时,goes()函数通过if语句转动相应的函数,执行相应的算法。

  1. 遗传算法:

  遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。是模拟达尔文生物进化论自然选择遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。该算法通过数学的方式,利用计算机仿真运算,将问题的求解过程转换成类似生物进化中的染色体基因的交叉、变异等过程。在求解较为复杂的组合优化问题时,相对一些常规的优化算法,通常能够较快地获得较好的优化结果。遗传算法已被人们广泛地应用于组合优化、机器学习、信号处理、自适应控制和人工生命等领域。

  遗传算法解决(0-1)背包问题:

graph TB A(开始)-->B[初始化种群]-->C[交叉]-->D[变异]-->E[计算适应度函数并轮盘赌选择]-->F{"是否结束?"} F{"是否结束?"}--Y-->G(结束) F{"是否结束?"}--N-->C
##遗传算法
def best_x(F, S, N):
    y = 0
    x = 0
    B = [0] * N
    for i in range(N):
        if y < F[i]:
            x = i
        y = F[x]
        B = S[x]
    return B, y


## 计算比率
def rate(x):
    p = [0] * len(x)
    s = 0
    for i in x:
        s += i
    for i in range(len(x)):
        p[i] = x[i] / s
    return p


## 选择
def chose(p, X, m, n):
    X1 = X
    r = np.random.rand(m)
    for i in range(m):
        k = 0
        for j in range(n):
            k = k + p[j]
            if r[i] <= k:
                X1[i] = X[j]
                break
    return X1


##交配
def match(X, m, n, p):
    r = np.random.rand(m)
    k = [0] * m
    for i in range(m):
        if r[i] < p:
            k[i] = 1
    u = v = 0
    k[0] = k[0] = 0
    for i in range(m):
        if k[i]:
            if k[u] == 0:
                u = i
            elif k[v] == 0:
                v = i
        if k[u] and k[v]:
            # print(u,v)
            q = np.random.randint(n - 1)
            # print(q)
            for i in range(q + 1, n):
                X[u][i], X[v][i] = X[v][i], X[u][i]
            k[u] = 0
            k[v] = 0
    return X


##变异
def vari(X, m, n, p):
    for i in range(m):
        for j in range(n):
            q = np.random.rand()
            if q < p:
                X[i][j] = np.random.randint(0, 2)

    return X
  1. write_log_to_Text():

  该函数时用来动态打印日志的,通过get_current_time()函数返回的本地时间,进行日志记录。

  1. 数据库

  本此实验使用的sql server数据库,连接步骤如下:

   step1: 连接数据库
   step2: 打开游标
   step3: 对数据库进行增删改查
   step4: 关闭游标
   step5: 关闭连接

 sqlconn = pyodbc.connect(DRIVER='{ODBC Driver 17 for SQL Server}',
                             SERVER='xueli',
                             DATABASE='SR',
                             Trusted_Connection='yes'
                             )
    # 连接数据库
    cursor = sqlconn.cursor()  # 打开游标
    cursor.execute("CREATE TABLE hb(\
                   Weight varchar(32) not null,\
                   Value varchar(255) not null,)\
                   ")  # 执行SQL语句
    with open(filename.get()) as f:
        datas = f.readlines()[1:]

    for data in datas:
        txt = re.split(r'[;,\s]\s*', data)
        Weight = txt[0]
        Value = txt[1]
        cursor.execute("INSERT INTO hb(Weight,Value)VALUES('%s','%s')" % (Weight, Value))
    print("数据库插入完成!")
    cursor.execute("SELECT * FROM hb")  # 执行sql语句
    queryResult = cursor.fetchall()  # 查询执行的sql操作
    print(queryResult)
    sqlconn.commit()
    cursor.close()  # 关闭游标
    sqlconn.close()  # 关闭数据库连接
五、测试
1. 整体框架:
2. 文件选择:
3.求最优解:
4. 绘制散点图:
5. 排序:
6. 数据库:

六、结对编程
        
七、提交记录
八、小结感受:

  本次编程收益颇丰,按照PSP过程完成了实验,一改之前的拖沓,可能因为是结对编程的缘故,有同伴督促,上次实验是在最后几天才完成的,而本次实验却进度迅速。此外,在完成实验的过程中,也学习到了很多新的知识如遗传算法,也对以前学到的知识进行了巩固。结对编程过程中,互相督促,互相解决了很多问题,实现了1+1>2的效果。

posted @ 2022-04-03 19:19  丸子头野鸽儿  阅读(59)  评论(4编辑  收藏  举报