oo第三次博客

一、梳理JML语言的理论基础、应用工具链情况

理论基础

JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言
(Behavior Interface Specification Language,BISL),基于Larch方法构建。BISL提供了对方法和类型的规格定义
手段。所谓接口即一个方法或类型外部可见的内容。JML主要由Leavens教授在Larch上的工作,并融入了Betrand
Meyer, John Guttag等人关于Design by Contract的研究成果。近年来,JML持续受到关注,为严格的程序设计提供
了一套行之有效的方法。通过JML及其支持工具,不仅可以基于规格自动构造测试用例,并整合了SMT Solver等工具
以静态方式来检查代码实现对规格的满足情况

  • 注释结构 

  JML以javadoc注释的方式来表示规格,每行都以@起头。有两种注释方式,行注释和块注释。其中行注释的表示方式
  为 //@annotation ,块注释的方式为 /* @ annotation @*/ 。

  • JML表达式

    • 原子表达式

      • \result表达式:表示一个非 void 类型的方法执行所获得的结果,即方法执行后的返回值。
      • \old( expr )表达式:用来表示一个表达式 expr 在相应方法执行前的取值。
    • 量化表达式

      • \forall表达式:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。
      • \exists表达式:存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。
    • 操作符

      • 子类型关系操作符: E1<:E2 ,如果类型E1是类型E2的子类型(sub type),则该表达式的结果为真,否则为假。
      • 等价关系操作符: b_expr1<==>b_expr2 或者 b_expr1<=!=>b_expr2 ,其中b_expr1和b_expr2都是布尔表达式,这两个表达式的意思是 b_expr1==b_expr2 或者 b_expr1!=b_expr2 。
      • 推理操作符: b_expr1==>b_expr2 或者 b_expr2<==b_expr1 。
  • 方法规格

    • 前置条件(pre-condition):前置条件通过requires子句来表示: requires P。

    • 后置条件(post-condition):后置条件通过ensures子句来表示: ensures P。
  • 类型规格

    • 不变式(invariant)是要求在所有可见状态下都必须满足的特性,语法上定义 invariant P ,其中 invariant 为关键词, P 为谓词。对于类型规格而言,可见状态(visible state)是一个特别重要的概念。

    • 状态变化约束(constraint)对象的状态在变化时往往也许满足一些约束,这种约束本质上也是一种不变式。

工具链

jmlrac: test for violations of assertions during execution

ESC/Java2: static verification; compile-time proving that contracts are never violated

jmldoc: javadoc-style documentation

jmlc: assertion-checking compilerj

jml4c: a new JML compiler built upon the Eclipse JDT open-source platform

SMT Solver: 验证程序等价性

OpenJML: 检查JML规范性

二、部署SMT Solver,至少选择3个主要方法来尝试进行验证,报告结果  

对MyPath进行测试

TRACE of MyPath.compareTo(com.oocourse.specs3.models.Path)
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires o != null; 
            VALUE: o     === REF!val!64
            VALUE: null     === NULL
            VALUE: o != null     === true
E:\eclipse-workspace\jml\src\MyPath.java:78: 注:      /*@ non_null */  Iterator<Integer> iter1 = this.iterator()
            VALUE: this.iterator()     === REF!val!103
            VALUE: iter1     === REF!val!103
E:\eclipse-workspace\jml\src\MyPath.java:7: 注:      PossiblyNullDeReference assertion: _JML__tmp242376 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26880
            VALUE: _$CPRE__26880     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242376.nodes.content != null) || _JML__tmp242376.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242376.nodes.content != null) || _JML__tmp242376.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242376.nodeCounter.content != null) || _JML__tmp242376.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242376.nodeCounter.content != null) || _JML__tmp242376.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:78: 注:      PossiblyNullInitialization assertion: _JML__tmp242377 != null
            VALUE: null     === NULL
