@softsky/utils 2.7.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -84,6 +84,9 @@ Only deletes last encountered.
84
84
 
85
85
  Returns index of deleted value.
86
86
 
87
+ ---
88
+ __function__ `reverse` - Reverse part of array
89
+
87
90
  ---
88
91
 
89
92
 
@@ -295,14 +298,16 @@ You can use `unfoldPathfindingResult()` to get array of nodes.
295
298
  __function__ `knapsack` - Knapsack find best way to get maximum value in limited capacity
296
299
 
297
300
  ---
298
- __function__ `tspHeldKarp` - Find min path between points. You need to supply 2-dim array
301
+ __function__ `hamiltonianCycle` - Find min path between points. You need to supply 2-dim array
299
302
  where first index is a point and second index is a distance from this point to another.
300
303
  Put infinity if where are no path. Returns cycle (start and end at the same point)
301
304
  Original: https://github.com/qntm/held-karp
302
305
 
303
306
  ---
304
- __function__ `tspHeldKarpPath` - Look for description of `tspHeldKarp`.
305
- Returns path without cycle
307
+ __function__ `traverseByNearestNeighbor` - Traverse all points by nearest neighbor. Should be able to go from any point to any other point.
308
+
309
+ ---
310
+ __function__ `twoOpt` - 2-opt improvement
306
311
 
307
312
  ---
308
313
 
package/dist/arrays.d.ts CHANGED
@@ -48,3 +48,5 @@ export declare function removeFromArray<T>(array: T[], value: T): number;
48
48
  * Returns index of deleted value.
49
49
  */
50
50
  export declare function removeLastFromArray<T>(array: T[], value: T): number;
51
+ /** Reverse part of array */
52
+ export declare function reverse<T>(array: T[], start: number, end: number): T[];
package/dist/arrays.js CHANGED
@@ -133,3 +133,14 @@ export function removeLastFromArray(array, value) {
133
133
  array.splice(index, 1);
134
134
  return index;
135
135
  }
136
+ /** Reverse part of array */
137
+ export function reverse(array, start, end) {
138
+ array = [...array];
139
+ const n = ((end - start + 1) / 2) | 0;
140
+ for (let index = 0; index < n; index++) {
141
+ const temporary = array[start + index];
142
+ array[start + index] = array[end - index];
143
+ array[end - index] = temporary;
144
+ }
145
+ return array;
146
+ }
package/dist/graphs.d.ts CHANGED
@@ -70,15 +70,10 @@ export declare function knapsack(weights: number[], values: number[], capacity:
70
70
  * Put infinity if where are no path. Returns cycle (start and end at the same point)
71
71
  * Original: https://github.com/qntm/held-karp
72
72
  */
73
- export declare function tspHeldKarp(distribution: number[][]): {
74
- distance: number;
75
- path: number[];
76
- };
73
+ export declare function hamiltonianCycle(distribution: number[][]): number[];
77
74
  /**
78
- * Look for description of `tspHeldKarp`.
79
- * Returns path without cycle
75
+ * Traverse all points by nearest neighbor. Should be able to go from any point to any other point.
80
76
  */
81
- export declare function tspHeldKarpPath(d: number[][]): {
82
- distance: number;
83
- path: number[];
84
- };
77
+ export declare function traverseByNearestNeighbor(distribution: number[][]): number[];
78
+ /** 2-opt improvement */
79
+ export declare function twoOpt(tour: number[], distribution: number[][]): number[];
package/dist/graphs.js CHANGED
@@ -137,10 +137,10 @@ export function knapsack(weights, values, capacity) {
137
137
  * Put infinity if where are no path. Returns cycle (start and end at the same point)
138
138
  * Original: https://github.com/qntm/held-karp
139
139
  */
140
- export function tspHeldKarp(distribution) {
140
+ export function hamiltonianCycle(distribution) {
141
141
  const n = distribution.length;
142
142
  if (n === 1)
143
- return { distance: 0, path: [0, 0] };
143
+ return [0, 0];
144
144
  const all = (1 << (n - 1)) - 1;
145
145
  const length = new Float64Array((1 << (n - 1)) * (n - 1));
146
146
  const previous = new Uint8Array((1 << (n - 1)) * (n - 1));
@@ -198,20 +198,60 @@ export function tspHeldKarp(distribution) {
198
198
  S = S2;
199
199
  }
200
200
  const index = cycle.indexOf(0);
201
- return {
202
- distance: cycle.reduce((accumulator, u, index_, cycle) => accumulator +
203
- distribution[u][cycle[index_ + 1 in cycle ? index_ + 1 : 0]], 0),
204
- path: [...cycle.slice(index), ...cycle.slice(0, index), 0],
205
- };
201
+ return [...cycle.slice(index), ...cycle.slice(0, index), 0];
206
202
  }
207
203
  /**
208
- * Look for description of `tspHeldKarp`.
209
- * Returns path without cycle
204
+ * Traverse all points by nearest neighbor. Should be able to go from any point to any other point.
210
205
  */
211
- export function tspHeldKarpPath(d) {
212
- const { distance, path } = tspHeldKarp([
213
- [0, ...new Array(d.length).fill(0)],
214
- ...d.map((d2) => [0, ...d2]),
215
- ]);
216
- return { distance, path: path.slice(1, -1).map((u) => u - 1) };
206
+ export function traverseByNearestNeighbor(distribution) {
207
+ const n = distribution.length;
208
+ const toVisit = new Array(n).fill(true);
209
+ const path = [0];
210
+ let last = 0;
211
+ toVisit[0] = false;
212
+ for (let index = 1; index < n; index++) {
213
+ let nearest = -1;
214
+ let nearestDistribution = Infinity;
215
+ for (let index = 0; index < n; index++) {
216
+ if (toVisit[index] && distribution[last][index] < nearestDistribution) {
217
+ nearest = index;
218
+ nearestDistribution = distribution[last][index];
219
+ }
220
+ }
221
+ path.push(nearest);
222
+ last = nearest;
223
+ toVisit[nearest] = false;
224
+ }
225
+ return path;
226
+ }
227
+ /** 2-opt improvement */
228
+ export function twoOpt(tour, distribution) {
229
+ let improved = true;
230
+ const nStart = tour.length - 2;
231
+ const nEnd = tour.length - 1;
232
+ while (improved) {
233
+ improved = false;
234
+ for (let start = 1; start < nStart; start++) {
235
+ for (let end = start + 1; end < nEnd; end++) {
236
+ const t0 = distribution[tour[start - 1]];
237
+ const t1 = tour[start];
238
+ const tk1 = tour[end];
239
+ const tk2 = tour[end + 1];
240
+ if (t0[tk1] +
241
+ distribution[t1][tk2] -
242
+ t0[t1] -
243
+ distribution[tk1][tk2] <
244
+ -1e-9) {
245
+ const n = ((end - start + 1) / 2) | 0;
246
+ for (let index = 0; index < n; index++) {
247
+ const temporary = tour[start + index];
248
+ tour[start + index] = tour[end - index];
249
+ tour[end - index] = temporary;
250
+ }
251
+ improved = true;
252
+ }
253
+ }
254
+ }
255
+ }
256
+ return tour;
217
257
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softsky/utils",
3
- "version": "2.7.0",
3
+ "version": "2.7.1",
4
4
  "description": "JavaScript/TypeScript utilities",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {