# 架构设计

### 算法技巧

1.并查集

qci指令要求我们频繁查询图中两个点的连通性，而并查集天生就是为了这种要求而存在的，只需要在ap中为并查集添加节点、ar中维护并查集连通性，即可实现qci的O(1)查询

ap 1 1 200
ap 2 2 200
ap 3 3 200
ap 4 4 200
.....
ap 5000 5000 200
ar 1 2 1000
ar 2 3 1000
ar 3 4 1000
ar 4 5 1000
ar 5 6 1000
ar 6 7 1000
ar 7 8 1000
......
ar 4999 5000 1000
qci 1 5000

2.堆优化的prim算法(最小生成树)

3.堆优化的迪杰斯特拉算法(最短路)

### 容器选择

1.NetWork

private HashMap<Integer, Person> people;
private HashMap<Integer, Group> groups;
private HashMap<Integer, Message> messages;
private HashMap<Integer, Integer> emojiIdMap;
private DisjointSet disjointSet;

2.Group

private HashMap<Integer, Person> people;

3.Person

private HashMap<Integer, Person> acquaintance;
private HashMap<Integer, Integer> values;

4.Message

5.Exception

private static HashMap<Integer, Integer> messageExceptionCounter = new HashMap<>();
private static int totalExceptionCounter = 0;

messageExceptionCounter存储id与异常次数映射

totalExceptionCounter存储异常总次数

# 基于JML规格的数据生成及自动化测试

​ 我在本单元如前两个单元一样搭建了评测机，对自己的程序进行正确性检验（之所以叫正确性检验，是因为一些极限数据是很难由评测机自动生成的，只能通过手工构造）。本单元的评测机搭建比较像第一单元，主要分为数据生成和自动化测试，其中难点在数据生成(与第一单元一样)，自动化测试只需要和小伙伴对拍即可，无需像第二单元一样搭建起一套完整的评测逻辑。

## 数据生成

father = {} #维护并查集
noPersonIdList = [i for i in range(-4000, 4000)] #选取Person的ID
personIdList = []
noGroupIdList = [i for i in range(-1500, 1500)] #选取组的ID
groupIdList = []
messageIdList = []
noMessageIdList = [i for i in range(-2000, 2000)] #选取消息ID
emojiIdList = []
noEmojiIdList = [i for i in range(10001)] #选取表情ID

queryValueExp = 0.3
isCircleExp = 0.3
queryGroupPeopleSumExp = 0.3
queryGroupValueSumExp = 0.3
queryGroupAgeVarExp = 0.3
messageTypeZero = 0.5
messageTypeOne = 0.1
sendMessageExp = 0.3
querySocialValueExp = 0.3
queryLeastConnectionExp = 0.3
cleanNoticesExp = 0.3
storeEmojiIdExp = 0.3
queryPopularityExp = 0.3
queryMoneyExp = 0.3

p = random.random()
p1 = random.random()
if p1 > 0.5:
if not messageIdList:
messageId = random.choice(messageIdList)
if personIdList:
id1 = random.choice(personIdList)
else:
id1 = random.choice(noPersonIdList)
id2 = id1
else:
if not noMessageIdList:
return sendMessage()
messageId = random.choice(noMessageIdList)
noMessageIdList.remove(messageId)
messageIdList.append(messageId)
if personIdList:
id1 = random.choice(personIdList)
else:
id1 = random.choice(noPersonIdList)
id2 = id1
messageType = random.randint(0, 1)
socialValue = random.randint(-1000, 1000)
else:
p2 = random.random()
if p2 > messageTypeZero:
messageType = 0
messageId = random.choice(noMessageIdList)
noMessageIdList.remove(messageId)
messageIdList.append(messageId)
if len(personIdList) < 3:
p3 = random.random()
if p3 > sendMessageExp:
else:
id1 = random.choice(personIdList)
if id1 in linkedPersonGroup: #Disjoint Union
while find(id2) != find(id1):
else:
id2 = random.choice(personIdList)
while id2 == id1:
id2 = random.choice(personIdList)
else:
messageType = 1
if not noMessageIdList:
return sendMessage()
messageId = random.choice(noMessageIdList)
noMessageIdList.remove(messageId)
messageIdList.append(messageId)
if len(groupIdList) < 1:
if not personIdList:
if random.random() > sendMessageExp:
else:
id2 = random.choice(groupIdList)
id1 = random.choice(personIdList)
socialValue = random.randint(-1000, 1000)
if returnType == 0:
return "am {} {} {} {} {}".format(messageId, socialValue, messageType, id1, id2)
else:
return [messageId, messageType, id1, id2]

functionNum = 24

def generDataSpecial():
global functionList
funcList = random.sample(functionList, functionNum)
s = useFuncToGengerData(funcList)
return s

def useFuncToGengerData(functions: list):
s = ''
for i in range(20000):
s += random.choice(functions)()
s += '\n'
return s

