个人项目
这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/SoftwareEngineering2024
这个给作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/SoftwareEngineering2024/homework/13136
这个作业的目标 论文查重

一、github链接:

https://github.com/githdx/3122004570.git

二、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 15 18
-Estimate -估计这个任务需要多少时间 15 18
Development 开发 450 495
-Analysis -需求分析 (包括学习新技术) 200 240
-Design Spec -生成设计文档 20 20
-Design Review -设计复审 15 10
-Coding Standard -代码规范 (为目前的开发制定合适的规范) 5 5
-Design -具体设计 60 65
-Coding -具体编码 100 120
-Code Review -代码复审 30 20
-Test -测试(自我测试,修改代码,提交修改) 20 15
Reporting 报告 40 38
-Test Repor -测试报告 15 12
-Size Measurement -计算工作量 10 8
-Postmortem & Process Improvement Plan -事后总结, 并提出过程改进计划 15 18
All 合计 505 551

三、计算模块接口的设计与实现过程

设计:

CheckMain类:实现类。

  • 读取命令行参数。读取第一个路径为原文txt,第二个路径为抄袭txt,第三个路径为答案txt。经过一系列方法后将相似度写入答案txt中。

txtHandle类:处理txt文件

  • txtRead方法:文本读取。将txt文本内容读取成字符串。
  • txtWrite方法:文本写入。将相似度写入到txt文本内。

Calculation类:获取SimHash

  • getSimHash方法:获取字符串的SimHash。传入txt文本内容的字符串,经过一系列方法,输出该文本的SimHash值。
  • participle方法:分词。传入txt文本内容的字符串,输出特征词数组
  • Hash方法:传入特征词数组,输出对应的hash值
  • weightedAndMerged方法:加权、合并。传入文本的hash值,经过加权、合并最后输出权重向量
  • dimensionalityReduction方法:降维。传入文本的权重向量,输出文本的SimHash值
  • calculateHammingDistance方法:根据两个文本的SimHash计算海明距离
  • calculateHammingSimilarity方法:根据海明距离计算论文相似度保留两位小数

流程图:

算法关键:

参考:https://zhuanlan.zhihu.com/p/578254728
先通过txtRead读取原文文件和抄袭文件后,再经过分词、hash、加权、合并和降维分别计算两个文本SimHash值,接着根据两个文本的SimHash值计算海明距离,最后再计算出相似度并写入答案文件中

四、计算模块接口部分的性能改进

改进部分:

原加权、合并方法分开写,要经历两次两层for循环

//加权
    private static int[][] weighted(List<String> hashList){
        int size= hashList.size();
        int[][] weightVectorList=new int[size][256];
        for(int i=0;i<size;i++) {
            String str = hashList.get(i);
            for (int j = 0; j < str.length(); j++) {
                //权重范围0-10,特征词在数组中位置越靠前权重越大
                int weight = 10 - 10 * i / size;
                //加权
                if (str.charAt(j) == '1') weightVectorList[i][j] = weight;
                else weightVectorList[i][j] = -weight;
            }
        }

        return weightVectorList;
    }

    //合并
     public static int[] merged(int[][] list){
        int length=list.length;
        int[] weightVectorList=new int[length];
        int i=0;
        System.out.println(list.length);
        for(int[] arr:list){
            //System.out.println(arr.length);
            for(int j=0;j<256;j++){
                weightVectorList[i]+=arr[j];
            }
            i++;
        }
        return weightVectorList;
    }

优化后,加权、合并在一个方法中,只经历一次两层for循环

//加权、合并
    private static int[] weightedAndMerged(List<String> hashList){
        int size= hashList.size();
        //256位的加权向量
        int[] weightVectorList=new int[256];
        for(int i=0;i<size;i++) {
            String str = hashList.get(i);
            for (int j = 0; j < str.length(); j++) {
                //权重范围0-10,特征词在数组中位置越靠前权重越大
                int weight = 10 - 10 * i / size;
                //加权并合并
                if (str.charAt(j) == '1') weightVectorList[j] += weight;
                else weightVectorList[j] -= weight;
            }
        }
        return weightVectorList;
    }

性能图

五、计算模块部分单元测试展示

测试在不同的原文文件和抄袭文件下得到的相似度

@Test
    public void mainTest(){
        String test1= "../../src/resources/orig.txt";
        String test2= "../../src/resources/orig_0.8_add.txt";
        String test3= "../../src/resources/orig_0.8_del.txt";
        String test4= "../../src/resources/orig_0.8_dis_1.txt";
        String test5= "../../src/resources/orig_0.8_dis_10.txt";
        String test6= "../../src/resources/orig_0.8_dis_15.txt";
        String test7= "../../src/resources/test_1.txt";
        String test8= "../../src/resources/test_2.txt";
        String test9= "../../src/resources/test_3.txt";
        String test10= "../../src/resources/test_4.txt";
        String ans1="../../src/resources/answer_test.txt";

        System.out.println("测试一结果:");
        test(test1,test2,ans1);
        System.out.println("测试二结果:");
        test(test1,test3,ans1);
        System.out.println("测试三结果:");
        test(test1,test4,ans1);
        System.out.println("测试四结果:");
        test(test1,test5,ans1);
        System.out.println("测试五结果:");
        test(test1,test6,ans1);
        System.out.println("测试六结果:");
        test(test1,test7,ans1);
        System.out.println("测试七结果:");
        test(test1,test8,ans1);
        System.out.println("测试八结果:");
        test(test1,test9,ans1);
        System.out.println("测试九结果:");
        test(test1,test10,ans1);
        System.out.println("测试十结果:");
        test(test4,test5,ans1);
    }

    public static void test(String path1,String path2,String path3){
        String txt1,txt2;
        //文件打开失败,结束
        if((txt1=TxtHandle.txtRead(path1))==null||(txt2=TxtHandle.txtRead(path2))==null)return;
        //获取txt文本的SimHash值
        int[] weightVectorList1,weightVectorList2;
        //文本内容过短,结束
        if((weightVectorList1=Calculation.getSimHash(txt1))==null||(weightVectorList2=Calculation.getSimHash(txt2))==null)return ;
        //计算海明距离
        int distance= Calculation.calculateHammingDistance(weightVectorList1,weightVectorList2);
        //计算论文相似度
        double similarity= Calculation.calculateHammingSimilarity(distance);
        System.out.println("论文相似度为:"+similarity+"%");
        //将结果写入文件
        TxtHandle.txtWrite(path3,similarity);
    }

测试结果

测试覆盖率

六、计算模块部分异常处理说明

输入的文本路径数量不对时,输出错误提示

输入的文本路径不存在时,输出错误提示

输入的文本内容过短时,输出错误提示

posted on 2024-03-13 21:42  BrD29  阅读(24)  评论(0编辑  收藏  举报