OO第三单元单元总结

目录

  • JML知识梳理
  • 部署JMLUnitNG/JMLUnit
  • 按照作业梳理自己的架构设计,并特别分析迭代中对架构的重构
  • 按照作业分析代码实现的bug和修复情况
  • 阐述对规格撰写和理解上的心得体会

JML知识梳理

JML理论基础

关于JML的相关介绍其实课程给出的指导书就已经足够使用了,由于指导书上都有相关知识的梳理,所以这里不花费大量篇幅去书写这部分内容,只是简单提及一些东西。首先是什么是JML,课程进行,其实阅读简单的JML已经没有多大障碍了,但是对于JML的定义这种概念已经忘记的差不多了。JML是用于对Java程序进行规格化设计的一种表示语言,JML是一种行为接口规格语言,基于Larch方法创建。通过使用JML及其相关的支持工具,我们可以基于规格自动构造测试样例,并整合了SMT Solver 等工具以静态方法来检查代买实现对规格的满足情况。目前学习到的JML语言特征只是level0级别,所以只是入门啊(虽然入门就已经能够解决许多问题了)。

JML应用工具链

? JML拥有丰富的工具库,可以给用户提供JML规范检查,或者是随机测试数据生成测试。现仅举出课程中所涉及的几个.

? 1.OpenJml来检查JML的规范性

? 2.使用SMT Solver检查代码等价性

? 3.使用JMUnitNG生成数据测试代码

? 4.JMLAutoTest...

部署JMLUnitNG/JMLUnit

针对Graph接口的实现自动生成测试用例, 并结合规格对生成的测试用例和数据进行简要分析。

按照作业梳理自己的架构设计,并特别分析迭代中对架构的重构

第一次作业

第一次的架构其实很清晰了,因为最顶层的架构关系指导书已经指定了,实际上我们实现的是相关方法和细节(都是些比较底层的东西),所以这样主要提一提相关方法和细节的设计实现,顶层架构为将path抽象成一个类,并且在MyPath中实现相关path内的方法,用PathContainer,处理path间的相关操作,并存储所有的path。

path和不同点的存储:采用三HashMap的结构。

private HashMap<Path,Integer> ptoid = new HashMap<>(1024);
private HashMap<Integer,Path> idtop = new HashMap<>(1024);
private HashMap<Integer,Integer> valuepoint = new HashMap<>(102400);

复杂度分析

其中valuepoint中的key是当前路径中所出现的结点id,对应的value是该结点出现的次数。这样对于getDistinctNodeCount()方法,我们只需要输出valuepoint.size()即可。其他查询方法类似。

第二次作业

第二次作业与第一次作业的主要区别在于最短路和连通块上,而其他需求和第一次作业是一样的,所以我的第二次的架构,首先保留了第一次的架构设计(拷贝粘贴到MyGraph,MyPath类消失),在此基础上,在MyGraph类里主要实现了两个操作,一个是维护并查集,一个是用bfs求最短路。由于求最短路的问题,是一个图相关的问题,所以实现了相关的建图函数(邻接表建图)

具体来说,

//新增类 MyGraph , 删除类 MyPath

//新增方法
public int anc(int x)
public void unin(int x, int y)
public void buildufset() // 并查集
public void buildgraph() // 建图
public void buildsp() // 最短路

//bfs求最短路

 public void buildspforone(int x)
    {
        int [] vis = new int [300];
        for (int i = 0;i < 300;i++)
        {
            vis[i] = 0;
        }
        int [] node = new int [90000];
        node[0] = x;
        vis[node[0]] = 1;
        sp[x][x] = 0;
        int l = 0;
        int r = 0;
        while (l <= r)
        {
            int nd = node[l];
            for (int i = 0;i < edges[nd].size();i++)
            {
                int nnd = edges[nd].get(i);
                if (vis[nnd] == 0)
                {
                    vis[nnd] = 1;
                    r++;
                    node[r] = nnd;
                    sp[x][nnd] = sp[x][nd] + 1;
                }
            }
            l++;
        }
    }
//新增数据成员
private int [][]sp = new int[300][300]; // 最短路。
private int [] father = new int[300]; // 并查集
private ArrayList<Integer> [] edges  = new ArrayList[300]; // 存储边

复杂度分析

