@mark1russell7/highways 0.8.1 → 0.9.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.
Files changed (54) hide show
  1. package/README.md +112 -8
  2. package/build/index.d.ts +989 -187
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +9761 -6738
  5. package/build/index.js.map +1 -1
  6. package/package.json +3 -2
  7. package/src/bench/compare.ts +174 -5
  8. package/src/bench/room.ts +1 -1
  9. package/src/bench/run.ts +38 -3
  10. package/src/bench/screen/exercise.ts +5 -0
  11. package/src/bench/screen/forms.ts +5 -1
  12. package/src/bench/screen/generators.ts +11 -41
  13. package/src/bench/screen/screen.ts +16 -10
  14. package/src/bench/screen/set.ts +156 -49
  15. package/src/bench/suite.ts +110 -12
  16. package/src/cases.ts +64 -18
  17. package/src/families/cases.ts +108 -0
  18. package/src/families/fixtures.ts +101 -0
  19. package/src/families/index.ts +36 -0
  20. package/src/families/model.ts +55 -0
  21. package/src/fixtures.ts +8 -2
  22. package/src/highways/fixtures.test-util.ts +13 -0
  23. package/src/highways/follow.ts +3 -2
  24. package/src/highways/free-lines.ts +141 -0
  25. package/src/highways/gaps/index.ts +85 -0
  26. package/src/highways/index.ts +6 -0
  27. package/src/highways/interchanges/index.ts +231 -0
  28. package/src/highways/search/index.ts +170 -0
  29. package/src/highways/snap.ts +4 -2
  30. package/src/highways/soft-keys/index.ts +8 -4
  31. package/src/highways/steiner/index.ts +215 -0
  32. package/src/highways/streets/index.ts +78 -0
  33. package/src/index.ts +8 -0
  34. package/src/lane-order.ts +37 -0
  35. package/src/lane-orders/stretch/index.ts +486 -0
  36. package/src/lane-orders/stretch/router.ts +22 -0
  37. package/src/levels/depths/index.ts +57 -0
  38. package/src/model.ts +60 -4
  39. package/src/plugs/facing/index.ts +22 -0
  40. package/src/portfolio/router.ts +44 -0
  41. package/src/routers/attraction/index.ts +61 -0
  42. package/src/routers/corners.ts +31 -7
  43. package/src/routers/index.ts +2 -1
  44. package/src/routers/plugs.ts +3 -2
  45. package/src/routers/sections.ts +25 -42
  46. package/src/routers/shared.ts +96 -14
  47. package/src/routers/straight.ts +3 -2
  48. package/src/routers/trunks.ts +24 -5
  49. package/src/segments.ts +4 -25
  50. package/src/strategies/builtins.ts +109 -2
  51. package/src/strategies/model.ts +55 -10
  52. package/src/strategies/options.ts +36 -4
  53. package/src/strategies/schemas.ts +124 -5
  54. package/src/whole/pipeline/index.ts +66 -0
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ExerciseEvidence, HashOptions, MeasureSpec, Member, MemberStatus, MemberTrace, OutputGroup, PickSpec, Portfolio, PortfolioKey, PortfolioLevel, PortfolioOptions, PortfolioPick, PortfolioTrace, RECORD_EPS, SelectCandidate, SelectLevel, Selection, Verdict, canonicalJson, compareMeasure, exercised, minEffectOf, outputGroups, outputHash, pickMoves, portfolio, selectBest, sha256Hex } from "@mark1russell7/layout-contract";
1
+ import { ClaimBreak, CorpusDimension, CorpusDimension as CorpusDimension$1, CorpusFamily, CorpusFamily as CorpusFamily$1, CorpusSplit, DEFAULT_RNG, DeclaredClaim, DimensionValues, DimensionValues as DimensionValues$1, ExerciseEvidence, FamilyBy, FamilyCell, FamilyRegistry, FamilyRegistry as FamilyRegistry$1, GenerateContext, HashOptions, MeasureSpec, Member, MemberStatus, MemberTrace, OutputGroup, ParamValue, ParamValue as ParamValue$1, PickSpec, Portfolio, PortfolioKey, PortfolioLevel, PortfolioOptions, PortfolioPick, PortfolioTrace, RECORD_EPS, SelectCandidate, SelectLevel, Selection, Verdict, canonicalJson, compareMeasure, createFamilyRegistry, dimensionAt, dimensionUnit, exercised, familyKind, levelsOf, minEffectOf, outputGroups, outputHash, paramProblem, pickMoves, portfolio, randomInt, selectBest, sha256Hex } from "@mark1russell7/layout-contract";
2
2
  /** A point in the plane. */
