system_hetero.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import logging
  2. import numpy as np
  3. from easyfl.simulation.mobile_ratio import MOBILE_RATIO
  4. from easyfl.datasets.simulation import equal_division
  5. logger = logging.getLogger(__name__)
  6. SIMULATE_ISO = "iso" # isometric sleep time distribution among selected clients
  7. SIMULATE_DIR = "dir" # use symmetric dirichlet process to sample sleep time heterogenous
  8. SIMULATE_REAL = "real" # use real speed ratio of main stream smartphones to simulate sleep time heterogenous
  9. def assign_value_to_group(groups, values):
  10. assert len(groups) == len(values)
  11. result = []
  12. for i in range(len(groups)):
  13. result.extend([values[i]] * len(groups[i]))
  14. return result
  15. def sample_real_ratio(num_values):
  16. value_pool = list(MOBILE_RATIO.values())
  17. idxs = np.random.randint(0, len(value_pool), size=num_values)
  18. return np.array([value_pool[i] for i in idxs]).astype(float)
  19. def resource_hetero_simulation(fraction, hetero_type, sleep_group_num, level, total_time, num_clients):
  20. """Simulated resource heterogeneous by add sleeping time to clients.
  21. Args:
  22. fraction (float): The fraction of clients attending heterogeneous simulation.
  23. hetero_type (str): The type of heterogeneous simulation, options: iso, dir or real.
  24. sleep_group_num (int): The number of groups with different sleep time.
  25. level (int): The level of heterogeneous (0-5), 0 means no heterogeneous among clients.
  26. total_time (float): The total sleep time of all clients.
  27. num_clients (int): The total number of clients.
  28. Returns:
  29. list[float]: A list of sleep time with distribution according to heterogeneous type.
  30. """
  31. sleep_clients = int(fraction * num_clients)
  32. unsleep_clients = [0] * (num_clients - sleep_clients)
  33. sleep_group_num = sleep_group_num
  34. if sleep_group_num > sleep_clients:
  35. logger.warning("sleep_group_num {} is more than sleep_clients number {}, \
  36. so we set sleep_group_num to sleep_clients".format(sleep_group_num, sleep_clients))
  37. sleep_group_num = sleep_clients
  38. groups, _ = equal_division(sleep_group_num, np.arange(sleep_clients))
  39. if level == 0:
  40. distribution = np.array([1] * sleep_clients)
  41. elif hetero_type == SIMULATE_DIR:
  42. alpha = 1 / (level * level)
  43. values = np.random.dirichlet(np.repeat(alpha, sleep_group_num))
  44. distribution = assign_value_to_group(groups, values)
  45. elif hetero_type == SIMULATE_ISO:
  46. if level > 5:
  47. raise ValueError("level cannot be more than 5")
  48. begin = 0.5 - level * 0.1
  49. end = 0.5 + level * 0.1
  50. values = np.arange(begin, end, (end - begin) / sleep_group_num)
  51. distribution = assign_value_to_group(groups, values)
  52. elif hetero_type == SIMULATE_REAL:
  53. values = sample_real_ratio(sleep_group_num)
  54. distribution = assign_value_to_group(groups, values)
  55. else:
  56. raise ValueError("sleep type not supported, please use either dir or iso")
  57. distribution += unsleep_clients
  58. np.random.shuffle(distribution)
  59. return distribution / sum(distribution) * total_time