BUAA OO Summary3
OO Unit3 Summary
Part1:自测数据
单条指令 直接采用随机数的方法生成
```python
def ap(persons,groups):
id = random.randint(0, 2147483647)
if id not in persons:
persons.append(id)
groups.append([])
name = ''.join(random.choice((string.ascii_letters + string.digits)) for _ in range(random.randint(2, 8)))
age = random.randint(0, 2147483647)
return 'ap ' + str(id) + ' ' + name + ' ' + str(age)
```
指令顺序
- 维护一个全局的persons、groups等来记录并控制excpetions的生成
Junit使用
- 因为之前写过kruskal、dijkstra等算法,所以直接把数据灌入后获得正确数据(误)用于Junit的断言
Part2:架构设计
异常类
- 通过接口实现作业要求的异常类,并创立统一的异常计数器来记录静态内容
- 实现MyPerson、MyGroup、MyNetwork等主类,在其中进行异常的处理,主体部分在TrueNet类之中实现,如
@Override
public void addRelation(int id1, int id2, int value) throws PersonIdNotFoundException
, EqualRelationException {
if (!contains(id1)) {
throw new MyPersonIdNotFound(id1);
} else if (!contains(id2)) {
throw new MyPersonIdNotFound(id2);
} else if (getPerson(id1).isLinked(getPerson(id2))) {
throw new MyEqualRelation(id1,id2);
} else {
network.addRelation(id1,id2,value);
}
}
- TrueNet如下,其中存储维护了所有需要的节点、边信息,但该类较庞大,未把部分算法内容分隔开来
- 第三次作业时,由于要实现最短路径问题,并且在有代码行数的限制之下,我重新开了一个算法类Dijkstra,让TrueNet类调用从而控制该核心类,避免无限膨胀
Part3:性能问题与修复情况
对于qvs方法,我原始的实现为
public int getValueSum(int id) {
HashMap<Integer,Person> group = groupNet.get(id);
int result = 0;
for (Edge edge : edges) {
if (group.containsKey(edge.getTo()) && group.containsKey(edge.getFrom())) {
result += edge.getWeight();
}
}
return result * 2;
}
直接两重循环,复杂度为n²
修复为更换容器,用HashSet记录边edges,private final HashSet<Edge> edges;
从而复杂度降为nlogn
public int getValueSum(int id) {
HashMap<Integer,Person> group = groupNet.get(id);
int result = 0;
for (Edge edge : edges) {
if (group.containsKey(edge.getTo()) && group.containsKey(edge.getFrom())) {
result += edge.getWeight();
}
}
return result * 2;
}
修复过程中会发现,这是整个架构上的设计失误,更换容器意味着所有该容器使用处都需要更改,bug修复时候远超限制的5行,不得不撰写文档详细阐释
Part4:扩展
需要将每个Person分类为Customer、Producer、Advertiser、Person
销售路径为Customer->Advertiser->Producer
广告路径为Producer->Advertiser->Customer
->表示isLinked(),Advertiser是买卖双方的acquaintance
Customer可以通过acquaintance查询自己想要商品,碰到Advertiser可继续查询
Producer可以通过acquaintance发布自己生产商品,碰到Advertiser可继续发布
可从原先的最短路径拓展,进行Edge的筛选,即始末为Customer<->Advertiser与Producer<->Advertiser,中间的边为Advertiser<->Advertiser,Advertiser充当传播者
@ public instance model non_null Product[] pruductList;
查销售额
/*@public normal_behavior
@ requires (\exists int i; 0 <= i && i < procuctList.length; procuctList[i] == product);
@ \result = (\sum int i;0 <= i && i<= people.length;people[i].queryProductSale(product));
@ also
@ public exceptional_behavior
@ requires !(\exists int i; 0 <= i && i < procuctList.length; procuctList[i] == product);
@ signals_only ProductNotFoundException;
@*/
public /*@ pure @*/ int querySale(Product product) throws ProductNotFoundException;
查最短销售路径
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < procuctList.length; procuctList[i] == product);
@ requires (\exists int i; 0 <= i && i < people.length; people[i] == customer);
@ requires (\exists int i; 0 <= i && i < people.length; people[i] == producer);
@ ensures \result.length >= 3;
@ ensures (\forall int i; 1 <= i && i < \result.length - 1;\result[i] instanceof Advertiser && (Advertiser)\result[i]).products.contains(product);
@ ensures \result[0] instanceof Customer && \result[0].products.contains(product);
@ ensures \result[\result.length - 1] instance of Producer && \result[\result.length - 1].products.contains(product;
@ ensures (\forall int i; 0 <= i && i < \result.length - 1;\result[i].isLinked(\result[i+1]));
@ ensures \result[\result.length - 2].isLinked(\result[\result.length - 1]);
@ ensures (\exists Person[] pathM;
@ pathM.length >= 3 &&
@ pathM[0].equals(customer) &&
@ pathM[pathM.length - 1].equals(producer) &&
@ (\forall int i; 1 <= i && i < pathM.length; pathM[i - 1].isProductLinked(pathM[i],product));
@ (\forall Person[] path;
@ path.length >= 3 &&
@ path[0].equals(customer) &&
@ path[path.length - 1].equals(producer) &&
@ (\forall int i; 1 <= i && i < path.length; path[i - 1].isProductLinked(path[i],product));
@ (\sum int i; 1 <= i && i < path.length; path[i - 1].queryLevel(path[i])) >=
@ (\sum int i; 1 <= i && i < pathM.length; pathM[i - 1].queryLevel(pathM[i]))) &&
@ \result==(\sum int i; 1 <= i && i < pathM.length; pathM[i - 1].queryLevel(pathM[i])));
@ also
@ public exceptional_behavior
@ requires !(\exists int i; 0 <= i && i < procuctList.length; procuctList[i] == product);
@ signals_only ProductNotFoundException;
@ public exceptional_behavior
@ requires !(\exists int i; 0 <= i && i < people.length; people[i] == customer)
@ signals_only PersonNotFoundException;
@ public exceptional_behavior
@ requires !(\exists int i; 0 <= i && i < people.length; people[i] == producer)
@ signals_only PersonNotFoundException;
@*/
public /*@ pure @*/ List<Person> queryLeastProductPath(Product product,Customer customer,Producer producer) throws ProductNotFoundException,PersonNotFoundException;
Part5:心得体会
- 又了解了一种描述语言,并且jml立刻就可以在第四单元的uml绘制之中发挥作用
- 最小生成树、最短路径的jml阅读起来相当烧脑,难以想象该如何撰写
- 第一次从数据量的角度感受到算法优化所带来的的影响,之前总是从理论分析,并没有实际实验,才直观感受logn与n之间的复杂度差距