Dynamic Framed Slotted ALOHA (DFSA)防撞方法
DFSA 的核心邏輯:
動態框長 (Dynamic Frame Size):閱讀器會根據上一輪的結果(碰撞次數、空閒次數)來動態調整下一輪的時槽數(框長 $L$)。
效率優化:當標籤很多時,增加時槽以減少碰撞;當標籤變少時,減少時槽以避免浪費時間。
調整策略:
碰撞過多:增加框長(通常是乘以 2)。
空閒過多:減少框長(通常是除以 2)。
理想狀態:時槽數接近待識別標籤數時,系統吞吐量最高(約 36.8%)。
DFSA 模擬器重點:
動態反饋:
在日誌中你可以看到
[調整]訊息。如果第一輪 12 個標籤擠在 4 個時槽,會發生嚴重碰撞,程式會立刻將下一輪的L提升到 8 或 16。
效率視覺化:
紅色時槽:代表碰撞(Collision)。
綠色時槽:代表成功(Success)。
灰色時槽:代表浪費掉的電力與時間(Idle)。
重新開始:
每次 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()

沒有留言:
張貼留言