【Python】人工智能-机器学习——不调库手撕演化算法解决函数最小值问题

1 作业内容描述

1.1 背景

  1. 现在有一个函数 3 − s i n 2 ( j x 1 ) − s i n 2 ( j x 2 ) 3-sin^2(jx_1)-sin^2(jx_2) 3sin2(jx1)sin2(jx2),有两个变量 x 1 x_1 x1 x 2 x_2 x2,它们的定义域为 x 1 , x 2 ∈ [ 0 , 6 ] x_1,x_2\in[0,6] x1,x2[0,6],并且 j = 2 j=2 j=2,对于此例,所致对于 j = 2 , 3 , 4 , 5 j=2,3,4,5 j=2,3,4,5分别有 16,36,64,100 个全局最优解。

  2. 现在有一个Shubert函数 ∏ i = 1 n ∑ j = 1 5 j cos ⁡ [ ( j + 1 ) x i + j ] \prod_{i=1}^{n}\sum_{j=1}^{5}j\cos[(j+1)x_i+j] i=1nj=15jcos[(j+1)xi+j],其中定义域为 − 10 < x i < 10 -10<x_i<10 10<xi<10,对于此问题,当n=2时有18个不同的全局最优解

1.2 要求

  1. 求该函数的最小值即 m i n ( 3 − s i n 2 ( j x 1 ) − s i n 2 ( j x 2 ) ) min(3-sin^2(jx_1)-sin^2(jx_2)) min(3sin2(jx1)sin2(jx2)),j=2,精确到小数点后6位。
  2. 求该Shubert函数的最小值即 m i n ( ∏ i = 1 2 ∑ j = 1 5 j cos ⁡ [ ( j + 1 ) x i + j ] ) min(\prod_{i=1}^{2}\sum_{j=1}^{5}j\cos[(j+1)x_i+j]) min(i=12j=15jcos[(j+1)xi+j]),精确到小数点后6位

2 作业已完成部分和未完成部分

该作业已经全部完成,没有未完成的部分。

Value在这里插入图片描述
Colab NotebookGithub Rep

3. 作业运行结果截图

最后跑出的结果如下:

  1. 第一个函数的最小值为 1.0000000569262162
  2. 第二个函数的最小值为-186.73042323192567

4 核心代码和步骤

4.1 基本的步骤

  1. 定义目标函数 objective_function:使用了一个二维的目标函数,即 3 − s i n 2 ( j x 1 ) − s i n 2 ( j x 2 ) 3-sin^2(jx_1)-sin^2(jx_2) 3sin2(jx1)sin2(jx2)
  2. 定义选择函数 crossover:用于交叉操作,通过交叉率(crossover_rate)确定需要进行交

叉的父母对的数量,并在这些父母对中交换某些变量的值。

  1. 定义变异函数 mutate:用于变异操作,通过变异率(mutation_rate)确定需要进行变异

的父母对的数量,并在这些父母对中随机改变某些变量的值。

  1. 定义进化算法 evolutionary_algorithm:初始化种群,其中每个个体都是一个二维向量。在

每一代中,计算每个个体的适应度值,绘制三维图表展示种群分布和最佳解。

  1. 更新全局最佳解。根据适应度值确定复制的数量并形成繁殖池。选择父母、进行交叉和变

异,更新种群。重复上述步骤直到达到指定的迭代次数。

  1. 设置算法参数:population_size:种群大小。;num_generations:迭代的次数。;muta

tion_rate:变异率。;crossover_rate:交叉率。

  1. 运行进化算法 evolutionary_algorithm:调用进化算法函数并获得最终的最佳解、最佳适

应度值和每一代的演化数据。

  1. 输出结果:打印最终的最佳解和最佳适应度值。输出每个迭代步骤的最佳适应度值。

  2. 可视化结果:绘制函数曲面和最优解的三维图表。绘制适应度值随迭代次数的变化曲线。