E:\eclipse-workspace\jml\src\MyPath.java:79: 注:      /*@ non_null */  Iterator<Integer> iter2 = p.iterator()
            VALUE: p     === REF!val!64
            VALUE: p.iterator()     === REF!val!130
            VALUE: iter2     === REF!val!130
E:\eclipse-workspace\jml\src\MyPath.java:79: 注:      PossiblyNullDeReference assertion: _JML__tmp242393 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26881
            VALUE: _$CPRE__26881     === true
E:\eclipse-workspace\jml\src\MyPath.java:79: 注:      PossiblyNullInitialization assertion: _JML__tmp242394 != null
            VALUE: null     === NULL
E:\eclipse-workspace\jml\src\MyPath.java:80: 注:      Loop test
            VALUE: iter1     === REF!val!103
            VALUE: iter1.hasNext()     === false
            VALUE: iter1.hasNext() && iter2.hasNext()     === false
            VALUE: (iter1.hasNext() && iter2.hasNext())     === false
E:\eclipse-workspace\jml\src\MyPath.java:80: 注:      PossiblyNullDeReference assertion: _JML__tmp242403 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26882
            VALUE: _$CPRE__26882     === true
E:\eclipse-workspace\jml\src\MyPath.java:87: 注:      return Integer.compare(this.size(), p.size());
            VALUE: this.size()     === ( - 2147476275 )
            VALUE: p     === REF!val!64
            VALUE: p.size()     === ( - 2147480014 )
            VALUE: Integer.compare(this.size(), p.size())     === 0
E:\eclipse-workspace\jml\src\MyPath.java:7: 注:      PossiblyNullDeReference assertion: _JML__tmp242581 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26888
            VALUE: _$CPRE__26888     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242581.nodes.content != null) || _JML__tmp242581.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242581.nodes.content != null) || _JML__tmp242581.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242581.nodeCounter.content != null) || _JML__tmp242581.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242581.nodeCounter.content != null) || _JML__tmp242581.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:87: 注:      PossiblyNullDeReference assertion: _JML__tmp242595 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26889
            VALUE: _$CPRE__26889     === true
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26887
            VALUE: _$CPRE__26887     === true
E:\eclipse-workspace\jml\src\MyPath.java:8: 注:      NullField assertion: _JML__tmp242607
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:8: 注:      Invariant assertion: !(THIS.nodes != null) || _JML__tmp242610
F:\eclipse\jee-photon2\eclipse\configuration\org.eclipse.osgi\998\0\.cp\specs\java\util\Collection.jml:70: 注:  Invalid assertion (Invariant)
compareTo
TRACE of MyPath.equals(java.lang.Object)
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires this == obj; 
            VALUE: this     === THIS
            VALUE: obj     === THIS
            VALUE: this == obj     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires obj != null && \typeof(this) == \type(Object); 
            VALUE: obj     === THIS
            VALUE: null     === NULL
            VALUE: obj != null     === true
            VALUE: this     === THIS
            VALUE: \typeof(this)     === JMLTypeSort!val!55
            VALUE: \type(Object)     === JMLTypeSort!val!6
            VALUE: \typeof(this) == \type(Object)     === false
            VALUE: obj != null && \typeof(this) == \type(Object)     === false
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires obj == null; 
            VALUE: obj     === THIS
            VALUE: null     === NULL
            VALUE: obj == null     === false
