1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.examples.sofm.tsp;
19
20 import java.io.FileNotFoundException;
21 import java.io.PrintWriter;
22 import java.io.UnsupportedEncodingException;
23 import java.nio.charset.StandardCharsets;
24 import java.util.concurrent.Callable;
25
26 import picocli.CommandLine;
27 import picocli.CommandLine.Option;
28 import picocli.CommandLine.Command;
29
30 import org.apache.commons.rng.UniformRandomProvider;
31 import org.apache.commons.rng.simple.RandomSource;
32
33
34
35
36 @Command(description = "Run the application",
37 mixinStandardHelpOptions = true)
38 public final class StandAlone implements Callable<Void> {
39
40 @Option(names = { "-n" }, paramLabel = "neuronsPerCity",
41 description = "Average number of neurons per city (default: ${DEFAULT-VALUE}).")
42 private double neuronsPerCity = 2.2;
43
44 @Option(names = { "-s" }, paramLabel = "numSamples",
45 description = "Number of samples for the training (default: ${DEFAULT-VALUE}).")
46 private long numSamples = 2000L;
47
48 @Option(names = { "-j" }, paramLabel = "numJobs",
49 description = "Number of concurrent tasks (default: ${DEFAULT-VALUE}).")
50 private int numJobs = Runtime.getRuntime().availableProcessors();
51
52 @Option(names = { "-m" }, paramLabel = "maxTrials",
53 description = "Maximal number of trials (default: ${DEFAULT-VALUE}).")
54 private int maxTrials = 10;
55
56 @Option(names = { "-o" }, paramLabel = "outputFile", required = true,
57 description = "Output file name.")
58 private String outputFile;
59
60
61
62
63
64
65 public static void main(String[] args) {
66 CommandLine.call(new StandAlone(), args);
67 }
68
69 @Override
70 public Void call() throws FileNotFoundException, UnsupportedEncodingException {
71
72 final City[] cities = {
73 new City("o0", 0, 0),
74 new City("o1", 1, 0),
75 new City("o2", 2, 0),
76 new City("o3", 3, 0),
77 new City("o4", 3, 1),
78 new City("o5", 3, 2),
79 new City("o6", 3, 3),
80 new City("o7", 2, 3),
81 new City("o8", 1, 3),
82 new City("o9", 0, 3),
83 new City("i3", 1, 2),
84 new City("i2", 2, 2),
85 new City("i1", 2, 1),
86 new City("i0", 1, 1),
87 };
88
89 final UniformRandomProvider rng = RandomSource.KISS.create();
90 City[] best = null;
91 int maxCities = 0;
92 double minDist = Double.POSITIVE_INFINITY;
93
94 int count = 0;
95 while (count++ < maxTrials) {
96 final City[] travel = TravellingSalesmanSolver.solve(cities,
97 neuronsPerCity,
98 numSamples,
99 numJobs,
100 rng);
101 final int numCities = City.unique(travel).size();
102 if (numCities > maxCities) {
103 best = travel;
104 maxCities = numCities;
105 }
106
107 if (numCities == cities.length) {
108 final double dist = computeDistance(travel);
109 if (dist < minDist) {
110 minDist = dist;
111 best = travel;
112 }
113 }
114 }
115
116 printSummary(outputFile, best, computeDistance(cities));
117
118 return null;
119 }
120
121
122
123
124
125
126
127 private static double computeDistance(City[] cityList) {
128 double dist = 0;
129 for (int i = 0; i < cityList.length; i++) {
130 final double[] currentCoord = cityList[i].getCoordinates();
131 final double[] nextCoord = cityList[(i + 1) % cityList.length].getCoordinates();
132
133 final double xDiff = currentCoord[0] - nextCoord[0];
134 final double yDiff = currentCoord[1] - nextCoord[1];
135
136 dist += Math.sqrt(xDiff * xDiff + yDiff * yDiff);
137 }
138
139 return dist;
140 }
141
142
143
144
145
146
147
148
149
150
151
152 private static void printSummary(String fileName,
153 City[] travel,
154 double optimalDistance)
155 throws FileNotFoundException, UnsupportedEncodingException {
156 try (PrintWriter out = new PrintWriter(fileName, StandardCharsets.UTF_8.name())) {
157 out.println("# Number of unique cities: " + City.unique(travel).size());
158 out.println("# Travel distance: " + computeDistance(travel));
159 out.println("# Optimal travel distance: " + optimalDistance);
160
161 for (final City c : travel) {
162 final double[] coord = c.getCoordinates();
163 out.println(coord[0] + " " + coord[1] + " # " + c.getName());
164 }
165 }
166 }
167 }