当前位置: 首页 > news >正文

利用改进的遗传算法(种群隔离与个体迁移)mpi并行解决tsp问题

关于tsp问题的概述以及如何使用遗传算法进行求解已经在上一篇文章中说明了:遗传算法解决TSP问题.

但是,作为一种演化算法,遗传算法还存在着许多问题,比如早熟的情况,很容易在算法前期就已经收敛了,大量的个体都趋向于一致,种群多样性降低。

这种情况下,就很容易陷入局部最优解。即使扩大迭代次数、种群中的个体数量,也是无济于事的。

一、优化思想

那如何进行优化呢?一种做法就是,进行种群隔离,既然一个种群会出现趋同的情况,那么我们就搞许多个种群。

如果这些种群之间不进行通信,那么是不是可以认为他们就属于两个物种呢?

如果这样的话,那么我们采用少量的个体交换,对于这些种群,他们的物种丰富度是不是就提高了?

所以,这篇文章采用并行计算的方法,我们搞16个种群,这些种群每迭代2000次进行一次个体交换,通过这种多次的交换,来丰富物种多样性。

二、迁移策略

但是,如何在16个种群间进行物种迁移呢?这就要考虑到他们迁移的拓扑结构。

2.1 环形拓扑

环形拓扑主要就是将一个种群中的某个个体迁移到其他种群中去,具体如下:

在这里插入图片描述

2.2 随机拓扑

随机拓扑是任意的,即:一个种群可以向其他任意种群中传递个体。如图:

在这里插入图片描述

看起来就很乱,而且每一次种群间交流完全都是随机的。

三、替换策略

确定了那两个种群进行交换后,如何确定交换种群中的那两个个体呢?

3.1 最优-最差替换

最优发送:即选择种群中的最优个体给其他种群。

最差替换:接收到个体的种群,用别人给的最优的,替换自己最差的个体(适应度值最小)。

3.2 随机-随机替换

随机发送:随机发送一个个体给其他种群。

随机替换:接收到其他种群发送过来的个体后,随机选择一个自己种群的个体替换掉。

四、代码实现

串行改并行,主要分为两个步骤来进行。

第一步就是写好串行的代码;

第二步把串行的代码改成并行的。

最后可能还要稍微改下bug。

4.1 串行代码

#pragma once
// 解决TSP问题的重构算法(主要是tsp0的代码风格太丑陋了,修改成C++风格)
#include<iostream>
#include<fstream>
#include<vector>
#include<time.h>
#include<string>
using namespace std;class TSP_M {
private:int numCity;					 // 城市数量vector<vector<double>> cityXY;	 // 城市坐标vector<vector<double>> cityDis;  // 城市间距离的邻接矩阵int numColony = 100;			 // 种群数量vector<vector<int>> colony;		 // 种群vector<double> individualAdaptability; // 个体适应度int maxGen = 200000;			 // 最大演化代数int curGen = 0;					 // 当前演化代数double probabilityMutation = 0.02;	// 变异概率vector<int> bestIndividual;			// 当前最优个体double bestAdaptability;			// 当前最优个体的适应度// 用于控制是否记录结果bool isRecordResult2File = false;bool isRecordResult2Console = true;public:void hello(int myrank) {cout << "Hello from " << myrank << endl;}// 计算种群中每个个体的适应度void calculateColonyAdaptability() {// 计算每个个体的适应度for (int i = 0; i < numColony; i++) {double sum = 0;for (int j = 0; j < numCity; j++) {sum += cityDis[colony[i][j]][colony[i][(j + 1) % numCity]];}individualAdaptability[i] = sum;}}// 计算个体的适应度double calculateIndividualAdaptability(vector<int> path) {double sum = 0;for (int i = 0; i < numCity; i++) {sum += cityDis[path[i]][path[(i + 1) % numCity]];}return sum;}// 计算距离矩阵void calculateDistanceMatrix() {// 初始化距离矩阵cityDis.resize(numCity);for (int i = 0; i < numCity; i++) {cityDis[i].resize(numCity);}// 计算距离矩阵for (int i = 0; i < numCity; i++) {for (int j = 0; j < numCity; j++) {cityDis[i][j] = sqrt(pow(cityXY[i][0] - cityXY[j][0], 2) + pow(cityXY[i][1] - cityXY[j][1], 2));}}}// 初始化 = 读取数据 + 计算数据void init(string filePath) {// 读取 tsp 文件readTspFile(filePath);// 初始化距离矩阵、种群等必要数据calculateData();}// 进行迭代计算void evolution() {for (; curGen < maxGen; curGen++) { // 迭代maxGen次for (int i = 0; i < numColony; i++) { // 遍历种群中所有个体vector<int> path = colony[i]; // 用于存放变异后的路径int posC1 = rand() % numCity; // 随机生成变异点1(在path中的位置)int posC2 = rand() % numCity; // 随机生成变异点2(在path中的位置)int C1, C2; // 变异点1和变异点2对应的城市编号C1 = path[posC1]; // 获取变异点1对应的城市int j = rand() % numColony;   // 用于外变异的另一个 与 i个体 不同的个体int pos_flag = 0; // 用于标记变异过的点的数量double distanceChange = 0; // 用于记录距离变化while (true){// 以 probabilityMutation (default = 0.02)的概率进行内变异if (rand() / 32768.0 < probabilityMutation) {posC2 = rand() % numCity;while (posC1 == posC2) { // 如果两个变异点相同,则重新生成posC2 = rand() % numCity;}C2 = colony[i][posC2]; // 获取变异点1对应的城市}else { // 进行外变异(交叉)j = rand() % numColony;while (i == j) { // 如果两个个体相同,则重新生成j = rand() % numColony;}// 获取个体 j 中 变异点1 对应城市的位置int pos = position(colony[j], path[posC1]);C2 = colony[j][(pos + 1) % numCity]; // 获取变异点2对应的城市posC2 = position(path, C2); // 获取变异点2在个体 i 中的位置(即变异点2对应的城市在个体 i 中的位置}// 如果两个变异点相邻,continueif ((posC1 + 1) % numCity == posC2 || (posC1 - 1 + numCity) % numCity == posC2)break;//if (abs(posC1 - posC2) == 1 || abs(posC1 - posC2) == numCity - 1) {//	continue;//}// 否则进行倒位操作int C1_left = path[posC1]; // 变异点1左边的城市int C1_right = path[(posC1 + 1) % numCity]; // 变异点1右边的城市int C2_left = path[posC2]; // 变异点2左边的城市int C2_right = path[(posC2 + 1) % numCity]; // 变异点2右边的城市// 计算倒位后的路径长度distanceChange += cityDis[C1_left][C2_left] + cityDis[C1_right][C2_right]- cityDis[C1_left][C1_right] - cityDis[C2_left][C2_right];invert(path, posC1, posC2); // 倒位操作pos_flag++; // 变异点数量加一if (pos_flag >= numCity)break;posC1++; // 变异点1的位置加一if (posC1 >= numCity) posC1 = 0; // 如果变异点1的位置超过了numCity,则变异点1的位置为0}// 更新子个体的适应度individualAdaptability[numColony + i] = individualAdaptability[i] + distanceChange;distanceChange = 0;// 记录 产生的 子个体for (int j = 0; j < numCity; j++) {colony[numColony + i][j] = path[j];}}// 一轮迭代之后进行选择selection();bestIndividual = colony[0]; // 更新最优个体bestAdaptability = individualAdaptability[0]; // 更新最优个体的适应度for (int i = 1; i < numColony; i++) {if (individualAdaptability[i] < bestAdaptability) {bestIndividual = colony[i];bestAdaptability = individualAdaptability[i];}}if (isRecordResult2Console) {// cout << "第" << curGen << "代的最优个体适应度为:" << bestAdaptability << endl;cout << curGen << ":" << bestAdaptability << endl;}// 每 2000 代将最优个体的适应度写入文件if (isRecordResult2File && (curGen + 1) % 2000 == 0) {// 创建 outfile.txt 文件ofstream outfile("outfile.txt", ios::app);outfile << curGen << ":" << bestAdaptability << endl;// 关闭文件outfile.close();}}}// 获取城市在路径中的位置int position(vector<int>& path, int city) {for (int i = 0; i < numCity; i++) {if (path[i] == city) {return i;}}return -1;}void invert(vector<int>& path, int pos1, int pos2) {// 如果pos1在pos2的左边,为一段if (pos1 < pos2) {for (int i = pos1 + 1, j = pos2; i < j; i++, j--) {swap(path[i], path[j]);}}// 如果pos1在pos2的右边,为两段else {// 右边的段 <= 左边的段if (numCity - 1 - pos1 <= pos2 + 1) {int i, j;for (i = pos2 + 1, j = pos1; i <= numCity - 1; i++, j--) {swap(path[i], path[j]);}for (i = 0; i < j; i++, j--) {swap(path[i], path[j]);}}// 右边的段 > 左边的段else {int i, j;for (i = pos2 + 1, j = pos1; j >= 0; i++, j--) {swap(path[i], path[j]);}for (j = numCity - 1; i < j; i++, j--) {swap(path[i], path[j]);}}}}// 在父代和子代中进行一个锦标赛选择void selection() {for (int i = 0; i < numColony; i++) {if (individualAdaptability[i] > individualAdaptability[numColony + i]) {individualAdaptability[i] = individualAdaptability[numColony + i];for (int j = 0; j < numCity; j++) {colony[i][j] = colony[numColony + i][j];}}}}// 读取tsp文件bool readTspFile(string filePath) {fstream input(filePath, ios::in);if (!input) {cout << "文件打开失败" << endl;return false;}input >> numCity; // 城市数量cout << numCity << endl;// 初始化cityXYcityXY = vector<vector<double>>(numCity, vector<double>(2));// 读取城市坐标double x, y;for (int i = 0; i < numCity; i++) {int tmp;input >> tmp >> x >> y;cout << tmp << " " << x << " " << y << endl;cityXY[i][0] = x;cityXY[i][1] = y;}// 关闭文件input.close();return true;}// 根据tsp数据计算城市之间的距离、并随机初始化种群、同时计算适应度void calculateData() {// 初始化cityDiscalculateDistanceMatrix();// 初始化colony (包括父代和子代)colony = vector<vector<int>>(2 * numColony, vector<int>(numCity));// 以时间为种子,随机生成种群srand((unsigned)time(NULL));// 建立一个用于随机生成种群的数组vector<int> tmp(numCity);for (int i = 0; i < numCity; i++) {tmp[i] = i;}// 随机初始化种群for (int i = 0; i < numColony; i++) {int numNeedToRand = numCity;	// 当前需要随机的次数for (int j = 0; j < numCity; j++) {int randIndex = rand() % numNeedToRand; // 随机生成下标colony[i][j] = tmp[randIndex]; // 将随机生成的下标对应的值赋给种群swap(tmp[randIndex], tmp[numNeedToRand - 1]); // 将已经随机过的下标与最后一个下标交换numNeedToRand--; // 需要随机的次数减一}}// 初始化individualAdaptabilityindividualAdaptability = vector<double>(2 * numColony); // 后面的numColony个是用于存放子个体的适应度的// 计算种群中每个个体的适应度calculateColonyAdaptability();}// 替换掉当前种群中最差的个体void replaceWorstIndividual(vector<int> individual) {int worstIndex = 0;for (int i = 1; i < numColony; i++) {if (individualAdaptability[i] > individualAdaptability[worstIndex]) {worstIndex = i;}}individualAdaptability[worstIndex] = calculateIndividualAdaptability(individual);for (int i = 0; i < numCity; i++) {colony[worstIndex][i] = individual[i];}}// 随机替换掉当前种群中的一个个体void replaceRandomIndividual(vector<int> individual) {int randIndex = rand() % numColony;individualAdaptability[randIndex] = calculateIndividualAdaptability(individual);for (int i = 0; i < numCity; i++) {colony[randIndex][i] = individual[i];}}// get 方法// 获取城市数量int getNumCity() {return numCity;}// 获取城市坐标vector<vector<double>> getCityXY() {return cityXY;}// 获取最优个体vector<int> getBestIndividual() {int bestIndex = 0;for (int i = 1; i < numColony; i++) {if (individualAdaptability[i] < individualAdaptability[bestIndex]) {bestIndex = i;}}return colony[bestIndex];}// 随机获取一个个体vector<int> getRandomIndividual() {int randIndex = rand() % numColony;return colony[randIndex];}// 获取最大迭代次数int getMaxGen() {return maxGen;}// 获取当前迭代次数int getCurGen() {return curGen;}// set 方法void setNumCity(int numCity) {this->numCity = numCity;}void setCityXY(vector<vector<double>> cityXY) {this->cityXY = cityXY;}void setMaxGen(int maxGeneration) {this->maxGen = maxGeneration;}
};

