Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Good heuristic for the traveling salesman problem using simulated annealing.
- [salesman](#salesman)
- [salesman~Point](#salesmanpoint)
- [new Point(x, y)](#new-pointx-y)
- [salesman~solve(points, \[temp\_coeff\], \[callback\], \[callback\]) ⇒ Array.\<number\>](#salesmansolvepoints-temp_coeff-callback-callback--arraynumber)
- [salesman~solve(points, \[temp\_coeff\], \[callback\], \[callback\], \[keep\_end\]) ⇒ Array.\<number\>](#salesmansolvepoints-temp_coeff-callback-callback-keep_end--arraynumber)

<a name="module_salesman..Point"></a>

Expand All @@ -31,7 +31,7 @@ Represents a point in two dimensions. Used as the input for `solve`.

<a name="module_salesman..solve"></a>

### salesman~solve(points, [temp_coeff], [callback], [callback]) ⇒ <code>Array.&lt;number&gt;</code>
### salesman~solve(points, [temp_coeff], [callback], [callback], [keep_end]) ⇒ <code>Array.&lt;number&gt;</code>
Solves the following problem:
Given a list of points and the distances between each pair of points,
what is the shortest possible route that visits each point exactly
Expand All @@ -46,6 +46,7 @@ Solves the following problem:
| [temp_coeff] | <code>number</code> | <code>0.999</code> | changes the convergence speed of the algorithm. Smaller values (0.9) work faster but give poorer solutions, whereas values closer to 1 (0.99999) work slower, but give better solutions. |
| [callback] | <code>function</code> | | An optional callback to be called after each iteration. |
| [callback] | <code>function</code> | <code>euclidean</code> | An optional argument to specify how distances are calculated. The function takes two Point objects as arguments and returns a number for distance. Defaults to simple Euclidean distance calculation. |
| [keep_end] | <code>boolean</code> | <code>false</code> | An optional argument to specify if the last point is fixed. If false then the minimum circuit is calculated, if true the minimum path from first to last node is calculated. |

**Example**
```js
Expand Down
3 changes: 2 additions & 1 deletion salesman.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* @param [temp_coeff=0.999] changes the convergence speed of the algorithm: the closer to 1, the slower the algorithm and the better the solutions.
* @param [callback=] An optional callback to be called after each iteration.
* @param [distance=euclidean] An optional argument to specify how distances are calculated. The function takes two Point objects as arguments and returns a number for distance. Defaults to simple Euclidean distance calculation.
* @param [keep_end=false] An optional argument to specify if the last point is fixed. If false then the minimum circuit is calculated, if true the minimum path from first to last node is calculated.
*
* @returns An array of indexes in the original array. Indicates in which order the different points are visited.
*
Expand All @@ -25,7 +26,7 @@
* var ordered_points = solution.map(i => points[i]);
* // ordered_points now contains the points, in the order they ought to be visited.
*/
export function solve(points: Point[], temp_coeff?: number, callback?: (order: number[]) => void, distance?: (p: Point, q: Point) => number): number[];
export function solve(points: Point[], temp_coeff?: number, callback?: (order: number[]) => void, distance?: (p: Point, q: Point) => number, keep_end?: boolean): number[];

export class Point {
/**
Expand Down
12 changes: 7 additions & 5 deletions salesman.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
* along with an array which maintains a record of distances between points.
* @param {Points[]} points The points in the path.
* @param {Function} distanceFunc The function to use to calculate the distance between two points.
*/
function Path(points, distanceFunc) {
* @param {boolean} keepEnd Specify if the last point is fixed. If false then the minimum circuit is calculated, if true the minimum path from first to last node is calculated.
*/
function Path(points, distanceFunc, keepEnd) {
this.points = points;
this.distanceFunc = distanceFunc;
this.keepEnd = keepEnd;
this.initializeOrder();
this.initializeDistances();
}
Expand Down Expand Up @@ -140,7 +142,7 @@ Path.prototype.distance = function(i, j) {
* @returns {number} A random index.
*/
Path.prototype.randomPos = function() {
return 1 + Math.floor(Math.random() * (this.points.length - 1));
return 1 + Math.floor(Math.random() * (this.points.length - (this.keepEnd ? 2 : 1)));
};

/**
Expand Down Expand Up @@ -176,8 +178,8 @@ function Point(x, y) {
* var ordered_points = solution.map(i => points[i]);
* // ordered_points now contains the points, in the order they ought to be visited.
**/
function solve(points, temp_coeff = 0.999, callback, distance = euclidean) {
var path = new Path(points, distance);
function solve(points, temp_coeff = 0.999, callback, distance = euclidean, keep_end = false) {
var path = new Path(points, distance, keep_end);
// Optimization: If there is only one point in the list, there is no path.
if (points.length < 2) return path.order;
// Optimization: If the user would provide a bad input, end immediately.
Expand Down
3 changes: 2 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ var salesman = require("./salesman.js");
var tests = [
{q:[[0,0]], r:[0]},
{q:[[0,0],[1,1]], r:[0,1]},
{q:[[0,0],[2,2],[1,1]], r:[0,1,2], e: true},
];


for(let test of tests) {
var points = test.q.map(([x,y])=>new salesman.Point(x,y));
var res = salesman.solve(points);
var res = salesman.solve(points, undefined, undefined, undefined, test.e);
assert.deepEqual(test.r, res);
}