BUAA-OO-2022 Unit-3 博客总结

BUAA-OO-2022 Unit-3 博客总结

本单元的目标为熟悉JML规格,任务是构建一个包含人、组、网络、消息的社交网络。在维护过程中,我们需要通过某些算法来进行优化以缩减查询时间。抽象来讲,人可以视为社交网络中的一个节点;一个组可以视为社交网络中的连通图;而整张网络可以视为图;人与人的关系便可以看做带权边,由此,我们将一个具体问题转换成了一个图论问题。

架构分析

图模型构建

第一次作业

涉及的元素为网络;涉及的操作为添加关系(人与人、人与组),查询联通图数量等。

第二次作业

新增元素消息;有关消息的操作包含添加发送等;同时考察群组部分属性的查询,涉及了最小生成树。

第三次作业

消息元素中引入表情提醒红包三个种类;新增涉及这三种种类消息的操作以及消息的间接发送

维护策略

在本单元中,涉及性能优化的主要有三点:在维护联通图数量时采用并查集算法;在最小权值搜索时采用 Dijskra 算法;在针对属性查询的操作中采用以空间换时间的思想,实时维护变量简化查询。

路径压缩的并查集

前文提到,可以将视为联通图,因此我们对于组数的查询实际就是对联通图数量的查询。而我们可以将每一个联通图视为一个集合,作为结点就是集合中的元素,所以当我们可以为每个人附加一个集合的标识,在添加人与人的关系时就将这个标识统一成一个,这就是并查集的思想。而笔者在合并时同时采取了按秩合并与路径压缩。

堆优化的Dijskra 算法

在最小生成树中,笔者采取了堆优化的 Dijskra 算法,如果未采用堆优化或者使用 DFS 存在较大超时风险。对于该问题,结点是人,而边的权值便是关系中的Value

以空间换时间

在对于属性的查询中,如果每次查询再更新,时间复杂大较大。因此我们可以维护对应该属性的变量,在关系更新的时候实时更新该变量,就可以以O(1)的时间复杂度进行查询。

数据构造与测试

数据构造

数据构造主要采用随机构造与针对构造的方式。随机构造不言而喻,针对构造主要是依据 UML规格 中的细节以及性能进行。

测试

在本地测试时,笔者主要与伙伴采用多人对拍的形式进行。同时,建议在实现过程中独立思考,以免同时和多个伙伴理解错 JML规格

BUG 分析

自测

主要是通过大量随机数据与伙伴对拍,同时共享各自认为 JML规格 中可能出现问题的点并进行测试。

强测

笔者三次强测未出现问题。

互测

笔者在第二次作业自测环节末发现了 qgvs 时间复杂度较高的问题,但出于稳妥起见,为避免引入更多 BUG 而没有对该点进行优化,这导致了三次作业中唯一的 BUG

而针对他人的测试主要是随机数据的压力测试,以及对组员上限qgvs并查集维护Dijskra实现进行测试。

Network 拓展

需求

假设出现了几种不同的Person

  • Advertiser:持续向外发送产品广告

  • Producer:产品生产商,通过Advertiser来销售产品

  • Customer:消费者,会关注广告并选择和自己偏好匹配的产品来购买 -- 所谓购买,就是直接通过Advertiser给相应Producer发一个购买消息

  • Person:吃瓜群众,不发广告,不买东西,不卖东西

/*@ public normal_behavior
@ requires contains(id1) && contains(id2) && getPerson(id1) instanceof Advertiser && getPerson(id2) instanceof Customer
     @ ensures (getPerson(id2).getAdvertisement.addAll((Advertiser) getPerson(id1).getAdvertisement))
     @ also
     @ public exceptional_behavior
     @ signals (PersonIdNotFoundException e) !contains(id1);
     @ signals (PersonIdNotFoundException e) contains(id1) && !contains(id2);
     @ signals (PersonTypeNotCorrectException e) contains(id1) && contains(id2) && !(getPerson(id1) instanceof Advertiser)
     @ signals (PersonTypeNotCorrectException e) contains(id1) && contains(id2) && getPerson(id1) instanceof Advertiser && !(getPerson(id2) instanceof Customer);
     @*/
   public void sendAdvertisement(int id1, int id2) throws PersonIdNotFoundException, PersonTypeNotCorrectException;


   /*@ public normal_behavior
    @ requires contains(id) && getPerson(id) instanceof Advertiser
    @ ensures \result == (\sum int i; 0 <= i && i < people.length; people[i] instanceof Customer &&
    @ \sum int j; 0 <= j && j < people[i].getPreference && people[i].getPreference[j].equals(id); 1
    @ also
    @ public exceptional_behavior
    @ signals (PersonIdNotFoundException e) !contains(id);
    @ signals (PersonTypeNotCorrectException e) contains(id) && !(getPerson(id) instanceof Advertiser)
    @*/
   public int querySalesValue(int id) throws PersonIdNotFoundException, PersonTypeNotCorrectException;

   /*@ public normal_behavior
    @ requires contains(id) && getPerson(id) instanceof Producer
    @ ensures \result == (\num_of int i; 0 <= i && i < people.length; people[i] instanceof Advertiser &&
    @                           (Advertiser) people[i].getProducer.equals((Producer) getPerson(id)));
    @ also
    @ public exceptional_behavior
    @ signals (PersonIdNotFoundException e) !contains(id);
    @ signals (PersonTypeNotCorrectException e) contains(id) && !(getPerson(id) instanceof Producer)
    @*/
   public List<PersonqueryMarketChannel(int id) throws PersonIdNotFoundException, PersonTypeNotCorrectException;

心得体会

通过本单元,笔者对 JML 有了较为清晰的认识,但笔者认为本单元不应将同学过多的注意点引导至性能优化。

而关于如果书写 JML ,笔者认为应当首要明确需求,然后梳理异常与正常的情况,最后给出不同情况下的处理。

posted @ 2022-06-06 12:10  yufu06  阅读(15)  评论(0编辑  收藏  举报