Untitled
unknown
plain_text
2 years ago
14 kB
12
Indexable
from ctypes import *
from py_interface import *
import json
import os
import random
import asyncio
import numpy as np
PARTICLES_COUNT = 10
MAX_ITERATIONS = 20
DEFAULT_COGNITIVE_PARAMETER = 2.0
DEFAULT_SOCIAL_PARAMETER = 2.0
DEFAULT_INERTIA_WEIGHT = 0.8
GLOBAL_OUTPUT_PATH = os.path.dirname(__file__) + '/../../simulation_output'
PARAMETERS_INDEXES = ['ttlStart', 'ttlIncrement', 'ttlThreshold', 'rreqRetries', 'nodeTraversalTime',
'activeRouteTimeout', 'netDiameter', 'maxQueueLength', 'allowedHelloLoss']
PARAMETERS_BOUNDS = {
'ttlStart': {
'min': 1.0,
'max': 10.0
},
'ttlIncrement': {
'min': 1.0,
'max': 10.0
},
'ttlThreshold': {
'min': 1.0,
'max': 20.0
},
'rreqRetries': {
'min': 1.0,
'max': 10.0
},
'nodeTraversalTime': {
'min': 10.0,
'max': 1000.0
},
'activeRouteTimeout': {
'min': 1.0,
'max': 30.0
},
'netDiameter': {
'min': 15.0,
'max': 100.0
},
'maxQueueLength': {
'min': 1.0,
'max': 100
},
'allowedHelloLoss': {
'min': 1.0,
'max': 10.0
},
}
os.chdir(os.path.dirname(__file__))
global_best_positions_simulations = []
global_best_costs_simulations = []
class Env(Structure):
_pack_ = 1
_fields_ = [
('ttlStart', c_int),
('ttlIncrement', c_int),
('ttlThreshold', c_int),
('rreqRetries', c_int),
('nodeTraversalTime', c_double),
('activeRouteTimeout', c_int),
('netDiameter', c_int),
('maxQueueLength', c_int),
('allowedHelloLoss', c_int)
]
class Act(Structure):
_pack_ = 1
_fields_ = [
('packetDeliveryRatio', c_double)
]
class Particle:
def __init__(self, params):
self.position = np.array([params['ttlStart'], params['ttlIncrement'],
params['ttlThreshold'], params['rreqRetries'],
params['nodeTraversalTime'],
params['activeRouteTimeout'],
params['netDiameter'], params['maxQueueLength'],
params['allowedHelloLoss']])
self.velocity = np.zeros_like(self.position)
self.best_position = self.position.copy()
self.best_cost = 1001
def update_velocity(self, global_best_position):
"""
Update velocity of particle.
:param global_best_position: set of parameters, that have best position in n-dimensional space
"""
for j in range(len(self.position)):
r1 = np.random.rand()
r2 = np.random.rand()
cognitive_component = DEFAULT_COGNITIVE_PARAMETER * r1 * (self.best_position[j] - self.position[j])
social_component = DEFAULT_SOCIAL_PARAMETER * r2 * (global_best_position[j] - self.position[j])
self.velocity[j] = DEFAULT_INERTIA_WEIGHT * self.velocity[j] + cognitive_component + social_component
def update_position(self):
"""
Update position of particle - set value for each parameter in set of parameters.
"""
for j in range(len(self.position)):
self.position[j] += self.velocity[j]
self.position[j] = check_parameter_bounds(PARAMETERS_INDEXES[j], self.position[j])
def update_cost(self, cost):
"""
Update best_cost and best_position of particle if cost is lower than the previous one.
:param cost: calculated cost from simulation
"""
# if cost < self.best_cost:
# self.best_cost = cost
# self.best_position = self.position
if cost < self.best_cost:
self.best_cost = cost
self.best_position = self.position
class PSO:
def __init__(self, entry_particles):
self.global_best_cost = 1001
self.global_best_position = entry_particles[0].best_position
self.particles = entry_particles
async def fitness_function(self, iteration):
"""
Fitness function of PSO implementation which runs 10 simulations sequentially.
:param iteration: Number of iteration of PSO algorithm.
"""
print(f"Running {iteration} iteration of PSO algorithm.")
coroutines = []
simulations_iteration = 0
mempool_keys, memblock_keys = generate_simulations_memory_parameters()
for simulation in convert_particles_array_to_ns3_settings_array(self.particles):
simulation['pathOfOutput'] = os.path.dirname(__file__) + '/../../simulation_output' + str(
simulations_iteration) + '.json'
coroutine = run_simulation(mempool_keys[simulations_iteration], memblock_keys[simulations_iteration],
simulation)
coroutines.append(coroutine)
simulations_iteration += 1
sim_results = await asyncio.gather(*coroutines)
simulation_outputs = []
for i in range(10):
f = open(os.path.dirname(__file__) + '/../../simulation_output' + str(i) + '.json')
data = json.load(f)
simulation_outputs.append(data)
costs = calculate_costs(simulation_outputs)
best_cost, best_set_of_parameters = find_best_cost(costs,
convert_particles_array_to_ns3_settings_array(
self.particles))
if best_cost < self.global_best_cost:
self.global_best_cost = best_cost
self.global_best_position = best_set_of_parameters
global_best_positions_simulations.append(best_set_of_parameters)
global_best_costs_simulations.append(best_cost)
iteration = 0
for particle in self.particles:
particle.update_velocity(convert_ns3_settings_to_array(self.global_best_position))
particle.update_position()
particle.update_cost(costs[iteration])
iteration += 1
async def run(self):
"""
Runs fitness function in number of iterations set by MAX_ITERATIONS and evaluates results of implemented
algorithm.
"""
simulations_results = []
for pso_iteration in range(MAX_ITERATIONS):
simulations_results.append(await self.fitness_function(pso_iteration))
print('Global best cost is: ' + str(self.global_best_cost))
print('Global best position is: ' + str(self.global_best_position))
#print('Global best costs: ' + str(global_best_costs_simulations))
#print('Global best positions: ' + str(global_best_positions_simulations))
def generate_simulations_memory_parameters():
"""
Generate memory parameters for simulations according to count of particles from range 1000-10000.
:return: Generated mempool_keys and memblock_keys for ns3 simulations.
"""
generatedNumbers = random.sample(range(1000, 10000), PARTICLES_COUNT * 2)
mempool_keys = generatedNumbers[:10]
memblock_keys = generatedNumbers[10:]
return mempool_keys, memblock_keys
def check_parameter_bounds(parameter_type, value):
"""
Check if new parameter value fits into bounds for this parameter. If not, set closest possible value.
:param parameter_type: Name of parameter.
:param value: New value of parameter.
:return: Correct new value of parameter.
"""
if value < PARAMETERS_BOUNDS[parameter_type]['min']:
value = PARAMETERS_BOUNDS[parameter_type]['min']
elif value > PARAMETERS_BOUNDS[parameter_type]['max']:
value = PARAMETERS_BOUNDS[parameter_type]['max']
return value
async def run_simulation(mempool_key, memblock_key, ns3Settings):
"""
Run new ns3 simulation via ns3-ai class Experiment and wait till the simulation is not finished.
:param mempool_key: Integer value for mempool_key from range 1000-10000.
:param memblock_key: Integer value for memblock_key from range 1000-10000.
:param ns3Settings: Set of parameters for AODV protocol.
:return: Results of simulation.
"""
mem_size = 4096
exp = Experiment(mempool_key, mem_size, 'bp-pso13', '../../')
exp.reset()
pro = exp.run(setting=ns3Settings, show_output=True)
pro_wait = pro.wait()
if not type(pro_wait) is int:
await pro.wait()
return pro
def calculate_costs(results_of_simulations):
"""
Calculate costs for each simulation run in one iteration of PSO algorithm.
:param results_of_simulations: Array of results of simulations consisting from PDR, Delay and Average Throughput.
:return: Array of calculated costs.
"""
costs = []
for result_of_simulation in results_of_simulations:
pdr = result_of_simulation["PDR"]
delay = result_of_simulation["EtE"]
throughput = result_of_simulation["avgThroughput"]
w_pdr = 0.4
w_delay = 0.3
w_throughput = 0.3
cost = w_pdr * (1 - pdr / 100) + w_delay * delay + w_throughput * throughput
costs.append(cost)
return costs
def find_best_cost(costs, simulations_ns3_params):
"""
Find best cost in array of costs.
:param costs: Array of costs.
:param simulations_ns3_params: Array of parameters for each simulation.
:return: Lowest cost and the corresponding set of parameters.
"""
lowest_cost = min(costs)
lowest_cost_index = costs.index(lowest_cost)
return lowest_cost, simulations_ns3_params[lowest_cost_index]
def convert_ns3_settings_to_array(params):
"""
Convert object of simulation parameters to array form which is used for representation of particle position in
n-dimensional space.
:param params: Object of simulation parameters.
:return: Particle position in n-dimensional space.
"""
return np.array([params['ttlStart'], params['ttlIncrement'],
params['ttlThreshold'], params['rreqRetries'],
params['nodeTraversalTime'],
params['activeRouteTimeout'],
params['netDiameter'], params['maxQueueLength'],
params['allowedHelloLoss']])
def convert_particle_to_ns3_settings(pso_particle):
"""
Convert array of particle position to object of simulation parameters.
:param pso_particle: Array of particle position.
:return: Object that represents simulation parameters.
"""
return {
'ttlStart': pso_particle.position[0],
'ttlIncrement': pso_particle.position[1],
'ttlThreshold': pso_particle.position[2],
'rreqRetries': pso_particle.position[3],
'nodeTraversalTime': pso_particle.position[4],
'activeRouteTimeout': pso_particle.position[5],
'netDiameter': pso_particle.position[6],
'maxQueueLength': pso_particle.position[7],
'allowedHelloLoss': pso_particle.position[8]
}
def convert_particles_array_to_ns3_settings_array(pso_particles_array):
"""
Convert array of particles to array of simulations parameters.
:param pso_particles_array: Array of particles.
:return: Array of parameters for simulations.
"""
ns3_settings_array = []
for pso_particle in pso_particles_array:
ns3_settings_array.append(convert_particle_to_ns3_settings(pso_particle))
return ns3_settings_array
def convert_ns3_settings_to_particle(ns3_settings):
"""
Convert array of parameters for simulations to new particle.
:param ns3_settings: Array of parameters for many simulations.
:return: Object of particle.
"""
return Particle(ns3_settings)
def convert_ns3_settings_array_to_particles_array(ns3_settings_array):
"""
Convert array of set of parameters for simulations to array of particles.
:param ns3_settings_array: Array of set of parameters for simulations.
:return: Array of particles.
"""
particles_array = []
for ns3_settings in ns3_settings_array:
particles_array.append(convert_ns3_settings_to_particle(ns3_settings['ns3Settings']))
return particles_array
async def main():
mempool_keys, memblock_keys = generate_simulations_memory_parameters()
simulationsNs3Params = []
for i in range(10):
ns3Settings = {
'ttlStart': random.uniform(1.0, 10.0),
'ttlIncrement': random.uniform(1.0, 10.0),
'ttlThreshold': random.uniform(1.0, 20.0),
'rreqRetries': random.uniform(1.0, 10.0),
'nodeTraversalTime': random.uniform(10.0, 1000.0),
'activeRouteTimeout': random.uniform(1.0, 10.0),
'netDiameter': random.uniform(10.0, 50.0),
'maxQueueLength': random.uniform(1.0, 10.0),
'allowedHelloLoss': random.uniform(1.0, 10.0),
'pathOfOutput': os.path.dirname(__file__) + '/../../simulation_output' + str(i) + '.json'
}
simulationsNs3Params.append(
{'mempool_key': mempool_keys[i], 'memblock_key': memblock_keys[i], 'ns3Settings': ns3Settings})
particles = []
for i in range(PARTICLES_COUNT):
params = {
'ttlStart': simulationsNs3Params[i]['ns3Settings']['ttlStart'],
'ttlIncrement': simulationsNs3Params[i]['ns3Settings']['ttlIncrement'],
'ttlThreshold': simulationsNs3Params[i]['ns3Settings']['ttlThreshold'],
'rreqRetries': simulationsNs3Params[i]['ns3Settings']['rreqRetries'],
'nodeTraversalTime': simulationsNs3Params[i]['ns3Settings']['nodeTraversalTime'],
'activeRouteTimeout': simulationsNs3Params[i]['ns3Settings']['activeRouteTimeout'],
'netDiameter': simulationsNs3Params[i]['ns3Settings']['netDiameter'],
'maxQueueLength': simulationsNs3Params[i]['ns3Settings']['maxQueueLength'],
'allowedHelloLoss': simulationsNs3Params[i]['ns3Settings']['allowedHelloLoss']
}
particle = Particle(params)
particles.append(particle)
pso = PSO(convert_ns3_settings_array_to_particles_array(simulationsNs3Params))
await pso.run()
asyncio.run(main())
Editor is loading...