@mark1russell7/highways 0.4.0 → 0.4.2

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.
Files changed (52) hide show
  1. package/README.md +67 -1
  2. package/build/index.d.ts +954 -2
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +5914 -1419
  5. package/build/index.js.map +1 -1
  6. package/package.json +2 -1
  7. package/src/bench/measures/bundles.ts +101 -2
  8. package/src/bench/measures/highways.ts +93 -0
  9. package/src/bench/measures/index.ts +2 -0
  10. package/src/bench/measures/order.ts +97 -0
  11. package/src/bench/room.ts +126 -9
  12. package/src/bench/screen/measures.ts +17 -0
  13. package/src/bench/screen/screen.ts +87 -9
  14. package/src/highways/base.ts +126 -0
  15. package/src/highways/flow-field/index.ts +49 -0
  16. package/src/highways/gates/ambiguity/index.ts +110 -0
  17. package/src/highways/gates/breakeven/index.ts +62 -0
  18. package/src/highways/gates/hysteresis/index.ts +48 -0
  19. package/src/highways/gates/ids/index.ts +59 -0
  20. package/src/highways/gates/index.ts +6 -0
  21. package/src/highways/gates/model.ts +129 -0
  22. package/src/highways/gates/stretch/index.ts +39 -0
  23. package/src/highways/grouped.ts +123 -0
  24. package/src/highways/index.ts +15 -0
  25. package/src/highways/level-links/index.ts +114 -0
  26. package/src/highways/meet/index.ts +84 -0
  27. package/src/highways/model.ts +5 -0
  28. package/src/highways/od-cells/index.ts +50 -0
  29. package/src/highways/quickbundles/index.ts +117 -0
  30. package/src/highways/road-classes/index.ts +74 -0
  31. package/src/highways/router.ts +1 -1
  32. package/src/highways/select/index.ts +162 -0
  33. package/src/highways/stretches.ts +141 -0
  34. package/src/highways/stubs/index.ts +117 -0
  35. package/src/highways/weiszfeld/index.ts +105 -0
  36. package/src/highways/wspd/index.ts +130 -0
  37. package/src/highways/zipper/index.ts +168 -0
  38. package/src/index.ts +2 -0
  39. package/src/order/index.ts +65 -0
  40. package/src/plugs/justify.ts +48 -0
  41. package/src/plugs/side.ts +138 -0
  42. package/src/repair/index.ts +377 -0
  43. package/src/repair/walk.ts +220 -0
  44. package/src/room/lanes.ts +109 -10
  45. package/src/routers/corners.ts +73 -6
  46. package/src/routers/fan.ts +145 -0
  47. package/src/routers/index.ts +2 -2
  48. package/src/routers/shared.ts +107 -8
  49. package/src/routers/snell.ts +140 -0
  50. package/src/routers/trunks.ts +43 -2
  51. package/src/strategies/builtins.ts +149 -7
  52. package/src/strategies/schemas.ts +173 -2
package/README.md CHANGED
@@ -142,6 +142,27 @@ The error of 47.6% is on a new run of two lanes. With `split`, these lanes go on
142
142
 
143
143
  The benchmark compares each curve type to the polylines of each router, on the fixtures of 100 nodes or fewer. It counts the curves that go through a box, with and without the free space. It also gives the ratio of the lengths.
144
144
 
145
+ ### Options of the cost, the order and the merges
146
+
147
+ These options of `shared` and `trunks` are off by default. With the defaults, the routes do not change.
148
+
149
+ - `cost: flow` of `shared` sets the cost of a link with `f` edges to `len * f^alpha`. A smaller `alpha` gives more sharing and a longer stretch (EDA-029).
150
+ - `passes` of `shared` sets the number of passes. After the first pass, each edge finds its way again with the ways of the other edges fixed (HWY-039).
151
+ - `order` of `shared` sets the order of the edges of a key: `span` (the default, the longest first), `shortest`, `load` or `input` (NAT-024).
152
+ - `merge: snell` of `shared` moves each merge point to the angle `acos(d)` on the run (NAT-035). It cuts the sharp merges.
153
+ - `splitAt: gilbert` of `trunks` puts the split point where the flow cost is least, with the exponent `alpha` (EDA-030).
154
+ - `fan: tree` of `trunks` grows a balancing-factor tree for each group, with the factor `bf` (NAT-017). 0 gives the least ink.
155
+
156
+ The screen `screen-v1` compares the options with the defaults on the boards `small-clustered`, `dense-groups`, `hub-chain` and `many-groups`.
157
+
158
+ | Option | Router | Result |
159
+ |---|---|---|
160
+ | `passes: 3` | `shared-all` | B1 rises 1% to 8%, and the B3 q95 falls or stays, on 4 boards. Crossings fall up to 28%. |
161
+ | `merge: snell` | `shared`, `shared-all` | The B6 max falls 8% to 27% on 6 board pairs. The ink rises 0.5% at most. Crossings rise 6% to 13%, and from 18 to 24 on `hub-chain`. |
162
+ | `cost: flow`, `alpha` 0.5 | `shared-all` | B1 rises 1% to 32%, but the B3 q95 rises up to 67%. |
163
+ | `fan: tree`, `bf` 0.2 | `trunks` | On `dense-groups`, B1 rises from 0.081 to 0.095 and the B3 q95 falls. |
164
+ | `splitAt: gilbert` | `trunks` | The B6 max rises. The ink changes 0.6% at most. |
165
+
145
166
  ## Room for the links