4.2 并行代码

利用mpi编写的并行代码如下:

#include <stdio.h>
#include <mpi.h>
#include <iostream>
#include <algorithm>
#include "TSP_M.h"
using namespace std;int main(int argc, char* argv[]){// 迁移间隔int migrationInterval = 2000;// 迁移次数int migrationTimes = 100;// tsp文件路径string tspFilePath = "./pcb442.tsp";// 当前进程的编号、进程数量int myrank, numProcess;MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &myrank);MPI_Comm_size(MPI_COMM_WORLD, &numProcess);// 创建TSP_M对象TSP_M tsp;if (myrank == 0) { // 地主进程// 读取文件tsp.readTspFile(tspFilePath);// 给其他进程发送 tsp 中的数据for (int i = 1; i < numProcess; i++) {// 发送城市数量int numCity = tsp.getNumCity();MPI_Send(&numCity, 1, MPI_INT, i, 0, MPI_COMM_WORLD);// 发送城市坐标vector<vector<double>> cityXY = tsp.getCityXY();for (int j = 0; j < numCity; j++) {MPI_Send(&cityXY[j][0], 2, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);}}// 计算距离矩阵(后边计算适应度的时候会用到)tsp.calculateDistanceMatrix();}else {// 接收地主进程发送的数据// 接收城市数量int numCity;MPI_Recv(&numCity, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);// 接收城市坐标vector<vector<double>> cityXY(numCity, vector<double>(2));for (int j = 0; j < numCity; j++) {MPI_Recv(&cityXY[j][0], 2, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);}// 给TSP_M对象赋值tsp.setNumCity(numCity);tsp.setCityXY(cityXY);// 计算距离矩阵等数据tsp.calculateData();// 设置最大迭代次数为2000tsp.setMaxGen(migrationInterval);// 进行迭代计算,每2000代通信一次,进行100轮for (int i = 0; i < migrationTimes; i++) {// 进行2000代迭代tsp.evolution();// 发送当前最优个体vector<int> sendIndividualTo0 = tsp.getBestIndividual();// 随机选择一个个体// vector<int> sendIndividualTo0 = tsp.getRandomIndividual();// 向 0 号进程发送当前最优个体MPI_Send(&sendIndividualTo0[0], numCity, MPI_INT, 0, 0, MPI_COMM_WORLD);// 接收 0 号进程发送的最优个体vector<int> recvIndividualFrom0(numCity);MPI_Recv(&recvIndividualFrom0[0], numCity, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);// 替换掉当前最差个体tsp.replaceWorstIndividual(recvIndividualFrom0);// 随机替换一个个体// tsp.replaceRandomIndividual(recvIndividualFrom0);// 设置最大迭代次数 + 2000tsp.setMaxGen(tsp.getMaxGen() + migrationInterval);}}if (myrank == 0) {// 用于接收其他进程发送的个体vector<vector<int>> recvIndividuals(numProcess - 1, vector<int>(tsp.getNumCity()));// 进行100轮分发for (int i = 0; i < migrationTimes; i++) {for (int j = 1; j < numProcess; j++) {MPI_Recv(&recvIndividuals[j - 1][0], tsp.getNumCity(), MPI_INT, j, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);}// 环形拓扑,将收到的个体按顺序传递给下一个进程// 1 -> 2 -> 3 -> ... -> numProcess - 1 -> 1//for (int j = 1; j < numProcess - 1; j++) {//    MPI_Send(&recvIndividuals[j - 1][0], tsp.getNumCity(), MPI_INT, j + 1, 0, MPI_COMM_WORLD);//}//MPI_Send(&recvIndividuals[numProcess - 2][0], tsp.getNumCity(), MPI_INT, 1, 0, MPI_COMM_WORLD);// 随机拓扑,将收到的个体打乱顺序vector<int> randomOrder(numProcess - 1);for (int j = 0; j < numProcess - 1; j++) {randomOrder[j] = j;}// 采用随机洗牌算法打乱顺序random_shuffle(randomOrder.begin(), randomOrder.end());// 将打乱顺序后的个体传递给农民进程for (int j = 0; j < numProcess - 1; j++) {MPI_Send(&recvIndividuals[randomOrder[j]][0], tsp.getNumCity(), MPI_INT, j + 1, 0, MPI_COMM_WORLD);}}// 输出 recvIndividuals 中的最优个体double bestFitness = tsp.calculateIndividualAdaptability(recvIndividuals[0]);int bestIndividualIndex = 0;for (int i = 1; i < numProcess - 1; i++) {double fitness = tsp.calculateIndividualAdaptability(recvIndividuals[i]);if (fitness < bestFitness) {bestFitness = fitness;bestIndividualIndex = i;}}cout << "best fitness: " << bestFitness << endl;//cout << "best individual: ";//      for (int i = 0; i < tsp.getNumCity(); i++) {//          cout << bestIndividuals[bestIndividualIndex][i] << " ";//      }// 将最优个体写入文件fstream outfile;outfile.open("bestIndividual.txt", ios::out);for (int i = 0; i < tsp.getNumCity(); i++) {outfile << recvIndividuals[bestIndividualIndex][i] << " ";}outfile.close();}MPI_Finalize();return 0;
}

五、结果分析与讨论

采用matlab对求解结果进行可视化,代码如下:

clear all;                %清除所有变量
close all;                %清图
clc;                      %清屏C=load('./file/tsp442.txt');
R_best=load('./file/data/并行-随机拓扑-随机替换.txt');
n = size(C,1);for i=1:n-1                             % 绘制历代最优路线的图plot([ C(R_best(i) + 1,1), C(R_best(i+1) + 1,1)],... % 绘制 n-1 条边[C(R_best(i) + 1,2), C(R_best(i+1) + 1,2)],'bo-');hold on;
end
plot([C(R_best(n) + 1,1), C(R_best(1) + 1,1)],...        % 连接首尾边[C(R_best(n) + 1,2), C(R_best(1) + 1,2)],'ro-');  % 串行 51509.1% 并行(100轮、2000次、环形拓扑、最好-最差) 51617.3
% 并行(100轮、2000次、环形拓扑、随机-随机) 51897.5
% 并行(100轮、2000次、随机拓扑、最好-最差) 51677.7
% 并行(100轮、2000次、随机拓扑、随机-随机) 51451title(['并行(随机拓扑、最优-最差)遗传算法优化最短距离:',num2str(51677.7)]);

5.1 串行求解结果

最优路线长度:51509.1

在这里插入图片描述