E:\eclipse-workspace\jml\src\MyPath.java:40: 注:      if (!(obj instanceof Path)) ...
            VALUE: obj     === THIS
            VALUE: obj instanceof Path     === true
            VALUE: (obj instanceof Path)     === true
            VALUE: !(obj instanceof Path)     === false
            VALUE: (!(obj instanceof Path))     === false
                Condition = false
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      if (nodes.size() != ((Path)obj).size()) ...
            VALUE: nodes     === REF!val!78
            VALUE: nodes.size()     === 2275
            VALUE: obj     === THIS
            VALUE: (Path)obj     === THIS
            VALUE: ((Path)obj)     === THIS
            VALUE: ((Path)obj).size()     === 2275
            VALUE: nodes.size() != ((Path)obj).size()     === false
            VALUE: (nodes.size() != ((Path)obj).size())     === false
                Condition = false
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      PossiblyNullDeReference assertion: _JML__tmp785 != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!78
            VALUE: this     === REF!val!78
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      InvariantLeaveCaller assertion: _JML__tmp787
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 2275
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantLeaveCaller assertion: _JML__tmp789
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!78
            VALUE: this     === REF!val!78
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      InvariantLeaveCaller assertion: _JML__tmp790
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 2275
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantLeaveCaller assertion: _JML__tmp792
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!78
            VALUE: this     === REF!val!78
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      InvariantEntrance assertion: _JML__tmp793
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 2275
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantEntrance assertion: _JML__tmp795
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!78
            VALUE: this     === REF!val!78
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      InvariantEntrance assertion: _JML__tmp796
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 2275
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantEntrance assertion: _JML__tmp798
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__35
            VALUE: _$CPRE__35     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!78
            VALUE: this     === REF!val!78
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 2275
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!78
            VALUE: this     === REF!val!78
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 2275
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp799 && _JML__tmp785.content != null) || _JML__tmp785.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp799 && _JML__tmp785.values != null) || _JML__tmp785.values != null
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      PossiblyBadCast assertion: obj == null || obj instanceof com.oocourse.specs3.models.Path
E:\eclipse-workspace\jml\src\MyPath.java:43: 注:      PossiblyNullDeReference assertion: _JML__tmp814 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__36
            VALUE: _$CPRE__36     === true
E:\eclipse-workspace\jml\src\MyPath.java:46: 注:      /*@ non_null */  Iterator<Integer> iter1 = this.iterator()
            VALUE: this.iterator()     === REF!val!105
            VALUE: iter1     === REF!val!105
E:\eclipse-workspace\jml\src\MyPath.java:7: 注:      PossiblyNullDeReference assertion: _JML__tmp822 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__37
            VALUE: _$CPRE__37     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp822.nodes.content != null) || _JML__tmp822.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp822.nodes.content != null) || _JML__tmp822.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp822.nodeCounter.content != null) || _JML__tmp822.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp822.nodeCounter.content != null) || _JML__tmp822.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:46: 注:      PossiblyNullInitialization assertion: _JML__tmp823 != null
            VALUE: null     === NULL
E:\eclipse-workspace\jml\src\MyPath.java:47: 注:      /*@ non_null */  Iterator<Integer> iter2 = ((Path)obj).iterator()
            VALUE: obj     === THIS
            VALUE: (Path)obj     === THIS
            VALUE: ((Path)obj)     === THIS
            VALUE: ((Path)obj).iterator()     === REF!val!105
            VALUE: iter2     === REF!val!105
E:\eclipse-workspace\jml\src\MyPath.java:47: 注:      PossiblyBadCast assertion: obj == null || obj instanceof com.oocourse.specs3.models.Path
E:\eclipse-workspace\jml\src\MyPath.java:47: 注:      PossiblyNullDeReference assertion: _JML__tmp840 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__38
            VALUE: _$CPRE__38     === true
E:\eclipse-workspace\jml\src\MyPath.java:47: 注:      PossiblyNullInitialization assertion: _JML__tmp841 != null
            VALUE: null     === NULL
E:\eclipse-workspace\jml\src\MyPath.java:48: 注:      Loop test
            VALUE: iter1     === REF!val!105
            VALUE: iter1.hasNext()     === true
            VALUE: iter2     === REF!val!105
            VALUE: iter2.hasNext()     === true
            VALUE: iter1.hasNext() && iter2.hasNext()     === true
            VALUE: (iter1.hasNext() && iter2.hasNext())     === true
E:\eclipse-workspace\jml\src\MyPath.java:48: 注:      PossiblyNullDeReference assertion: _JML__tmp850 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__39
            VALUE: _$CPRE__39     === true
