OO_BLOG3_規格化設計(JML學習)

目錄

  • JML語言學習筆記
    • 理論基礎
    • 應用工具鏈情況
    • JMLUnit/JMLUnitNG
  • UNIT3 作業分析
    • 作業 3-1 實現兩個容器類Path和PathContainer
    • 作業 3-2 實現容器類Path和數據結構類Graph
    • 作業 3-3 實現容器類Path,地鐵系統類RailwaySystem
  • 規格撰寫的心得與體會
  • 最后,衷心感謝為這門課程辛苦付出的老師和助教。???

JML語言學習筆記

理論基礎

1. 注釋結構

2. JML表達式

  • 原子表達式,量化表達式,集合表達式,操作符,etc.

3. 方法規格

  • 前置條件(pre-condition)
  • 后置條件(post-condition)
  • 副作用范圍限定(side-effects)

4. 類型規格

  • 不變式(invariant)
  • 狀態變化約束(constraint)

應用工具鏈情況

1. OpenJML & SMT Solver

  • 首先由OpenJML將JML規格轉換乘SMT-LIB格式的代碼,然后調用SMT solver進行檢查。用于靜態檢查

2. JMLUnitNG

  • 根據規格自動生成測試文件。用于自動測試

3. JMLdoc

  • 可以快速生成JML文檔的相關文件

4. Junit

  • Junit主要用于單元化測試與一定的自動化測試,配合JML食用效果極佳。

JMLUnit/JMLUnitNG

1. 前期準備

  • 簡單代碼示例與jar包配置
1615869-20190522120128637-1519398093.png1615869-20190522120152160-30847359.png

2. 命令行操作

