@mark1russell7/highways 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -7
- package/build/index.d.ts +549 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4965 -2175
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bench/screen/exercise.ts +2 -1
- package/src/highways/balance/index.ts +93 -0
- package/src/highways/index.ts +3 -0
- package/src/highways/manifolds/index.ts +157 -0
- package/src/highways/slots/index.ts +178 -0
- package/src/index.ts +6 -0
- package/src/levels/detail/index.ts +140 -0
- package/src/plugs/leaders/index.ts +42 -0
- package/src/plugs/spread/index.ts +39 -5
- package/src/routers/adam/index.ts +294 -0
- package/src/routers/canals/index.ts +191 -0
- package/src/routers/index.ts +3 -0
- package/src/routers/reroute/index.ts +164 -0
- package/src/routers/shared.ts +3 -0
- package/src/strategies/builtins.ts +102 -1
- package/src/strategies/schemas.ts +89 -0
- package/src/whole/curriculum/index.ts +243 -0
- package/src/whole/fireflies/index.ts +177 -0
- package/src/whole/preferences/index.ts +247 -0
- package/src/whole/tracing/index.ts +144 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { dist, type Point } from "../../geom.ts";
|
|
2
|
+
import type { Graph, GroupRule, Result, Router } from "../../model.ts";
|
|
3
|
+
import { defineStrategy, type Strategy } from "../../strategies/model.ts";
|
|
4
|
+
import type { OptionSchema } from "../../strategies/options.ts";
|
|
5
|
+
import { sharedRouter, type SharedSearch, type Way } from "../shared.ts";
|
|
6
|
+
import { byCollection } from "../trunks.ts";
|
|
7
|
+
|
|
8
|
+
/** The sine of 1 degree, as a literal. A literal gives the same bits on each platform, so a decision does not depend on `Math.sin`. */
|
|
9
|
+
const SIN_1 = 0.01745240643728351;
|
|
10
|
+
|
|
11
|
+
/** The options of the router `reroute` (RULE-044: a corner graph with the prices of the rules, and rounds of rip-up and reroute). */
|
|
12
|
+
export interface RerouteOptions {
|
|
13
|
+
/** The price of a link in a narrow channel, from 0 to 2. The default is 1. */
|
|
14
|
+
readonly alpha: number;
|
|
15
|
+
/** The price of each edge of another key on a link, from 0 to 2. The default is 0.5. */
|
|
16
|
+
readonly beta: number;
|
|
17
|
+
/** The discount of a link that an edge of the same key uses, from 0 to 2. The default is 0.5. */
|
|
18
|
+
readonly gamma: number;
|
|
19
|
+
/** The price of a turn, in units of `clearance`, from 0 to 2. The default is 0.25. */
|
|
20
|
+
readonly tau: number;
|
|
21
|
+
/** The number of rounds of rip-up and reroute, from 1 to 5. The default is 2. */
|
|
22
|
+
readonly rounds: number;
|
|
23
|
+
/** The share of the edges that each round rips up: the edges with the largest price over their direct length, from 0.05 to 0.3. The default is 0.15. */
|
|
24
|
+
readonly q: number;
|
|
25
|
+
/** A channel narrower than this width gets the price `alpha`, from 4 to 64. The default is 16. */
|
|
26
|
+
readonly clearance: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The default options of the router `reroute`. */
|
|
30
|
+
export const REROUTE_DEFAULTS: Readonly<RerouteOptions> = Object.freeze({ alpha: 1, beta: 0.5, gamma: 0.5, tau: 0.25, rounds: 2, q: 0.15, clearance: 16 });
|
|
31
|
+
|
|
32
|
+
/** The declarations of the options of the router `reroute` (RULE-044). */
|
|
33
|
+
export const REROUTE_SCHEMA: OptionSchema<RerouteOptions> = {
|
|
34
|
+
alpha: { type: "number", min: 0, max: 2, step: 0.05, marks: [0, 1, 2], default: 1, describe: "The price of a link in a narrow channel." },
|
|
35
|
+
beta: { type: "number", min: 0, max: 2, step: 0.05, marks: [0, 0.5, 1], default: 0.5, describe: "The price of each edge of another key on a link." },
|
|
36
|
+
gamma: { type: "number", min: 0, max: 2, step: 0.05, marks: [0, 0.5, 1], default: 0.5, describe: "The discount of a link that an edge of the same key uses." },
|
|
37
|
+
tau: { type: "number", min: 0, max: 2, step: 0.05, marks: [0, 0.25, 1], default: 0.25, describe: "The price of a turn, in units of the clearance." },
|
|
38
|
+
rounds: { type: "integer", min: 1, max: 5, step: 1, marks: [1, 2, 3, 5], default: 2, describe: "The number of rounds of rip-up and reroute." },
|
|
39
|
+
q: { type: "number", min: 0.05, max: 0.3, step: 0.05, marks: [0.05, 0.15, 0.3], default: 0.15, describe: "The share of the edges that each round rips up: the edges with the largest price over their direct length." },
|
|
40
|
+
clearance: { type: "number", min: 4, max: 64, step: 1, marks: [8, 16, 32], default: 16, describe: "A channel narrower than this width gets the price alpha." },
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** This function gives the number of turns of a way: the points where the direction changes by more than 1 degree. */
|
|
44
|
+
export function turnsOf(seq: readonly Point[]): number {
|
|
45
|
+
let turns = 0;
|
|
46
|
+
for (let i = 1; i + 1 < seq.length; i++) {
|
|
47
|
+
const a = seq[i - 1]!;
|
|
48
|
+
const b = seq[i]!;
|
|
49
|
+
const c = seq[i + 1]!;
|
|
50
|
+
const ux = b.x - a.x;
|
|
51
|
+
const uy = b.y - a.y;
|
|
52
|
+
const vx = c.x - b.x;
|
|
53
|
+
const vy = c.y - b.y;
|
|
54
|
+
const lu = Math.sqrt(ux * ux + uy * uy);
|
|
55
|
+
const lv = Math.sqrt(vx * vx + vy * vy);
|
|
56
|
+
if (lu <= 1e-9 || lv <= 1e-9) continue;
|
|
57
|
+
if (Math.abs(ux * vy - uy * vx) > SIN_1 * lu * lv || ux * vx + uy * vy < 0) turns++;
|
|
58
|
+
}
|
|
59
|
+
return turns;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The use of one link of the corner graph: the number of edges of each key on it. */
|
|
63
|
+
type LinkUse = Map<string, number>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* This function rips up and reroutes the ways of `shared` (RULE-044, after the rip-up and reroute of PathFinder, McMurchie 1995).
|
|
67
|
+
* The price factor of a link is `max(0.05, 1 + alpha × narrow + beta × others - gamma × same)`.
|
|
68
|
+
* `narrow` is `max(0, 1 - width / clearance)`. `others` counts the edges of the other keys on the link.
|
|
69
|
+
* `same` is 1 when an edge of the same key uses the link.
|
|
70
|
+
* The price of a way is the sum of the price factor times the length of each link, plus `tau × clearance` for each turn.
|
|
71
|
+
* Each round takes the share `q` of the ways with the largest price over their direct length. Each one gets a new search with the prices of the links.
|
|
72
|
+
* The new way stays only when its price is lower. The search has no state for the turns, so only the comparison reads `tau`.
|
|
73
|
+
*/
|
|
74
|
+
export function rerouteWays(ways: readonly Way[], search: SharedSearch, options: Partial<RerouteOptions> = {}): void {
|
|
75
|
+
const o = { ...REROUTE_DEFAULTS, ...options };
|
|
76
|
+
const n = search.corners;
|
|
77
|
+
const use = new Map<number, LinkUse>();
|
|
78
|
+
const linksOf = (w: Way): number[] => {
|
|
79
|
+
const out: number[] = [];
|
|
80
|
+
for (let i = 1; i < w.ids.length; i++) {
|
|
81
|
+
const a = w.ids[i - 1]!;
|
|
82
|
+
const b = w.ids[i]!;
|
|
83
|
+
if (a < n && b < n) out.push(search.link(a, b));
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
};
|
|
87
|
+
const change = (w: Way, by: number): void => {
|
|
88
|
+
for (const k of linksOf(w)) {
|
|
89
|
+
let m = use.get(k);
|
|
90
|
+
if (!m) use.set(k, (m = new Map()));
|
|
91
|
+
const next = (m.get(w.key) ?? 0) + by;
|
|
92
|
+
if (next > 0) m.set(w.key, next);
|
|
93
|
+
else m.delete(w.key);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const found = ways.filter((w) => w.found && w.ids.length >= 2);
|
|
97
|
+
for (const w of found) change(w, 1);
|
|
98
|
+
const factor = (i: number, j: number, key: string): number => {
|
|
99
|
+
const m = use.get(search.link(i, j));
|
|
100
|
+
let others = 0;
|
|
101
|
+
let same = 0;
|
|
102
|
+
for (const [k, c] of m ?? []) {
|
|
103
|
+
if (k === key) same = 1;
|
|
104
|
+
else others += c;
|
|
105
|
+
}
|
|
106
|
+
const narrow = o.alpha > 0 ? Math.max(0, 1 - search.width(i, j) / o.clearance) : 0;
|
|
107
|
+
return Math.max(0.05, 1 + o.alpha * narrow + o.beta * others - o.gamma * same);
|
|
108
|
+
};
|
|
109
|
+
const priceOf = (seq: readonly Point[], ids: readonly number[], key: string): number => {
|
|
110
|
+
let p = 0;
|
|
111
|
+
for (let i = 1; i < seq.length; i++) {
|
|
112
|
+
const a = ids[i - 1]!;
|
|
113
|
+
const b = ids[i]!;
|
|
114
|
+
const d = dist(seq[i - 1]!, seq[i]!);
|
|
115
|
+
p += a < n && b < n ? d * factor(a, b, key) : d;
|
|
116
|
+
}
|
|
117
|
+
return p + o.tau * o.clearance * turnsOf(seq);
|
|
118
|
+
};
|
|
119
|
+
const floor = Math.max(0.05, 1 - o.gamma);
|
|
120
|
+
const count = (share: number): number => Math.max(1, Math.round(share * found.length));
|
|
121
|
+
for (let round = 0; round < Math.max(1, Math.floor(o.rounds)); round++) {
|
|
122
|
+
const ranked = found
|
|
123
|
+
.map((w) => ({ w, score: priceOf(w.seq, w.ids, w.key) / Math.max(1e-9, dist(w.ps.point, w.pt.point)) }))
|
|
124
|
+
.sort((a, b) => b.score - a.score || (a.w.edge.id < b.w.edge.id ? -1 : a.w.edge.id > b.w.edge.id ? 1 : 0));
|
|
125
|
+
let moved = 0;
|
|
126
|
+
for (const { w } of ranked.slice(0, count(Math.min(0.3, Math.max(0.05, o.q))))) {
|
|
127
|
+
change(w, -1);
|
|
128
|
+
const before = priceOf(w.seq, w.ids, w.key);
|
|
129
|
+
const next = search.find(w, (i, j, d) => d * factor(i, j, w.key), floor);
|
|
130
|
+
if (next && priceOf(next.seq, next.ids, w.key) < before - 1e-9) {
|
|
131
|
+
w.seq = next.seq;
|
|
132
|
+
w.ids = next.ids;
|
|
133
|
+
moved++;
|
|
134
|
+
}
|
|
135
|
+
change(w, 1);
|
|
136
|
+
}
|
|
137
|
+
if (moved === 0) break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* This function makes the router `reroute` (RULE-044). It is the router `shared`, then the rounds of rip-up and reroute of `rerouteWays`.
|
|
143
|
+
* The runs and the bundles come from the ways after the rounds.
|
|
144
|
+
*/
|
|
145
|
+
export function rerouteRouter(options: Partial<RerouteOptions> & { readonly name: string; readonly rule?: GroupRule; readonly maxNodes?: number }): Router {
|
|
146
|
+
const o = { ...REROUTE_DEFAULTS, ...options };
|
|
147
|
+
return sharedRouter({ name: o.name, ...(o.rule === undefined ? {} : { rule: o.rule }), ...(o.maxNodes === undefined ? {} : { maxNodes: o.maxNodes }) }, undefined, {
|
|
148
|
+
refine: (ways, search) => rerouteWays(ways, search, o),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The router strategy `reroute` (RULE-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.
|
|
154
|
+
* A screen module or a consumer adds it to a registry.
|
|
155
|
+
*/
|
|
156
|
+
export const rerouteStrategy: Strategy<"router", RerouteOptions> = defineStrategy({
|
|
157
|
+
step: "router",
|
|
158
|
+
name: "reroute",
|
|
159
|
+
describe: "Rule prices and rip-up (RULE-044). The ways of `shared` with the largest prices of narrow channels, other keys and turns get a new search.",
|
|
160
|
+
defaults: { ...REROUTE_DEFAULTS },
|
|
161
|
+
schema: REROUTE_SCHEMA,
|
|
162
|
+
maxNodes: 10_000,
|
|
163
|
+
run: (graph: Graph, o: Readonly<RerouteOptions>): Result => rerouteRouter({ ...o, name: "reroute", rule: byCollection }).route(graph),
|
|
164
|
+
});
|
package/src/routers/shared.ts
CHANGED
|
@@ -108,6 +108,8 @@ export interface SharedSearch {
|
|
|
108
108
|
* The function `cost` can change the cost of the link from corner `i` to corner `j`, of length `d`. It must give at least `floor` × `d`.
|
|
109
109
|
*/
|
|
110
110
|
find(w: Way, cost?: (i: number, j: number, d: number) => number, floor?: number): { seq: Point[]; ids: number[] } | undefined;
|
|
111
|
+
/** This function gives the free space across the link from corner `i` to corner `j` (`channelWidth`). The router keeps each width that it finds. */
|
|
112
|
+
width(i: number, j: number): number;
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
/**
|
|
@@ -212,6 +214,7 @@ export function sharedRouter(options: SharedOptions, negotiation?: SharedNegotia
|
|
|
212
214
|
const way = corners.path(ways.out(w.ps), ways.out(w.pt), cost, floor);
|
|
213
215
|
return way && { seq: way, ids: way.map((p, i) => (i === 0 || i === way.length - 1 ? endId(p) : index.get(p)!)) };
|
|
214
216
|
},
|
|
217
|
+
width: (i, j) => widthOf(i, j),
|
|
215
218
|
};
|
|
216
219
|
const sorted = orderWays(all, options.order ?? "span", graph);
|
|
217
220
|
const order = hooks?.order ? hooks.order(sorted, search) : sorted;
|
|
@@ -47,6 +47,8 @@ import { SCALE_SPACE_DEFAULTS, scaleSpacePlan, type ScaleSpaceOptions } from "..
|
|
|
47
47
|
import { GAP_DEFAULTS, gapPlan, type GapOptions } from "../highways/gaps/index.ts";
|
|
48
48
|
import { INTERCHANGE_DEFAULTS, interchangePlan, type InterchangeOptions } from "../highways/interchanges/index.ts";
|
|
49
49
|
import { KNEE_DEFAULTS, kneePlan, type KneeOptions } from "../highways/knee/index.ts";
|
|
50
|
+
import { BALANCE_DEFAULTS, balancePlan, type BalanceOptions } from "../highways/balance/index.ts";
|
|
51
|
+
import { MANIFOLD_DEFAULTS, manifoldPlan, type ManifoldOptions } from "../highways/manifolds/index.ts";
|
|
50
52
|
import { BRONCHIAL_DEFAULTS, bronchialPlan, type BronchialOptions } from "../highways/bronchial/index.ts";
|
|
51
53
|
import { SEARCH_DEFAULTS, searchPlan, type SearchOptions } from "../highways/search/index.ts";
|
|
52
54
|
import { STEINER_DEFAULTS, steinerPlan, type SteinerOptions } from "../highways/steiner/index.ts";
|
|
@@ -75,11 +77,13 @@ import { WSPD_DEFAULTS, wspdPlan, type WspdOptions } from "../highways/wspd/inde
|
|
|
75
77
|
import { ZIPPER_DEFAULTS, zipperPlan, type ZipperOptions } from "../highways/zipper/index.ts";
|
|
76
78
|
import { depthLevels, type DepthLevelOptions } from "../levels/depths/index.ts";
|
|
77
79
|
import { VENATION_DEFAULTS, venationLevels, type VenationOptions } from "../levels/venation/index.ts";
|
|
80
|
+
import { DETAIL_DEFAULTS, detailLevels, type DetailOptions } from "../levels/detail/index.ts";
|
|
78
81
|
import type { Graph, Result, Router } from "../model.ts";
|
|
79
82
|
import { facingEnds } from "../plugs/facing/index.ts";
|
|
80
83
|
import { justifyEnds, type JustifyOptions } from "../plugs/justify.ts";
|
|
81
84
|
import { sideEnds, type SidePlugOptions } from "../plugs/side.ts";
|
|
82
85
|
import { SPREAD_DEFAULTS, spreadEnds, type SpreadOptions } from "../plugs/spread/index.ts";
|
|
86
|
+
import { LEADER_DEFAULTS, leaderEnds, type LeaderOptions } from "../plugs/leaders/index.ts";
|
|
83
87
|
import { roomDemand, type RoomMethod, type RoomOptions } from "../room/index.ts";
|
|
84
88
|
import { levelRoom, type LevelRoomOptions } from "../room/levels/index.ts";
|
|
85
89
|
import { cornersRouter, type CornersOptions } from "../routers/corners.ts";
|
|
@@ -91,10 +95,15 @@ import { byCollection, trunksRouter, type TrunksOptions } from "../routers/trunk
|
|
|
91
95
|
import { buildSections, SECTION_DEFAULTS, type SectionOptions } from "../sections.ts";
|
|
92
96
|
import { runPipeline, type PipelineOptions } from "../whole/pipeline/index.ts";
|
|
93
97
|
import { BOARD_PORTFOLIO_DEFAULTS, boardPortfolio, type BoardPortfolioOptions, type PortfolioSetting } from "../whole/portfolio/index.ts";
|
|
98
|
+
import { CURRICULUM_DEFAULTS, curriculum, type CurriculumOptions } from "../whole/curriculum/index.ts";
|
|
99
|
+
import { SLOT_DEFAULTS, slotPlan, type SlotOptions } from "../highways/slots/index.ts";
|
|
100
|
+
import { PREFERENCE_DEFAULTS, preferences, type PreferenceOptions } from "../whole/preferences/index.ts";
|
|
101
|
+
import { FIREFLY_DEFAULTS, fireflies, type FireflyOptions } from "../whole/fireflies/index.ts";
|
|
102
|
+
import { TRACING_DEFAULTS, tracing, type TracingOptions } from "../whole/tracing/index.ts";
|
|
94
103
|
import { createRegistry, defineStrategy, type AnyStrategy, type CurveInput, type LaneBoard, type Registry, type Strategy } from "./model.ts";
|
|
95
104
|
import type { OptionSchema } from "./options.ts";
|
|
96
105
|
import { AREA_SCHEMA, CONFLUENT_SCHEMA, CROSSBAR_SCHEMA, FRECHET_SCHEMA, MLSEB_SCHEMA, POWER_SCHEMA, SBEB_SCHEMA } from "./schemas.ts";
|
|
97
|
-
import { DEPTHS_SCHEMA, JUSTIFY_SCHEMA, PIPELINE_SCHEMA, SIDE_PLUG_SCHEMA, SPREAD_SCHEMA, CLOTHOID_SCHEMA, CORNERS_SCHEMA, CORRIDOR_SCHEMA, CONSENSUS_SCHEMA, CUBU_SCHEMA, CUT_SCHEMA, DIFFUSION_SCHEMA, DIVIDED_SCHEMA, EDGE_PATH_SCHEMA, FDEB_SCHEMA, FLOW_CLUSTER_SCHEMA, FLOW_FIELD_SCHEMA, GROWTH_SCHEMA, HDBSCAN_SCHEMA, HIERARCHY_SCHEMA, HIGHWAY_SCHEMA, HOUGH_SCHEMA, HUB_ARC_SCHEMA, KD_SCHEMA, KDEEB_SCHEMA, KEY_SCHEMA, LANES_SCHEMA, LEVEL_HIGHWAY_SCHEMA, LEVEL_ROOM_SCHEMA, LINK_COMMUNITY_SCHEMA, MEET_SCHEMA, MESH_SCHEMA, MINGLE_SCHEMA, NESTED_SCHEMA, OD_CELL_SCHEMA, P_HUB_SCHEMA, QUICKBUNDLES_SCHEMA, RADIUS_SCHEMA, RESISTANCE_SCHEMA, RIDGE_SCHEMA, ROAD_CLASS_SCHEMA, ROOM_SCHEMA, SCALE_SPACE_SCHEMA, SECTION_SCHEMA, SELECT_SCHEMA, SECTIONS_SCHEMA, SHARED_ALL_SCHEMA, SHARED_SCHEMA, SMOOTH_SCHEMA, SOFT_KEY_SCHEMA, SPECTRAL_SCHEMA, SPIRAL_SCHEMA, STUB_SCHEMA, TENSION_SCHEMA, TERRITORY_SCHEMA, TRACLUS_SCHEMA, TRUNKS_SCHEMA, WEISZFELD_SCHEMA, WSPD_SCHEMA, ZIPPER_SCHEMA, STEINER_SCHEMA, GAP_SCHEMA, STREET_SCHEMA, SEARCH_SCHEMA, INTERCHANGE_SCHEMA, KNEE_SCHEMA, BRONCHIAL_SCHEMA, BOARD_PORTFOLIO_SCHEMA, VENATION_SCHEMA } from "./schemas.ts";
|
|
106
|
+
import { DEPTHS_SCHEMA, JUSTIFY_SCHEMA, PIPELINE_SCHEMA, SIDE_PLUG_SCHEMA, SPREAD_SCHEMA, CLOTHOID_SCHEMA, CORNERS_SCHEMA, CORRIDOR_SCHEMA, CONSENSUS_SCHEMA, CUBU_SCHEMA, CUT_SCHEMA, DIFFUSION_SCHEMA, DIVIDED_SCHEMA, EDGE_PATH_SCHEMA, FDEB_SCHEMA, FLOW_CLUSTER_SCHEMA, FLOW_FIELD_SCHEMA, GROWTH_SCHEMA, HDBSCAN_SCHEMA, HIERARCHY_SCHEMA, HIGHWAY_SCHEMA, HOUGH_SCHEMA, HUB_ARC_SCHEMA, KD_SCHEMA, KDEEB_SCHEMA, KEY_SCHEMA, LANES_SCHEMA, LEVEL_HIGHWAY_SCHEMA, LEVEL_ROOM_SCHEMA, LINK_COMMUNITY_SCHEMA, MEET_SCHEMA, MESH_SCHEMA, MINGLE_SCHEMA, NESTED_SCHEMA, OD_CELL_SCHEMA, P_HUB_SCHEMA, QUICKBUNDLES_SCHEMA, RADIUS_SCHEMA, RESISTANCE_SCHEMA, RIDGE_SCHEMA, ROAD_CLASS_SCHEMA, ROOM_SCHEMA, SCALE_SPACE_SCHEMA, SECTION_SCHEMA, SELECT_SCHEMA, SECTIONS_SCHEMA, SHARED_ALL_SCHEMA, SHARED_SCHEMA, SMOOTH_SCHEMA, SOFT_KEY_SCHEMA, SPECTRAL_SCHEMA, SPIRAL_SCHEMA, STUB_SCHEMA, TENSION_SCHEMA, TERRITORY_SCHEMA, TRACLUS_SCHEMA, TRUNKS_SCHEMA, WEISZFELD_SCHEMA, WSPD_SCHEMA, ZIPPER_SCHEMA, STEINER_SCHEMA, GAP_SCHEMA, STREET_SCHEMA, SEARCH_SCHEMA, INTERCHANGE_SCHEMA, KNEE_SCHEMA, BRONCHIAL_SCHEMA, BOARD_PORTFOLIO_SCHEMA, VENATION_SCHEMA, BALANCE_SCHEMA, MANIFOLD_SCHEMA, LEADER_SCHEMA, DETAIL_SCHEMA, CURRICULUM_SCHEMA, SLOT_SCHEMA, PREFERENCE_SCHEMA, FIREFLY_SCHEMA, TRACING_SCHEMA } from "./schemas.ts";
|
|
98
107
|
|
|
99
108
|
/** The options of a router strategy: the options of its router, without the name and the limit of the benchmark. */
|
|
100
109
|
export type RouterPreset<O> = Omit<O, "name" | "maxNodes">;
|
|
@@ -480,6 +489,9 @@ export const highwayStrategies: {
|
|
|
480
489
|
readonly interchanges: Strategy<"highway", InterchangeOptions>;
|
|
481
490
|
readonly knee: Strategy<"highway", KneeOptions>;
|
|
482
491
|
readonly bronchial: Strategy<"highway", BronchialOptions>;
|
|
492
|
+
readonly balance: Strategy<"highway", BalanceOptions>;
|
|
493
|
+
readonly manifolds: Strategy<"highway", ManifoldOptions>;
|
|
494
|
+
readonly slots: Strategy<"highway", SlotOptions>;
|
|
483
495
|
readonly "corridors+breakeven": Strategy<"highway", CorridorOptions & BreakEvenOptions>;
|
|
484
496
|
readonly "corridors+stretch": Strategy<"highway", CorridorOptions & StretchOptions>;
|
|
485
497
|
readonly "corridors+ambiguity": Strategy<"highway", CorridorOptions & AmbiguityGuardOptions>;
|
|
@@ -973,6 +985,33 @@ export const highwayStrategies: {
|
|
|
973
985
|
maxNodes: 10_000,
|
|
974
986
|
run: (input: HighwayInput, o: Readonly<BronchialOptions>) => bronchialPlan(input, o),
|
|
975
987
|
}),
|
|
988
|
+
balance: defineStrategy({
|
|
989
|
+
step: "highway",
|
|
990
|
+
name: "balance",
|
|
991
|
+
describe: "Stretch balance in a bundle (EDA-017). A price for each edge grows while its stretch is above the target, and the price moves its exit forward.",
|
|
992
|
+
defaults: { ...BALANCE_DEFAULTS } as BalanceOptions,
|
|
993
|
+
schema: BALANCE_SCHEMA,
|
|
994
|
+
maxNodes: 10_000,
|
|
995
|
+
run: (input: HighwayInput, o: Readonly<BalanceOptions>) => balancePlan(input, o),
|
|
996
|
+
}),
|
|
997
|
+
manifolds: defineStrategy({
|
|
998
|
+
step: "highway",
|
|
999
|
+
name: "manifolds",
|
|
1000
|
+
describe: "Manifolds for a fan to a row (WILD-036). A straight header in the gap before the row, with taps at right angles and one feed from the node.",
|
|
1001
|
+
defaults: { ...MANIFOLD_DEFAULTS } as ManifoldOptions,
|
|
1002
|
+
schema: MANIFOLD_SCHEMA,
|
|
1003
|
+
maxNodes: 10_000,
|
|
1004
|
+
run: (input: HighwayInput, o: Readonly<ManifoldOptions>) => manifoldPlan(input, o),
|
|
1005
|
+
}),
|
|
1006
|
+
slots: defineStrategy({
|
|
1007
|
+
step: "highway",
|
|
1008
|
+
name: "slots",
|
|
1009
|
+
describe: "A pull toward the lane slots of the trunks (RULE-047). An edge near a trunk joins it on a new lane when the pull is larger than its detour.",
|
|
1010
|
+
defaults: { ...SLOT_DEFAULTS } as SlotOptions,
|
|
1011
|
+
schema: SLOT_SCHEMA,
|
|
1012
|
+
maxNodes: 10_000,
|
|
1013
|
+
run: (input: HighwayInput, o: Readonly<SlotOptions>) => slotPlan(input, o),
|
|
1014
|
+
}),
|
|
976
1015
|
"corridors+breakeven": gateStrategy(corridors, breakEvenGate),
|
|
977
1016
|
"corridors+stretch": gateStrategy(corridors, stretchGate),
|
|
978
1017
|
"corridors+ambiguity": gateStrategy(corridors, ambiguityGate),
|
|
@@ -986,6 +1025,7 @@ export const plugStrategies: {
|
|
|
986
1025
|
readonly side: Strategy<"plugs", SidePlugOptions>;
|
|
987
1026
|
readonly justify: Strategy<"plugs", JustifyOptions>;
|
|
988
1027
|
readonly spread: Strategy<"plugs", SpreadOptions>;
|
|
1028
|
+
readonly leaders: Strategy<"plugs", LeaderOptions>;
|
|
989
1029
|
} = Object.freeze({
|
|
990
1030
|
facing: defineStrategy({
|
|
991
1031
|
step: "plugs",
|
|
@@ -1019,12 +1059,21 @@ export const plugStrategies: {
|
|
|
1019
1059
|
schema: SPREAD_SCHEMA,
|
|
1020
1060
|
run: (input, o) => spreadEnds(input, o),
|
|
1021
1061
|
}),
|
|
1062
|
+
leaders: defineStrategy<"plugs", LeaderOptions>({
|
|
1063
|
+
step: "plugs",
|
|
1064
|
+
name: "leaders",
|
|
1065
|
+
describe: "Boundary leaders as plug stubs (EDA-041). The plugs of each wall take the order of po-leaders with no crossing, and keep a least gap.",
|
|
1066
|
+
defaults: { ...LEADER_DEFAULTS },
|
|
1067
|
+
schema: LEADER_SCHEMA,
|
|
1068
|
+
run: (input, o) => leaderEnds(input, o),
|
|
1069
|
+
}),
|
|
1022
1070
|
});
|
|
1023
1071
|
|
|
1024
1072
|
/** The built-in level rules: the strategies of the step `levels`. The router `sections` makes its zoom levels with its option `level`. */
|
|
1025
1073
|
export const levelStrategies: {
|
|
1026
1074
|
readonly depths: Strategy<"levels", DepthLevelOptions>;
|
|
1027
1075
|
readonly venation: Strategy<"levels", VenationOptions>;
|
|
1076
|
+
readonly detail: Strategy<"levels", DetailOptions>;
|
|
1028
1077
|
} = Object.freeze({
|
|
1029
1078
|
depths: defineStrategy<"levels", DepthLevelOptions>({
|
|
1030
1079
|
step: "levels",
|
|
@@ -1042,6 +1091,14 @@ export const levelStrategies: {
|
|
|
1042
1091
|
schema: VENATION_SCHEMA,
|
|
1043
1092
|
run: (input, o) => venationLevels(input, o),
|
|
1044
1093
|
}),
|
|
1094
|
+
detail: defineStrategy<"levels", DetailOptions>({
|
|
1095
|
+
step: "levels",
|
|
1096
|
+
name: "detail",
|
|
1097
|
+
describe: "The level of detail of the bundles (WILD-016 with EDA-038). Legs of level links closer than a few pixels at the scale of their level become one stroke.",
|
|
1098
|
+
defaults: { ...DETAIL_DEFAULTS },
|
|
1099
|
+
schema: DETAIL_SCHEMA,
|
|
1100
|
+
run: (input, o) => detailLevels(input, o),
|
|
1101
|
+
}),
|
|
1045
1102
|
});
|
|
1046
1103
|
|
|
1047
1104
|
/**
|
|
@@ -1058,6 +1115,14 @@ export const BOARD_PORTFOLIO_SETTINGS: readonly PortfolioSetting[] = Object.free
|
|
|
1058
1115
|
].map((s) => Object.freeze(s)),
|
|
1059
1116
|
);
|
|
1060
1117
|
|
|
1118
|
+
/**
|
|
1119
|
+
* The pool of routes of the whole strategy `curriculum` (RULE-048), in order: the routers of the base of the screen. The first one gives the first answer.
|
|
1120
|
+
* The option `settings` takes the first ones.
|
|
1121
|
+
*/
|
|
1122
|
+
export const CURRICULUM_POOL: readonly PortfolioSetting[] = Object.freeze(
|
|
1123
|
+
(["corners", "shared", "trunks"] as const).map((name) => Object.freeze({ name, pipeline: { router: routerStrategies[name] as Strategy<"router"> } })),
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1061
1126
|
/**
|
|
1062
1127
|
* 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.
|
|
1063
1128
|
* Without options, it routes the graph with the router `corners`.
|
|
@@ -1065,6 +1130,10 @@ export const BOARD_PORTFOLIO_SETTINGS: readonly PortfolioSetting[] = Object.free
|
|
|
1065
1130
|
export const wholeStrategies: {
|
|
1066
1131
|
readonly pipeline: Strategy<"whole", PipelineOptions>;
|
|
1067
1132
|
readonly "board-portfolio": Strategy<"whole", BoardPortfolioOptions>;
|
|
1133
|
+
readonly curriculum: Strategy<"whole", CurriculumOptions>;
|
|
1134
|
+
readonly preferences: Strategy<"whole", PreferenceOptions>;
|
|
1135
|
+
readonly fireflies: Strategy<"whole", FireflyOptions>;
|
|
1136
|
+
readonly tracing: Strategy<"whole", TracingOptions>;
|
|
1068
1137
|
} = Object.freeze({
|
|
1069
1138
|
pipeline: defineStrategy<"whole", PipelineOptions>({
|
|
1070
1139
|
step: "whole",
|
|
@@ -1082,6 +1151,38 @@ export const wholeStrategies: {
|
|
|
1082
1151
|
schema: BOARD_PORTFOLIO_SCHEMA,
|
|
1083
1152
|
run: (graph, o) => boardPortfolio(graph, BOARD_PORTFOLIO_SETTINGS, o).output,
|
|
1084
1153
|
}),
|
|
1154
|
+
curriculum: defineStrategy<"whole", CurriculumOptions>({
|
|
1155
|
+
step: "whole",
|
|
1156
|
+
name: "curriculum",
|
|
1157
|
+
describe: "A curriculum of rules (RULE-048). Each stage adds one rule, and each edge takes the route of a pool that improves it with no loss on the earlier rules.",
|
|
1158
|
+
defaults: { ...CURRICULUM_DEFAULTS },
|
|
1159
|
+
schema: CURRICULUM_SCHEMA,
|
|
1160
|
+
run: (graph, o) => curriculum(graph, CURRICULUM_POOL, o),
|
|
1161
|
+
}),
|
|
1162
|
+
preferences: defineStrategy<"whole", PreferenceOptions>({
|
|
1163
|
+
step: "whole",
|
|
1164
|
+
name: "preferences",
|
|
1165
|
+
describe: "Rule weights from preferences (RULE-038). A fit to made-up pairs gives the weights, and each edge takes the route of a pool with the least weighted cost.",
|
|
1166
|
+
defaults: { ...PREFERENCE_DEFAULTS },
|
|
1167
|
+
schema: PREFERENCE_SCHEMA,
|
|
1168
|
+
run: (graph, o) => preferences(graph, CURRICULUM_POOL, o),
|
|
1169
|
+
}),
|
|
1170
|
+
fireflies: defineStrategy<"whole", FireflyOptions>({
|
|
1171
|
+
step: "whole",
|
|
1172
|
+
name: "fireflies",
|
|
1173
|
+
describe: "Firefly and bee searches (NAT-047). A seeded swarm searches the discount and the margin of `shared` on the board, within a budget of settings.",
|
|
1174
|
+
defaults: { ...FIREFLY_DEFAULTS },
|
|
1175
|
+
schema: FIREFLY_SCHEMA,
|
|
1176
|
+
run: (graph, o) => fireflies(graph, routerStrategies.shared as Strategy<"router">, o).output,
|
|
1177
|
+
}),
|
|
1178
|
+
tracing: defineStrategy<"whole", TracingOptions>({
|
|
1179
|
+
step: "whole",
|
|
1180
|
+
name: "tracing",
|
|
1181
|
+
describe: "The least tracing load (WILD-057). The pipeline tries a fixed list of settings, and the least load of crossings, merges and bends on one edge wins.",
|
|
1182
|
+
defaults: { ...TRACING_DEFAULTS },
|
|
1183
|
+
schema: TRACING_SCHEMA,
|
|
1184
|
+
run: (graph, o) => tracing(graph, BOARD_PORTFOLIO_SETTINGS, o).output,
|
|
1185
|
+
}),
|
|
1085
1186
|
});
|
|
1086
1187
|
|
|
1087
1188
|
/** The built-in strategies of each step, in order. A consumer adds its own: `createRegistry([...BUILT_IN_STRATEGIES, mine])`. */
|
|
@@ -9,6 +9,15 @@ import type { CutOptions } from "../groups/cut/index.ts";
|
|
|
9
9
|
import type { JustifyOptions } from "../plugs/justify.ts";
|
|
10
10
|
import type { SidePlugOptions } from "../plugs/side.ts";
|
|
11
11
|
import type { SpreadOptions } from "../plugs/spread/index.ts";
|
|
12
|
+
import type { LeaderOptions } from "../plugs/leaders/index.ts";
|
|
13
|
+
import type { BalanceOptions } from "../highways/balance/index.ts";
|
|
14
|
+
import type { ManifoldOptions } from "../highways/manifolds/index.ts";
|
|
15
|
+
import type { DetailOptions } from "../levels/detail/index.ts";
|
|
16
|
+
import type { CurriculumOptions } from "../whole/curriculum/index.ts";
|
|
17
|
+
import type { SlotOptions } from "../highways/slots/index.ts";
|
|
18
|
+
import type { PreferenceOptions } from "../whole/preferences/index.ts";
|
|
19
|
+
import type { FireflyOptions } from "../whole/fireflies/index.ts";
|
|
20
|
+
import type { TracingOptions } from "../whole/tracing/index.ts";
|
|
12
21
|
import type { KdOptions } from "../groups/kd/index.ts";
|
|
13
22
|
import type { KeyOptions } from "../groups/keys/index.ts";
|
|
14
23
|
import type { HighwayBase } from "../highways/base.ts";
|
|
@@ -1070,3 +1079,83 @@ export const BOARD_PORTFOLIO_SCHEMA: OptionSchema<BoardPortfolioOptions> = {
|
|
|
1070
1079
|
ink: { type: "number", min: 0, max: 4, step: 0.25, marks: [0, 1, 2], default: 1, describe: "The weight of the ink saved (B1) in the score." },
|
|
1071
1080
|
budget: { type: "number", min: 0, max: 10, step: 0.1, marks: [0, 1, 10], default: 0, describe: "The time budget in seconds. The value 0 sets no budget." },
|
|
1072
1081
|
};
|
|
1082
|
+
|
|
1083
|
+
/** The declarations of the options of the highway strategy `balance` (EDA-017). */
|
|
1084
|
+
export const BALANCE_SCHEMA: OptionSchema<BalanceOptions> = {
|
|
1085
|
+
tau: { type: "number", min: 1.1, max: 2, step: 0.05, marks: [1.1, 1.2, 1.5, 2], default: 1.2, describe: "The target of the stretch of an edge: its route on the plan over its route alone." },
|
|
1086
|
+
iterations: { type: "integer", min: 5, max: 30, step: 1, marks: [5, 10, 30], default: 5, describe: "The number of updates of the prices." },
|
|
1087
|
+
end: { type: "enum", values: ["exit", "entry", "both"], default: "exit", describe: "The end of a ride that the price moves: the exit, the entry, or both by half." },
|
|
1088
|
+
from: { ...HIGHWAY_BASE, default: "shared-ways" },
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1091
|
+
/** The declarations of the options of the highway strategy `manifolds` (WILD-036). */
|
|
1092
|
+
export const MANIFOLD_SCHEMA: OptionSchema<ManifoldOptions> = {
|
|
1093
|
+
kMin: { type: "integer", min: 3, max: 8, step: 1, marks: [3, 4, 6, 8], default: 3, describe: "A manifold has this number of taps or more." },
|
|
1094
|
+
band: { type: "number", min: 0.5, max: 2, step: 0.25, marks: [0.5, 1, 2], default: 1, describe: "The nodes of one row have centers in a band of this many median box heights." },
|
|
1095
|
+
side: { type: "enum", values: ["near", "far"], default: "near", describe: "The place of the header in the gap before the row: near the row, or near the feed node." },
|
|
1096
|
+
detour: { type: "number", min: 1, max: 3, step: 0.05, marks: [1.25, 1.5, 2], default: 1.5, describe: "A tap stays on the manifold only when its way is this many times the direct line or less." },
|
|
1097
|
+
from: { ...HIGHWAY_BASE, default: "shared-ways" },
|
|
1098
|
+
};
|
|
1099
|
+
|
|
1100
|
+
/** The declarations of the options of the highway strategy `slots` (RULE-047). */
|
|
1101
|
+
export const SLOT_SCHEMA: OptionSchema<SlotOptions> = {
|
|
1102
|
+
pull: { type: "number", min: 0.25, max: 8, step: 0.25, marks: [0.5, 1, 2, 4, 8], default: 2, describe: "The weight of the pull toward the slot of a new lane." },
|
|
1103
|
+
reach: { type: "number", min: 8, max: 64, step: 4, marks: [8, 16, 24, 48, 64], default: 24, describe: "A route point farther than this distance from a trunk gets no pull." },
|
|
1104
|
+
laneSpacing: { type: "number", min: 2, max: 8, step: 1, marks: [2, 4, 8], default: 4, describe: "The distance between two lanes of a trunk." },
|
|
1105
|
+
maxStretch: { type: "number", min: 1.05, max: 2, step: 0.05, marks: [1.1, 1.25, 1.5, 2], default: 1.25, describe: "The largest new length of a route over its first length after it joins a trunk." },
|
|
1106
|
+
keys: { type: "enum", values: ["same", "any"], default: "same", describe: "The edges that can join a trunk: only the edges with the key of the trunk, or each edge." },
|
|
1107
|
+
from: { ...HIGHWAY_BASE, default: "shared-ways" },
|
|
1108
|
+
};
|
|
1109
|
+
|
|
1110
|
+
/** The declarations of the options of the plug strategy `leaders` (EDA-041). */
|
|
1111
|
+
export const LEADER_SCHEMA: OptionSchema<LeaderOptions> = {
|
|
1112
|
+
leader: { type: "enum", values: ["s", "po", "opo"], default: "po", describe: "The type of leader: the order of the angles, the order along the wall, or even places." },
|
|
1113
|
+
slotSpacing: { type: "number", min: 2, max: 8, step: 1, marks: [2, 4, 8], default: 8, describe: "The least gap between two plugs of one wall." },
|
|
1114
|
+
inset: SPREAD_SCHEMA.inset,
|
|
1115
|
+
rounds: { type: "integer", min: 0, max: 4, step: 1, default: 2, describe: "The passes that sort each wall again by the new places of the far ends." },
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
/** The declarations of the options of the level strategy `detail` (WILD-016 with EDA-038): the options of `depths`, and the limits of the collapse. */
|
|
1119
|
+
export const DETAIL_SCHEMA: OptionSchema<DetailOptions> = {
|
|
1120
|
+
...DEPTHS_SCHEMA,
|
|
1121
|
+
pxMin: { type: "number", min: 0.5, max: 4, step: 0.5, marks: [1, 2, 3, 4], default: 3, describe: "Two parallel legs closer than this number of pixels on the screen become one stroke." },
|
|
1122
|
+
minCount: { type: "integer", min: 2, max: 5, step: 1, default: 2, describe: "A stroke holds this number of edges or more." },
|
|
1123
|
+
w0: { type: "number", min: 1, max: 4, step: 0.5, default: 1.5, describe: "The width of a stroke of one edge, in pixels." },
|
|
1124
|
+
widthScale: { type: "enum", values: ["linear", "sqrt", "log"], default: "log", describe: "The growth of the width of a stroke with its count." },
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
/** The declarations of the options of the whole strategy `curriculum` (RULE-048). */
|
|
1128
|
+
export const CURRICULUM_SCHEMA: OptionSchema<CurriculumOptions> = {
|
|
1129
|
+
order: { type: "enum", values: ["R1-R12-R2", "R12-R1-R2", "R1-R2-R12"], default: "R1-R12-R2", describe: "The order in which the stages add the rules." },
|
|
1130
|
+
passes: { type: "integer", min: 1, max: 3, step: 1, default: 1, describe: "The number of passes over the edges in each stage." },
|
|
1131
|
+
settings: { type: "integer", min: 2, max: 3, step: 1, default: 3, describe: "The number of settings in the pool of routes, from the start of its list." },
|
|
1132
|
+
detour: { type: "number", min: 1.5, max: 4, step: 0.25, marks: [1.5, 2, 3], default: 2, describe: "A new route has a detour of at most this value, or of its old route." },
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
/** The declarations of the options of the whole strategy `preferences` (RULE-038). */
|
|
1136
|
+
export const PREFERENCE_SCHEMA: OptionSchema<PreferenceOptions> = {
|
|
1137
|
+
l2: { type: "number", min: 0, max: 1, step: 0.01, marks: [0, 0.01, 0.1, 1], default: 0.01, describe: "The weight of the L2 term of the fit of the weights to the made-up pairs." },
|
|
1138
|
+
passes: { type: "integer", min: 1, max: 3, step: 1, default: 1, describe: "The number of passes over the edges." },
|
|
1139
|
+
settings: { type: "integer", min: 2, max: 3, step: 1, default: 3, describe: "The number of settings in the pool of routes, from the start of its list." },
|
|
1140
|
+
detour: { type: "number", min: 1.5, max: 4, step: 0.25, marks: [1.5, 2, 3], default: 2, describe: "A new route has a detour of at most this value, or of its old route." },
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
/** The declarations of the options of the whole strategy `fireflies` (NAT-047). */
|
|
1144
|
+
export const FIREFLY_SCHEMA: OptionSchema<FireflyOptions> = {
|
|
1145
|
+
search: { type: "enum", values: ["firefly", "bees"], default: "firefly", describe: "The search: the firefly algorithm, or the artificial bee colony." },
|
|
1146
|
+
budget: { type: "integer", min: 4, max: 40, step: 1, marks: [4, 12, 20, 40], default: 12, describe: "The largest number of different settings that the search routes." },
|
|
1147
|
+
colony: { type: "integer", min: 4, max: 20, step: 1, marks: [4, 6, 10, 20], default: 6, describe: "The number of fireflies or food sources." },
|
|
1148
|
+
gamma: { type: "number", min: 0.01, max: 10, step: 0.01, scale: "log", marks: [0.01, 0.1, 1, 10], default: 1, describe: "The absorption of the light of a firefly." },
|
|
1149
|
+
alpha: { type: "number", min: 0.01, max: 0.5, step: 0.01, marks: [0.01, 0.1, 0.2, 0.5], default: 0.2, describe: "The size of the random step of a firefly, as a share of the range." },
|
|
1150
|
+
limit: { type: "integer", min: 10, max: 100, step: 10, marks: [10, 50, 100], default: 10, describe: "A scout bee leaves a food source after this number of tries with no gain." },
|
|
1151
|
+
seed: { type: "integer", min: 0, max: 1_000_000, step: 1, marks: [1, 2, 3], default: 1, describe: "The seed of the search. The same seed gives the same routes." },
|
|
1152
|
+
};
|
|
1153
|
+
|
|
1154
|
+
/** The declarations of the options of the whole strategy `tracing` (WILD-057). */
|
|
1155
|
+
export const TRACING_SCHEMA: OptionSchema<TracingOptions> = {
|
|
1156
|
+
crossing: { type: "number", min: 0, max: 4, step: 0.25, marks: [0, 1, 2, 4], default: 1, describe: "The weight of a crossing in the tracing load." },
|
|
1157
|
+
merge: { type: "number", min: 0, max: 4, step: 0.25, marks: [0, 1, 2, 4], default: 2, describe: "The weight of a merge or a split where the edge is not an outer lane." },
|
|
1158
|
+
bend: { type: "number", min: 0, max: 4, step: 0.25, marks: [0, 0.5, 1, 4], default: 0.5, describe: "The weight of a bend in the tracing load." },
|
|
1159
|
+
settings: { type: "integer", min: 1, max: 12, step: 1, marks: [1, 4, 8, 12], default: 4, describe: "The number of settings that the strategy tries, from the start of its list." },
|
|
1160
|
+
quantile: { type: "enum", values: ["q50", "q95", "mean"], default: "q95", describe: "The value of the loads of the edges that the pick reads." },
|
|
1161
|
+
};
|