【CPLEX教程03】java調用cplex求解一個TSP問題模型


00 前言

前面我們已經搭建好cplex的java環境了,相信大家已經躍躍欲試,想動手寫幾個模型了。今天就來拿一個TSP的問題模型來給大家演示一下吧~

CPLEX系列教程可以關注我們的公眾號哦!獲取更多精彩消息!

01 TSP建模

關於TSP建模,就不多解釋了。以及什么是TSP問題,也不要問我了。直接貼一個現成的模型出來吧。

02 程序框架

整個程序框架如圖,app下是調用cplex的主要package。


其中:

  • App.java:程序入口,cplex調用建模求解過程。
  • ConstraintFactory.java:控制子環約束的。
  • FileManager.java:讀取instance數據的。

package graph定義了一些變量,在求解過程中需要用到。input是算例,包含100-9000個城市。

03 求解過程

求解過程可以分為以下幾步進行:

  1. 定義一個模型
IloCplex model = new IloCplex();
  1. 定義決策變量,boolVar可以返回一個01的bool類型決策變量。
// define variables
IloIntVar[][] x = new IloIntVar[data.size()][data.size()];
for (int i = 0; i < x.length; i++) {
	for (int j = 0; j < x.length; j++) {
		x[i][j] = model.boolVar("X[" + i + ", " + j + "]");
	}
}

  1. 添加約束7-1,addTerm將1*x[i][j]添加進表達式r里面,最終r的取值是里面所有的元素之和,也就是\(1*x[i][1]+1*x[i][2]+...+1*x[i][n]\)
// one has only a city to go, and should
for (int i = 0; i < x.length; i++) {
	IloLinearIntExpr r = model.linearIntExpr();
	for (int j = 0; j < x.length; j++) {
//						if (i == j)
//							continue;
		r.addTerm(1, x[i][j]);
	}
	model.addEq(r, 1);
}

  1. 添加約束7-2,原理同上一條。
// one can only arrive to one city at a time, and should
for (int j = 0; j < x.length; j++) {
	IloLinearIntExpr r = model.linearIntExpr();
	for (int i = 0; i < x.length; i++) {
//						if (i == j)
//							continue;
		r.addTerm(1, x[i][j]);
	}
	model.addEq(r, 1);
}

  1. 添加約束7-3,子環約束處理有點復雜,但這個不是本文重點,讀者自行理解。
// add cycle restrictions
for (Stack<Edge> stack : stacks) {
//					stack.forEach((edge) -> System.out.println(edge.getFrom() + "->" + edge.getTo()));
	constraintFactory.cycleRestrictions(model, x, stack);
}
  1. 添加目標函數,z的表達式同上。
// one should complete the tour within the smallest distance possible
IloLinearNumExpr z = model.linearNumExpr();
for (int i = 0; i < x.length; i++) {
	for (int j = 0; j < x.length; j++) {
		if (i == j)
			continue;
		z.addTerm(distance[i][j], x[i][j]);
	}
}

  1. 確定目標是最小化目標
model.addMinimize(z);
  1. 開始求解
if (model.solve()) {

	// get tour
	for (int i = 0; i < x.length; i++) {
		for (int j = 0; j < x.length; j++) {
			if (model.getValue(x[i][j]) >= 0.5) {
				tour.add(new Edge(i, j));
			}
		}
	}

	// repaint tour
} else {
	System.err.println("Boi, u sick!");
	System.exit(1);
}

注意,一次求解不一定能求得最優解,小編跑了一個早上都跑不出來,還是100個節點的。model.getValue(x[i][j]) >= 0.5這個判斷只是把求解過程中一些較好的邊給添加進去而已。最優解是要滿足所有約束的。

04 運行說明

代碼下載請關注我們的公眾號哦!后台回復【CPTSP】不包括【】即可下載。

代碼來源GitHub,小編去掉了部分代碼。期待后期進一步精簡和修改,大家下載下來后用eclipse導入,設置好cplex環境以后。在App.java里面,右鍵Run As->Run configurations...:

找到App,在Arguments窗口,找到Program arguments:

輸入參數說明:
--instancePath+空格+算例文件的路徑,注意用英文雙引號括起來。
--maximumRead+空格+數字,表示算例大小,也就是多少個城市,文件名可以直接看出。

然后就可以愉快的run了。

附上運行結果:

大家可以在while(count<1)這個條件里面更改迭代次數,以便能獲取更好的解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM