OO_第三单元总结

OO_第三单元总结

一、测试

  • 对于性能测试构造了菊花图,完全图等数据测试程序性能
  • 对于正确性。随机生成数据,和同学对拍

二、架构设计

图模型构建和维护策略

  • 对于qbs和qci指令我使用的并查集维护,并进行路径压缩,复杂度为 O(nα(n))
  • 对于qlc指令,我用的Kruskal算法计算最小生成树,并用并查集优化。每次查询时对在一个联通块的点单独建图计算,复杂度为 O(mlogm)
        this.people = people;
        this.edges = new ArrayList<>();
        father = new int[17000];
        indHashMap = new HashMap<>();
        for (int i = 0; i < people.size(); i += 1) {
            father[i] = i;
            indHashMap.put(people.get(i).getId(), i);
        }
        for (Person person: people) {
            ArrayList<Person> acquaintance = ((MyPerson) person).getAcquaintance();
            ArrayList<Integer> value = ((MyPerson) person).getValue();
            for (int i = 0; i < value.toArray().length; i += 1) {
                if (indHashMap.containsKey(acquaintance.get(i).getId()) == false) {
                    continue;
                }
                Edge edge = new Edge();
                edge.setEdge(person.getId(), acquaintance.get(i).getId(), value.get(i));
                edges.add(edge);
            }
        }
        edges.sort(new SortByIndex());
        blockSum = people.size();
    }
  • 对于sim指令,我用堆优化的迪杰斯特拉算法进行计算,复杂度为 O((m+n)logn)
        Comparator<SPathNode> queueComparator = new PersonComparator();
        PriorityQueue<SPathNode> priorityQueue = new PriorityQueue<>(2550, queueComparator);
        HashMap<Integer, Integer> shortestDis = new HashMap<>();
        shortestDis.put(stId, 0);
        SPathNode stNode = new SPathNode(stId, 0);
        priorityQueue.add(stNode);
        int result = -1;
        while (true) {
            if (priorityQueue.isEmpty()) {
                break;
            }
            SPathNode nowNode = priorityQueue.remove();
            if (nowNode.getPersonId() == endId) {
                if (result == -1) {
                    result = nowNode.getDistance();
                }
                else {
                    if (result > nowNode.getDistance()) {
                        result = nowNode.getDistance();
                    }
                }
            }
            if (nowNode.getDistance() > shortestDis.get(nowNode.getPersonId())) {
                continue;
            }
            ArrayList<Integer> value = ((MyPerson) getPerson(nowNode.getPersonId())).getValue();
            ArrayList<Person> acquaintance =
                    ((MyPerson) getPerson(nowNode.getPersonId())).getAcquaintance();
            for (int i = 0; i < acquaintance.size(); i += 1) {
                int toId = acquaintance.get(i).getId();
                int newDis = nowNode.getDistance() + value.get(i);
                if (!shortestDis.containsKey(toId)) {
                    shortestDis.put(toId, newDis);
                    SPathNode addNode = new SPathNode(toId, newDis);
                    priorityQueue.add(addNode);
                }
                else {
                    if (shortestDis.get(toId) > newDis) {
                        shortestDis.replace(toId, newDis);
                        SPathNode addNode = new SPathNode(toId, newDis);
                        priorityQueue.add(addNode);
                    }
                }
            }
        }
        return result;
    }

三、问题与修复

  • 在阅读qgva的规格时把
@ ensures \result == (people.length == 0? 0 : ((\sum int i; 0 <= i && i < people.length; 
@          (people[i].getAge() - getAgeMean()) * (people[i].getAge() - getAgeMean())) / 
@           people.length));

的people.length前的/位置搞错,本应是先求和后除法,写成了先除法后求和

  • 性能上获取network中的人时。一开始我是遍历所有的人,这样复杂度较高为O(n)的,有点点会TLE。而后改成了Hashmap做映射。

四、Network进行扩展

  • Advertiser:持续向外发送产品广告。方法addProductInfoMessage
/*@ public normal_behavior
  @ requires !(\exists int i; 0 <= i && i < messages.length; messages[i].equals(message)));
  @ assignable messages, countOfProducts;
  @ ensures messages.length == \old(messages.length) + 1;
  @ ensures (\forall int i; 0 <= i && i < \old(messages.length);
  @          (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
  @ ensures (\exists int i; 0 <= i && i < messages.length; messages[i].equals(message));
  @ ensures countOfProducts.get(products) == \old(countOfProducts.get(products)) + 1;
  @ also
  @ public exceptional_behavior
  @ signals (EqualMessageIdException e) (\exists int i; 0 <= i && i < messages.length;
  @                                     messages[i].equals(message));
  @*/
public void addProductInfoMessage(Product product);
  • Producer:产品生产商,通过Advertiser来销售产品。方法:sendAdvertisement
/*@ public normal_behavior
  @ requires containsMessage(id) && countOfProducts.get(product) != 0;
  @ assignable messages, countOfProducts, advertise.advertiserProduct;
  @ 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 advertise.advertiserProduct.contains(products)
  @ ensures (\forall int i; 0 <= i && i < \old(advertise.advertiserProduct.size());
                (\exits int j; 0 <= j && j < advertise.advertiserProduct.size();
                old\(advertise.advertiserProduct.get(i)) == advertise.advertiserProduct.get(j)));
  @ also
  @ public exceptional_behavior
  @ signals (MessageIdNotFoundException e) !containsMessage(id);
  @ signals (ProductNotFoundException e) countOfProducts.get(product) == 0;
 */
  public void sendAdvertisement(Product product, Advertiser advertise);
  • Customer:消费者,会关注广告并选择和自己偏好匹配的产品来购买
*@ public normal_behaviour
	  @ requires message instanceof purchaseMessage;
	  @ requires contains(advertiserId) && 
	  @ (getPerson(advertiserId) instanceof Advertiser);
        @ requires !getPerson(advertiserId).containsMessage(message.getId())
	  
  	  @ assignable getPerson(advertiserId).message[];
 	  @ ensuers getPerson(advertiserId).message.length == \old(getPerson(advertiserId).message.length) &&                
        @ getPerson(advertiserId).containsMessage(message.getId());
 	  @ also
        @ public exceptional_behavior
        @ signals (PersonIdNotFoundException e) !contains(advertiserId);
        @ signals (WrongMessageTypeException e) !(message instanceof purchaseMessage);
        @*/
void purchase(int advertiserId, Message message) throws
            PersonIdNotFoundException, WrongMessageTypeException;

五、学习体会

这个单元我体会到了JML规格的严谨性。使用JML可以无二义性地描述自己的需求,并且对程序的实现也较为友好。但编写JML挺麻烦的,需要多加练习。阅读JMl规格时一定要搞清楚()的作用范围。程序的模块化很重要。在对于qlc,sim等命令在开发中需要更低的时间复杂度时,能够模块化封装运算,编写时很方便。

posted @ 2022-06-06 14:36  ordered_bread  阅读(9)  评论(1编辑  收藏  举报