4.2 第一个函数 3 − s i n 2 ( j x 1 ) − s i n 2 ( j x 2 ) 3-sin^2(jx_1)-sin^2(jx_2) 3sin2(jx1)sin2(jx2)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# 定义目标函数
def objective_function(x):j = 2return 3 - np.sin(j * x[0])**2 - np.sin(j * x[1])**2 # 3 - sin(2x1)^2 - sin(2x2)^2# 定义选择函数
def crossover(parents_1, parents_2, crossover_rate):num_parents = len(parents_1) # 父母的数量 num_crossover = int(crossover_rate * num_parents) # 选择进行交叉的父母对的数量# 选择进行交叉的父母对crossover_indices = np.random.choice(num_parents, size=num_crossover, replace=False) # 选择进行交叉的父母对的索引# 复制父母copy_parents_1 = np.copy(parents_1)copy_parents_2 = np.copy(parents_2)# 进行交叉操作for i in crossover_indices:parents_1[i][1] = copy_parents_2[i][1] # 交叉变量x2parents_2[i][1] = copy_parents_1[i][1] # 交叉变量x2return parents_1, parents_2# 定义变异函数
def mutate(parents_1, parents_2, mutation_rate):num_parents = len(parents_1) # 父母的数量num_mutations = int(mutation_rate * num_parents) # 选择进行变异的父母对的数量# 选择进行变异的父母对mutation_indices = np.random.choice(num_parents, size=num_mutations, replace=False) # 选择进行变异的父母对的索引# 进行变异操作for i in mutation_indices:parents_1[i][1] = np.random.uniform(0, 6)  # 变异变量x2parents_2[i][1] = np.random.uniform(0, 6)  # 变异变量x2return parents_1, parents_2# 定义进化算法
def evolutionary_algorithm(population_size, num_generations, mutation_rate, crossover_rate):bounds = [(0, 6), (0, 6)]  # 变量的取值范围# 保存每个迭代步骤的信息evolution_data = []# 初始化种群population = np.random.uniform(bounds[0][0], bounds[0][1], size=(population_size, 2))# 设置初始的 best_solutionbest_solution = population[0]  # 选择种群中的第一个个体作为初始值best_fitness = objective_function(best_solution) # 计算初始值的适应度值for generation in range(num_generations):# 计算适应度fitness_values = np.apply_along_axis(objective_function, 1, population)# 找到当前最佳解current_best_index = np.argmin(fitness_values)current_best_solution = population[current_best_index]current_best_fitness = fitness_values[current_best_index]# 绘制每次迭代的三维分布图fig = plt.figure() # 创建一个新的图形ax = fig.add_subplot(111, projection='3d') # 创建一个三维的坐标系ax.scatter(population[:, 0], population[:, 1], fitness_values, color='black', marker='.', label='Population') # 绘制种群的分布图ax.scatter(best_solution[0], best_solution[1], best_fitness, s=100, color='red', marker='o', label='Best Solution') # 绘制最佳解的分布图# 设置坐标轴的标签ax.set_xlabel('X1') ax.set_ylabel('X2')ax.set_zlabel('f(x)')ax.set_title(f'Generation {generation} - Best Fitness: {best_fitness:.6f}')ax.legend() # 显示图例plt.show() # 显示图形# 更新全局最佳解if current_best_fitness < best_fitness: # 如果当前的最佳解的适应度值小于全局最佳解的适应度值best_solution = current_best_solutionbest_fitness = current_best_fitness# 保存当前迭代步骤的信息evolution_data.append({'generation': generation,'best_solution': best_solution,'best_fitness': best_fitness})# 根据适应度值确定复制的数量并且形成繁殖池reproduction_ratios = fitness_values / np.sum(fitness_values) # 计算每个个体的适应度值占总适应度值的比例sorted_index_ratios = np.argsort(reproduction_ratios) # 对比例进行排序half_length = len(sorted_index_ratios) // 2 # 选择前一半的个体first_half_index = sorted_index_ratios[:half_length] # 选择前一半的个体的索引new_half_population = population[first_half_index] # 选择前一半的个体breeding_pool = np.concatenate((new_half_population, new_half_population)) # 将前一半的个体复制一份,形成繁殖池# 选择父母        parents_1 = breeding_pool[:half_length]parents_2 = breeding_pool[half_length:] # 先获取最后一半的父母parents_2 = np.flip(parents_2, axis=0) # 再将父母的顺序反转# 选择和交叉parents_1, parents_2 = crossover(parents_1, parents_2, crossover_rate)# 变异parents_1, parents_2 = mutate(parents_1, parents_2, mutation_rate)# 更新种群population = np.vstack([parents_1, parents_2])return best_solution, best_fitness, evolution_data# 设置算法参数
population_size = 10000
num_generations = 40
mutation_rate = 0.1  # 变异率
crossover_rate = 0.4   # 交叉率# 运行进化算法
best_solution, best_fitness, evolution_data = evolutionary_algorithm(population_size, num_generations, mutation_rate, crossover_rate)# 输出结果
print("最小值:", best_fitness)
print("最优解:", best_solution)# 输出每个迭代步骤的最佳适应度值
print("每个迭代步骤的最佳适应度值:")
for step in evolution_data:print(f"Generation {step['generation']}: {step['best_fitness']}")# 可视化函数曲面和最优解
x1_vals = np.linspace(0, 6, 100)
x2_vals = np.linspace(0, 6, 100)
X1, X2 = np.meshgrid(x1_vals, x2_vals)
Z = 3 - np.sin(2 * X1)**2 - np.sin(2 * X2)**2fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X1, X2, Z, alpha=0.5, cmap='viridis')
ax.scatter(best_solution[0], best_solution[1], best_fitness, color='red', marker='o', label='Best Solution')
ax.set_xlabel('X1')
ax.set_ylabel('X2')
ax.set_zlabel('f(x)')
ax.set_title('Objective Function and Best Solution')
ax.legend()# 绘制适应度值的变化曲线
evolution_df = pd.DataFrame(evolution_data)
plt.figure()
plt.plot(evolution_df['generation'], evolution_df['best_fitness'], label='Best Fitness')
plt.xlabel('Generation')
plt.ylabel('Fitness')
plt.title('Evolution of Fitness')
plt.legend()plt.show()

4.3 Shubert 函数的最小值

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# 定义目标函数
def objective_function(x):result = 1for i in range(1, 3):inner_sum = 0for j in range(1, 6):inner_sum += j * np.cos((j + 1) * x[i - 1] + j)result *= inner_sumreturn result # 定义选择函数
def crossover(parents_1, parents_2, crossover_rate):num_parents = len(parents_1) # 父母的数量 num_crossover = int(crossover_rate * num_parents) # 选择进行交叉的父母对的数量# 选择进行交叉的父母对crossover_indices = np.random.choice(num_parents, size=num_crossover, replace=False) # 选择进行交叉的父母对的索引# 复制父母copy_parents_1 = np.copy(parents_1)copy_parents_2 = np.copy(parents_2)# 进行交叉操作for i in crossover_indices:parents_1[i][1] = copy_parents_2[i][1] # 交叉变量x2parents_2[i][1] = copy_parents_1[i][1] # 交叉变量x2return parents_1, parents_2# 定义变异函数
def mutate(parents_1, parents_2, mutation_rate):num_parents = len(parents_1) # 父母的数量num_mutations = int(mutation_rate * num_parents) # 选择进行变异的父母对的数量# 选择进行变异的父母对mutation_indices = np.random.choice(num_parents, size=num_mutations, replace=False) # 选择进行变异的父母对的索引# 进行变异操作for i in mutation_indices:parents_1[i][1] = np.random.uniform(-10, 10)  # 变异变量x2parents_2[i][1] = np.random.uniform(-10, 10)  # 变异变量x2return parents_1, parents_2# 定义进化算法
def evolutionary_algorithm(population_size, num_generations, mutation_rate, crossover_rate):bounds = [(-10, 10), (-10, 10)]  # 变量的取值范围# 保存每个迭代步骤的信息evolution_data = []# 初始化种群population = np.random.uniform(bounds[0][0], bounds[0][1], size=(population_size, 2))# 设置初始的 best_solutionbest_solution = population[0]  # 选择种群中的第一个个体作为初始值best_fitness = objective_function(best_solution) # 计算初始值的适应度值for generation in range(num_generations):# 计算适应度fitness_values = np.apply_along_axis(objective_function, 1, population) # 找到当前最佳解current_best_index = np.argmin(fitness_values)current_best_solution = population[current_best_index]current_best_fitness = fitness_values[current_best_index]# 绘制每次迭代的三维分布图fig = plt.figure() # 创建一个新的图形ax = fig.add_subplot(111, projection='3d') # 创建一个三维的坐标系ax.scatter(population[:, 0], population[:, 1], fitness_values, color='black', marker='.', label='Population') # 绘制种群的分布图ax.scatter(current_best_solution[0], current_best_solution[1], current_best_fitness, s=100, color='red', marker='o', label='Best Solution') # 绘制最佳解的分布图# 设置坐标轴的标签ax.set_xlabel('X1') ax.set_ylabel('X2')ax.set_zlabel('f(x)')ax.set_title(f'Generation {generation} - Best Fitness: {current_best_fitness:.6f}')ax.legend() # 显示图例plt.show() # 显示图形# 更新全局最佳解if current_best_fitness < best_fitness: # 如果当前的最佳解的适应度值小于全局最佳解的适应度值best_solution = current_best_solutionbest_fitness = current_best_fitness# 保存当前迭代步骤的信息evolution_data.append({'generation': generation,'best_solution': best_solution,'best_fitness': best_fitness})# 根据适应度值确定复制的数量并且形成繁殖池reproduction_ratios = fitness_values / np.sum(fitness_values) # 计算每个个体的适应度值占总适应度值的比例sorted_index_ratios = np.argsort(reproduction_ratios) # 对比例进行排序half_length = len(sorted_index_ratios) // 2 # 选择后一半的个体first_half_index = sorted_index_ratios[half_length:] # 选择后一半的个体的索引new_half_population = population[first_half_index] # 选择后一半的个体breeding_pool = np.concatenate((new_half_population, new_half_population)) # 将后一半的个体复制一份,形成繁殖池# 选择父母        parents_1 = breeding_pool[:half_length]parents_2 = breeding_pool[half_length:] # 先获取最后一半的父母parents_2 = np.flip(parents_2, axis=0) # 再将父母的顺序反转# 选择和交叉parents_1, parents_2 = crossover(parents_1, parents_2, crossover_rate)# 变异parents_1, parents_2 = mutate(parents_1, parents_2, mutation_rate)# 更新种群population = np.vstack([parents_1, parents_2])return best_solution, best_fitness, evolution_data# 设置算法参数
population_size = 15000
num_generations = 40
mutation_rate = 0.08  # 变异率
crossover_rate = 0.2   # 交叉率# 运行进化算法
best_solution, best_fitness, evolution_data = evolutionary_algorithm(population_size, num_generations, mutation_rate, crossover_rate)# 输出结果
print("最小值:", best_fitness)
print("最优解:", best_solution)# 输出每个迭代步骤的最佳适应度值
print("每个迭代步骤的最佳适应度值:")
for step in evolution_data:print(f"Generation {step['generation']}: {step['best_fitness']}")# 可视化函数曲面和最优解
x1_vals = np.linspace(-10, 10, 100)
x2_vals = np.linspace(-10, 10, 100)
X1, X2 = np.meshgrid(x1_vals, x2_vals)
Z = np.zeros_like(X1)
for i in range(Z.shape[0]):for j in range(Z.shape[1]):Z[i, j] = objective_function([X1[i, j], X2[i, j]])fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X1, X2, Z, alpha=0.5, cmap='viridis')
ax.scatter(best_solution[0], best_solution[1], best_fitness, color='red', marker='o', label='Best Solution')
ax.set_xlabel('X1')
ax.set_ylabel('X2')
ax.set_zlabel('f(x)')
ax.set_title('Objective Function and Best Solution')
ax.legend()# 绘制适应度值的变化曲线
evolution_df = pd.DataFrame(evolution_data)
plt.figure()
plt.plot(evolution_df['generation'], evolution_df['best_fitness'], label='Best Fitness')
plt.xlabel('Generation')
plt.ylabel('Fitness')
plt.title('Evolution of Fitness')
plt.legend()plt.show()

5 附录

5.1 In[1] 输出

output_0_0

output_0_1

output_0_2

output_0_3

output_0_4

output_0_5

output_0_6

output_0_7

output_0_8

output_0_9

output_0_10

output_0_11

output_0_12

output_0_13

output_0_14

output_0_15

output_0_16

output_0_17

output_0_18

output_0_19

output_0_20

output_0_21

output_0_22

output_0_23

output_0_24

output_0_25

output_0_26

output_0_27

output_0_28

output_0_29

output_0_30

output_0_31

output_0_32

output_0_33

output_0_34

output_0_35

output_0_36

output_0_37

output_0_38

output_0_39

output_0_41

最小值: 1.0000002473000187

最优解: [0.78562713 0.7854951 ]

每个迭代步骤的最佳适应度值:

Generation 0: 1.0000153042180673

Generation 1: 1.0000153042180673

Generation 2: 1.0000153042180673

Generation 3: 1.0000136942409763

Generation 4: 1.0000136942409763

Generation 5: 1.0000136942409763

Generation 6: 1.0000136942409763

Generation 7: 1.0000100419077742

Generation 8: 1.000005565304546

Generation 9: 1.000002458099502

Generation 10: 1.0000022366988228

Generation 11: 1.0000007727585987

Generation 12: 1.0000007727585987

