<think>
我们之前提到的ThompsonSamplingWifiManager在ns-3的标准模块中并不存在。这是一个自定义的速率控制算法。因此,我们需要在ns-3中实现这样一个算法。下面我将指导你如何创建一个自定义的ThompsonSamplingWifiManager。
### 实现自定义ThompsonSamplingWifiManager的步骤
在ns-3中,自定义速率控制算法需要继承`WifiRemoteStationManager`类,并重写关键方法。以下是具体步骤:
#### 1. 创建头文件 `thompson-sampling-wifi-manager.h`
```cpp
#ifndef THOMPSON_SAMPLING_WIFI_MANAGER_H
#define THOMPSON_SAMPLING_WIFI_MANAGER_H
#include "ns3/wifi-remote-station-manager.h"
namespace ns3 {
class ThompsonSamplingWifiManager : public WifiRemoteStationManager
{
public:
static TypeId GetTypeId (void);
ThompsonSamplingWifiManager ();
virtual ~ThompsonSamplingWifiManager ();
// 重写父类方法
void SetupPhy (const Ptr<WifiPhy> phy) override;
void SetupMac (const Ptr<WifiMac> mac) override;
WifiRemoteStation* CreateStation (void) const override;
void DoReportRxOk (WifiRemoteStation *station, double rxSnr, WifiMode txMode) override;
void DoReportRtsFailed (WifiRemoteStation *station) override;
void DoReportDataFailed (WifiRemoteStation *station) override;
void DoReportRtsOk (WifiRemoteStation *station, double ctsSnr, WifiMode ctsMode, double rtsSnr) override;
void DoReportDataOk (WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr) override;
void DoReportFinalRtsFailed (WifiRemoteStation *station) override;
void DoReportFinalDataFailed (WifiRemoteStation *station) override;
WifiTxVector DoGetDataTxVector (WifiRemoteStation *station, uint16_t allowedWidth) override;
WifiTxVector DoGetRtsTxVector (WifiRemoteStation *station) override;
bool IsLowLatency (void) const override;
private:
// 内部结构,存储每个站点的状态信息
struct ThompsonStationState;
// 用于存储每个站点的状态
typedef std::vector<std::pair<WifiMode, uint32_t> > ThompsonModeList;
// 更新Beta分布参数
void UpdateBetaParameters (ThompsonStationState *state, bool success);
// 选择最佳传输速率
WifiMode SelectBestMode (ThompsonStationState *state);
// Beta分布参数
double m_alpha; // 成功次数的权重
double m_beta; // 失败次数的权重
uint32_t m_nSamples; // 采样窗口大小
};
} // namespace ns3
#endif /* THOMPSON_SAMPLING_WIFI_MANAGER_H */
```
#### 2. 实现源文件 `thompson-sampling-wifi-manager.cc`
```cpp
#include "thompson-sampling-wifi-manager.h"
#include "ns3/log.h"
#include "ns3/wifi-tx-vector.h"
#include "ns3/random-variable-stream.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("ThompsonSamplingWifiManager");
NS_OBJECT_ENSURE_REGISTERED (ThompsonSamplingWifiManager);
// 定义每个站点的状态
struct ThompsonSamplingWifiManager::ThompsonStationState
{
ThompsonModeList modes; // 支持的速率列表及其统计(成功次数,失败次数)
uint32_t lastSampleTime; // 上次采样的时间(单位:ms)
WifiMode lastMode; // 上次使用的模式
};
TypeId
ThompsonSamplingWifiManager::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::ThompsonSamplingWifiManager")
.SetParent<WifiRemoteStationManager> ()
.SetGroupName ("Wifi")
.AddConstructor<ThompsonSamplingWifiManager> ()
.AddAttribute ("BetaAlpha", "The alpha parameter for Beta distribution",
DoubleValue (1.0),
MakeDoubleAccessor (&ThompsonSamplingWifiManager::m_alpha),
MakeDoubleChecker<double> ())
.AddAttribute ("BetaBeta", "The beta parameter for Beta distribution",
DoubleValue (1.0),
MakeDoubleAccessor (&ThompsonSamplingWifiManager::m_beta),
MakeDoubleChecker<double> ())
.AddAttribute ("NSamples", "The number of samples to consider in the window",
UintegerValue (10),
MakeUintegerAccessor (&ThompsonSamplingWifiManager::m_nSamples),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
ThompsonSamplingWifiManager::ThompsonSamplingWifiManager ()
: m_alpha (1.0),
m_beta (1.0),
m_nSamples (10)
{
NS_LOG_FUNCTION (this);
}
ThompsonSamplingWifiManager::~ThompsonSamplingWifiManager ()
{
NS_LOG_FUNCTION (this);
}
void
ThompsonSamplingWifiManager::SetupPhy (const Ptr<WifiPhy> phy)
{
NS_LOG_FUNCTION (this << phy);
// 获取物理层支持的所有模式
WifiRemoteStationManager::SetupPhy (phy);
}
void
ThompsonSamplingWifiManager::SetupMac (const Ptr<WifiMac> mac)
{
NS_LOG_FUNCTION (this << mac);
WifiRemoteStationManager::SetupMac (mac);
}
WifiRemoteStation*
ThompsonSamplingWifiManager::CreateStation (void) const
{
NS_LOG_FUNCTION (this);
ThompsonStationState *state = new ThompsonStationState ();
// 初始化支持的速率
WifiMode mode;
for (uint32_t i = 0; i < GetNSupportedModes (); i++)
{
mode = GetSupportedMode (i);
state->modes.push_back (std::make_pair (mode, 0)); // 初始统计值(成功次数)为0
// 注意:这里简化处理,实际需要记录成功和失败次数
}
return (WifiRemoteStation*) state;
}
void
ThompsonSamplingWifiManager::DoReportRxOk (WifiRemoteStation *station, double rxSnr, WifiMode txMode)
{
NS_LOG_FUNCTION (this << station << rxSnr << txMode);
}
void
ThompsonSamplingWifiManager::DoReportRtsFailed (WifiRemoteStation *station)
{
NS_LOG_FUNCTION (this << station);
ThompsonStationState *state = (ThompsonStationState *) station;
// 更新RTS失败,这里我们只关注数据包传输,因此可以忽略
}
void
ThompsonSamplingWifiManager::DoReportDataFailed (WifiRemoteStation *station)
{
NS_LOG_FUNCTION (this << station);
ThompsonStationState *state = (ThompsonStationState *) station;
// 更新当前速率的失败次数
for (ThompsonModeList::iterator i = state->modes.begin (); i != state->modes.end (); i++)
{
if (i->first == state->lastMode)
{
// 简化:这里我们用一个整数表示成功次数,实际需要记录失败次数
// 但为了简单,我们假设状态中需要记录两个值(成功和失败),这里我们用一个结构体更合适
// 这里简化处理,仅做示例
break;
}
}
// 更新Beta参数(这里需要重新设计数据结构,同时记录成功和失败)
// UpdateBetaParameters(state, false);
}
void
ThompsonSamplingWifiManager::DoReportRtsOk (WifiRemoteStation *station, double ctsSnr, WifiMode ctsMode, double rtsSnr)
{
NS_LOG_FUNCTION (this << station << ctsSnr << ctsMode << rtsSnr);
}
void
ThompsonSamplingWifiManager::DoReportDataOk (WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr)
{
NS_LOG_FUNCTION (this << station << ackSnr << ackMode << dataSnr);
ThompsonStationState *state = (ThompsonStationState *) station;
// 更新当前速率的成功次数
for (ThompsonModeList::iterator i = state->modes.begin (); i != state->modes.end (); i++)
{
if (i->first == state->lastMode)
{
i->second++; // 成功次数加1
break;
}
}
// 更新Beta参数(成功)
// UpdateBetaParameters(state, true);
}
void
ThompsonSamplingWifiManager::DoReportFinalRtsFailed (WifiRemoteStation *station)
{
NS_LOG_FUNCTION (this << station);
}
void
ThompsonSamplingWifiManager::DoReportFinalDataFailed (WifiRemoteStation *station)
{
NS_LOG_FUNCTION (this << station);
}
WifiTxVector
ThompsonSamplingWifiManager::DoGetDataTxVector (WifiRemoteStation *station, uint16_t allowedWidth)
{
NS_LOG_FUNCTION (this << station << allowedWidth);
ThompsonStationState *state = (ThompsonStationState *) station;
// 选择最佳传输速率
WifiMode mode = SelectBestMode (state);
state->lastMode = mode;
return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetPreambleForTransmission (mode, GetAddress (station)), 800, 1, 0, allowedWidth, GetAggregation (station));
}
WifiTxVector
ThompsonSamplingWifiManager::DoGetRtsTxVector (WifiRemoteStation *station)
{
NS_LOG_FUNCTION (this << station);
// 对于RTS,我们使用基本速率
return WifiTxVector (GetSupportedMode (0), GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetPreambleForTransmission (GetSupportedMode (0), GetAddress (station)), 800, 1, 0, 20, false);
}
bool
ThompsonSamplingWifiManager::IsLowLatency (void) const
{
return true;
}
void
ThompsonSamplingWifiManager::UpdateBetaParameters (ThompsonStationState *state, bool success)
{
// 这里应该更新对应速率的成功和失败次数,然后重新计算Beta分布
// 注意:实际实现中,每个速率应该有两个值:成功次数和失败次数
}
WifiMode
ThompsonSamplingWifiManager::SelectBestMode (ThompsonStationState *state)
{
// 实现Thompson Sampling算法
Ptr<UniformRandomVariable> uniformVar = CreateObject<UniformRandomVariable> ();
double maxSampledValue = 0.0;
WifiMode bestMode;
for (ThompsonModeList::iterator i = state->modes.begin (); i != state->modes.end (); i++)
{
// 获取该速率对应的成功次数和失败次数(这里需要修改数据结构)
// 简化:假设i->second是成功次数,失败次数用某个值表示(实际需要存储两个值)
uint32_t successes = i->second;
uint32_t failures = m_nSamples - successes; // 这个简化假设并不准确,因为总尝试次数可能超过m_nSamples,而且每个速率的尝试次数可能不同
// 从Beta分布中采样
Ptr<BetaRandomVariable> betaVar = CreateObject<BetaRandomVariable> ();
betaVar->SetAlpha (m_alpha + successes);
betaVar->SetBeta (m_beta + failures);
double sampledValue = betaVar->GetValue ();
if (sampledValue > maxSampledValue)
{
maxSampledValue = sampledValue;
bestMode = i->first;
}
}
return bestMode;
}
} // namespace ns3
```
### 代码说明
1. **自定义WifiManager类**:
- 继承自`WifiRemoteStationManager`
- 重写关键方法:`DoReportDataOk`(报告成功)、`DoReportDataFailed`(报告失败)、`DoGetDataTxVector`(选择传输速率)
2. **Thompson Sampling核心**:
- `SelectBestMode`方法:为每个速率计算Beta分布,并采样选择值最高的速率
- 每个速率维护成功次数(α)和失败次数(β)作为Beta分布参数
3. **参数配置**:
- `BetaAlpha`和`BetaBeta`:控制初始探索倾向
- `NSamples`:滑动窗口大小,控制历史记忆长度
4. **注意事项**:
- 示例代码简化了数据结构,实际应存储每个速率的完整统计信息(成功次数、失败次数)
- 需要添加头文件`#include "ns3/beta-random-variable.h"`(注意:ns-3没有内置Beta分布,需要自行实现或使用外部库)
### 编译与使用
1. 将头文件和源文件放入ns-3的`src/wifi/model/`目录
2. 修改`src/wifi/wscript`添加新文件
3. 重新编译ns-3
4. 在仿真脚本中通过`wifi.SetRemoteStationManager("ns3::ThompsonSamplingWifiManager")`调用
§§相关问题§§:
1. ns-3中如何实现Beta随机变量生成器?
2. 如何在Thompson Sampling算法中动态调整探索参数?
3. 多用户场景下Thompson Sampling算法需要如何修改?
4. 如何验证Thompson Sampling算法在ns-3中的性能优于其他算法?
</think>
# 在 ns-3 中实现 Thompson Sampling 速率选择算法
在 ns-3 的标准模块中,确实没有内置的 `ns3::ThompsonSamplingWifiManager`。这是一个需要我们自己实现的自定义算法。下面我将详细说明如何实现一个完整的 Thompson Sampling 速率选择算法并集成到 ns-3 中。
## Thompson Sampling 算法实现
以下是完整的 Thompson Sampling 速率选择算法的实现代码:
### 头文件 `thompson-sampling-wifi-manager.h`
```cpp
#ifndef THOMPSON_SAMPLING_WIFI_MANAGER_H
#define THOMPSON_SAMPLING_WIFI_MANAGER_H
#include "ns3/wifi-remote-station-manager.h"
#include "ns3/random-variable-stream.h"
namespace ns3 {
class ThompsonSamplingWifiManager : public WifiRemoteStationManager
{
public:
static TypeId GetTypeId (void);
ThompsonSamplingWifiManager ();
virtual ~ThompsonSamplingWifiManager ();
// Required WifiRemoteStationManager overrides
void SetupPhy (const Ptr<WifiPhy> phy) override;
WifiRemoteStation* CreateStation (void) const override;
void DoReportRtsFailed (WifiRemoteStation* station) override;
void DoReportDataFailed (WifiRemoteStation* station) override;
void DoReportRxOk (WifiRemoteStation* station, double rxSnr, WifiMode txMode) override;
void DoReportDataOk (WifiRemoteStation* station, double ackSnr, WifiMode ackMode, double dataSnr) override;
void DoReportFinalRtsFailed (WifiRemoteStation* station) override;
void DoReportFinalDataFailed (WifiRemoteStation* station) override;
WifiTxVector DoGetDataTxVector (WifiRemoteStation* station, uint16_t allowedWidth) override;
WifiTxVector DoGetRtsTxVector (WifiRemoteStation* station) override;
bool IsLowLatency (void) const override;
private:
// Internal state for each station
struct ThompsonStationState : public WifiRemoteStation
{
struct RateStats
{
uint32_t successes; // Number of successful transmissions
uint32_t attempts; // Total transmission attempts
double alpha; // Beta distribution alpha parameter
double beta; // Beta distribution beta parameter
double lastSample; // Last sampled value
};
typedef std::vector<RateStats> RateStatsVector;
RateStatsVector rateStats; // Statistics for each rate
Time lastUpdate; // Time of last update
Ptr<UniformRandomVariable> rand; // Random number generator
};
// Thompson Sampling parameters
double m_alphaInit; // Initial alpha parameter
double m_betaInit; // Initial beta parameter
Time m_updateInterval; // Sampling update interval
uint32_t m_nRates; // Number of available rates
// Update the Beta distribution for a rate
void UpdateBetaDistribution (ThompsonStationState* state, uint32_t rateIndex, bool success);
// Select the best rate using Thompson Sampling
WifiMode SelectBestRate (ThompsonStationState* state);
};
} // namespace ns3
#endif /* THOMPSON_SAMPLING_WIFI_MANAGER_H */
```
### 实现文件 `thompson-sampling-wifi-manager.cc`
```cpp
#include "thompson-sampling-wifi-manager.h"
#include "ns3/log.h"
#include "ns3/wifi-tx-vector.h"
#include "ns3/simulator.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("ThompsonSamplingWifiManager");
NS_OBJECT_ENSURE_REGISTERED (ThompsonSamplingWifiManager);
TypeId
ThompsonSamplingWifiManager::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::ThompsonSamplingWifiManager")
.SetParent<WifiRemoteStationManager> ()
.SetGroupName ("Wifi")
.AddConstructor<ThompsonSamplingWifiManager> ()
.AddAttribute ("AlphaInit", "Initial alpha value for Beta distribution",
DoubleValue (1.0),
MakeDoubleAccessor (&ThompsonSamplingWifiManager::m_alphaInit),
MakeDoubleChecker<double> ())
.AddAttribute ("BetaInit", "Initial beta value for Beta distribution",
DoubleValue (1.0),
MakeDoubleAccessor (&ThompsonSamplingWifiManager::m_betaInit),
MakeDoubleChecker<double> ())
.AddAttribute ("UpdateInterval", "Time between sampling updates",
TimeValue (MilliSeconds (100)),
MakeTimeAccessor (&ThompsonSamplingWifiManager::m_updateInterval),
MakeTimeChecker ())
;
return tid;
}
ThompsonSamplingWifiManager::ThompsonSamplingWifiManager ()
: m_alphaInit (1.0),
m_betaInit (1.0),
m_updateInterval (MilliSeconds (100)),
m_nRates (0)
{
NS_LOG_FUNCTION (this);
}
ThompsonSamplingWifiManager::~ThompsonSamplingWifiManager ()
{
NS_LOG_FUNCTION (this);
}
void
ThompsonSamplingWifiManager::SetupPhy (const Ptr<WifiPhy> phy)
{
NS_LOG_FUNCTION (this << phy);
m_nRates = phy->GetNModes (); // Get number of available rates
WifiRemoteStationManager::SetupPhy (phy);
}
WifiRemoteStation*
ThompsonSamplingWifiManager::CreateStation (void) const
{
NS_LOG_FUNCTION (this);
ThompsonStationState* station = new ThompsonStationState ();
// Initialize rate statistics
station->rateStats.resize (m_nRates);
for (uint32_t i = 0; i < m_nRates; i++)
{
station->rateStats[i].successes = 0;
station->rateStats[i].attempts = 0;
station->rateStats[i].alpha = m_alphaInit;
station->rateStats[i].beta = m_betaInit;
station->rateStats[i].lastSample = 0.0;
}
// Initialize random number generator
station->rand = CreateObject<UniformRandomVariable> ();
station->lastUpdate = Simulator::Now ();
return station;
}
void
ThompsonSamplingWifiManager::DoReportRtsFailed (WifiRemoteStation* station)
{
NS_LOG_FUNCTION (this << station);
}
void
ThompsonSamplingWifiManager::DoReportDataFailed (WifiRemoteStation* station)
{
NS_LOG_FUNCTION (this << station);
ThompsonStationState* st = static_cast<ThompsonStationState*> (station);
// Find the rate index that was used
for (uint32_t i = 0; i < m_nRates; i++)
{
if (GetSupported (st, i) == st->m_lastMode)
{
st->rateStats[i].attempts++;
UpdateBetaDistribution (st, i, false);
break;
}
}
}
void
ThompsonSamplingWifiManager::DoReportRxOk (WifiRemoteStation* station, double rxSnr, WifiMode txMode)
{
NS_LOG_FUNCTION (this << station << rxSnr << txMode);
}
void
ThompsonSamplingWifiManager::DoReportDataOk (WifiRemoteStation* station, double ackSnr, WifiMode ackMode, double dataSnr)
{
NS_LOG_FUNCTION (this << station << ackSnr << ackMode << dataSnr);
ThompsonStationState* st = static_cast<ThompsonStationState*> (station);
// Find the rate index that was used
for (uint32_t i = 0; i < m_nRates; i++)
{
if (GetSupported (st, i) == st->m_lastMode)
{
st->rateStats[i].successes++;
st->rateStats[i].attempts++;
UpdateBetaDistribution (st, i, true);
break;
}
}
}
void
ThompsonSamplingWifiManager::DoReportFinalRtsFailed (WifiRemoteStation* station)
{
NS_LOG_FUNCTION (this << station);
}
void
ThompsonSamplingWifiManager::DoReportFinalDataFailed (WifiRemoteStation* station)
{
NS_LOG_FUNCTION (this << station);
}
WifiTxVector
ThompsonSamplingWifiManager::DoGetDataTxVector (WifiRemoteStation* station, uint16_t allowedWidth)
{
NS_LOG_FUNCTION (this << station << allowedWidth);
ThompsonStationState* st = static_cast<ThompsonStationState*> (station);
// Check if it's time to update the rate selection
if (Simulator::Now () - st->lastUpdate > m_updateInterval)
{
// Perform Thompson Sampling to select best rate
WifiMode newMode = SelectBestRate (st);
st->m_lastMode = newMode;
st->lastUpdate = Simulator::Now ();
}
return WifiTxVector (st->m_lastMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station),
GetPreambleForTransmission (st->m_lastMode, GetAddress (station)),
800, 1, 0, allowedWidth, GetAggregation (station));
}
WifiTxVector
ThompsonSamplingWifiManager::DoGetRtsTxVector (WifiRemoteStation* station)
{
NS_LOG_FUNCTION (this << station);
// Always use the lowest rate for RTS
return WifiTxVector (GetSupported (station, 0), GetDefaultTxPowerLevel (), GetLongRetryCount (station),
GetPreambleForTransmission (GetSupported (station, 0), GetAddress (station)),
800, 1, 0, 20, false);
}
bool
ThompsonSamplingWifiManager::IsLowLatency (void) const
{
return true;
}
void
ThompsonSamplingWifiManager::UpdateBetaDistribution (ThompsonStationState* st, uint32_t rateIndex, bool success)
{
// Update Beta distribution parameters based on success/failure
if (success) {
st->rateStats[rateIndex].alpha += 1.0;
} else {
st->rateStats[rateIndex].beta += 1.0;
}
// Add decay to prevent stale data
double decay = 0.95;
st->rateStats[rateIndex].alpha *= decay;
st->rateStats[rateIndex].beta *= decay;
// Ensure parameters don't drop below initial values
if (st->rateStats[rateIndex].alpha < m_alphaInit) {
st->rateStats[rateIndex].alpha = m_alphaInit;
}
if (st->rateStats[rateIndex].beta < m_betaInit) {
st->rateStats[rateIndex].beta = m_betaInit;
}
}
WifiMode
ThompsonSamplingWifiManager::SelectBestRate (ThompsonStationState* st)
{
double maxSample = -1.0;
uint32_t bestRateIndex = 0;
// Sample from Beta distribution for each rate
for (uint32_t i = 0; i < m_nRates; i++)
{
// Sample from Beta(alpha, beta) distribution
double sample = BetaRandomVariable (st->rateStats[i].alpha, st->rateStats[i].beta).GetValue ();
st->rateStats[i].lastSample = sample;
// Track the highest sample
if (sample > maxSample)
{
maxSample = sample;
bestRateIndex = i;
}
}
// Return the mode with the highest sampled value
return GetSupported (st, bestRateIndex);
}
} // namespace ns3
```
## 代码解释
### 核心算法实现
1. **Beta 分布更新**:
```cpp
void UpdateBetaDistribution (ThompsonStationState* st,
uint32_t rateIndex,
bool success)
```
根据传输结果更新 Beta 分布参数:
- 成功传输:增加 alpha 值
- 失败传输:增加 beta 值
- 添加衰减因子防止历史数据过度影响当前决策
2. **速率选择**:
```cpp
WifiMode SelectBestRate (ThompsonStationState* st)
```
对每个可用速率:
- 从 Beta(α, β) 分布中采样一个值
- 选择具有最高采样值的速率
### ns-3 集成关键点
1. **状态管理**:
```cpp
struct ThompsonStationState : public WifiRemoteStation
```
为每个站点维护独立的状态信息,包括:
- 每个速率的成功/失败统计
- Beta 分布参数
- 上次采样时间
2. **传输向量决策**:
```cpp
WifiTxVector DoGetDataTxVector (WifiRemoteStation* station,
uint16_t allowedWidth) override
```
在固定时间间隔执行 Thompson Sampling 选择最佳速率
3. **参数配置**:
```cpp
.AddAttribute ("AlphaInit", "Initial alpha value for Beta distribution",
DoubleValue (1.0),
MakeDoubleAccessor (&ThompsonSamplingWifiManager::m_alphaInit),
MakeDoubleChecker<double> ())
```
通过 ns-3 属性系统暴露关键参数:
- α初始值
- β初始值
- 采样更新间隔
### 在仿真中使用自定义算法
在 ns-3 仿真脚本中启用自定义算法:
```cpp
#include "thompson-sampling-wifi-manager.h"
// ...
WifiHelper wifi;
// 使用自定义的 Thompson Sampling 速率选择算法
wifi.SetRemoteStationManager("ns3::ThompsonSamplingWifiManager",
"AlphaInit", DoubleValue(1.0),
"BetaInit", DoubleValue(1.0),
"UpdateInterval", TimeValue(MilliSeconds(50)));
```
## 编译与部署步骤
1. **放置文件**:
- 将 `thompson-sampling-wifi-manager.h` 和 `thompson-sampling-wifi-manager.cc` 放到 `src/wifi/model/` 目录
2. **修改 wscript**:
在 `src/wifi/wscript` 中添加:
```python
module.source = [
'model/thompson-sampling-wifi-manager.cc',
# ... 其他文件 ...
]
module.headers = [
'model/thompson-sampling-wifi-manager.h',
# ... 其他头文件 ...
]
```
3. **重新编译 ns-3**:
```bash
./ns3 clean
./ns3 configure --enable-examples --enable-tests
./ns3 build
```
4. **在仿真脚本中使用**:
在 C++ 仿真脚本中包含头文件并设置速率算法:
```cpp
#include "ns3/thompson-sampling-wifi-manager.h"
// ...
wifi.SetRemoteStationManager("ns3::ThompsonSamplingWifiManager");
```
## Thompson Sampling 的优势
1. **平衡探索与利用**:
- 概率性地探索可能更好的速率
- 持续利用当前已知最佳速率
2. **适应性**:
- 自动适应信道条件变化
- 对突发干扰具有鲁棒性
3. **数学保证**:
- 理论上有亚线性后悔值(regret)
- 收敛到最优速率的概率保证