E:\eclipse-workspace\jml\src\MyPath.java:48: 注:      PossiblyNullDeReference assertion: _JML__tmp858 != null
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__40
            VALUE: _$CPRE__40     === true
E:\eclipse-workspace\jml\src\MyPath.java:49: 注:      if (!iter1.next().equals(iter2.next())) ...
            VALUE: iter1     === REF!val!105
            VALUE: iter1.next()     === REF!val!142
            VALUE: iter2     === REF!val!105
            VALUE: iter2.next()     === REF!val!145
            VALUE: iter1.next().equals(iter2.next())     === false
            VALUE: !iter1.next().equals(iter2.next())     === true
            VALUE: (!iter1.next().equals(iter2.next()))     === true
                Condition = true
E:\eclipse-workspace\jml\src\MyPath.java:49: 注:      PossiblyNullDeReference assertion: _JML__tmp867 != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires moreElements; 
            VALUE: moreElements     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires !moreElements; 
            VALUE: moreElements     === true
            VALUE: !moreElements     === false
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      Precondition assertion: _$CPRE__42
            VALUE: _$CPRE__42     === true
E:\eclipse-workspace\jml\src\MyPath.java:49: 注:      PossiblyNullDeReference assertion: _JML__tmp943 != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires moreElements; 
            VALUE: moreElements     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      requires !moreElements; 
            VALUE: moreElements     === true
            VALUE: !moreElements     === false
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      Precondition assertion: _$CPRE__43
            VALUE: _$CPRE__43     === true
E:\eclipse-workspace\jml\src\MyPath.java:49: 注:      Exception thrown by next()
            VALUE: _JML___exceptionCall     === REF!val!156
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      Terminated with exception
            VALUE: _JML___exception     === REF!val!156
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      signals () false; 
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      ExceptionalPostcondition assertion: !Pre_2 || false
E:\eclipse-workspace\jml\src\MyPath.java:49: 注:  Invalid assertion (ExceptionalPostcondition)
: F:\eclipse\jee-photon2\eclipse\configuration\org.eclipse.osgi\998\0\.cp\specs\java\lang\Object.jml:76: 注:  Associated location
equals
TRACE of MyPath.hashCode()
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:      return nodes.hashCode();
            VALUE: nodes     === REF!val!57
            VALUE: nodes.hashCode()     === ( - 2147473923 )
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:      PossiblyNullDeReference assertion: _JML__tmp242634 != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!57
            VALUE: this     === REF!val!57
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:      InvariantLeaveCaller assertion: _JML__tmp242636
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 1142
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantLeaveCaller assertion: _JML__tmp242638
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!57
            VALUE: this     === REF!val!57
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:      InvariantLeaveCaller assertion: _JML__tmp242639
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 1142
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantLeaveCaller assertion: _JML__tmp242641
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!57
            VALUE: this     === REF!val!57
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:      InvariantEntrance assertion: _JML__tmp242642
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 1142
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantEntrance assertion: _JML__tmp242644
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!57
            VALUE: this     === REF!val!57
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:      InvariantEntrance assertion: _JML__tmp242645
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 1142
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      InvariantEntrance assertion: _JML__tmp242647
E:\eclipse-workspace\jml\src\MyPath.java:1: 注:      Precondition assertion: _$CPRE__26890
            VALUE: _$CPRE__26890     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!57
            VALUE: this     === REF!val!57
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 1142
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      //@ public invariant content.owner == this; 
            VALUE: content.owner     === REF!val!57
            VALUE: this     === REF!val!57
            VALUE: content.owner == this     === true
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:93: 注:      //@ public invariant content.theSize >= 0; 
            VALUE: content.theSize     === 1142
            VALUE: 0     === 0
            VALUE: content.theSize >= 0     === true
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(_JML__tmp242634.content != null) || _JML__tmp242634.content != null
E:\eclipse-workspace\jml\src\MyPath.java:8: 注:      NullField assertion: _JML__tmp242661
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:8: 注:      Invariant assertion: !(THIS.nodes != null) || _JML__tmp242664
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodes.content != null) || THIS.nodes.content != null
E:\eclipse-workspace\jml\src\MyPath.java:8: 注:      Invariant assertion: !(THIS.nodes != null) || _JML__tmp242666
E:\eclipse-workspace\jml\src\MyPath.java:9: 注:      NullField assertion: _JML__tmp242669
E:\eclipse-workspace\jml\src\MyPath.java:91: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:9: 注:      Invariant assertion: !(THIS.nodeCounter != null) || _JML__tmp242672
E:\eclipse-workspace\jml\src\MyPath.java:95: 注:      UndefinedNullDeReference assertion: !(THIS.nodeCounter.content != null) || THIS.nodeCounter.content != null
E:\eclipse-workspace\jml\src\MyPath.java:9: 注:      Invariant assertion: !(THIS.nodeCounter != null) || _JML__tmp242674
E:\eclipse-workspace\jml\src\MyPath.java:81: 注:      ensures \result == theHashCode; 
            VALUE: \result     === ( - 2147473923 )
            VALUE: theHashCode     === ( - 2147473923 )
            VALUE: \result == theHashCode     === true
