1. シミュレーテッド アニーリング アルゴリズム
シミュレーテッド アニーリング アルゴリズムはグローバルな最適化アルゴリズムであり、通常、特定の関数を最小化 (または最大化) するグローバルな最適解を見つけることが解決される問題です。物理的アニーリングのプロセスをシミュレートして解空間を探索します. 最初はある温度でランダムに初期解を生成し, その後温度を徐々に下げていきます. 同時に, 新しい解を周囲にランダムに探索します.ある確率で悪い方を受け入れることで、局所最適解から飛び出し、最終的に大域最適解を得ることができます。
以下の簡単な例を見てみましょう. 目的関数 f(x,y)=sin(10x)+cos(3y) の大域的最小値を解きたいとすると、 −2≤x≤2, −1≤ を取ります検索範囲として y≤ 1。これは、次のコードで実行できます。
import math
import random
# 定义目标函数
def objective_function(x, y):
return math.sin(10*x) + math.cos(3*y)
# 定义模拟退火算法
def simulated_annealing(initial_temperature, cooling_rate, num_iterations):
# 设置初始解和初始温度
current_solution = [random.uniform(-2, 2), random.uniform(-1, 1)]
current_energy = objective_function(current_solution[0], current_solution[1])
current_temperature = initial_temperature
# 迭代固定次数
for i in range(num_iterations):
# 根据当前温度随机生成新的解
new_solution = [current_solution[0] + 0.1*random.uniform(-1, 1),
current_solution[1] + 0.1*random.uniform(-1, 1)]
new_energy = objective_function(new_solution[0], new_solution[1])
# 计算能量差
delta_energy = new_energy - current_energy
# 如果新解更优,则接受它
if delta_energy < 0:
current_solution = new_solution
current_energy = new_energy
# 否则以一定概率接受更差的解
else:
probability = math.exp(-delta_energy / current_temperature)
if random.uniform(0, 1) < probability:
current_solution = new_solution
current_energy = new_energy
# 降低温度
current_temperature *= cooling_rate
return current_solution, current_energy
# 设置初始温度、冷却速率和迭代次数
initial_temperature = 100
cooling_rate = 0.95
num_iterations = 1000
# 运行模拟退火算法
best_solution, best_energy = simulated_annealing(initial_temperature, cooling_rate, num_iterations)
# 输出结果
print("全局最优解:", best_solution)
print("全局最优值:", best_energy)
この例では、objective_function
関数目的関数を定義しました。次に、シミュレーテッド アニーリング アルゴリズムのコア部分を実現するsimulated_annealing
関数。ここで、パラメーターはinitial_temperature
初期温度を表し、cooling_rate
反復ごとの温度低下の比率を表し、num_iterations
反復回数を表します。simulated_annealing
関数では、現在の温度とエネルギー差を使用して、新しい解を受け入れるかどうか、および新しい解が不十分な場合に受け入れるかどうかを決定します. これらは、シミュレーテッド アニーリング アルゴリズムのコア ステップです.
最後に、初期温度、冷却速度、反復回数を設定し、シミュレーテッド アニーリング アルゴリズムを実行するsimulated_annealing
関数大域最適解と最適値を取得し、コンソールに出力します。複数の実行にわたってパラメータを調整して、より正確な結果を得ることができます。
2. 遺伝的アルゴリズム
目的関数が複数ある場合は、多目的関数最適化アルゴリズムを使用できます。より一般的に使用されるアルゴリズムの 1 つは NSGA-II (Non-dominated Sorting Genetic Algorithm II) です。これは、遺伝的アルゴリズムを使用して多目的最適化問題を解決するアルゴリズムです。
NSGA-II アルゴリズムの核となる考え方は、パレート フロントを維持することによって非優越解を見つけ、次にこれらの解に対して選択操作と交差操作を実行して、次世代の母集団を生成することです。具体的な手順は次のとおりです。
- 母集団を初期化し、各個体の適応度、パレート順位、密集距離を計算します。
- パレートソートを実行し、パレートレベルに従って母集団内のすべての個体を小さいものから大きいものにソートし、次に同じレベルの個体を密集距離に従って大きいものから小さいものにソートします。
- 優良個体の一部を親として選択し、交叉・突然変異操作を行って次世代個体群を生成します。
- 停止条件が満たされるまで、上記の手順を繰り返します。
以下は、Python を使用して NSGA-II アルゴリズムを実装し、多目的問題を解決するサンプル コードです。
import random
import copy
# 定义目标函数
def objective_function(population):
fitness = []
for x in population:
obj_1 = pow(x[0], 2)
obj_2 = pow(x[0]-2, 2) + pow(x[1], 2)
# 将两个目标函数值合并成一个列表
fitness.append([obj_1, obj_2])
return fitness
# 定义帕累托排序
def pareto_ranking(fitness):
n = len(fitness)
p = []
rank = [0] * n
S = [[] for i in range(n)]
F = [[] for i in range(n+1)]
for i in range(n):
S[i] = []
rank[i] = 0
for j in range(n):
if i != j:
if fitness[i][0] <= fitness[j][0] and fitness[i][1] <= fitness[j][1]:
if j not in S[i]:
S[i].append(j)
elif fitness[j][0] <= fitness[i][0] and fitness[j][1] <= fitness[i][1]:
rank[i] += 1
if rank[i] == 0:
F[0].append(i)
i = 0
while len(F[i]) > 0:
Q = []
for j in range(len(F[i])):
p_j = F[i][j]
for k in range(len(S[p_j])):
q = S[p_j][k]
rank[q] -= 1
if rank[q] == 0:
Q.append(q)
i += 1
F[i] = copy.deepcopy(Q)
del F[len(F)-1]
for f in F:
for x in f:
p.append(x)
return p
# 定义拥挤距离
def crowding_distance(fitness, indices):
n = len(indices)
distance = [0.0] * n
for m in range(2):
sorted_indices = sorted(indices, key=lambda x:fitness[x][m])
distance[sorted_indices[0]] = float('inf')
distance[sorted_indices[n-1]] = float('inf')
for i in range(1, n-1):
distance[sorted_indices[i]] += (fitness[sorted_indices[i+1]][m] - fitness[sorted_indices[i-1]][m])
return distance
# 定义选择操作
def selection(population, fitness, num_parents):
parents = []
n = len(population)
indices = [i for i in range(n)]
for i in range(num_parents):
front = pareto_ranking(fitness)
distance = crowding_distance(fitness, front)
max_distance_index = indices[front[distance.index(max(distance))]]
parents.append(population[max_distance_index])
indices.remove(max_distance_index)
return parents
# 定义交叉和变异操作
def crossover(parents, offspring_size):
offspring = []
for i in range(offspring_size):
parent_1 = random.choice(parents)
parent_2 = random.choice(parents)
child = [parent_1[j] if random.random() < 0.5 else parent_2[j]
for j in range(len(parent_1))]
offspring.append(child)
return offspring
def mutation(offspring_crossover):
for i in range(len(offspring_crossover)):
if random.random() < 0.1:
offspring_crossover[i][0] += random.uniform(-0.5, 0.5)
if random.random() < 0.1:
offspring_crossover[i][1] += random.uniform(-0.5, 0.5)
return offspring_crossover
# 设置算法参数
num_generations = 50
population_size = 100
num_parents = 20
offspring_size = population_size - num_parents
# 初始化种群
population = [[random.uniform(-5, 5), random.uniform(-5, 5)] for i in range(population_size)]
for i in range(num_generations):
# 计算适应度值和帕累托等级
fitness = objective_function(population)
# 选择操作
parents = selection(population, fitness, num_parents)
# 交叉操作
offspring_crossover = crossover(parents, offspring_size)
# 变异操作
offspring_mutation = mutation(offspring_crossover)
# 将父代和后代合并成一个种群
population = parents + offspring_mutation
# 输出当前最优解
best_individual_index = pareto_ranking(fitness)[0]
print("Generation ", i+1, ": Most optimal solution is ", population[best_individual_index])
# 输出所有 Pareto 最优解
pareto_front = pareto_ranking(fitness)
print("\nPareto front:")
for i in pareto_front:
print(population[i], objective_function([population[i]])[0])
この例では、まだ Python を使用して、2 つの目的関数を持つ多目的問題を実装しています。まず、母集団を取り、各個体に対して 2 つの目的関数値を返すobjective_function
関数。次に、pareto_ranking
関数crowding_distance
パレート ランクと混雑距離を計算します。このうち、pareto_ranking
関数を使用して母集団をパレート ソートし、各個体のパレート レベルを取得し、crowding_distance
関数を使用して各個体の密集距離を計算します。最後に、 functions 、 functions 、およびfunctionsselection
を定義して、遺伝的アルゴリズムの一般的な操作である選択、交差、および突然変異操作を実行します。crossover
mutation
メイン関数では、上記の関数を使用して NSGA-II アルゴリズムを実装し、母集団のパレート フロントを使用してすべての実行可能な解を出力します。人口サイズ、反復回数などのパラメーターを変更することで、アルゴリズムを調整できます。
3.違いとつながり
シミュレーテッド アニーリング (SA) と NSGA-II 遺伝的アルゴリズム (非優性ソート遺伝的アルゴリズム II) は 2 つの異なる最適化アルゴリズムであり、次のような違いがあります。
アルゴリズムが違う
SA アルゴリズムは、シミュレートされた固体のアニーリング プロセスに基づくヒューリスティック ランダム検索アルゴリズムであり、下位の解を受け入れる確率の下で、グローバルな最適解に徐々に近づくことができます。NSGA-II アルゴリズムは、パレート フロントを維持して非優性解を見つけることにより、主に多目的最適化問題用の多目的遺伝的アルゴリズムです。
さまざまなアプリケーション シナリオ
SA アルゴリズムは、特に探索空間が小さい場合や明確な解析解がない場合に、単一目的の最適化問題の大域的な最適解を求めるのに適しています。NSGA-II アルゴリズムは、複数の目的関数を同時に処理し、パレート フロンティアで一連のパレート最適解を生成できる多目的最適化問題を対象としています。
さまざまな最適化方法
SA アルゴリズムは、温度を変化させることで劣悪な解を受け入れる確率を制御するという目的を達成すると同時に、グローバル スコープで解空間を検索するために、局所最適解から飛び出すことを可能にします。NSGA-II アルゴリズムは、主に選択、交叉、突然変異などの操作によって次世代集団を生成し、パレート ソーティングによってパレート最適解を維持します。
アルゴリズムの複雑さはさまざま
SA アルゴリズムの時間の複雑さは温度降下率に関連しており、複雑さは通常は低くなりますが、大域的な最適解に収束するには多数の反復が必要になる場合があります。NSGA-II アルゴリズムの時間計算量は、主に人口サイズや次世代人口を生成する操作などの要因に影響され、通常は SA アルゴリズムよりも複雑です。
一般に、シミュレーテッド アニーリング アルゴリズムと NSGA-II 遺伝的アルゴリズムは比較的一般的な最適化アルゴリズムであり、適用可能な問題の種類と検索戦略は異なり、特定の状況に応じて適切なアルゴリズムを選択できます。