java -jar jmlunitng.jar src/Demo.java 
javac -cp jmlunitng.jar src/*.java

3. 測試結果

1615869-20190522120135812-2074808793.png1615869-20190522120144850-322293277.png

4. 結果分析

  • 我們可以看出,自動生成的測試樣例對各種極端情況進行了測試,具有較好的覆蓋性。
  • 但是,在試驗過程中,JML測試的局限性也被暴露出來了。

UNIT3 作業分析

作業 3-1 實現兩個容器類Path和PathContainer

1. 架構設計

1)度量分析
1615869-20190522120201178-1202747953.png
2)結構分析
1615869-20190522120739470-1906886274.png
3)算法分析
  • MyPath

    • // path的存儲結構,用來順序存儲結點
      private ArrayList<Integer> arrayNodes; 
      // 用來存儲一條path中的node的個數(無重復)。key:結點名稱;value:該結點出現的次數
      private HashMap<Integer, Integer> hashNodes; 
    • ADD:
      1)讀入一個結點數組
      2)將結點順序存入arrayNodes
      3)遍歷結點數組,對于任一結點node,若node不在hashNodes中,即存入(node, 1);若已存在,即存入(node, value + 1)。
  • MyPathContainer

    • private int id = 0; // pathID
      private HashMap<Path, Integer> hashPaths; // Path --> PathID
      private HashMap<Integer, Path> hashIds; // PathID --> Path
      private HashMap<Integer, Integer> nodes; // Node --> frequentNumber
    • ADD:
      原理與path相同REMOVE:
      1)hashIds.remove(pathID),hashPaths.remove(path)
      2)對于path中的每一個node,(設node的出現次數為frequentNumber),若frequentNumber=1,則將node從nodes中移除;若frequentNumber>1,則 nodes.replace(node, frequentNumber-1)。

2. BUG分析

1)bug情況
  • 由于測試數據量的限制,程序在評測與互測環節沒有出現錯誤。
2)修復情況
  • 該程序存在一些不優美的地方,如MyPath中,利用HashMap來存儲不同結點是復雜的,可以說是自己造了個輪子,改正方法為使用HashSet進行存儲,通過容器的特性來減少手動判斷。

作業 3-2 實現容器類Path和數據結構類Graph

1. 架構設計

1)度量分析
1615869-20190522120214819-888796446.png1615869-20190522120220143-2140036106.png
2)結構分析
1615869-20190522120748711-1822232574.png
3)算法分析
  • AlGraph

    • // alGraph: node1 --> (node2 -> node2_frequentNumber)
      private HashMap<Integer, HashMap<Integer, Integer>> alGraph; 
      // edges: node1 --> (node2 -> shortestPathLength_From_Node1_To_Node2)
      private HashMap<Integer, HashMap<Integer, Integer>> edges; 
    • // 由原始圖(alGraph)生成距離圖(edges)的算法 ———— Floyd算法
      for (k = 0; k< MAX; k++) for (i = 0; i < MAX; i++) for (j = 0; j < MAX; j++) if (Graph[i][j] > Graph[i][k] + Graph[k][j]) Graph[i][j] = Graph[i][k] + Graph[k][j];
      
    • public boolean containsEdge(int node1, int node2) {return alGraph.get(node1).containsKey(node2);
      }
      public boolean isConnected(int node1, int node2) {if (node1 == node2) return true;else                return edges.get(node1).containsKey(node2);
      }
      public int getShortestPathLength(int node1, int node2) {if (node1 == node2) return 0;else                return edges.get(node1).get(node2);
      }
4)迭代中對架構的重構
  • AlGraph繼承了上一次作業中的PathContainer,并進行了適當的擴充(具體擴充見如上算法分析)。

2. BUG分析

1)bug情況
  • 測試數據量增大時,程序出現 CPU_TIME_LIMIT_EXCEED 的錯誤。
  • 原因(據我分析):在Floyd算法中加入的大量的判斷,當數據量增大時,造成CPU的負擔過大,運算超時。
2)修復情況
  • 重構后UML圖
1615869-20190522120754021-238182921.png
  • 算法分析

    • private final int biggest = 999999999; // 極大數(自由定義,小于2^31即可)
      private int id = 0; // PathID(同上一次作業)
      private HashMap<Path, Integer> pathToId; // Path --> PathID(同上一次作業)
      private HashMap<Integer, Path> idToPath; // PathID --> Path(同上一次作業)
      private HashMap<Integer, Integer> nodeToSum; // Node --> Node_Sum(同上一次作業)
      private HashMap<Integer, Integer> nodeToIndex; // Node --> Node_index_in_matrix
      private HashSet<Integer>[] adjVexSets; // 臨界表:Node--Set{node1, node2, ...}
      private int[][] disMatrix; // Graph生成的存儲各點之間距離的距離矩陣
      private Stack<Integer> indexStack; // 用來維護node<->index的映射的棧
    • '映射關系建立機制,搭建點與數組下標的關系
      if      put_New_Node_Into_Graph then bond_NewNode_to_IndexStack.pop() 
      else if remove_Node_From_Graph  then indexStack.push(oldNode.index)
3)前后對比
  • // 原程序,floyd部分代碼
    for (int k : tempEdges.keySet()) for (int i : tempEdges.keySet()) for (int j : tempEdges.keySet()) if (tempEdges.get(i).containsKey(k) && tempEdges.get(k).containsKey(j)) { int via = tempEdges.get(i).get(k) + tempEdges.get(k).get(j);if (tempEdges.get(i).containsKey(j)) {if (tempEdges.get(i).get(j) > via) {tempEdges.get(i).replace(j, via);}} else {tempEdges.get(i).put(j, via);}}
  • // 重構后,floyd部分代碼
    for (int k = 0; k < 255; k++) for (int i = 0; i < 255; i++) for (int j = 0; j < 255; j++) if (disMatrix[i][j] > (newDis = disMatrix[i][k] + disMatrix[k][j])) disMatrix[i][j] = newDis;

作業 3-3 實現容器類Path,地鐵系統類RailwaySystem

1. 架構設計

1)度量分析
1615869-20190522120225784-579982037.png1615869-20190522120230939-364199165.png
2)結構分析
1615869-20190522120800108-1985593861.png
3)算法分析
  • MyRailwaySystem

    • private int cbCount = 0; // 連通塊個數
      private int[][] disMatrix; // 距離矩陣 
      private int[][] transferMatrix; // 最小換乘矩陣
      private int[][] priceMatrix; // 價格矩陣
      private int[][] happyMatrix; // 最低不滿意度矩陣
    • // 下面是算法的偽代碼,以價格矩陣的更新為例,其它類似
      private void updatePriceMatrix() {priceMatrix = initMatrix(2);for (Each path : paths) {maxSize = path.size();priceArray = ((MyPath)path).getPriceArray();nodeMap = ((MyPath)path).getNodeMap();for (Each node1, node2 : nodeMap)if (priceArray[tempId1][tempId2] + 2 < priceMatrix[index1][index2]) priceMatrix[index1][index2] = priceMatrix[index2][index1] = priceArray[tempId2][tempId1] + 2;}floyd(priceMatrix, 125);
      }
4)迭代中對架構的重構
  • MyPath

    • MyPath添加了兩個距離矩陣,用來存儲一個Path(地鐵線路)內部的(加權)距離信息。
    • 首先,將Path構建成兩個加權無向圖(權值分別為價格和滿意度);然后,通過Floyd算法生成各自的距離矩陣,存儲下來。

    • private int[][] priceArray; // 加權(價錢)距離矩陣
      private int[][] happyArray; // 加權(滿意度)距離矩陣
      // 以下是算法的偽代碼
      private void updateMatrix() {setNodeMap(); // 重新建立映射關系priceArray = initMatrix(nodeCount, 2); // 距離矩陣初始化happyArray = initMatrix(nodeCount, 32); // 距離矩陣初始化for (Each node1, node2 :nodes) { // 建圖賦權priceArray[node1.index][node2.index] = priceArray[node2.index][node1.index] = 1;happyArray[node1.index][node2.index] = happyArray[node2.index][node1.index] = = CalculatePleasure();}floyd(priceArray); floyd(happyArray); // 計算各點之間距離
      }

2. BUG分析

1)bug情況
  • 這種算法在測試數據(最多結點數以及最多圖變動指令數)有所約束時,展現出非常出色的性能。在強測與互測中均未出現錯誤。
  • 但是,我的代碼結構有著較為嚴重的問題:幾乎完全面向過程的寫法嚴重違反了OOP的原則;多個相似結構重復計算等。
2)修復情況
  • 尚未進行代碼重構,僅對課程組給出的標程進行了研究,并進行了簡單的算法優化嘗試。

規格撰寫的心得與體會

  • 規格化設計和契約式編程,讓人如沐清風,受益匪淺。 其實這次的代碼工程量很大,但是由于課程組給出的JML的引導以及課程組已經將我們需要填寫的代碼抽象成了接口,這使得我們在寫代碼時會產生一種錯覺——“這是面向對象課程嗎?”、“這是數據結構補習課吧!”…… 這正是規格化設計和契約式編程 的巨大作用。
  • JML語言——好用不好寫。 JML語言書寫的困難度過高(從課程組編寫JML出現的各種狀況可以看出),給我的感覺是“可遠觀而不可褻玩”。而且,由于DDL過多加上學習資料不足(網上、課程資料都幾乎為零),我缺乏自己動手寫JML的動力。
  • 沒有指引,路程變成了痛苦的過程。也許,是因為JML這一課還在探索階段,課程對JML編寫、檢測、使用的工具的講解和介紹頗少,基本全靠討論區和大佬們的指點,自己摸索著完成任務。固然,可以說這是對我們自主學習能力的養成,但是,有必要嗎?我相信JML單元會一步步從碎片化走向體系化,更加容易上手。
  • 在路上 ……

最后,衷心感謝為這門課程辛苦付出的老師和助教。???

轉載于:https://www.cnblogs.com/FUJI-Mount/p/10905195.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386757.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386757.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386757.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA獲取JVM內存空間和物理內存空間

一、獲取JVM內存空間 系統環境&#xff1a;WIN JDK版本&#xff1a;1.8re 直接調用Runtime中相應的方法即可&#xff1a; public long maxMemory() Returns the maximum amount of memory that the Java virtual machine will attempt to use. If there is no inherent lim…

CMU Database Systems - Sorting,Aggregation,Join

Sorting 排序如果可在內存里面排&#xff0c;用經典的排序算法就ok&#xff0c;比如快排 問題在于&#xff0c;數據表中的的數據是很多的&#xff0c;沒法一下都放到內存里面進行排序 所以就需要用到&#xff0c;外排&#xff0c;多路并歸排序 看下最簡單的&#xff0c;2路并歸…

springboot線程池的使用和擴展

實戰環境 windowns10&#xff1b;jdk1.8&#xff1b;springboot 1.5.9.RELEASE&#xff1b;開發工具&#xff1a;IntelliJ IDEA&#xff1b; 實戰源碼 本次實戰的源碼可以在我的GitHub下載&#xff0c;地址&#xff1a;gitgithub.com:zq2599/blog_demos.git&#xff0c;項目主…

統計單詞個數

我是抄題解狂魔 /* 1.s.substr(x,len) 在s中取出從x位置開始&#xff0c;長度為len的字符串&#xff0c;并返回string類型的字符串。 2.s.find(a) 在s中查找字符串a,并返回起始下標&#xff08;從0開始&#xff09;&#xff0c;若不存在&#xff0c;返回1844674407370955161&am…

通過Rancher安裝K8s

說明 我們用kubernetes去管理Docker集群&#xff0c;即可以將Docker看成Kubernetes內部使用的低級別組件。另外&#xff0c;kubernetes不僅僅支持Docker&#xff0c;還支持Rocket&#xff0c;這是另一種容器技術。希望我這篇文章中簡單的描述能讓你對兩者有所理解和認識。 機…

35. 搜索插入位置-LeetCode

心得&#xff1a;這個題也是二分查找&#xff0c;但是有個小技巧&#xff1a;當left>right的時候 left就是要插入的位置。 代碼&#xff1a; 1 class Solution {2 public int searchInsert(int[] nums, int target) {3 if(numsnull||nums.length0)4 …

Kubectl指令集

1 Kubectl指令集 1.1 Master查詢節點信息 [rootmaster1 kubernetes-1.10]# kubectl get nodes 1.2 查詢所有Pod信息 [rootmaster1 ~]# kubectl get pods --namespacekube-system 1.3 查詢故障的Pod信息 [rootmaster1 ~]# kubectl get pods -n kube-sys…

SQL基礎培訓實戰教程[全套]

學習簡介&#xff1a;林楓山根據網上搜索資料進行參考&#xff0c;編寫制作的SQL Server實操學習教程&#xff0c;歡迎下載學習。 下載鏈接目錄如下&#xff1a; 進度0-SQL基礎語法 下載學習文檔 進度1-建數據表-美化版-2018-6-12 下載學習文檔 進度2-關于主鍵-美化…

K8S儀表板Service unavailable故障的解決辦法

K8S儀表板Service unavailable故障的解決辦法 &#xff08;使用Rancher部署Kubernetes后訪問儀表板提示Service unavailable的問題&#xff09; 一、逐項檢查&#xff1a; 1、操作系統Kernel版本&#xff08;3.10以上&#xff09; 2、檢查OS版本&#xff08;Ubuntu16.04.x、…

實驗五報告

一、實驗結論&#xff1a; 1. 二分查找&#xff1a;補足程序ex1_1.cpp// 練習&#xff1a;使用二分查找&#xff0c;在一組有序元素中查找數據項 // 形參是數組&#xff0c;實參是數組名 #include <stdio.h> const int N5; int binarySearch(int x[], int n, int item…

關于瀏覽器內核

介紹一下對瀏覽器內核的理解主要分成兩個部分&#xff1a;渲染引擎(Render Engine)和JS引擎。常見的瀏覽器內核有哪些&#xff1f;Trident內核&#xff1a;IE&#xff0c;360&#xff0c;搜過瀏覽器&#xff1b;Gecko內核&#xff1a;Netscape6及以上版本&#xff0c;Presto內核…

docker 全部殺掉

殺死所有正在運行的容器 docker kill $(docker ps -a -q) 刪除所有已經停止的容器 docker rm $(docker ps -a -q) 刪除所有未打 dangling 標簽的鏡像 docker rmi $(docker images -q -f danglingtrue) 刪除所有鏡像 docker rmi $(docker images -q) 強制刪除鏡像名稱中包含“do…

實驗五 網絡編程與安全-----實驗報告

一、實驗五 網絡編程與安全-1 1.實驗要求&#xff1a; 兩人一組結對編程&#xff1a; &#xff08;1&#xff09;參考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA &#xff1b; &#xff08;2&#xff09;結對實現中綴表達式轉后綴表達式的功能 MyBC.java&#xff1b…

K8S的HelloWorld之旅

安裝kubectl。使用Google提供商&#xff08;如Google Container Engine或Amazon Web Services&#xff09;創建Kubernetes群集。本教程創建一個 外部負載均衡器&#xff0c;它需要一個云提供商。配置kubectl與Kubernetes API服務器通信。有關說明&#xff0c;請參閱云提供商的文…

思維構造——cf1090D

/* 只要找到兩個沒有關系的點即可 */ #include<bits/stdc.h> using namespace std; #define maxn 100005 long long n,m; int a[maxn],b[maxn]; vector<int>G[maxn]; int main(){cin>>n>>m;if(n1){puts("NO");return 0;}if(n*(n-1)/2<m)…