由于维护了并查集,所以对于连通块的平均查询是O(1)的,显然可以接受。

对于最短路,由于第二次作业并没有票价之内的问题,所以可以使用bfs来解决无权图的最短路问题,复杂度是O(V+E),由于边数最多为4000,所以也是可以接受的。

对于floyd,由于它的复杂度是稳定在O(n^3)的,所以虽然它好写,我还是没有写,但是事实证明也能过。

第三次作业

第三次作业与第二次作业在需求上有几个主要的不同点:不满意度、票价、换乘、连通块个数。仔细分析可以发现

对于不满意度、票价、换乘都可以抽象成有权图的最短路问题。所以实际上第三次作业与第二次作业的最大区别就是

图有权了,至于连通块个数,由于第二次作业已经实现了并查集,所以直接通过n-times(unin)就得到连通块个数了。

前面说到抽象成有权图的最短路问题,是有一个问题的,如果不拆点,图中的结点同时在多条路径中,也就是说图中结点具有多种性质,朴素的建图是解决不了这种问题的。

然后想到了拆点,结果写完拆点复杂度爆炸,因为极端情况下,拆点使得点数扩大了几十倍,而对于边数更是扩大了上千倍,这种情况下使用现有的算法都面临爆炸的风险,所以当时以为凉凉了...

//拆点 + Dij 思路
public int predij(int x,int y,int model,int num,int ans)
    {
        for (int i = 0;i < 130;i++)
        {
            for (int j = 0; j < 50; j++)
            {
                dis[i][j] = 1070000000;
                vis[i][j] = false;
            }
        }
        dis[x][num] = 0;
        int w  = 0;
        Queue<Edge> q = new PriorityQueue<>();
        Edge e0 = new Edge(x,x,w,num);
        {
            q.add(e0);
            for (int j = 0;j < namount;j++)
            {
                Edge ne;
                int nn;
                do {
                    ne =  q.poll();
                    nn = ne.getV2();
                } while (vis[nn][ne.getPid()]);
                vis[nn][ne.getPid()] = true;
                if (nn == y)
                {
                    if (ans >  dis[nn][ne.getPid()])
                    {
                        return  dis[nn][ne.getPid()];
                    }
                    else { return ans; }
                }
                for (int k = 0;k < edge[nn].size();k++)
                {
                    costs++;
                    Node nm = edge[nn].get(k);
                    w = caculw(nn,nm.getId(),ne.getPid(),nm.getPid(),model);
                    if (dis[nm.getId()][nm.getPid()] > dis[nn][ne.getPid()] + w)
                    {
                        dis[nm.getId()][nm.getPid()] = dis[nn][ne.getPid()] + w;
                        Edge e = new Edge(nn,nm.getId(),
                                dis[nm.getId()][nm.getPid()],nm.getPid());
                        q.add(e);
                    }
                }
            }
        }
        return ans;
    }

直到看到了分层图,顿时发现了新世界,通过把path压缩成小图,然后在把各个图进行合并,最终保留下来的图满足,任意两个直接相连的结点一定属于小图,并且该边权值最小。然后通过对每一个path跑一遍最短路,再对合并之后的大图跑一遍最短路就得到了解。

//分层图 + floyd 

//建小图,跑最短路

for (int i = 0;i <= 60;i++)
        {
            if (ridtop.containsKey(i))
            {
                Path p = ridtop.get(i);
                clearpathedge(pathedge);
                nnode.clear();
                for (int j = 0;j < p.size() - 1;j++)
                {
                    int s1 = p.getNode(j);
                    int s2 = p.getNode(j + 1);
                    if (vtoidx.containsKey(s1) == false) {
                        vtoidx.put(s1,++nodecnt);
                        idxtov.put(nodecnt,s1);
                    }
                    if (vtoidx.containsKey(s2) == false) {
                        vtoidx.put(s2,++nodecnt);
                        idxtov.put(nodecnt,s2);
                    }
                    int idx1 = vtoidx.get(s1);
                    int idx2 = vtoidx.get(s2);
                    {
                        pathedge[idx1][idx2] = caculw(idx1,idx2,1,1,model);
                        pathedge[idx2][idx1] = caculw(idx2,idx1,1,1,model);
                        if (!nnode.contains(idx1)) { nnode.add(idx1); }
                        if (!nnode.contains(idx2)) { nnode.add(idx2); }
                    }
                }
                addpathedge(model);
            }
        }

