OO第三单元总结
分析在本单元自测过程中如何利用JML规格来准备测试数据
学习了推荐的Junit,尝试了使用。
在数据方面,主要根据JML规格中各个分支进行考虑,对于各个分支可能出现的情况手动构造数据以及一些特殊强度的数据,并结合一定的自动生成的数据。
比如测试sim的是否发生超时
FILE *rpstop,*rp,*wp;
wp = fopen("results.txt","w");
if ( wp == NULL ){
perror("Can't open ");
return 1;
}
int i = 0;
for(i = 1; i <= 2000; i ++)
{
fprintf(wp,"ap %d idis%d %d\n",i,i,100);
}
fprintf(wp,"ag 1\n");
for(i = 1; i <= 2000; i++)
{
fprintf(wp,"ar %d 1 %d\n",i,i);
}
for(i = 2; i<= 500; i++)
{
fprintf(wp,"arem %d 100 0 1 %d\n", i , 2000);
}
for(i = 2; i <= 500; i++)
{
fprintf(wp,"sim %d\n",i);
}
fprintf(wp,"qm 1");
梳理本单元的架构设计,分析自己的图模型构建和维护策略
本单元的图结构是比较清晰的,person作为结点,relation为边,value为边的权值。
对于图的维护,由于主题都是在Network中实现的,在Network中设置了一个存储person,而对于每个Person的relation,并没有在network中直接的存储,而是对于每个人,在Person的结构中保存。
而对于容器的选择,由于JML并不对我们的实现做出要求,使用的容器并没有具体的限制。但是站在性能方面进行考虑,由于id的唯一性,Hashmap可行,而在查找的性能方面,就产生了较大的优势。
一些算法的实现
对 isCircle
并查集
public int findlinkendid(int id, HashMap<Integer,Integer> tree) {
if (tree.get(id) == id) { return id; }
else {
depth++;
return findlinkendid(tree.get(id),tree);
}
}
public void mergelink(int id1,int id2,HashMap<Integer,Integer> tree) {
depth = 0;
int idend1 = findlinkendid(id1,tree);
int depth1 = depth;
depth = 0;
int idend2 = findlinkendid(id2,tree);
int depth2 = depth;
if (idend1 != idend2) {
if (depth1 >= depth2) {
tree.replace(idend2,idend1);
}
else {
tree.replace(idend1,idend2);
}
}
}
对qlc
采用 prim
算法
HashMap<Integer, Integer> islinked = getblock(id);
int size = islinked.size();
int sum = 0;
ArrayList<Road> roads = new ArrayList<>();
for (Integer integer : islinked.keySet()) {
Person p1 = getPerson(integer);
ArrayList<Integer> value = ((MyPerson) p1).getValue();
for (int i = 0; i < value.size(); i++) {
Road road = new Road(p1.getId(),
((MyPerson) p1).getAcquaintance().get(i).getId(), value.get(i));
roads.add(road);
}
}
Collections.sort(roads);
Iterator<Road> iterator = roads.iterator();
int n = 1;
while (iterator.hasNext()) {
Road temproad = iterator.next();
int id1 = temproad.getBegin();
int id2 = temproad.getEnd();
if (forlink.findlinkendid(id1, islinked) != forlink.findlinkendid(id2, islinked)) {
forlink.mergelink(id1, id2, islinked);
sum += getPerson(id1).queryValue(getPerson(id2));
n++;
if (n == size) {
break;
}
}
}
return sum;
对 sim
基于堆优化的 dijsktra
算法
HashMap<Integer,Integer> havein = new HashMap<>();
PriorityQueue<Canarrive> queue = new PriorityQueue<>();
queue.add(new Canarrive(p1id, 0));
while (queue.peek().getId() != p2id) {
Canarrive temp = queue.poll();
int tempid = temp.getId();
if (havein.get(tempid) == null) {
havein.put(tempid,1);
ArrayList<Integer> tperson =
((MyPerson) getPerson(tempid)).getAcquaintanceid();
ArrayList<Integer> tvalue = ((MyPerson) getPerson(tempid)).getValue();
int size = tperson.size();
for (int i = 0; i < size; i++) {
if (havein.get(tperson.get(i)) == null) {
queue.add(new Canarrive(tperson.get(i),
temp.getDistance() + tvalue.get(i)));
}
}
}
}
return queue.poll().getDistance();
按照作业分析代码实现出现的性能问题和修复情况
在本次作业中,性能方面的问题,主要出现在第三次作业中的sim,在修复bug时,采用了基于堆优化的 dijsktra
对Network进行扩展,并给出相应的JML规格
扩展方案
-
新增Advertiser、Producer、Customer类,均继承自Person类
-
新增Advertisement、PurchaseMessage类
-
新增product类,记录了ProducerId,Price,Sale(销售额)等信息
-
Network类新增 product[] productList 属性
-
Producer可以生成产品,添加到productList中,而Advertiser可以发送addvertisement,
核心方法
void Addadvertisement(int id) 添加addvertisement,在sendaddvertisement时,就可以将product添加到用户的偏好中去。
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == aid && people[i] instanceof Advertiser) && (\exists int i; 0 <= i && i<= productList.length; productList[i].getId() == productid);
@ requires !ContainMessage(Mid)
@ ensures
@ assignable messages;
@ ensures ContainsMessage(Mid)
@ ensures messages.length == \old(messages.length) + 1
@ ensures (\forall int i; 0 <= i && i < \old(messages.length);
@ (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
@ ensuers (\exists int i; 0 <= i && i < messages.length; (\old !ContainMessage((Advertisement)messages[i].getid)) && messages[i] instanceof Advertisement && messages[i].getGroupId == productid;
@ also
@ public exceptional_behavior
@ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length;
@ people[i].getId() == aid && people[i] instanceof Advertiser);
@ signals (EqualMessageIdException e) (\exists int i; 0 <= i && i < messages.length;
@ messages[i].getId = Mid)) && (\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Advertiser);
@ signals (ProductIdNotFoundException e) (\exists int i; 0 <= i && i < messages.length;
@ messages[i].getId = Mid)) && !(\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Advertiser) && !(\exists int i; 0 <= i && i < productList.length;productList[i].getId() == productid)
@*/
void Addadvertisement(int aid,int productid,int Mid)void Purchase(int aid,int CustomerId) ,让用户在自己偏好中的广告,根据其信息进行购买,用户减少产品价格的money,产品10%的价格给Advertiser,90%给Producer,且增加Project的sale(销售额)。
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == CustomerId)
@ requires (\exists int i; 0 <= i && i < people.getPerson(CustomerId).getprefer.length; people.getPerson(CustomerId).getprefer[i].getId() == aid))
@ ensures
@ assignable getPerson(getMessge(aid).getAdvertiserId).getmoney,getPerson(getProduct(getMessge(aid).getProductId()).getProducerId).getmoney, getPerson(CustonerId).getmoney ;
@ assignable getProduct(getMessge(aid).getProductId).getsale;
@ ensures (\exists int i; 0 <= i && i < people.length; people[i].getId() == CustomerId && people[i].getmoney = (\old people[i].getmoney) - getProduct(getMessge(aid).getProductId()).getPrice);
@ ensures (\exists int i; 0 <= i && i < people.length; people[i].getId() == getMessge(aid).getAdvertiserId && people[i].getmoney = (\old people[i].getmoney) + getProduct(getMessge(aid).getProductId()).getPrice / 10);
@ ensures (\exists int i; 0 <= i && i < people.length; people[i].getId() == getProduct(getMessge(aid).getProductId()).getProducerId && people[i].getmoney = (\old people[i].getmoney) + getProduct(getMessge(aid).getProductId()).getPrice / 10 * 9 );
@ ensures (\exists int i; 0 <= i && i < productList.length; productList[i].getId() == getMessge(aid).getProductId() && productList[i].getsale = (productList[i].getsale) + getProduct(getMessge(aid).getProductId()).getPrice);
@ also
@ public exceptional_behavior
@ signals (PersonIdNotFoundException e) !(\exists int i; 0 <= i && i < people.length;
@ people[i].getId() == CustmoerId);
@ signals (AdvertisementIdException e) (\exists int i; 0 <= i && i < people.length;
@ people[i].getId() == CustmoerId) !(\exists int i; 0 <= i && i < people.getPerson(CustomerId).getprefer.length; people.getPerson(CustomerId).getprefer[i].getId() == aid));
@*/
void Purchase(int aid,int CustomerId)int getSale(int productId) 查询销售额,达到要求中能够查询销售额的目的
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i<= productList.length; productList[i].getId() == productid);
@ ensures
@ assignable \nothing
@ ensures (\exists int i; 0 <= i && i<= productList.length; productList[i].getId() == productid && \result = productList[i].getSale);
@ also
@ public exceptional_behavior
@ signals (ProductIdNotFoundException e) !(\exists int i; 0 <= i && i < productList.length;productList[i].getId() == productid)
@*/
本单元学习体会
本单元主要对于JML进行了学习,总体上感觉,无论是看JML还是写JML,都是非常困难的一件事(也许因为不熟悉),看JML的时候,和以往习惯的,利用自然语言进行的需求表达,差距非常的大,比如本单元中一些最短路径、最小生成图的JML表达,初看时并不能很快的明白到底是要干什么。同时多个括号的重叠导致了一定的阅读困难。
而在写JML方面,在研讨课的那次自己写JML,自己写的JML和官方的JML的比较,发现了挺大的差距的。而且写JML的过程也挺困难的,很多的时候,做不到把逻辑上的想法转换为JML形式上的表达。
还有就是一些算法,算是复习了之前离散数学和数据结构的一些知识。