Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a1bf70c

Browse filesBrowse files
author
linyiqun
committed
ACO蚁群算法工具类
ACO蚁群算法工具类
1 parent dce1e86 commit a1bf70c
Copy full SHA for a1bf70c

File tree

Expand file treeCollapse file tree

1 file changed

+341
-0
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

1 file changed

+341
-0
lines changed
Open diff view settings
Collapse file

‎Others/DataMining_ACO/ACOTool.java‎

Copy file name to clipboard
+341Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
package DataMining_ACO;
2+
3+
import java.io.BufferedReader;
4+
import java.io.File;
5+
import java.io.FileReader;
6+
import java.io.IOException;
7+
import java.text.MessageFormat;
8+
import java.util.ArrayList;
9+
import java.util.Collections;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
import java.util.Random;
13+
14+
/**
15+
* 蚁群算法工具类
16+
*
17+
* @author lyq
18+
*
19+
*/
20+
public class ACOTool {
21+
// 输入数据类型
22+
public static final int INPUT_CITY_NAME = 1;
23+
public static final int INPUT_CITY_DIS = 2;
24+
25+
// 城市间距离邻接矩阵
26+
public static double[][] disMatrix;
27+
// 当前时间
28+
public static int currentTime;
29+
30+
// 测试数据地址
31+
private String filePath;
32+
// 蚂蚁数量
33+
private int antNum;
34+
// 控制参数
35+
private double alpha;
36+
private double beita;
37+
private double p;
38+
private double Q;
39+
// 随机数产生器
40+
private Random random;
41+
// 城市名称集合,这里为了方便,将城市用数字表示
42+
private ArrayList<String> totalCitys;
43+
// 所有的蚂蚁集合
44+
private ArrayList<Ant> totalAnts;
45+
// 城市间的信息素浓度矩阵,随着时间的增多而减少
46+
private double[][] pheromoneMatrix;
47+
// 目标的最短路径,顺序为从集合的前部往后挪动
48+
private ArrayList<String> bestPath;
49+
// 信息素矩阵存储图,key采用的格式(i,j,t)->value
50+
private Map<String, Double> pheromoneTimeMap;
51+
52+
public ACOTool(String filePath, int antNum, double alpha, double beita,
53+
double p, double Q) {
54+
this.filePath = filePath;
55+
this.antNum = antNum;
56+
this.alpha = alpha;
57+
this.beita = beita;
58+
this.p = p;
59+
this.Q = Q;
60+
this.currentTime = 0;
61+
62+
readDataFile();
63+
}
64+
65+
/**
66+
* 从文件中读取数据
67+
*/
68+
private void readDataFile() {
69+
File file = new File(filePath);
70+
ArrayList<String[]> dataArray = new ArrayList<String[]>();
71+
72+
try {
73+
BufferedReader in = new BufferedReader(new FileReader(file));
74+
String str;
75+
String[] tempArray;
76+
while ((str = in.readLine()) != null) {
77+
tempArray = str.split(" ");
78+
dataArray.add(tempArray);
79+
}
80+
in.close();
81+
} catch (IOException e) {
82+
e.getStackTrace();
83+
}
84+
85+
int flag = -1;
86+
int src = 0;
87+
int des = 0;
88+
int size = 0;
89+
// 进行城市名称种数的统计
90+
this.totalCitys = new ArrayList<>();
91+
for (String[] array : dataArray) {
92+
if (array[0].equals("#") && totalCitys.size() == 0) {
93+
flag = INPUT_CITY_NAME;
94+
95+
continue;
96+
} else if (array[0].equals("#") && totalCitys.size() > 0) {
97+
size = totalCitys.size();
98+
// 初始化距离矩阵
99+
this.disMatrix = new double[size + 1][size + 1];
100+
this.pheromoneMatrix = new double[size + 1][size + 1];
101+
102+
// 初始值-1代表此对应位置无值
103+
for (int i = 0; i < size; i++) {
104+
for (int j = 0; j < size; j++) {
105+
this.disMatrix[i][j] = -1;
106+
this.pheromoneMatrix[i][j] = -1;
107+
}
108+
}
109+
110+
flag = INPUT_CITY_DIS;
111+
continue;
112+
}
113+
114+
if (flag == INPUT_CITY_NAME) {
115+
this.totalCitys.add(array[0]);
116+
} else {
117+
src = Integer.parseInt(array[0]);
118+
des = Integer.parseInt(array[1]);
119+
120+
this.disMatrix[src][des] = Double.parseDouble(array[2]);
121+
this.disMatrix[des][src] = Double.parseDouble(array[2]);
122+
}
123+
}
124+
}
125+
126+
/**
127+
* 计算从蚂蚁城市i到j的概率
128+
*
129+
* @param cityI
130+
* 城市I
131+
* @param cityJ
132+
* 城市J
133+
* @param currentTime
134+
* 当前时间
135+
* @return
136+
*/
137+
private double calIToJProbably(String cityI, String cityJ, int currentTime) {
138+
double pro = 0;
139+
double n = 0;
140+
double pheromone;
141+
int i;
142+
int j;
143+
144+
i = Integer.parseInt(cityI);
145+
j = Integer.parseInt(cityJ);
146+
147+
pheromone = getPheromone(currentTime, cityI, cityJ);
148+
n = 1.0 / disMatrix[i][j];
149+
150+
if (pheromone == 0) {
151+
pheromone = 1;
152+
}
153+
154+
pro = Math.pow(n, alpha) * Math.pow(pheromone, beita);
155+
156+
return pro;
157+
}
158+
159+
/**
160+
* 计算综合概率蚂蚁从I城市走到J城市的概率
161+
*
162+
* @return
163+
*/
164+
public String selectAntNextCity(Ant ant, int currentTime) {
165+
double randomNum;
166+
double tempPro;
167+
// 总概率指数
168+
double proTotal;
169+
String nextCity = null;
170+
ArrayList<String> allowedCitys;
171+
// 各城市概率集
172+
double[] proArray;
173+
174+
// 如果是刚刚开始的时候,没有路过任何城市,则随机返回一个城市
175+
if (ant.currentPath.size() == 0) {
176+
nextCity = String.valueOf(random.nextInt(totalCitys.size()) + 1);
177+
178+
return nextCity;
179+
} else if (ant.nonVisitedCitys.isEmpty()) {
180+
// 如果全部遍历完毕,则再次回到起点
181+
nextCity = ant.currentPath.get(0);
182+
183+
return nextCity;
184+
}
185+
186+
proTotal = 0;
187+
allowedCitys = ant.nonVisitedCitys;
188+
proArray = new double[allowedCitys.size()];
189+
190+
for (int i = 0; i < allowedCitys.size(); i++) {
191+
nextCity = allowedCitys.get(i);
192+
proArray[i] = calIToJProbably(ant.currentPos, nextCity, currentTime);
193+
proTotal += proArray[i];
194+
}
195+
196+
for (int i = 0; i < allowedCitys.size(); i++) {
197+
// 归一化处理
198+
proArray[i] /= proTotal;
199+
}
200+
201+
// 用随机数选择下一个城市
202+
randomNum = random.nextInt(100) + 1;
203+
randomNum = randomNum / 100;
204+
// 因为1.0是无法判断到的,,总和会无限接近1.0取为0.99做判断
205+
if (randomNum == 1) {
206+
randomNum = randomNum - 0.01;
207+
}
208+
209+
tempPro = 0;
210+
// 确定区间
211+
for (int j = 0; j < allowedCitys.size(); j++) {
212+
if (randomNum > tempPro && randomNum <= tempPro + proArray[j]) {
213+
// 采用拷贝的方式避免引用重复
214+
nextCity = allowedCitys.get(j);
215+
break;
216+
} else {
217+
tempPro += proArray[j];
218+
}
219+
}
220+
221+
return nextCity;
222+
}
223+
224+
/**
225+
* 获取给定时间点上从城市i到城市j的信息素浓度
226+
*
227+
* @param t
228+
* @param cityI
229+
* @param cityJ
230+
* @return
231+
*/
232+
private double getPheromone(int t, String cityI, String cityJ) {
233+
double pheromone = 0;
234+
String key;
235+
236+
// 上一周期需将时间倒回一周期
237+
key = MessageFormat.format("{0},{1},{2}", cityI, cityJ, t);
238+
239+
if (pheromoneTimeMap.containsKey(key)) {
240+
pheromone = pheromoneTimeMap.get(key);
241+
}
242+
243+
return pheromone;
244+
}
245+
246+
/**
247+
* 每轮结束,刷新信息素浓度矩阵
248+
*
249+
* @param t
250+
*/
251+
private void refreshPheromone(int t) {
252+
double pheromone = 0;
253+
// 上一轮周期结束后的信息素浓度,丛信息素浓度图中查找
254+
double lastTimeP = 0;
255+
// 本轮信息素浓度增加量
256+
double addPheromone;
257+
String key;
258+
259+
for (String i : totalCitys) {
260+
for (String j : totalCitys) {
261+
if (!i.equals(j)) {
262+
// 上一周期需将时间倒回一周期
263+
key = MessageFormat.format("{0},{1},{2}", i, j, t - 1);
264+
265+
if (pheromoneTimeMap.containsKey(key)) {
266+
lastTimeP = pheromoneTimeMap.get(key);
267+
} else {
268+
lastTimeP = 0;
269+
}
270+
271+
addPheromone = 0;
272+
for (Ant ant : totalAnts) {
273+
// 每只蚂蚁传播的信息素为控制因子除以距离总成本
274+
addPheromone += Q / ant.calSumDistance();
275+
}
276+
277+
// 将上次的结果值加上递增的量,并存入图中
278+
pheromone = p * lastTimeP + addPheromone;
279+
key = MessageFormat.format("{0},{1},{2}", i, j, t);
280+
pheromoneTimeMap.put(key, pheromone);
281+
}
282+
}
283+
}
284+
285+
}
286+
287+
public void antStartSearching() {
288+
// 蚁群寻找的总次数
289+
int loopCount = 0;
290+
// 选中的下一个城市
291+
String selectedCity = "";
292+
293+
pheromoneTimeMap = new HashMap<String, Double>();
294+
totalAnts = new ArrayList<>();
295+
random = new Random();
296+
297+
while (loopCount < 10) {
298+
initAnts();
299+
300+
while (true) {
301+
for (Ant ant : totalAnts) {
302+
selectedCity = selectAntNextCity(ant, currentTime);
303+
ant.goToNextCity(selectedCity);
304+
}
305+
306+
// 如果已经遍历完所有城市,则跳出此轮循环
307+
if (totalAnts.get(0).isBack()) {
308+
break;
309+
}
310+
}
311+
312+
// 周期时间叠加
313+
currentTime++;
314+
refreshPheromone(currentTime);
315+
}
316+
317+
// 根据距离成本,选出所花距离最短的一个路径
318+
Collections.sort(totalAnts);
319+
bestPath = totalAnts.get(0).currentPath;
320+
for (String cityName : bestPath) {
321+
System.out.println(MessageFormat.format("-->{0}", cityName));
322+
}
323+
}
324+
325+
/**
326+
* 初始化蚁群操作
327+
*/
328+
private void initAnts() {
329+
Ant tempAnt;
330+
ArrayList<String> nonVisitedCitys;
331+
totalAnts.clear();
332+
333+
// 初始化蚁群
334+
for (int i = 0; i < antNum; i++) {
335+
nonVisitedCitys = (ArrayList<String>) totalCitys.clone();
336+
tempAnt = new Ant(pheromoneMatrix, nonVisitedCitys);
337+
338+
totalAnts.add(tempAnt);
339+
}
340+
}
341+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.