ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OO_Unit3

2022-06-05 21:32:36  阅读:145  来源: 互联网

标签:OO product get ensures private Person Unit3 public


OO_Unit3

一、架构设计

本单元所处理的图网络结构的核心部分为 Person (对应点)与 Relation(对应边),当然,考虑到社交网络的真实情况,我们还引入了 Group (由 Person 构成的集合,可以类比为圈子)。在后续迭代开发过程中又引入了一系列 Message 作为 Person 之间的交互手段。

综上,我们考虑主要对 Person、Relation、Group 与 Message 进行建模。

从面向对象设计的角度来看,Person 类应以邻接表的形式存储 Relation 与 Message,它应该仅关注与自己相关的 Relation、Group 与 Message。而为了方便统一管理数据,在整个社交网络中既可以使用邻接矩阵(在自行测试时数据规模较大,因而没使用这种实现方式)也可以使用邻接表的形式。

此外,考虑到建立网络后需要进行大量的查询操作,在设计时尽可能使用 HashMap 可以大幅提高查找效率。

二、测试数据

受限于数据规模,自行搭建的数据生成器难以在有限时间内完成全覆盖测试,因此,在测试过程中,一边用评测机与其他同学的程序进行对拍,一边自行构造测试数据完成功能性测试与最大数据规模下的时间测试。

构造数据规模限制下的最大完全图对 sim 指令时间性能进行测试时,本地测出 Prim 算法约 2.3s,堆优化的 Dijkstra 算法约 2.8s。

三、性能相关

为了避免重复查询带来的额外性能开销,可以考虑脏位静态数据管理的设计。相比之下,脏位的实现较为简单,但在循环<修改数据-查询>的极端情况下(被针对性构造数据)仍旧会超时。所以,最终还是得“用空间换时间”,尽可能将所有查询结果存下来,让查询操作可以以 O(1) 的复杂度获取所需数据。

具体来说,在实现 qgvs、qgav 等查询 Group 数据的指令时,将本属于它们的计算操作分解到 ag、dfg、ar、 atg 等修改操作中,避免重复查询带来的重复计算的时间开销。此外,对于 qci 等查询图中节点间连通性的指令,使用并查集维护一个新的 Block 是个不错的选择(为后续使用 Dijkstra 算法传递 Message提供帮助)。

为了实现最后一次版本迭代中新增的 sim 指令,应使用经过堆优化的 Dijkstra 算法。之所以使用该算法,是因为考虑到数据规模限制为:<人数:≤ 2500 人,sim 指令数:≤ 100 条,总指令数:≤ 10000条>,一方面,在人数与指令数最大化时为稀疏图,故应使用 Dijkstra 而非 Prim ;另一方面,传统 Dijkstra 算法的复杂度为 ​,按 C 语言 1s 1亿次操作,C 运行速度为 Java 10倍来粗略估计,在数据规模最大化的情况下,传统 Dijkstra 算法执行一次至少需耗时 0.625s,100 次即为 62.5s,超出了时间限制范围。而如果使用经过堆优化的 Dijkstra 算法,其复杂度为 ​,其中 m 为边数,n 为点数,同样在最大数据规模下,执行一次 sim 指令耗时约 0.0038s ,100次即为 0.38s,在可接受范围内。

四、扩展 NetWork

题目要求

假设出现了几种不同的Person

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

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

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

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

如此Network可以支持市场营销,并能查询某种商品的销售额和销售路径等 请讨论如何对Network扩展,给出相关接口方法,并选择3个核心业务功能的接口方法撰写JML规格(借鉴所总结的JML规格模式)

相关接口及方法

(为了简洁,不列出相应 set 和 get 方法)

 public interface Advertiser extends Person{
     private ArrayList<Producer> producers;
     private ArrayList<Customer> customers;
     public void sendAdvertisement(Customer customer, Advertisement advertisement);
     public void sendRequest(Producer prodecer);
 }
 public interface Producer extends Person{
     private ArrayList<Advertiser> advertisers;
     private ArrayList<Product> production;
     public Product produce();
     public void sale(Advertiser advertiser, Product product);
 }
 public interface Customer extends Person{
     private int preference;
     private ArrayList<Advertiser> advertisers;
     private ArrayList<Advertisement> advertisements;
     private ArrayList<Product> production;
     public void buy(Advertiser advertiser);
 }

撰写核心业务 JML 规格

     /*@ public normal_behavior
       @ requires (\exists int i; 0 <= i && i < advertisers.length;
       @ advertisers.get(i).equals(advertiser));
       @ ensures money == \old(money) - product.getValue();
       @ ensures production.length == \old(production).length + 1;
       @ ensures (\exists int i; 0 <= i && i < production.length;
       @ production.get(i).equals(product));
       @*/
     public /*@ pure @*/ void buy(Advertiser advertiser, Product product);
 ​
 /*@ public normal_behavior
       @ requires (\exists int i; 0 <= i && i < advertisers.length;
       @ advertisers.get(i).equals(advertiser));
       @ requires (\exists int i; 0 <= i && i < \old(production).length;
       @ \old(productions.get(i)).equals(product));
       @ ensures money == \old(money) + product.getValue();
       @ ensures production.length == \old(production).length - 1;
       @ ensures (\forall int i; 0 <= i && i < production.length;
       @ !production.get(i).equals(product));
       @*/
 public /*@ pure @*/ void sale(Advertiser advertiser, Product product);
 ​
 /*@ public normal_behavior
       @ requires (\exists int i; 0 <= i && i < customers.length;
       @ customers.get(i).equals(customer));
       @ ensures customer.getAdvertisements.length ==
       @ \old(customer.getAdvertisements).length + 1;
       @ ensures (\exists int i; 0 <= i && i < customer.getAdvertisements.length
       @ customer.getAdvertisements.get(i).equals(advertisement));
       @*/
 public /*@ pure @*/ void sendAdvertisement(Customer customer,
                                                Advertisement advertisement);

五、心得体会

本单元本意是学习使用 JML 规格来无歧义地表达需求以便于理解。然而,我认为当 JML 规格长达数十行时,各类循环语句嵌套时,使用 JML 并不能加快读者的理解,而辅以一定的文字性说明则可以大大缩短理解时间(比如 sim:求两人之间的带权最短路)。此外,JML 规格本身其实更像是通俗化的数理逻辑,是将离散数学中的布尔代数、谓词逻辑等内容应用到实际开发场景中的产物。

在进行测试的过程中,由于本单元涉及的指令过多,且程序运行速度受到限制,难以进行较为全面的自动化测试,即便在自动化测试中找到了 bug ,在自动生成的数万行的数据中进行 bug 定位也是极为耗时的工作。现在想来,可能针对各个模块或者方法做针对性的单元测试可能更为合理,从局部的正确性推广到全局的正确性。

标签:OO,product,get,ensures,private,Person,Unit3,public
来源: https://www.cnblogs.com/iszry/p/16345164.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有