功能:
1.定义了一个General类,用于表示每个将军的状态和行为。
2.实现了一个拜占庭容错算法的模拟过程,处理多轮消息交换和决策。
3.初始化指挥官发送命令,并根据叛徒情况调整消息内容。
4.每轮决策采用多数决原则。
5.测试框架验证算法正确性,包括一致性和遵循指挥官命令的条件。
6.处理合法和非法测试用例,进行压力测试。
step1:C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\hello.py
import random
class General:
def __init__(self, id, is_traitor=False):
self.id = id
self.is_traitor = is_traitor
self.received_orders = {} # 按轮次存储收到的命令 {round: {sender_id: order}}
self.decisions = {} # 按轮次存储的决策 {round: decision}
def receive_order(self, sender_id, order, round):
"""接收来自sender_id的命令,记录到对应的轮次"""
if round not in self.received_orders:
self.received_orders[round] = {}
self.received_orders[round][sender_id] = order
def byzantine_simulation(num_generals, traitor_ids, commander_order):
t = len(traitor_ids)
required_rounds = t + 1 # 根据拜占庭容错算法确定所需轮次
# 初始化将军们
generals = {gid: General(gid, gid in traitor_ids) for gid in range(num_generals)}
# 初始轮次(轮次0):指挥官发送命令
commander = generals[0]
for receiver_id in generals:
if receiver_id == 0:
continue
# 叛徒指挥官发送随机命令,否则发送真实命令
order = random.choice([True, False]) if commander.is_traitor else commander_order
generals[receiver_id].receive_order(0, order, 0)
# 计算初始轮次的决策
for general in generals.values():
if general.id == 0:
continue
orders = general.received_orders.get(0, {})
true_count = sum(orders.values())
general.decisions[0] = true_count > len(orders) / 2
# 进行多轮消息交换
for current_round in range(1, required_rounds):
# 收集当前轮次的消息
for sender_id in generals:
sender = generals[sender_id]
if sender.id == 0:
continue # 指挥官只在第一轮发送
for receiver_id in generals:
if receiver_id in [0, sender_id]:
continue
# 确定发送的消息内容
if sender.is_traitor:
order = random.choice([True, False]) # 叛徒发送随机消息
else:
# 忠诚将军发送上一轮的决策
prev_round = current_round - 1
order = sender.decisions.get(prev_round, False)
generals[receiver_id].receive_order(sender_id, order, current_round)
# 计算当前轮次的决策
for general in generals.values():
if general.id == 0:
continue
orders = general.received_orders.get(current_round, {})
true_count = sum(orders.values())
general.decisions[current_round] = true_count > len(orders) / 2
# 生成最终决策结果
decisions = {}
for gid in generals:
if gid == 0:
continue
final_decision = generals[gid].decisions.get(required_rounds - 1, False)
decisions[gid] = final_decision
return decisions
def run_comprehensive_tests():
test_cases = [
(4, [3], True),
(4, [3], False),
(7, [2, 4], True),
(7, [1, 5], False),
(10, [3, 6, 9], True)
]
for case in test_cases:
num_generals, traitor_ids, commander_order = case
t = len(traitor_ids)
# 拜占庭容错基本条件检查
if num_generals < 3 * t + 1:
print(f"跳过不合法测试:将军数{num_generals} < 3*{t}+1")
continue
print(
f"\n测试案例:将军数={num_generals}, 叛徒={traitor_ids}, 指挥官命令={'进攻' if commander_order else '撤退'}")
result = byzantine_simulation(
num_generals=num_generals,
traitor_ids=traitor_ids,
commander_order=commander_order
)
# 展示结果
print("将军决策:")
for gid in sorted(result.keys()):
status = "叛徒" if gid in traitor_ids else "忠诚"
action = "进攻" if result[gid] else "撤退"
print(f"将军 {gid:2} ({status}): {action}")
# 验证一致性
loyal_generals = [gid for gid in result if gid not in traitor_ids]
loyal_decisions = [result[gid] for gid in loyal_generals]
if len(loyal_decisions) == 0:
print("无忠诚将军")
continue
consistent = all(d == loyal_decisions[0] for d in loyal_decisions)
print("所有忠诚将军达成一致:" + ("成功" if consistent else "失败"))
# 如果指挥官忠诚,检查是否遵循命令
commander = 0
if commander not in traitor_ids:
expected_decision = commander_order
actual_decisions = set(loyal_decisions)
assert len(actual_decisions) == 1, "忠诚将军意见不一致"
assert actual_decisions.pop() == expected_decision, "忠诚将军未遵循指挥官命令"
if __name__ == "__main__":
# 运行多组测试案例
run_comprehensive_tests()
# 随机压力测试
print("\n正在进行随机压力测试...")
for _ in range(100):
t = random.randint(1, 3)
n = 3 * t + 1 + random.randint(0, 2)
traitor_ids = random.sample(range(1, n), t)
commander_order = random.choice([True, False])
print(f"测试案例:n={n} t={t} 叛徒={traitor_ids} 命令={'进攻' if commander_order else '撤退'}")
try:
result = byzantine_simulation(n, traitor_ids, commander_order)
loyal_generals = [gid for gid in result if gid not in traitor_ids]
loyal_decisions = [result[gid] for gid in loyal_generals]
if loyal_generals:
consistent = all(d == loyal_decisions[0] for d in loyal_decisions)
assert consistent, "忠诚将军未达成一致"
if 0 not in traitor_ids:
assert all(d == commander_order for d in loyal_decisions), "未遵循忠诚指挥官命令"
except AssertionError as e:
print(f"测试失败:{e}")
print("详细结果:")
for gid in sorted(result.keys()):
status = "叛徒" if gid in traitor_ids else "忠诚"
action = "进攻" if result[gid] else "撤退"
print(f"将军 {gid:2} ({status}): {action}")
exit(1)
print("所有压力测试通过!")
step2:运行结果:
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python hello.py
测试案例:将军数=4, 叛徒=[3], 指挥官命令=进攻
将军决策:
将军 1 (忠诚): 进攻
将军 2 (忠诚): 进攻
将军 3 (叛徒): 进攻
所有忠诚将军达成一致:成功
测试案例:将军数=4, 叛徒=[3], 指挥官命令=撤退
将军决策:
将军 1 (忠诚): 撤退
将军 2 (忠诚): 撤退
将军 3 (叛徒): 撤退
所有忠诚将军达成一致:成功
测试案例:将军数=7, 叛徒=[2, 4], 指挥官命令=进攻
将军决策:
将军 1 (忠诚): 进攻
将军 2 (叛徒): 进攻
将军 3 (忠诚): 进攻
将军 4 (叛徒): 进攻
将军 5 (忠诚): 进攻
将军 6 (忠诚): 进攻
所有忠诚将军达成一致:成功
测试案例:将军数=7, 叛徒=[1, 5], 指挥官命令=撤退
将军决策:
将军 1 (叛徒): 撤退
将军 2 (忠诚): 撤退
将军 3 (忠诚): 撤退
将军 4 (忠诚): 撤退
将军 5 (叛徒): 撤退
将军 6 (忠诚): 撤退
所有忠诚将军达成一致:成功
测试案例:将军数=10, 叛徒=[3, 6, 9], 指挥官命令=进攻
将军决策:
将军 1 (忠诚): 进攻
将军 2 (忠诚): 进攻
将军 3 (叛徒): 进攻
将军 4 (忠诚): 进攻
将军 5 (忠诚): 进攻
将军 6 (叛徒): 进攻
将军 7 (忠诚): 进攻
将军 8 (忠诚): 进攻
将军 9 (叛徒): 进攻
所有忠诚将军达成一致:成功
正在进行随机压力测试...
测试案例:n=6 t=1 叛徒=[3] 命令=进攻
测试案例:n=6 t=1 叛徒=[4] 命令=撤退
测试案例:n=12 t=3 叛徒=[7, 11, 2] 命令=撤退
测试案例:n=8 t=2 叛徒=[3, 2] 命令=进攻
测试案例:n=10 t=3 叛徒=[6, 9, 1] 命令=进攻
测试案例:n=10 t=3 叛徒=[8, 5, 7] 命令=进攻
测试案例:n=6 t=1 叛徒=[5] 命令=进攻
测试案例:n=6 t=1 叛徒=[4] 命令=进攻
测试案例:n=6 t=1 叛徒=[2] 命令=进攻
测试案例:n=5 t=1 叛徒=[4] 命令=撤退
测试案例:n=9 t=2 叛徒=[2, 5] 命令=撤退
测试案例:n=5 t=1 叛徒=[2] 命令=撤退
测试案例:n=9 t=2 叛徒=[5, 2] 命令=撤退
测试案例:n=9 t=2 叛徒=[7, 2] 命令=进攻
测试案例:n=9 t=2 叛徒=[2, 6] 命令=进攻
测试案例:n=5 t=1 叛徒=[2] 命令=进攻
测试案例:n=7 t=2 叛徒=[4, 5] 命令=撤退
测试案例:n=6 t=1 叛徒=[2] 命令=进攻
测试案例:n=4 t=1 叛徒=[2] 命令=进攻
测试案例:n=5 t=1 叛徒=[4] 命令=进攻
测试案例:n=7 t=2 叛徒=[3, 2] 命令=撤退
测试案例:n=6 t=1 叛徒=[1] 命令=撤退
测试案例:n=7 t=2 叛徒=[2, 5] 命令=进攻
测试案例:n=11 t=3 叛徒=[3, 4, 1] 命令=进攻
测试案例:n=10 t=3 叛徒=[1, 2, 4] 命令=进攻
测试案例:n=5 t=1 叛徒=[1] 命令=进攻
测试案例:n=4 t=1 叛徒=[1] 命令=进攻
测试案例:n=8 t=2 叛徒=[5, 2] 命令=撤退
测试案例:n=9 t=2 叛徒=[3, 4] 命令=撤退
测试案例:n=5 t=1 叛徒=[3] 命令=撤退
测试案例:n=6 t=1 叛徒=[4] 命令=撤退
测试案例:n=5 t=1 叛徒=[1] 命令=进攻
测试案例:n=8 t=2 叛徒=[3, 7] 命令=进攻
测试案例:n=10 t=3 叛徒=[9, 6, 8] 命令=进攻
测试案例:n=7 t=2 叛徒=[3, 6] 命令=撤退
测试案例:n=6 t=1 叛徒=[1] 命令=撤退
测试案例:n=10 t=3 叛徒=[2, 9, 5] 命令=撤退
测试案例:n=4 t=1 叛徒=[3] 命令=进攻
测试失败:忠诚将军未达成一致
详细结果:
将军 1 (忠诚): 撤退
将军 2 (忠诚): 进攻
将军 3 (叛徒): 进攻
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1>