E:\eclipse-workspace\jml\src\MyPath.java:92: 注:  Invalid assertion (Postcondition)
: F:\eclipse\jee-photon2\eclipse\configuration\org.eclipse.osgi\998\0\.cp\specs\java\lang\Object.jml:63: 注:  Associated location
hashCode

对MyRailwaySystem进行测试

错误反馈

TRACE of MyRailwaySystem.addPath(com.oocourse.specs3.models.Path)
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.idPathMap.content != null) || THIS.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.pathIdMap.content != null) || THIS.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:57: 注:      if (path == null || !path.isValid()) ...
            VALUE: path     === REF!val!81
            VALUE: null     === NULL
            VALUE: path == null     === false
            VALUE: path     === REF!val!81
            VALUE: path.isValid()     === false
            VALUE: !path.isValid()     === true
            VALUE: path == null || !path.isValid()     === true
            VALUE: (path == null || !path.isValid())     === true
                Condition = true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:57: 注:      PossiblyNullDeReference assertion: _JML__tmp594 != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__142
            VALUE: _$CPRE__142     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:58: 注:      return 0;
            VALUE: 0     === 0
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:13: 注:      NullField assertion: _JML__tmp1322
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.idPathMap.content != null) || THIS.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:13: 注:      Invariant assertion: !(THIS.idPathMap != null) || _JML__tmp1325
F:\eclipse\jee-photon2\eclipse\configuration\org.eclipse.osgi\998\0\.cp\specs\java\util\Map.jml:76: 注:  Invalid assertion (Invariant)
addPath
TRACE of MyRailwaySystem.containsEdge(int,int)
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.idPathMap.content != null) || THIS.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.pathIdMap.content != null) || THIS.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      if (containsNode(fromNodeId) && containsNode(toNodeId)) ...
            VALUE: fromNodeId     === ( - 2147483610 )
            VALUE: containsNode(fromNodeId)     === true
            VALUE: toNodeId     === ( - 2147475929 )
            VALUE: containsNode(toNodeId)     === true
            VALUE: containsNode(fromNodeId) && containsNode(toNodeId)     === true
            VALUE: (containsNode(fromNodeId) && containsNode(toNodeId))     === true
                Condition = true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__448
            VALUE: _$CPRE__448     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(_JML__tmp2101.idPathMap.content != null) || _JML__tmp2101.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(_JML__tmp2101.pathIdMap.content != null) || _JML__tmp2101.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__449
            VALUE: _$CPRE__449     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(_JML__tmp2114.idPathMap.content != null) || _JML__tmp2114.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(_JML__tmp2114.pathIdMap.content != null) || _JML__tmp2114.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:105: 注:      return monitor.containsEdge(fromNodeId, toNodeId);
            VALUE: monitor     === REF!val!146
            VALUE: fromNodeId     === ( - 2147483610 )
            VALUE: toNodeId     === ( - 2147475929 )
            VALUE: monitor.containsEdge(fromNodeId, toNodeId)     === false
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:105: 注:      PossiblyNullDeReference assertion: _JML__tmp2129 != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__450
            VALUE: _$CPRE__450     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:13: 注:      NullField assertion: _JML__tmp2144
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.idPathMap.content != null) || THIS.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:13: 注:      Invariant assertion: !(THIS.idPathMap != null) || _JML__tmp2147
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:14: 注:      NullField assertion: _JML__tmp2150
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.pathIdMap.content != null) || THIS.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:14: 注:      Invariant assertion: !(THIS.pathIdMap != null) || _JML__tmp2153
F:\eclipse\jee-photon2\eclipse\configuration\org.eclipse.osgi\998\0\.cp\specs\java\util\Map.jml:76: 注:  Invalid assertion (Invariant)
containsEdge
TRACE of MyRailwaySystem.getShortestPathLength(int,int)
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.idPathMap.content != null) || THIS.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.pathIdMap.content != null) || THIS.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:129: 注:      if (!isConnected(fromNodeId, toNodeId)) ...
            VALUE: fromNodeId     === ( - 2147475929 )
            VALUE: toNodeId     === ( - 2147475928 )
            VALUE: isConnected(fromNodeId, toNodeId)     === true
            VALUE: !isConnected(fromNodeId, toNodeId)     === false
            VALUE: (!isConnected(fromNodeId, toNodeId))     === false
                Condition = false
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__485
            VALUE: _$CPRE__485     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(_JML__tmp2312.idPathMap.content != null) || _JML__tmp2312.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(_JML__tmp2312.pathIdMap.content != null) || _JML__tmp2312.pathIdMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:131: 注:      if (fromNodeId == toNodeId) ...
            VALUE: fromNodeId     === ( - 2147475929 )
            VALUE: toNodeId     === ( - 2147475928 )
            VALUE: fromNodeId == toNodeId     === false
            VALUE: (fromNodeId == toNodeId)     === false
                Condition = false
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:134: 注:      return monitor.query().distance(fromNodeId, toNodeId);
            VALUE: monitor     === REF!val!130
            VALUE: monitor.query()     === REF!val!220
            VALUE: fromNodeId     === ( - 2147475929 )
            VALUE: toNodeId     === ( - 2147475928 )
            VALUE: monitor.query().distance(fromNodeId, toNodeId)     === 0
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:134: 注:      PossiblyNullDeReference assertion: _JML__tmp2334 != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__488
            VALUE: _$CPRE__488     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:134: 注:      PossiblyNullDeReference assertion: _JML__tmp2351 != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:1: 注:      Precondition assertion: _$CPRE__487
            VALUE: _$CPRE__487     === true
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:13: 注:      NullField assertion: _JML__tmp2365
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:104: 注:      UndefinedNullDeReference assertion: !(THIS.idPathMap.content != null) || THIS.idPathMap.content != null
E:\eclipse-workspace\jml\src\MyRailwaySystem.java:13: 注:      Invariant assertion: !(THIS.idPathMap != null) || _JML__tmp2368
F:\eclipse\jee-photon2\eclipse\configuration\org.eclipse.osgi\998\0\.cp\specs\java\util\Map.jml:76: 注:  Invalid assertion (Invariant)
getShortestPathLength