//采用朴素的floyd
 public void floyd(int [][]a,int type)
    {
        for (int k = 0;k < 130;k++)
        {
            if (type == 0 || nnode.contains(k))
            {
                for (int i = 0; i < 130; i++)
                {
                    for (int j = 0; j < 130; j++)
                    {
                        if (a[i][j] > a[i][k] + a[k][j])
                        {
                            a[i][j] = a[i][k] + a[k][j];
                        }
                    }
                }
            }
        }
    }
//最后对大图进行一次然后再跑一次floyd就OK了,^@^

按照作业分析代码实现的bug和修复情况

三次作业中,强测测试和互测测试我都没有丢分(开心..),这里主要是针对提交测评前曾经遇到的bug。

作业一bug分析
  • path的hashmap实现

    path是自定义的对象,所以需要去手动实现它的hashcode和equals方法,这里主要说一下hashcode一定

    要保证能够复现....

  • 判断大小

    判断大小要注意直接减会数值溢出。

作业二bug分析
  • 并查集的实现

    并查集最好实现路径压缩和按秩合并,否则容易被卡成链造成tle.

  • bfs的实现

    bfs注意标记数组,以及bfs只能跑连通块,不连通的点的最短路无限大

  • 标记数组初始化

    由于有重建图操作,以及会跑多次bfs和并查集,所以需要每一次初始化好标记数组的值

作业三bug分析
  • Dijkstra及Floyd的正确书写

    这个算法网上都有,但是由于不熟练,debug弄了很久。

  • 容器内元素是自定义对象时,重写相关方法

    第三次作业中由于自定义了Edge对象,所以使用ArrrayList.contains的时候

    就需要重写equals方法,要不然会按照地址进行查找。

阐述对规格撰写和理解上的心得体会

? 写规格的速度贼慢,写完之后感觉有语法错误,语法错误de完了,发现还有bug。但是,规格确实比自然语言表意清晰的多,在编写代码的时候也更明白自己到底要做些什么。

? 具体的规格撰写我的一点小心得就是,从上到下,先思考顶层功能是什么,约束是什么?然后逐层向下思考相同问题。

原文地址:https://www.cnblogs.com/backkom-buaa/p/10904461.html

时间: 2024-09-29 17:19:47

OO第三单元单元总结的相关文章

OO第三次单元总结

一.规格化设计发展历史 软件规格化方法,最早可追溯到20世纪50年代后期对于程序设计语言编译技术的研究,当时出现了各种语法分析程序自动生成器以及语法制导的编译方法,使编译系统的开发从"手工艺制作方式"发展成具有牢固理论基础的系统方法.规格化设计的研究高潮始于20世纪60年代后期,针对当时所谓的"软件危机",人们提出种种解决方法,如采用工程方法来组织.管理开发过程和通过钻研规律建立严密的理论以指导开发实践. 经过30多年的研究和应用,如今人们在规格化设计取得了大量.重

规格化设计——OO第三单元总结

规格化设计--OO第三单元总结 一.JML语言理论基础.应用工具链 1.1 JML语言 ? JML(java modeling language)是一种描述代码行为的语言,包括前置条件.副作用等等.JML是一种行为接口规格语言 (Behavior Interface Speci?cation Language,BISL),基于Larch方法构建. ? 通过使用JML,我们可以忽略一个类.一个方法内部的具体实现,专注于描述方法的预期功能,从而把过程性的思考延迟到方法设计中,扩展了面向对象设计的原则

OO第三单元总结 JML

OO第三单元总结 JML JML语言的理论基础.应用工具链情况 JML是一种形式化的,面向JAVA的行为接口规格语言,它结合了Eiffel的契约方法和Larch方法,以及细化演算的一些元素,有着坚实的理论基础. JML最主要的语法有前置条件,后置条件,不变式,通过这些语法对输入和输出进行约束,也就是达成了一种契约.当模块实现后,只要输入输出满足这些约束表达式就满足了规格的要求.JML主要使用java的语法,除此之外还有自己的一些语法,比如/forall,/exist等等,来实现对输入输出的约束.

OO第三单元总结(规格设计)

