HIT软件构造实验2

HIT软件构造lab2实验总结

    • 1 实验目标概述
    • 2 实验环境配置
    • 3 实验过程
      • 3.1 Poetic Walks
        • 3.1.1 Get the code and prepare Git repository
      • 3.1.2 Problem 1: Test Graph < String >
      • 3.1.3 Problem 2: Implement Graph < String >
        • 3.1.3.1 Implement ConcreteEdgesGraph
        • 3.1.3.2 Implement ConcreteVerticesGraph
      • 3.1.4 Problem 3: Implement generic Graph< L >
        • 3.1.4.1 Make the implementations generic
      • 3.1.5 Problem 4: Poetic walks
        • 3.1.5.1 Test GraphPoet
        • 3.1.5.3 Graph poetry slam
    • 3.2 Re-implement the Social Network in Lab1
      • 3.2.1 FriendshipGraph类
      • 3.2.2 Person类
      • 3.2.3 客户端main()
      • 3.2.4 测试用例

1 实验目标概述

本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象 编程(OOP)技术实现 ADT。具体来说:
针对给定的应用问题,从问题描述中识别所需的 ADT;
 设计 ADT 规约(pre-condition、post-condition)并评估规约的质量;
 根据 ADT 的规约设计测试用例;
 ADT 的泛型化;
 根据规约设计 ADT 的多种不同的实现;针对每种实现,设计其表示 (representation)、表示不变性(rep invariant)、抽象过程(abstraction function)
 使用 OOP 实现 ADT,并判定表示不变性是否违反、各实现是否存在表 示泄露(rep exposure);
 测试 ADT 的实现并评估测试的覆盖度;
 使用 ADT 及其实现,为应用问题开发程序;
 在测试代码中,能够写出 testing strategy 并据此设计测试用例。

2 实验环境配置

简要陈述你配置本次实验所需环境的过程,必要时可以给出屏幕截图。特别是要记录配置过程中遇到的问题和困难,以及如何解决的。

在 Eclipse IDE 中安装配置 EclEmma(一个用于统计 JUnit 测试用例的代码覆盖度的 plugin)直接从Eclipse Market下载安装即可。
在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号)。
https://github.com/ComputerScienceHIT/Lab2-1170301026.git

3 实验过程

请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。

3.1 Poetic Walks

分别在两个类ConcreteEdgesGraph,ConcreteVerticesGraph 实现Graph接口。
Graph接口要求实现add(添加新节点),set(添加新边),remove(移除节点),vertices(获得所有的节点集合),sources(target)获得以target为目标节点的边的起始节点,targes(source)获得以source为起始节点的边的目标节点。
Poet:假设存在一条由a到b的有向边,构造有向图,再给定一句子,如果句子中两个相邻单词在有向图中有一个中间单词,则将该单词插入到a与b中间,若存在多个中间单词,则插入权重最大的那个

3.1.1 Get the code and prepare Git repository

自https://github.com/rainywang/Spring2019_HITCS_SC_Lab2/tree/master/P1 获得实验代码。
Git命令:

git init
git remote add origin [email protected]:ComputerScienceHIT/Lab2-1170301026.git
git pull origin master
git add .
git commit -m “init”
git push origin master

3.1.2 Problem 1: Test Graph < String >

测试Graph需将empty改成如下:

更改empty函数
可运行GraphStaticTest进行测试

3.1.3 Problem 2: Implement Graph < String >

以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。

3.1.3.1 Implement ConcreteEdgesGraph

  • 1 实现Edge< L >
