@mark1russell7/highways 0.5.1 → 0.6.0

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/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "directory": "packages/core"
10
10
  },
11
11
  "homepage": "https://mark1russell7.github.io/highways/",
12
- "version": "0.5.1",
12
+ "version": "0.6.0",
13
13
  "type": "module",
14
14
  "main": "./build/index.js",
15
15
  "types": "./build/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@mark1russell7/layout-contract": "^0.2.6"
32
+ "@mark1russell7/layout-contract": "^0.2.7"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@mark1russell7/cue": "github:mark1russell7/cue",
@@ -219,33 +219,179 @@ export function exactModel(graph: Graph, o: Readonly<ExactOptions>): ExactModel
219
219
  return { lp, columns: binaries.length, rows: rows.length, edges: arcsOf.length, lengths, decode };
220
220
  }
221
221
 
222
+ /** A binary heap of node indexes by a key, smallest first. A node can be in the heap more than one time. The search skips an old entry. */
223
+ class NodeHeap {
224
+ #key: Float64Array = new Float64Array(64);
225
+ #node: Int32Array = new Int32Array(64);
226
+ size = 0;
227
+
228
+ push(key: number, node: number): void {
229
+ if (this.size === this.#key.length) {
230
+ const k = new Float64Array(2 * this.size);
231
+ k.set(this.#key);
232
+ this.#key = k;
233
+ const n = new Int32Array(2 * this.size);
234
+ n.set(this.#node);
235
+ this.#node = n;
236
+ }
237
+ const keys = this.#key;
238
+ const nodes = this.#node;
239
+ let i = this.size++;
240
+ while (i > 0) {
241
+ const up = (i - 1) >> 1;
242
+ if (keys[up]! <= key) break;
243
+ keys[i] = keys[up]!;
244
+ nodes[i] = nodes[up]!;
245
+ i = up;
246
+ }
247
+ keys[i] = key;
248
+ nodes[i] = node;
249
+ }
250
+
251
+ /** This method removes the node with the smallest key, and gives it. */
252
+ pop(): number {
253
+ const keys = this.#key;
254
+ const nodes = this.#node;
255
+ const top = nodes[0]!;
256
+ const n = --this.size;
257
+ const key = keys[n]!;
258
+ const node = nodes[n]!;
259
+ let i = 0;
260
+ for (;;) {
261
+ let c = 2 * i + 1;
262
+ if (c >= n) break;
263
+ if (c + 1 < n && keys[c + 1]! < keys[c]!) c++;
264
+ if (keys[c]! >= key) break;
265
+ keys[i] = keys[c]!;
266
+ nodes[i] = nodes[c]!;
267
+ i = c;
268
+ }
269
+ keys[i] = key;
270
+ nodes[i] = node;
271
+ return top;
272
+ }
273
+ }
274
+
222
275
  /**
223
- * This function gives the stretch of each route as the exact model counts it, by the edge id.
224
- * The stretch of a route is its length without its two plug ends, divided by the shortest way in the network of the model.
225
- * The function builds the network one time. The result function then measures each list of routes of the graph, so a portfolio pays for the network once.
226
- * An edge without a route or without a way in the network has no value.
276
+ * This function gives the shortest distance from `start` to each node of `targets` (A*). The search stops when it has each target.
277
+ * The guide is the straight distance to the nearest target. Each link is a straight line, so the guide is not above the true distance at any time.
278
+ * Thus the distances are the distances of Dijkstra. Only the order of the search changes.
279
+ * A target that the search cannot reach gets `Infinity`.
227
280
  */
228
- export function exactStretches(graph: Graph, o: Readonly<WayOptions> = {}): (routes: readonly Route[]) => Map<string, number> {
229
- const { adj, ends, margin } = exactNetwork(graph, o);
230
- const best = new Map<number, Float64Array>();
231
- const from = (a: number): Float64Array => {
232
- if (!best.has(a)) best.set(a, distances(adj, a));
233
- return best.get(a)!;
281
+ function distancesTo(points: readonly Point[], adj: readonly (readonly { to: number; len: number }[])[], start: number, targets: readonly number[]): Map<number, number> {
282
+ const d = new Float64Array(adj.length).fill(Infinity);
283
+ const done = new Uint8Array(adj.length);
284
+ const goal = new Set(targets);
285
+ const ends = targets.map((t) => points[t]!);
286
+ const guide = (v: number): number => {
287
+ let h = Infinity;
288
+ for (const t of ends) h = Math.min(h, dist(points[v]!, t));
289
+ return h;
234
290
  };
291
+ const heap = new NodeHeap();
292
+ d[start] = 0;
293
+ heap.push(guide(start), start);
294
+ let left = goal.size;
295
+ while (heap.size > 0 && left > 0) {
296
+ const u = heap.pop();
297
+ if (done[u]) continue;
298
+ done[u] = 1;
299
+ if (goal.has(u)) left--;
300
+ for (const { to, len } of adj[u]!) {
301
+ const nd = d[u]! + len;
302
+ if (nd < d[to]!) {
303
+ d[to] = nd;
304
+ // A rounding error can make the guide a little too large. Then a node opens again, so its distance stays the least.
305
+ done[to] = 0;
306
+ heap.push(nd + guide(to), to);
307
+ }
308
+ }
309
+ }
310
+ return new Map(targets.map((t) => [t, d[t]!]));
311
+ }
312
+
313
+ /**
314
+ * This function gives the shortest distance in the network between the two end points of each edge, by the pair `a,b` of the end points.
315
+ * The distance does not depend on the direction, so one search serves each edge between the same two points.
316
+ * An end point of many edges starts one search to all its other end points. The function starts the searches from the end points with the most edges first.
317
+ */
318
+ function pairDistances(network: ExactNetwork): Map<string, number> {
319
+ const pairKey = (a: number, b: number): string => (a < b ? `${a},${b}` : `${b},${a}`);
320
+ const partners = new Map<number, Set<number>>();
321
+ const open = new Set<string>();
322
+ for (const e of network.ends) {
323
+ if (e.a === e.b) continue;
324
+ const k = pairKey(e.a, e.b);
325
+ if (open.has(k)) continue;
326
+ open.add(k);
327
+ for (const [u, v] of [
328
+ [e.a, e.b],
329
+ [e.b, e.a],
330
+ ] as const) {
331
+ if (!partners.has(u)) partners.set(u, new Set());
332
+ partners.get(u)!.add(v);
333
+ }
334
+ }
335
+ const out = new Map<string, number>();
336
+ const order = [...partners.keys()].sort((u, v) => partners.get(v)!.size - partners.get(u)!.size || u - v);
337
+ for (const u of order) {
338
+ const targets = [...partners.get(u)!].filter((v) => open.has(pairKey(u, v)));
339
+ if (targets.length === 0) continue;
340
+ for (const [v, len] of distancesTo(network.points, network.adj, u, targets)) {
341
+ const k = pairKey(u, v);
342
+ out.set(k, len);
343
+ open.delete(k);
344
+ }
345
+ }
346
+ return out;
347
+ }
348
+
349
+ /** This function gives the function of the stretch of each route of the graph, from the network and the shortest distance of each edge. */
350
+ function stretchesOf(network: ExactNetwork, best: (e: ExactNetwork["ends"][number]) => number): (routes: readonly Route[]) => Map<string, number> {
235
351
  return (routes) => {
236
352
  const byEdge = new Map(routes.map((r) => [r.edge, r]));
237
353
  const out = new Map<string, number>();
238
- for (const e of ends) {
354
+ for (const e of network.ends) {
239
355
  const r = byEdge.get(e.edge.id);
240
356
  if (!r || r.points.length < 2 || e.a === e.b) continue;
241
- const b = from(e.a)[e.b]!;
357
+ const b = best(e);
242
358
  if (!Number.isFinite(b) || b <= 1) continue;
243
- out.set(e.edge.id, (polylineLength(r.points) - 2 * margin) / b);
359
+ out.set(e.edge.id, (polylineLength(r.points) - 2 * network.margin) / b);
244
360
  }
245
361
  return out;
246
362
  };
247
363
  }
248
364
 
365
+ /**
366
+ * This function gives the stretch of each route as the exact model counts it, by the edge id.
367
+ * The stretch of a route is its length without its two plug ends, divided by the shortest way in the network of the model.
368
+ * The function builds the network one time. The result function then measures each list of routes of the graph, so a portfolio pays for the network once.
369
+ * The first call finds the shortest ways with one A* search for each end point with edges (PORTFOLIO-SPEED). The later calls use them again.
370
+ * An edge without a route or without a way in the network has no value.
371
+ */
372
+ export function exactStretches(graph: Graph, o: Readonly<WayOptions> = {}): (routes: readonly Route[]) => Map<string, number> {
373
+ const network = exactNetwork(graph, o);
374
+ let best: Map<string, number> | undefined;
375
+ return stretchesOf(network, (e) => {
376
+ best ??= pairDistances(network);
377
+ return best.get(e.a < e.b ? `${e.a},${e.b}` : `${e.b},${e.a}`) ?? Infinity;
378
+ });
379
+ }
380
+
381
+ /**
382
+ * This function gives the same values as `exactStretches` with the search of the first version. That search is one full Dijkstra with a scan, from the first end point of each edge.
383
+ * It is slow on large boards. The tests and the check `portfolio:time --check-stretch` compare the two functions.
384
+ */
385
+ export function exactStretchesReference(graph: Graph, o: Readonly<WayOptions> = {}): (routes: readonly Route[]) => Map<string, number> {
386
+ const network = exactNetwork(graph, o);
387
+ const best = new Map<number, Float64Array>();
388
+ const from = (a: number): Float64Array => {
389
+ if (!best.has(a)) best.set(a, distances(network.adj, a));
390
+ return best.get(a)!;
391
+ };
392
+ return stretchesOf(network, (e) => from(e.a)[e.b]!);
393
+ }
394
+
249
395
  /**
250
396
  * This function gives the largest stretch of routes as the exact model counts it (`exactStretches`).
251
397
  * The cap of the model is a limit on this value.
package/src/index.ts CHANGED
@@ -29,6 +29,8 @@ export * from "./bench/suite.ts";
29
29
  export * from "./strategies/index.ts";
30
30
  export * from "./bench/compare.ts";
31
31
  export * from "./bench/screen/index.ts";
32
+ // The stretch of the exact model, for a benchmark that compares routers with the measures of the portfolio (PORTFOLIO-SPEED).
33
+ export { exactStretch, exactStretches } from "./bench/exact/index.ts";
32
34
  export * from "./highways/index.ts";
33
35
  export * from "./order/index.ts";
34
36
  export * from "./repair/index.ts";
@@ -20,11 +20,16 @@ export interface PortfolioBand {
20
20
  readonly maxNodes: number;
21
21
  }
22
22
 
23
- /** The size bands: up to 12 nodes, 13 to 24 nodes, and 25 to 40 nodes. An input above 40 nodes uses the band `n25-40`. */
23
+ /**
24
+ * The size bands: up to 12 nodes, 13 to 24 nodes, 25 to 40 nodes, 41 to 64 nodes and 65 to 128 nodes. An input above 128 nodes uses the band `n65-128`.
25
+ * The two large bands come from PORTFOLIO-SPEED. Their boards have no optima, so their sets come from the B1 under the guard.
26
+ */
24
27
  export const PORTFOLIO_BANDS: readonly PortfolioBand[] = [
25
28
  { id: "n1-12", maxNodes: 12 },
26
29
  { id: "n13-24", maxNodes: 24 },
27
30
  { id: "n25-40", maxNodes: 40 },
31
+ { id: "n41-64", maxNodes: 64 },
32
+ { id: "n65-128", maxNodes: 128 },
28
33
  ];
29
34
 
30
35
  /** This function gives the band of a node count: the first band whose `maxNodes` is the count or more, else the last band. */
@@ -1,29 +1,41 @@
1
1
  // This file is generated by `scripts/portfolio-sets.ts` (`pnpm portfolio:sets`). Do not edit it. The test `sets.test.ts` checks that it is current.
2
- // The times come from the CI run 40658558076 (the workflow `Portfolio`, `portfolio:time --members`).
2
+ // The times come from the CI run 40670252502 (the workflow `Portfolio`, `portfolio:time --members`).
3
3
  import type { PortfolioCap, PortfolioRule } from "./bands.ts";
4
4
 
5
5
  /**
6
6
  * The fit of each rule, cap and size band, by the key `<rule>|<cap>|<band>`: the members of the default of the portfolio router, in their order.
7
- * Each member has a node limit: it runs only on an input with that many nodes or fewer. The limits keep the model time at or below 40 ms.
7
+ * Each member has a node limit: it runs only on an input with that many nodes or fewer. The limits keep the model time at or below 42 ms.
8
8
  * The base `shared` is not in a fit: the portfolio always runs it first.
9
9
  */
10
10
  export const PORTFOLIO_FIT: Readonly<Record<`${PortfolioRule}|${PortfolioCap}|${string}`, readonly (readonly [string, number])[]>> = {
11
11
  "collection|1.1|n1-12": [["corners-side", 12], ["w2c:select+stretch", 12], ["trunks-gilbert-a05", 12], ["w3a:spiral-a15", 12], ["trunks-tree-bf08", 12], ["hw:zipper", 12], ["w2c:level-links+stretch-b1.1", 12], ["hw:stubs", 12]],
12
- "collection|1.1|n13-24": [["w3e:crossbars+stretch", 24], ["corners-side", 24], ["shared-p2", 24], ["w2c:zipper+stretch-b1.1", 18], ["trunks-tree-bf08", 18], ["hw:weiszfeld", 18]],
13
- "collection|1.1|n25-40": [["w2a:shared-ways+breakeven", 32], ["w2b:weiszfeld-a1", 32]],
12
+ "collection|1.1|n13-24": [["w3e:crossbars+stretch", 24], ["trunks-tree-bf08", 24], ["corners-side", 24], ["shared-p2", 24], ["w2c:zipper+stretch-b1.1", 18]],
13
+ "collection|1.1|n25-40": [["w2a:shared-ways+breakeven", 40], ["w2b:weiszfeld-a1", 32]],
14
+ "collection|1.1|n41-64": [],
15
+ "collection|1.1|n65-128": [],
14
16
  "collection|1.25|n1-12": [["corners-side", 12], ["trunks-tree-bf06", 12], ["w3f:p-hub-a0.2", 12], ["hw:stubs", 12], ["hw:p-hub", 12], ["hw:spiral", 12], ["w2c:level-links+stretch", 12], ["w3f:spectral-c0.3", 12]],
15
- "collection|1.25|n13-24": [["w2a:shared-ways+stretch", 24], ["shared-p3", 24], ["trunks-gilbert-a07", 24], ["w3e:crossbars+stretch", 24], ["trunks-tree-bf06", 18], ["w3c:hdbscan+stretch", 18], ["shared-wind-p2-r1-e2", 18], ["hw:stubs", 18]],
16
- "collection|1.25|n25-40": [["w2a:shared-ways+stretch", 32], ["shared-p3", 32], ["shared-order-shortest", 32]],
17
+ "collection|1.25|n13-24": [["w2a:shared-ways+stretch", 24], ["shared-p3", 24], ["trunks-gilbert-a07", 24], ["w3e:crossbars+stretch", 24], ["trunks-tree-bf06", 24], ["w3c:hdbscan+stretch", 18], ["shared-wind-p2-r1-e2", 18]],
18
+ "collection|1.25|n25-40": [["w2a:shared-ways+stretch", 40], ["shared-p3", 40], ["shared-order-shortest", 32]],
19
+ "collection|1.25|n41-64": [],
20
+ "collection|1.25|n65-128": [],
17
21
  "collection|1.5|n1-12": [["trunks-gilbert-a03", 12], ["w3e:areas-keys", 12], ["trunks-tree-bf02", 12], ["w3f:p-hub-a0.2", 12], ["w2b:zipper-a1", 12], ["w3a:spiral-a35", 12], ["w3f:spectral-c0.3", 12], ["w2c:level-links+stretch", 12]],
18
- "collection|1.5|n13-24": [["shared-wind-p2-r0.5", 24], ["trunks-gilbert-a03", 24], ["w3e:crossbars+stretch", 24], ["shared-wind-p2-r1-e2", 24], ["trunks-tree-bf06", 24], ["shared-flow-a06-p3", 18], ["shared-wind-p3-r1", 18], ["trunks-gilbert-a07", 18]],
19
- "collection|1.5|n25-40": [["shared-p3", 40], ["hw:lanes", 32], ["shared-wind-p2-r1-e2", 32]],
20
- "all|1.1|n1-12": [["w2b:zipper-p2", 12], ["hw:cubu", 12], ["w3d:kdeeb+stretch", 12], ["w3c:hough-wide", 12], ["w3d:kdeeb-routes", 12], ["hw:stubs", 12], ["hw:spiral", 12], ["w3b:growth-s0.7", 12]],
22
+ "collection|1.5|n13-24": [["shared-wind-p2-r0.5", 24], ["trunks-gilbert-a03", 24], ["w3e:crossbars+stretch", 24], ["shared-wind-p2-r1-e2", 24], ["trunks-tree-bf06", 24], ["shared-flow-a06-p3", 24], ["shared-wind-p3-r1", 18], ["trunks-gilbert-a07", 18]],
23
+ "collection|1.5|n25-40": [["shared-p3", 40], ["hw:lanes", 40], ["shared-wind-p2-r1-e2", 32]],
24
+ "collection|1.5|n41-64": [["shared-flow-a06-p3", 64]],
25
+ "collection|1.5|n65-128": [],
26
+ "all|1.1|n1-12": [["w2b:zipper-p2", 12], ["hw:cubu", 12], ["w3d:kdeeb+stretch", 12], ["w3c:hough-wide", 12], ["w3d:kdeeb-routes", 12], ["hw:stubs", 10], ["hw:spiral", 10], ["w3b:growth-s0.7", 10]],
21
27
  "all|1.1|n13-24": [["w3e:frechet-e0.5", 24], ["w3a:diffusion-wide", 24], ["w2c:zipper+stretch-b1.1", 24], ["w3d:cubu+stretch", 18]],
22
- "all|1.1|n25-40": [["w2c:zipper+stretch-b1.1", 32], ["w3a:spiral-a15", 32]],
23
- "all|1.25|n1-12": [["w3d:kdeeb-routes", 12], ["w3e:mlseb+stretch", 12], ["hw:growth", 12], ["hw:level-links", 12], ["w3b:growth-input", 12], ["w3e:confluent+stretch", 12], ["w3d:kdeeb-nomask", 10], ["w3a:diffusion-g2", 10]],
24
- "all|1.25|n13-24": [["w3d:kdeeb-routes", 24], ["w3e:mlseb+stretch", 18]],
25
- "all|1.25|n25-40": [["w3d:kdeeb-routes", 32]],
26
- "all|1.5|n1-12": [["w3b:growth-s0.3", 12], ["w3e:mlseb-a0", 12], ["w3e:mlseb-routes", 10], ["w3c:edge-paths-k1.5", 10]],
28
+ "all|1.1|n25-40": [["w2c:zipper+stretch-b1.1", 40], ["w3a:spiral-a15", 32]],
29
+ "all|1.1|n41-64": [],
30
+ "all|1.1|n65-128": [],
31
+ "all|1.25|n1-12": [["w3d:kdeeb-routes", 12], ["w3e:mlseb+stretch", 12], ["hw:growth", 12], ["hw:level-links", 10], ["w3b:growth-input", 10], ["w3e:confluent+stretch", 10]],
32
+ "all|1.25|n13-24": [["w3d:kdeeb-routes", 24], ["w3f:p-hub-a0.2", 18], ["w3d:kdeeb-nomask", 18]],
33
+ "all|1.25|n25-40": [],
34
+ "all|1.25|n41-64": [],
35
+ "all|1.25|n65-128": [],
36
+ "all|1.5|n1-12": [["w3b:growth-s0.3", 12], ["w3e:mlseb-a0", 12], ["w3e:mlseb-routes", 10], ["w3c:edge-paths-k1.5", 10], ["w3f:territories-r2", 10]],
27
37
  "all|1.5|n13-24": [["hw:growth", 24], ["w3b:growth-input", 24]],
28
- "all|1.5|n25-40": [["hw:growth", 40], ["w3b:growth-s0.7", 32], ["w3b:growth-s0.3", 32]],
38
+ "all|1.5|n25-40": [["hw:growth", 40], ["w3b:growth-s0.7", 40]],
39
+ "all|1.5|n41-64": [],
40
+ "all|1.5|n65-128": [],
29
41
  };
@@ -1,5 +1,5 @@
1
1
  // This file is generated by `scripts/portfolio-sets.ts` (`pnpm portfolio:sets`). Do not edit it. The test `sets.test.ts` checks that it is current.
2
- // The records come from the CI runs 40631516113, 40644555345, 40644557536, 40644560237, 40644562652, 40644565132, 40644567956, 40644570455, 40644572910, 40644575649, 40644578541, 40644580965, 40644583603.
2
+ // The records come from the CI runs 40631516113, 40644555345, 40644557536, 40644560237, 40644562652, 40644565132, 40644567956, 40644570455, 40644572910, 40644575649, 40644578541, 40644580965, 40644583603, 40665016754.
3
3
  import type { PortfolioCap, PortfolioRule } from "./bands.ts";
4
4
 
5
5
  /**
@@ -8,21 +8,33 @@ import type { PortfolioCap, PortfolioRule } from "./bands.ts";
8
8
  */
9
9
  export const PORTFOLIO_SETS: Readonly<Record<`${PortfolioRule}|${PortfolioCap}|${string}`, readonly string[]>> = {
10
10
  "collection|1.1|n1-12": ["corners-side", "w2c:select+stretch", "trunks-gilbert-a05", "w3a:spiral-a15", "trunks-tree-bf08", "hw:zipper", "w2c:level-links+stretch-b1.1", "hw:stubs"],
11
- "collection|1.1|n13-24": ["w3e:crossbars+stretch", "corners-side", "shared-p2", "w2c:zipper+stretch-b1.1", "trunks-tree-bf08", "hw:weiszfeld", "trunks-gilbert-a07", "hw:stubs"],
11
+ "collection|1.1|n13-24": ["w3e:crossbars+stretch", "trunks-tree-bf08", "corners-side", "shared-p2", "w2c:zipper+stretch-b1.1", "hw:weiszfeld", "trunks-gilbert-a07", "hw:stubs"],
12
12
  "collection|1.1|n25-40": ["w2a:shared-ways+breakeven", "w2b:weiszfeld-a1", "w2c:level-links+stretch-b1.1"],
13
+ "collection|1.1|n41-64": [],
14
+ "collection|1.1|n65-128": [],
13
15
  "collection|1.25|n1-12": ["corners-side", "trunks-tree-bf06", "w3f:p-hub-a0.2", "hw:stubs", "hw:p-hub", "hw:spiral", "w2c:level-links+stretch", "w3f:spectral-c0.3"],
14
16
  "collection|1.25|n13-24": ["w2a:shared-ways+stretch", "shared-p3", "trunks-gilbert-a07", "w3e:crossbars+stretch", "trunks-tree-bf06", "w3c:hdbscan+stretch", "shared-wind-p2-r1-e2", "hw:stubs"],
15
17
  "collection|1.25|n25-40": ["w2a:shared-ways+stretch", "shared-p3", "shared-order-shortest", "w2b:weiszfeld-a1", "w3e:crossbars+stretch", "trunks-tree-bf08", "w2a:shared-ways+ambiguity", "w2b:weiszfeld-a0"],
18
+ "collection|1.25|n41-64": ["hw:lanes", "w3e:crossbars+stretch", "w2a:shared-ways+stretch", "shared-flow-a06-p3"],
19
+ "collection|1.25|n65-128": ["hw:lanes"],
16
20
  "collection|1.5|n1-12": ["trunks-gilbert-a03", "w3e:areas-keys", "trunks-tree-bf02", "w3f:p-hub-a0.2", "w2b:zipper-a1", "w3a:spiral-a35", "w3f:spectral-c0.3", "w2c:level-links+stretch"],
17
21
  "collection|1.5|n13-24": ["shared-wind-p2-r0.5", "trunks-gilbert-a03", "w3e:crossbars+stretch", "shared-wind-p2-r1-e2", "trunks-tree-bf06", "shared-flow-a06-p3", "shared-wind-p3-r1", "trunks-gilbert-a07"],
18
22
  "collection|1.5|n25-40": ["shared-p3", "hw:lanes", "shared-wind-p2-r1-e2", "hw:crossbars", "shared-flow-a06-p3", "trunks-tree-bf06", "shared-wind-p2-r1", "shared-wind-p2-r2"],
23
+ "collection|1.5|n41-64": ["shared-flow-a06-p3", "hw:lanes", "shared-p2", "trunks-tree-bf06"],
24
+ "collection|1.5|n65-128": ["shared-p2", "shared-p3", "shared-flow-a06-p3", "hw:lanes"],
19
25
  "all|1.1|n1-12": ["w2b:zipper-p2", "hw:cubu", "w3d:kdeeb+stretch", "w3c:hough-wide", "w3d:kdeeb-routes", "hw:stubs", "hw:spiral", "w3b:growth-s0.7"],
20
26
  "all|1.1|n13-24": ["w3e:frechet-e0.5", "w3a:diffusion-wide", "w2c:zipper+stretch-b1.1", "w3d:cubu+stretch", "w3a:spiral-a15", "w3d:kdeeb-routes", "hw:diffusion", "hw:mesh"],
21
27
  "all|1.1|n25-40": ["w2c:zipper+stretch-b1.1", "w3a:spiral-a15", "w3d:mesh+stretch", "w3a:diffusion+stretch", "w3a:diffusion-wide", "w2c:road-classes-d0.3", "w3d:kdeeb-routes"],
28
+ "all|1.1|n41-64": ["hw:diffusion", "w3a:spiral-a15", "w2c:zipper+stretch-b1.1", "w3e:frechet-e0.5"],
29
+ "all|1.1|n65-128": ["hw:diffusion"],
22
30
  "all|1.25|n1-12": ["w3d:kdeeb-routes", "w3e:mlseb+stretch", "hw:growth", "hw:level-links", "w3b:growth-input", "w3e:confluent+stretch", "w3d:kdeeb-nomask", "w3a:diffusion-g2"],
23
- "all|1.25|n13-24": ["w3d:kdeeb-routes", "w3e:mlseb+stretch", "w3f:p-hub-a0.2", "w3a:spiral-n3", "w3a:diffusion-l3", "trunks-tree-bf06", "hw:cubu", "w3a:spiral-a35"],
31
+ "all|1.25|n13-24": ["w3d:kdeeb-routes", "w3f:p-hub-a0.2", "w3d:kdeeb-nomask", "w3a:spiral-n3", "w3b:growth-input", "w3d:cubu+stretch", "w3a:spiral-a35", "trunks-tree-bf06"],
24
32
  "all|1.25|n25-40": ["w3d:kdeeb-routes", "hw:spiral", "hw:shared-ways-all", "w3a:diffusion-g2", "w3e:frechet+stretch", "hw:cubu"],
33
+ "all|1.25|n41-64": ["w3e:frechet+stretch", "hw:cubu", "w3a:diffusion-wide", "w2a:shared-ways+stretch", "w3a:spiral-a35"],
34
+ "all|1.25|n65-128": ["hw:diffusion", "w3a:diffusion-wide", "w3a:diffusion-l3"],
25
35
  "all|1.5|n1-12": ["w3b:growth-s0.3", "w3e:mlseb-a0", "w3e:mlseb-routes", "w3c:edge-paths-k1.5", "w3f:territories-r2", "hw:mlseb", "hw:growth", "w3e:mlseb-parabola"],
26
- "all|1.5|n13-24": ["hw:growth", "w3b:growth-input", "hw:mlseb", "w3e:mlseb+stretch", "w3b:growth-s0.3"],
36
+ "all|1.5|n13-24": ["hw:growth", "w3b:growth-input", "hw:mlseb", "w3b:growth-s0.3"],
27
37
  "all|1.5|n25-40": ["hw:growth", "w3b:growth-s0.7", "w3b:growth-s0.3", "w3b:growth-t1.2", "w3b:growth-input"],
38
+ "all|1.5|n41-64": ["hw:growth", "w3b:growth-s0.3", "w3a:diffusion-g2", "w3b:growth-s0.7", "w3a:diffusion-l3", "w3b:growth-input"],
39
+ "all|1.5|n65-128": ["hw:growth", "w3b:growth-s0.3", "hw:shared-ways-all", "w3a:diffusion-g2"],
28
40
  };