TSP问题禁忌搜索c++实现

今天作业汇报完,直接开源!

1.数据准备:

1.1随机初始化版:

初始化城市数量以及维度:

pair<int, int> initial::read_private_i() {
	cout << "sizec:    " <<this->sizec << endl;
	cout << "sizek:    " << this->sizek << endl;
	int a, b;
	a = this->sizec;
	b = this->sizek;
	return make_pair(a,b);
}

随机初始化城市方位:

int **initial::chengshichushihua() {
	int** chengshi = (int**)malloc(initial::sizec* sizeof(int*));
	for (int i = 0;i < initial::sizec;i++){
		chengshi[i] = (int*)malloc(initial::sizek * sizeof(int));
		for (int j = 0;j < initial::sizek;j++){
			chengshi[i][j] = getRand(1, 1000);
		}
	}
	this->chengshibiao = chengshi;
	return chengshi;
}

返回相应指针,并更新类中的属性

根据随机初始化的城市算与其他城市的距离(假设所有城市之间都能相互到达)

double** initial::get_juli() {
	double** juli = (double**)malloc(this->sizec * sizeof(double*));
	for (int i = 0;i < this->sizec;i++) {
		juli[i] = (double*)malloc(this->sizec * sizeof(double));
		for (int j = 0;j < this->sizec;j++) {
			if (i == j) {
				juli[i][j] = 0;
			}
			else {
				juli[i][j] = sqrt(pow(this->chengshibiao[i][0] - this->chengshibiao[j][0], 2) + pow(this->chengshibiao[i][1] - this->chengshibiao[j][1], 2));
			}
		}
	}
	this->len = juli;
	return juli;
}

同样也是返回指针

1.2使用kroA100.TSP数据集版:

将.tsp文件转换成.txt文件进行读取:

void teacher_data::read_data() {
	string data;
	ifstream inf;
	inf.open("..\\kroA100.txt");
	if (!inf) {
		cout << "error" << endl;
	}
	while (getline(inf, data)) {
		string a = data;
		int i = 0;
		if (a[0] >= '0' && a[0] <= '9') {
			while (a[i] != ' ') {
				i++;
			}
			i++;
			string b;
			while (a[i] != ' ') {
				b.push_back(a[i]);
				i++;
			}
			i++;
			string c;
			while (a[i] >= '0' && a[i] <= '9') {
				c.push_back(a[i]);
				i++;
			}
			vector<int> d;
			d.push_back(stoi(b));
			d.push_back(stoi(c));
			this->data.push_back(d);
		}
	}
	/*for (int i = 0;i < 100;i++) {
		for (int j = 0;j < 2;j++) {
			cout << this->data[i][j];
			cout << "   ";
		}
		cout << endl;
	}*/

	inf.close();
}

计算距离:

double ** teacher_data::jisuanjuli() {
	double** juli = (double**)malloc(100 * sizeof(double*));
	for (int i = 0;i < 100;i++) {
		juli[i] = (double*)malloc(100 * sizeof(double));
		for (int j = 0;j < 100;j++) {
			if (i == j) {
				juli[i][j] = 0;
			}
			else {
				juli[i][j] = sqrt(pow(this->data[i][0] - this->data[j][0], 2) + pow(this->data[i][1] - this->data[j][1], 2));
			}
		}
	}
	this->juli_data = juli;
	return juli;
}

2.禁忌搜索:

整体流程:

vector<int> jinjisousuo::TSP(int x) {
	this->min_len = x;
	this->chushihuajie();
	this->jisuan();
	//this->read_private();
	vector<int> ans;
	double best = 0;
	for (int i = 0;i < this->maxiter;i++) {
		this->xunzhaolingyu();
		auto p= this->xunzhaolingyuzuiyoujie();
		if (p.second == 0) {
			i--;
			this->op++;
			if (op == 7000) {
				break;
			}
			continue;
		}
		ans = p.first;
		best = p.second;
		bool jo=this->teshe(best,ans);
		if (jo == true) {
			jinji(ans);
		}
		this->op = 0;
		cout << "最优解: " <<  this->min_len<< endl;
	}
	return this->zuiyoujie;
}

代码进行了优化,只记录有效迭代,无效迭代会直接舍弃

初始化一个解:

void jinjisousuo::chushihuajie() {

	for (int i = 0;i < jinjisousuo::sum;i++) {
		this->fir.push_back(i);
		this->zuiyoujie.push_back(i);
	}
}

计算要搜索得领域数量:

void jinjisousuo::jisuan() {
	int suml = 0;
	for (int i = 1;i < jinjisousuo::sum;i++) {
		suml = suml + i;
	}
	suml = int(suml * 0.002);
	jinjisousuo::lingyushuliang = suml;
}

确定领域数量之后进行领域搜索

vector<vector<int>> jinjisousuo::xunzhaolingyu() {
	vector<vector<int>> r;
	vector<int> l;
	int len = this->fir.size();
	for (int i = 0;i < len;i++) {
		l.push_back(this->fir[i]);
	}
	for (int i = 0;i <this->lingyushuliang;i++) {
		int k = getRand2(0, this->sum-1);
		int q = 0;
	    q= getRand2(0, this->sum-1);
		int tmp = l[k];
		l[k] = l[q];
		l[q] = tmp;
		//cout << k << "  " << q << endl;
		int j = 0;
		/*while (j < this->num) {
			k = getRand2(0, this->sum - 1);
			q = getRand2(0, this->sum - 1);
			tmp = l[k];
			l[k] = l[q];
			l[q] = tmp;
			j++;
		}*/
		r.push_back(l);
	}
	this->lingyu = r;
	return r;
}

计算每个领域集中得最优解:

pair<vector<int>,double> jinjisousuo::xunzhaolingyuzuiyoujie() {
	auto l = this->fir;
	auto p = this->lingyushuliang;
	double min = 100000000000;
	for (int i = 0;i < p;i++) {
		double j = this->jisuanjuli(lingyu[i]);
		if (j < min) {
			min = j;
			for(int u=0;u<this->fir.size();u++)
				l[u] = lingyu[i][u];
		}
	}
	if (min > this->min_len) {
		min = 0;
	}
	//cout << "min:   " << min << endl;
	return make_pair(l,min);
}

更新禁忌表:


void jinjisousuo::gengxin(vector<int> y) {
	if (t == maxt) {
		vector<vector<int>>::iterator k = this->tabulist.begin();
		this->tabulist.erase(k);
		this->tabulist.push_back(y);
	}
	else {
		this->tabulist.push_back(y);
		this->t++;
	}

}

特赦:

bool jinjisousuo::teshe(int x, vector<int> y) {
	if (pteshe(x) == true) {
		this->zuiyoujie = y;
		this->fir = y;
		this->min_len = x;
		return true;
	}
	else {
		jinji(y);
		return false;
	}
}

禁忌操作:

void jinjisousuo::jinji(vector<int> y) {
	if (this->panduan_in(y) == false) {
		this->fir = y;
		this->gengxin(y);
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

life_exe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值