- 算法设计与分析
- 家
- 算法基础知识
- DAA - 简介
- DAA - 算法分析
- DAA-分析方法
- 渐近符号和先验分析
- 时间复杂度
- 马斯特定理
- DAA - 空间复杂性
- 分而治之
- DAA-分而治之
- DAA - 最大最小问题
- DAA-归并排序
- DAA-二分查找
- 施特拉森矩阵乘法
- 唐叶算法
- 河内塔
- 贪心算法
- DAA-贪婪法
- 旅行商问题
- Prim 的最小生成树
- 克鲁斯卡尔的最小生成树
- Dijkstra 的最短路径算法
- 地图着色算法
- DAA-分数背包
- DAA - 带截止日期的作业排序
- DAA - 最佳合并模式
- 动态规划
- DAA-动态规划
- 矩阵链乘法
- 弗洛伊德·沃歇尔算法
- DAA - 0-1 背包
- 最长公共子序列
- 旅行商问题| 动态规划
- 随机算法
- 随机算法
- 随机快速排序
- 卡格的最低削减
- 费舍尔-耶茨洗牌
- 近似算法
- 近似算法
- 顶点覆盖问题
- 设置封面问题
- 旅行推销员近似算法
- 排序技巧
- DAA-快速排序
- DAA-冒泡排序
- DAA——插入排序
- DAA-选择排序
- DAA——希尔排序
- DAA-堆排序
- DAA——桶排序
- DAA——计数排序
- DAA - 基数排序
- 搜索技巧
- 搜索技术介绍
- DAA - 线性搜索
- DAA-二分查找
- DAA - 插值搜索
- DAA - 跳转搜索
- DAA - 指数搜索
- DAA - 斐波那契搜索
- DAA - 子列表搜索
- DAA-哈希表
- 图论
- DAA-最短路径
- DAA - 多级图
- 最优成本二叉搜索树
- 堆算法
- DAA-二叉堆
- DAA-插入法
- DAA-Heapify 方法
- DAA-提取方法
- 复杂性理论
- 确定性计算与非确定性计算
- DAA-最大派系
- DAA - 顶点覆盖
- DAA - P 级和 NP 级
- DAA-库克定理
- NP 硬课程和 NP 完全课程
- DAA - 爬山算法
- DAA 有用资源
- DAA - 快速指南
- DAA - 有用的资源
- DAA - 讨论
爬山算法设计与分析
前面几章讨论的算法是系统运行的。为了实现这一目标,需要存储一条或多条先前探索的解决方案路径,以找到最佳解决方案。
对于许多问题来说,实现目标的路径是无关紧要的。例如,在N皇后问题中,我们不需要关心皇后的最终配置以及皇后添加的顺序。
爬山
爬山是一种解决某些优化问题的技术。在这种技术中,我们从次优解决方案开始,并反复改进该解决方案,直到某个条件最大化。
从次优解决方案开始的想法与从山脚开始相比,改进解决方案与步行上山相比,最后最大化某些条件与到达山顶相比。
因此,爬山技术可以被视为以下阶段 -
- 构造服从问题约束的次优解
- 逐步改进解决方案
- 改进解决方案,直到无法再改进为止
爬山技术主要用于解决计算难题。它只关注当前状态和近期的未来状态。因此,该技术具有内存效率,因为它不维护搜索树。
Algorithm: Hill Climbing Evaluate the initial state. Loop until a solution is found or there are no new operators left to be applied: - Select and apply a new operator - Evaluate the new state: goal -→ quit better than current state -→ new current state
迭代改进
在迭代改进方法中,最优解是通过在每次迭代中向最优解前进来实现的。然而,该技术可能会遇到局部最大值。在这种情况下,附近没有更好的解决方案。
这个问题可以通过不同的方法来避免。这些方法之一是模拟退火。
随机重启
这是解决局部最优问题的另一种方法。该技术进行一系列搜索。每次,它都从随机生成的初始状态开始。因此,比较所执行的搜索的解决方案可以获得最佳或接近最佳的解决方案。
爬山技术存在的问题
局部极大值
如果启发式不是凸的,爬山法可能会收敛到局部最大值,而不是全局最大值。
山脊和小巷
如果目标函数创建了一个狭窄的山脊,那么登山者只能通过之字形爬上山脊或下山。在这种情况下,登山者需要采取非常小的步骤,需要更多的时间才能到达目标。
高原
当搜索空间平坦或足够平坦以至于目标函数返回的值与附近区域返回的值无法区分时,就会遇到平台期,这是由于机器用来表示其值的精度所致。
爬山技术的复杂性
该技术不会遇到与空间相关的问题,因为它只查看当前状态。以前探索过的路径不会被存储。
对于随机重启爬山技术中的大多数问题,可以在多项式时间内获得最优解。然而,对于 NP 完全问题,计算时间可以根据局部最大值的数量呈指数增长。
爬山技术的应用
爬山技术可用于解决许多问题,其中当前状态允许精确的评估函数,例如网络流、旅行商问题、8皇后问题、集成电路设计等。
爬山法也用于归纳学习方法。该技术用于机器人技术,用于团队中多个机器人之间的协调。使用该技术还存在许多其他问题。
例子
该技术可用于解决旅行商问题。首先确定一个初始解决方案,即访问所有城市一次。因此,这个初始解决方案在大多数情况下都不是最佳的。即使这个解决方案也可能非常糟糕。爬山算法从这样的初始解开始,并以迭代的方式对其进行改进。最终,可能会获得更短的路线。
例子
#include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM_CITIES 4 // Distance matrix representing distances between cities // Replace this with the actual distance matrix for your problem int distance_matrix[NUM_CITIES][NUM_CITIES] = { {0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0} }; int total_distance(int* path, int num_cities) { // Calculate the total distance traveled in the given path int total = 0; for (int i = 0; i < num_cities - 1; i++) { total += distance_matrix[path[i]][path[i + 1]]; } total += distance_matrix[path[num_cities - 1]][path[0]]; // Return to starting city return total; } void hill_climbing_tsp(int num_cities, int max_iterations) { int current_path[NUM_CITIES]; // Initial solution, visiting cities in order for (int i = 0; i < num_cities; i++) { current_path[i] = i; } int current_distance = total_distance(current_path, num_cities); for (int it = 0; it < max_iterations; it++) { // Generate a neighboring solution by swapping two random cities int neighbor_path[NUM_CITIES]; for (int i = 0; i < num_cities; i++) { neighbor_path[i] = current_path[i]; } int i = rand() % num_cities; int j = rand() % num_cities; int temp = neighbor_path[i]; neighbor_path[i] = neighbor_path[j]; neighbor_path[j] = temp; int neighbor_distance = total_distance(neighbor_path, num_cities); // If the neighbor solution is better, move to it if (neighbor_distance < current_distance) { for (int i = 0; i < num_cities; i++) { current_path[i] = neighbor_path[i]; } current_distance = neighbor_distance; } } printf("Optimal path: "); for (int i = 0; i < num_cities; i++) { printf("%d ", current_path[i]); } printf("\nTotal distance: %d\n", current_distance); } int main() { srand(time(NULL)); int max_iterations = 10000; hill_climbing_tsp(NUM_CITIES, max_iterations); return 0; }
输出
Optimal path: 1 0 2 3 Total distance: 80
#include <iostream> #include <vector> #include <algorithm> #include <ctime> #include <cstdlib> #define NUM_CITIES 4 // Distance matrix representing distances between cities // Replace this with the actual distance matrix for your problem int distance_matrix[NUM_CITIES][NUM_CITIES] = { {0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0} }; int total_distance(const std::vector<int>& path) { // Calculate the total distance traveled in the given path int total = 0; for (size_t i = 0; i < path.size() - 1; i++) { total += distance_matrix[path[i]][path[i + 1]]; } total += distance_matrix[path.back()][path[0]]; // Return to starting city return total; } void hill_climbing_tsp(int num_cities, int max_iterations) { std::vector<int> current_path(num_cities); // Initial solution, visiting cities in order for (int i = 0; i < num_cities; i++) { current_path[i] = i; } int current_distance = total_distance(current_path); for (int it = 0; it < max_iterations; it++) { // Generate a neighboring solution by swapping two random cities std::vector<int> neighbor_path = current_path; int i = rand() % num_cities; int j = rand() % num_cities; std::swap(neighbor_path[i], neighbor_path[j]); int neighbor_distance = total_distance(neighbor_path); // If the neighbor solution is better, move to it if (neighbor_distance < current_distance) { current_path = neighbor_path; current_distance = neighbor_distance; } } std::cout << "Optimal path: "; for (int city : current_path) { std::cout << city << " "; } std::cout << std::endl; std::cout << "Total distance: " << current_distance << std::endl; } int main() { srand(time(NULL)); int max_iterations = 10000; hill_climbing_tsp(NUM_CITIES, max_iterations); return 0; }
输出
Optimal path: 0 1 3 2 Total distance: 80
import java.util.ArrayList; import java.util.List; import java.util.Random; public class HillClimbingTSP { private static final int NUM_CITIES = 4; // Distance matrix representing distances between cities // Replace this with the actual distance matrix for your problem private static final int[][] distanceMatrix = { {0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0} }; private static int totalDistance(List<Integer> path) { // Calculate the total distance traveled in the given path int total = 0; for (int i = 0; i < path.size() - 1; i++) { total += distanceMatrix[path.get(i)][path.get(i + 1)]; } total += distanceMatrix[path.get(path.size() - 1)][path.get(0)]; // Return to starting city return total; } private static List<Integer> generateRandomPath(int numCities) { List<Integer> path = new ArrayList<>(); for (int i = 0; i < numCities; i++) { path.add(i); } Random rand = new Random(); for (int i = numCities - 1; i > 0; i--) { int j = rand.nextInt(i + 1); int temp = path.get(i); path.set(i, path.get(j)); path.set(j, temp); } return path; } public static void hillClimbingTSP(int numCities, int maxIterations) { List<Integer> currentPath = generateRandomPath(numCities); // Initial solution int currentDistance = totalDistance(currentPath); for (int it = 0; it < maxIterations; it++) { // Generate a neighboring solution by swapping two random cities List<Integer> neighborPath = new ArrayList<>(currentPath); int i = new Random().nextInt(numCities); int j = new Random().nextInt(numCities); int temp = neighborPath.get(i); neighborPath.set(i, neighborPath.get(j)); neighborPath.set(j, temp); int neighborDistance = totalDistance(neighborPath); // If the neighbor solution is better, move to it if (neighborDistance < currentDistance) { currentPath = neighborPath; currentDistance = neighborDistance; } } System.out.print("Optimal path: "); for (int city : currentPath) { System.out.print(city + " "); } System.out.println(); System.out.println("Total distance: " + currentDistance); } public static void main(String[] args) { int maxIterations = 10000; hillClimbingTSP(NUM_CITIES, maxIterations); } }
输出
Optimal path: 1 3 2 0 Total distance: 80
import random # Distance matrix representing distances between cities # Replace this with the actual distance matrix for your problem distance_matrix = [ [0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0] ] def total_distance(path): # Calculate the total distance traveled in the given path total = 0 for i in range(len(path) - 1): total += distance_matrix[path[i]][path[i+1]] total += distance_matrix[path[-1]][path[0]] # Return to starting city return total def hill_climbing_tsp(num_cities, max_iterations=10000): current_path = list(range(num_cities)) # Initial solution, visiting cities in order current_distance = total_distance(current_path) for _ in range(max_iterations): # Generate a neighboring solution by swapping two random cities neighbor_path = current_path.copy() i, j = random.sample(range(num_cities), 2) neighbor_path[i], neighbor_path[j] = neighbor_path[j], neighbor_path[i] neighbor_distance = total_distance(neighbor_path) # If the neighbor solution is better, move to it if neighbor_distance < current_distance: current_path = neighbor_path current_distance = neighbor_distance return current_path def main(): num_cities = 4 # Number of cities in the TSP solution = hill_climbing_tsp(num_cities) print("Optimal path:", solution) print("Total distance:", total_distance(solution)) if __name__ == "__main__": main()
输出
Optimal path: [1, 0, 2, 3] Total distance: 80