Skip to content

Commit

Permalink
GA: fix a bug in the integer mode, a new algorithm in a way. version …
Browse files Browse the repository at this point in the history
…0.5.7. #32 #37 #59
  • Loading branch information
guofei9987 committed Jun 8, 2020
1 parent 9884eff commit 1716709
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 23 deletions.
8 changes: 4 additions & 4 deletions docs/en/more_ga.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ print('best_x:', best_x, '\n', 'best_y:', best_y)
```

Notice:
- if `precision` is an integer, and the number of all possible value is $2^n$, the performance is best
- if `precision` is an integer, and the number of all possible value is not $2^n$, `GA` do these:
- If `precision` is an integer, the number of all possible value would better be $2^n$, in which case the performance is the best. It also works if the number is not $2^n$
<!-- - if `precision` is an integer, and the number of all possible value is not $2^n$, `GA` do these:
1. Modify `ub` bigger, making the number of all possible value to be $2^n$
2. Add an **unequal constraint**, and use penalty function to deal with it
3. If your **equal constraint** `constraint_eq`**unequal constraint** `constraint_ueq` is too much, the performance is not too good. you may want to manually deal with it.
3. If your **equal constraint** `constraint_eq` 和 **unequal constraint** `constraint_ueq` is too much, the performance is not too good. you may want to manually deal with it. -->
- If `precision` is not an integer, but you still want this mode, manually deal with it. For example, your original `precision=0.5`, just make a new variable, multiplied by `2`


Expand Down Expand Up @@ -49,7 +49,7 @@ def cal_total_distance(routine):
cal_total_distance(np.arange(num_points))
'''
num_points, = routine.shape
routine = np.concatenate([[num_points],routine,[num_points+1]])
routine = np.concatenate([[num_points], routine, [num_points+1]])
return sum([distance_matrix[routine[i], routine[i + 1]] for i in range(num_points+2-1)])
```

Expand Down
12 changes: 6 additions & 6 deletions docs/zh/more_ga.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ print('best_x:', best_x, '\n', 'best_y:', best_y)
```

说明:
-`precision` 为整数时,会启用整数规划模式
- 在整数规划模式下,如果某个变量的取值可能个数是 $2^n$,不会对性能有影响
- 在整数规划模式下,如果某个变量的取值可能个数不是 $2^n$,`GA` 会做这些事:
-`precision` 为整数时,对应的自变量会启用整数规划模式
- 在整数规划模式下,变量的取值可能个数最好是 $2^n$,这样收敛速度快,效果好。
<!-- - 在整数规划模式下,如果某个变量的取值可能个数不是 $2^n$,`GA` 会做这些事:
1. 调整 `ub`,使得可能取值扩展成 $2^n$ 个
2. 增加一个 **不等式约束** `constraint_ueq`,并使用罚函数法来处理
3. 如果你的 **等式约束** `constraint_eq`**不等式约束** `constraint_ueq` 已经很多了,更加推荐先手动做调整,以规避可能个数不是 $2^n$这种情况,毕竟太多的约束会影响性能。
3. 如果你的 **等式约束** `constraint_eq` 和 **不等式约束** `constraint_ueq` 已经很多了,更加推荐先手动做调整,以规避可能个数不是 $2^n$这种情况,毕竟太多的约束会影响性能。 -->
- 如果 `precision` 不是整数(例如是0.5),则不会进入整数规划模式,如果还想用这个模式,那么把对应自变量乘以2,这样 `precision` 就是整数了。

## 遗传TSP问题如何固定起点和终点?
Expand Down Expand Up @@ -50,7 +50,7 @@ def cal_total_distance(routine):
'''
num_points, = routine.shape
# start_point,end_point 本身不参与优化。给一个固定的值,参与计算总路径
routine=np.concatenate([[num_points],routine,[num_points+1]])
routine = np.concatenate([[num_points], routine, [num_points+1]])
return sum([distance_matrix[routine[i], routine[i + 1]] for i in range(num_points+2-1)])
```

Expand All @@ -76,7 +76,7 @@ plt.show()

## 如何设定初始点或初始种群

- 对于遗传算法 `GA`, 运行 `ga=GA(**params)` 生成模型后,赋值设定初始种群,例如 `ga.Chrom = np.random.randint(0,2,size=(80,20))`
- 对于遗传算法 `GA`, 运行 `ga=GA(**params)` 生成模型后,赋值设定初始种群,例如 `ga.Chrom = np.random.randint(0,2,size=(80,20))`
- 对于查分进化算法 `DE`,设定 `de.X` 为初始 X.

This comment has been minimized.

Copy link
@PlanetesDDH

PlanetesDDH Jul 3, 2020

查分→差分

- 对于模拟退火算法 `SA`,入参 `x0` 就是初始点.
- 对于粒子群算法 `PSO`,手动赋值 `pso.X` 为初始 X, 然后执行 `pso.cal_y(); pso.update_gbest(); pso.update_pbest()` 来更新历史最优点
33 changes: 21 additions & 12 deletions sko/GA.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,16 +150,13 @@ def __init__(self, func, n_dim,

# if precision is integer:
# if Lind_raw is integer, which means the number of all possible value is 2**n, no need to modify
# if Lind_raw is decimal, modify: make the ub bigger and add a constraint_ueq
int_mode = (self.precision % 1 == 0) & (Lind_raw % 1 != 0)
# int_mode is an array of True/False. If True, variable is int constraint and need more code to deal with
for i in range(self.n_dim):
if int_mode[i]:
self.constraint_ueq.append(
lambda x: x[i] - self.ub[i]
)
self.has_constraint = True
self.ub[i] = self.lb[i] + np.exp2(self.Lind[i]) - 1
# if Lind_raw is decimal, we need ub_extend to make the number equal to 2**n,
self.int_mode_ = (self.precision % 1 == 0) & (Lind_raw % 1 != 0)
self.int_mode = np.any(self.int_mode_)
if self.int_mode:
self.ub_extend = np.where(self.int_mode_
, self.lb + (np.exp2(self.Lind) - 1) * self.precision
, self.ub)

self.len_chrom = sum(self.Lind)

Expand Down Expand Up @@ -188,7 +185,14 @@ def chrom2x(self, Chrom):
else:
Chrom_temp = Chrom[:, cumsum_len_segment[i - 1]:cumsum_len_segment[i]]
X[:, i] = self.gray2rv(Chrom_temp)
X = self.lb + (self.ub - self.lb) * X

if self.int_mode:
X = self.lb + (self.ub_extend - self.lb) * X
X = np.where(X > self.ub, self.ub, X)
# the ub may not obey precision, which is ok.
# for example, if precision=2, lb=0, ub=5, then x can be 5
else:
X = self.lb + (self.ub - self.lb) * X
return X

ranking = ranking.ranking
Expand Down Expand Up @@ -224,7 +228,12 @@ def chrom2x(self, Chrom):
else:
Chrom_temp = Chrom[:, cumsum_len_segment[i - 1]:cumsum_len_segment[i]]
X[:, i] = self.gray2rv(Chrom_temp)
X = self.lb + (self.ub - self.lb) * X

if self.int_mode:
X = self.lb + (self.ub_extend - self.lb) * X
X = np.where(X > self.ub, self.ub, X)
else:
X = self.lb + (self.ub - self.lb) * X
return X

self.register('mutation', mutation_gpu.mutation). \
Expand Down
2 changes: 1 addition & 1 deletion sko/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.5.6'
__version__ = '0.5.7'


def start():
Expand Down

0 comments on commit 1716709

Please sign in to comment.