hackerkiller

导航

统计

第三单元总结

(1) 分析在本单元自测过程中如何利用JML规格来准备测试数据

在理解JML规格含义及要求的前提下,对JML中的每个normal_behavior和exceptional_behavior设计多组相应的测试数据,尤其是针对边界数据、null等特殊情况的数据,并对相应的后置条件进行检查,并使用repOk判断是否满足不变式和约束。

(2) 梳理本单元的架构设计,分析自己的图模型构建和维护策略

本单元作业以每个人为点,人于人之间的关系为有权值的无向边,用每个人的acquaintance和value维护每个点的相连的点和边权。Group是某些点的集合,在图中并无实际含义。Messege可看作可在图中按边移动的属性。Network是协调点的属性、点之间关系、Group的成员、Message的移动,以及整个图属性的总类。在实现时要对每条边(即关系)进行保存,以便于最小生成树的操作。对于连通性、连通分量的维护用并查集实现。

(3) 按照作业分析代码实现出现的性能问题和修复情况

第一次作业

本次作业以社交网络为背景,对于某些暴力开销较大的方法使用相应的图论算法来改善性能。如此次作业中isCircle和queryBlockSum使用路径压缩并查集维护。维护一个连通分量个数blockSum,每次加人时将该变量加一,有效合并并查集时将该变量减一。对于某些查询量可采用提前计算的方式维护一个量并动态维护,如针对年龄平均值的查询可维护一个年龄总数的变量。

第二次作业

本次作业中新增的queryLeastConnection使用Kruskal最小生成树算法实现。对于Group类中queryGroupValueSum的性能问题,可在每次addToGroup,delFromGroup,addRelation操作中维护每个组的总value,从而改善每条指令的最高性能开销。但对于实际应用来说,getValueSum的调用频率可能不及addToGroup,delFromGroup,addRelation这些方法的调用那么频繁,因此以加权平均性能的指标考量,以上解决方案甚至可能是负优化。

第三次作业

本次作业中新增的sendIndirectMessage使用spfa最短路算法实现。其他新增方法仅需按照规格编写即可。

(4) 请针对下页ppt内容对Network进行扩展,并给出相应的JML规格

假设出现了几种不同的Person

Advertiser:持续向外发送产品广告
Producer:产品生产商,通过Advertiser来销售产品
Customer:消费者,会关注广告并选择和自己偏好匹配的产品来购买 -- 所谓购买,就是直接通过Advertiser给相应Producer发一个购买消息
Person:吃瓜群众,不发广告,不买东西,不卖东西

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

Advertiser、Producer、Customer均继承自Person,Advertisement、Product均继承自Message。其中Advertisement的Person1只能为Advertiser,Product中新增price属性,且type只能为0,Person1只能为Advertiser,Person1只能为Customer。新建ProductInfo类用来保存每种产品的相关信息。同时创建抽象模型productInfoList来维护产品的相关信息。

