@mark1russell7/highways 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/build/index.d.ts +12 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +40 -21
- package/build/index.js.map +1 -1
- package/package.json +2 -2
- package/src/bench/screen/portfolio-pick.ts +2 -1
- package/src/portfolio/fit.ts +15 -15
- package/src/portfolio/router.ts +19 -3
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"directory": "packages/core"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://mark1russell7.github.io/highways/",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.7.0",
|
|
13
13
|
"type": "module",
|
|
14
14
|
"main": "./build/index.js",
|
|
15
15
|
"types": "./build/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@mark1russell7/layout-contract": "^0.2.
|
|
32
|
+
"@mark1russell7/layout-contract": "^0.2.8"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@mark1russell7/cue": "github:mark1russell7/cue",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// The portfolio combinator (PORTFOLIO-API): `portfolio`, `selectBest` and `pickMoves` come from `@mark1russell7/layout-contract` 0.2.6 (PORTFOLIO-FIT).
|
|
2
|
-
// The
|
|
2
|
+
// The option `hashes` of `PortfolioOptions` comes from the contract 0.2.8 (HASH-LAZY).
|
|
3
|
+
// The rules of the pick, the time limit, the hashes and the trace are in `docs/PORTFOLIO.md` of the contract.
|
|
3
4
|
export {
|
|
4
5
|
pickMoves,
|
|
5
6
|
portfolio,
|
package/src/portfolio/fit.ts
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
// This file is generated by `scripts/portfolio-sets.ts` (`pnpm portfolio:sets`). Do not edit it. The test `sets.test.ts` checks that it is current.
|
|
2
|
-
// The times come from the CI run
|
|
2
|
+
// The times come from the CI run 40681241949 (the workflow `Portfolio`, `portfolio:time --members`).
|
|
3
3
|
import type { PortfolioCap, PortfolioRule } from "./bands.ts";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The fit of each rule, cap and size band, by the key `<rule>|<cap>|<band>`: the members of the default of the portfolio router, in their order.
|
|
7
|
-
* Each member has a node limit: it runs only on an input with that many nodes or fewer. The limits keep the model time at or below
|
|
7
|
+
* Each member has a node limit: it runs only on an input with that many nodes or fewer. The limits keep the model time at or below 45 ms.
|
|
8
8
|
* The base `shared` is not in a fit: the portfolio always runs it first.
|
|
9
9
|
*/
|
|
10
10
|
export const PORTFOLIO_FIT: Readonly<Record<`${PortfolioRule}|${PortfolioCap}|${string}`, readonly (readonly [string, number])[]>> = {
|
|
11
11
|
"collection|1.1|n1-12": [["corners-side", 12], ["w2c:select+stretch", 12], ["trunks-gilbert-a05", 12], ["w3a:spiral-a15", 12], ["trunks-tree-bf08", 12], ["hw:zipper", 12], ["w2c:level-links+stretch-b1.1", 12], ["hw:stubs", 12]],
|
|
12
|
-
"collection|1.1|n13-24": [["w3e:crossbars+stretch", 24], ["trunks-tree-bf08", 24], ["corners-side", 24], ["shared-p2", 24], ["w2c:zipper+stretch-b1.1", 18]],
|
|
13
|
-
"collection|1.1|n25-40": [["w2a:shared-ways+breakeven", 40], ["w2b:weiszfeld-a1",
|
|
12
|
+
"collection|1.1|n13-24": [["w3e:crossbars+stretch", 24], ["trunks-tree-bf08", 24], ["corners-side", 24], ["shared-p2", 24], ["w2c:zipper+stretch-b1.1", 18], ["hw:weiszfeld", 18], ["trunks-gilbert-a07", 18]],
|
|
13
|
+
"collection|1.1|n25-40": [["w2a:shared-ways+breakeven", 40], ["w2b:weiszfeld-a1", 40]],
|
|
14
14
|
"collection|1.1|n41-64": [],
|
|
15
15
|
"collection|1.1|n65-128": [],
|
|
16
16
|
"collection|1.25|n1-12": [["corners-side", 12], ["trunks-tree-bf06", 12], ["w3f:p-hub-a0.2", 12], ["hw:stubs", 12], ["hw:p-hub", 12], ["hw:spiral", 12], ["w2c:level-links+stretch", 12], ["w3f:spectral-c0.3", 12]],
|
|
17
|
-
"collection|1.25|n13-24": [["w2a:shared-ways+stretch", 24], ["shared-p3", 24], ["trunks-gilbert-a07", 24], ["w3e:crossbars+stretch", 24], ["trunks-tree-bf06", 24], ["w3c:hdbscan+stretch", 18], ["shared-wind-p2-r1-e2", 18]],
|
|
18
|
-
"collection|1.25|n25-40": [["w2a:shared-ways+stretch", 40], ["shared-p3", 40], ["shared-order-shortest", 32]],
|
|
17
|
+
"collection|1.25|n13-24": [["w2a:shared-ways+stretch", 24], ["shared-p3", 24], ["trunks-gilbert-a07", 24], ["w3e:crossbars+stretch", 24], ["trunks-tree-bf06", 24], ["w3c:hdbscan+stretch", 18], ["shared-wind-p2-r1-e2", 18], ["hw:stubs", 18]],
|
|
18
|
+
"collection|1.25|n25-40": [["w2a:shared-ways+stretch", 40], ["shared-p3", 40], ["shared-order-shortest", 40], ["w2b:weiszfeld-a1", 32]],
|
|
19
19
|
"collection|1.25|n41-64": [],
|
|
20
20
|
"collection|1.25|n65-128": [],
|
|
21
21
|
"collection|1.5|n1-12": [["trunks-gilbert-a03", 12], ["w3e:areas-keys", 12], ["trunks-tree-bf02", 12], ["w3f:p-hub-a0.2", 12], ["w2b:zipper-a1", 12], ["w3a:spiral-a35", 12], ["w3f:spectral-c0.3", 12], ["w2c:level-links+stretch", 12]],
|
|
22
|
-
"collection|1.5|n13-24": [["shared-wind-p2-r0.5", 24], ["trunks-gilbert-a03", 24], ["w3e:crossbars+stretch", 24], ["shared-wind-p2-r1-e2", 24], ["trunks-tree-bf06", 24], ["shared-flow-a06-p3", 24], ["shared-wind-p3-r1",
|
|
23
|
-
"collection|1.5|n25-40": [["shared-p3", 40], ["hw:lanes", 40], ["shared-wind-p2-r1-e2", 32]],
|
|
22
|
+
"collection|1.5|n13-24": [["shared-wind-p2-r0.5", 24], ["trunks-gilbert-a03", 24], ["w3e:crossbars+stretch", 24], ["shared-wind-p2-r1-e2", 24], ["trunks-tree-bf06", 24], ["shared-flow-a06-p3", 24], ["shared-wind-p3-r1", 24], ["trunks-gilbert-a07", 24]],
|
|
23
|
+
"collection|1.5|n25-40": [["shared-p3", 40], ["hw:lanes", 40], ["shared-wind-p2-r1-e2", 40], ["hw:crossbars", 32]],
|
|
24
24
|
"collection|1.5|n41-64": [["shared-flow-a06-p3", 64]],
|
|
25
25
|
"collection|1.5|n65-128": [],
|
|
26
|
-
"all|1.1|n1-12": [["w2b:zipper-p2", 12], ["hw:cubu", 12], ["w3d:kdeeb+stretch", 12], ["w3c:hough-wide", 12], ["w3d:kdeeb-routes", 12], ["hw:stubs",
|
|
27
|
-
"all|1.1|n13-24": [["w3e:frechet-e0.5", 24], ["w3a:diffusion-wide", 24], ["w2c:zipper+stretch-b1.1", 24], ["w3d:cubu+stretch", 18]],
|
|
26
|
+
"all|1.1|n1-12": [["w2b:zipper-p2", 12], ["hw:cubu", 12], ["w3d:kdeeb+stretch", 12], ["w3c:hough-wide", 12], ["w3d:kdeeb-routes", 12], ["hw:stubs", 12], ["hw:spiral", 12], ["w3b:growth-s0.7", 10]],
|
|
27
|
+
"all|1.1|n13-24": [["w3e:frechet-e0.5", 24], ["w3a:diffusion-wide", 24], ["w2c:zipper+stretch-b1.1", 24], ["w3d:cubu+stretch", 18], ["w3a:spiral-a15", 18]],
|
|
28
28
|
"all|1.1|n25-40": [["w2c:zipper+stretch-b1.1", 40], ["w3a:spiral-a15", 32]],
|
|
29
|
-
"all|1.1|n41-64": [],
|
|
29
|
+
"all|1.1|n41-64": [["hw:diffusion", 64]],
|
|
30
30
|
"all|1.1|n65-128": [],
|
|
31
|
-
"all|1.25|n1-12": [["w3d:kdeeb-routes", 12], ["w3e:mlseb+stretch", 12], ["hw:growth", 12], ["hw:level-links",
|
|
32
|
-
"all|1.25|n13-24": [["w3d:kdeeb-routes", 24], ["w3f:p-hub-a0.2",
|
|
33
|
-
"all|1.25|n25-40": [],
|
|
31
|
+
"all|1.25|n1-12": [["w3d:kdeeb-routes", 12], ["w3e:mlseb+stretch", 12], ["hw:growth", 12], ["hw:level-links", 12], ["w3b:growth-input", 10], ["w3e:confluent+stretch", 10], ["w3d:kdeeb-nomask", 10]],
|
|
32
|
+
"all|1.25|n13-24": [["w3d:kdeeb-routes", 24], ["w3f:p-hub-a0.2", 24], ["w3d:kdeeb-nomask", 18], ["w3a:spiral-n3", 18]],
|
|
33
|
+
"all|1.25|n25-40": [["w3d:kdeeb-routes", 32]],
|
|
34
34
|
"all|1.25|n41-64": [],
|
|
35
35
|
"all|1.25|n65-128": [],
|
|
36
36
|
"all|1.5|n1-12": [["w3b:growth-s0.3", 12], ["w3e:mlseb-a0", 12], ["w3e:mlseb-routes", 10], ["w3c:edge-paths-k1.5", 10], ["w3f:territories-r2", 10]],
|
|
37
37
|
"all|1.5|n13-24": [["hw:growth", 24], ["w3b:growth-input", 24]],
|
|
38
|
-
"all|1.5|n25-40": [["hw:growth", 40], ["w3b:growth-s0.7", 40]],
|
|
38
|
+
"all|1.5|n25-40": [["hw:growth", 40], ["w3b:growth-s0.7", 40], ["w3b:growth-s0.3", 32]],
|
|
39
39
|
"all|1.5|n41-64": [],
|
|
40
40
|
"all|1.5|n65-128": [],
|
|
41
41
|
};
|
package/src/portfolio/router.ts
CHANGED
|
@@ -30,8 +30,20 @@ export interface PortfolioRouterOptions {
|
|
|
30
30
|
readonly maxMembers?: number;
|
|
31
31
|
/** The clock in milliseconds. The default is `performance.now`. */
|
|
32
32
|
readonly now?: () => number;
|
|
33
|
+
/**
|
|
34
|
+
* The members that get an output hash in the trace (HASH-LAZY). The pick does not use the hashes, so the winner and the output do not change.
|
|
35
|
+
* - With `pick` (the default), only the base and the winner get a hash, and only when the winner is not the base.
|
|
36
|
+
* - With `all`, each member that ran gets a hash, as before HASH-LAZY. Use it when you need the `outputHash` of each member.
|
|
37
|
+
*/
|
|
38
|
+
readonly hashes?: PortfolioHashes;
|
|
33
39
|
}
|
|
34
40
|
|
|
41
|
+
/** The values of the option `hashes` of the portfolio router. */
|
|
42
|
+
export type PortfolioHashes = "all" | "pick";
|
|
43
|
+
|
|
44
|
+
/** The values of the option `hashes`, in order. The default is `pick`. */
|
|
45
|
+
export const PORTFOLIO_HASHES: readonly PortfolioHashes[] = ["pick", "all"];
|
|
46
|
+
|
|
35
47
|
/** The base member of each portfolio: the router `shared` with the rule `byCollection`. It is the fallback output above the cap. */
|
|
36
48
|
export const PORTFOLIO_BASE_MEMBER = "shared";
|
|
37
49
|
|
|
@@ -49,14 +61,16 @@ export interface PortfolioRoute {
|
|
|
49
61
|
}
|
|
50
62
|
|
|
51
63
|
/** This function checks the options of the portfolio router, and gives them with their defaults. It throws a `RangeError` for a bad value. */
|
|
52
|
-
function checked(o: PortfolioRouterOptions): { rule: PortfolioRule; cap: PortfolioCap; k: 3 | 5 | 8 | undefined } {
|
|
64
|
+
function checked(o: PortfolioRouterOptions): { rule: PortfolioRule; cap: PortfolioCap; k: 3 | 5 | 8 | undefined; hashes: PortfolioHashes } {
|
|
53
65
|
const rule = o.rule ?? "collection";
|
|
54
66
|
const cap = o.cap ?? 1.5;
|
|
55
67
|
const k = o.k;
|
|
68
|
+
const hashes = o.hashes ?? "pick";
|
|
56
69
|
if (!PORTFOLIO_RULES.includes(rule)) throw new RangeError(`The portfolio router has the rule "${String(rule)}". It must be ${PORTFOLIO_RULES.join(" or ")}.`);
|
|
57
70
|
if (!PORTFOLIO_CAPS.includes(cap)) throw new RangeError(`The portfolio router has the cap ${String(cap)}. It must be ${PORTFOLIO_CAPS.join(", ")}.`);
|
|
58
71
|
if (k !== undefined && !PORTFOLIO_KS_API.includes(k)) throw new RangeError(`The portfolio router has the k ${String(k)}. It must be ${PORTFOLIO_KS_API.join(", ")}.`);
|
|
59
|
-
|
|
72
|
+
if (!PORTFOLIO_HASHES.includes(hashes)) throw new RangeError(`The portfolio router has the hashes "${String(hashes)}". It must be ${PORTFOLIO_HASHES.join(" or ")}.`);
|
|
73
|
+
return { rule, cap, k, hashes };
|
|
60
74
|
}
|
|
61
75
|
|
|
62
76
|
/** This function gives the name of the portfolio router with the options `options`: `portfolio-<rule>-<cap>-k<k>`, or `portfolio-<rule>-<cap>-fit` without `k`. */
|
|
@@ -83,11 +97,12 @@ export function portfolioMembers(nodes: number, options: PortfolioRouterOptions
|
|
|
83
97
|
* The key is `portfolioKey`: a member wins only when it passes the guard against the base. Of those members, the winner has the most ink saved.
|
|
84
98
|
* A tie within the `minEffect` of B1 goes to the first member (`selectBest`). A member that throws does not win.
|
|
85
99
|
* The result carries the trace of the pick and the move count `move.pick`.
|
|
100
|
+
* With the option `hashes` "pick" (the default), only the base and the winner get an `outputHash` in the trace. They get it only when the winner is not the base.
|
|
86
101
|
*/
|
|
87
102
|
export function routePortfolio(graph: Graph, options: PortfolioRouterOptions = {}): PortfolioRoute {
|
|
88
103
|
// A member with a node limit below the size of the graph does not run. The base `shared` has no such limit below the limit of the router.
|
|
89
104
|
const names = portfolioMembers(graph.nodes.length, options).filter((name) => name === PORTFOLIO_BASE_MEMBER || (portfolioMember(name)?.maxNodes ?? Infinity) >= graph.nodes.length);
|
|
90
|
-
const { rule, cap } = checked(options);
|
|
105
|
+
const { rule, cap, hashes } = checked(options);
|
|
91
106
|
// The key compares each member with the output of the base, so the run of the base keeps its output.
|
|
92
107
|
let base: Result | undefined;
|
|
93
108
|
const members: Member<Graph, Result>[] = names.map((name) => {
|
|
@@ -104,6 +119,7 @@ export function routePortfolio(graph: Graph, options: PortfolioRouterOptions = {
|
|
|
104
119
|
};
|
|
105
120
|
});
|
|
106
121
|
const p = portfolio(portfolioName(options), members, portfolioKey(graph, rule, cap, () => base), {
|
|
122
|
+
hashes,
|
|
107
123
|
...(options.budgetMs === undefined ? {} : { budgetMs: options.budgetMs }),
|
|
108
124
|
...(options.maxMembers === undefined ? {} : { maxMembers: options.maxMembers }),
|
|
109
125
|
...(options.now === undefined ? {} : { now: options.now }),
|