3
3
  export interface Point {
4
4
  readonly x: number;
@@ -83,7 +83,8 @@ export declare function segmentBounds(a: Point, b: Point): Box;
83
83
  export type Side = "north" | "east" | "south" | "west";
84
84
  /**
85
85
  * A plug of a node: a place where edges go into the node.
86
- * A plug with `at` is fixed. The router does not move it. A plug without `at` is free: the router places it.
86
+ * A plug with `at` is fixed. The router does not move it. A plug with `side` and `along` is fixed too.
87
+ * Another plug is free: the router places it.
87
88
  */
88
89
  export interface Port {
89
90
  readonly id: string;
@@ -91,6 +92,12 @@ export interface Port {
91
92
  readonly at?: Point;
92
93
  /** This side is where a free plug goes. Without it, the router picks the side. */
93
94
  readonly side?: Side;
95
+ /**
96
+ * This fraction from 0 to 1 fixes the plug on its `side`. The plug is at the side start plus `along` times the side length.
97
+ * The start of `north` and `south` is the left end. The start of `east` and `west` is the top end.
98
+ * A plug with `along` needs a `side` and has no `at`. `resolvePorts` throws a `RangeError` for a bad value.
99
+ */
100
+ readonly along?: number;
94
101
  }
95
102
  /** A node: a box that routes must not go through. */
96
103
  export interface Node {
@@ -190,7 +197,20 @@ export interface Router {
190
197
  }
191
198
  /** This function gives a map from the id of each node to the node. */
192
199
  export declare function nodeIndex(g: Graph): Map<string, Node>;
193
- /** This function gives the absolute place of a fixed plug, or `undefined` for a free plug or no plug. */
200
+ /**
201
+ * This function gives the place of a fixed plug, relative to the top-left corner of the node box, or `undefined` for a free plug.
202
+ * A plug with `at` gives `at`. A plug with `side` and `along` gives the point of `portPoint` of `@mark1russell7/layout-contract`.
203
+ */
204
+ export declare function portOffset(box: Box, port: Port): Point | undefined;
205
+ /** This function throws a `RangeError` when the `along` of a plug is bad: not finite, outside 0 to 1, without `side` or with `at`. */
206
+ export declare function checkPort(node: Node, port: Port): void;
207
+ /**
208
+ * This function checks the plugs of a graph, and gives each plug with `side` and `along` a fixed `at`. The plug keeps its `side`.
209
+ * Each router calls it at the start of `route`, so all routers agree. A graph without `along` comes back as the same object.
210
+ * It throws a `RangeError` for a bad `along` (`checkPort`).
211
+ */
212
+ export declare function resolvePorts(graph: Graph): Graph;
213
+ /** This function gives the absolute place of a fixed plug, or `undefined` for a free plug or no plug. A plug with `side` and `along` is fixed. */
194
214
  export declare function fixedPortPoint(node: Node, end: End): Point | undefined;
195
215
  /** This function gives a seeded random source with values in [0, 1) (mulberry32). */
196
216
  export declare function rng(seed: number): () => number;
@@ -214,11 +234,14 @@ export interface FixtureSpec {
214
234
  }
215
235
  /** The fixtures of the benchmark, from 10 to 100 000 nodes. */
216
236
  export declare const FIXTURES: readonly FixtureSpec[];
237
+ /** This function gives the seed of the random numbers of a fixture: `(seed × 2654435761 + nodes) >>> 0`. */
238
+ export declare function fixtureRngSeed(seed: number, nodes: number): number;
217
239
  /**
218
240
  * This function makes the graph of a fixture. The same spec always gives the same graph.
219
241
  * Node boxes do not overlap, and a gap of 12 units stays between them.
242
+ * The default source of random numbers is `rng(fixtureRngSeed(spec.seed, spec.nodes))`. A corpus family gives the same stream from its registry.
220
243
  */
221
- export declare function makeFixture(spec: FixtureSpec): Graph;
244
+ export declare function makeFixture(spec: FixtureSpec, random?: () => number): Graph;
222
245
  /**
223
246
  * A board of made-up data that shows one known defect of the routes or of the zoom levels.
224
247
  * The benchmark races the routers on each case, and the measures of `measureLinks` give a number for the defect.
@@ -230,23 +253,60 @@ export interface CaseBoard {
230
253
  /** This function makes the graph. The same function always gives the same graph. */
231
254
  readonly make: () => Graph;
232
255
  }
256
+ /** The options of a case board with a seed: `hubChainBoard` and `manyGroupsBoard`. */
257
+ export interface CaseSeedOptions {
258
+ /** The seed of the random links of the board. Each board has its own default. */
259
+ readonly seed?: number;
260
+ }
233
261
  /**
234
262
  * This function makes a dense board: 150 nodes in tight clusters. At the far view, the boxes of the groups overlap.
235
263
  * Then a level link starts or ends in a group that another group covers.
236
264
  */
237
265
  export declare function denseGroupsBoard(): Graph;
266
+ /** The options of `hubChainBoard`. Each option at its default keeps the board of today. */
267
+ export interface HubChainOptions extends CaseSeedOptions {
268
+ /** The number of rows of cards. The default is 3. */
269
+ readonly rows?: number;
270
+ /** The number of cards in each row. The default is 32. */
271
+ readonly cols?: number;
272
+ /** The number of tries for a long link. The default is 40. */
273
+ readonly long?: number;
274
+ /** The free space between two cards, in units. The default is 48. */
275
+ readonly gap?: number;
276
+ }
238
277
  /**
239
278
  * This function makes a board of three rows of 32 cards. Each card links to the next card of its row.
240
279
  * Forty long links join cards far apart. The hub of a section is near the middle of its cards.
241
280
  * So a long link climbs to hubs behind its source or past its target, and comes back.
242
- */
243
- export declare function hubChainBoard(): Graph;
281
+ *
282
+ * The seed changes only the long links. The rows of cards, and thus the chain of hubs, do not change.
283
+ * The default seed is 3. Without options, the board does not change.
284
+ * The default source of random numbers is `rng(seed)`. A corpus family gives the same stream from its registry.
285
+ */
286
+ export declare function hubChainBoard(options?: HubChainOptions, random?: () => number): Graph;
287
+ /** The options of `manyGroupsBoard`. Each option at its default keeps the board of today. */
288
+ export interface ManyGroupsOptions extends CaseSeedOptions {
289
+ /** The number of columns of groups. The default is 8. */
290
+ readonly groupCols?: number;
291
+ /** The number of rows of groups. The default is 4. */
292
+ readonly groupRows?: number;
293
+ /** The number of cards in each group. The default is 4. */
294
+ readonly perGroup?: number;
295
+ /** The number of random links between groups, for each group. The default is 3. */
296
+ readonly crossLinksPerGroup?: number;
297
+ /** The free space between two groups, in units. The default is 60. */
298
+ readonly groupGap?: number;
299
+ }
244
300
  /**
245
301
  * This function makes a board of 32 groups in 8 columns and 4 rows. Each group has 4 cards in a square.
246
302
  * The cards of a group link in a chain, and 96 random links join cards of two groups.
247
303
  * On a level with many groups, some level links go around the outer edge of the board.
304
+ *
305
+ * The seed changes only the 96 links between groups. The 32 groups and their chains do not change.
306
+ * The default seed is 7. Without options, the board does not change.
307
+ * The default source of random numbers is `rng(seed)`. A corpus family gives the same stream from its registry.
248
308
  */
249
- export declare function manyGroupsBoard(): Graph;
309
+ export declare function manyGroupsBoard(options?: ManyGroupsOptions, random?: () => number): Graph;
250
310
  /** The options of `packedGridBoard`. */
251
311
  export interface PackedGridOptions {
252
312
  /** The seed of the links. The default is 11. */
@@ -257,6 +317,8 @@ export interface PackedGridOptions {
257
317
  readonly rows?: number;
258
318
  /** The number of long links between boxes far apart. The default is 48. */
259
319
  readonly long?: number;
320
+ /** The largest step, in rows and in columns, of the link of a box to a box near it. The default is 2. */
321
+ readonly reach?: number;
260
322
  }
261
323
  /**
262
324
  * This function makes the far view of a board after a host layout packs it.
@@ -266,8 +328,9 @@ export interface PackedGridOptions {
266
328
  *
267
329
  * The board is not in `CASES`, because the digests of the router fix the output on each board of `CASES`.
268
330
  * The options make a family of such boards for the measure suite. Without options, the board does not change.
331
+ * The default source of random numbers is `rng(seed)`. A corpus family gives the same stream from its registry.
269
332
  */
270
- export declare function packedGridBoard(options?: PackedGridOptions): Graph;
333
+ export declare function packedGridBoard(options?: PackedGridOptions, random?: () => number): Graph;
271
334
  /**
272
335
  * This function makes a packed board with three zoom levels of groups. The board has 256 touching boxes in a grid of 16 columns and 16 rows.
273
336
  * The quadtree of `buildSections` splits it into 4, 16 and 64 groups. Each box links to a box near it, and 64 long links join boxes far apart.
@@ -1004,112 +1067,6 @@ export declare const straightRouter: Router;
1004
1067
  * It goes to the target plug on the curve of the rule. This router measures the rule alone.
1005
1068
  */
1006
1069
  export declare const plugsRouter: Router;
1007
- /** The ways to place a free plug of the corner router. */
1008
- type PlugPlace = "facing" | "side";
1009
- /** The options of the corner router. */
1010
- interface CornersOptions extends WayOptions {
1011
- /** The name in the benchmark. */
1012
- readonly name: string;
1013
- /** The benchmark skips a fixture with more nodes. */
1014
- readonly maxNodes?: number;
1015
- /**
1016
- * The place of a free plug. The default is `facing`: the plug faces the other end (`placePlug`).
1017
- * With `side`, the search starts from the whole free side, and the plug goes where the way leaves the side (`sidePlugs`, WILD-001).
1018
- */
1019
- readonly plugs?: PlugPlace;
1020
- /**
1021
- * The least gap between two free plugs of one side. The default is 0: each plug stays where it is.
1022
- * Above 0, the free plugs of each side keep their order and move the least distance (`justifyPlugs`, WILD-002).
1023
- */
1024
- readonly plugGap?: number;
1025
- }
1026
- /**
1027
- * This function makes a router that goes around the nodes.
1028
- * Each edge leaves its plug along the normal of the side. It goes a shortest way (A*) through a sparse visibility graph
1029
- * of the box corners, without the needless corners. It enters the target plug along its normal.
1030
- */
1031
- export declare function cornersRouter(options: CornersOptions): Router;
1032
- /** The cost of a link that edges of one key share: a fixed discount, or the flow cost `len * f^alpha` (EDA-029). */
1033
- type ShareCost = "fixed" | "flow";
1034
- /** The order of the edges of one key: the longest first, the shortest first, the most load first, or the order of the input (NAT-024). */
1035
- type ShareOrder = "span" | "shortest" | "load" | "input";
1036
- /** The place where a route joins or leaves a run: at a corner of the graph, or at the Snell angle (NAT-035). */
1037
- type ShareMerge = "corner" | "snell";
1038
- /** The options of the router with shared ways. */
1039
- interface SharedOptions extends WayOptions {
1040
- /** The name in the benchmark. */
1041
- readonly name: string;
1042
- /** The edges with one key share their ways. Without a rule, all edges share. An edge without a key shares with no edge. */
1043
- readonly rule?: GroupRule;
1044
- /** The cost of a link that an edge with the same key uses already, as a share of its length. The default is 0.5. */
1045
- readonly discount?: number;
1046
- /** The lane order of the runs. With `bundle`, the default, two edges keep one order on each run of their common stretch. With `run`, each run gets its order alone. */
1047
- readonly laneOrder?: RunOrder;
1048
- /**
1049
- * The cost of a shared link. With `fixed`, the default, a link that the key uses already costs `discount` times its length.
1050
- * With `flow`, one more edge on a link with `f` edges costs `len * ((f + 1)^alpha - f^alpha)` (EDA-029).
1051
- */
1052
- readonly cost?: ShareCost;
1053
- /** The exponent of the flow cost, from 0.1 to 1. A smaller value gives more sharing. The default is 0.6. Only the cost `flow` uses it. */
1054
- readonly alpha?: number;
1055
- /** The number of passes. In each pass after the first, each edge leaves its links and finds its way again with the others fixed (HWY-039). The default is 1. */
1056
- readonly passes?: number;
1057
- /**
1058
- * The order of the edges of one key. With `span`, the default, the longest edge goes first. With `shortest`, the shortest edge goes first.
1059
- * With `load`, the edge with the most edges between its two sections goes first. With `input`, the edges keep the order of the graph (NAT-024).
1060
- */
1061
- readonly order?: ShareOrder;
1062
- /**
1063
- * The place where a route joins or leaves a run. With `corner`, the default, it is a corner of the graph.
1064
- * With `snell`, the route meets the run at the angle `acos(d)`, with `d` the cost share of the run for the route (NAT-035).
1065
- */
1066
- readonly merge?: ShareMerge;
1067
- /**
1068
- * The pull of the busy links of the pass before (HWY-005, Winding Roads). With a value above 0 and two passes or more, each later pass routes each edge again from no ways.
1069
- * A link then costs `len / (1 + reuse * u)^reuseExponent`, with `u` the edges of the key on it in the pass before. The default is 0: the later passes are rip-up passes.
1070
- */
1071
- readonly reuse?: number;
1072
- /** The exponent of the pull of `reuse`. The default is 1. */
1073
- readonly reuseExponent?: number;
1074
- /**
1075
- * The cost of a lane that does not fit in its channel (HWY-016). One more edge on a link with `f` edges of the key costs `capacity * max(0, (f + 1) * laneWidth - width)` more.
1076
- * `width` is the free space across the link (`channelWidth`). The default is 0: the router does not read the channels.
1077
- */
1078
- readonly capacity?: number;
1079
- /** The width of one lane, for `capacity`. The default is 4. */
1080
- readonly laneWidth?: number;
1081
- /** The benchmark skips a fixture with more nodes. */
1082
- readonly maxNodes?: number;
1083
- }
1084
- /**
1085
- * This function makes a router where edges share their ways (after Pupyrev, Nachmanson, Bereg and Holroyd, "Edge routing with ordered bundles").
1086
- * The edges go one by one through the corner graph. A link that an edge with the same key uses already costs less.
1087
- * Thus the edges of a key come together on common ways. Each stretch that several edges share has the same points in each route.
1088
- * The result gives each stretch as a run, with the order of its lanes.
1089
- */
1090
- export declare function sharedRouter(options: SharedOptions): Router;
1091
- /** Two items of a level that a link joins, and the count of the edges between them. */
1092
- interface ItemPair {
1093
- readonly source: string;
1094
- readonly target: string;
1095
- readonly count: number;
1096
- }
1097
- /** The options of the links of a level: the options of the ways, and two limits of the level links. */
1098
- interface LevelLinkOptions extends WayOptions {
1099
- /**
1100
- * The margin of the second corner graph. A gap between two boxes wider than approximately 1.5 times this margin lets a link through.
1101
- * The second graph uses the smaller of this value and `margin`. The default is 1.
1102
- */
1103
- readonly tightMargin?: number;
1104
- /** A plug stays at least this far from the corners of its side. The level links use the smaller of this value and `margin`. The default is 6. */
1105
- readonly plugInset?: number;
1106
- /**
1107
- * The cost of a level link through a far box, in units of the mean box size. A far box overlaps neither end of the link.
1108
- * A link through a far box gets a second way that can go through boxes (`SoftGraph`). The link keeps the way with fewer far boxes.
1109
- * The value 0 turns the second way off and gives the links of version 0.1.5. The default is 8.
1110
- */
1111
- readonly throughCost?: number;
1112
- }
1113
1070
  /** The input of a highway strategy: the boxes and the edges, and optionally the first routes of a router. */
1114
1071
  interface HighwayInput {
1115
1072
  readonly graph: Graph;
@@ -1319,6 +1276,11 @@ export interface NumberOption extends OptionBase {
1319
1276
  readonly special?: readonly number[];
1320
1277
  /** These values are the notable values of the option: the default and the values of the sweeps of the benchmark. */
1321
1278
  readonly marks?: readonly number[];
1279
+ /**
1280
+ * These values are the only valid values of the option, in the order of a control. A control shows them as a list, and a sweep gives them.
1281
+ * Without them, each value on the range is valid.
1282
+ */
1283
+ readonly values?: readonly number[];
1322
1284
  /** The strategy uses this value when the caller and `defaults` give no value. */
1323
1285
  readonly default?: number;
1324
1286
  }
@@ -1333,6 +1295,11 @@ export interface EnumOption<V extends string = string> extends OptionBase {
1333
1295
  readonly type: "enum";
1334
1296
  /** The values of the option, in the order of a control. */
1335
1297
  readonly values: readonly V[];
1298
+ /**
1299
+ * With `function`, the option also takes a rule of the caller in place of a name. A control sets only the names.
1300
+ * Each name is a known rule of the strategy.
1301
+ */
1302
+ readonly custom?: "function";
1336
1303
  /** The strategy uses this value when the caller and `defaults` give no value. */
1337
1304
  readonly default?: V;
1338
1305
  }
@@ -1349,8 +1316,11 @@ export interface ValueOption<V = unknown> extends OptionBase {
1349
1316
  }
1350
1317
  /** The declaration of one option of any type. */
1351
1318
  export type AnyOption = NumberOption | BooleanOption | EnumOption | ValueOption;
1352
- /** The declaration that fits the type of an option value: numbers, booleans, string unions or other values. */
1353
- export type OptionDeclaration<V> = [V] extends [number] ? NumberOption : [V] extends [boolean] ? BooleanOption : [V] extends [string] ? EnumOption<V> : ValueOption<V>;
1319
+ /**
1320
+ * The declaration that fits the type of an option value: numbers, booleans, string unions or other values.
1321
+ * A union of strings and other values takes an enum of the strings or a value declaration. An example is a rule or the name of a rule.
1322
+ */
1323
+ export type OptionDeclaration<V> = [V] extends [number] ? NumberOption : [V] extends [boolean] ? BooleanOption : [V] extends [string] ? EnumOption<V> : [Extract<V, string>] extends [never] ? ValueOption<V> : EnumOption<Extract<V, string>> | ValueOption<V>;
1354
1324
  /** The declarations of the options of a strategy. The schema has one declaration for each key of the options type, and no other key. */
1355
1325
  export type OptionSchema<O> = { readonly [K in keyof O]-?: OptionDeclaration<NonNullable<O[K]>>; };
1356
1326
  /** One problem of an option value against its declaration. */
@@ -1399,12 +1369,12 @@ export declare function optionDefaults<S extends Step, O extends object>(strateg
1399
1369
  export declare function checkOptions<S extends Step, O extends object>(strategy: Strategy<S, O>, options: Partial<O>): OptionIssue[];
1400
1370
  /**
1401
1371
  * This function moves each number option into the range of its declaration, for a control. An integer option gets the nearest whole number.
1402
- * A special value stays. The function keeps each other value as it is. `checkOptions` reports the values that this function cannot correct.
1372
+ * An option with a list of `values` gets the nearest value of the list. A special value stays. The function keeps each other value as it is. `checkOptions` reports the values that this function cannot correct.
1403
1373
  */
1404
1374
  export declare function clampOptions<S extends Step, O extends object>(strategy: Strategy<S, O>, options: Partial<O>): Partial<O>;
1405
1375
  /**
1406
1376
  * This function gives the values of a sweep of one option declaration.
1407
- * A number option gives its `marks`, or `count` values on its range and its scale. A boolean gives `false` and `true`. An enum gives its values.
1377
+ * A number option gives its `marks`, or its list of `values`, or `count` values on its range and its scale. A boolean gives `false` and `true`. An enum gives its values.
1408
1378
  * An option of another type has no sweep, so the function throws an error.
1409
1379
  */
1410
1380
  export declare function sweepValues(declaration: AnyOption, options?: SweepOptions): unknown[];
@@ -1464,20 +1434,53 @@ export interface RoomInput {
1464
1434
  */
1465
1435
  readonly sections?: Section;
1466
1436
  }
1437
+ /** The input of a plug strategy: the graph, and optionally the way finder of the router that reads the plugs. */
1438
+ export interface PlugInput {
1439
+ readonly graph: Graph;
1440
+ /** The ways around the nodes of the graph, for a strategy that reads the free space. The default strategy `facing` does not read it. */
1441
+ readonly ways?: WayFinder;
1442
+ }
1443
+ /** The plugs of the two ends of one edge: the output of a plug strategy for that edge. */
1444
+ export interface PlugPair {
1445
+ readonly edge: string;
1446
+ readonly source: Plug;
1447
+ readonly target: Plug;
1448
+ }
1449
+ /** The input of a level strategy: the graph, the tree of sections of its grouping rule and the routes of the router. */
1450
+ export interface LevelInput {
1451
+ readonly graph: Graph;
1452
+ /** The tree of sections. The indices of its nodes are the indices of `graph.nodes`. */
1453
+ readonly root: Section;
1454
+ /** The routes of the router. The default strategy `depths` gives the links of the last level the points of these routes. */
1455
+ readonly routes: readonly Route[];
1456
+ }
1457
+ /** The output of a strategy of the step `whole`: the board that the routes go on, and the routes. */
1458
+ export interface WholeOutput {
1459
+ /** The board: the graph, or the graph with the gaps that a room strategy opened. It has the edges of the input. */
1460
+ readonly graph: Graph;
1461
+ readonly result: Result;
1462
+ }
1467
1463
  /**
1468
1464
  * The steps that have strategies, with the fixed input and output type of each step.
1469
1465
  *
1470
1466
  * - `group`: a graph in, the tree of sections out. The router `sections` makes its hubs and its zoom levels from this tree.
1467
+ * - `plugs`: a graph in, the plugs of the two ends of each edge out. The router `corners` routes between these plugs.
1471
1468
  * - `router`: a graph in, the routes (and the `levels`, `bundles` and `runs`) out.
1472
1469
  * - `highway`: a graph and optionally its first routes in, a highway plan out. `follow` routes the edges along the plan.
1470
+ * - `levels`: a graph, its tree of sections and its routes in, the zoom levels out. The router `sections` gives them in its result.
1473
1471
  * - `curve`: a polyline in, the segments of a curve out.
1474
1472
  * - `room`: the boxes and links of a board in, the gaps of the board with their need out.
1473
+ * - `whole`: a graph in, the board and its routes out. A strategy of this step runs the other steps.
1475
1474
  */
1476
1475
  export interface StepTypes {
1477
1476
  readonly group: {
1478
1477
  readonly input: Graph;
1479
1478
  readonly output: Section;
1480
1479
  };
1480
+ readonly plugs: {
1481
+ readonly input: PlugInput;
1482
+ readonly output: PlugPair[];
1483
+ };
1481
1484
  readonly router: {
1482
1485
  readonly input: Graph;
1483
1486
  readonly output: Result;
@@ -1486,6 +1489,10 @@ export interface StepTypes {
1486
1489
  readonly input: HighwayInput;
1487
1490
  readonly output: HighwayPlan;
1488
1491
  };
1492
+ readonly levels: {
1493
+ readonly input: LevelInput;
1494
+ readonly output: Level[];
1495
+ };
1489
1496
  readonly curve: {
1490
1497
  readonly input: CurveInput;
1491
1498
  readonly output: CurveSegment[];
@@ -1494,6 +1501,10 @@ export interface StepTypes {
1494
1501
  readonly input: RoomInput;
1495
1502
  readonly output: Gap[];
1496
1503
  };
1504
+ readonly whole: {
1505
+ readonly input: Graph;
1506
+ readonly output: WholeOutput;
1507
+ };
1497
1508
  }
1498
1509
  /** The name of a step that has strategies. */
1499
1510
  export type Step = keyof StepTypes;
@@ -1501,7 +1512,11 @@ export type Step = keyof StepTypes;
1501
1512
  export type StepInput<S extends Step> = StepTypes[S]["input"];
1502
1513
  /** The output type of a step. */
1503
1514
  export type StepOutput<S extends Step> = StepTypes[S]["output"];
1504
- /** The steps that have strategies, in the order of the pipeline. */
1515
+ /**
1516
+ * The steps that have strategies, in the order of the pipeline.
1517
+ * The plugs come before the router, because the router searches its ways between them. The levels come after the routes, because the last level reads them.
1518
+ * The step `whole` runs the other steps, so it comes last.
1519
+ */
1505
1520
  export declare const STEPS: readonly Step[];
1506
1521
  /**
1507
1522
  * A strategy: one way to do one step, with a name and a description.
@@ -1546,12 +1561,11 @@ export declare function defineStrategy<S extends Step, O extends object>(definit
1546
1561
  /**
1547
1562
  * A registry: the strategies of each step, in order. A registry is data. No import changes it.
1548
1563
  * A consumer makes its own registry with `createRegistry`, and adds a strategy with `register`.
1549
- * The lists `group` and `highway` are optional in the type, so a registry from version 0.1.5 or 0.3.0 stays a registry. `createRegistry` always gives them.
1564
+ * The lists `group`, `highway`, `plugs`, `levels` and `whole` are optional in the type, so a registry of an older version stays a registry. `createRegistry` always gives them.
1550
1565
  */
1551
- export type Registry = { readonly [S in Exclude<Step, "group" | "highway">]: readonly Strategy<S>[]; } & {
1552
- readonly group?: readonly Strategy<"group">[];
1553
- readonly highway?: readonly Strategy<"highway">[];
1554
- };
1566
+ export type Registry = { readonly [S in Exclude<Step, OptionalStep>]: readonly Strategy<S>[]; } & { readonly [S in OptionalStep]?: readonly Strategy<S>[]; };
1567
+ /** The steps whose lists are optional in a `Registry`: the steps that came after version 0.1.5. */
1568
+ type OptionalStep = "group" | "highway" | "plugs" | "levels" | "whole";
1555
1569
  /** This function makes a registry from a list of strategies. It keeps their order. Two strategies with one step and one name are an error. */
1556
1570
  export declare function createRegistry(strategies: readonly AnyStrategy[]): Registry;
1557
1571
  /** This function gives a new registry with the strategies of `registry` and then `strategies`. It does not change `registry`. */
@@ -1566,66 +1580,93 @@ export declare function getStrategy<S extends Step>(registry: Registry, step: S,
1566
1580
  export declare function asRouter<O extends object>(strategy: Strategy<"router", O>, options?: Partial<O>): Router;
1567
1581
  /** This function gives the router strategies of a registry as `Router` objects, in order. The benchmark races them. */
1568
1582
  export declare function routersOf(registry: Registry): Router[];
1569
- /**
1570
- * The options of the router with sections. Each option has a default, and the defaults give the output of version 0.1.5.
1571
- * The options `cap`, `maxDepth` and `collapse` are the limits of the default grouping rule, the quadtree of `buildSections`.
1572
- * The options `tightMargin`, `plugInset` and `throughCost` are the limits of the level links (`levelLinks`).
1573
- */
1574
- interface SectionsOptions extends LevelLinkOptions, SectionOptions {
1583
+ /** The ways to place a free plug of the corner router. */
1584
+ type PlugPlace = "facing" | "side";
1585
+ /** The options of the corner router. */
1586
+ interface CornersOptions extends WayOptions {
1575
1587
  /** The name in the benchmark. */
1576
1588
  readonly name: string;
1589
+ /** The benchmark skips a fixture with more nodes. */
1590
+ readonly maxNodes?: number;
1577
1591
  /**
1578
- * The number of hubs on each side of the lowest common section that a way passes. A smaller number gives shorter ways
1579
- * and fewer shared ways. Without it, a way passes each hub from its node up.
1580
- */
1581
- readonly hubs?: number;
1582
- /**
1583
- * The hub limit. A way through the hubs can be at most this many times as long as the line between its plugs, plus `stretchPad` margins.
1584
- * Else the edge goes directly. The default is 2. The value `Infinity` keeps each way through the hubs.
1585
- */
1586
- readonly stretch?: number;
1587
- /** A way through the hubs can be this many margins longer than `stretch` times the line between its plugs. The default is 4. */
1588
- readonly stretchPad?: number;
1589
- /**
1590
- * A way skips a hub that is more than this many units farther from the target than the nearest approach of the way before it.
1591
- * The default is 80, two times `BACKTRACK_MIN`. The value `Infinity` keeps each hub.
1592
+ * The place of a free plug. The default is `facing`: the plug faces the other end (`placePlug`).
1593
+ * With `side`, the search starts from the whole free side, and the plug goes where the way leaves the side (`sidePlugs`, WILD-001).
1592
1594
  */
1593
- readonly hubSlack?: number;
1595
+ readonly plugs?: PlugPlace;
1594
1596
  /**
1595
- * The grouping rule: a strategy of the step `group` that makes the tree of sections. The hubs and the zoom levels come from this tree.
1596
- * Without it, the router uses the quadtree of `buildSections` with the options `cap`, `maxDepth` and `collapse`.
1597
+ * The least gap between two free plugs of one side. The default is 0: each plug stays where it is.
1598
+ * Above 0, the free plugs of each side keep their order and move the least distance (`justifyPlugs`, WILD-002).
1597
1599
  */
1598
- readonly group?: Strategy<"group">;
1599
- /** The options of the strategy `group`. The strategy gets its `defaults` for each option that this object does not give. */
1600
- readonly groupOptions?: object;
1600
+ readonly plugGap?: number;
1601
1601
  /**
1602
- * The depths of the tree that get a zoom level with groups. The last level, with each node alone, always comes after them.
1603
- * The default is each depth, from 0 to the depth of the deepest section.
1602
+ * The plug rule: a strategy of the step `plugs` that places the plugs of each edge. It takes the place of the option `plugs`.
1603
+ * Without it, the router places the plugs with the option `plugs`. An edge without plugs from the strategy gets the plugs of `facing`.
1604
1604
  */
1605
- readonly levels?: readonly number[];
1606
- /** The lane order of the runs. With `run`, the default, each run gets its order alone. With `bundle`, two edges keep one order on each run of their common stretch. */
1607
- readonly laneOrder?: RunOrder;
1608
- /** The benchmark skips a fixture with more nodes. */
1609
- readonly maxNodes?: number;
1605
+ readonly plug?: Strategy<"plugs">;
1606
+ /** The options of the strategy `plug`. The strategy gets its `defaults` for each option that this object does not give. */
1607
+ readonly plugOptions?: object;
1610
1608
  }
1611
1609
  /**
1612
- * This function makes a router with a tree of sections. Each section has a hub: the free corner nearest to the center of its nodes.
1613
- * An edge goes from its node up the hubs of its sections to the lowest common section, across, and down to the other node.
1614
- * Each way from hub to hub is found one time, so all the edges on it share its points.
1615
- * The edges in one section of the lowest level go straight around the nodes.
1610
+ * This function makes a router that goes around the nodes.
1611
+ * Each edge leaves its plug along the normal of the side. It goes a shortest way (A*) through a sparse visibility graph
1612
+ * of the box corners, without the needless corners. It enters the target plug along its normal.
1613
+ */
1614
+ export declare function cornersRouter(options: CornersOptions): Router;
1615
+ /**
1616
+ * The lane order of the stretches (LANE-STRETCH).
1616
1617
  *
1617
- * An edge skips a hub that takes it away from its target. A way that still goes out and back gives way to the direct way.
1618
+ * - `none`: each run gets its own order, as the order `bundle` of `orderLanes` gives it.
1619
+ * - `consensus`: one order of the pair relation of the stretch, from the heuristic of Eades, Lin and Smyth for the feedback arc set.
1620
+ * - `periphery`: the largest run gives its order. Each next run keeps that order and puts each new edge at the place with the fewest broken pairs.
1621
+ * - `sifting`: the order of `consensus`. Then each edge moves to the place with the fewest broken pairs, for `passes` passes.
1622
+ */
1623
+ export type LaneStretchOrder = "none" | "consensus" | "periphery" | "sifting";
1624
+ /** The values of `LaneStretchOrder`, in the order of a control. */
1625
+ export declare const LANE_STRETCH_ORDERS: readonly LaneStretchOrder[];
1626
+ /** The options of `stretchLaneOrders`. */
1627
+ export interface LaneStretchOptions {
1628
+ /** The lane order of the stretches. The default is `sifting`. */
1629
+ readonly method: LaneStretchOrder;
1630
+ /** The number of passes of the method `sifting`, from 1 to 4. The default is 2. The other methods do not read it. */
1631
+ readonly passes: number;
1632
+ }
1633
+ /** The default options of `stretchLaneOrders`. */
1634
+ export declare const LANE_STRETCH_DEFAULTS: Readonly<LaneStretchOptions>;
1635
+ /** One run: its points and the routes on it. Each route holds the points of the run in a row, in either direction. */
1636
+ export interface LaneRun {
1637
+ readonly points: readonly Point[];
1638
+ readonly routes: readonly Route[];
1639
+ }
1640
+ /** One stretch: the runs that follow each other on the routes, and the order of the edges of the stretch. */
1641
+ export interface LaneStretch {
1642
+ /** The indexes of the runs in the list of the input. The first run is the root: the run with the most lanes. The others follow in the order of a breadth-first walk. */
1643
+ readonly runs: readonly number[];
1644
+ /** The way of each run of `runs` against the root. The value -1 tells that the left of the root is the right of the run. */
1645
+ readonly turns: readonly (1 | -1)[];
1646
+ /** The edges of the stretch from left to right, in the way of the root. A stretch of one run has the order `bundle` of the run. */
1647
+ readonly order: readonly string[];
1648
+ }
1649
+ /**
1650
+ * This function gives the stretches of the runs (LANE-STRETCH). Two runs are in one stretch when a chain of links joins them.
1651
+ * A link joins two runs when a route goes through one and then the other, and they share two edges or more.
1652
+ * The result does not depend on the order of the runs or of the routes of each run.
1653
+ */
1654
+ export declare function laneStretches(runs: readonly LaneRun[], options?: Partial<LaneStretchOptions>): LaneStretch[];
1655
+ /**
1656
+ * This function gives the lane order of each run (LANE-STRETCH). The orders are in the order of `runs`.
1657
+ * Each order holds the edges of the run from left to right. The way goes from the first point of the run to its last point, with the y axis down.
1658
+ * A route that does not hold its run goes last, as in `orderLanes`.
1618
1659
  *
1619
- * The result gives one zoom level for each depth of the tree.
1620
- * A link of a level goes from the boundary of one item to the boundary of the other, around the other items.
1660
+ * With the method `none`, each run gets the order `bundle` of `orderLanes`. With the other methods, each run of a stretch gets the order of the stretch.
1661
+ * Thus two runs of one stretch give two edges the same side. The result does not depend on the order of the runs or of the routes of each run.
1621
1662
  */
1622
- export declare function sectionsRouter(options: SectionsOptions): Router;
1663
+ export declare function stretchLaneOrders(runs: readonly LaneRun[], options?: Partial<LaneStretchOptions>): string[][];
1623
1664
  /** The options of the trunk router. */
1624
1665
  interface TrunksOptions extends WayOptions {
1625
1666
  /** The name in the benchmark. */
1626
1667
  readonly name: string;
1627
- /** The grouping rule. The edges from one plug with one key share a trunk. */
1628
- readonly rule: GroupRule;
1668
+ /** The grouping rule, or the name of a built-in rule (`GROUP_RULE_NAMES`). The edges from one plug with one key share a trunk. */
1669
+ readonly rule: GroupRule | GroupRuleName;
1629
1670
  /** The split point is at this share of the way to the center of the targets. The default is 0.5. */
1630
1671
  readonly split?: number;
1631
1672
  /** A group with fewer edges stays unbundled. The default is 2. */
@@ -1662,6 +1703,8 @@ type TrunkSplit = "share" | "gilbert";
1662
1703
  type TrunkFan = "split" | "tree";
1663
1704
  /** The rule that groups the edges by the collection of their target, in `data.collection`. */
1664
1705
  export declare const byCollection: GroupRule;
1706
+ /** The names of the built-in grouping rules of the edges. With `collection`, the rule is `byCollection`. With `all`, each edge has one key. */
1707
+ type GroupRuleName = "collection" | "all";
1665
1708
  /**
1666
1709
  * This function groups the edges by their source plug and their key. Each group keeps the order of the edges.
1667
1710
  * A group with fewer than `minSize` edges does not appear.
@@ -1686,6 +1729,204 @@ export declare function splitPoint(start: Point, targets: readonly Point[], spli
1686
1729
  * The edges outside the groups go as in the corner router.
1687
1730
  */
1688
1731
  export declare function trunksRouter(options: TrunksOptions): Router;
1732
+ /** The cost of a link that edges of one key share: a fixed discount, or the flow cost `len * f^alpha` (EDA-029). */
1733
+ type ShareCost = "fixed" | "flow";
1734
+ /** The order of the edges of one key: the longest first, the shortest first, the most load first, or the order of the input (NAT-024). */
1735
+ type ShareOrder = "span" | "shortest" | "load" | "input";
1736
+ /** The place where a route joins or leaves a run: at a corner of the graph, or at the Snell angle (NAT-035). */
1737
+ type ShareMerge = "corner" | "snell";
1738
+ /** The options of the router with shared ways. */
1739
+ interface SharedOptions extends WayOptions {
1740
+ /** The name in the benchmark. */
1741
+ readonly name: string;
1742
+ /**
1743
+ * The edges with one key share their ways. The option takes a rule or the name of a built-in rule (`GROUP_RULE_NAMES`).
1744
+ * Without a rule, or with `all`, all edges share. An edge without a key shares with no edge.
1745
+ */
1746
+ readonly rule?: GroupRule | GroupRuleName;
1747
+ /** The cost of a link that an edge with the same key uses already, as a share of its length. The default is 0.5. */
1748
+ readonly discount?: number;
1749
+ /** The lane order of the runs. With `bundle`, the default, two edges keep one order on each run of their common stretch. With `run`, each run gets its order alone. */
1750
+ readonly laneOrder?: RunOrder;
1751
+ /**
1752
+ * The lane order of each stretch of runs (LANE-STRETCH). With `none`, the default, each run gets its order alone.
1753
+ * With `consensus`, `periphery` or `sifting`, the runs that follow each other on the routes share one order. Only the lane order `bundle` reads it.
1754
+ */
1755
+ readonly stretchOrder?: LaneStretchOrder;
1756
+ /** The number of passes of the stretch order `sifting`, from 1 to 4. The default is 2. */
1757
+ readonly siftPasses?: number;
1758
+ /**
1759
+ * The cost of a shared link. With `fixed`, the default, a link that the key uses already costs `discount` times its length.
1760
+ * With `flow`, one more edge on a link with `f` edges costs `len * ((f + 1)^alpha - f^alpha)` (EDA-029).
1761
+ */
1762
+ readonly cost?: ShareCost;
1763
+ /** The exponent of the flow cost, from 0.1 to 1. A smaller value gives more sharing. The default is 0.6. Only the cost `flow` uses it. */
1764
+ readonly alpha?: number;
1765
+ /** The number of passes. In each pass after the first, each edge leaves its links and finds its way again with the others fixed (HWY-039). The default is 1. */
1766
+ readonly passes?: number;
1767
+ /**
1768
+ * The order of the edges of one key. With `span`, the default, the longest edge goes first. With `shortest`, the shortest edge goes first.
1769
+ * With `load`, the edge with the most edges between its two sections goes first. With `input`, the edges keep the order of the graph (NAT-024).
1770
+ */
1771
+ readonly order?: ShareOrder;
1772
+ /**
1773
+ * The place where a route joins or leaves a run. With `corner`, the default, it is a corner of the graph.
1774
+ * With `snell`, the route meets the run at the angle `acos(d)`, with `d` the cost share of the run for the route (NAT-035).
1775
+ */
1776
+ readonly merge?: ShareMerge;
1777
+ /**
1778
+ * The pull of the busy links of the pass before (HWY-005, Winding Roads). With a value above 0 and two passes or more, each later pass routes each edge again from no ways.
1779
+ * A link then costs `len / (1 + reuse * u)^reuseExponent`, with `u` the edges of the key on it in the pass before. The default is 0: the later passes are rip-up passes.
1780
+ */
1781
+ readonly reuse?: number;
1782
+ /** The exponent of the pull of `reuse`. The default is 1. */
1783
+ readonly reuseExponent?: number;
1784
+ /**
1785
+ * The cost of a lane that does not fit in its channel (HWY-016). One more edge on a link with `f` edges of the key costs `capacity * max(0, (f + 1) * laneWidth - width)` more.
1786
+ * `width` is the free space across the link (`channelWidth`). The default is 0: the router does not read the channels.
1787
+ */
1788
+ readonly capacity?: number;
1789
+ /** The width of one lane, for `capacity`. The default is 4. */
1790
+ readonly laneWidth?: number;
1791
+ /** The benchmark skips a fixture with more nodes. */
1792
+ readonly maxNodes?: number;
1793
+ }
1794
+ /**
1795
+ * The negotiation of the router `attraction` (HWY-044, PathFinder turned around). Each pass routes each edge again from no ways.
1796
+ * A link costs `len (1 - attraction h) (1 + weight max(0, use - cap))` more than in `shared`, with `h` the history of the link.
1797
+ */
1798
+ interface SharedNegotiation {
1799
+ /** The number of passes, 1 or more. */
1800
+ readonly passes: number;
1801
+ /** The pull of the history of a link, from 0 to 1. */
1802
+ readonly attraction: number;
1803
+ /** The cost weight of each edge over the capacity of a link, 0 or more. */
1804
+ readonly capacityWeight: number;
1805
+ /** The width of one lane. The capacity of a link is its free width divided by this width, and 1 or more. */
1806
+ readonly laneWidth: number;
1807
+ }
1808
+ /**
1809
+ * This function makes a router where edges share their ways (after Pupyrev, Nachmanson, Bereg and Holroyd, "Edge routing with ordered bundles").
1810
+ * The edges go one by one through the corner graph. A link that an edge with the same key uses already costs less.
1811
+ * Thus the edges of a key come together on common ways. Each stretch that several edges share has the same points in each route.
1812
+ * The result gives each stretch as a run, with the order of its lanes.
1813
+ */
1814
+ export declare function sharedRouter(options: SharedOptions, negotiation?: SharedNegotiation): Router;
1815
+ /** The options of the router `attraction` (HWY-044 of the note on highways: negotiated attraction, PathFinder turned around). */
1816
+ interface AttractionOptions {
1817
+ /** The number of passes, from 1 to 10. Each pass after the first routes each edge again from no ways. The default is 3. */
1818
+ readonly passes: number;
1819
+ /** The pull `a` of the history of a link, from 0 to 1. A link then costs `1 - a h` times more. The default is 0.5. */
1820
+ readonly attraction: number;
1821
+ /** The cost weight `b` of each edge over the capacity of a link, from 0 to 10. The default is 1. */
1822
+ readonly capacityWeight: number;
1823
+ /** The width of one lane. The capacity of a link is its free width divided by this width. The default is 4. */
1824
+ readonly laneWidth: number;
1825
+ }
1826
+ /** The default options of the router `attraction`. */
1827
+ export declare const ATTRACTION_DEFAULTS: Readonly<AttractionOptions>;
1828
+ /** The declarations of the options of the router `attraction` (HWY-044). */
1829
+ export declare const ATTRACTION_SCHEMA: OptionSchema<AttractionOptions>;
1830
+ /**
1831
+ * This function makes the router `attraction` (HWY-044). It is the router `shared` with a negotiation over the passes.
1832
+ * After each pass, the history `h` of each link grows by `use / m`, with `m` the edges of the key. The history stops at `0.9 / a`.
1833
+ * In each pass, a link costs `len (1 - a h) (1 + b max(0, use - cap))` times the cost in `shared`.
1834
+ * The busy links of the passes before thus pull the edges, and a link over its capacity pushes them away.
1835
+ */
1836
+ export declare function attractionRouter(options: Partial<AttractionOptions> & {
1837
+ readonly name: string;
1838
+ readonly rule?: GroupRule;
1839
+ readonly maxNodes?: number;
1840
+ }): Router;
1841
+ /**
1842
+ * The router strategy `attraction` (HWY-044), with the rule `byCollection` of `shared`. It is not a built-in router, so the benchmark and the hashes of `ROUTERS` do not change.
1843
+ * A screen module or a consumer adds it to a registry.
1844
+ */
1845
+ export declare const attractionStrategy: Strategy<"router", AttractionOptions>;
1846
+ /** Two items of a level that a link joins, and the count of the edges between them. */
1847
+ interface ItemPair {
1848
+ readonly source: string;
1849
+ readonly target: string;
1850
+ readonly count: number;
1851
+ }
1852
+ /** The options of the links of a level: the options of the ways, and two limits of the level links. */
1853
+ interface LevelLinkOptions extends WayOptions {
1854
+ /**
1855
+ * The margin of the second corner graph. A gap between two boxes wider than approximately 1.5 times this margin lets a link through.
1856
+ * The second graph uses the smaller of this value and `margin`. The default is 1.
1857
+ */
1858
+ readonly tightMargin?: number;
1859
+ /** A plug stays at least this far from the corners of its side. The level links use the smaller of this value and `margin`. The default is 6. */
1860
+ readonly plugInset?: number;
1861
+ /**
1862
+ * The cost of a level link through a far box, in units of the mean box size. A far box overlaps neither end of the link.
1863
+ * A link through a far box gets a second way that can go through boxes (`SoftGraph`). The link keeps the way with fewer far boxes.
1864
+ * The value 0 turns the second way off and gives the links of version 0.1.5. The default is 8.
1865
+ */
1866
+ readonly throughCost?: number;
1867
+ }
1868
+ /**
1869
+ * The options of the router with sections. Each option has a default, and the defaults give the output of version 0.1.5.
1870
+ * The options `cap`, `maxDepth` and `collapse` are the limits of the default grouping rule, the quadtree of `buildSections`.
1871
+ * The options `tightMargin`, `plugInset` and `throughCost` are the limits of the level links (`levelLinks`).
1872
+ */
1873
+ interface SectionsOptions extends LevelLinkOptions, SectionOptions {
1874
+ /** The name in the benchmark. */
1875
+ readonly name: string;
1876
+ /**
1877
+ * The number of hubs on each side of the lowest common section that a way passes. A smaller number gives shorter ways
1878
+ * and fewer shared ways. Without it, a way passes each hub from its node up.
1879
+ */
1880
+ readonly hubs?: number;
1881
+ /**
1882
+ * The hub limit. A way through the hubs can be at most this many times as long as the line between its plugs, plus `stretchPad` margins.
1883
+ * Else the edge goes directly. The default is 2. The value `Infinity` keeps each way through the hubs.
1884
+ */
1885
+ readonly stretch?: number;
1886
+ /** A way through the hubs can be this many margins longer than `stretch` times the line between its plugs. The default is 4. */
1887
+ readonly stretchPad?: number;
1888
+ /**
1889
+ * A way skips a hub that is more than this many units farther from the target than the nearest approach of the way before it.
1890
+ * The default is 80, two times `BACKTRACK_MIN`. The value `Infinity` keeps each hub.
1891
+ */
1892
+ readonly hubSlack?: number;
1893
+ /**
1894
+ * The grouping rule: a strategy of the step `group` that makes the tree of sections. The hubs and the zoom levels come from this tree.
1895
+ * Without it, the router uses the quadtree of `buildSections` with the options `cap`, `maxDepth` and `collapse`.
1896
+ */
1897
+ readonly group?: Strategy<"group">;
1898
+ /** The options of the strategy `group`. The strategy gets its `defaults` for each option that this object does not give. */
1899
+ readonly groupOptions?: object;
1900
+ /**
1901
+ * The depths of the tree that get a zoom level with groups. The last level, with each node alone, always comes after them.
1902
+ * The default is each depth, from 0 to the depth of the deepest section.
1903
+ */
1904
+ readonly levels?: readonly number[];
1905
+ /**
1906
+ * The level rule: a strategy of the step `levels` that makes the zoom levels from the tree and the routes.
1907
+ * Without it, the router uses the strategy `depths` (`depthLevels`). The strategy gets the options `levels`, `margin`, `k`, `tightMargin`, `plugInset` and `throughCost` of the router,
1908
+ * and then `levelOptions`.
1909
+ */
1910
+ readonly level?: Strategy<"levels">;
1911
+ /** The options of the strategy `level`. They go over the level options of the router. */
1912
+ readonly levelOptions?: object;
1913
+ /** The lane order of the runs. With `run`, the default, each run gets its order alone. With `bundle`, two edges keep one order on each run of their common stretch. */
1914
+ readonly laneOrder?: RunOrder;
1915
+ /** The benchmark skips a fixture with more nodes. */
1916
+ readonly maxNodes?: number;
1917
+ }
1918
+ /**
1919
+ * This function makes a router with a tree of sections. Each section has a hub: the free corner nearest to the center of its nodes.
1920
+ * An edge goes from its node up the hubs of its sections to the lowest common section, across, and down to the other node.
1921
+ * Each way from hub to hub is found one time, so all the edges on it share its points.
1922
+ * The edges in one section of the lowest level go straight around the nodes.
1923
+ *
1924
+ * An edge skips a hub that takes it away from its target. A way that still goes out and back gives way to the direct way.
1925
+ *
1926
+ * The result gives one zoom level for each depth of the tree.
1927
+ * A link of a level goes from the boundary of one item to the boundary of the other, around the other items.
1928
+ */
1929
+ export declare function sectionsRouter(options: SectionsOptions): Router;
1689
1930
  /** The built-in routers. The registry `STRATEGIES` holds the same routers as strategies, and the benchmark races the routers of the registry. */
1690
1931
  export declare const ROUTERS: readonly Router[];
1691
1932
  /**
@@ -1793,6 +2034,71 @@ export declare function levelPairs(items: readonly LevelItem[], owner: readonly
1793
2034
  * A nearer level only adds growth, so no gap of a far level gets narrower, and a box moves with its parent.
1794
2035
  */
1795
2036
  export declare function levelRoom<T extends Boxed>(nodes: readonly T[], links: readonly RoomLink[], root: Section, options?: LevelRoomOptions): LevelRoom<T>;
2037
+ /**
2038
+ * This function gives the plugs of the plug strategy `facing`: each free plug faces the other end of its edge (`placePlug`).
2039
+ * A fixed plug stays at its point, and a plug with a side stays on that side. It is the default of the router `corners`.
2040
+ * The output has one entry for each edge with two known nodes, in the order of the edges.
2041
+ */
2042
+ export declare function facingEnds(input: PlugInput): PlugPair[];
2043
+ /** The options of the level strategy `depths`: the limits of the level links, and the depths that get a level with groups. */
2044
+ export interface DepthLevelOptions extends Omit<LevelLinkOptions, "smooth"> {
2045
+ /**
2046
+ * The depths of the tree that get a zoom level with groups. The last level, with each node alone, always comes after them.
2047
+ * The default is each depth, from 0 to the depth of the deepest section.
2048
+ */
2049
+ readonly levels?: readonly number[];
2050
+ }
2051
+ /**
2052
+ * This function gives the zoom levels of the level strategy `depths`.
2053
+ * It gives one level for each depth of the tree, and a last level with each node alone.
2054
+ * It is the default of the router `sections`. With the option `levels`, only those depths get a level with groups.
2055
+ * At depth d, a section of depth d is one item. A link joins two items and counts the edges between them.
2056
+ * In a level with groups, a link goes around the boxes of the other items (`levelLinks`).
2057
+ * In the last level, the points of a link are the route of its first edge.
2058
+ */
2059
+ export declare function depthLevels(input: LevelInput, options?: DepthLevelOptions): Level[];
2060
+ /**
2061
+ * The options of the whole strategy `pipeline`: one strategy of each step, and the options of each one.
2062
+ * A rule of the steps `group`, `plugs` and `levels` acts only on a router that reads a rule of that step (`strategyKey`).
2063
+ */
2064
+ export interface PipelineOptions {
2065
+ /** The router. A highway plan takes its place. */
2066
+ readonly router: Strategy<"router">;
2067
+ /** The options of the router. */
2068
+ readonly routerOptions?: object;
2069
+ /** The highway strategy. With it, the plan of the strategy and `follow` give the routes, not the router. */
2070
+ readonly highway?: Strategy<"highway">;
2071
+ /** The options of the highway strategy. */
2072
+ readonly highwayOptions?: object;
2073
+ /** The grouping rule of a router that reads one, for example `sections`. */
2074
+ readonly group?: Strategy<"group">;
2075
+ /** The options of the grouping rule. */
2076
+ readonly groupOptions?: object;
2077
+ /** The plug rule of a router that reads one, for example `corners`. */
2078
+ readonly plugs?: Strategy<"plugs">;
2079
+ /** The options of the plug rule. */
2080
+ readonly plugOptions?: object;
2081
+ /** The level rule of a router that reads one, for example `sections`. */
2082
+ readonly levels?: Strategy<"levels">;
2083
+ /** The options of the level rule. */
2084
+ readonly levelOptions?: object;
2085
+ /** The room strategy. With it, the pipeline opens the gaps of the board before the routes (`openGaps`). */
2086
+ readonly room?: Strategy<"room">;
2087
+ /** The options of the room strategy. */
2088
+ readonly roomOptions?: object;
2089
+ }
2090
+ /**
2091
+ * This function gives the key of the option of a router that takes a strategy of one step.
2092
+ * It gives `undefined` when the router has no such option.
2093
+ * The schema of the router declares the option with the type `strategy` and the step. The options of that strategy have the key `<key>Options`.
2094
+ */
2095
+ export declare function strategyKey(router: Strategy<"router">, step: Step): string | undefined;
2096
+ /**
2097
+ * This function runs the whole strategy `pipeline` on one graph. The room strategy opens the gaps of the board first.
2098
+ * A highway strategy makes its plan, and `follow` routes the plan. Otherwise the router routes, with each rule of the steps `group`, `plugs` and `levels` that it reads.
2099
+ * The output has the board and the routes. The function does not examine the `maxNodes` of the router.
2100
+ */
2101
+ export declare function runPipeline(graph: Graph, options: PipelineOptions): WholeOutput;
1796
2102
  /** A broken hard rule. A correct router has none. */
1797
2103
  export interface Violation {
1798
2104
  readonly rule: "complete" | "ends-at-plugs" | "fixed-plugs" | "no-pass-through" | "counts-sum" | "link-ends" | "bundle-trunk" | "run-shared";
@@ -1967,6 +2273,22 @@ export interface BenchRow {
1967
2273
  readonly levelFaults: readonly LevelFaults[];
1968
2274
  /** The routes of this cell took longer than the cell limit. The cell did not start more routes. A row within the limit has no such field. */
1969
2275
  readonly overLimit?: OverLimit;
2276
+ /** The time of the paired baseline arm (BENCH-GREEN). Only a cell with a baseline router has it. */
2277
+ readonly paired?: Paired;
2278
+ }
2279
+ /**
2280
+ * The paired baseline arm of a cell. The baseline router routes the same graph in turn with the router, on the same CPU.
2281
+ * The ratio does not change with the speed of the runner, so the ratios of two runs compare better than their times.
2282
+ */
2283
+ export interface Paired {
2284
+ /** The name of the baseline router. */
2285
+ readonly base: string;
2286
+ /** The median time of one route of the router in the paired routes, in milliseconds. */
2287
+ readonly ms: number;
2288
+ /** The median time of one route of the baseline router, in milliseconds. */
2289
+ readonly baseMs: number;
2290
+ /** The ratio `ms / baseMs`. A ratio below 1 tells that the router is faster than the baseline. */
2291
+ readonly ratio: number;
1970
2292
  }
1971
2293
  /** The record of a cell over its time limit. */
1972
2294
  export interface OverLimit {
@@ -2003,8 +2325,12 @@ export interface BenchRun {
2003
2325
  readonly row: BenchRow;
2004
2326
  readonly result: Result;
2005
2327
  }
2006
- /** This function does the work of `benchOne` and also gives the result, so more measures can read it without a second route. */
2007
- export declare function benchRun(router: Router, fixture: string, graph: Graph, repeat?: number, cellLimit?: number): BenchRun;
2328
+ /**
2329
+ * This function does the work of `benchOne` and also gives the result, so more measures can read it without a second route.
2330
+ * With a baseline router `pair`, the baseline routes the graph one time for each route of the router, in turn: first before, then after.
2331
+ * The row then gets `paired`. The baseline routes do not count for the cell limit, and their results do not change the row.
2332
+ */
2333
+ export declare function benchRun(router: Router, fixture: string, graph: Graph, repeat?: number, cellLimit?: number, pair?: Router): BenchRun;
2008
2334
  /**
2009
2335
  * This function puts rows in the order of one benchmark run: by fixture, then by router, each in the order of its list.
2010
2336
  * A name that is not in its list goes after the names of the list. Rows with the same place keep their order.
@@ -2218,6 +2544,8 @@ export interface RoomBenchRow {
2218
2544
  * The function also measures the lane routes of the router `sections` at the lane width `spacing`.
2219
2545
  */
2220
2546
  export declare function measureBoard(graph: Graph, spacing: number, order?: LaneOrder): Omit<RoomBenchRow, "fixture" | "board" | "area" | "ms">;
2547
+ /** This function gives the links of the far view of a board: `levelLinks` with each node as one item. */
2548
+ export declare function farLinks(graph: Graph): LevelLink[];
2221
2549
  /**
2222
2550
  * This function measures a packed board, the board with each gap open to the gutter only, and the board that each room strategy opens.
2223
2551
  * The options are the same for each strategy, except `method`. The default strategies are the methods `routes` and `lines` of `roomDemand`.
@@ -2952,6 +3280,29 @@ export interface SuiteOptions {
2952
3280
  readonly steps?: readonly Step[];
2953
3281
  /** The time limit of one cell of the step `router`, in milliseconds, as `BenchOptions.cellLimit` gives it. The default is no limit. */
2954
3282
  readonly cellLimit?: number;
3283
+ /**
3284
+ * One shard of the cells of the steps `router` and `highway` (BENCH-GREEN). The default is all the cells.
3285
+ * The strategy at place `s` of its step, on the seed `k`, belongs to the shard `(s + k) % count`, from 0.
3286
+ * So the seeds of one strategy go to different shards, and each shard gets a similar share of the time.
3287
+ * A shard has only these two steps and the step `curve`, because the cells of the other steps do not divide.
3288
+ */
3289
+ readonly shard?: {
3290
+ readonly index: number;
3291
+ readonly count: number;
3292
+ };
3293
+ /**
3294
+ * The largest fixture of a strategy of the steps `router` and `highway`, in nodes, by the name of the strategy. The default is no cap.
3295
+ * A capped strategy does not route a larger fixture. The report lists each such cell in `capped`, so the row is capped, not missing.
3296
+ */
3297
+ readonly caps?: Readonly<Record<string, number>>;
3298
+ /**
3299
+ * The name of the baseline router of the paired arm, for example `shared`. The default is no paired arm.
3300
+ * On the first seed of each fixture, the baseline routes the same graph in turn with each strategy of the steps `router` and `highway`.
3301
+ * The row and the bench row then get `paired`.
3302
+ */
3303
+ readonly pair?: string;
3304
+ /** The paired arm routes only the fixtures up to this number of nodes. The default is 1000. */
3305
+ readonly pairMax?: number;
2955
3306
  /** This function gets one line of progress for each fixture and seed. */
2956
3307
  readonly log?: (line: string) => void;
2957
3308
  }
@@ -2990,6 +3341,18 @@ export interface SuiteRow {
2990
3341
  readonly treeMs?: number;
2991
3342
  /** The measures, by a key that starts with the id of MEAS0, or the name of a proposed rule. */
2992
3343
  readonly values: Readonly<Record<string, number>>;
3344
+ /** The time of the paired baseline arm (`SuiteOptions.pair`). Only the first seed of a fixture has it. */
3345
+ readonly paired?: Paired;
3346
+ }
3347
+ /** A cell that the suite did not route, because the fixture is larger than the cap of the strategy (`SuiteOptions.caps`). */
3348
+ export interface CappedCell {
3349
+ readonly step: Step;
3350
+ readonly strategy: string;
3351
+ readonly fixture: string;
3352
+ /** The nodes of the fixture. */
3353
+ readonly nodes: number;
3354
+ /** The cap of the strategy, in nodes. */
3355
+ readonly cap: number;
2993
3356
  }
2994
3357
  /** The spread of each measure of one strategy on one fixture family, over the seeds. */
2995
3358
  export interface SuiteSummary {
@@ -3037,8 +3400,13 @@ export interface SuiteReport {
3037
3400
  readonly summaries: readonly SuiteSummary[];
3038
3401
  readonly fronts: readonly SuiteFront[];
3039
3402
  readonly rules: readonly RuleCount[];
3403
+ /** The cells over the cap of their strategy, one for each strategy and fixture. A report with no cap has no such field. */
3404
+ readonly capped?: readonly CappedCell[];
3040
3405
  }
3041
- /** The axes of the Pareto front of each step. The note MEAS0 asks for two to four scores. */
3406
+ /**
3407
+ * The axes of the Pareto front of each step. The note MEAS0 asks for two to four scores.
3408
+ * The steps `plugs`, `levels` and `whole` run as routers (`stepRouterStrategy`), so they use the axes of the step `router`.
3409
+ */
3042
3410
  export declare const FRONT_OBJECTIVES: Readonly<Record<Step, readonly Objective[]>>;
3043
3411
  /** This function gives the seed of the member `k` of the family of a fixture. The member 0 is the fixture itself. */
3044
3412
  export declare function familySeed(spec: FixtureSpec, k: number): number;
@@ -3151,6 +3519,13 @@ export declare function formatRules(rules: readonly RuleCount[]): string;
3151
3519
  * It gives one row for each fixture family of a step. The extra routes of the stability measures have their own column.
3152
3520
  */
3153
3521
  export declare function formatMeasureTime(rows: readonly SuiteRow[], step?: Step): string;
3522
+ /** This function writes the capped cells as a Markdown table. Each line is a cell that the cap of its strategy stopped, so the row is capped, not missing. */
3523
+ export declare function formatCapped(capped: readonly CappedCell[]): string;
3524
+ /**
3525
+ * This function writes the paired arm of the rows as a Markdown table. It gives the medians of the strategy and of the baseline, and their ratio.
3526
+ * Only the rows with `paired` count.
3527
+ */
3528
+ export declare function formatPaired(rows: readonly SuiteRow[]): string;
3154
3529
  /**
3155
3530
  * The options of the highway strategy `corridors` (HWY-031 of the note on highways).
3156
3531
  * The options `margin` and `k` set the corner graph of the first ways, when the input has no first routes.
@@ -3534,6 +3909,8 @@ interface SnapLine {
3534
3909
  interface SnapOptions extends Pick<WayOptions, "margin" | "k"> {
3535
3910
  /** A highway has this number of edges or more. The value is 2 or more. */
3536
3911
  readonly minSize: number;
3912
+ /** With `true`, a line in clear view is its own spine, with no path through the corner graph. The default is `false`. */
3913
+ readonly direct?: boolean;
3537
3914
  }
3538
3915
  /** This function gives the line `u d + rho n` of the direction angle `theta`, with `d = (cos, sin)` and the normal `n = (-sin, cos)`. */
3539
3916
  export declare function linePoint(theta: number, rho: number, u: number): Point;
@@ -4570,6 +4947,212 @@ export declare function scaleSpaceGroups(input: HighwayInput, o: Readonly<ScaleS
4570
4947
  * A short-lived cluster is noise, so a zoom level shows only the stable structure.
4571
4948
  */
4572
4949
  export declare function scaleSpacePlan(input: HighwayInput, o: Readonly<ScaleSpaceOptions>): HighwayPlan;
4950
+ /** The source of the candidate streets: the middle lines of the gaps of the room step, or the lines through the corners. */
4951
+ type StreetSource = "room" | "corners";
4952
+ /** The values of `StreetSource`. */
4953
+ export declare const STREET_SOURCES: readonly StreetSource[];
4954
+ /** One axis-parallel street in the free space, from `a` to `b`. */
4955
+ interface FreeLine {
4956
+ readonly a: Point;
4957
+ readonly b: Point;
4958
+ }
4959
+ /** One edge for the streets: its two points out of its plugs, and the length of its first route. */
4960
+ interface StreetEdge {
4961
+ readonly edge: string;
4962
+ readonly s: Point;
4963
+ readonly t: Point;
4964
+ readonly base: number;
4965
+ }
4966
+ /** The ride of one edge on one street. It has the points where the edge joins and leaves the street, and two lengths. */
4967
+ interface StreetRide {
4968
+ readonly on: Point;
4969
+ readonly off: Point;
4970
+ /** The length on the street. */
4971
+ readonly ride: number;
4972
+ /** The length of the two ramps, to the street and from it. */
4973
+ readonly ramps: number;
4974
+ }
4975
+ /**
4976
+ * This function gives the candidate streets of a board. Each street is an axis-parallel piece of free space.
4977
+ * The source `room` takes the middle line of each gap of `boardGaps` that is two margins wide or more.
4978
+ * The source `corners` takes the lines one margin out from each side of each box.
4979
+ * A street is two margins long or more. The list has no copies, and its order is the same each time.
4980
+ */
4981
+ export declare function freeLines(graph: Graph, finder: WayFinder, source: StreetSource): FreeLine[];
4982
+ /** This function gives the edges of the input for the streets, with the points out of their plugs and the lengths of their first routes. */
4983
+ export declare function streetEdges(input: HighwayInput, finder: WayFinder): StreetEdge[];
4984
+ /** This function gives the point of the street nearest to `p`. */
4985
+ export declare function streetPoint(line: FreeLine, p: Point): Point;
4986
+ /** This function gives the ride of an edge on a street. The edge joins the street at the point nearest to `s`, and leaves it at the point nearest to `t`. */
4987
+ export declare function streetRide(line: FreeLine, e: StreetEdge): StreetRide;
4988
+ /** The options of the highway strategy `gaps` (HWY-057 of the note on highways). */
4989
+ interface GapOptions {
4990
+ /** A street with fewer edges than this number (the demand `k`) is not a highway. The default is 3. */
4991
+ readonly minSize: number;
4992
+ /** The cost of a length on a street against a length off the streets, from 0.1 to 0.8. The default is 0.5. */
4993
+ readonly discount: number;
4994
+ /** An edge rides a street only when its way along the street is this many times its first route or less. The default is 1.3. */
4995
+ readonly detour: number;
4996
+ /** The source of the streets: the gaps of the room step, or the lines through the corners. The default is `room`. */
4997
+ readonly source: StreetSource;
4998
+ }
4999
+ /** The default options of the strategy `gaps`. */
5000
+ export declare const GAP_DEFAULTS: Readonly<GapOptions>;
5001
+ /**
5002
+ * This function gives the highways on the gaps of the board (HWY-057). The streets are the free middle lines of the gaps.
5003
+ * Each edge takes the street that saves it the most cost, when a length on a street costs `discount` times its length.
5004
+ * A street with `minSize` edges or more becomes a highway. The edges of the other streets then choose again among the highways, two times.
5005
+ */
5006
+ export declare function gapPlan(input: HighwayInput, o: Readonly<GapOptions>): HighwayPlan;
5007
+ /** The plan that gives the highways of the network: the plan of `corridors` or of `shared-ways`, with their defaults. */
5008
+ type InterchangeBase = "corridors" | "shared-ways";
5009
+ /** The values of `InterchangeBase`. */
5010
+ export declare const INTERCHANGE_BASES: readonly InterchangeBase[];
5011
+ /** The options of the highway strategy `interchanges` (HWY-060 of the note on highways). */
5012
+ interface InterchangeOptions {
5013
+ /** The plan that gives the highways. The default is `corridors`. */
5014
+ readonly from: InterchangeBase;
5015
+ /** The cost of a change between two highways, in units of the board, from 0 to 8. The default is 2. */
5016
+ readonly changeCost: number;
5017
+ /** The largest number of interchanges, from 1 to 32. The default is 16. */
5018
+ readonly interchanges: number;
5019
+ /** The largest number of highways on the way of one edge, from 1 to 3. The default is 2. */
5020
+ readonly perEdge: number;
5021
+ /** Two highways get an interchange where they come this near, in units of the board. The default is 2. */
5022
+ readonly radius: number;
5023
+ /** The cost of a length on a highway against a length off the highways, from 0.1 to 1. The default is 0.5. */
5024
+ readonly discount: number;
5025
+ /** An edge rides the network only when its way is this many times its first route or less. The default is 1.5. */
5026
+ readonly detour: number;
5027
+ }
5028
+ /** The default options of the strategy `interchanges`. */
5029
+ export declare const INTERCHANGE_DEFAULTS: Readonly<InterchangeOptions>;
5030
+ /** One interchange: a place on the highway `h`, a place on the highway `g`, and the length of the link between the two places. */
5031
+ interface Interchange {
5032
+ readonly h: number;
5033
+ readonly hAt: number;
5034
+ readonly g: number;
5035
+ readonly gAt: number;
5036
+ readonly gap: number;
5037
+ }
5038
+ /** This function gives the candidate interchanges: the nearest places of each pair of spines that come within `radius`, with a link in clear view. */
5039
+ export declare function interchangeCandidates(spines: readonly (readonly Point[])[], radius: number, clear: (a: Point, b: Point) => boolean): Interchange[];
5040
+ /**
5041
+ * This function gives the highways of a network with interchanges (HWY-060). The highways come from a plan. Two highways that come near get an interchange.
5042
+ * Each edge takes its cheapest way: a ride on one highway, or on up to `perEdge` highways with a change at an interchange.
5043
+ * A change costs `changeCost` units. The interchanges that the most edges use stay, up to `interchanges`.
5044
+ */
5045
+ export declare function interchangePlan(input: HighwayInput, o: Readonly<InterchangeOptions>): HighwayPlan;
5046
+ /** The options of the highway strategy `search` (HWY-059 of the note on highways). */
5047
+ interface SearchOptions {
5048
+ /** The plan where the search starts. The default is `corridors`. */
5049
+ readonly from: CandidateSource;
5050
+ /** The generators of the highways that the move `add` takes. The default is `quickbundles` and `road-classes`. */
5051
+ readonly pool: readonly CandidateSource[];
5052
+ /** The number of plans that the search measures, from 0 to 400. The value 0 gives the start plan. The default is 16. */
5053
+ readonly evaluations: number;
5054
+ /** The first temperature of the annealing, on the scale of the score. Each sweep of 4 moves multiplies it by 0.95. The default is 0.02. */
5055
+ readonly temperature: number;
5056
+ /** The weight of the ink that the routes save (B1). The default is 1. */
5057
+ readonly inkWeight: number;
5058
+ /** The weight of the 0.95 quantile of the stretch against the first routes (B3). The default is 0.5. */
5059
+ readonly stretchWeight: number;
5060
+ /** The weight of the ambiguity (B4). The default is 0.5. */
5061
+ readonly ambiguityWeight: number;
5062
+ /** The weight of the largest merge angle (B6), divided by 180 degrees. The default is 0.25. */
5063
+ readonly angleWeight: number;
5064
+ /** The seed of the moves. The default is 1. */
5065
+ readonly seed: number;
5066
+ }
5067
+ /** The default options of the strategy `search`. */
5068
+ export declare const SEARCH_DEFAULTS: Readonly<SearchOptions>;
5069
+ /** The moves of the search. */
5070
+ type SearchMove = "add" | "drop" | "edge" | "point";
5071
+ /** The values of `SearchMove`, in the order of the draw. */
5072
+ export declare const SEARCH_MOVES: readonly SearchMove[];
5073
+ /**
5074
+ * This function gives the score of the routes of a plan: `w1 B1 - w3 B3 - w4 B4 - w6 B6 / 180`. Higher is better.
5075
+ * B3 is the 0.95 quantile of the stretch against the first routes. The score reads only the graph and the routes of the plan.
5076
+ */
5077
+ export declare function searchScore(graph: Graph, routes: readonly Route[], first: readonly Route[], o: Readonly<SearchOptions>): number;
5078
+ /**
5079
+ * This function gives the highways of a local search over the set of highways (HWY-059). The search starts at the plan of `from`.
5080
+ * Each move adds a highway of the pool, drops a highway, moves one edge to another highway, or moves one point of a spine.
5081
+ * The annealing keeps a worse plan with the chance `acceptance(-delta / T)`. The best plan that the search measures is the result.
5082
+ *
5083
+ * The score reads only this graph and its routes. Thus the search does not fit to the inputs of a screen.
5084
+ */
5085
+ export declare function searchPlan(input: HighwayInput, o: Readonly<SearchOptions>): HighwayPlan;
5086
+ /** The groups of the trees: the edges from one source node, or the edges of one collection. */
5087
+ type SteinerGroup = "source" | "key";
5088
+ /** The values of `SteinerGroup`. */
5089
+ export declare const STEINER_GROUPS: readonly SteinerGroup[];
5090
+ /** The method of the tree: the iterated 1-Steiner method on the Hanan grid, or the spanning tree of the terminals alone. */
5091
+ type SteinerMethod = "one-steiner" | "spanning";
5092
+ /** The values of `SteinerMethod`. */
5093
+ export declare const STEINER_METHODS: readonly SteinerMethod[];
5094
+ /** The metric of the tree: rectilinear (two directions) or octilinear (four directions). */
5095
+ type SteinerMetric = "rectilinear" | "octilinear";
5096
+ /** The values of `SteinerMetric`. */
5097
+ export declare const STEINER_METRICS: readonly SteinerMetric[];
5098
+ /** The options of the highway strategy `steiner` (HWY-036 of the note on highways, with EDA-015). */
5099
+ interface SteinerOptions {
5100
+ /** The groups of the trees. The default is `source`. */
5101
+ readonly group: SteinerGroup;
5102
+ /** The method of the tree. The default is `one-steiner`. */
5103
+ readonly method: SteinerMethod;
5104
+ /** A group with more terminals than this number gets the spanning tree alone. The default is 12. */
5105
+ readonly maxGroup: number;
5106
+ /** The metric of the tree. The default is `rectilinear`. */
5107
+ readonly metric: SteinerMetric;
5108
+ /** An edge rides the tree only when its path in the tree is this many times its first route or less. The default is 1.5. */
5109
+ readonly detour: number;
5110
+ /** A stretch of a tree with fewer edges than this number is not a highway. The default is 2. */
5111
+ readonly minSize: number;
5112
+ }
5113
+ /** The default options of the strategy `steiner`. */
5114
+ export declare const STEINER_DEFAULTS: Readonly<SteinerOptions>;
5115
+ /** This function gives the links of the spanning tree of the points (Prim), as pairs of indices, and the sum of their lengths. */
5116
+ export declare function spanningTree(points: readonly Point[], metric: SteinerMetric): {
5117
+ links: [number, number][];
5118
+ cost: number;
5119
+ };
5120
+ /**
5121
+ * This function gives a Steiner tree of the terminals by the iterated 1-Steiner method (Kahng and Robins). The candidates are the points of the Hanan grid.
5122
+ * Each round adds the candidate that makes the spanning tree shortest, and drops each added point with two links or fewer.
5123
+ * The test `free` removes the candidates in the boxes. The result has the terminals first, then the added points.
5124
+ */
5125
+ export declare function oneSteiner(terminals: readonly Point[], metric: SteinerMetric, free: (p: Point) => boolean): {
5126
+ points: Point[];
5127
+ links: [number, number][];
5128
+ };
5129
+ /**
5130
+ * This function gives the highways of obstacle-avoiding Steiner trees (HWY-036 with EDA-015). Each group of edges gets one tree over the points out of its plugs.
5131
+ * The links of the tree are rectilinear or octilinear, and they go around the boxes. Each edge takes its path in the tree, when that path is short enough.
5132
+ * The stretches of the tree that two edges or more share become highways.
5133
+ */
5134
+ export declare function steinerPlan(input: HighwayInput, o: Readonly<SteinerOptions>): HighwayPlan;
5135
+ /** The options of the highway strategy `streets` (HWY-058 of the note on highways). */
5136
+ interface StreetOptions {
5137
+ /** A street covers an edge when the way of the edge along the street is this many times its first route or less (the limit `s`). The default is 1.2. */
5138
+ readonly detour: number;
5139
+ /** The greedy cover stops when the best street gives less than this gain: the length that its edges ride over the length of the street. The default is 2. */
5140
+ readonly minGain: number;
5141
+ /** The largest number of streets. The default is 32. */
5142
+ readonly maxStreets: number;
5143
+ /** A street with fewer new edges than this number is not a highway. The default is 2. */
5144
+ readonly minSize: number;
5145
+ /** The source of the streets: the gaps of the room step, or the lines through the corners. The default is `corners`. */
5146
+ readonly source: StreetSource;
5147
+ }
5148
+ /** The default options of the strategy `streets`. */
5149
+ export declare const STREET_DEFAULTS: Readonly<StreetOptions>;
5150
+ /**
5151
+ * This function gives orthogonal streets by a greedy set cover (HWY-058). A street covers each edge whose way along it is at most `detour` times its first route.
5152
+ * Each step takes the street with the largest gain: the length that its new edges ride, over the length of the street that they use.
5153
+ * The cover stops at `maxStreets` streets, or when the best gain is below `minGain`. Each edge rides one street at most.
5154
+ */
5155
+ export declare function streetPlan(input: HighwayInput, o: Readonly<StreetOptions>): HighwayPlan;
4573
5156
  /** The lines that make the density: the straight lines of the edges, or their first routes. */
4574
5157
  type RidgeSource = "lines" | "routes";
4575
5158
  /** The options of the highway strategy `ridges` (HWY-032 of the note on highways). */
@@ -4636,8 +5219,11 @@ export declare function ridgeLines(input: HighwayInput, o: Readonly<RidgeOptions
4636
5219
  export declare function ridgePlan(input: HighwayInput, o: Readonly<RidgeOptions>): HighwayPlan;
4637
5220
  /** The options of the highway strategy `soft-keys` (HWY-019 of the note on highways). */
4638
5221
  interface SoftKeyOptions {
4639
- /** The rule that gives the key of each edge. The default is `byCollection`: the string `data.collection`. */
4640
- readonly rule: GroupRule;
5222
+ /**
5223
+ * The rule that gives the key of each edge, or the name of a built-in rule (`GROUP_RULE_NAMES`). The default is `byCollection`: the string `data.collection`.
5224
+ * With `all`, each edge has one key, so the keys add no distance.
5225
+ */
5226
+ readonly rule: GroupRule | GroupRuleName;
4641
5227
  /** The distance that two different keys add. `Infinity` keeps the edges of two keys apart, as the hard keys do. The default is 0.25. */
4642
5228
  readonly lambda: number;
4643
5229
  /** Two clusters join while their distance is this value or less. The default is 0.5. */
@@ -5335,21 +5921,51 @@ export declare const highwayStrategies: {
5335
5921
  readonly consensus: Strategy<"highway", ConsensusOptions>;
5336
5922
  readonly "p-hub": Strategy<"highway", PHubOptions>;
5337
5923
  readonly "scale-space": Strategy<"highway", ScaleSpaceOptions>;
5924
+ readonly steiner: Strategy<"highway", SteinerOptions>;
5925
+ readonly gaps: Strategy<"highway", GapOptions>;
5926
+ readonly streets: Strategy<"highway", StreetOptions>;
5927
+ readonly search: Strategy<"highway", SearchOptions>;
5928
+ readonly interchanges: Strategy<"highway", InterchangeOptions>;
5338
5929
  readonly "corridors+breakeven": Strategy<"highway", CorridorOptions & BreakEvenOptions>;
5339
5930
  readonly "corridors+stretch": Strategy<"highway", CorridorOptions & StretchOptions>;
5340
5931
  readonly "corridors+ambiguity": Strategy<"highway", CorridorOptions & AmbiguityGuardOptions>;
5341
5932
  readonly "corridors+hysteresis": Strategy<"highway", CorridorOptions & HysteresisOptions>;
5342
5933
  readonly "corridors+ids": Strategy<"highway", CorridorOptions & StableIdOptions>;
5343
5934
  };
5935
+ /** The built-in plug rules: the strategies of the step `plugs`. The router `corners` routes between their plugs with its option `plug`. */
5936
+ export declare const plugStrategies: {
5937
+ readonly facing: Strategy<"plugs", object>;
5938
+ };
5939
+ /** The built-in level rules: the strategies of the step `levels`. The router `sections` makes its zoom levels with its option `level`. */
5940
+ export declare const levelStrategies: {
5941
+ readonly depths: Strategy<"levels", DepthLevelOptions>;
5942
+ };
5943
+ /**
5944
+ * The built-in whole strategies: the strategies of the step `whole`. The strategy `pipeline` runs one strategy of each step, as the demo of the site does.
5945
+ * Without options, it routes the graph with the router `corners`.
5946
+ */
5947
+ export declare const wholeStrategies: {
5948
+ readonly pipeline: Strategy<"whole", PipelineOptions>;
5949
+ };
5344
5950
  /** The built-in strategies of each step, in order. A consumer adds its own: `createRegistry([...BUILT_IN_STRATEGIES, mine])`. */
5345
5951
  export declare const BUILT_IN_STRATEGIES: readonly AnyStrategy[];
5346
5952
  /** The registry of the built-in strategies. The benchmark and the site take their lists from it. */
5347
5953
  export declare const STRATEGIES: Registry;
5954
+ /**
5955
+ * The steps whose strategies give no routes alone. `compareAnyStep` and the screen compare each strategy of these steps as a router (`stepRouterStrategy`).
5956
+ * The step `highway` gives a plan, and the step `plugs` gives the plugs.
5957
+ * The step `levels` gives the zoom levels, and the step `whole` gives a board with its routes.
5958
+ */
5959
+ export type RoutedStep = "plugs" | "highway" | "levels" | "whole";
5960
+ /** The steps of `RoutedStep`, in the order of the pipeline. */
5961
+ export declare const ROUTED_STEPS: readonly RoutedStep[];
5962
+ /** This function tells if a step is a step of `RoutedStep`. */
5963
+ export declare const isRoutedStep: (step: Step) => step is RoutedStep;
5348
5964
  /**
5349
5965
  * The steps that `compareStep` compares. The step `room` takes a packed board, not a graph, so it is not in the list.
5350
- * The step `highway` gives a plan, not routes. The screen routes each plan with `follow` and compares it as a router.
5966
+ * The steps of `RoutedStep` give no routes alone, so they are not in the list. `compareAnyStep` compares them as routers.
5351
5967
  */
5352
- export type CompareStep = Exclude<Step, "room" | "highway">;
5968
+ export type CompareStep = Exclude<Step, "room" | RoutedStep>;
5353
5969
  /** The steps that `compareStep` compares, in the order of the pipeline. */
5354
5970
  export declare const COMPARE_STEPS: readonly CompareStep[];
5355
5971
  /** The options of `compareStep`. */
@@ -5419,6 +6035,60 @@ export interface StepComparison {
5419
6035
  * The same graph and the same options give the same measures. Only the times change.
5420
6036
  */
5421
6037
  export declare function compareStep(step: CompareStep, graph: Graph, options?: CompareOptions): StepComparison;
6038
+ /** The steps that `compareAnyStep` compares: each step of `STEPS`, in the order of the pipeline. */
6039
+ export declare const COMPARE_ALL_STEPS: readonly Step[];
6040
+ /**
6041
+ * This function gives a router for each highway strategy of a registry, in the order of the registry.
6042
+ * Each router makes the plan of its strategy and routes the plan with `follow` (`highwayRouterStrategy`).
6043
+ * The screen and `compareAnyStep` compare the highway strategies as these routers.
6044
+ */
6045
+ export declare function highwayRouters(registry: Registry): Strategy<"router">[];
6046
+ /**
6047
+ * This function gives a router strategy that runs a strategy of a step of `RoutedStep`. The router has the name, the options and the schema of the strategy.
6048
+ * - A highway strategy makes its plan, and `follow` routes the plan (`highwayRouterStrategy`).
6049
+ * - A plug rule gives the plugs of the router `corners` (its option `plug`).
6050
+ * - A level rule gives the zoom levels of the router `sections` (its option `level`).
6051
+ * - A whole strategy gives the routes of its output. A room strategy in its options can change the board, but the measures read the input graph.
6052
+ */
6053
+ export declare function stepRouterStrategy(strategy: Strategy<RoutedStep>): Strategy<"router">;
6054
+ /** This function gives a router for each strategy of one step of `RoutedStep` in a registry, in the order of the registry (`stepRouterStrategy`). */
6055
+ export declare function stepRouters(registry: Registry, step: RoutedStep): Strategy<"router">[];
6056
+ /** One strategy of any step on one graph: a row of `compareStep`, or a row of the steps `highway` and `room`. */
6057
+ export interface AnyCompareRow extends Omit<CompareRow, "step"> {
6058
+ readonly step: Step;
6059
+ /** The boxes of the board that the room strategy opens, in the order of the nodes, for the step `room`. */
6060
+ readonly boxes?: readonly Box[];
6061
+ /** The links of the far view on the board that the room strategy opens, for the step `room`. */
6062
+ readonly links?: readonly LevelLink[];
6063
+ }
6064
+ /** The comparison of the strategies of any step on one graph. */
6065
+ export interface AnyStepComparison extends Omit<StepComparison, "step" | "rows"> {
6066
+ readonly step: Step;
6067
+ /** One row for each strategy of the step, in the order of the registry. */
6068
+ readonly rows: readonly AnyCompareRow[];
6069
+ }
6070
+ /** The options of `compareAnyStep`. */
6071
+ export interface AnyCompareOptions extends CompareOptions {
6072
+ /** This function gets each row when its strategy is done, with the number of rows that are done and the number of all rows. A host can show the progress. */
6073
+ readonly onRow?: (row: AnyCompareRow, done: number, total: number) => void;
6074
+ }
6075
+ /**
6076
+ * This function gives the measures of a board that a room strategy opened.
6077
+ * It uses the keys and the lane spacing 4 of the step `room` of `runSuite`.
6078
+ * The measures are the area against the board before (`M1.area`), the lane routes through a box (`M4.laneThrough`), the faults of the far view and `room-order`.
6079
+ */
6080
+ export declare function roomValues(graph: Graph, open: readonly Node[]): Record<string, number>;
6081
+ /**
6082
+ * This function runs each strategy of any step of `STEPS` on one graph and measures it. Then it gives the Pareto front of `FRONT_OBJECTIVES`.
6083
+ * The steps `group`, `router` and `curve` give the rows of `compareStep`.
6084
+ * The step `highway` makes the plan of each strategy and routes it with `follow`, as the screen does. It measures the routes as the step `router`.
6085
+ * The steps `plugs`, `levels` and `whole` also run each strategy as a router (`stepRouterStrategy`), and measure the routes as the step `router`.
6086
+ * The step `room` opens the gaps of the board with each strategy (`openGaps`). It measures the open board as the step `room` of `runSuite`.
6087
+ * The step `room` expects a packed board, for example `packedGridBoard`. On a board with wide gaps, a gap opens only when its links need more room.
6088
+ *
6089
+ * The function runs one strategy at a time and gives each row to `onRow`. The same graph and the same options give the same measures. Only the times change.
6090
+ */
6091
+ export declare function compareAnyStep(step: Step, graph: Graph, options?: AnyCompareOptions): AnyStepComparison;
5422
6092
  /** This function gives the bytes of a string in UTF-8. The contract does not export its own `utf8`, so the core keeps this function. */
5423
6093
  export declare function utf8(text: string): Uint8Array;
5424
6094
  /**
@@ -5445,6 +6115,8 @@ export interface LayoutPort {
5445
6115
  /** The fixed place of the port, from the top-left corner of the box. The router does not move a port with `x` and `y`. */
5446
6116
  readonly x?: number;
5447
6117
  readonly y?: number;
6118
+ /** The fixed place of the port on its `side`: a fraction from 0 to 1. The start is the top end or the left end of the side. */
6119
+ readonly along?: number;
5448
6120
  }
5449
6121
  /** A point of a region: `[x, y]`. The y axis points down. */
5450
6122
  export type RegionPoint = readonly [number, number];
@@ -5657,7 +6329,7 @@ export interface LayoutPrediction {
5657
6329
  }
5658
6330
  /**
5659
6331
  * This function writes a graph as an input file of the form `layout-input/1`, with its hash.
5660
- * A fixed plug gets `x`, `y` and the side that holds it. `inputGraph` reads the file back.
6332
+ * A fixed plug gets `x`, `y` and the side that holds it. A plug with `along` keeps its `side` and `along`. `inputGraph` reads the file back.
5661
6333
  */
5662
6334
  export declare function graphInput(graph: Graph, head: LayoutInputHead): LayoutInput;
5663
6335
  /**
@@ -5778,20 +6450,55 @@ export interface ScreenFamily {
5778
6450
  /** The cell of each member in the taxonomy of the corpus. */
5779
6451
  readonly cell: LayoutCell;
5780
6452
  }
6453
+ /**
6454
+ * The key of the family of a screen input (SCREEN-WEIGHT). The map form gives the kind of the cell as the key, with no other dimension.
6455
+ * The cells of a screen set have no `kind`, and `dense-groups` and `many-groups` have the same cell. Thus `familyCell` adds the family of the input as the kind.
6456
+ */
6457
+ export declare const SCREEN_FAMILY_BY: FamilyBy;
6458
+ /** This function gives the cell of an input for the key `familyBy`: the cell of the input, with its family as `kind`. */
6459
+ export declare const familyCell: (input: {
6460
+ readonly family: string;
6461
+ readonly cell?: LayoutCell;
6462
+ }) => FamilyCell;
6463
+ /** The claims of a manifest. `declared` gives the count of the inputs of each family (`docs/CORPUS-CHECKS.md` of `layout-contract`). */
6464
+ export interface CorpusClaims {
6465
+ readonly declared: DeclaredClaim;
6466
+ }
5781
6467
  /** A screen set: a fixed list of small boards with an id. A new board or a changed board gets a new id. */
5782
6468
  export interface ScreenSet {
5783
6469
  /** The id of the set, for example `screen-v1`. The records name it in `set` and `corpus`. */
5784
6470
  readonly id: string;
5785
6471
  readonly families: readonly ScreenFamily[];
6472
+ /** The claims of the manifest of the set. A set without claims has no field `claims` in its manifest. */
6473
+ readonly claims?: CorpusClaims;
6474
+ /** The member seeds of each family that the split `default` holds out. A set without them has no split file. */
6475
+ readonly heldOut?: readonly number[];
5786
6476
  }
6477
+ /** This function gives the seed of the member `k` of a case board with the base seed `base`: `base + 1009 * k`, the rule of `familySeed`. */
6478
+ export declare function caseSeed(base: number, k: number): number;
5787
6479
  /**
5788
6480
  * The screen set `screen-v1`: 14 boards of made-up data from 10 to 150 nodes. Each family shows a known hard case.
5789
6481
  * The seed 0 of each family is the fixture or the case board of the benchmark. The seed `k` of a fixture family is `familySeed(spec, k)`, as in `runSuite`.
5790
6482
  * The generators wrap the fixtures and the case boards without a change to their output.
5791
- * This set does not change. The tests compare it with the files in `corpus/screen-v1`.
6483
+ *
6484
+ * The manifest declares the inputs of each family, with `minCount` 3. The case boards `hub-chain` and `many-groups` have 1 input, so they are in `thin`.
6485
+ * The boards of this set do not change. The tests compare it with the files in `corpus/screen-v1`.
5792
6486
  */
5793
6487
  export declare const SCREEN_V1: ScreenSet;
5794
- /** The screen sets by id: `screen-v1`, the small boards with a known optimum `exact-v1` (MEAS2), and the larger boards with bounds `exact-v1-bounds` (EXACT-BOUNDS). */
6488
+ /** The member seeds of each family of `screen-v2` that the split `default` holds out. */
6489
+ export declare const SCREEN_V2_HELD_OUT: readonly number[];
6490
+ /**
6491
+ * The screen set `screen-v2` (CORPUS-SEEDS): the 6 families of `screen-v1`, each with the 10 members 0 to 9, thus 60 boards.
6492
+ * Each family keeps the seed rule of `screen-v1`. Thus the members 0 to 2 are the boards of `screen-v1`, and the member 0 of `hub-chain` and `many-groups` is their board.
6493
+ *
6494
+ * The manifest declares 10 inputs for each family, and each family key has 10 inputs or more. The split `default` holds out the members 7 to 9 of each family.
6495
+ * This set does not change. The tests compare it with the files in `corpus/screen-v2`.
6496
+ */
6497
+ export declare const SCREEN_V2: ScreenSet;
6498
+ /**
6499
+ * The screen sets by id. `screen-v1` and its larger version `screen-v2` (CORPUS-SEEDS) have the boards of the screen.
6500
+ * `exact-v1` has small boards with a known optimum (MEAS2). `exact-v1-bounds` has larger boards with bounds (EXACT-BOUNDS).
6501
+ */
5795
6502
  export declare const SCREEN_SETS: Readonly<Record<string, ScreenSet>>;
5796
6503
  /** This function gives the id of the member `seed` of a family of a set: `<set>/<family>/s<seed>`. */
5797
6504
  export declare function inputId(set: string, family: string, seed: number): string;
@@ -5814,9 +6521,35 @@ export interface LayoutCorpus {
5814
6521
  readonly hash: string;
5815
6522
  readonly cell: LayoutCell;
5816
6523
  }[];
6524
+ readonly claims?: CorpusClaims;
5817
6525
  }
5818
- /** This function gives the manifest of a list of inputs. The inputs of one generator, version and parameters share one spec. */
5819
- export declare function corpusManifest(corpus: string, inputs: readonly LayoutInput[]): LayoutCorpus;
6526
+ /**
6527
+ * This function gives the manifest of a list of inputs. The inputs of one generator, version and parameters share one spec.
6528
+ * With `claims`, the manifest has the field `claims`.
6529
+ */
6530
+ export declare function corpusManifest(corpus: string, inputs: readonly LayoutInput[], claims?: CorpusClaims): LayoutCorpus;
6531
+ /** This function gives the manifest of a screen set, with the claims of the set. */
6532
+ export declare function setManifest(set: ScreenSet, inputs?: readonly LayoutInput[]): LayoutCorpus;
6533
+ /** The hook of the claim `declared` of a screen set: each input declares its family. */
6534
+ export declare const declaresFamily: (input: {
6535
+ readonly family: string;
6536
+ }) => readonly string[];
6537
+ /**
6538
+ * This function checks the claim `declared` of a manifest against its inputs, with the shared check of the contract. A manifest without the claim gives no break.
6539
+ * With `familyBy`, the check reads the cell of each input with `familyCell`.
6540
+ */
6541
+ export declare function checkFamilies(manifest: LayoutCorpus, inputs: readonly LayoutInput[]): ClaimBreak[];
6542
+ /** This function gives the hash of the corpus of a manifest with the shared function `corpusHashOf` of the contract. It reads the input ids and the input hashes. */
6543
+ export declare function manifestHash(manifest: LayoutCorpus): string;
6544
+ /**
6545
+ * This function gives the split file `corpus-split/1` of a screen set with `heldOut`. A set without `heldOut` gives `undefined`.
6546
+ * The seeds of a split file are the seeds of the specs of the manifest. Thus each fold lists the generator seeds of its members.
6547
+ * - The split `default` has one fold. It holds out the members `heldOut` of each family and trains on the other members.
6548
+ * - The split `by-member` has one fold for each member `k`. The fold holds out the member `k` of each family.
6549
+ */
6550
+ export declare function screenSplit(set: ScreenSet, manifest?: LayoutCorpus): CorpusSplit | undefined;
6551
+ /** This function gives the path of the split file of a corpus, relative to the folder of the corpora: `splits/<corpus id>.<corpus hash>.json`. */
6552
+ export declare function splitPath(split: CorpusSplit): string;
5820
6553
  /**
5821
6554
  * This function gives the output hash of a result of a router, in the highways form.
5822
6555
  * The form holds the routes in the order of the edge ids, and the levels, the bundles and the runs as the router gives them.
@@ -6069,10 +6802,11 @@ export declare function gapValues(input: {
6069
6802
  readonly hash: string;
6070
6803
  }, graph: Graph, result: Result, corners: readonly Route[], baselines: Readonly<Record<GapRule, number>>, optima: ReadonlyMap<string, ExactOptimum>): Record<string, number>;
6071
6804
  /**
6072
- * The steps of the screen: the steps of `compareStep` and the step `highway`.
6805
+ * The steps of the screen: the steps of `compareStep` and the steps of `RoutedStep`.
6073
6806
  * The screen of the step `highway` routes the plan of each strategy with `follow`, and measures the routes as the routes of a router.
6807
+ * The screen of the steps `plugs`, `levels` and `whole` runs each strategy as a router (`stepRouterStrategy`). It measures the routes as the routes of a router.
6074
6808
  */
6075
- export type ScreenStep = CompareStep | "highway";
6809
+ export type ScreenStep = CompareStep | RoutedStep;
6076
6810
  /** The steps of the screen, in the order of the pipeline. */
6077
6811
  export declare const SCREEN_STEPS: readonly ScreenStep[];
6078
6812
  /** The routers that the screen of the step `highway` also runs by default. They are the baselines of the note on highways. */
@@ -6217,8 +6951,6 @@ export declare function unwrappedName(name: string): string;
6217
6951
  export declare function screen(step: ScreenStep, strategies?: readonly (Strategy<ScreenStep> | string)[], options?: ScreenOptions): ScreenReport;
6218
6952
  /** This function writes the summary of a screen as Markdown: one row for each strategy, the front and the predictions. */
6219
6953
  export declare function formatScreen(summary: ScreenSummary): string;
6220
- /** This function gives a whole number from `lo` to `hi`, both included, from a generator of random numbers. */
6221
- export declare function randomInt(r: () => number, lo: number, hi: number): number;
6222
6954
  /** The parameters of the generator `rect-scattered`. */
6223
6955
  export interface RectScatteredParams {
6224
6956
  /** The number of boxes. */
@@ -6226,8 +6958,9 @@ export interface RectScatteredParams {
6226
6958
  }
6227
6959
  /**
6228
6960
  * This function makes the input of the shared generator `rect-scattered`, version 1: a fixed rectangle container, scattered obstacles and boxes without positions.
6229
- * The repository `packing` makes the same file, byte for byte. A test in each repository pins the hashes of the seeds 1, 2 and 3.
6230
- * The steps are `container`, `obstacles` and `boxes`. Each step has its own generator from `stepSeed`.
6961
+ * It uses the shared family `RECT_SCATTERED` of `@mark1russell7/layout-contract` (CORPUS-GEN). The repository `packing` makes the same file, byte for byte.
6962
+ *
6963
+ * @deprecated Use `RECT_SCATTERED` on a registry of `createFamilyRegistry`. This function stays for the callers of today.
6231
6964
  */
6232
6965
  export declare function rectScattered(seed: number, params: RectScatteredParams, set?: string): LayoutInput;
6233
6966
  /** The board classes of the small boards with a known optimum (MEAS2). */
@@ -6272,6 +7005,70 @@ export declare function boundsFamilyName(cls: ExactClass, nodes: number): string
6272
7005
  * This set does not change. The tests compare it with the files in `corpus/exact-v1-bounds`.
6273
7006
  */
6274
7007
  export declare const EXACT_V1_BOUNDS: ScreenSet;
7008
+ /**
7009
+ * The output of a family of highways: the graph of the board and its generator record.
7010
+ * A screen set puts the board into an input file with `graphInput`. The set gives the id, the member seed and the cell.
7011
+ */
7012
+ export interface HighwaysBoard {
7013
+ readonly graph: Graph;
7014
+ /** The generator of the board: its name, its version, its parameters and its input seed. */
7015
+ readonly generator: LayoutGenerator;
7016
+ }
7017
+ /** A corpus family of highways: a family of the shared registry whose output is a `HighwaysBoard`. */
7018
+ export type HighwaysFamily = CorpusFamily$1<HighwaysBoard>;
7019
+ /** The engine of each dimension of the families of highways. */
7020
+ export declare const HIGHWAYS_ENGINE = "highways";
7021
+ /** The fields of a numeric dimension of `numberDimension`. */
7022
+ interface NumberFields {
7023
+ readonly name: string;
7024
+ readonly kind: "int" | "real";
7025
+ readonly min: number;
7026
+ readonly max: number;
7027
+ readonly default: number;
7028
+ readonly scale?: "linear" | "log";
7029
+ readonly meaning: string;
7030
+ }
7031
+ /** This function gives an `int` or a `real` dimension that only highways reads. */
7032
+ export declare function numberDimension(fields: NumberFields): CorpusDimension$1;
7033
+ /** This function gives an `enum` dimension that only highways reads. */
7034
+ export declare function enumDimension(name: string, values: readonly string[], value: string, meaning: string): CorpusDimension$1;
7035
+ /** This function gives the values of the dimensions that differ from their defaults, in the order of the dimensions. */
7036
+ export declare function changedDimensions(dimensions: readonly CorpusDimension$1[], dims: DimensionValues$1): Record<string, ParamValue$1>;
7037
+ /** This function gives the value of a numeric dimension. It throws a `RangeError` when the value is not a number. */
7038
+ export declare function numberOf(dims: DimensionValues$1, name: string): number;
7039
+ /** The values of the dimension `layout`: each `FixtureKind`. */
7040
+ export declare const FIXTURE_LAYOUTS: readonly FixtureKind[];
7041
+ /** The share of the edges near the source when a spec has no `locality`: the default of `makeFixture`. */
7042
+ export declare const FIXTURE_LOCALITY = .65;
7043
+ /** This function gives the spec of a fixture board from the full dimension values. A field at the default of `makeFixture` stays out of the spec. */
7044
+ export declare function fixtureSpecOf(name: string, seed: number, dims: DimensionValues$1): FixtureSpec;
7045
+ /**
7046
+ * This function gives the parameters of the generator record of a fixture board: the spec without its name and its seed.
7047
+ * Thus the record of each screen board stays the record of today, for example `{ kind, nodes, edgesPerNode, fixedPorts }` of `small-clustered`.
7048
+ */
7049
+ export declare function fixtureParams(spec: FixtureSpec): Readonly<Record<string, unknown>>;
7050
+ /** The family `tiny-uniform`: 10 nodes at random places. It is the fixture `tiny-uniform` of `FIXTURES` at its defaults. */
7051
+ export declare const TINY_UNIFORM: HighwaysFamily;
7052
+ /** The family `small-clustered`: 100 nodes in clusters, with a fixed plug on 20% of the nodes. It is the fixture `small-clustered` at its defaults. */
7053
+ export declare const SMALL_CLUSTERED: HighwaysFamily;
7054
+ /** The family `dense-groups`: 150 nodes in tight clusters. It is `denseGroupsBoard` at its defaults. */
7055
+ export declare const DENSE_GROUPS: HighwaysFamily;
7056
+ /** The family `hub-chain`: rows of cards in a chain, and long links between rows. At its defaults, it is `hubChainBoard`. */
7057
+ export declare const HUB_CHAIN: HighwaysFamily;
7058
+ /** The family `many-groups`: groups of cards in a grid, with links between groups. At its defaults, it is `manyGroupsBoard`. */
7059
+ export declare const MANY_GROUPS: HighwaysFamily;
7060
+ /**
7061
+ * The family `packed-grid`: a grid of boxes that touch. At its defaults, it is `packedGridBoard` with 12 columns, 8 rows and 48 long links.
7062
+ * Its generator record always has `cols`, `rows` and `long`, as the screen sets of today. It has `reach` only away from its default.
7063
+ */
7064
+ export declare const PACKED_GRID: HighwaysFamily;
7065
+ /**
7066
+ * The corpus families of highways, in the order of the screen sets. Each family at its defaults makes the board of its screen family.
7067
+ * An import registers nothing. A host makes a registry with `createFamilyRegistry(HIGHWAYS_FAMILIES)`, or with the lists of other engines too.
7068
+ */
7069
+ export declare const HIGHWAYS_FAMILIES: readonly HighwaysFamily[];
7070
+ /** This function gives a new registry of `HIGHWAYS_FAMILIES`. */
7071
+ export declare function highwaysRegistry(): FamilyRegistry$1<HighwaysBoard>;
6275
7072
  /**
6276
7073
  * This function gives the stretch of each route as the exact model counts it, by the edge id.
6277
7074
  * The stretch of a route is its length without its two plug ends, divided by the shortest way in the network of the model.
@@ -6310,7 +7107,7 @@ interface FollowOptions extends WayOptions {
6310
7107
  * The result has a shared run for each stretch of a spine where the same two edges or more go. Each run holds the points of its routes in a row.
6311
7108
  * The same graph, plan and options give the same result.
6312
7109
  */
6313
- export declare function follow(graph: Graph, plan: HighwayPlan, options?: FollowOptions): Result;
7110
+ export declare function follow(input: Graph, plan: HighwayPlan, options?: FollowOptions): Result;
6314
7111
  /**
6315
7112
  * This function gives the highways of a result of a router: one highway for each shared run and for each trunk of a bundle.
6316
7113
  * The spine is the points of the run or of the trunk. Each edge of the run is a member, from one end of the spine to the other end, in the way of its route.
@@ -6659,5 +7456,10 @@ export declare const portfolioStrategy: Strategy<"router", PortfolioRouterOption
6659
7456
  * Each set comes from the train seeds (0 to 4) of its band. The base `shared` is not in a set: the portfolio always runs it first.
6660
7457
  */
6661
7458
  export declare const PORTFOLIO_SETS: Readonly<Record<`${PortfolioRule}|${PortfolioCap}|${string}`, readonly string[]>>;
6662
- export { type AdvectionSettings, type AmbiguityGuardOptions, type ArcOptions, type ArcSource, type AreaOptions, type AreaWidth, type Biclique, type BreakEvenOptions, type BundleLine, type BundleOrder, type CandidateSource, type CellStep, type ClothoidOptions, type ConfluentOptions, type ConsensusLinkage, type ConsensusOptions, type CornersOptions, type CorridorOptions, type Crossbar, type CrossbarOptions, type CubuOptions, type CurveSpace, type CutObjective, type CutOptions, type DensityGrid, type DensityImage, type DensityKernel, type DensitySource, type DiffusionOptions, type DividedOptions, type EdgeDistance, type EdgeEnds, type EdgeGroup, type EdgeLengths, type EdgePathOptions, type EdgePlugs, type ExerciseEvidence, type FdebOptions, type FieldEnd, type FlowClusterOptions, type FlowFieldOptions, type FollowOptions, type FrechetBundle, type FrechetOptions, type Gate, type GroupScope, type GroupSpine, type GroupedOptions, type GrowthOptions, type GrowthOrder, type HashOptions, type HdbscanOptions, type HierarchyGroups, type HierarchyOptions, type Highway, type HighwayBase, type HighwayInput, type HighwayMember, type HighwayOptions, type HighwayPlan, type HoughOptions, type HoughPeak, type HubAllocation, type HubArcOptions, type HubCandidates, type HysteresisOptions, type JogStyle, type KdAxis, type KdLine, type KdOptions, type KdeebOptions, type KeyOptions, type KeyedWay, type KeysOptions, type LaneCurve, type LanesOptions, type LevelHighwayOptions, type LinkCommunityOptions, type LinkEdge, type Linkage, type MeetOptions, type Member, type MemberStatus, type MemberTrace, type MeshOptions, type MingleOptions, type MlsFit, type MlsebOptions, type ModuleRule, type NestedOptions, type NodeKey, type NodeLinks, type OdCellOptions, type OutputGroup, type PHubOptions, type PathStep, type PickSpec, type Portfolio, type PortfolioKey, type PortfolioLevel, type PortfolioOptions, type PortfolioPick, type PortfolioTrace, type PowerOptions, type QuickBundlesOptions, RECORD_EPS, type ResistanceOptions, type Ridge, type RidgeOptions, type RidgeSource, type RoadClassOptions, type RoomBends, type RoundedOptions, type RouteCrossing, type RouteSegment, type SbebOptions, type ScaleCluster, type ScaleSpaceOptions, type SectionsOptions, type SelectCandidate, type SelectLevel, type SelectOptions, type Selection, type ShapeSkeleton, type ShareCost, type ShareMerge, type ShareOrder, type SharedOptions, type SharedStretchOptions, type SharedWaysOptions, type SkeletonGroups, type SkeletonTarget, type SmoothOptions, type SnapLine, type SnapMember, type SnapOptions, type SoftKeyOptions, type SpectralOptions, type SpiralNode, type SpiralOptions, type SplineOptions, type SplitCell, type StableIdOptions, type StretchOptions, type StubEnds, type StubOptions, type TerritoryOptions, type TerritoryPoints, type TraceOptions, type TraclusOptions, type TrafficRule, type TrunkFan, type TrunkSplit, type TrunksOptions, type WeiszfeldOptions, type WspdOptions, type Zip, type ZipLimits, type ZipperOptions, canonicalJson, compareMeasure, exercised, minEffectOf, outputGroups, outputHash, pickMoves, portfolio, selectBest, sha256Hex };
7459
+ /**
7460
+ * The router strategy `shared-stretch` (LANE-STRETCH). It routes as `shared`, and the runs of one stretch share one lane order.
7461
+ * The default stretch order is `sifting`, the best order of the screen. The option `stretchOrder` selects `consensus` or `periphery`.
7462
+ */
7463
+ export declare const sharedStretchStrategy: Strategy<"router", RouterPreset<SharedOptions>>;
7464
+ export { type AdvectionSettings, type AmbiguityGuardOptions, type ArcOptions, type ArcSource, type AreaOptions, type AreaWidth, type AttractionOptions, type Biclique, type BreakEvenOptions, type BundleLine, type BundleOrder, type CandidateSource, type CellStep, type ClothoidOptions, type ConfluentOptions, type ConsensusLinkage, type ConsensusOptions, type CornersOptions, type CorpusDimension, type CorpusFamily, type CorridorOptions, type Crossbar, type CrossbarOptions, type CubuOptions, type CurveSpace, type CutObjective, type CutOptions, DEFAULT_RNG, type DensityGrid, type DensityImage, type DensityKernel, type DensitySource, type DiffusionOptions, type DimensionValues, type DividedOptions, type EdgeDistance, type EdgeEnds, type EdgeGroup, type EdgeLengths, type EdgePathOptions, type EdgePlugs, type ExerciseEvidence, type FamilyRegistry, type FdebOptions, type FieldEnd, type FlowClusterOptions, type FlowFieldOptions, type FollowOptions, type FrechetBundle, type FrechetOptions, type FreeLine, type GapOptions, type Gate, type GenerateContext, type GroupScope, type GroupSpine, type GroupedOptions, type GrowthOptions, type GrowthOrder, type HashOptions, type HdbscanOptions, type HierarchyGroups, type HierarchyOptions, type Highway, type HighwayBase, type HighwayInput, type HighwayMember, type HighwayOptions, type HighwayPlan, type HoughOptions, type HoughPeak, type HubAllocation, type HubArcOptions, type HubCandidates, type HysteresisOptions, type Interchange, type InterchangeBase, type InterchangeOptions, type JogStyle, type KdAxis, type KdLine, type KdOptions, type KdeebOptions, type KeyOptions, type KeyedWay, type KeysOptions, type LaneCurve, type LanesOptions, type LevelHighwayOptions, type LinkCommunityOptions, type LinkEdge, type Linkage, type MeetOptions, type Member, type MemberStatus, type MemberTrace, type MeshOptions, type MingleOptions, type MlsFit, type MlsebOptions, type ModuleRule, type NestedOptions, type NodeKey, type NodeLinks, type OdCellOptions, type OutputGroup, type PHubOptions, type ParamValue, type PathStep, type PickSpec, type Portfolio, type PortfolioKey, type PortfolioLevel, type PortfolioOptions, type PortfolioPick, type PortfolioTrace, type PowerOptions, type QuickBundlesOptions, RECORD_EPS, type ResistanceOptions, type Ridge, type RidgeOptions, type RidgeSource, type RoadClassOptions, type RoomBends, type RoundedOptions, type RouteCrossing, type RouteSegment, type SbebOptions, type ScaleCluster, type ScaleSpaceOptions, type SearchMove, type SearchOptions, type SectionsOptions, type SelectCandidate, type SelectLevel, type SelectOptions, type Selection, type ShapeSkeleton, type ShareCost, type ShareMerge, type ShareOrder, type SharedNegotiation, type SharedOptions, type SharedStretchOptions, type SharedWaysOptions, type SkeletonGroups, type SkeletonTarget, type SmoothOptions, type SnapLine, type SnapMember, type SnapOptions, type SoftKeyOptions, type SpectralOptions, type SpiralNode, type SpiralOptions, type SplineOptions, type SplitCell, type StableIdOptions, type SteinerGroup, type SteinerMethod, type SteinerMetric, type SteinerOptions, type StreetEdge, type StreetOptions, type StreetRide, type StreetSource, type StretchOptions, type StubEnds, type StubOptions, type TerritoryOptions, type TerritoryPoints, type TraceOptions, type TraclusOptions, type TrafficRule, type TrunkFan, type TrunkSplit, type TrunksOptions, type WeiszfeldOptions, type WspdOptions, type Zip, type ZipLimits, type ZipperOptions, canonicalJson, compareMeasure, createFamilyRegistry, dimensionAt, dimensionUnit, exercised, familyKind, levelsOf, minEffectOf, outputGroups, outputHash, paramProblem, pickMoves, portfolio, randomInt, selectBest, sha256Hex };
6663
7465
  //# sourceMappingURL=index.d.ts.map