2026年1月19日 星期一

Dynamic Framed Slotted ALOHA (DFSA) 防撞方法

 Dynamic Framed Slotted ALOHA (DFSA)防撞方法


DFSA 的核心邏輯:

  1. 動態框長 (Dynamic Frame Size):閱讀器會根據上一輪的結果(碰撞次數、空閒次數)來動態調整下一輪的時槽數(框長 $L$)。

  2. 效率優化:當標籤很多時,增加時槽以減少碰撞;當標籤變少時,減少時槽以避免浪費時間。

  3. 調整策略

    • 碰撞過多:增加框長(通常是乘以 2)。

    • 空閒過多:減少框長(通常是除以 2)。

    • 理想狀態:時槽數接近待識別標籤數時,系統吞吐量最高(約 36.8%)。

DFSA 模擬器重點:

  1. 動態反饋

    • 在日誌中你可以看到 [調整] 訊息。如果第一輪 12 個標籤擠在 4 個時槽,會發生嚴重碰撞,程式會立刻將下一輪的 L 提升到 8 或 16。

  2. 效率視覺化

    • 紅色時槽:代表碰撞(Collision)。

    • 綠色時槽:代表成功(Success)。

    • 灰色時槽:代表浪費掉的電力與時間(Idle)。

  3. 重新開始

    • 每次 Reset 會隨機生成不同數量的標籤,你可以觀察系統如何根據不同的標籤密度調整其策略。






import tkinter as tk
from tkinter import messagebox
import random

class DFSASimulator:
    def __init__(self, root):
        self.root = root
        self.root.title("Dynamic Slotted ALOHA (DFSA) 模擬器")
        self.root.geometry("700x750")

        # 初始參數
        self.tags = []           # 待識別標籤
        self.identified = []     # 已識別標籤
        self.frame_size = 4      # 初始框長 (動態調整)
        self.round_count = 0
        
        self.setup_ui()
        self.reset_sim()

    def setup_ui(self):
        tk.Label(self.root, text="Dynamic Framed Slotted ALOHA (DFSA)", font=("Arial", 16, "bold")).pack(pady=10)
        
        # 資訊看板
        self.info_frame = tk.Frame(self.root, relief=tk.SUNKEN, bd=1)
        self.info_frame.pack(pady=5, padx=20, fill=tk.X)
        
        self.tag_label = tk.Label(self.info_frame, text="", font=("Consolas", 11), fg="blue")
        self.tag_label.pack(pady=5)

        self.stat_label = tk.Label(self.root, text="", font=("Arial", 10, "bold"))
        self.stat_label.pack()

        # 時槽視覺化
        self.canvas = tk.Canvas(self.root, width=600, height=120, bg="white", highlightthickness=1)
        self.canvas.pack(pady=10)

        # 日誌顯示
        self.log_box = tk.Listbox(self.root, width=85, height=18, font=("Consolas", 9))
        self.log_box.pack(pady=10)

        # 控制鈕
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=10)
        
        self.btn_next = tk.Button(btn_frame, text="執行下一輪 (Step)", width=15, bg="#e1f5fe", command=self.run_round)
        self.btn_next.pack(side=tk.LEFT, padx=10)
        
        tk.Button(btn_frame, text="重新開始 (Reset)", width=15, command=self.reset_sim).pack(side=tk.LEFT, padx=10)

    def reset_sim(self):
        # 隨機產生 8 到 12 個 3-bit 標籤 (測試動態調整效果)
        all_ids = [format(i, '03b') for i in range(8)]
        self.tags = [random.choice(all_ids) for _ in range(random.randint(8, 12))]
        
        self.identified = []
        self.frame_size = 4 # 回到初始框長
        self.round_count = 0
        
        self.log_box.delete(0, tk.END)
        self.log_box.insert(tk.END, "--- 系統重置:DFSA 準備開始 ---")
        self.log_box.insert(tk.END, f"初始標籤數: {len(self.tags)}, 初始框長: {self.frame_size}")
        self.update_ui()
        self.btn_next.config(state=tk.NORMAL)

    def update_ui(self, slot_data=None):
        self.tag_label.config(text=f"剩餘標籤: {self.tags}")
        self.stat_label.config(text=f"輪數: {self.round_count} | 當前框長 (L): {self.frame_size} | 已識別: {len(self.identified)}")
        self.draw_slots(slot_data)

    def draw_slots(self, slot_data):
        self.canvas.delete("all")
        if not slot_data: return
        
        n = len(slot_data)
        w = 600 / n
        for i, occupants in enumerate(slot_data):
            count = len(occupants)
            color = "white"
            txt = f"S{i}"
            
            if count == 0: color = "#f5f5f5"; txt = "Idle"
            elif count == 1: color = "#c8e6c9"; txt = f"OK\n{occupants[0]}"
            else: color = "#ffcdd2"; txt = f"COLL\n({count})"
            
            self.canvas.create_rectangle(i*w, 0, (i+1)*w, 120, fill=color, outline="gray")
            self.canvas.create_text(i*w + w/2, 60, text=txt, justify=tk.CENTER, font=("Arial", 8))

    def run_round(self):
        if not self.tags:
            messagebox.showinfo("完成", "所有標籤識別完畢!")
            self.btn_next.config(state=tk.DISABLED)
            return

        self.round_count += 1
        slots = [[] for _ in range(self.frame_size)]
        
        # 標籤隨機選擇時槽
        for tag in self.tags:
            idx = random.randint(0, self.frame_size - 1)
            slots[idx].append(tag)

        # 統計結果
        success_tags = []
        collision_count = 0
        idle_count = 0
        
        self.log_box.insert(tk.END, f">> Round {self.round_count} (L={self.frame_size})")
        
        for i, occ in enumerate(slots):
            if len(occ) == 1:
                success_tags.append(occ[0])
            elif len(occ) > 1:
                collision_count += 1
            else:
                idle_count += 1

        # 更新列表
        for t in success_tags:
            if t in self.tags: self.tags.remove(t)
            self.identified.append(t)

        self.log_box.insert(tk.END, f"   結果: 成功={len(success_tags)}, 碰撞={collision_count}, 空閒={idle_count}")

        # --- 動態調整框長邏輯 ---
        old_size = self.frame_size
        if collision_count > (self.frame_size * 0.3): # 碰撞太多,擴張
            self.frame_size = min(32, self.frame_size * 2)
            self.log_box.insert(tk.END, f"   [調整] 碰撞過多 -> 框長增加至 {self.frame_size}", "red")
        elif idle_count > (self.frame_size * 0.6) and self.frame_size > 4: # 空閒過多,縮小
            self.frame_size = max(4, self.frame_size // 2)
            self.log_box.insert(tk.END, f"   [調整] 空閒過多 -> 框長縮小至 {self.frame_size}", "blue")

        self.update_ui(slots)
        self.log_box.see(tk.END)

if __name__ == "__main__":
    root = tk.Tk()
    app = DFSASimulator(root)
    root.mainloop()

沒有留言:

張貼留言

Dynamic Framed Slotted ALOHA (DFSA) 防撞方法

 Dynamic Framed Slotted ALOHA (DFSA)防撞方法 DFSA 的核心邏輯: 動態框長 (Dynamic Frame Size) :閱讀器會根據上一輪的結果(碰撞次數、空閒次數)來 動態調整 下一輪的時槽數(框長 $L$ )。 效率優化 :當標籤很多時...