Fileds 作用
private L source 起始节点
private L target 目标节点
private int weight 边权值
Method 作用
getsource() 返回有向边起始节点
gettarget() 返回有向边目标节点
getweight() 返回边权值
@Override toString() 使用@Override注释toString以确保正确覆盖Object方法的toString方法
/**
 * TODO specification Immutable. This class is internal to the rep of
 * ConcreteEdgesGraph.
 * 
 * 

* PS2 instructions: the specification and implementation of this class is up to * you. */ class Edge<L> { // TODO fields private final L source; private final L target; private final int weight; // Abstraction function: // AF(source,target,weight)=an edge contains the source vertex,the target vertex label,weight // Representation invariant: // weight no negative number // Safety from rep exposure: // All fields are private; // source and target are Strings, so are guaranteed immutable; // use final to guarantee weight is immutable; // TODO constructor public Edge(L s, L t, int w) { this.source = s; this.target = t; this.weight = w; checkRep(); } // TODO checkRep //Check the rep invariant is true //***Warning:this does nothing unless you turn on assertion checking // by passing -enableassertions to Java private void checkRep() { assert weight>=0; } // TODO methods public L getsource() { checkRep(); return source; } public L gettarget() { checkRep(); return target; } public int getweight() { checkRep(); return weight; } // TODO toString() @Override public String toString() { String tmp = null; tmp=source.toString()+target.toString()+Integer.toString(weight); checkRep(); return tmp; } }

  • 2.实现ConcreteEdgeGraph
method 作用
add(L vertex) 调用vertices.add,其返回结果为boolean且满足spec定义。
set(L source,L target,int weight) 检查输入满足weight!=0,若满足则调用edges.add添加边并返回weight,若满足weight=0且该边存在于edges中
remove(L vertex) 检查输入满足vertex存在vertices中,当存在时,删除该节点,同时删除所有与之相连的边
Set vertices 返回vertices
Sources(L target) 遍历edges,调用gettarget方法,若找到与tareget相同的,则将该边加入map中
Targets(L source) 遍历edges,调用getsource方法,若找到与source相同的,则将该边加入map中
@Override toString()
/* Copyright (c) 2015-2016 MIT 6.005 course staff, all rights reserved.
 * Redistribution of original or derived work requires permission of course staff.
 */


package src.P1.graph;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * An implementation of Graph.
 * 
 * 

* PS2 instructions: you MUST use the provided rep. */ public class ConcreteEdgesGraph<L> implements Graph<L> { private final Set<L> vertices = new HashSet<>(); private final List<Edge<L>> edges = new ArrayList<>(); // Abstraction function: // AF(vertices,edges)=a graph with vertices and edges // Safety from rep exposure: // All fields are private // use final to guarantee immutable @Override public boolean add(L vertex) { try { if (!vertices.contains(vertex)) { vertices.add(vertex); return true; } else return false; } catch (Exception e) { throw new RuntimeException("not implemented"); } } @Override public int set(L source, L target, int weight) { try { Edge<L> e = new Edge<L>(source, target, weight); if (weight != 0) { edges.add(e); return weight; } // if weight nozero,add edge and set weight else if (weight == 0 && edges.contains(e)) { edges.remove(e); return 0; } // if weight zero&the edge exists, else return 0; } catch (Exception e) { throw new RuntimeException("not implemented"); } } @Override public boolean remove(L vertex) { try { if (vertices.contains(vertex)) { for (Edge<L> item : edges) { if (vertex == item.getsource() || vertex == item.gettarget()) { edges.remove(item); } } return vertices.remove(vertex); } else return false; } catch (Exception e) { throw new RuntimeException("not implemented"); } } @Override public Set<L> vertices() { try { return vertices; } catch (Exception e) { throw new RuntimeException("not implemented"); } } @Override public Map<L, Integer> sources(L target) { try { Map <L,Integer>map=new HashMap<>(); for(Edge<L> item:edges) { if(target==item.gettarget()) { map.put(item.getsource(),Integer.valueOf(item.getweight())); } } return map; } catch(Exception e) { throw new RuntimeException("not implemented"); } } @Override public Map<L, Integer> targets(L source) { try { Map <L,Integer>map=new HashMap<>(); for(Edge<L> item:edges) { if(source==item.getsource()) { map.put(item.gettarget(),Integer.valueOf(item.getweight())); } } return map; } catch(Exception e) { throw new RuntimeException("not implemented"); } } // TODO toString() @Override public String toString() { String tmp = null; tmp = getClass().getName() + '@' + Integer.toHexString(hashCode()); return tmp; } }

3.1.3.2 Implement ConcreteVerticesGraph

  • 1 实现Vertex< L >
Field 作用
private L label 节点名字
private Map sources 所有以label为目标节点的边,<起始节点lable,边的权重>.
private Map targets 所有以label为其实节点的边,<目标节点label,边的权重>
Interface 作用
setSource(L source,int weight) 检查输入满足source!=null,weight>=0。当weight==0时,调用this.removeSource,当weight>0时,调用Map.put修改source并且记录初始值。
removeSource(L source) 检查输入满足source!=null,调用sources.remove,并返回(不存在则返回0)。
setTarget(L target,int weight) 检查输入满足target!=null,weight>=0,当weight=0时,调用this.removeTarget,当weight>0时,调用targets.put并返回(不存在则返回0)。
removeTarget(L target) 检查满足target!=null。调用targets.remove(),返回。
remove(final L vertex) 调用removeSource和removeTarget
  • 2 实现ConcreteVerticeGraph
Method 实现思路
add(L vertex) 检查输入满足vertex!=null。遍历点集vertices,若已存在vertex则返回false,否则调vertices.add并返回true
set(L source,L target,int weight) 遍历点集两次,分别检查vertices中是否存在source vertex和target vertex,若均不存在则调用vertices.add并调用source.setTarget和target.setSource设置边和权值,
remove(L vertex) 检查输入满足vertex!=null。如果输入节点不存在则返回false,否则,遍历vertices中的每一个节点调用v.remove在targes和sources中删除该节点,
Set vertices(L vertex) 遍历点集,找到Label与vertex相同的点并加入Setans中,最后返回ans
Sources(L target) 遍历点集.如果没有target则返回空集合,否则调用targetVertex.getSources(target)
Targets(L source) 遍历点集如果没有target则返回空集合,否则调用sourceVertex.getTargets(source)

3.1.4 Problem 3: Implement generic Graph< L >

3.1.4.1 Make the implementations generic

将类及接口声明改为:
ConcreteVerticesGraph< L >
ConcreteEdgeGraph< L >

3.1.5 Problem 4: Poetic walks

3.1.5.1 Test GraphPoet

HIT软件构造实验2_第1张图片

Field 说明
Private final Graph affinityGraph 配置文件生成的Graph
Private final List corpusWord 文集包含的单词

3.1.5.3 Graph poetry slam

  • main函数:
    在这里插入图片描述

3.2 Re-implement the Social Network in Lab1

用P1中实现的ConcreteEdgeGraph或者ConcreteVertexGraph实现FriendshipGraph

3.2.1 FriendshipGraph类

public class FriendshipGraph extends ConcreteEdgesGraph<Person> {

	/**
	 * Add Vertex(Person)
	 * 
	 * @param a person p
	 */
	public void addVertex(Person p) {
		this.add(p);
	}

	/**
	 * Add Edge
	 * 
	 * @param Person pa
	 * @param Person pb
	 * @param weight
	 */
	public void addEdge(Person pa, Person pb, int w) {
		this.set(pa, pb, w);
	}

	/**
	 * Calculate the distance between two person
	 * 
	 * @param a person pa
	 * @param a person pb
	 * @return the shortest distance between two person,return -1 if personA can't
	 *         reach personB
	 */
	public int getDistance(Person pa, Person pb) {
		if (pa == pb) {
			return 0;
		}
		int dis = 1;
		// BFS
		Queue<Person> queue = new LinkedList<Person>();
		// use LinkedList to implement queue
		Map<Person, Integer> map = new HashMap<Person, Integer>();
		queue.offer(pa);
		while (!queue.isEmpty()) // queue not empty
		{
			Person p = queue.poll();// return top person
			Map<Person, Integer> neighbour = this.targets(p);
			Iterator entries = neighbour.entrySet().iterator();
			// Traversing the map to find key person
			while (entries.hasNext()) {
				Map.Entry<Person, Integer> entry = (Map.Entry<Person, Integer>) entries.next();
				Person key = entry.getKey();
				Integer value = entry.getValue();
				if (!map.containsKey(key)) {
					map.put(key, value);
					queue.offer(key);
					if (key == pb) {
						return map.get(key);
					}
				}
			}
			dis++;
		}
		return -1;
	}
}
函数 实现思路
addVertex(Person p) 调用父类接口this.add(newPerson)
addEdge(Person pa,Person pb) 调用父类接口this.set(pa,pb,1)
getDistance(Person pa,Person pb) 使用BFS算法求得图中stPerson与edPerson之间的最短距离,BFS中需要遍历邻居节点,遍历map并调用父类接口的targets方法获得父类接口

3.2.2 Person类

HIT软件构造实验2_第2张图片

3.2.3 客户端main()

与实验一中基本一致

3.2.4 测试用例

直接采用实验一测试代码,认识的两人之间权值设置为1即可

你可能感兴趣的:(Software,Construction)