软工作业2:个人项目

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13229
这个作业的目标 <完成个人项目:设计一个论文查重算法>

Github链接

https://github.com/huangyanyi172/ruangong/tree/main/3222004767

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 30
Estimate 估计这个任务需要多少时间 370 420
Development 开发 300 360
Analysis 需求分析 (包括学习新技术) 100 120
Design Spec 生成设计文档 40 40
Design Review 设计复审 20 20
Coding Standard 需求分析 (包括学习新技术) 30 40
Design 具体设计 30 40
Coding 具体编码 30 40
Code Review 代码复审 20 30
Test 测试(自我测试,修改代码,提交修改) 40 40
Reporting 报告 40 40
Test Repor 测试报告 15 15
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 15 15
合计 400 450

需求分析

题目:论文查重

描述如下:

设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率

  • 原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
  • 抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。

要求输入输出采用文件输入输出,规范如下:

  • 命令行参数给出:论文原文的文件的绝对路径
  • 命令行参数给出:抄袭版论文的文件的绝对路径
  • 命令行参数给出:输出的答案文件的绝对路径

我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。

注意:答案文件中输出的答案为浮点型,精确到小数点后两位

SimHash算法

SimHash算法是一种局部敏感哈希算法,用于处理大规模数据的相似度计算问题。

  • 1、文本分词和去停用词:首先对输入的文本进行分词处理,并去除停用词(如“的”、“是”等),以提取具有实际意义并且对文本内容有较强代表性的关键词。

  • 2、特征权重计算:利用TF-IDF算法计算每个关键词的权重,以此衡量关键词在文本中的重要程度。

  • 3、生成哈希向量:对每个关键词计算hash值,并根据关键词的权重对这些哈希值的每一位进行加权处理。

  • 4、叠加生成最终哈希值:将所有关键词的加权hash值进行叠加,根据每位的正负决定最终hash值的位值。

  • 5、降维处理:对于n-bit签名的累加结果,如果大于0则置1,否则置0,从而得到该语句的simhash值。

  • 6、计算汉明距离:通过比较不同文本的SimHash值,计算汉明距离,即两个字符串对应位置的不同字符的数量,来判定文本间的相似度。

流程图

接口设计与实现

类名 实现方法
HammingUtils类 计算海明距离并输出相似度
SimHashUtils类 计算哈希值、计算simHash值
TxtIOUtils类 读取txt文本内容并向txt文件输出文本
Main类 计算哈希值、计算simHash值
MainTest类 读取txt文本内容并向txt文件输出文本

性能分析

  • 概览

  • 实时内存

测试

  • 单元测试展示

···

@Test
public void Test1(){
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str2 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_add.txt");
    String str3 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_del.txt");
    String str4 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_1.txt");
    String str5 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_10.txt");
    String str6 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_15.txt");
    String ansFileName = "src/test/resources/test/test1.txt";
    double ans1 = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str1), SimHashUtils.getSimHash(str1));
    double ans2 = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str1), SimHashUtils.getSimHash(str2));
    double ans3 = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str1), SimHashUtils.getSimHash(str3));
    double ans4 = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str1), SimHashUtils.getSimHash(str4));
    double ans5 = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str1), SimHashUtils.getSimHash(str5));
    double ans6 = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str1), SimHashUtils.getSimHash(str6));
    TxtIOUtil.writeTxt(ans1, ansFileName);
    TxtIOUtil.writeTxt(ans2, ansFileName);
    TxtIOUtil.writeTxt(ans3, ansFileName);
    TxtIOUtil.writeTxt(ans4, ansFileName);
    TxtIOUtil.writeTxt(ans5, ansFileName);
    TxtIOUtil.writeTxt(ans6, ansFileName);
}

@Test
public void Test2(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String ansFileName = "src/test/resources/test/test2.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

@Test
public void Test3(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_add.txt");
    String ansFileName = "src/test/resources/test/test3.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

@Test
public void Test4(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_del.txt");
    String ansFileName = "src/test/resources/test/test4.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

@Test
public void Test5(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_1.txt");
    String ansFileName = "src/test/resources/test/test5.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

@Test
public void Test6(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_10.txt");
    String ansFileName = "src/test/resources/test/test6.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

@Test
public void Test7(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_15.txt");
    String ansFileName = "src/test/resources/test/test7.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans,ansFileName);
}

··

  • 测试覆盖率

  • 测试结果

异常处理说明

  • 文件不存在的异常测试:

···

/**
 * 文件不存在异常测试
 * @throws Exception
 */
@Test
public void Test8() throws Exception {
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.8_dis_.txt");
    String ansFileName = "src/test/resources/test/test8.txt";
    if(str0 == "" || str1 == ""){
        throw new Exception("文件不存在");
    }
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

···

  • 文件为空的异常测试:

···

/**
 * 文件为空异常测试
 */
@Test
public void Test9(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.1.txt");
    String ansFileName = "src/test/resources/test/test9.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

···

  • 文件字数太少的异常测试:

···

/**
 * 文件字数太少异常测试
 */
@Test
public void Test10(){
    String str0 = TxtIOUtil.readTxt("src/test/resources/test/orig.txt");
    String str1 = TxtIOUtil.readTxt("src/test/resources/test/orig_0.2.txt");
    String ansFileName = "src/test/resources/test/test10.txt";
    double ans = HammingUtils.getSimilarity(SimHashUtils.getSimHash(str0), SimHashUtils.getSimHash(str1));
    TxtIOUtil.writeTxt(ans, ansFileName);
}

···

总结

  • 在本项目中,我们完成了一个论文查重算法,用于检测原文与修改后的抄袭论文间的重复率,并将结果保存至指定文件。

  • 算法的核心思想是对原文和抄袭版论文进行文本分词,并计算它们之间的相似度。我们使用了基于文本相似度的算法,通过比较原文和抄袭版论文中的词语、句子等元素,来判断它们之间的重复程度。

  • 该算法通过命令行接收三个文件路径作为输入:原文、抄袭版和输出答案文件。核心基于文本相似度计算,对两篇论文进行分词并比较其相似度。

  • 测试样例中,使用orig.txt作为原文文件,orig_add.txt等作为抄袭版文件,算法成功计算出各抄袭文件与原文的重复率,结果以浮点数形式精确到小数点后两位。

  • 这个算法具有一定的实际应用价值,可以帮助人们发现论文抄袭行为,保护学术诚信。

posted @ 2024-09-12 11:31  Saltyi  阅读(31)  评论(0编辑  收藏  举报