146
167
 
147
168
  A host layout can pack the boxes of a far view in a grid, with no gap between them. Then the links have no channel, and they go through the boxes. The router knows the room that the links need. The room functions give that room, and they can open the gaps.
@@ -323,7 +344,7 @@ The steps of the pipeline that vary have strategies. Each step has one interface
323
344
  |---|---|---|---|
324
345
  | `group` | `Graph` | `Section`: the tree of groups of the router `sections` | `quadtree`, `keys`, `kd`, `cut` |
325
346
  | `router` | `Graph` | `Result` | `straight`, `plugs`, `corners`, `corners-smooth`, `trunks`, `shared`, `shared-all`, `sections`, `sections-tree` |
326
- | `highway` | `HighwayInput`: the graph, and optionally the first routes of a router | `HighwayPlan`: the highways as data | `keys`, `shared-ways`, `corridors` |
347
+ | `highway` | `HighwayInput`: the graph, optionally the first routes of a router, and optionally the plan before an edit | `HighwayPlan`: the highways as data | `keys`, `shared-ways`, `corridors`, `meet`, `weiszfeld`, `stubs`, `zipper`, `level-links`, `quickbundles`, `road-classes`, `flow-field`, `wspd`, `od-cells`, `select`, `corridors+breakeven`, `corridors+stretch`, `corridors+ambiguity`, `corridors+hysteresis`, `corridors+ids` |
327
348
  | `curve` | `CurveInput`: the points, the normals of the plugs, the free space and the lane on its board | `CurveSegment[]` | `straight`, `rounded`, `spline`, `arc`, `smooth`, `clothoid`, `highway` |
328
349
  | `room` | `RoomInput`: the boxes and the links of a board, and the tree of sections for `levels` | `Gap[]` | `routes`, `lines`, `levels` |
329
350
 
@@ -352,10 +373,36 @@ The step `highway` decides which edges share a way. It gives a plan, not routes.
352
373
  | `keys` | The trunks and the runs of the router `trunks`. `planOfResult` reads them. The router does not change. |
353
374
  | `shared-ways` | The runs of the router `shared`. `planOfResult` reads them. The router does not change. |
354
375
  | `corridors` | The corridor signatures of HWY-031. The links of the first routes get a MinHash signature, and each cluster of ways gives a highway. |
376
+ | `meet` | The merge points and split points of HWY-050. Each member joins its spine where its first route meets the spine, and leaves where they part. |
377
+ | `weiszfeld` | The meeting points of HWY-043. Each highway gets the merge and split points with the least ink, with the weight `k^alpha` on the trunk. |
378
+ | `stubs` | The stubs of HWY-015. The ends on one side of a box that go in near directions share one plug and one short stub. |
379
+ | `zipper` | The axon zipper of NAT-022. Two near, nearly parallel legs zip into one line when the shared length pays for the jogs. |
380
+ | `level-links` | The level links of HWY-056. The edges between two items of a zoom level ride the link of the level. |
381
+ | `quickbundles` | The QuickBundles of HWY-026. One pass puts each edge in the nearest cluster of resampled lines. Each cluster gets highways. |
382
+ | `road-classes` | The road classes of HWY-034. The links that most ways use become main roads. A second pass routes the edges onto them. |
383
+ | `flow-field` | The flow field of EDA-046. The edges into one side of a box merge like streams on shortest ways to one root. |
384
+ | `wspd` | The well-separated pairs of HWY-018. The edges between the two sets of one pair share one highway. |
385
+ | `od-cells` | The origin and destination cells of EDA-033. The edges between two cells of a zoom level share one trunk. |
386
+ | `select` | The candidate selection of HWY-045. Some strategies propose highways, and a greedy pass with swaps keeps the best set. |
355
387
 