OO第三单元总结 一.关于JML Java Modeling Language,即JML是一种规格化表示语言,主要用于对Java程序的各种方法功能的规范描述.这样做既可以给程序设计人员明确清晰的功能要求,又可以充分全面地验证已有的代码实现保证其满足规格描述的要求. 1.语法梳理 JML的语法清晰直观地描述了一个Java的各种特征.它的语法主要由以下三个部分组成. (1)表达式: 诸如 \result \old等有具体确定意义的固定关键词称为表达式.通过不同的搭配组合可以表示不同的含义,比如(\f

网易云课堂_C++程序设计入门(下)_第10单元:月映千江未减明 – 模板_第10单元 - 单元作业:OJ编程 - 创建数组类模板

第10单元 - 单元作业:OJ编程 - 创建数组类模板 查看帮助 返回 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截止时间之前不限次数提交答案,系统将取其中的最高分作为最终成绩. 本单元作业练习创建模板类.单元作业会涉及冒泡排序.线性查找等算法.如果对排序.查找不熟悉,可以自行baidu或者google 依照学术诚信条款,我保证此作业是本人独立完成的. 1 编写一个数组类模板 Array,能够存储不同类型的数组元素.对数组元素进行查找.

网易云课堂_C++程序设计入门(下)_第11单元:工欲善其事必先利其器 - STL简介_第11单元 - 单元作业1:OJ编程 - vector 与 sort

第11单元 - 单元作业1:OJ编程 - vector 与 sort 查看帮助 返回 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截止时间之前不限次数提交答案,系统将取其中的最高分作为最终成绩. 本次作业练习使用 vector 容器以及 sort 算法,对输入的数据进行排序 依照学术诚信条款,我保证此作业是本人独立完成的. 1 本次作业练习使用 vector 容器以及 sort 算法,对输入的数据进行排序(5分) 题目的具体内容参见 [第

OO第三次课程总结分析

OO第三次课程总结分析 规格化设计发展历史 在网上找了好久也没找到合适的信息,稍稍参考了同学的博客.大致如下:最初的的软件并没有形式化方法,随着软件工程的兴起,为了便于工程间的协调管理,人们提出采用工程方法来组织.管理软件的开发过程并深入探讨程序和程序开发过程的规律,建立严密的理论.随着时代的发展,软件的复杂度日益加大,结构化程序设计的缺点日渐暴露出来,面向对象设计由此产生,规格化设计进一步发展,这一次的规格设计可以更好地区分置换条件,以适应面向对象设计.如今,规格化设计基本完善,软件可以轻松实

OO第三单元总结

JML语言理论基础 Java建模语言(Java Modeling Language,JML)是一种进行详细设计的符号语言,他鼓励你用一种全新的方式来看待Java的类和方法.JML是一种行为接口规格语言 (Behavior Interface Speci?cation Language,BISL),基于Larch方法构建.BISL提供了对方法和类型的规格定义手段.所谓接口即一个方法或类型外部可见的内容.通过在Java代码中增加了一些符号,这些符号用来标识一个方法是干什么的,却并不关心它的实现.使用

2019年北航OO第三单元(JML规格任务)总结

一.JML简介 1.1 JML与契约式设计 说起JML,就不得不提到契约式设计(Design by Contract).这种设计模式的始祖是1986年的Eiffel语言.它是一种限定了软件中每个元素所必需的责任与义务的开发模式,程序设计中的每个元素都需要用规范的语言精准地限定其前置条件(Preconditions).后置条件(Postconditions)和不变式(Invariants).通过这三项限定,我们可以清晰地获得对一个函数功能的刻画,从而达成设计与实现的分离,便于优化.测试和生成文档.

OO第三单元总结-规格化设计

OO规格化编程体验小结 1. JML语言的理论基础.应用工具链情况 JML 理论基础: JML建立契约式编程的基础上,是一种实现契约式编程的规格化语言.顾名思义,契约式编程,是供求双方建立在一定的契约上进行软件的开发和应用.类似于在共同完成这一个工程的时候我们对于每个方法都以一个供求双方都统一并且详细知晓的合同,在这个合同上,供应方要不多不少完成合同上的所有要求,需求方的可提出的需求范围只限于合同上的明确条文.这样同时明确了双方的权利和义务.而产生契约式编程的背景是很多工程的开发过程权责混乱,导