python拜占庭将军

功能:

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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值