OO爆点忏悔录&&规格学习笔记
之前从来没有爆过点的自己,看到第一次JML作业时,笑了笑,呵呵,什么呀,这次作业是给好算法写代码?啪啪啪一下子照着规格没脑子地乱写一通,然后当50分的出来的时候,简直抓狂。
当时自己天真的以为,自己第一次只是因为自己根本就是没有用hashmap等高端的结构(因为大家都是用了hashmap等数据结构),只用了数组等超级简单的数据结构,于是第二次作业的时候,凡是能用到hashmap的结构,自己都用到了。
然而当第二次强测再次爆出70分时,自己吓傻了。
这一回,大家又开始用数组等数据结构了?
开始恐慌?为什么每次自己都在用跟主流的数据结构相反的数据结构呢?
到第三次作业的时候才恍然大悟。
原来复杂的结构并不是时间复杂度低的保证,我们要寻求的,是适合自己算法的数据结构。
研究完指导书,搜刮过讨论区,加上为了加速debug到晚上后,最后一次终于侥幸地通过了。
所以这次谈bug及修复情况自己可以谈一晚上,先把这件最重要的事情放在一遍,按照可爱可敬的助教便于批改作业的顺序将这篇文章进行下去。
JML语言的理论基础、应用工具链情况
Java建模语言 (Java Modeling Language,JML)是一种进行详细设计的符号语言,它鼓励我们用一种全新的方式看待Java的类和方法。面对对象的分析和设计的一个终于原则就是过程性的思考应该尽可能地推迟。Java建模语言在Java代码中增加了一些符号,这些符号用来标识一个方法是干什么的,却不关心它的实现。通过这种方式,JML把过程性的思考延迟到了方法设计中,从而拓展了面对对象的这个原则,同时通过引入大量用于描述行为的结构,比如有模型域、量词、断言可视范围、预处理、后处理、正常行为与异常行为等等,这些结构就使得JML非常强大了。
将建模标记加入到JAVA程序代码中有以下的好处:
1、能够更为精确地描述这些代码是做什么的
2、能够高效地发现和修正程序中的bug
3、可以在应用程序升级时降低引入bug的机会
4、可以提早发现客户代码对类的错误使用
5、可以提供与应用程序代码完全一致的JML格式的文档
目前,应用工具链有OpenJml、JML UnitNG等工具。
参考文献:
[1] 寿智振.应用建模语言JML改进Java程序.
[2] 刘树锟,阳小华,刘杰.Java建模语言在程序不变量动态发现过程中的应用
SMT Solver篇
在第三次作业上验证。
1、测试Dijsktra.java
结果:
错误: A catastrophic JML internal error occurred. Please report the bug with as much information as you can. Reason: MISMATCHED BLOCKS C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:15: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method dijsktra dis[startIndex] = 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:15: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method dijsktra dis[startIndex] = 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:45: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method dijsktra inside[minIndex] = true; ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:45: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method dijsktra inside[minIndex] = true; ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:33: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method dijsktra if (!inside[i] && dis[i] != -1) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:11: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method dijsktra dis[i] = -1; ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:23: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method dijsktra: overflow in int sum dis[frontIndex] + edge[frontIndex][i] < dis[i]) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:21: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method dijsktra if (!inside[i] && edge[frontIndex][i] != -1) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:21: 警告: The prover cannot establish an assertion (PossiblyNullDeReference) in method dijsktra if (!inside[i] && edge[frontIndex][i] != -1) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:21: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method dijsktra if (!inside[i] && edge[frontIndex][i] != -1) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:21: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method dijsktra if (!inside[i] && edge[frontIndex][i] != -1) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:21: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method dijsktra if (!inside[i] && edge[frontIndex][i] != -1) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:23: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method dijsktra: underflow in int sum dis[frontIndex] + edge[frontIndex][i] < dis[i]) { ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:24: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method dijsktra: underflow in int sum dis[i] = dis[frontIndex] + edge[frontIndex][i]; ^ C:\Users\14912\eclipse-workspace\homework11\src\Dijsktra.java:24: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method dijsktra: overflow in int sum dis[i] = dis[frontIndex] + edge[frontIndex][i];
2、测试FlodWithChange.java
结果:
C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:20: 警告: The prover cannot establish an assertion (PossiblyNegativeSize) in method FlodWithChange isReady = new boolean[dissum]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:23: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method FlodWithChange isReady[i] = false; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: The prover cannot establish an assertion (Invariant) in method FlodWithChange //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: The prover cannot establish an assertion (Invariant) in method FlodWithChange //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method FlodWithChange public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method FlodWithChange public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method FlodWithChange public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method FlodWithChange public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:30: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis if (!isReady[from]) { ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:30: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method getDis if (!isReady[from]) { ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:40: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis return dis[from][to]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:40: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method getDis return dis[from][to]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:40: 警告: The prover cannot establish an assertion (PossiblyNullDeReference) in method getDis return dis[from][to]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:40: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis return dis[from][to]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 警告: The prover cannot establish an assertion (UndefinedTooLargeIndex) in method getDis dis[from][j] = newdis[endNode.get(b)]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:35: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis int b = index2num[j]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis dis[from][j] = newdis[endNode.get(b)]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:38: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis isReady[from] = true; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: The prover cannot establish an assertion (Invariant) in method getDis //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: The prover cannot establish an assertion (Invariant) in method getDis //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method getDis public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method getDis public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method getDis public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: The prover cannot establish an assertion (Invariant) in method getDis public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:35: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method getDis int b = index2num[j]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 警告: The prover cannot establish an assertion (PossiblyNullDeReference) in method getDis dis[from][j] = newdis[endNode.get(b)]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 注: ) in method getDis: (Caller: FlodWithChange.getDis(int,int), Callee: java.util.HashMap.get(java.lang.Object)) dis[from][j] = newdis[endNode.get(b)]; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):76: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 注: public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):188: 警告: The prover cannot establish an assertion (UndefinedCalledMethodPrecondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):60: 注: ) in method getDis @ requires !content.hasMap(key);// hasMap or hasMapObject -- FIXME ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):60: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Map.jml):188: 注: public boolean hasMap(nullable Object key); ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:34: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method getDis: overflow in int sum for (j = 0; j < dissum; j++) { ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 警告: The prover cannot establish an assertion (PossiblyTooLargeIndex) in method getDis dis[from][j] = newdis[endNode.get(b)]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:36: 警告: The prover cannot establish an assertion (PossiblyNegativeIndex) in method getDis dis[from][j] = newdis[endNode.get(b)]; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:69: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method getSum: int multiply overflow sum += 2 * nodeNum; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:69: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method getSum: overflow in int sum sum += 2 * nodeNum; ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:65: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method getSum: underflow in int sum sum = sum + temp.getDistinctNodeCount(); ^ C:\Users\14912\eclipse-workspace\homework11\src\FlodWithChange.java:65: 警告: The prover cannot establish an assertion (ArithmeticOperationRange) in method getSum: overflow in int sum sum = sum + temp.getDistinctNodeCount(); ^ 错误: ESC could not be attempted because of a failure in typechecking or AST transformation: ready 错误: ESC could not be attempted because of a failure in typechecking or AST transformation: readyMap 3 个错误 37 个警告
3、测试MyPath.java
结果:
C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:97: 警告: The prover cannot establish an assertion (PossiblyBadCast) in method compareTo: a com.oocourse.specs3.models.Path cannot be proved to be a MyPath MyPath p = (MyPath) o; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: The prover cannot establish an assertion (Invariant) in method compareTo //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: The prover cannot establish an assertion (Invariant) in method compareTo //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: The prover cannot establish an assertion (Invariant) in method compareTo //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: The prover cannot establish an assertion (Invariant) in method compareTo //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 注: ) in method compareTo: (Caller: MyPath.compareTo(com.oocourse.specs3.models.Path), Callee: java.util.ArrayList.get(int)) if (this.nodes.get(i) < ((MyPath) o).nodes.get(i)) { ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 注: //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 注: ) in method compareTo: (Caller: MyPath.compareTo(com.oocourse.specs3.models.Path), Callee: java.util.ArrayList.get(int)) if (this.nodes.get(i) < ((MyPath) o).nodes.get(i)) { ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 注: //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 注: ) in method compareTo: (Caller: MyPath.compareTo(com.oocourse.specs3.models.Path), Callee: java.util.ArrayList.get(int)) if (this.nodes.get(i) < ((MyPath) o).nodes.get(i)) { ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 注: //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 注: ) in method compareTo: (Caller: MyPath.compareTo(com.oocourse.specs3.models.Path), Callee: java.util.ArrayList.get(int)) if (this.nodes.get(i) < ((MyPath) o).nodes.get(i)) { ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:108: 注: //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:56: 警告: The prover cannot establish an assertion (Postcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/lang/Object.jml):78: 注: ) in method equals return (compareTo((Path) obj) == 0); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/lang/Object.jml):78: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:56: 注: @ ensures \result; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:56: 警告: The prover cannot establish an assertion (ExceptionalPostcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/lang/Object.jml):76: 注: ) in method equals return (compareTo((Path) obj) == 0); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/lang/Object.jml):76: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:56: 注: @ public normal_behavior ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:62: 警告: The prover cannot establish an assertion (Postcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/lang/Object.jml):63: 注: ) in method hashCode return nodes.hashCode(); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/lang/Object.jml):63: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:62: 注: //-RAC@ ensures \result == theHashCode; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: The prover cannot establish an assertion (Invariant) in method iterator //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: The prover cannot establish an assertion (Invariant) in method iterator //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: The prover cannot establish an assertion (Invariant) in method iterator //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: The prover cannot establish an assertion (Invariant) in method iterator //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:80: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 注: ) in method hasNext: (Caller: MyPath.MyIterator.hasNext(), Callee: java.util.ArrayList.size()) return nowIndex < nodes.size(); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:80: 注: //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:80: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 注: ) in method hasNext: (Caller: MyPath.MyIterator.hasNext(), Callee: java.util.ArrayList.size()) return nowIndex < nodes.size(); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:80: 注: //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:80: 警告: The prover cannot establish an assertion (Postcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):61: 注: ) in method hasNext return nowIndex < nodes.size(); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):61: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:80: 注: @ ensures \result <==> moreElements; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:85: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 注: ) in method next: (Caller: MyPath.MyIterator.next(), Callee: java.util.ArrayList.size()) if (nowIndex < nodes.size()) { ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):71: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:85: 注: //-RAC@ public invariant content.theSize >= 0; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:85: 警告: The prover cannot establish an assertion (InvariantLeaveCaller: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 注: ) in method next: (Caller: MyPath.MyIterator.next(), Callee: java.util.ArrayList.size()) if (nowIndex < nodes.size()) { ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Collection.jml):70: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:85: 注: //-RAC@ public invariant content.owner == this; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:89: 警告: The prover cannot establish an assertion (Postcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):83: 注: ) in method next return null; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):83: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:89: 注: E next(); ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:89: 警告: The prover cannot establish an assertion (Postcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):83: 注: ) in method next return null; ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):83: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:89: 注: E next(); ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:87: 警告: The prover cannot establish an assertion (Postcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):78: 注: ) in method next return nodes.get(nowIndex - 1); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):78: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:87: 注: @ public exceptional_behavior ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:87: 警告: The prover cannot establish an assertion (ExceptionList: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):81: 注: ) in method next return nodes.get(nowIndex - 1); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):81: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:87: 注: @ signals_only NoSuchElementException; ^ C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:87: 警告: The prover cannot establish an assertion (ExceptionalPostcondition: C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):72: 注: ) in method next return nodes.get(nowIndex - 1); ^ C:\Users\14912\eclipse-workspace\openjml-0.8.42-20190401\openjml.jar(specs/java/util/Iterator.jml):72: 警告: Associated declaration: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java:87: 注: /*@ public normal_behavior ^ 注: C:\Users\14912\eclipse-workspace\homework11\src\MyPath.java使用了未经检查或不安全的操作。 注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。 43 个警告
JMLUnitNG/JMLUnit篇
对于Mygraph类的测试结果如下:
(以下是命令行界面)
C:\Users\14912\eclipse-workspace\homework10\test\out>java -cp "../../../jmlunitng-1_4.jar;../../src/specs-homework-2-1.2-raw-jar-with-dependencies.jar;./" MyGraph_JML_Test [TestNG] Running: Command line suite Failed: racEnabled() Passed: constructor MyGraph() Passed: <<MyGraph@27082746>>.addPath(null) Passed: <<MyGraph@5b1d2887>>.containsEdge(-2147483648, -2147483648) Passed: <<MyGraph@1c2c22f3>>.containsEdge(0, -2147483648) Passed: <<MyGraph@18e8568>>.containsEdge(2147483647, -2147483648) Passed: <<MyGraph@33e5ccce>>.containsEdge(-2147483648, 0) Passed: <<MyGraph@5a42bbf4>>.containsEdge(0, 0) Passed: <<MyGraph@270421f5>>.containsEdge(2147483647, 0) Passed: <<MyGraph@52d455b8>>.containsEdge(-2147483648, 2147483647) Passed: <<MyGraph@4f4a7090>>.containsEdge(0, 2147483647) Passed: <<MyGraph@18ef96>>.containsEdge(2147483647, 2147483647) Passed: <<MyGraph@6956de9>>.containsNode(-2147483648) Passed: <<MyGraph@769c9116>>.containsNode(0) Passed: <<MyGraph@2d6d8735>>.containsNode(2147483647) Passed: <<MyGraph@ba4d54>>.containsPathId(-2147483648) Passed: <<MyGraph@12bc6874>>.containsPathId(0) Passed: <<MyGraph@de0a01f>>.containsPathId(2147483647) Passed: <<MyGraph@4c75cab9>>.containsPath(null) Passed: <<MyGraph@1ef7fe8e>>.flod() Passed: <<MyGraph@6f79caec>>.getDistinctNodeCount() Failed: <<MyGraph@3ac42916>>.getPathById(-2147483648) Failed: <<MyGraph@47d384ee>>.getPathById(0) Failed: <<MyGraph@2d6a9952>>.getPathById(2147483647) Failed: <<MyGraph@22a71081>>.getPathId(null) Failed: <<MyGraph@3930015a>>.getShortestPathLength(-2147483648, -2147483648) Failed: <<MyGraph@629f0666>>.getShortestPathLength(0, -2147483648) Failed: <<MyGraph@1bc6a36e>>.getShortestPathLength(2147483647, -2147483648) Failed: <<MyGraph@1ff8b8f>>.getShortestPathLength(-2147483648, 0) Failed: <<MyGraph@387c703b>>.getShortestPathLength(0, 0) Failed: <<MyGraph@224aed64>>.getShortestPathLength(2147483647, 0) Failed: <<MyGraph@c39f790>>.getShortestPathLength(-2147483648, 2147483647) Failed: <<MyGraph@71e7a66b>>.getShortestPathLength(0, 2147483647) Failed: <<MyGraph@2ac1fdc4>>.getShortestPathLength(2147483647, 2147483647) Failed: <<MyGraph@5f150435>>.isConnected(-2147483648, -2147483648) Failed: <<MyGraph@1c53fd30>>.isConnected(0, -2147483648) Failed: <<MyGraph@50cbc42f>>.isConnected(2147483647, -2147483648) Failed: <<MyGraph@75412c2f>>.isConnected(-2147483648, 0) Failed: <<MyGraph@282ba1e>>.isConnected(0, 0) Failed: <<MyGraph@13b6d03>>.isConnected(2147483647, 0) Failed: <<MyGraph@f5f2bb7>>.isConnected(-2147483648, 2147483647) Failed: <<MyGraph@73035e27>>.isConnected(0, 2147483647) Failed: <<MyGraph@64c64813>>.isConnected(2147483647, 2147483647) Failed: <<MyGraph@3ecf72fd>>.removePathById(-2147483648) Failed: <<MyGraph@483bf400>>.removePathById(0) Failed: <<MyGraph@21a06946>>.removePathById(2147483647) Failed: <<MyGraph@77f03bb1>>.removePath(null) Passed: <<MyGraph@326de728>>.renewdis() Passed: <<MyGraph@25618e91>>.size() =============================================== Command line suite Total tests run: 49, Failures: 27, Skips: 0 ===============================================
遇到了一个很严重的问题
开始不可以对于引入外部jar包的程序进行分析。
后来命令行引入外部包才解决了这一问题。
自己的方法:
先在自己想测的src所在的工程文件夹内新建test文件夹,再在test文件夹里面新建out文件夹
之后 命令行运行以下的一系列命令就可以跑出结果。
cd C:\Users\14912\eclipse-workspace java -jar jmlunitng-1_4.jar -d "homework10\test" -cp homework10\src\specs-homework-2-1.2-raw-jar-with-dependencies.jar -sp homework10\src homework10\src\MyGraph.java "C:\Program Files\Java\jdk1.8.0_191\bin\javac.exe" -cp "jmlunitng-1_4.jar;homework10\src\specs-homework-2-1.2-raw-jar-with-dependencies.jar" -sourcepath homework10\src -d homework10\test\out homework10\test\*.java java -jar openjml-0.8.42-20190401\openjml.jar -rac -classpath "homework10\src\specs-homework-2-1.2-raw-jar-with-dependencies.jar" -specspath homework10\src homework10\src\MyGraph.java cd homework10\test\out java -cp "../../../jmlunitng-1_4.jar;../../src/specs-homework-2-1.2-raw-jar-with-dependencies.jar;./" MyGraph_JML_Test
这里
C:\Users\14912\eclipse-workspace
是自己的第10次作业工程文件的所在的文件夹
注意:
1、把所有相关的路径全部改掉成自己要测的。
2、能否运行成功跟文件有关,一般简单的文件成功概率较大
架构设计
三次作业的复杂度呈指数性增长,从类图中可以直观地感受到:
第一次作业

架构上没有什么好说的,从图中可以看到,自己所有的结构都是数组。一点算法都没有考虑,然后查找全部都是逐个遍历。
第二次作业

比前一次复杂了很多。
基本思想是分块,以块为单位更新所有的距离矩阵。
数据结构上严重依赖hashmap,非常地复杂。为了维护一系列的复杂结构,花费了不少心思。
第二次设计吃亏的地方:
- 每次查询map都要考虑可能查不到,map还没有更新的情形——map的危险之处
- 有两个对应的缓冲区,一个用于distinct的更新,一个用于block最短路径的更新。相当于有两个cache,但是这两个cache的更新并不是同步的.很多时候会迟缓。比如删除路径,关于块的操作这个时候在图里面还找不到,因为还在缓冲区。这样,就带来了很多一系列的错误
1、架构上的失误:
CONTAINS_EDGE 指令不需要放到图里面的,可以放到二级cache里面。这样会使得如果路径变更后只有查边的操作简单很多。
2、写代码时候没有考虑到map的get可能查不到。这里导致了很多不必要的错误。
第三次作业

这里关于最小路径自己就用了4个不同的类封装(主要为了不断地加速)。
- 最小代价,不满意度算法:
这里抛弃了第二次作业划分连通块的做法,同时最小不满意度和最小代价都是拆点,(对于每个点分成两个总点和n个与路径数目相等的汇点。)
- 最小换乘的算法
不过关于最小换乘的算法比较神奇,目前还没有开到有人和自己是一样的做法,这里有必要介绍一下:
将每一条路径压缩成一个点,将交点变成一条边,但凡两条路径之间出现交点,就在两个点之间连一条边。
先看哪些路径含有A点
哪些路径含有B点。那么A到B的最小换乘次数就是从含有A的路径到含有B的路径的最小距离。
bug和修复情况(忏悔录详解)
第一次:
错在用数组搜寻,这样的查询时间复杂度太高了。
第二次:
最消耗时间的步骤是不断地new Edge这一过程,为了查询方便,头脑简单地构造了边这个类。然后每次查询都要傻傻地new 一次,然后最短路径构造矩阵时候,也要反复地new 多次,构造函数本身还是会非常地消耗时间的。
然而自己最傻的还不是new Edge本身。
而是自己建立了连通块分图机制。
自己原本以为,连通块会降低图的大小,于是才采取了这个优化策略的。
为了这个实际上并没有什么用的优化,自己可谓是费尽了心思。
而自己的连通块算法本身也非常地傻,每次都要把路径不断地加入,拿出,因为自己的算法是每次加入路径都要拆掉连通图重建。这样代码的复杂性并不低。自己还写了几天,80%的bug都是连通块产生的。因此这么看来,自己可能做的还是“负优化”。
第三次:
开始没有把中间结果保存,时间复杂度惊人,但是觉得bug主要不是出没有保存中间结果在这里,因为分析了一下,如果测试数据对于每次路径更新对于所有的路径都查询一遍,保存中间结果和不保存是一样的(50*120=6000)。于是锲而不舍地先优化查询算法。这里dijkstra用了最小堆结构,一下子把时间从100s+变成了7s。
- 前两次的教训告诫自己,我们总是太注重算法,而忽略了数据结构的重要性
- 越是底层的数据结构,越快。
- 不要花费过多的精力在奇技淫巧上,要将主要精力放在把大家都会用到的算法写好上面
防错总结:
最关键有效的还是构造边缘测试集。
规格撰写和理解上的心得体会
规格的确是一个很好的指导自己将来看得懂自己代码的工具,有了规格的帮助,至少在理解的正确性方面不会出很大的问题。
但是规格永远不会告诉我们该怎么做才能达到最好的设计效果。
就像一开始自己本来以为会像指导书上写的那样“最轻松的一次作业”,但是实际上却发现,作业比想象中的困难太多太多。
规格只是给了我们一个方向,一个描述,就像将来产品经理对我们会提到的要求,但是数据结构,算法,一切的架构,还是都要我们自己来摸索完成。

浙公网安备 33010602011771号