三、部署JMLUnitNG/JMLUnit,实现自动生成测试用例

我使用的JML Level 0 手册中的样例来测试,因为Graph中尝试了修改规格,但是任然无法避免\forall和\exist的使用,下面是Student的代码

 1 public class Student {
 2     private /*@ spec_public @*/ String name;
 3     //@ public invariant credits >= 0;
 4     private /*@ spec_public @*/ int credits;
 5     /*@ public invariant credits < 180 ==> !master &&
 6       @ credits >= 180 ==> master;
 7       @*/
 8     private /*@ spec_public @*/ boolean master;
 9     /*@ requires sname != null;
10       @ assignable \everything;
11       @ ensures name == sname && credits == 0 && master == false;
12       @*/
13     public Student (String sname) {
14         name = sname;
15         credits = 0;
16         master = false;
17     }
18 
19     /*@ requires c >= 0;
20       @ ensures credits == \old(credits) + c;
21       @ assignable credits, master;
22       @ ensures (credits > 180) ==> master;
23       @ */
24     public void addCredits(int c) {
25         updateCredits(c);
26         if (credits >= 180) {
27             changeToMaster();
28         }
29     }
30 
31     /*@ requires c >= 0;
32       @ ensures credits == \old(credits) + c;
33       @ assignable credits;
34       @*/
35     private void updateCredits(int c) {
36         credits += c;
37     }
38 
39     /*@ requires credits >= 180;
40       @ ensures master;
41       @ assignable master;
42       @*/
43     private void changeToMaster() {
44         master = true;
45     }
46 
47     /*@ ensures this.name == name;
48       @ assignable this.name;
49       @*/
50     public void setName(String name) {
51         this.name = name;
52     }
53 
54     /*@ ensures \result == name;
55     @*/
56     public /*@ pure @*/ String getName() {
57         return name;
58     }
59 }
View Code