5.2 并行求解结果

种群交流方式
拓扑结构环形拓扑随机拓扑
替换策略最优-最差随机-随机

拓扑结构有2种选择,替换策略也有2种选择,因此,一共有4种组合方式。

5.2.1 环形拓扑、最优-最差

最优路线长度:51617.3

在这里插入图片描述

5.2.2 环形拓扑、随机-随机

最优路线长度:51897.5

在这里插入图片描述

5.2.3 随机拓扑、最优-最差

最优路线长度:51677.7

在这里插入图片描述

5.2.4 随机拓扑、随机-随机

最优路线长度:51451

在这里插入图片描述

5.3 结果分析

上述结果是在迭代200000次得到的结果,其中每2000次进行一次种群交流。

由于计算资源有限,没有进行大量实验,但由于迭代次数较大,实验结果应当是较为稳定的。

从有限的实验结果中可以看到,随机拓扑+随机替换策略,找到的解为51451,是更优的。

这也说明,我们通过种群间交流,主要目的就是增加种群的物种多样性,而通过两种随机的策略(随机拓扑+随机替换)相互结合,相比于(环形拓扑+最优替换)增大了种群交流的随机性,较好地利用了多个种群,所以产生了较好地效果。

相关文章:

利用改进的遗传算法(种群隔离与个体迁移)mpi并行解决tsp问题

序 关于tsp问题的概述以及如何使用遗传算法进行求解已经在上一篇文章中说明了&#xff1a;遗传算法解决TSP问题. 但是&#xff0c;作为一种演化算法&#xff0c;遗传算法还存在着许多问题&#xff0c;比如早熟的情况&#xff0c;很容易在算法前期就已经收敛了&#xff0c;大量…...

【C++】—— C++11之线程库

前言&#xff1a; 在本期&#xff0c;我将给大家介绍的是 C11 中新引进的知识&#xff0c;即关于线程库的相关知识。 目录 &#xff08;一&#xff09;线程库的介绍 1、线程库的由来 2、线程库的简单介绍 &#xff08;二&#xff09;线程函数参数 &#xff08;三&#xf…...

前端面试:【性能优化】前端缓存、CDN、懒加载和预加载

亲爱的前端开发者&#xff0c;Web性能对用户体验至关重要。如果你想让你的网站更快、更具吸引力&#xff0c;就需要关注前端性能优化。在这篇文章中&#xff0c;我们将深入探讨四个关键的性能优化策略&#xff1a;前端缓存、CDN&#xff08;内容分发网络&#xff09;、懒加载和…...

民族传统文化分享系统uniapp 微信小程序

管理员、用户可通过Android系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、用户管理、知识分类管理、知识资源管理、用户分享管理、意见反馈、系统管理&#xff0c;用户前端&#xff1b;首页、知识资源、用户分享、我的等。 本系统的使用…...

netty(二):NIO——处理可写事件

处理可写事件 什么情况下需要注册可写事件&#xff1f; 在服务端一次性无法把数据发送完的情况下&#xff0c;需要注册可写事件 服务端一次性是否能够把数据全部发送完成取决于服务端的缓冲区大小&#xff0c;该缓冲区不受程序控制 注册可写事件的步骤 判断ByteBuffer是否仍…...

PHP基本语法解析与应用指南

PHP&#xff08;Hypertext Preprocessor&#xff09;是一种广泛应用的开源脚本语言&#xff0c;特别适用于Web开发。本文将深入探讨PHP的基本语法&#xff0c;包括变量、数据类型、运算符、控制流等方面的内容。我们将详细介绍每个主题的基本概念、语法规则和常见应用&#xff…...

ICS PA1

ICS PA1 init.shmake 编译加速ISA计算机是个状态机程序是个状态机准备第一个客户程序parse_argsinit_randinit_loginit_meminit_isa load_img剩余的初始化工作运行第一个客户程序调试&#xff1a;零断点TUI 基础设施单步执行打印寄存器状态扫描内存 表达式求值词法分析递归求值…...

Java学数据结构(4)——散列表Hash table 散列函数 哈希冲突

目录 引出散列表Hash table关键字Key和散列函数(hash function)散列函数解决collision哈希冲突&#xff08;碰撞&#xff09;分离链接法(separate chaining)探测散列表(probing hash table)双散列(double hashing) Java标准库中的散列表总结 引出 1.散列表&#xff0c;key&…...

OVRL-V2: A simple state-of-art baseline for IMAGENAV and OBJECTNAV 论文阅读

论文信息 题目&#xff1a;OVRL-V2: A simple state-of-art baseline for IMAGENAV and OBJECTNAV 作者:Karmesh Yadav&#xff0c; Arjun Majumdar&#xff0c; Ram Ramrakhya 来源&#xff1a;arxiv 时间&#xff1a;2023 代码地址&#xff1a; https://github.com/ykarmesh…...

【安全】原型链污染 - Hackit2018

目录 准备工作 解题 代码审计 Payload 准备工作 将这道题所需依赖模块都安装好后 运行一下&#xff0c;然后可以试着访问一下&#xff0c;报错是因为里面没内容而已&#xff0c;不影响,准备工作就做好了 解题 代码审计 const express require(express) var hbs require…...

net.ipv4.ip_forward=0导致docker容器无法与外部通信

在启动一个docker容器时报错&#xff1a; WARNING: IPv4 forwarding is disabled. Networking will not work. 并且&#xff0c;此时本机上的其他容器的网络服务&#xff0c;只能在本机上访问&#xff0c;其他机器上访问不到。 原因&#xff1a; sysctl net.ipv4.ip_forward …...

软考高级系统架构设计师系列论文九十八:论软件开发平台的选择与应用

软考高级系统架构设计师系列论文九十八:论软件开发平台的选择与应用 一、相关知识点二、摘要三、正文四、总结一、相关知识点 软考高级系统架构设计师系列之:面向构件的软件设计,构件平台与典型架构二、摘要 本文讨论选择新软件开发平台用于重新开发银行中间业务系统。银行中…...

Springboot整合WebFlux

一、使用WebFlux入门 WebFlux整合MysqlWebFlux整合ESWebFlus整合MongdbWebFlus整合Redis 1、添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><version>2.2.1.…...

uniapp 实现地图距离计算

在uniapp中实现地图距离计算可以借助第三方地图服务API来实现。以下是一种基本的实现方式&#xff1a; 注册地图服务API账号&#xff1a;你可以选择使用高德地图、百度地图等提供地图服务的厂商&#xff0c;注册一个开发者账号并获取API密钥。 安装相关插件或SDK&#xff1a;根…...

破除“中台化”误区,两大新原则考核中后台

近年来&#xff0c;“中台化”已成为许多企业追求的目标&#xff0c;旨在通过打通前后台数据和业务流程&#xff0c;提升运营效率和创新能力。然而&#xff0c;在实施过程中&#xff0c;一些误解可能导致“中台化”未能如预期般发挥作用。本文将探讨这些误解&#xff0c;并提出…...

基于YOLOV8模型和Kitti数据集的人工智能驾驶目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOV8模型和Kitti数据集的人工智能驾驶目标检测系统可用于日常生活中检测与定位车辆、汽车等目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用…...

基于Android的课程教学互动系统 微信小程序uniapp

教学互动是学校针对学生必不可少的一个部分。在学校发展的整个过程中&#xff0c;教学互动担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类教学互动程序也在不断改进。本课题所设计的springboot基于Android的教学互动系统&#xff0c;使用SpringBoot框架&am…...

OpenCV基础知识(9)— 视频处理(读取并显示摄像头视频、播放视频文件、保存视频文件等)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV不仅能够处理图像&#xff0c;还能够处理视频。视频是由大量的图像构成的&#xff0c;这些图像是以固定的时间间隔从视频中获取的。这样&#xff0c;就能够使用图像处理的方法对这些图像进行处理&#xff0c;进而达到…...

PostgreSQL命令行工具psql常用命令

1. 概述 通常情况下操作数据库使用图形化客户端工具&#xff0c;在实际工作中&#xff0c;生产环境是不允许直接连接数据库主机&#xff0c;只能在跳板机上登录到Linux服务器才能连接数据库服务器&#xff0c;此时就需要使用到命令行工具。psql是PostgreSQL中的一个命令行交互…...

【CSS 画个梯形】

使用clip-path: polygon画梯形 clip-path: polygon使用方式如下&#xff1a; 效果实现 clip-path: polygon 是CSS的属性之一&#xff0c;用于裁剪元素的形状。它可以通过定义一个具有多边形顶点坐标的值来创建一个多边形的裁剪区域&#xff0c;从而实现元素的非矩形裁剪效果。…...

Spring Data Redis

文章目录 Redis各种Java客户端Spring Data Redis使用方式操作字符串类型的数据操作哈希类型数据列表类型集合类型有序集合类型通用类型 Redis各种Java客户端 Java中如何操作redis&#xff0c;这里主讲IDEA中的框架Spring Data Redis来操作redis Jedis是官方推出的&#xff0c;…...

软件测试的方法有哪些?

软件测试 根据利用的被测对象信息的不同&#xff0c;可以将软件测试方法分为&#xff1a;黑盒测试、灰盒测试、白盒测试。 1、白盒测试 1&#xff09;概念&#xff1a;是依据被测软件分析程序内部构造&#xff0c;并根据内部构造分析用例&#xff0c;来对内部控制流程进行测试…...

Python Qt学习(二)Qt Designer

一开始以为Designer是个IDE&#xff0c;多番尝试之后&#xff0c;发现&#xff0c;是个UI设计工具&#xff0c;并不能在其中直接添加代码。保存之后&#xff0c;会生成一个后缀是UI的文件&#xff0c;再用pyuic5.exe将ui文件转化成py文件。pyuic5 -o 目标py文件 源ui文件...

我的数据上传类操作(以webDAV为例)

在登录处进行初始化&#xff1a; 1.读取配置 GModel.ServerSetin JsonToIni.GetClass<ServerSet>(ConfigFiles.ConfigFile);if (!string.IsNullOrWhiteSpace(GModel.ServerSetin.FTPUser)){OPCommon.NetControls.NetworkShareConnect.connectToShare(GModel.ServerSeti…...

move与函数指针的简单使用

std::move() C11的标准库 提供了一个非常有用的函数 std::move()&#xff0c;std::move() 函数将一个左值强制转化为右值引用&#xff0c;以用于移动语义。 就是说 std::move(str); 之后原来的值因为变成了右值失效了 但是这样赋值可以避免出现拷贝 #include <iostream&g…...

第五章 树与二叉树 二、二叉树的定义和常考考点

一、定义 二叉树可以用以下方式详细定义&#xff1a; 二叉树是由节点构成的树形结构&#xff0c;每个节点最多可以有两个子节点。每个节点有以下几个属性&#xff1a; 值&#xff1a;存储该节点的数据。左子节点&#xff1a;有一个左子节点&#xff0c;如果没有则为空。右子节…...

算法笔记/USACO Guide GOLD金组DP 1. Introduction to DP

USACO Guide中金组的内容分为一下六个章节 DP数学图论数据结构树一些附加主题 今天学习DP&#xff0c;以下内容&#xff1a; 初入DP背包DP图表中的路线最长递增序列状态压缩DP区间DP数位DP 初入DP Dynamic Programming (DP) is an important algorithmic technique in Comp…...

天锐绿盾安全U盘系统

安全U盘系统 01 简介 天锐绿盾安全U盘系统&#xff0c;是一款致力于保障U盘数据内容安全的产品。通过严格身份认证、便捷安全的密保机制、智能的U盘锁定或自毁设置、详细的文件操作日志、文件粉碎、设置还原等&#xff0c;天锐绿盾安全U盘系统为您U盘的数据保驾护航&#xff0…...

灰色预测模型

当谈论灰色预测时&#xff0c;通常是指灰色系统理论&#xff0c;它是一种用于处理少量数据或缺乏充分信息的情况下进行预测和分析的数学方法。灰色预测的核心思想是通过建立灰色模型来分析和预测数据的变化趋势。 我会解释灰色预测的基本原理、步骤和方法&#xff1a; 1. 灰色…...

Yolo系列-yolov1

YOLO-V1 经典的one-stage方法 YouOnlyLookOnce&#xff0c;名字就已经说明了一切&#xff01;把检测问题转化成回归问题&#xff0c;一个CNN就搞定了&#xff01;可以对视频进行实时检测&#xff0c;应用领域非常广&#xff01; 核心思想&#xff1a; Yolov1的核心思想是将对象…...

网站开发难度/seo策略是什么意思

记得在异常出现之前&#xff0c;只安装了MySQL&#xff0c;之后OrCAD Capture、Allegro就打不开了。 Capture.exe - 系统错误 allegro.exe - 系统错误 我尝试在Cadence的安装目录下搜索这些dll文件&#xff0c;可以找到得到。 上网搜了一下&#xff0c;怀疑是系统变量缺失导致的…...

用java做的游戏下载网站/免费推广的方式有哪些

实验07.挂载ISO镜像文件实验目标从Win7真机中拷贝一个.iso镜像文件挂载到/mnt/sos目录实验环境在虚拟机Linux系统下RHEL5.9光盘文件虚拟机中要装VMware ToolsWin7中拷贝一个.iso镜像文件。实验步骤1. 挂载boot.iso镜像文件[rootlocalhost ~]# mount -o loop/root/Desktop/linu…...

wordpress 密码访问/长沙关键词优化费用

目录 VI/VIM编辑器常用操作介绍&#xff1a; 1.VI和VIM是什么 2.一般模式 2.1常用语法 3.编辑模式 3.1常用语法 4.指令模式 4.1基本语法 5.模式转换 6.VI/VIM键盘图 1.VI和VIM是什么 VI 是 Unix 操作系统和类 Unix 操作系统中最通用的文本编辑器。VIM 编辑器是从 VI…...

进网站显示建设中怎么解决/长沙seo搜索

转自&#xff1a;http://www.cnblogs.com/daqiang/archive/2011/12/04/2275646.html STM32的定时器是个强大的模块&#xff0c;定时器使用的频率也是很高的&#xff0c;定时器可以做一些基本的定时&#xff0c;还可以做PWM输出或者输入捕获功能。 时钟源问题&#xff1a; 名…...

和平网站建设优化seo/百度seo网站在线诊断

在对read的使用过程中&#xff0c;发现对其返回值的处理比较重要&#xff0c;这里做一下总结。read函数原型&#xff1a;ssize_t read(int fd,void *buf,size_t count)函数返回值分为下面几种情况&#xff1a;1、如果读取成功&#xff0c;则返回实际读到的字节数。这里又有两种…...

云南 房地产网站建设/sem竞价开户

创建了超级管理员之后登录http://127.0.0.1:8000/admin/怎么都显示查不到url&#xff0c;查了很多网站也没找到原因&#xff0c;后来想起每次新建项目的时候都会有默认的一个url&#xff0c;而系统找不到admin页面的原因就是没有下面的路径 from django.contrib import admin …...