誤刪docker0網橋之后怎么辦呢?

誤刪docker0網橋之后怎么辦呢&#xff1f; 今天&#xff0c;在搭建k8s node節點環境的時候&#xff0c;好巧不巧&#xff0c;執行了如下命令&#xff1a; 1 2 [roothxin221 ~]# ifconfig docker0 down &>/dev/null [roothxin221 ~]# brctl delbr docker0 &>/de…

boost.asio學習

https://mmoaay.gitbooks.io/boost-asio-cpp-network-programming-chinese/content/Chapter1.html轉載于:https://www.cnblogs.com/hshy/p/10930398.html

Harbor:私有企業級Registry倉庫--快速搭建

前言 Harbor可以通過Docker Composer的方式來部署&#xff0c;如果有正常運行的k8s環境&#xff0c;也可以使用k8s來部署Harbor&#xff0c;本文采用 Docker Composer的方式。 準備 假定Linux系統為Centos 7。 docker &#xff0c;默認安裝即可 yum -y install docker 1 dock…

java-Mysql學生管理系統

Window1//主方法 package stu_zizhu1; import java.awt.Button; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JBu…

Docker版本Jenkins的使用

Docker版本Jenkins的使用 低調的微胖關注贊賞支持 Docker版本Jenkins的使用 12018.05.15 18:21:50字數 1202閱讀 22588 一. 什么是Jenkins Jenkins是當前非常流行的一款持續集成工具&#xff0c;可以幫助大家把更新后的代碼自動部署到服務器上運行。 二. 為什么用docker版…