测试验证,结果都可以通过

测试分析:自动生成的测试样例测试了两个不同对象在addCredits的参数中包括最大整数和最小整数和0,测试了两个不同对象的getName方法,以及setName,其中参数为Null或者为空的时候的情况。

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

第一次作业

为了实现对节点的计数我另外创建了一个结构NodeCounter,对于path中的节点可以直接使用HashSet来实现,但是对于PathContainer中的节点,由于有路径的增加和删除所以需要对不同的节点进行计数,为了避免复杂度出现问题,就以节点为key,节点的出现册数为value建立hashMap,然后将增加路径和删除路径的操作封装起来供PathContainer来进行调用

第二次作业

由于需要计算最短路径,所以在上次的结构基础上额外增加了计算最短路径的Distance类。

NodeMonitor:NodeMonitor是MyPathContainer中的一个对象,这个对象实现了对查询和删除功能的封装,如果需要增删与查询直接调用这个对象的方法即可。当每次在NodeMonitor中进行加减路径的时候,都将NodeMonitor中的newest置为false;每次对NodeMonitor进行查询的时候,如果发现不是最新的(newest为false),则清空distance,然后根据新的请求重新计算并存储在distance的距离矩阵中,如果一直不发生写操作,那么距离矩阵就可以一直进行缓存。

Distance:在distance中对求解联通性和最短距离进行统一建模,对每次求解过的源点加入primaryKey中。

  • 连通性:先看是否在primaryKey中是否存在起点或者终点,如果存在说明已经以起点或者终点计算过最短路径,然后看是否在距离矩阵中存在起点和重点之间的距离,如果在primaryKey中存在起点或者终点,但是没有起点和终点之间的距离,说明不连通,如果存在则说明联通;如果在primaryKey中不存在起点或者终点,那么以起点为源计算最短路,并将起点加入primaryKey,然后返回起点和终点之间是否存在路径。
  • 最短距离:直接返回对应的距离值即可,因为调用最短距离之前一定判断过联通性,所以联通的点对之间的距离一定存在。

第三次作业

Monitor:由于功能的增加,Monitor相当于继续扩展了原来NodeMonitor的功能,保留了原来除增删路径的方法之外,并新添加了其他相关的查询方法,做到查询和增删功能的单独封装。和之前一样,Monitor只是MyRailwaySystem中的一个查询对象,需要查询什么就直接调用Monitor对象即可。

Nodes: 辅助类,存储所有的Station,同样需要实现增删路径的方法。

