From 8f4ae5bfeb599d071a17b87b53b61a14dcbe92f0 Mon Sep 17 00:00:00 2001 From: Prakash Shelokar Date: Wed, 15 Oct 2025 01:54:44 -0400 Subject: [PATCH 1/2] added random state arg in PSO for run results reproducibility. --- examples/demo_pso.py | 9 ++++++++- sko/PSO.py | 14 +++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/demo_pso.py b/examples/demo_pso.py index 8f055d9..213dd5c 100644 --- a/examples/demo_pso.py +++ b/examples/demo_pso.py @@ -1,3 +1,6 @@ +import sys + + def demo_func(x): x1, x2, x3 = x return x1 ** 2 + (x2 - 0.05) ** 2 + x3 ** 2 @@ -6,7 +9,11 @@ def demo_func(x): # %% Do PSO from sko.PSO import PSO -pso = PSO(func=demo_func, n_dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5) +#PSO without random_state +#pso = PSO(func=demo_func, n_dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5) + +#PSO with random_state +pso = PSO(func=demo_func, n_dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5, random_state=42) pso.run() print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y) diff --git a/sko/PSO.py b/sko/PSO.py index eb64112..79e87a2 100644 --- a/sko/PSO.py +++ b/sko/PSO.py @@ -4,6 +4,7 @@ # @Author : github.com/guofei9987 import numpy as np +from sklearn.utils.validation import check_random_state from sko.tools import func_transformer from .base import SkoBase from .operators import crossover, mutation, ranking, selection @@ -61,6 +62,8 @@ class PSO(SkoBase): equal constraint. Note: not available yet. constraint_ueq : tuple unequal constraint + random_state : int + Random seed for reproducibility n_processes : int Number of processes, 0 means use all cpu Attributes @@ -84,7 +87,7 @@ class PSO(SkoBase): def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0.8, c1=0.5, c2=0.5, constraint_eq=tuple(), constraint_ueq=tuple(), verbose=False - , dim=None, n_processes=0): + , dim=None, random_state=None, n_processes=0): n_dim = n_dim or dim # support the earlier version @@ -95,6 +98,7 @@ def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0. self.n_dim = n_dim # dimension of particles, which is the number of variables of func self.max_iter = max_iter # max iter self.verbose = verbose # print the result of each iter or not + self.random_state = check_random_state(random_state) # use a dedicated random_state for reproducibility of experiments self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' @@ -104,9 +108,9 @@ def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0. self.constraint_ueq = constraint_ueq self.is_feasible = np.array([True] * pop) - self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) + self.X = self.random_state.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) v_high = self.ub - self.lb - self.V = np.random.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles + self.V = self.random_state.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles self.Y = self.cal_y() # y = f(x) for all particles self.pbest_x = self.X.copy() # personal best location of every particle in history self.pbest_y = np.array([[np.inf]] * pop) # best image of every particle in history @@ -128,8 +132,8 @@ def check_constraint(self, x): return True def update_V(self): - r1 = np.random.rand(self.pop, self.n_dim) - r2 = np.random.rand(self.pop, self.n_dim) + r1 = self.random_state.rand(self.pop, self.n_dim) + r2 = self.random_state.rand(self.pop, self.n_dim) self.V = self.w * self.V + \ self.cp * r1 * (self.pbest_x - self.X) + \ self.cg * r2 * (self.gbest_x - self.X) From 3246cec23c6376d4bc4c62a27335700804bb5931 Mon Sep 17 00:00:00 2001 From: Prakash Shelokar Date: Wed, 15 Oct 2025 02:23:58 -0400 Subject: [PATCH 2/2] Revert "added random state arg in PSO for run results reproducibility." This reverts commit 8f4ae5bfeb599d071a17b87b53b61a14dcbe92f0. --- examples/demo_pso.py | 9 +-------- sko/PSO.py | 14 +++++--------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/examples/demo_pso.py b/examples/demo_pso.py index 213dd5c..8f055d9 100644 --- a/examples/demo_pso.py +++ b/examples/demo_pso.py @@ -1,6 +1,3 @@ -import sys - - def demo_func(x): x1, x2, x3 = x return x1 ** 2 + (x2 - 0.05) ** 2 + x3 ** 2 @@ -9,11 +6,7 @@ def demo_func(x): # %% Do PSO from sko.PSO import PSO -#PSO without random_state -#pso = PSO(func=demo_func, n_dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5) - -#PSO with random_state -pso = PSO(func=demo_func, n_dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5, random_state=42) +pso = PSO(func=demo_func, n_dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5) pso.run() print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y) diff --git a/sko/PSO.py b/sko/PSO.py index 79e87a2..eb64112 100644 --- a/sko/PSO.py +++ b/sko/PSO.py @@ -4,7 +4,6 @@ # @Author : github.com/guofei9987 import numpy as np -from sklearn.utils.validation import check_random_state from sko.tools import func_transformer from .base import SkoBase from .operators import crossover, mutation, ranking, selection @@ -62,8 +61,6 @@ class PSO(SkoBase): equal constraint. Note: not available yet. constraint_ueq : tuple unequal constraint - random_state : int - Random seed for reproducibility n_processes : int Number of processes, 0 means use all cpu Attributes @@ -87,7 +84,7 @@ class PSO(SkoBase): def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0.8, c1=0.5, c2=0.5, constraint_eq=tuple(), constraint_ueq=tuple(), verbose=False - , dim=None, random_state=None, n_processes=0): + , dim=None, n_processes=0): n_dim = n_dim or dim # support the earlier version @@ -98,7 +95,6 @@ def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0. self.n_dim = n_dim # dimension of particles, which is the number of variables of func self.max_iter = max_iter # max iter self.verbose = verbose # print the result of each iter or not - self.random_state = check_random_state(random_state) # use a dedicated random_state for reproducibility of experiments self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' @@ -108,9 +104,9 @@ def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0. self.constraint_ueq = constraint_ueq self.is_feasible = np.array([True] * pop) - self.X = self.random_state.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) + self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) v_high = self.ub - self.lb - self.V = self.random_state.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles + self.V = np.random.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles self.Y = self.cal_y() # y = f(x) for all particles self.pbest_x = self.X.copy() # personal best location of every particle in history self.pbest_y = np.array([[np.inf]] * pop) # best image of every particle in history @@ -132,8 +128,8 @@ def check_constraint(self, x): return True def update_V(self): - r1 = self.random_state.rand(self.pop, self.n_dim) - r2 = self.random_state.rand(self.pop, self.n_dim) + r1 = np.random.rand(self.pop, self.n_dim) + r2 = np.random.rand(self.pop, self.n_dim) self.V = self.w * self.V + \ self.cp * r1 * (self.pbest_x - self.X) + \ self.cg * r2 * (self.gbest_x - self.X)