356
388
  The strategy `corridors` joins two ways when they share a long length. The length is `BREAK_EVEN` times the lane width or more, and the share `rho` of the shorter way or more.
389
+ The strategies `meet`, `weiszfeld`, `stubs`, `zipper` and `level-links` change the plan of the option `from`: `shared-ways` (the default), `corridors` or `none`.
357
390
  The routers `trunks` and `shared` keep their own code. A test pins their output, so the strategies `keys` and `shared-ways` read the same decision.
358
391
 
392
+ A gate keeps, drops or changes the highways of a plan. `gateStrategy(strategy, gate)` puts a gate after a highway strategy, with the name `<strategy>+<gate>`.
393
+ The new strategy has the options of both. The keys of the options of a gate are not keys of the strategy before it. Gates can follow gates.
394
+
395
+ | Gate | Rule |
396
+ |---|---|
397
+ | `breakeven` (HWY-047) | An edge stays on its highways only when its share of the shared ink is larger than its detour. The option `shareAlpha` sets the cost `n^shareAlpha` of a stretch for `n` edges. |
398
+ | `stretch` (HWY-048) | An edge stays only when its route is at most `budget` times its route alone, plus `pad`. |
399
+ | `ambiguity` (HWY-049) | Each highway keeps its largest group of edges whose end nodes have an ambiguity of `maxAmbiguity` or less. The ambiguity is the share of the pairs of end nodes without an edge. |
400
+ | `hysteresis` (HWY-046) | A new highway needs `kOn` edges. A highway of the plan before the edit stays while it has `kOff` edges. |
401
+ | `ids` (HWY-054) | Each highway takes the id of the highway of the plan before the edit with the most common edges. The routes do not change. |
402
+
403
+ The gates `hysteresis` and `ids` read `HighwayInput.previous`: the graph and the plan before an edit. Without it, `hysteresis` uses the limit `kOn` and `ids` changes nothing.
404
+ The functions `keepMembers`, `edgeLengths`, `matchHighways`, `jaccard` and `commonEdges` help a new gate.
405
+
359
406
  A registry is data. No import changes it. The benchmark and the site take their lists from `STRATEGIES`, so a new built-in strategy gets its rows and its button with no other edit. A consumer makes its own registry:
360
407
 
361
408
  ```ts
@@ -383,6 +430,25 @@ const rows = runBenchmark(routersOf(registry), FIXTURES.slice(0, 1)); // The row
383
430
 
384
431
  The built-in strategies give the same output as their functions. `curveStrategies.rounded.run({ points, space }, { radius: 8 })` gives the segments of `curveOf(points, { type: "rounded", space, radius: 8 })`. `benchCurveStrategies` and the fourth argument of `benchRoom` take a list of strategies.
385
432
 
433
+ ### Wrappers of a router
434
+
435
+ Two functions wrap a router strategy. The wrapped strategy has a new name, and the router does not change.
436
+
437
+ - `stableOrderStrategy(strategy)` gives `<name>+stable`. It routes the edges in a stable order: by a hash of their ids, then by the ids. Thus each order of the input edges gives the same output.
438
+ - `repairStrategy(strategy, repair?)` gives `<name>+repair`. After the router, `repairResult` repairs the breaks of the hard rules.
439
+ - It moves each free end back to its plug, and pushes each inner leg out of a box.
440
+ - It replaces each other leg through a box with a detour through the corner graph.
441
+ - When a leg does not repair, it routes the whole route again. Else it walks along the boundaries of the boxes, so boxes that touch do not block it.
442
+ - A route that it cannot repair keeps its base route.
443
+ - `withStableOrder(router)` and `withRepair(router, repair?)` wrap a `Router` in the same way.
444
+
445
+ ```ts
446
+ import { repairStrategy, routerStrategies, stableOrderStrategy } from "@mark1russell7/highways";
447
+
448
+ const shared = stableOrderStrategy(routerStrategies.shared);
449
+ const result = repairStrategy(shared).run(graph); // The router `shared+stable+repair`.
450
+ ```
451
+
386
452
  ### Declarations of the options
387
453
 
388
454
  Each strategy declares its options in `schema`. A declaration tells the type, the range, the step and the meaning of one option. Tools make controls and sweeps from these declarations, with no other data.