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:架构设计

异常类

  • 通过接口实现作业要求的异常类,并创立统一的异常计数器来记录静态内容
    image
  • 实现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如下,其中存储维护了所有需要的节点、边信息,但该类较庞大,未把部分算法内容分隔开来
    image
  • 第三次作业时,由于要实现最短路径问题,并且在有代码行数的限制之下,我重新开了一个算法类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;
    }

直接两重循环,复杂度为
修复为更换容器,用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之间的复杂度差距
posted @ 2022-06-06 15:55  阿莫誒  阅读(36)  评论(0编辑  收藏  举报