scikit-opt icon indicating copy to clipboard operation
scikit-opt copied to clipboard

为什么用粒子群算法做的等式约束不能实现?

Open masker-can opened this issue 4 years ago • 5 comments

constraint_eq_2 = [ lambda x: x[4] - 0.624510, lambda x: x[6] - 0.117594, lambda x: x[8] - 0.828125, lambda x: x[9] - 0.391045]

constraint_ueq_2 = [ lambda x: 0-svr.predict(np.array(x).reshape(1,13)), lambda x: x[12] - 0.209, lambda x: 0 - x[12], lambda x: svr.predict(np.array(x).reshape(1,13)) - 0.7*svr.predict(np.array(data_12_x_nor.iloc[0,:]).reshape(1,13)), lambda x: 0 - np.min(x), lambda x: np.max(x) - 0.865692441322172 ] from sko.PSO import PSO pso = PSO(func=func_2, n_dim=13, pop=40, max_iter=15, lb=[0, 0, 0,0,0,0,0,0,0,0,0,0,0], ub=[1, 1, 1,1,1,1,1,1,1,1,1,1,1], w=0.8, c1=0.5, c2=0.5,constraint_eq=constraint_eq_2, constraint_ueq=constraint_ueq_2) pso.run() print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y)

结果: best_x is [0.26858353 0.18923076 0.21069997 0.83421386 0.24298983 0.24772933 0.34677789 0.47642962 0.37834972 0.15027168 0.75211158 0.21605726 0.17657801] best_y is [-0.99187476]

masker-can avatar Aug 24 '21 11:08 masker-can

  1. 其实粒子群的不等式约束实现也有问题,源代码中直接让不符合constrain的粒子不更新了,这样写是完全错误的,这样会导致符合要求的粒子越来越少。正确的写法是采用外罚函数法或者内罚函数法添加一个惩罚因子让粒子逼近约束条件边界。
  2. 等式约束和不等式约束有比较大的差异,虽然可以通过外罚函数法也添加一个等式约束罚因子(注意,内罚函数法是不能添加等式约束的),但在粒子群中这个方法似乎并不奏效。我试过,然而因为粒子群优化的问题大部分都是非凸的,每次有等式约束时收敛的最优解都相差较大(虽然是近似满足等式约束的,但仍然不太理想),所以建议不要在粒子群中使用等式约束,能替换变量就替换变量,实在不行就把等式约束变为不等式约束(|y-yr|<=tol的格式)

gitouni avatar Sep 26 '21 16:09 gitouni

  1. 其实粒子群的不等式约束实现也有问题,源代码中直接让不符合constrain的粒子不更新了,这样写是完全错误的,这样会导致符合要求的粒子越来越少。正确的写法是采用外罚函数法或者内罚函数法添加一个惩罚因子让粒子逼近约束条件边界。
  2. 等式约束和不等式约束有比较大的差异,虽然可以通过外罚函数法也添加一个等式约束罚因子(注意,内罚函数法是不能添加等式约束的),但在粒子群中这个方法似乎并不奏效。我试过,然而因为粒子群优化的问题大部分都是非凸的,每次有等式约束时收敛的最优解都相差较大(虽然是近似满足等式约束的,但仍然不太理想),所以建议不要在粒子群中使用等式约束,能替换变量就替换变量,实在不行就把等式约束变为不等式约束(|y-yr|<=tol的格式)

如果指的是 https://github.com/guofei9987/scikit-opt/blob/037d23fe628f981c2c2b68dc65e5ff629bbee78a/sko/PSO.py#L150 这一行的话,它是把不符合约束的粒子位置记录到 pbest,粒子本身的位置还是会更新的

guofei9987 avatar Sep 27 '21 11:09 guofei9987

  1. 其实粒子群的不等式约束实现也有问题,源代码中直接让不符合constrain的粒子不更新了,这样写是完全错误的,这样会导致符合要求的粒子越来越少。正确的写法是采用外罚函数法或者内罚函数法添加一个惩罚因子让粒子逼近约束条件边界。
  2. 等式约束和不等式约束有比较大的差异,虽然可以通过外罚函数法也添加一个等式约束罚因子(注意,内罚函数法是不能添加等式约束的),但在粒子群中这个方法似乎并不奏效。我试过,然而因为粒子群优化的问题大部分都是非凸的,每次有等式约束时收敛的最优解都相差较大(虽然是近似满足等式约束的,但仍然不太理想),所以建议不要在粒子群中使用等式约束,能替换变量就替换变量,实在不行就把等式约束变为不等式约束(|y-yr|<=tol的格式)

如果指的是

https://github.com/guofei9987/scikit-opt/blob/037d23fe628f981c2c2b68dc65e5ff629bbee78a/sko/PSO.py#L150

这一行的话,它是把不符合约束的粒子位置记录到 pbest,粒子本身的位置还是会更新的

如果仔细看代码就会发现,这个check_constriant对于不符合要求约束的粒子会返回False,符合的才会返回True,而更新的时候使用了np.where函数做选择,符合要求的地方设置原来的值,否则就设为定值pbest,强行设为pbest会导致粒子重合,搜索能力就会大幅度下降。

gitouni avatar Sep 27 '21 12:09 gitouni

  1. 其实粒子群的不等式约束实现也有问题,源代码中直接让不符合constrain的粒子不更新了,这样写是完全错误的,这样会导致符合要求的粒子越来越少。正确的写法是采用外罚函数法或者内罚函数法添加一个惩罚因子让粒子逼近约束条件边界。
  2. 等式约束和不等式约束有比较大的差异,虽然可以通过外罚函数法也添加一个等式约束罚因子(注意,内罚函数法是不能添加等式约束的),但在粒子群中这个方法似乎并不奏效。我试过,然而因为粒子群优化的问题大部分都是非凸的,每次有等式约束时收敛的最优解都相差较大(虽然是近似满足等式约束的,但仍然不太理想),所以建议不要在粒子群中使用等式约束,能替换变量就替换变量,实在不行就把等式约束变为不等式约束(|y-yr|<=tol的格式)

如果指的是 https://github.com/guofei9987/scikit-opt/blob/037d23fe628f981c2c2b68dc65e5ff629bbee78a/sko/PSO.py#L150

这一行的话,它是把不符合约束的粒子位置记录到 pbest,粒子本身的位置还是会更新的

如果仔细看代码就会发现,这个check_constriant对于不符合要求约束的粒子会返回False,符合的才会返回True,而更新的时候使用了np.where函数做选择,符合要求的地方设置原来的值,否则就设为定值pbest,强行设为pbest会导致粒子重合,搜索能力就会大幅度下降。

https://github.com/guofei9987/scikit-opt/blob/037d23fe628f981c2c2b68dc65e5ff629bbee78a/sko/PSO.py#L152

更新的是 pbest,不是 X.
X 才是 粒子的位置,pbest 是粒子的历史最佳位置。

如有其它相关资料,欢迎贴出来

guofei9987 avatar Sep 29 '21 03:09 guofei9987

等式约束是还没实现吗?因为看到constraint_eq : tuple,equal constraint. Note: not available yet.

zhaozirun avatar Nov 24 '22 03:11 zhaozirun