Station:辅助类,存储一个NodeId和地铁线编号pathId

StaionDistance:辅助类,用于计算Dijkstra中最短路径的距离和Station点对,实现了Comparable接口。

WeightedGraph:对于换乘票价以及不满意度,都统一进行拆点并构造有权图来建模,有权图中存权重矩阵和距离矩阵,以及一个Nodes对象,根据不同的需求对非换成站边权以及换乘站边权进行初始化,然后采用Dijkstra的方法来计算最短路径并缓存

Pleasure:由于不满意度的边权计算与换乘和票价不太相同,所以Pleasure继承了有权图,并重写了构建边权的方法。

UnweightedGraph:这个类与上次的distance类是一样的,为了名字统一叫做UnweightedGraph

Matrix:由于有权图中权重矩阵,距离矩阵,无权图中的距离矩阵都用到了嵌套的HashMap,所以我重新封装了这次作业中嵌套hashMap的add和remove方法,以及containsKey等方法。在有权图中Key的类型可能是Station,也可能是Integer所以需要利用泛型来解决。

import java.util.HashMap;

public class Matrix<T> {
    private HashMap<T, HashMap<T, Integer>> matrix = new HashMap<>();

    public Matrix() {

    }

    public void clear() {
        matrix.clear();
    }

    public void add(T firstKey, T secondKey, int value) {
        if (matrix.containsKey(firstKey)) {
            matrix.get(firstKey).put(secondKey, value);
        } else {
            HashMap<T, Integer> secondHash = new HashMap<>();
            secondHash.put(secondKey, value);
            matrix.put(firstKey, secondHash);
        }
    }

    public void remove(T firstKey, T secondKey) {
        if (matrix.containsKey(firstKey) &&
                matrix.get(firstKey).containsKey(secondKey)) {
            matrix.get(firstKey).remove(secondKey);
            if (matrix.get(firstKey).size() == 0) {
                matrix.remove(firstKey);
            }
        }
    }

    public HashMap<T, Integer> get(T key) {
        return matrix.get(key);
    }

    public Integer get(T firstKey, T secondKey) {
        return matrix.get(firstKey).get(secondKey);
    }

    public boolean containsKey(T firstKey, T secondKey) {
        return matrix.containsKey(firstKey) &&
                matrix.get(firstKey).containsKey(secondKey);
    }
}
View Code

 

Connectivity:实现了计算连通块的数量和判断联通性的查询功能,根据pathId建立邻接矩阵,描述path之间的邻接关系,同样需要对应实现增加路径和删除路径的方法add和remove方法,由于写指令数很少,所以最多有50个点,所以每次无论查询连通性或者计算联通块数都要通过BFS将path分块,然后将pathId和块号建立映射。Connectivity中有和WeightedGraph共享的Nodes对象,所以根据Nodes对象即可知道NodeId与pathId的映射,所以根据这两个映射,可以根据pathId来找块号,从而判断联通性。块数的查询直接返回存储联通块的容器的大小即可。

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

第一次作业:时间复杂度没有考虑,所以之后修改为利用Hashmap来查询访问的方式。

第二次作业:计算最短路径时,忘记考虑是否以该源点计算过最短距离的问题,只要存在key但是不存在value就认为不连通,因为比如一开始查询1-5的距离,然后查询5-6,由于1-5的距离对称填到key为5和1的矩阵行,这时5-6之间是没有计算而不是算出来距离不存在,导致联通性判断错误,改为通过使用primaryKey来计算以其为源点计算过的NodeId。

第三次作业:在联通性计算的时候直接使用的path对象,而忘记使用pathId,导致每次插入hashMap的时候每次比较path对象,时间复杂度过高,改为之后使用pathId来区分path。

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

使用规格使我们的代码便于进行自动化检查和测试,大大提高了正确率,通过学习规格我学到了很多。

posted @ 2019-05-22 11:58  王延鹏  阅读(184)  评论(0编辑  收藏  举报