p = random.random()
if 0.95 < p:
elif 0.90 < p <= 0.95:
elif 0.80 < p <= 0.85:
elif 0.75 < p <= 0.80:
context = queryValue()
elif 0.70 < p <= 0.75:
elif 0.65 < p <= 0.70:
context = delFromGroup()
elif 0.60 < p <= 0.65:
context = queryCircle()
elif 0.55 < p <= 0.60:
context = queryBlockSum()
elif 0.50 < p <= 0.55:
context = queryPeopleSum()
elif 0.45 < p <= 0.5:
context = queryGroupValueSum()
elif 0.4 < p <= 0.45:
context = queryGroupAgeVar()
elif 0.35 < p <= 0.4:
elif 0.3 < p <= 0.35:
context = sendMessage()
elif 0.25 < p <= 0.3:
context = querySocialValue()
elif 0.2 < p <= 0.25:
elif 0.15 < p <= 0.20:
context = queryLeastConnection()
elif 0.1 < p <= 0.15:
elif 0.05 < p <= 0.1:
context = sendMessage()
else:
context = queryLeastConnection()
else:
p = random.random()
if 0.65 < p:
elif 0.35 < p:
context = sendMessage()
else:

## 自动化评测

for jar in jarList:
cmd = "java -jar {}".format(jar + '.jar')
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
encoding='utf-8')
stdout, stderr = proc.communicate(stdinData)

# 自己与他人的bug分析

## 分析自己的bug

/*@ ensures \result == (\sum int i; 0 <= i && i < people.length;
@          (\sum int j; 0 <= j && j < people.length &&
@*/

## 他人的bug

### 有趣的bug(JAVA里printf和pringln的区别)

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
//import java.io.*;
public class 快速输入输出 {

public static void main(String[] args) throws IOException {
// TODO 自动生成的方法存根
//想输入一个数（数组长度）
int b=Integer.valueOf(c);
//想输入一个数组
String a[]=aString.split(" ");
int v[]=new int[b];
for (int i = 0; i < a.length; i++) {
v[i]=Integer.valueOf(a[i]);
}
//为了获得最高效率，可考虑将 OutputStreamWriter 包装到 BufferedWriter 中，以避免频繁调用转换器。
//Writer writer=new OutputStreamWriter(System.out);
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(System.out));
for (int i = 0; i < a.length; i++) {
writer.write(a[i]);
}
writer.write("\r");//
writer.write("hello");
writer.flush();//释放资源
}

}

# Network扩展

## 概述

public void sendPurchaseMessage(Message message) throws MessageIdNotFoundException; //发送购买消息

## JML规格

/*@ public normal_behavior
@ requires containsMessage(id) && getMessage(id).getType() == 2 &&
@ assignable 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 int i; 0 <= i && i < \old(getMessage(id).getPerson1().acquaintance[i]);
@          \old(getMessage(id).getPerson1().acquaintance[i].getMessages().get(i+1) == \old(getMessage(id).getPerson1().acquaintance[i].getMessages().get(i)));
@ ensures \old(getMessage(id).getPerson1().acquaintance[i].getMessages().get(0).equals(\old(getMessage(id)));
@ ensures \old(getMessage(id)).getPerson1().acquaintance[i].getMessages().size() == \old(getMessage(id).getPerson1().acquaintance[i].getMessages().size()) + 1;
@ also
@ public exceptional_behavior
@ signals (MessageIdNotFoundException e) !containsMessage(id);
@ signals (noAdvertiserException e) containsMessage(id) && getMessage(id).getType() == 2 &&
@*/

/*@ public normal_behavior
@ requires !(\exists int i; 0 <= i && i < messages.length; messages[i].equals(message)) &&
@ message.getType() == 2 && (message.getPerson1() instanceof Advertiser);
@ assignable messages;
@ 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));
@ also
@ public exceptional_behavior
@ signals (EqualMessageIdException e) (\exists int i; 0 <= i && i < messages.length;
@                                     messages[i].equals(message));
@ signals (noAdvertiserException e) !(\exists int i; 0 <= i && i < messages.length;
@                                     messages[i].equals(message)) && !(messages[i].getPerson1() 			  @										instanceof Advertiser);
@*/

/*@ public normal_behavior
@ requires !(\exists int i; 0 <= i && i < messages.length; messages[i].equals(message)) &&
@ message.getType() == 3 && (message.getPerson1() instanceof Advertiser) && (message.getPerson2() 		  @ instanceof Customer) && (message.getPerson3() instanceof Producer);
@ assignable messages;
@ 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));
@ also
@ public exceptional_behavior
@ signals (EqualMessageIdException e) (\exists int i; 0 <= i && i < messages.length;
@                                     messages[i].equals(message));
@ signals (noAdvertiserException e) !(\exists int i; 0 <= i && i < messages.length;
@                                     messages[i].equals(message)) && !(messages[i].getPerson1() 			  @										instanceof Advertiser);
@ signals (noCustomerException e) !(\exists int i; 0 <= i && i < messages.length;
@                                     messages[i].equals(message)) && !(messages[i].getPerson1() 			  @										instanceof noCustomerException);
@ signals (noProducerException e) !(\exists int i; 0 <= i && i < messages.length;
@                                     messages[i].equals(message)) && !(messages[i].getPerson() 			  @										instanceof noProducerException);
@*/

# 心得体会

posted @ 2022-05-31 09:21  繁华丶人间  阅读(277)  评论(2编辑  收藏  举报