Generation 13: 1.0000007091648468

Generation 14: 1.0000007091648468

Generation 15: 1.0000004471760704

Generation 16: 1.0000004471760704

Generation 17: 1.0000004471760704

Generation 18: 1.0000004471760704

Generation 19: 1.0000002609708571

Generation 20: 1.0000002609708571

Generation 21: 1.0000002609708571

Generation 22: 1.0000002609708571

Generation 23: 1.0000002609708571

Generation 24: 1.0000002609708571

Generation 25: 1.0000002609708571

Generation 26: 1.0000002609708571

Generation 27: 1.0000002609708571

Generation 28: 1.0000002609708571

Generation 29: 1.0000002473000187

Generation 30: 1.0000002473000187

Generation 31: 1.0000002473000187

Generation 32: 1.0000002473000187

Generation 33: 1.0000002473000187

Generation 34: 1.0000002473000187

Generation 35: 1.0000002473000187

Generation 36: 1.0000002473000187

Generation 37: 1.0000002473000187

Generation 38: 1.0000002473000187

Generation 39: 1.0000002473000187

output_0_41

output_0_42

5.2 In[2] 输出

output_1_0

output_1_1

output_1_2

output_1_3

output_1_4

output_1_5

output_1_6

output_1_7

output_1_8

output_1_9

output_1_10

output_1_11

output_1_12

output_1_13

output_1_14

output_1_15

output_1_16

output_1_17

output_1_18

output_1_19

output_1_20

output_1_21

output_1_22

output_1_23

output_1_24

output_1_25

output_1_26

output_1_27

output_1_28

output_1_29

output_1_30

output_1_31

output_1_32

output_1_33

output_1_34

output_1_35

output_1_36

output_1_37

output_1_38

output_1_39

最小值: -186.73042323192567

最优解: [-7.70876845 -7.08354764]

每个迭代步骤的最佳适应度值:

Generation 0: -186.59098010602338

Generation 1: -186.59098010602338

Generation 2: -186.59098010602338

Generation 3: -186.59098010602338

Generation 4: -186.70224634663253

Generation 5: -186.70224634663253

Generation 6: -186.70224634663253

Generation 7: -186.70224634663253

Generation 8: -186.70224634663253

Generation 9: -186.70224634663253

Generation 10: -186.70224634663253

Generation 11: -186.71507272172664

Generation 12: -186.71507272172664

Generation 13: -186.7289048406221

Generation 14: -186.73006643615773

Generation 15: -186.73006643615773

Generation 16: -186.73006643615773

Generation 17: -186.73006643615773

Generation 18: -186.73009038074477

Generation 19: -186.73009038074477

Generation 20: -186.73009038074477

Generation 21: -186.73009038074477

Generation 22: -186.73009038074477

Generation 23: -186.73042323192567

Generation 24: -186.73042323192567

Generation 25: -186.73042323192567

Generation 26: -186.73042323192567

Generation 27: -186.73042323192567

Generation 28: -186.73042323192567

Generation 29: -186.73042323192567

Generation 30: -186.73042323192567

Generation 31: -186.73042323192567

Generation 32: -186.73042323192567

Generation 33: -186.73042323192567

Generation 34: -186.73042323192567

Generation 35: -186.73042323192567

Generation 36: -186.73042323192567

Generation 37: -186.73042323192567

Generation 38: -186.73042323192567

Generation 39: -186.73042323192567

output_1_41

output_1_42

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/416700.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 【C编程】 引入线程,线程相关函数

1.线程的引入 1.1使用线程同时读取键盘和鼠标 代码演示&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <termios.h> #include <fcntl.h> #include <string.h> // 读取…

爬取的数据可以入表吗?怎样入表?

合规是数据入表的前提。当前爬虫数据是非常敏感的&#xff0c;因为爬虫极容易造成两大不合规的问题&#xff1a;一是没有经过个人同意获取数据&#xff0c;二是爬取的数据里可能含有个人敏感信息也是一个问题。现在法律对于这部分非常严苛&#xff0c;如果企业里有50条未获得授…

Pytest系列(2) - assert断言详细使用

前言 与unittest不同&#xff0c;pytest使用的是python自带的assert关键字来进行断言assert关键字后面可以接一个表达式&#xff0c;只要表达式的最终结果为True&#xff0c;那么断言通过&#xff0c;用例执行成功&#xff0c;否则用例执行失败 assert小栗子 想在抛出异常之…

算数移位,逻辑移位以及循环移位

目录 一.算数移位 1.原码的算数移位一一符号位保持不变&#xff0c;仅对数值位进行移位 2.反码的算数移位 3.补码的算数移位 二.逻辑移位 三.循环移位 一.算数移位 1.原码的算数移位一一符号位保持不变&#xff0c;仅对数值位进行移位 算数移位是通过改变各个数码位和小…

vue二次封装ant-design-vue中的Modal弹窗组件,实现拖拽,全屏两种功能,原有参数属性不变

在我们的项目的有的地方需要用弹框的拖拽&#xff0c;以及弹窗自定义全屏显示的需求&#xff0c;所以再次将二次合一&#xff0c;同时弹框里面内容自适应屏幕高度 在ant-design-vue中&#xff0c;已经实现了拖拽&#xff0c;全屏的功能&#xff0c;下面是ant官网的示例 自定义…

宋仕强论道之再混华强北(三十五)

我是2012年重新回到华强北的&#xff0c;宋仕强说来深圳市第一份工作就在华强北担任一名工程师&#xff0c;和华强北有深厚的感情。我回来后经常混华强北的上层圈子跟老板老板娘们吹牛逼&#xff0c;最初大家看我穿的衣冠楚楚人模狗样的但态度吊儿郎当&#xff0c;理论一套一套…

K8s调试积累

文章目录 一、K8S 集群服务访问失败&#xff1f;二、K8S 集群服务访问失败&#xff1f;三、K8S 集群服务暴露失败&#xff1f;四、外网无法访问 K8S 集群提供的服务&#xff1f;五、pod 状态为 ErrImagePull&#xff1f;六、探测存活 pod 状态为 CrashLoopBackOff&#xff1f;七…

PDF.js - 免费开源的 JavaScript 读取、显示 PDF 文档的工具库,由 Mozilla 开发并且持续维护

最近新项目需要处理 PDF&#xff0c;研究了 PDf.js 之后觉得很不错&#xff0c;于是写篇文章推荐给大家。 PDF.js 的功能和它的名字一样简单&#xff0c;是一个使用 HTML5 技术来让前端网页支持读取、解析和显示 PDF 文档的 JS 工具库。这个项目由大名鼎鼎的 Mozilla 组织开发…

离线数据仓库-关于增量和全量

数据同步策略 数据仓库同步策略概述一、数据的全量同步二、数据的增量同步三、数据同步策略的选择 数据仓库同步策略概述 应用系统所产生的业务数据是数据仓库的重要数据来源&#xff0c;我们需要每日定时从业务数据库中抽取数据&#xff0c;传输到数据仓库中&#xff0c;之后…

简单实用的恒温控制器

工作原理如下&#xff1a;ST是WTQ-288型电接点压力式温度计&#xff0c;当恒温箱内的温度降低到下限时&#xff0c;ST的指针与下限接点接触&#xff0c;双向可控硅通过R被强制触发导通&#xff0c;接通加热器RL的电源&#xff0c;于是恒温箱内温度上升。ST的指针转动&#xff0…

SPI 动态服务发现机制

SPI&#xff08;Service Provier Interface&#xff09;是一种服务发现机制&#xff0c;通过ClassPath下的META—INF/services文件查找文件&#xff0c;自动加载文件中定义的类&#xff0c;再调用forName加载&#xff1b; spi可以很灵活的让接口和实现分离&#xff0c; 让API提…

Docker进阶篇-安装MySQL主从复制

一、MySQL主服务器 1、新建主服务器容器实例3307 docker run -p 3307:3306 \--name mysql-master \--privilegedtrue \-v /mydata/mysql-master/log:/var/log/mysql \-v /mydata/mysql-master/data:/var/lib/mysql \-v /mydata/mysql-master/conf:/etc/mysql \-e MYSQL_ROOT_…