Module deepcomp.agent.heuristics
Heuristic algorithms to use as baseline. Only work as multi-agent, not central (would be the same anyways).
Expand source code
"""
Heuristic algorithms to use as baseline. Only work as multi-agent, not central (would be the same anyways).
"""
import numpy as np
from deepcomp.agent.base import MultiAgent
class GreedyBestSelection(MultiAgent):
"""
Agent that is always connected to at most one BS. Greedily chooses the BS with highest achievable data rate.
This is comparable to 3GPP LTE cell selection based on highest SINR (with a hysteresis threshold of 0)
"""
def compute_action(self, obs, policy_id):
"""
Compute an action for one UE by connecting to the BS with highest data rate (if not connected yet).
Gets called for all UEs by simulator.
:param obs: Observation of a UE
:param policy_id: Ignored since the heuristic behaves identically for all UEs; just based on obs.
:return: Selected action: 0 = noop. 1-n = index of BS +1 to connect/disconnect
"""
# identify BS with highest data rate; in case of a tie, take the first one
best_bs = np.argmax(obs['dr'])
# if already connected to this BS, stay connected = do nothing
if obs['connected'][best_bs]:
return 0
# if connected to other BS, disconnect first
if sum(obs['connected']) > 0:
conn_bs = obs['connected'].index(1)
return conn_bs + 1
# else: not connected yet --> connect to best BS
return best_bs + 1
class GreedyAllSelection(MultiAgent):
"""Agent that always greedily connects to all BS."""
def compute_action(self, obs, policy_id):
"""
Compute action for a UE. Try to connect to all BS. Prioritize BS with higher data rate.
:param obs: Observations of the UE
:param policy_id: Ignored
:return: Action for the UE
"""
# identify BS that are not yet connected
disconn_bs = [idx for idx, conn in enumerate(obs['connected']) if not conn]
# if connected to all BS already, do nothing
if len(disconn_bs) == 0:
return 0
# else connect to the BS with the highest data rate
best_bs = disconn_bs[0]
best_dr = obs['dr'][best_bs]
for bs in disconn_bs:
if obs['dr'][bs] > best_dr:
best_bs = bs
best_dr = obs['dr'][bs]
# 0 = noop --> select BS with BS index + 1
return best_bs + 1
class DynamicSelection(MultiAgent):
"""
Heuristic that dynamically selects cells per UE depending on the SINR.
It always selects the strongest cell with SINR-1st and all cells that are within epsilon * SINR-1st.
Based on the following paper: 'Multi-point fairness in resource allocation for C-RAN downlink CoMP transmission'
https://jwcn-eurasipjournals.springeropen.com/articles/10.1186/s13638-015-0501-4
"""
def __init__(self, epsilon):
"""
:param epsilon: Scaling factor
"""
super().__init__()
self.epsilon = epsilon
def compute_action(self, obs, policy_id):
"""Select strongest BS and all that are within epsilon * SINR of that BS"""
# get set of selected cells
best_snr = max(obs['dr'])
threshold = best_snr * self.epsilon
selected_bs = [idx for idx, snr in enumerate(obs['dr']) if snr >= threshold]
connected_bs = [idx for idx, conn in enumerate(obs['connected']) if conn]
# disconnect from any BS not in the set of selected BS
for bs in connected_bs:
if bs not in selected_bs:
# 0 = noop --> select BS with BS index + 1
return bs + 1
# then connect to BS inside set, starting with the strongest --> sort with decreasing SINR
selected_bs_sorted = sorted(selected_bs, key=lambda idx: obs['dr'][idx], reverse=True)
for bs in selected_bs_sorted:
if not obs['connected'][bs]:
return bs + 1
# else do nothing
return 0
Classes
class DynamicSelection (epsilon)
-
Heuristic that dynamically selects cells per UE depending on the SINR. It always selects the strongest cell with SINR-1st and all cells that are within epsilon * SINR-1st.
Based on the following paper: 'Multi-point fairness in resource allocation for C-RAN downlink CoMP transmission' https://jwcn-eurasipjournals.springeropen.com/articles/10.1186/s13638-015-0501-4
:param epsilon: Scaling factor
Expand source code
class DynamicSelection(MultiAgent): """ Heuristic that dynamically selects cells per UE depending on the SINR. It always selects the strongest cell with SINR-1st and all cells that are within epsilon * SINR-1st. Based on the following paper: 'Multi-point fairness in resource allocation for C-RAN downlink CoMP transmission' https://jwcn-eurasipjournals.springeropen.com/articles/10.1186/s13638-015-0501-4 """ def __init__(self, epsilon): """ :param epsilon: Scaling factor """ super().__init__() self.epsilon = epsilon def compute_action(self, obs, policy_id): """Select strongest BS and all that are within epsilon * SINR of that BS""" # get set of selected cells best_snr = max(obs['dr']) threshold = best_snr * self.epsilon selected_bs = [idx for idx, snr in enumerate(obs['dr']) if snr >= threshold] connected_bs = [idx for idx, conn in enumerate(obs['connected']) if conn] # disconnect from any BS not in the set of selected BS for bs in connected_bs: if bs not in selected_bs: # 0 = noop --> select BS with BS index + 1 return bs + 1 # then connect to BS inside set, starting with the strongest --> sort with decreasing SINR selected_bs_sorted = sorted(selected_bs, key=lambda idx: obs['dr'][idx], reverse=True) for bs in selected_bs_sorted: if not obs['connected'][bs]: return bs + 1 # else do nothing return 0
Ancestors
Methods
def compute_action(self, obs, policy_id)
-
Select strongest BS and all that are within epsilon * SINR of that BS
Expand source code
def compute_action(self, obs, policy_id): """Select strongest BS and all that are within epsilon * SINR of that BS""" # get set of selected cells best_snr = max(obs['dr']) threshold = best_snr * self.epsilon selected_bs = [idx for idx, snr in enumerate(obs['dr']) if snr >= threshold] connected_bs = [idx for idx, conn in enumerate(obs['connected']) if conn] # disconnect from any BS not in the set of selected BS for bs in connected_bs: if bs not in selected_bs: # 0 = noop --> select BS with BS index + 1 return bs + 1 # then connect to BS inside set, starting with the strongest --> sort with decreasing SINR selected_bs_sorted = sorted(selected_bs, key=lambda idx: obs['dr'][idx], reverse=True) for bs in selected_bs_sorted: if not obs['connected'][bs]: return bs + 1 # else do nothing return 0
class GreedyAllSelection
-
Agent that always greedily connects to all BS.
Expand source code
class GreedyAllSelection(MultiAgent): """Agent that always greedily connects to all BS.""" def compute_action(self, obs, policy_id): """ Compute action for a UE. Try to connect to all BS. Prioritize BS with higher data rate. :param obs: Observations of the UE :param policy_id: Ignored :return: Action for the UE """ # identify BS that are not yet connected disconn_bs = [idx for idx, conn in enumerate(obs['connected']) if not conn] # if connected to all BS already, do nothing if len(disconn_bs) == 0: return 0 # else connect to the BS with the highest data rate best_bs = disconn_bs[0] best_dr = obs['dr'][best_bs] for bs in disconn_bs: if obs['dr'][bs] > best_dr: best_bs = bs best_dr = obs['dr'][bs] # 0 = noop --> select BS with BS index + 1 return best_bs + 1
Ancestors
Methods
def compute_action(self, obs, policy_id)
-
Compute action for a UE. Try to connect to all BS. Prioritize BS with higher data rate.
:param obs: Observations of the UE :param policy_id: Ignored :return: Action for the UE
Expand source code
def compute_action(self, obs, policy_id): """ Compute action for a UE. Try to connect to all BS. Prioritize BS with higher data rate. :param obs: Observations of the UE :param policy_id: Ignored :return: Action for the UE """ # identify BS that are not yet connected disconn_bs = [idx for idx, conn in enumerate(obs['connected']) if not conn] # if connected to all BS already, do nothing if len(disconn_bs) == 0: return 0 # else connect to the BS with the highest data rate best_bs = disconn_bs[0] best_dr = obs['dr'][best_bs] for bs in disconn_bs: if obs['dr'][bs] > best_dr: best_bs = bs best_dr = obs['dr'][bs] # 0 = noop --> select BS with BS index + 1 return best_bs + 1
class GreedyBestSelection
-
Agent that is always connected to at most one BS. Greedily chooses the BS with highest achievable data rate. This is comparable to 3GPP LTE cell selection based on highest SINR (with a hysteresis threshold of 0)
Expand source code
class GreedyBestSelection(MultiAgent): """ Agent that is always connected to at most one BS. Greedily chooses the BS with highest achievable data rate. This is comparable to 3GPP LTE cell selection based on highest SINR (with a hysteresis threshold of 0) """ def compute_action(self, obs, policy_id): """ Compute an action for one UE by connecting to the BS with highest data rate (if not connected yet). Gets called for all UEs by simulator. :param obs: Observation of a UE :param policy_id: Ignored since the heuristic behaves identically for all UEs; just based on obs. :return: Selected action: 0 = noop. 1-n = index of BS +1 to connect/disconnect """ # identify BS with highest data rate; in case of a tie, take the first one best_bs = np.argmax(obs['dr']) # if already connected to this BS, stay connected = do nothing if obs['connected'][best_bs]: return 0 # if connected to other BS, disconnect first if sum(obs['connected']) > 0: conn_bs = obs['connected'].index(1) return conn_bs + 1 # else: not connected yet --> connect to best BS return best_bs + 1
Ancestors
Methods
def compute_action(self, obs, policy_id)
-
Compute an action for one UE by connecting to the BS with highest data rate (if not connected yet). Gets called for all UEs by simulator.
:param obs: Observation of a UE :param policy_id: Ignored since the heuristic behaves identically for all UEs; just based on obs. :return: Selected action: 0 = noop. 1-n = index of BS +1 to connect/disconnect
Expand source code
def compute_action(self, obs, policy_id): """ Compute an action for one UE by connecting to the BS with highest data rate (if not connected yet). Gets called for all UEs by simulator. :param obs: Observation of a UE :param policy_id: Ignored since the heuristic behaves identically for all UEs; just based on obs. :return: Selected action: 0 = noop. 1-n = index of BS +1 to connect/disconnect """ # identify BS with highest data rate; in case of a tie, take the first one best_bs = np.argmax(obs['dr']) # if already connected to this BS, stay connected = do nothing if obs['connected'][best_bs]: return 0 # if connected to other BS, disconnect first if sum(obs['connected']) > 0: conn_bs = obs['connected'].index(1) return conn_bs + 1 # else: not connected yet --> connect to best BS return best_bs + 1