以下分别为发布广告(单发或群发)、购买产品、查询某产品销售额的JML规格

    /*@ public normal_behavior
      @ requires containsMessage(id) && getMessage(id).getType() == 0 &&
	  @          getMessage(id) instanceof Advertisement &&
      @          getMessage(id).getPerson1().isLinked(getMessage(id).getPerson2()) &&
      @          getMessage(id).getPerson1() != getMessage(id).getPerson2();
      @ assignable messages;
      @ assignable getMessage(id).getPerson1().socialValue;
      @ assignable getMessage(id).getPerson2().messages, getMessage(id).getPerson2().socialValue;
      @ ensures !containsMessage(id) && messages.length == \old(messages.length) - 1 &&
      @         (\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != id;
      @         (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
      @ ensures \old(getMessage(id)).getPerson1().getSocialValue() ==
      @         \old(getMessage(id).getPerson1().getSocialValue()) + \old(getMessage(id)).getSocialValue() &&
      @         \old(getMessage(id)).getPerson2().getSocialValue() ==
      @         \old(getMessage(id).getPerson2().getSocialValue()) + \old(getMessage(id)).getSocialValue();
      @ ensures (\forall int i; 0 <= i && i < \old(getMessage(id).getPerson2().getMessages().size());
      @          \old(getMessage(id)).getPerson2().getMessages().get(i+1) == \old(getMessage(id).getPerson2().getMessages().get(i)));
      @ ensures \old(getMessage(id)).getPerson2().getMessages().get(0).equals(\old(getMessage(id)));
      @ ensures \old(getMessage(id)).getPerson2().getMessages().size() == \old(getMessage(id).getPerson2().getMessages().size()) + 1;
      also
      @ public normal_behavior
      @ requires containsMessage(id) && getMessage(id).getType() == 1 &&
	  @           getMessage(id) instanceof Advertisement &&
      @           getMessage(id).getGroup().hasPerson(getMessage(id).getPerson1());
      @ assignable people[*].socialValue, people[*].money, messages;
      @ ensures !containsMessage(id) && messages.length == \old(messages.length) - 1 &&
      @         (\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != id;
      @         (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
      @ ensures (\forall Person p; \old(getMessage(id)).getGroup().hasPerson(p); p.getSocialValue() ==
      @         \old(p.getSocialValue()) + \old(getMessage(id)).getSocialValue());
      @ ensures (\forall int i; 0 <= i && i < people.length && !\old(getMessage(id)).getGroup().hasPerson(people[i]);
      @          \old(people[i].getSocialValue()) == people[i].getSocialValue());
      @ also
      @ public exceptional_behavior
	  @ signals (MessageIdNotFoundException e) !containsMessage(id) ||
	  @      	 (containsMessage(id) && !getMessage(id) instanceof Advertisement);
      @ signals (RelationNotFoundException e) containsMessage(id) && getMessage(id).getType() == 0 &&
      @          !(getMessage(id).getPerson1().isLinked(getMessage(id).getPerson2()));
      @ signals (PersonIdNotFoundException e) containsMessage(id) && getMessage(id).getType() == 1 &&
      @          !(getMessage(id).getGroup().hasPerson(getMessage(id).getPerson1()));
      @*/
    public void sendAdvertisement(int id) throws
            RelationNotFoundException, MessageIdNotFoundException, PersonIdNotFoundException;



    /*@ public normal_behavior
      @ requires containsMessage(id) && getMessage(id).getType() == 0 &&
	  @          getMessage(id) instanceof Product &&
      @          getMessage(id).getPerson1().isLinked(getMessage(id).getPerson2()) &&
      @          getMessage(id).getPerson1() != getMessage(id).getPerson2();
      @ assignable messages, productInfoList;
      @ assignable getMessage(id).getPerson1().socialValue, getMessage(id).getPerson1().money;
      @ assignable getMessage(id).getPerson2().messages, getMessage(id).getPerson2().socialValue, getMessage(id).getPerson2().money;
      @ ensures !containsMessage(id) && messages.length == \old(messages.length) - 1 &&
      @         (\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != id;
      @         (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
      @ ensures \old(getMessage(id)).getPerson1().getSocialValue() ==
      @         \old(getMessage(id).getPerson1().getSocialValue()) + \old(getMessage(id)).getSocialValue() &&
      @         \old(getMessage(id)).getPerson2().getSocialValue() ==
      @         \old(getMessage(id).getPerson2().getSocialValue()) + \old(getMessage(id)).getSocialValue();
      @ ensures (\old(getMessage(id)).getPerson1().getMoney() ==
      @         \old(getMessage(id).getPerson1().getMoney()) + ((Product)\old(getMessage(id))).getMoney() &&
      @         \old(getMessage(id)).getPerson2().getMoney() ==
      @         \old(getMessage(id).getPerson2().getMoney()) - ((Product)\old(getMessage(id))).getMoney());
      @ ensures (\forall int i; 0 <= i && i < \old(getMessage(id).getPerson2().getMessages().size());
      @          \old(getMessage(id)).getPerson2().getMessages().get(i+1) == \old(getMessage(id).getPerson2().getMessages().get(i)));
      @ ensures \old(getMessage(id)).getPerson2().getMessages().get(0).equals(\old(getMessage(id)));
      @ ensures \old(getMessage(id)).getPerson2().getMessages().size() == \old(getMessage(id).getPerson2().getMessages().size()) + 1;
      @ ensures (\exists int i; 0 <= i && i < productInfoList.length && productInfoList[i].getId() == ((Product)\old(getMessage(id))).getProductId();
      @          productInfoList[i].getSaledNum() == \old(productInfoList[i].getSaledNum()) + 1);
      @ also
      @ public exceptional_behavior
	  @ signals (MessageIdNotFoundException e) !containsMessage(id) ||
	  @      	 (containsMessage(id) && !getMessage(id) instanceof Product);
      @ signals (RelationNotFoundException e) containsMessage(id) && getMessage(id).getType() == 0 &&
      @          !(getMessage(id).getPerson1().isLinked(getMessage(id).getPerson2()));
      @*/
    public void buyProduct(int id) throws
            RelationNotFoundException, MessageIdNotFoundException;



    /*@ public normal_behavior
      @ requires (\exists int i; 0 <= i && i < productInfoList.length; productInfoList[i].getId() == id);
      @ ensures (\exists int i; 0 <= i && i < productInfoList.length; productInfoList[i].getId() == id &&
      @          \result == productInfoList[i].getSaledNum());
      @ also
      @ public exceptional_behavior
      @ requires !(\exists int i; 0 <= i && i < productInfoList.length; productInfoList[i].getId() == id);
	  @ signals_only ProductIdNotFoundException;
      @*/
    public int querySaledProductNum(int id) throws ProductIdNotFoundException;

(5) 本单元学习体会

本单元作业最重要的就是要全面地理解JML的操作,并选择合适的容器及算法实现。对于简单易于实现的方法,严格按照JML的描述语言编写代码。对于按JML描述语言不易实现或性能较差的方法,则需在严格遵守JML约束的前提下谨慎选择实现算法。本单元第三次作业就因为Message类的equals方法偷懒用了IDEA自动生成的equals导致Message的id相同的不同子类不能触发EqualMessageIdException,最终未能进入互测(顺便吐槽一波中测难度,太水了)。相对于第二次作业,本单元作业难度明显降低,思考难度几乎没有,也不需要自行架构,仅需要将JML规格翻译成代码,但需要十分细心地编写或大量的测试数据,否则就会因为及其细小的问题惨遭爆零。

posted on   hacker_killer  阅读(31)  评论(0编辑  收藏  举报

(评论功能已被禁用)
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示