From 18c9fa43c39ca31395fc5ca96d2544e098064930 Mon Sep 17 00:00:00 2001 From: KuMiShi Date: Thu, 15 Jan 2026 20:33:19 +0100 Subject: [PATCH] MOPSO transition --- mopso.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++------ particle.py | 32 ++++++--------------------- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/mopso.py b/mopso.py index 983d36e..39e672e 100644 --- a/mopso.py +++ b/mopso.py @@ -1,20 +1,28 @@ +import random as rd from .particle import Particle class MOPSO(): - def __init__(self, n, t, w, c1, c2, a_max, surrogate=False): + def __init__(self, f_weigths:list, A_max:float, price_mean:float, price_std:float, n:int, t:int, w:float, c1:float, c2:float, archive_size:int=10, nb_vehicles:int=10, delta_t:int=60, nb_of_ticks:int=72, x_min=-100, x_max=100, v_alpha=0.1, surrogate=False): # Constants self.n = n # Number of particles - self.t = t # Number of iterations + self.t = t # Number of simulation iterations self.w = w # Inertia (for exploration) self.c1 = c1 # Individual trust self.c2 = c2 # Social trust - self.a_max = a_max # Archive size + self.archive_size = archive_size # Archive size + self.f_weigths = f_weigths # Weigths for aggregation of all function objective self.surrogate = surrogate # Using AI calculation - self.particles = [] # Particles of the simulation - # Fonctions objectifs - # Limites variables de decision + # Initialisation of particle's global parameters + self.A_max = A_max # Network's power limit + self.socs, self.socs_req = self.generate_state_of_charges(nb_vehicles,nb_of_ticks) + self.times = self.generate_times(nb_vehicles, nb_of_ticks, delta_t) + self.prices = self.generates_prices(price_mean,price_std) #TODO: Use RTE France prices for random prices generation according to number of ticks + + # Particles of the simulation + self.particles = [Particle(times=self.times,nb_vehicles=nb_vehicles, nb_of_ticks=nb_of_ticks, delta_t=delta_t, x_min=x_min, x_max=x_max, alpha=v_alpha) for _ in range(self.n)] + self.archive = [] def iterate(self): nb_iter = 0 @@ -35,4 +43,45 @@ class MOPSO(): # Checking boundaries # Evaluating particles # Update the archive - # Checking for best positions \ No newline at end of file + # Checking for best positions + + # Generation of arriving and leaving times for every vehicle + def generate_times(self, nb_vehicles, nb_of_ticks, delta_t): + times = [] + for _ in range(nb_vehicles): + # Minumun, we have one tick of charging/discharging during simulation + t_arrived = rd.randrange(0, (nb_of_ticks * delta_t - delta_t) +1, delta_t) + t_leaving = rd.randrange(t_arrived + delta_t, (nb_of_ticks * delta_t) +1, delta_t) + times.append((t_arrived,t_leaving)) + return times + + # Genrates different prices in [mean - std, mean + std] range + def generates_prices(self,nb_of_ticks:int, mean:float, std:float): + prices = [] + for _ in range(nb_of_ticks): + variation = rd.randrange(-(std*10), (std * 10) +1, 1) / 10 # Random float variation + prices.append(mean + variation) + return prices + + # Genrates the coordinated states of charges requested and initial (duplicated initially for other ticks) + def generate_state_of_charges(self, nb_vehicles:int, nb_of_ticks:int): + socs = [] + socs_req = [] + # We ensure soc_req is greater than what the soc_init is (percentage transformed into floats) + for _ in range(nb_vehicles): + soc_init = rd.randrange(0,100,1) + soc_req = rd.randrange(soc_init+1, 101,1) + + # Creating states of charges for each tick in time + for _ in range(nb_of_ticks): + socs.append(soc_init/100) + + # Adding the requested state of charge + socs_req.append(soc_req/100) + return socs, socs_req + + # Random uniform selection for a leader + def select_leader(self): + n = len(self.archive) # Archive length + rd_pos = rd.randrange(0, n, 1) + return self.archive[rd_pos] \ No newline at end of file diff --git a/particle.py b/particle.py index d8d748f..f44d791 100644 --- a/particle.py +++ b/particle.py @@ -1,7 +1,7 @@ import random as rd class Particle(): - def __init__(self, nb_vehicles:int=10, delta_t:int=60, nb_of_ticks:int=72, a_min=-100, a_max=100, alpha=0.1): + def __init__(self, times:list, nb_vehicles:int=10, delta_t:int=60, nb_of_ticks:int=72, x_min=-100, x_max=100, alpha=0.1): # Problem specific attributes self.nb_vehicles = nb_vehicles # Number of vehicles handles for the generations of position x self.delta_t = delta_t # delta_t for update purposes @@ -9,12 +9,11 @@ class Particle(): self.socs= self.generate_state_of_charges() # States of charge (initial, requested) - #TODO: Move that to MOPSO (using one batch of times for multiples particles) - self.times = self.generate_times() # Times (arrived, leaving) + self.times = times # (arrived, leaving) # Minima and maxima of a position value - self.a_min = a_min - self.a_max = a_max + self.x_min = x_min + self.x_max = x_max # Limitation of the velocity self.alpha = alpha @@ -36,24 +35,6 @@ class Particle(): for i in range(self.nb_vehicles): new_vel_i = w * self.v[i] + (self.p_best - self.x[i]) * c1 * self.r1[i] + (leader - self.x[i]) * c2 * self.r2[i] self.v[i] = new_vel_i - - def generate_state_of_charges(self): - socs = [] - # We ensure soc_req is greater than what the soc_init is (percentage transformed into floats) - for _ in range(self.nb_vehicles): - soc_init = rd.randrange(0,100,1) - soc_req = rd.randrange(soc_init+1, 101,1) - socs.append((soc_init/100, soc_req/100)) - return socs - - def generate_times(self): - times = [] - for _ in range(self.nb_vehicles): - # Minumun, we have one tick of charging during simulation - t_arrived = rd.randrange(0, (self.nb_of_ticks * self.delta_t - self.delta_t) +1, self.delta_t) - t_leaving = rd.randrange(t_arrived + self.delta_t, (self.nb_of_ticks*self.delta_t)+1, self.delta_t) - times.append((t_arrived,t_leaving)) - return times #TODO: Modify for uses of ticks def generate_position(self): @@ -61,13 +42,14 @@ class Particle(): for _ in range(self.nb_of_ticks): x_tick = [] for _ in range(self.nb_vehicles): - x_tick.append(rd.randrange(self.a_min, self.a_max +1, 1)) + x_tick.append(rd.randrange(self.x_min, self.x_max +1, 1)) pos.append(x_tick) return pos + # Randomize a velocity vector for each tick def generate_velocity(self): vel = [] - vel_coeff = self.a_max - self.a_min + vel_coeff = abs(self.x_max - self.x_min) for _ in range(self.nb_of_ticks): v_tick = [] for _ in range(self.nb_vehicles):