@mark1russell7/layout-contract 0.2.8 → 0.2.9
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 -1
- package/build/index.d.ts +93 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +148 -1
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/corpus.ts +197 -0
- package/src/index.ts +1 -0
package/README.md
CHANGED
|
@@ -20,6 +20,8 @@ The package has no runtime dependencies.
|
|
|
20
20
|
| The promotion guards | `outputGroups`, `OutputGroup`, `exercised`, `ExerciseEvidence` |
|
|
21
21
|
| The portfolio | `portfolio`, `Portfolio`, `PortfolioKey`, `PortfolioLevel`, `PortfolioOptions`, `PortfolioPick`, `PortfolioTrace`, `Member`, `MemberTrace`, `MemberStatus`, `pickMoves` |
|
|
22
22
|
| The pick rule | `selectBest`, `SelectCandidate`, `SelectLevel`, `Selection`, `PickSpec` |
|
|
23
|
+
| The corpus checks | `ClaimBreak`, `checkDeclared`, `declaredCounts`, `declaredClaimOf`, `DeclaredClaim`, `Declares`, `corpusHashOf`, `CorpusEntry` |
|
|
24
|
+
| The split files | `checkSplit`, `splitFolds`, `leaveOneSeedOut`, `splitFileName`, `SPLIT_SCHEMA`, `CorpusSplit`, `SplitFold`, `SplitCorpus` |
|
|
23
25
|
| The turn | `turnBox`, `turnPort`, `turnMargin`, `turnRegion`, `turnSide`, `turnPoint` |
|
|
24
26
|
| The tolerances | `EPS`, `RECORD_EPS`, `RECORD_SCALE`, `Tolerance`, `DEFAULT_TOLERANCE` |
|
|
25
27
|
| The hard rules | `countOverlaps`, `countObstacleHits`, `regionHitsRect`, `rectInRegion`, `countOutside`, `ContainerTest`, `countPortsOffBorder`, `packHard`, `PackHard`, `placedRect`, `checkInput` |
|
|
@@ -34,6 +36,7 @@ The package has no runtime dependencies.
|
|
|
34
36
|
- **The container rule.** `in-container` counts each box that goes out of the container made smaller by `inset`. The box counts with its margin. By default, a shaped container counts as its bounding box.
|
|
35
37
|
- **The exact container.** Give `{ exactContainer: true }` to `packHard` or `countOutside`. Then a box of a shaped container with the size `fixed` must stay inside the shape. A cut corner, a notch and a hole count. A container with a free side keeps the bounding test. The default changes to the exact test at the next breaking version.
|
|
36
38
|
- **The output hash.** `outputHash` gives the first 16 hex characters of the SHA-256 of the canonical JSON of an output. Each number goes to the grid of `RECORD_EPS` first.
|
|
39
|
+
- **The corpus checks.** `checkDeclared` and `checkSplit` give a list of `ClaimBreak`. An empty list tells that each claim is true. `corpusHashOf` gives the corpus hash of `packing`.
|
|
37
40
|
- **The tolerances.** `EPS` (`1e-6`) is for the float compares in an engine. `RECORD_EPS` (`1e-3`) is for the compares on a written file. A record writes the tolerance of each hard rule in its field `tolerance`. The defaults are `overlap` `0.001` and `through` `0.5`.
|
|
38
41
|
|
|
39
42
|
## An example
|
|
@@ -53,4 +56,4 @@ const placed = applyPack(input, output);
|
|
|
53
56
|
const hard = packHard(input, output);
|
|
54
57
|
```
|
|
55
58
|
|
|
56
|
-
The formats are in `docs/FORMAT.md` of `packing` and `docs/LAYOUT-RECORDS.md` of `highways`. The joint measures are in `docs/JOINT-MEASURES.md` of this repository, and the joint corpus is in `docs/JOINT-CORPUS.md`. The promotion guards are in `docs/PROMOTION.md`. The portfolio and its pick rule are in `docs/PORTFOLIO.md`.
|
|
59
|
+
The formats are in `docs/FORMAT.md` of `packing` and `docs/LAYOUT-RECORDS.md` of `highways`. The joint measures are in `docs/JOINT-MEASURES.md` of this repository, and the joint corpus is in `docs/JOINT-CORPUS.md`. The promotion guards are in `docs/PROMOTION.md`. The portfolio and its pick rule are in `docs/PORTFOLIO.md`. The corpus checks and the split files are in `docs/CORPUS-CHECKS.md`.
|
package/build/index.d.ts
CHANGED
|
@@ -697,4 +697,97 @@ export declare function pickMoves(trace: Pick<PortfolioTrace, "picked">): {
|
|
|
697
697
|
* It also throws a `RangeError` for an empty list of members, or for two members with the same id.
|
|
698
698
|
*/
|
|
699
699
|
export declare function portfolio<I, O>(id: string, members: readonly Member<I, O>[] | ((input: I) => readonly Member<I, O>[]), key: PortfolioKey<I, O>, options?: PortfolioOptions): Portfolio<I, O>;
|
|
700
|
+
/** One broken claim of a corpus, with the ids of the inputs that break it. */
|
|
701
|
+
export interface ClaimBreak {
|
|
702
|
+
/** The name of the claim, for example `declared`, `split` or `index`. */
|
|
703
|
+
readonly claim: string;
|
|
704
|
+
/** The text of the break. */
|
|
705
|
+
readonly detail: string;
|
|
706
|
+
/** The ids of the inputs that break the claim. The list is empty when the break has no input. */
|
|
707
|
+
readonly inputs: readonly string[];
|
|
708
|
+
}
|
|
709
|
+
/** The claim `claims.declared` of a manifest: the count of the inputs for each declared property. */
|
|
710
|
+
export interface DeclaredClaim {
|
|
711
|
+
/** A property with fewer inputs than this count is thin. */
|
|
712
|
+
readonly minCount: number;
|
|
713
|
+
/** The ids of the properties with a count below `minCount`. */
|
|
714
|
+
readonly thin: readonly string[];
|
|
715
|
+
/** The count of the inputs for each property id. */
|
|
716
|
+
readonly counts: Readonly<Record<string, number>>;
|
|
717
|
+
}
|
|
718
|
+
/** The hook that gives the ids of the properties that one input declares. */
|
|
719
|
+
export type Declares<I> = (input: I) => readonly string[];
|
|
720
|
+
/**
|
|
721
|
+
* This function gives the count of the inputs for each property id. Each id of `ids` has a count, also when the count is 0.
|
|
722
|
+
* An id from `declares` that is not in `ids` comes after the ids of `ids`, in the order of the first input that declares it.
|
|
723
|
+
*/
|
|
724
|
+
export declare function declaredCounts<I>(inputs: Iterable<I>, declares: Declares<I>, ids?: readonly string[]): Record<string, number>;
|
|
725
|
+
/**
|
|
726
|
+
* This function reads the field `claims.declared` of a manifest. A manifest without it gives `undefined`.
|
|
727
|
+
* It throws an `Error` for a claim without a whole `minCount`, a list `thin` of ids and a whole count for each id.
|
|
728
|
+
*/
|
|
729
|
+
export declare function declaredClaimOf(manifest: object): DeclaredClaim | undefined;
|
|
730
|
+
/**
|
|
731
|
+
* This function checks the claim `claims.declared` against the inputs. It gives one break `declared` for each problem. An empty list tells that the claim is true.
|
|
732
|
+
*
|
|
733
|
+
* - `ids` are the property ids. The default is the ids of `claim.counts`.
|
|
734
|
+
* - Each id of `ids` has a count in `claim.counts`, and `claim.counts` has no other id. Each count is the count of the inputs.
|
|
735
|
+
* - An id with a count below `minCount` is in `thin`. Each id of `thin` is an id of `ids`.
|
|
736
|
+
* - Each id that `declares` gives is an id of `ids`.
|
|
737
|
+
*/
|
|
738
|
+
export declare function checkDeclared<I>(inputs: Iterable<I>, declares: Declares<I>, claim: DeclaredClaim, ids?: readonly string[]): ClaimBreak[];
|
|
739
|
+
/** The id and the hash of one input of a corpus. */
|
|
740
|
+
export interface CorpusEntry {
|
|
741
|
+
readonly id: string;
|
|
742
|
+
readonly hash: string;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* This function gives the hash of a corpus: the first 16 hex characters of a SHA-256. The text of the SHA-256 is `canonicalJson`
|
|
746
|
+
* of the corpus id and the `[id, hash]` of each input, in the order of the manifest. A change of one input changes the hash.
|
|
747
|
+
*/
|
|
748
|
+
export declare function corpusHashOf(corpus: string, inputs: readonly CorpusEntry[]): string;
|
|
749
|
+
/** The schema of a split file. */
|
|
750
|
+
export declare const SPLIT_SCHEMA = "corpus-split/1";
|
|
751
|
+
/** One fold of a split: the seeds that fit a selector and the seeds that score it. */
|
|
752
|
+
export interface SplitFold {
|
|
753
|
+
readonly train: readonly number[];
|
|
754
|
+
readonly heldOut: readonly number[];
|
|
755
|
+
}
|
|
756
|
+
/** A split file `corpus-split/1`. Its name is `<corpus id>.<corpus hash>.json`. It is beside the corpus, so the corpus does not change. */
|
|
757
|
+
export interface CorpusSplit {
|
|
758
|
+
readonly schema: typeof SPLIT_SCHEMA;
|
|
759
|
+
readonly corpus: string;
|
|
760
|
+
/** The hash of the corpus: `corpusHashOf` of its manifest. */
|
|
761
|
+
readonly corpusHash: string;
|
|
762
|
+
/** The splits by name. Each split has one fold or more. */
|
|
763
|
+
readonly splits: Readonly<Record<string, {
|
|
764
|
+
readonly folds: readonly SplitFold[];
|
|
765
|
+
}>>;
|
|
766
|
+
}
|
|
767
|
+
/** The fields of a manifest that the split check reads. */
|
|
768
|
+
export interface SplitCorpus {
|
|
769
|
+
readonly corpus: string;
|
|
770
|
+
readonly specs: readonly {
|
|
771
|
+
readonly seeds: readonly number[];
|
|
772
|
+
}[];
|
|
773
|
+
readonly inputs: readonly CorpusEntry[];
|
|
774
|
+
}
|
|
775
|
+
/** This function gives the name of the split file of a corpus. */
|
|
776
|
+
export declare function splitFileName(corpus: string, hash: string): string;
|
|
777
|
+
/**
|
|
778
|
+
* This function checks a split file against a manifest. It gives one break `split` for each problem. An empty list tells that the file is good.
|
|
779
|
+
*
|
|
780
|
+
* - The schema is `corpus-split/1`, the corpus is the id of the manifest and `corpusHash` is `corpusHashOf` of the manifest.
|
|
781
|
+
* - Each split has one fold or more. In each fold, `train` and `heldOut` are lists of seeds, not empty and with no common seed.
|
|
782
|
+
* - Each seed is a seed of a spec of the manifest.
|
|
783
|
+
* - With `name`, the file has the split `name`.
|
|
784
|
+
*/
|
|
785
|
+
export declare function checkSplit(split: unknown, corpus: SplitCorpus, name?: string): ClaimBreak[];
|
|
786
|
+
/**
|
|
787
|
+
* This function gives a copy of the folds of the split `name` of a split file. `where` names the file in the text of an error.
|
|
788
|
+
* It throws an `Error` for each problem of `checkSplit`, and then for an unknown split name.
|
|
789
|
+
*/
|
|
790
|
+
export declare function splitFolds(split: unknown, corpus: SplitCorpus, name: string, where?: string): SplitFold[];
|
|
791
|
+
/** This function gives the folds that hold out one seed each, in the order of the seeds. Each fold trains on the other seeds. */
|
|
792
|
+
export declare function leaveOneSeedOut(seeds: readonly number[]): SplitFold[];
|
|
700
793
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/geometry.ts","../src/tolerance.ts","../src/input.ts","../src/output.ts","../src/record.ts","../src/rules.ts","../src/turn.ts","../src/measures.ts","../src/strategy.ts","../src/random.ts","../src/edges.ts","../src/hash.ts","../src/portfolio.ts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/geometry.ts","../src/tolerance.ts","../src/input.ts","../src/output.ts","../src/record.ts","../src/rules.ts","../src/turn.ts","../src/measures.ts","../src/strategy.ts","../src/random.ts","../src/edges.ts","../src/hash.ts","../src/portfolio.ts","../src/corpus.ts"],"mappings":"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"}
|
package/build/index.js
CHANGED
|
@@ -1393,6 +1393,153 @@ function portfolio(id, members, key, options = {}) {
|
|
|
1393
1393
|
run: (input) => pick(input).output
|
|
1394
1394
|
};
|
|
1395
1395
|
}
|
|
1396
|
-
|
|
1396
|
+
// src/corpus.ts
|
|
1397
|
+
/**
|
|
1398
|
+
* This function gives the count of the inputs for each property id. Each id of `ids` has a count, also when the count is 0.
|
|
1399
|
+
* An id from `declares` that is not in `ids` comes after the ids of `ids`, in the order of the first input that declares it.
|
|
1400
|
+
*/
|
|
1401
|
+
function declaredCounts(inputs, declares, ids = []) {
|
|
1402
|
+
const out = Object.fromEntries(ids.map((id) => [id, 0]));
|
|
1403
|
+
for (const input of inputs) for (const id of declares(input)) out[id] = (out[id] ?? 0) + 1;
|
|
1404
|
+
return out;
|
|
1405
|
+
}
|
|
1406
|
+
/** This function tells if a value is a plain object. */
|
|
1407
|
+
const isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1408
|
+
/**
|
|
1409
|
+
* This function reads the field `claims.declared` of a manifest. A manifest without it gives `undefined`.
|
|
1410
|
+
* It throws an `Error` for a claim without a whole `minCount`, a list `thin` of ids and a whole count for each id.
|
|
1411
|
+
*/
|
|
1412
|
+
function declaredClaimOf(manifest) {
|
|
1413
|
+
const claims = manifest["claims"];
|
|
1414
|
+
if (claims === void 0) return void 0;
|
|
1415
|
+
if (!isObject(claims)) throw new Error("The field claims of a corpus file is an object.");
|
|
1416
|
+
const declared = claims["declared"];
|
|
1417
|
+
if (declared === void 0) return void 0;
|
|
1418
|
+
if (!isObject(declared)) throw new Error("The field claims.declared of a corpus file is an object.");
|
|
1419
|
+
const { minCount, thin, counts } = declared;
|
|
1420
|
+
if (!Number.isInteger(minCount) || minCount < 0) throw new Error("The field claims.declared.minCount is a whole number of 0 or more.");
|
|
1421
|
+
if (!Array.isArray(thin) || !thin.every((id) => typeof id === "string")) throw new Error("The field claims.declared.thin is a list of property ids.");
|
|
1422
|
+
if (!isObject(counts) || !Object.values(counts).every((n) => Number.isInteger(n) && n >= 0)) throw new Error("The field claims.declared.counts gives a whole count for each property id.");
|
|
1423
|
+
return {
|
|
1424
|
+
minCount,
|
|
1425
|
+
thin: [...thin],
|
|
1426
|
+
counts: { ...counts }
|
|
1427
|
+
};
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* This function checks the claim `claims.declared` against the inputs. It gives one break `declared` for each problem. An empty list tells that the claim is true.
|
|
1431
|
+
*
|
|
1432
|
+
* - `ids` are the property ids. The default is the ids of `claim.counts`.
|
|
1433
|
+
* - Each id of `ids` has a count in `claim.counts`, and `claim.counts` has no other id. Each count is the count of the inputs.
|
|
1434
|
+
* - An id with a count below `minCount` is in `thin`. Each id of `thin` is an id of `ids`.
|
|
1435
|
+
* - Each id that `declares` gives is an id of `ids`.
|
|
1436
|
+
*/
|
|
1437
|
+
function checkDeclared(inputs, declares, claim, ids = Object.keys(claim.counts)) {
|
|
1438
|
+
const computed = declaredCounts(inputs, declares, ids);
|
|
1439
|
+
const out = [];
|
|
1440
|
+
for (const id of ids) if (!(id in claim.counts)) out.push(`the property "${id}" has no count`);
|
|
1441
|
+
else if (claim.counts[id] !== computed[id]) out.push(`the property "${id}" has the count ${claim.counts[id]}, but the inputs give ${computed[id]}`);
|
|
1442
|
+
for (const id of Object.keys(claim.counts)) if (!ids.includes(id)) out.push(`"${id}" is not a declared property`);
|
|
1443
|
+
for (const id of ids) if ((computed[id] ?? 0) < claim.minCount && !claim.thin.includes(id)) out.push(`the property "${id}" has ${computed[id]} inputs, below minCount ${claim.minCount}, and it is not in thin`);
|
|
1444
|
+
for (const id of claim.thin) if (!ids.includes(id)) out.push(`"${id}" of thin is not a declared property`);
|
|
1445
|
+
for (const id of Object.keys(computed)) if (!ids.includes(id)) out.push(`${computed[id]} inputs declare "${id}", which is not a declared property`);
|
|
1446
|
+
return out.map((detail) => ({
|
|
1447
|
+
claim: "declared",
|
|
1448
|
+
detail,
|
|
1449
|
+
inputs: []
|
|
1450
|
+
}));
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* This function gives the hash of a corpus: the first 16 hex characters of a SHA-256. The text of the SHA-256 is `canonicalJson`
|
|
1454
|
+
* of the corpus id and the `[id, hash]` of each input, in the order of the manifest. A change of one input changes the hash.
|
|
1455
|
+
*/
|
|
1456
|
+
function corpusHashOf(corpus, inputs) {
|
|
1457
|
+
return sha256Hex(canonicalJson({
|
|
1458
|
+
corpus,
|
|
1459
|
+
inputs: inputs.map((i) => [i.id, i.hash])
|
|
1460
|
+
})).slice(0, 16);
|
|
1461
|
+
}
|
|
1462
|
+
/** The schema of a split file. */
|
|
1463
|
+
const SPLIT_SCHEMA = "corpus-split/1";
|
|
1464
|
+
/** This function gives the name of the split file of a corpus. */
|
|
1465
|
+
function splitFileName(corpus, hash) {
|
|
1466
|
+
return `${corpus}.${hash}.json`;
|
|
1467
|
+
}
|
|
1468
|
+
/** This function tells if a value is a list of whole numbers. */
|
|
1469
|
+
const isSeeds = (value) => Array.isArray(value) && value.every((s) => Number.isInteger(s));
|
|
1470
|
+
/**
|
|
1471
|
+
* This function checks a split file against a manifest. It gives one break `split` for each problem. An empty list tells that the file is good.
|
|
1472
|
+
*
|
|
1473
|
+
* - The schema is `corpus-split/1`, the corpus is the id of the manifest and `corpusHash` is `corpusHashOf` of the manifest.
|
|
1474
|
+
* - Each split has one fold or more. In each fold, `train` and `heldOut` are lists of seeds, not empty and with no common seed.
|
|
1475
|
+
* - Each seed is a seed of a spec of the manifest.
|
|
1476
|
+
* - With `name`, the file has the split `name`.
|
|
1477
|
+
*/
|
|
1478
|
+
function checkSplit(split, corpus, name) {
|
|
1479
|
+
const out = [];
|
|
1480
|
+
const done = () => out.map((detail) => ({
|
|
1481
|
+
claim: "split",
|
|
1482
|
+
detail,
|
|
1483
|
+
inputs: []
|
|
1484
|
+
}));
|
|
1485
|
+
const f = split;
|
|
1486
|
+
if (f === null || typeof f !== "object") {
|
|
1487
|
+
out.push("the split file is not an object");
|
|
1488
|
+
return done();
|
|
1489
|
+
}
|
|
1490
|
+
if (f.schema !== "corpus-split/1") out.push(`the schema is ${String(f.schema)}, not ${SPLIT_SCHEMA}`);
|
|
1491
|
+
if (f.corpus !== corpus.corpus) out.push(`the corpus is ${String(f.corpus)}, not ${corpus.corpus}`);
|
|
1492
|
+
const hash = corpusHashOf(corpus.corpus, corpus.inputs);
|
|
1493
|
+
if (f.corpusHash !== hash) out.push(`the corpusHash is ${String(f.corpusHash)}, but the corpus gives ${hash}`);
|
|
1494
|
+
const seeds = new Set(corpus.specs.flatMap((s) => s.seeds));
|
|
1495
|
+
if (f.splits === null || typeof f.splits !== "object") {
|
|
1496
|
+
out.push("the field splits is not an object");
|
|
1497
|
+
return done();
|
|
1498
|
+
}
|
|
1499
|
+
for (const [key, value] of Object.entries(f.splits)) {
|
|
1500
|
+
const folds = value?.folds;
|
|
1501
|
+
if (!Array.isArray(folds) || folds.length === 0) {
|
|
1502
|
+
out.push(`the split ${key} has no folds`);
|
|
1503
|
+
continue;
|
|
1504
|
+
}
|
|
1505
|
+
folds.forEach((fold, k) => {
|
|
1506
|
+
const at = `the fold ${k} of the split ${key}`;
|
|
1507
|
+
const { train, heldOut } = fold ?? {};
|
|
1508
|
+
if (!isSeeds(train) || train.length === 0) out.push(`${at} has no train seeds`);
|
|
1509
|
+
if (!isSeeds(heldOut) || heldOut.length === 0) out.push(`${at} has no heldOut seeds`);
|
|
1510
|
+
if (!isSeeds(train) || !isSeeds(heldOut)) return;
|
|
1511
|
+
const common = train.filter((s) => heldOut.includes(s));
|
|
1512
|
+
if (common.length > 0) out.push(`${at} has the seeds ${common.join(", ")} in train and in heldOut`);
|
|
1513
|
+
const unknown = [...train, ...heldOut].filter((s) => !seeds.has(s));
|
|
1514
|
+
if (unknown.length > 0) out.push(`${at} has the seeds ${unknown.join(", ")}, which are not in the corpus`);
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
if (name !== void 0 && !Object.hasOwn(f.splits, name)) out.push(`the split file has no split ${name}. Its splits are ${Object.keys(f.splits).join(", ")}`);
|
|
1518
|
+
return done();
|
|
1519
|
+
}
|
|
1520
|
+
/**
|
|
1521
|
+
* This function gives a copy of the folds of the split `name` of a split file. `where` names the file in the text of an error.
|
|
1522
|
+
* It throws an `Error` for each problem of `checkSplit`, and then for an unknown split name.
|
|
1523
|
+
*/
|
|
1524
|
+
function splitFolds(split, corpus, name, where = "The split file") {
|
|
1525
|
+
const breaks = checkSplit(split, corpus);
|
|
1526
|
+
if (breaks.length > 0) throw new Error(`${where} is not good: ${breaks.map((b) => b.detail).join("; ")}.`);
|
|
1527
|
+
const splits = split.splits;
|
|
1528
|
+
const found = Object.hasOwn(splits, name) ? splits[name] : void 0;
|
|
1529
|
+
if (found === void 0) throw new Error(`${where} has no split ${name}. Its splits are ${Object.keys(splits).join(", ")}.`);
|
|
1530
|
+
return found.folds.map((f) => ({
|
|
1531
|
+
train: [...f.train],
|
|
1532
|
+
heldOut: [...f.heldOut]
|
|
1533
|
+
}));
|
|
1534
|
+
}
|
|
1535
|
+
/** This function gives the folds that hold out one seed each, in the order of the seeds. Each fold trains on the other seeds. */
|
|
1536
|
+
function leaveOneSeedOut(seeds) {
|
|
1537
|
+
const sorted = [...new Set(seeds)].sort((a, b) => a - b);
|
|
1538
|
+
return sorted.map((s) => ({
|
|
1539
|
+
train: sorted.filter((t) => t !== s),
|
|
1540
|
+
heldOut: [s]
|
|
1541
|
+
}));
|
|
1542
|
+
}
|
|
1543
|
+
export { DEFAULT_TOLERANCE, EDGE_DENSITY, EDGE_STEP_VERSION, EPS, JOINT_MEASURES, JOINT_MOVED_MIN, RECORD_EPS, RECORD_SCALE, SIDES, SPLIT_SCHEMA, applyPack, boundsOf, canonicalJson, checkDeclared, checkInput, checkSplit, compareMeasure, corpusHashOf, countObstacleHits, countOutside, countOverlaps, countPortsOffBorder, declaredClaimOf, declaredCounts, documentHash, edgeStep, exercised, fnv1a32, grow, leaveOneSeedOut, marginSides, minEffectOf, mulberry32, outputGroups, outputHash, overlapOf, packHard, pickMoves, placedRect, portfolio, randomInt, rectInRegion, regionHitsRect, selectBest, sha256Hex, splitFileName, splitFolds, stepRandom, toLayoutRecord, toPackInput, translate, turnBox, turnMargin, turnPoint, turnPort, turnRegion, turnSide };
|
|
1397
1544
|
|
|
1398
1545
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/geometry.ts","../src/tolerance.ts","../src/input.ts","../src/turn.ts","../src/output.ts","../src/record.ts","../src/rules.ts","../src/measures.ts","../src/utf8.ts","../src/random.ts","../src/edges.ts","../src/hash.ts","../src/portfolio.ts"],"sourcesContent":["/** A side of a box. The y axis points down, so `top` has the smallest y. */\nexport type Side = \"top\" | \"right\" | \"bottom\" | \"left\";\n\n/** The sides in clockwise order, from the top. */\nexport const SIDES: readonly Side[] = [\"top\", \"right\", \"bottom\", \"left\"];\n\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/** A rectangle: its top-left corner and its size. */\nexport interface Rect {\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n}\n\n/** A value for each side of a box. */\nexport interface Sides {\n readonly top: number;\n readonly right: number;\n readonly bottom: number;\n readonly left: number;\n}\n\n/**\n * A region. The forms and the rules are those of `docs/FORMAT.md` of `packing`.\n * A ring of a polygon closes without a copy of its first point.\n */\nexport type Region =\n | { readonly kind: \"rect\"; readonly x: number; readonly y: number; readonly w: number; readonly h: number }\n | {\n readonly kind: \"polygon\";\n readonly points: readonly (readonly [number, number])[];\n readonly holes?: readonly (readonly (readonly [number, number])[])[];\n }\n | { readonly kind: \"circle\"; readonly cx: number; readonly cy: number; readonly r: number }\n | { readonly kind: \"ellipse\"; readonly cx: number; readonly cy: number; readonly rx: number; readonly ry: number };\n\n/** A margin: one value for the four sides, or one value for each side. */\nexport type Margin = number | Sides;\n\n/** This function gives the value of each side of a margin. No margin gives 0 on each side. */\nexport function marginSides(margin: Margin | undefined): Sides {\n if (margin === undefined) return { top: 0, right: 0, bottom: 0, left: 0 };\n if (typeof margin === \"number\") return { top: margin, right: margin, bottom: margin, left: margin };\n return margin;\n}\n\n/** This function gives the rectangle made larger by the margin on each side. */\nexport function grow(rect: Rect, margin: Margin | undefined): Rect {\n const m = marginSides(margin);\n return { x: rect.x - m.left, y: rect.y - m.top, w: rect.w + m.left + m.right, h: rect.h + m.top + m.bottom };\n}\n\n/** This function gives the bounding box of a region. */\nexport function boundsOf(region: Region): Rect {\n switch (region.kind) {\n case \"rect\":\n return { x: region.x, y: region.y, w: region.w, h: region.h };\n case \"circle\":\n return { x: region.cx - region.r, y: region.cy - region.r, w: 2 * region.r, h: 2 * region.r };\n case \"ellipse\":\n return { x: region.cx - region.rx, y: region.cy - region.ry, w: 2 * region.rx, h: 2 * region.ry };\n case \"polygon\": {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const [x, y] of region.points) {\n x0 = Math.min(x0, x);\n y0 = Math.min(y0, y);\n x1 = Math.max(x1, x);\n y1 = Math.max(y1, y);\n }\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n }\n }\n}\n\n/** This function gives the region moved by `dx` and `dy`. */\nexport function translate(region: Region, dx: number, dy: number): Region {\n switch (region.kind) {\n case \"rect\":\n return { ...region, x: region.x + dx, y: region.y + dy };\n case \"circle\":\n case \"ellipse\":\n return { ...region, cx: region.cx + dx, cy: region.cy + dy };\n case \"polygon\": {\n const move = (ring: readonly (readonly [number, number])[]): [number, number][] => ring.map(([x, y]) => [x + dx, y + dy]);\n return region.holes === undefined\n ? { kind: \"polygon\", points: move(region.points) }\n : { kind: \"polygon\", points: move(region.points), holes: region.holes.map(move) };\n }\n }\n}\n\n/**\n * This function gives the overlap of the insides of two rectangles on each axis.\n * A value of 0 or less on an axis is no overlap. Two rectangles with a common edge have an overlap of 0.\n */\nexport function overlapOf(a: Rect, b: Rect): { readonly x: number; readonly y: number } {\n return {\n x: Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x),\n y: Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y),\n };\n}\n","/** The epsilon for the float compares in an engine. */\nexport const EPS = 1e-6;\n\n/**\n * The count of grid steps in one unit of a written file. A file rounds each number `v` to `Math.round(v * RECORD_SCALE) / RECORD_SCALE`.\n * Use a multiplication by this value, not a division by `RECORD_EPS`. The two differ at some half steps.\n */\nexport const RECORD_SCALE = 1000;\n\n/**\n * The epsilon for the float compares on a written file. A file rounds each number to 3 decimals,\n * so a difference of two values can move by up to 0.001. It is `1 / RECORD_SCALE`.\n */\nexport const RECORD_EPS = 1e-3;\n\n/**\n * The tolerance of each hard rule, in layout units. A record writes the tolerance that its run used,\n * in its field `tolerance`, next to `hard`.\n */\nexport interface Tolerance {\n /** Two boxes with their margins break `no-overlap` when their insides overlap by more than this on each axis. */\n readonly overlap: number;\n /** A route breaks `no-pass-through` when a part longer than this is inside a box made this much smaller. */\n readonly through: number;\n}\n\n/**\n * The default tolerance of each rule. The packer is exact, so `overlap` is one unit of the rounding.\n * Routes are sampled curves that follow the margin line, so `through` is larger.\n */\nexport const DEFAULT_TOLERANCE: Tolerance = Object.freeze({ overlap: 0.001, through: 0.5 });\n","import type { Margin, Region, Side } from \"./geometry.ts\";\n\n/**\n * A port of a box: a place where edges go into the box.\n * With `x` and `y`, the port is fixed on the border of the box, relative to its top-left corner.\n * Without them, the router places the port on its `side`. Without a side, the router picks the side.\n */\nexport interface Port {\n readonly id: string;\n readonly side?: Side;\n readonly x?: number;\n readonly y?: number;\n}\n\n/** A box of an input. In the packer, its name is item. */\nexport interface LayoutBox {\n readonly id: string;\n readonly w: number;\n readonly h: number;\n /** The packer writes the position. The router reads it. */\n readonly x?: number;\n readonly y?: number;\n /** A locked box keeps `x` and `y`. The packer reads it as an obstacle. */\n readonly locked?: boolean;\n /** The reading order. Without it, the order of the array is the rank. */\n readonly rank?: number;\n readonly parent?: string;\n readonly group?: string;\n /** A region relative to the origin of the box. Without it, the box is the rectangle `w` by `h`. */\n readonly shape?: Region;\n readonly ports?: readonly Port[];\n /** A ring around the box. No other box enters it. Only a route from a port of the box enters it, at a right angle. */\n readonly margin?: Margin;\n /** The packer can turn the box by 90 degrees. The output has the turned box and ports. */\n readonly turnable?: boolean;\n /** The free data of the node. The grouping rule `keys` of `highways` reads `data.group`. */\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** The packer name of a box. It is the same type. */\nexport type Item = LayoutBox;\n\n/** An edge between two boxes, with optional ports. */\nexport interface LayoutEdge {\n readonly id: string;\n readonly source: string;\n readonly target: string;\n readonly sourcePort?: string;\n readonly targetPort?: string;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** The container. `fixed` tells which sides of the size stay. */\nexport interface LayoutContainer {\n readonly w?: number;\n readonly h?: number;\n readonly fixed: \"size\" | \"width\" | \"height\" | \"none\";\n /** The target aspect: the width divided by the height. The default is 1. */\n readonly aspect?: number;\n /** The weight of the aspect error in the objective. 0 gives the least area. The default is 1. */\n readonly aspectWeight?: number;\n /** The shape. Without it, the container is the rectangle from 0, 0 to `w`, `h`. */\n readonly shape?: Region;\n /** The space between the border and the boxes with their margins. */\n readonly inset?: number;\n}\n\n/** An area that boxes and routes avoid. Without `move`, it stays. With `move`, the packer can move it for `cost` times the distance. */\nexport interface Obstacle {\n readonly id: string;\n readonly region: Region;\n readonly move?: { readonly cost: number };\n}\n\n/** The generator of an input. The same name, version, parameters and seed give the same file, byte for byte. */\nexport interface LayoutGenerator {\n readonly name: string;\n readonly version: number;\n readonly params: Readonly<Record<string, unknown>>;\n readonly seed: number;\n}\n\n/** The cell of an input in the taxonomy: one value for each dimension. The dimensions are in `docs/FORMAT.md` of `packing`. */\nexport interface LayoutCell {\n readonly containerSize?: \"fixed\" | \"freeHeight\" | \"freeWidth\" | \"freeAspect\" | \"freeArea\";\n readonly containerShape?: \"rect\" | \"convex\" | \"polygon\" | \"circle\" | \"ellipse\" | \"holes\";\n readonly obstacles?: \"none\" | \"center\" | \"scattered\" | \"wall\" | \"corridors\" | \"touching\" | \"edge\";\n readonly sizes?: \"identical\" | \"uniform\" | \"heavyTail\" | \"bimodal\" | \"extremeAspect\" | \"nearIdentical\";\n readonly count?: \"1\" | \"10\" | \"100\" | \"1k\" | \"10k\";\n readonly mode?: \"offline\" | \"online\" | \"incremental\";\n readonly edgeDensity?: \"sparse\" | \"medium\" | \"dense\";\n readonly edgeShape?: \"random\" | \"clustered\" | \"hubChain\" | \"longRange\" | \"tree\" | \"bundled\";\n readonly groups?: \"none\" | \"flat\" | \"nested\";\n readonly ports?: \"free\" | \"sides\" | \"fixed\";\n}\n\n/** An input of the corpus: the format `layout-input/1`. */\nexport interface LayoutInput {\n readonly schema: \"layout-input/1\";\n readonly id: string;\n readonly set?: string;\n readonly family?: string;\n readonly seed?: number;\n /** The origin: `made-up`, `published:<set>` or `known-best:<construction>`. */\n readonly source?: string;\n /** The first 16 hex characters of the SHA-256 of the canonical file without this field. */\n readonly hash?: string;\n /** The generator of the input. `null` or no value tells that a person made the input. */\n readonly generator?: LayoutGenerator | null;\n /** The steps that changed the input after its generator, in their order. `edgeStep` adds one. */\n readonly steps?: readonly LayoutGenerator[];\n readonly cell?: LayoutCell;\n /** The place of the input in a sequence of changes. */\n readonly step?: number;\n /** A router input can have no container. */\n readonly container?: LayoutContainer;\n /** The free space between two boxes with their margins. Routes use it. */\n readonly gap?: number;\n readonly boxes: readonly LayoutBox[];\n readonly edges?: readonly LayoutEdge[];\n readonly obstacles?: readonly Obstacle[];\n /**\n * A variant names its base input and its change.\n * With `packed`, the variant is the packed output of its base input: the router routes the positions of that pack.\n */\n readonly base?: string;\n readonly change?: \"add\" | \"remove\" | \"resize\" | \"reorder\" | \"packed\";\n}\n\n/** The input of a packer: a `layout-input/1` file without the edges. */\nexport interface PackInput {\n readonly container: LayoutContainer;\n readonly items: readonly Item[];\n readonly obstacles?: readonly Obstacle[];\n readonly gap?: number;\n}\n\n/** This function gives the packer input of a file. An input without a container gets `{ fixed: \"none\" }`, so the packer picks the size. */\nexport function toPackInput(input: LayoutInput): PackInput {\n return {\n container: input.container ?? { fixed: \"none\" },\n items: input.boxes,\n ...(input.obstacles === undefined ? {} : { obstacles: input.obstacles }),\n ...(input.gap === undefined ? {} : { gap: input.gap }),\n };\n}\n","import { SIDES, marginSides, type Margin, type Region, type Side } from \"./geometry.ts\";\nimport type { LayoutBox, Port } from \"./input.ts\";\n\n/*\n * The turn: 90 degrees clockwise, with the y axis down. The turned box has `w` and `h` swapped,\n * and its top-left corner stays at the position of the box. A point (px, py) of a box of height h\n * goes to (h - py, px). Thus the top-left corner goes to the top-right corner, and each side moves\n * one step clockwise: top to right, right to bottom, bottom to left, left to top.\n */\n\n/** This function gives the side after a turn of 90 degrees clockwise. */\nexport function turnSide(side: Side): Side {\n return SIDES[(SIDES.indexOf(side) + 1) % 4]!;\n}\n\n/** This function gives a point of a box of height `h` after the turn. */\nexport function turnPoint(x: number, y: number, h: number): [number, number] {\n return [h - y, x];\n}\n\n/** This function gives a port of a box of height `h` after the turn. Each value of the port turns, also a port with only `x` or only `y`. */\nexport function turnPort(port: Port, h: number): Port {\n const { side, x, y, ...rest } = port;\n return {\n ...rest,\n ...(side === undefined ? {} : { side: turnSide(side) }),\n ...(y === undefined ? {} : { x: h - y }),\n ...(x === undefined ? {} : { y: x }),\n };\n}\n\n/** This function gives a margin after the turn: the value of each side moves one side clockwise. */\nexport function turnMargin(margin: Margin): Margin {\n if (typeof margin === \"number\") return margin;\n const m = marginSides(margin);\n return { top: m.left, right: m.top, bottom: m.right, left: m.bottom };\n}\n\n/** This function gives a region relative to the origin of a box of height `h` after the turn. */\nexport function turnRegion(region: Region, h: number): Region {\n switch (region.kind) {\n case \"rect\":\n return { kind: \"rect\", x: h - region.y - region.h, y: region.x, w: region.h, h: region.w };\n case \"circle\":\n return { ...region, cx: h - region.cy, cy: region.cx };\n case \"ellipse\":\n return { kind: \"ellipse\", cx: h - region.cy, cy: region.cx, rx: region.ry, ry: region.rx };\n case \"polygon\": {\n const turn = (ring: readonly (readonly [number, number])[]): [number, number][] => ring.map(([x, y]) => turnPoint(x, y, h));\n return region.holes === undefined\n ? { kind: \"polygon\", points: turn(region.points) }\n : { kind: \"polygon\", points: turn(region.points), holes: region.holes.map(turn) };\n }\n }\n}\n\n/** This function gives a box after the turn: the size, the ports, the margin and the shape turn. The position stays. */\nexport function turnBox(box: LayoutBox): LayoutBox {\n return {\n ...box,\n w: box.h,\n h: box.w,\n ...(box.ports === undefined ? {} : { ports: box.ports.map((p) => turnPort(p, box.h)) }),\n ...(box.margin === undefined ? {} : { margin: turnMargin(box.margin) }),\n ...(box.shape === undefined ? {} : { shape: turnRegion(box.shape, box.h) }),\n };\n}\n","import { boundsOf, translate } from \"./geometry.ts\";\nimport type { LayoutInput } from \"./input.ts\";\nimport { turnBox } from \"./turn.ts\";\n\n/** The position of one item. `turn` is 90 when the packer turned a turnable item. */\nexport interface Placement {\n readonly id: string;\n readonly x: number;\n readonly y: number;\n readonly turn?: 0 | 90;\n}\n\n/** The facts of one stage of a strategy, for the records and the site. */\nexport interface StageTrace {\n readonly id: string;\n readonly ms?: number;\n readonly measures?: Readonly<Record<string, number>>;\n}\n\n/** The output of a packer. It does not change the input. */\nexport interface PackOutput {\n readonly placements: readonly Placement[];\n /** The ids of the items that the packer did not place. */\n readonly overflow: readonly string[];\n /** The size of the container after the pack. For a free size, the size that the search found. */\n readonly size: { readonly w: number; readonly h: number };\n /** The new top-left corner of the bounding box of each obstacle that moved. */\n readonly moved: readonly { readonly id: string; readonly x: number; readonly y: number }[];\n readonly trace?: readonly StageTrace[];\n}\n\n/**\n * This function gives the input with the output of a packer applied. Each placed box gets its position.\n * A turned box gets its turned size, ports, margin and shape. Each moved obstacle moves.\n * The container gets the size of the output. The router reads this result. It does not read `turn`.\n */\nexport function applyPack(input: LayoutInput, output: PackOutput): LayoutInput {\n const at = new Map(output.placements.map((p) => [p.id, p]));\n const moved = new Map(output.moved.map((m) => [m.id, m]));\n const boxes = input.boxes.map((box) => {\n const p = at.get(box.id);\n if (p === undefined) return box;\n const turned = p.turn === 90 ? turnBox(box) : box;\n return { ...turned, x: p.x, y: p.y };\n });\n const obstacles = input.obstacles?.map((o) => {\n const m = moved.get(o.id);\n if (m === undefined) return o;\n const b = boundsOf(o.region);\n return { ...o, region: translate(o.region, m.x - b.x, m.y - b.y) };\n });\n return {\n ...input,\n container: { ...(input.container ?? { fixed: \"none\" }), w: output.size.w, h: output.size.h },\n boxes,\n ...(obstacles === undefined ? {} : { obstacles }),\n };\n}\n","import type { Tolerance } from \"./tolerance.ts\";\nimport type { LayoutInput } from \"./input.ts\";\n\n/** The stage of a record: the packer, the router, or both together. */\nexport type Stage = \"pack\" | \"route\" | \"joint\";\n\n/** One run of one strategy on one input and seed: the format `layout-record/1`. A run writes one line of JSON Lines. */\nexport interface LayoutRecord {\n readonly schema: \"layout-record/1\";\n readonly stage: Stage;\n readonly step: string;\n readonly strategy: string;\n /** The options in full, with the defaults. */\n readonly options: Readonly<Record<string, unknown>>;\n readonly corpus: string;\n /** The id of the input. */\n readonly input: string;\n /** The `hash` of the input file. */\n readonly inputHash: string;\n readonly set: string;\n readonly seed: number;\n readonly nodes: number;\n readonly edges: number;\n /** The value of each measure, by its name: `pack.*`, `route.*` or `joint.*`. */\n readonly measures: Readonly<Record<string, number>>;\n /** The count of the breaks of each hard rule. A good run has 0 for each rule. */\n readonly hard: Readonly<Record<string, number>>;\n /** The tolerance of each hard rule of the run. */\n readonly tolerance?: Readonly<Partial<Tolerance>>;\n /** `true` when two runs with the same seed give the same positions. */\n readonly deterministic: boolean;\n /** The id of the prediction that was written before the run. */\n readonly prediction?: string;\n /** The median of `msRuns`, or the time of the one run. */\n readonly ms: number;\n /** The time of each timed repeat, in milliseconds. */\n readonly msRuns?: readonly number[];\n /**\n * The first 16 hex characters of the SHA-256 of the canonical output of the stage.\n * The packer hashes its placements by the order of the ids. The router hashes its routes by the order of the edge ids.\n */\n readonly outputHash?: string;\n /** The facts of the computer of the run. */\n readonly env?: RunEnv;\n /** The reason when the strategy did not run, for example an input over its `maxNodes`. Then the record has no measures. */\n readonly skipped?: string;\n readonly commit?: string;\n}\n\n/**\n * The values that a strategy supports, for each dimension of a taxonomy.\n * The dimension names are in `docs/FORMAT.md` of `packing` and `docs/LAYOUT-RECORDS.md` of `highways`.\n */\nexport type Supports = Readonly<Record<string, readonly string[]>>;\n\n/** The facts of the computer of a run. */\nexport interface RunEnv {\n readonly node: string;\n readonly os: string;\n readonly arch: string;\n /** The name of the runner, for example `ubuntu-latest` or `local`. */\n readonly runner: string;\n /** The model of the processor. */\n readonly cpu: string;\n /** The count of the logical processors. */\n readonly cpus: number;\n}\n\n/** The facts of a run that the input does not give. */\nexport type RunFacts = Omit<LayoutRecord, \"schema\" | \"input\" | \"inputHash\" | \"set\" | \"nodes\" | \"edges\">;\n\n/** This function gives the record of a run. The input gives its id, its hash, its set and the counts of the nodes and the edges. */\nexport function toLayoutRecord(input: LayoutInput, run: RunFacts): LayoutRecord {\n return {\n schema: \"layout-record/1\",\n ...run,\n input: input.id,\n inputHash: input.hash ?? \"\",\n set: input.set ?? \"\",\n nodes: input.boxes.length,\n edges: input.edges?.length ?? 0,\n };\n}\n","import { boundsOf, grow, overlapOf, type Rect, type Region } from \"./geometry.ts\";\nimport type { LayoutBox, LayoutInput, Obstacle } from \"./input.ts\";\nimport { applyPack, type PackOutput } from \"./output.ts\";\nimport { DEFAULT_TOLERANCE, EPS, RECORD_EPS } from \"./tolerance.ts\";\n\n/** This function gives the area of a placed box: its shape or its rectangle, at its position. A box without a position gives `undefined`. */\nexport function placedRect(box: LayoutBox): Rect | undefined {\n if (box.x === undefined || box.y === undefined) return undefined;\n if (box.shape === undefined) return { x: box.x, y: box.y, w: box.w, h: box.h };\n const b = boundsOf(box.shape);\n return { x: box.x + b.x, y: box.y + b.y, w: b.w, h: b.h };\n}\n\n/**\n * This function counts the pairs of placed boxes whose insides, with their margins, overlap by more than `tolerance` on each axis.\n * A box with a shape counts as its bounding box. That area is larger, thus the count is safe.\n */\nexport function countOverlaps(boxes: readonly LayoutBox[], tolerance: number = DEFAULT_TOLERANCE.overlap): number {\n const rects: Rect[] = [];\n for (const box of boxes) {\n const r = placedRect(box);\n if (r !== undefined) rects.push(grow(r, box.margin));\n }\n rects.sort((a, b) => a.x - b.x);\n let count = 0;\n for (let i = 0; i < rects.length; i++) {\n const a = rects[i]!;\n for (let j = i + 1; j < rects.length; j++) {\n const b = rects[j]!;\n if (b.x >= a.x + a.w - tolerance) break;\n const o = overlapOf(a, b);\n if (o.x > tolerance && o.y > tolerance) count++;\n }\n }\n return count;\n}\n\n/** The options of the container test of `countOutside` and `packHard`. */\nexport interface ContainerTest {\n /**\n * With `true`, a box of a shaped container with the size `fixed` must stay inside the shape, not only inside its bounding box.\n * The default is `false`. The default changes to `true` at the next breaking version.\n */\n readonly exactContainer?: boolean;\n}\n\n/**\n * This function counts the placed boxes that go out of the container.\n * Each box with its margin must stay inside the container made smaller by `inset`. Only the fixed sides of the size count. A shaped container counts as its bounding box.\n *\n * With `exactContainer`, a box of a shaped container with the size `fixed` also counts when `rectInRegion` tells that it is not inside the shape.\n * For that test, the box grows by `inset` and becomes smaller by `tolerance` on each side. A shaped container with a free side keeps the bounding test only.\n * An input without a container gives 0.\n */\nexport function countOutside(input: LayoutInput, tolerance: number = DEFAULT_TOLERANCE.overlap, options: ContainerTest = {}): number {\n const c = input.container;\n if (c === undefined) return 0;\n const shape = options.exactContainer === true && c.fixed === \"size\" ? c.shape : undefined;\n const area = c.shape === undefined ? { x: 0, y: 0, w: c.w ?? Infinity, h: c.h ?? Infinity } : boundsOf(c.shape);\n const inset = c.inset ?? 0;\n const fixW = c.fixed === \"size\" || c.fixed === \"width\";\n const fixH = c.fixed === \"size\" || c.fixed === \"height\";\n let count = 0;\n for (const box of input.boxes) {\n const r0 = placedRect(box);\n if (r0 === undefined) continue;\n const r = grow(r0, box.margin);\n const outX = r.x < area.x + inset - tolerance || r.x + r.w > area.x + area.w - inset + tolerance;\n const outY = r.y < area.y + inset - tolerance || r.y + r.h > area.y + area.h - inset + tolerance;\n if ((fixW && outX) || (fixH && outY)) count++;\n else if (shape !== undefined && !rectInRegion(shape, shrink(grow(r, inset), tolerance))) count++;\n }\n return count;\n}\n\n/** This function counts the fixed ports that are not on the border of their box, with the epsilon of a written file. A port without a side does not count. */\nexport function countPortsOffBorder(boxes: readonly LayoutBox[], eps: number = RECORD_EPS): number {\n let count = 0;\n for (const box of boxes) {\n for (const p of box.ports ?? []) {\n if (p.x === undefined || p.y === undefined || p.side === undefined) continue;\n const along = p.side === \"top\" || p.side === \"bottom\" ? p.x : p.y;\n const length = p.side === \"top\" || p.side === \"bottom\" ? box.w : box.h;\n const across = { top: p.y, bottom: p.y - box.h, left: p.x, right: p.x - box.w }[p.side];\n if (Math.abs(across) > eps || along < -eps || along > length + eps) count++;\n }\n }\n return count;\n}\n\n/** The count of the breaks of each hard rule of a pack. */\nexport interface PackHard {\n readonly \"no-overlap\": number;\n readonly \"in-container\": number;\n readonly \"locked-kept\": number;\n readonly complete: number;\n}\n\n/** This function tells if the inside of `region` and the inside of `rect` have a common point. */\nexport function regionHitsRect(region: Region, rect: Rect): boolean {\n if (rect.w <= 0 || rect.h <= 0) return false;\n switch (region.kind) {\n case \"rect\": {\n const o = overlapOf(region, rect);\n return o.x > 0 && o.y > 0;\n }\n case \"circle\":\n return circleHitsRect(region.cx, region.cy, region.r, region.r, rect);\n case \"ellipse\":\n return circleHitsRect(region.cx, region.cy, region.rx, region.ry, rect);\n case \"polygon\": {\n const rings = [region.points, ...(region.holes ?? [])];\n const inside = (x: number, y: number): boolean => x > rect.x && x < rect.x + rect.w && y > rect.y && y < rect.y + rect.h;\n if (region.points.some(([x, y]) => inside(x, y))) return true;\n for (const ring of rings) {\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!;\n const b = ring[(i + 1) % ring.length]!;\n const m = clipMid(a[0], a[1], b[0], b[1], rect);\n if (m !== undefined && inside(m[0], m[1])) return true;\n }\n }\n return pointInRings(rect.x + rect.w / 2, rect.y + rect.h / 2, rings);\n }\n }\n}\n\n/**\n * This function tells if all of `rect` is inside `region`. A point on the border counts as inside. No part of `rect` can overlap a hole.\n * The test of a circle, an ellipse or a polygon accepts an error of `EPS` on the border. A polygon can be concave.\n */\nexport function rectInRegion(region: Region, rect: Rect): boolean {\n const x1 = rect.x + rect.w;\n const y1 = rect.y + rect.h;\n const corners: readonly (readonly [number, number])[] = [\n [rect.x, rect.y],\n [x1, rect.y],\n [x1, y1],\n [rect.x, y1],\n ];\n switch (region.kind) {\n case \"rect\":\n return rect.x >= region.x && rect.y >= region.y && x1 <= region.x + region.w && y1 <= region.y + region.h;\n case \"circle\":\n return corners.every(([x, y]) => inEllipse(region.cx, region.cy, region.r, region.r, x, y));\n case \"ellipse\":\n return corners.every(([x, y]) => inEllipse(region.cx, region.cy, region.rx, region.ry, x, y));\n case \"polygon\": {\n const ring = region.points;\n if (ring.length < 3) return false;\n const points = [...corners, [rect.x + rect.w / 2, rect.y + rect.h / 2] as const];\n if (!points.every(([x, y]) => onRing(x, y, ring) || pointInRings(x, y, [ring]))) return false;\n const deep = (x: number, y: number): boolean => x > rect.x + EPS && x < x1 - EPS && y > rect.y + EPS && y < y1 - EPS;\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!;\n const b = ring[(i + 1) % ring.length]!;\n const m = clipMid(a[0], a[1], b[0], b[1], rect);\n if (m !== undefined && deep(m[0], m[1])) return false;\n }\n return (region.holes ?? []).every((hole) => !regionHitsRect({ kind: \"polygon\", points: hole }, rect));\n }\n }\n}\n\n/** This function gives the rectangle made smaller by `d` on each side. A side does not become smaller than 0. */\nfunction shrink(r: Rect, d: number): Rect {\n const dx = Math.min(d, r.w / 2);\n const dy = Math.min(d, r.h / 2);\n return { x: r.x + dx, y: r.y + dy, w: r.w - 2 * dx, h: r.h - 2 * dy };\n}\n\n/** This function tells if a point is inside an ellipse or on its border, with an error of `EPS`. */\nfunction inEllipse(cx: number, cy: number, rx: number, ry: number, x: number, y: number): boolean {\n if (rx <= 0 || ry <= 0) return false;\n const u = (x - cx) / rx;\n const v = (y - cy) / ry;\n return u * u + v * v <= 1 + EPS;\n}\n\n/** This function tells if a point is on a ring of a polygon, with an error of `EPS`. */\nfunction onRing(x: number, y: number, ring: readonly (readonly [number, number])[]): boolean {\n for (let i = 0; i < ring.length; i++) {\n const [ax, ay] = ring[i]!;\n const [bx, by] = ring[(i + 1) % ring.length]!;\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((x - ax) * dx + (y - ay) * dy) / len2));\n if (Math.hypot(x - (ax + t * dx), y - (ay + t * dy)) <= EPS) return true;\n }\n return false;\n}\n\n/** An ellipse with the radii `rx` and `ry` scales to a unit circle. The rectangle scales with it. */\nfunction circleHitsRect(cx: number, cy: number, rx: number, ry: number, rect: Rect): boolean {\n if (rx <= 0 || ry <= 0) return false;\n const x0 = (rect.x - cx) / rx;\n const x1 = (rect.x + rect.w - cx) / rx;\n const y0 = (rect.y - cy) / ry;\n const y1 = (rect.y + rect.h - cy) / ry;\n const dx = Math.max(x0, 0, -x1);\n const dy = Math.max(y0, 0, -y1);\n return dx * dx + dy * dy < 1;\n}\n\n/** This function gives the middle of the part of a segment inside a rectangle, or `undefined` when that part is a point or empty. */\nfunction clipMid(ax: number, ay: number, bx: number, by: number, r: Rect): readonly [number, number] | undefined {\n let t0 = 0;\n let t1 = 1;\n const dx = bx - ax;\n const dy = by - ay;\n const edges: readonly (readonly [number, number])[] = [\n [-dx, ax - r.x],\n [dx, r.x + r.w - ax],\n [-dy, ay - r.y],\n [dy, r.y + r.h - ay],\n ];\n for (const [p, q] of edges) {\n if (p === 0) {\n if (q < 0) return undefined;\n } else if (p < 0) {\n t0 = Math.max(t0, q / p);\n } else {\n t1 = Math.min(t1, q / p);\n }\n }\n if (t1 <= t0) return undefined;\n const t = (t0 + t1) / 2;\n return [ax + t * dx, ay + t * dy];\n}\n\n/** The even-odd rule over the outer ring and the holes. */\nfunction pointInRings(x: number, y: number, rings: readonly (readonly (readonly [number, number])[])[]): boolean {\n let inside = false;\n for (const ring of rings) {\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const [xi, yi] = ring[i]!;\n const [xj, yj] = ring[j]!;\n if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) inside = !inside;\n }\n }\n return inside;\n}\n\n/**\n * This function counts the pairs of a placed box and an obstacle that overlap by more than `tolerance`.\n * The box counts with its margin. A box with a shape counts as its bounding box.\n */\nexport function countObstacleHits(\n boxes: readonly LayoutBox[],\n obstacles: readonly Obstacle[] | undefined,\n tolerance: number = DEFAULT_TOLERANCE.overlap,\n): number {\n if (obstacles === undefined || obstacles.length === 0) return 0;\n let count = 0;\n for (const box of boxes) {\n const r0 = placedRect(box);\n if (r0 === undefined) continue;\n const r = grow(r0, box.margin);\n const small = { x: r.x + tolerance, y: r.y + tolerance, w: r.w - 2 * tolerance, h: r.h - 2 * tolerance };\n for (const o of obstacles) if (regionHitsRect(o.region, small)) count++;\n }\n return count;\n}\n\n/**\n * This function gives the count of each hard rule of the output of a packer.\n * It applies the output with `applyPack`. Only the placed boxes and the locked boxes count for the overlaps and the container.\n * `no-overlap` counts the pairs of boxes and the pairs of a box and an obstacle.\n * A locked box without a placement, or with a move of more than `RECORD_EPS`, breaks `locked-kept`.\n * A locked box without a position in the input is a bad input, not a break. `checkInput` finds it.\n * Another box without a placement that is not in `overflow` breaks `complete`.\n *\n * `options` goes to `countOutside` for `in-container`.\n */\nexport function packHard(input: LayoutInput, output: PackOutput, tolerance: number = DEFAULT_TOLERANCE.overlap, options: ContainerTest = {}): PackHard {\n const after = applyPack(input, output);\n const placed = new Set(output.placements.map((p) => p.id));\n const out = new Set(output.overflow);\n const was = new Map(input.boxes.map((b) => [b.id, b]));\n let lockedMoved = 0;\n let incomplete = 0;\n const kept: LayoutBox[] = [];\n for (const box of after.boxes) {\n const old = was.get(box.id);\n if (old?.locked === true) {\n if (old.x === undefined || old.y === undefined) continue;\n const moved = Math.abs(old.x - (box.x ?? old.x)) > RECORD_EPS || Math.abs(old.y - (box.y ?? old.y)) > RECORD_EPS;\n if (!placed.has(box.id) || moved) lockedMoved++;\n kept.push(box);\n } else if (placed.has(box.id)) {\n kept.push(box);\n } else if (!out.has(box.id)) {\n incomplete++;\n }\n }\n return {\n \"no-overlap\": countOverlaps(kept, tolerance) + countObstacleHits(kept, after.obstacles, tolerance),\n \"in-container\": countOutside({ ...after, boxes: kept }, tolerance, options),\n \"locked-kept\": lockedMoved,\n complete: incomplete,\n };\n}\n\n/**\n * This function gives the problems of an input file. An empty list tells that the file is good.\n * A problem is a bad input, not a break of a hard rule. Thus an engine refuses the input.\n */\nexport function checkInput(input: LayoutInput): readonly string[] {\n const problems: string[] = [];\n const ids = new Set<string>();\n for (const box of input.boxes) {\n if (ids.has(box.id)) problems.push(`box ${box.id}: the id is not unique`);\n ids.add(box.id);\n if (!(box.w > 0 && box.h > 0 && Number.isFinite(box.w) && Number.isFinite(box.h))) problems.push(`box ${box.id}: the size is not positive and finite`);\n if (box.locked === true && (box.x === undefined || box.y === undefined)) problems.push(`box ${box.id}: a locked box has no position`);\n }\n if (countPortsOffBorder(input.boxes) > 0) problems.push(\"a fixed port is not on the border of its box\");\n for (const edge of input.edges ?? []) {\n if (!ids.has(edge.source) || !ids.has(edge.target)) problems.push(`edge ${edge.id}: a box of the edge is not in the input`);\n }\n return problems;\n}\n","import { RECORD_EPS, RECORD_SCALE } from \"./tolerance.ts\";\n\n/** The direction of a measure: the side of the better values. */\nexport type Direction = \"lower\" | \"higher\";\n\n/**\n * The facts of one measure: its unit, its direction and its range.\n * `floor` and `tol` are the parameters of the floor rule of the promotion rule (`docs/PROMOTION.md` of `highways`).\n * Each engine exports the specs of its own measures. This package exports the specs of the `joint.*` measures.\n */\nexport interface MeasureSpec<Id extends string = string> {\n readonly id: Id;\n readonly unit: string;\n readonly direction: Direction;\n /** The lowest value. */\n readonly min: number;\n /** The highest value. The value `Infinity` tells that the measure has no upper limit. */\n readonly max: number;\n /** The family of the measure in the measure note of its engine. */\n readonly family?: string;\n /** The best value. Without it, the measure has no floor. */\n readonly floor?: number;\n /** The absolute tolerance at the floor. */\n readonly tol?: number;\n /**\n * The smallest change that counts as better or worse. A number is an absolute change. `{ rel }` is a share of the larger of the two values.\n * `docs/JOINT-MEASURES.md` gives the reason of each joint value.\n */\n readonly minEffect?: number | { readonly rel: number };\n /** The role of the measure in the joint selector. */\n readonly role?: \"guard\" | \"change-guard\" | \"diagnostic\" | \"time\";\n}\n\n/** The id of a joint measure. `docs/JOINT-MEASURES.md` gives the definitions. */\nexport type JointMeasureId =\n | \"joint.fill\"\n | \"joint.aspectError\"\n | \"joint.spill\"\n | \"joint.straight.crossings\"\n | \"joint.straight.length\"\n | \"joint.stability.mean\"\n | \"joint.stability.moved\"\n | \"joint.proxy.rank\"\n | \"joint.ms\";\n\n/** The specs of the joint measures, in the order of `docs/JOINT-MEASURES.md`. */\nexport const JOINT_MEASURES: readonly MeasureSpec<JointMeasureId>[] = Object.freeze([\n { id: \"joint.fill\", minEffect: 0.001, unit: \"0 to 1\", direction: \"higher\", min: 0, max: 1, floor: 1, role: \"guard\" },\n { id: \"joint.aspectError\", minEffect: 0.01, unit: \"natural log\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0.01, role: \"guard\" },\n { id: \"joint.spill\", minEffect: 0.001, unit: \"0 to 1\", direction: \"lower\", min: 0, max: 1, floor: 0, tol: 0.001, role: \"guard\" },\n { id: \"joint.straight.crossings\", minEffect: 0, unit: \"count\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0, role: \"guard\" },\n { id: \"joint.straight.length\", minEffect: 0.01, unit: \"S for each edge\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0.01, role: \"guard\" },\n { id: \"joint.stability.mean\", minEffect: 0.005, unit: \"W\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0.005, role: \"change-guard\" },\n { id: \"joint.stability.moved\", minEffect: 0.02, unit: \"0 to 1\", direction: \"lower\", min: 0, max: 1, floor: 0, tol: 0.02, role: \"change-guard\" },\n { id: \"joint.proxy.rank\", unit: \"-1 to 1\", direction: \"higher\", min: -1, max: 1, role: \"diagnostic\" },\n { id: \"joint.ms\", unit: \"milliseconds\", direction: \"lower\", min: 0, max: Infinity, role: \"time\" },\n] as const);\n\n/** The threshold of `joint.stability.moved`, in widths `W` of the base. */\nexport const JOINT_MOVED_MIN = 0.01;\n\n/** The result of a compare of a candidate with a baseline on one measure. A tie is not better. */\nexport type Verdict = \"better\" | \"worse\" | \"tie\";\n\n/**\n * This function gives the smallest change of a measure that counts between the values `a` and `b`.\n * The value is `max(RECORD_EPS, minEffect)`, or `max(RECORD_EPS, rel * max(|a|, |b|))` for a relative `minEffect`.\n * The larger value makes the threshold the same after a swap of `a` and `b`.\n */\nexport function minEffectOf(spec: Pick<MeasureSpec, \"minEffect\">, a = 0, b = 0): number {\n const m = spec.minEffect ?? 0;\n const t = typeof m === \"number\" ? m : m.rel * Math.max(Math.abs(a), Math.abs(b));\n return Math.max(RECORD_EPS, Number.isFinite(t) ? t : 0);\n}\n\n/** The slack of the threshold in grid steps. It absorbs only the float noise of the threshold, because the change is a whole number. */\nconst STEP_NOISE = 1e-6;\n\n/**\n * This function compares the value `candidate` with the value `baseline` of one measure on one input.\n * The compare uses whole grid steps of `RECORD_EPS`. Thus a live value and its rounded record give the same verdict.\n * A change of at most the threshold of `minEffectOf` in grid steps is a tie. A swap of the two values swaps better and worse.\n * Two equal values are a tie, also two infinite values. A value `NaN` is an error.\n */\nexport function compareMeasure(candidate: number, baseline: number, spec: Pick<MeasureSpec, \"direction\" | \"minEffect\">): Verdict {\n if (Number.isNaN(candidate) || Number.isNaN(baseline)) throw new RangeError(\"compareMeasure: a value is NaN\");\n if (candidate === baseline) return \"tie\";\n const a = Math.round(candidate * RECORD_SCALE);\n const b = Math.round(baseline * RECORD_SCALE);\n let delta: number;\n if (Number.isSafeInteger(a) && Number.isSafeInteger(b)) {\n delta = a - b;\n const m = spec.minEffect ?? 0;\n const t = typeof m === \"number\" ? m * RECORD_SCALE : m.rel * Math.max(Math.abs(a), Math.abs(b));\n if (Math.abs(delta) <= Math.max(1, Number.isFinite(t) ? t : 0) + STEP_NOISE) return \"tie\";\n } else {\n delta = candidate - baseline;\n if (!(Math.abs(delta) > minEffectOf(spec, candidate, baseline))) return \"tie\";\n }\n const better = spec.direction === \"lower\" ? delta < 0 : delta > 0;\n return better ? \"better\" : \"worse\";\n}\n","/** This function gives the UTF-8 bytes of a string. The package has no runtime dependencies, thus it does not use `TextEncoder`. */\nexport function utf8(text: string): number[] {\n const bytes: number[] = [];\n for (const ch of text) {\n const c = ch.codePointAt(0)!;\n if (c < 0x80) bytes.push(c);\n else if (c < 0x800) bytes.push(0xc0 | (c >> 6), 0x80 | (c & 63));\n else if (c < 0x10000) bytes.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63));\n else bytes.push(0xf0 | (c >> 18), 0x80 | ((c >> 12) & 63), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63));\n }\n return bytes;\n}\n","import { utf8 } from \"./utf8.ts\";\n\n/** This function gives a generator of random numbers in [0, 1). It is `mulberry32`, as in `docs/FORMAT.md` of `packing`. */\nexport function mulberry32(seed: number): () => number {\n let s = seed >>> 0;\n return () => {\n s = (s + 0x6d2b79f5) | 0;\n let t = Math.imul(s ^ (s >>> 15), 1 | s);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** This function gives the FNV-1a hash of 32 bits of the UTF-8 bytes of a string. */\nexport function fnv1a32(text: string): number {\n let h = 0x811c9dc5;\n for (const b of utf8(text)) h = Math.imul(h ^ b, 0x01000193) >>> 0;\n return h;\n}\n\n/** This function gives the generator of one step of a seeded generator: `mulberry32(fnv1a32(\"<seed>:<step>\"))`. */\nexport function stepRandom(seed: number, step: string): () => number {\n return mulberry32(fnv1a32(`${seed}:${step}`));\n}\n\n/** This function gives a whole number from `lo` to `hi`, both included. */\nexport function randomInt(r: () => number, lo: number, hi: number): number {\n return lo + Math.floor(r() * (hi - lo + 1));\n}\n","import { SIDES, type Side } from \"./geometry.ts\";\nimport type { LayoutBox, LayoutEdge, LayoutGenerator, LayoutInput, Port } from \"./input.ts\";\nimport { randomInt, stepRandom } from \"./random.ts\";\n\n/**\n * The shape of the edges of `edgeStep`. The values are the cells of `edgeShape`, and `hubs`.\n * `hubs` waits for the next breaking change to become a value of `LayoutCell.edgeShape`.\n */\nexport type EdgeShape = \"random\" | \"clustered\" | \"hubChain\" | \"hubs\" | \"longRange\" | \"tree\" | \"bundled\";\n\n/** The parameters of `edgeStep`. */\nexport interface EdgeStepParams {\n readonly edgeDensity: \"sparse\" | \"medium\" | \"dense\";\n readonly edgeShape: EdgeShape;\n /** The default is `none`. */\n readonly groups?: \"none\" | \"flat\" | \"nested\";\n /** The default is `free`. */\n readonly ports?: \"free\" | \"sides\" | \"fixed\";\n /** The order of the hubs of `hubs` and `tree`: the largest box first, or a random order. The default is `area`. */\n readonly hubBy?: \"area\" | \"random\";\n}\n\n/** The mean count of the edges of each box for each value of `edgeDensity`. */\nexport const EDGE_DENSITY: Readonly<Record<EdgeStepParams[\"edgeDensity\"], number>> = Object.freeze({ sparse: 0.5, medium: 1.5, dense: 4 });\n\n/** The version of `edgeStep`. A change of its output gives a new version. */\nexport const EDGE_STEP_VERSION = 1;\n\nconst CLUSTER = 8;\nconst CHAIN = 32;\nconst INSIDE = 0.85;\nconst FAN_SHARE = 0.6;\nconst FIXED_SHARE = 0.2;\nconst COLLECTIONS = [\"users\", \"orders\", \"items\", \"events\"] as const;\n\nconst round3 = (x: number): number => Math.round(x * 1000) / 1000;\n\n/**\n * This function gives the input with edges, groups and ports from its topology alone: a joint input has no positions before the pack.\n * The random numbers come from the steps `edges` and `ports` of `seed`. The function appends its stamp to `steps`, and removes the old `hash`.\n * The rules of each shape are in `docs/JOINT-CORPUS.md`.\n */\nexport function edgeStep(input: LayoutInput, params: EdgeStepParams, seed: number = input.seed ?? 0): LayoutInput {\n if ((input.edges?.length ?? 0) > 0) throw new RangeError(\"edgeStep: the input has edges already\");\n const full: Required<EdgeStepParams> = { groups: \"none\", ports: \"free\", hubBy: \"area\", ...params };\n const n = input.boxes.length;\n const r = stepRandom(seed, \"edges\");\n\n const perm = input.boxes.map((_, i) => i);\n for (let i = n - 1; i > 0; i--) {\n const j = randomInt(r, 0, i);\n [perm[i], perm[j]] = [perm[j]!, perm[i]!];\n }\n const clusterOf: number[] = new Array<number>(n);\n perm.forEach((box, p) => (clusterOf[box] = Math.floor(p / CLUSTER)));\n const clusters = Math.ceil(n / CLUSTER);\n const members = (c: number): readonly number[] => perm.slice(c * CLUSTER, (c + 1) * CLUSTER);\n const collectionOf =\n full.edgeShape === \"bundled\"\n ? clusterOf.map((c) => `${COLLECTIONS[c % COLLECTIONS.length]!}-${c}`)\n : input.boxes.map(() => COLLECTIONS[randomInt(r, 0, COLLECTIONS.length - 1)]!);\n const area = (i: number): number => input.boxes[i]!.w * input.boxes[i]!.h;\n const rank = full.hubBy === \"area\" ? input.boxes.map((_, i) => i).sort((a, b) => area(b) - area(a) || a - b) : perm;\n\n const pairs: [number, number][] = [];\n const seen = new Set<string>();\n const add = (u: number, v: number): void => {\n const key = u < v ? `${u}-${v}` : `${v}-${u}`;\n if (u === v || seen.has(key)) return;\n seen.add(key);\n pairs.push([u, v]);\n };\n const anyBox = (): number => randomInt(r, 0, n - 1);\n const inCluster = (c: number): number => {\n const m = members(c);\n return m[randomInt(r, 0, m.length - 1)]!;\n };\n const otherCluster = (c: number): number => {\n const o = randomInt(r, 0, clusters - 2);\n return o >= c ? o + 1 : o;\n };\n const target = Math.min(Math.round(n * EDGE_DENSITY[full.edgeDensity]), (n * (n - 1)) / 2);\n const fill = (pick: () => [number, number]): void => {\n for (let tries = 0; pairs.length < target && tries < target * 30; tries++) add(...pick());\n };\n const clustered = (): [number, number] => {\n const u = anyBox();\n return [u, r() < INSIDE ? inCluster(clusterOf[u]!) : anyBox()];\n };\n\n if (n >= 2) {\n switch (full.edgeShape) {\n case \"random\":\n fill(() => [anyBox(), anyBox()]);\n break;\n case \"clustered\":\n fill(clustered);\n break;\n case \"longRange\":\n fill(() => {\n const u = anyBox();\n return [u, clusters > 1 ? inCluster(otherCluster(clusterOf[u]!)) : anyBox()];\n });\n break;\n case \"hubs\":\n fill(() => [anyBox(), rank[Math.floor(n * r() ** 3)]!]);\n break;\n case \"tree\":\n for (let i = 1; i < n; i++) add(rank[randomInt(r, 0, i - 1)]!, rank[i]!);\n break;\n case \"hubChain\": {\n const k = Math.ceil(n / CHAIN);\n const length = Math.ceil(n / k);\n const chains = Array.from({ length: k }, (_, c) => perm.slice(c * length, (c + 1) * length));\n for (const chain of chains) for (let i = 0; i + 1 < chain.length; i++) add(chain[i]!, chain[i + 1]!);\n const skips = Math.max(0, target - pairs.length);\n for (let s = 0; s < skips; s++) {\n const c = k > 1 ? randomInt(r, 0, k - 2) : 0;\n const from = chains[c]!;\n const to = chains[k > 1 ? c + 1 : 0]!;\n const i = randomInt(r, 0, from.length - 1);\n const j = i + Math.floor(from.length / 8) + randomInt(r, 0, Math.floor(from.length / 2));\n if (j < to.length) add(from[i]!, to[j]!);\n }\n break;\n }\n case \"bundled\":\n for (let rounds = 0; pairs.length < target * FAN_SHARE && clusters > 1 && rounds < target; rounds++) {\n const u = anyBox();\n const c = otherCluster(clusterOf[u]!);\n const fan = randomInt(r, 4, 15);\n for (let f = 0; f < fan && pairs.length < target; f++) add(u, inCluster(c));\n }\n fill(clustered);\n break;\n }\n }\n\n const rp = stepRandom(seed, \"ports\");\n const ports: Port[][] = input.boxes.map((b) => [...(b.ports ?? [])]);\n const portOn = (box: LayoutBox, id: string, side: Side, fixed: boolean): Port => {\n if (!fixed) return { id, side };\n const along = round3(rp() * (side === \"top\" || side === \"bottom\" ? box.w : box.h));\n const at = { top: [along, 0], bottom: [along, box.h], left: [0, along], right: [box.w, along] }[side];\n return { id, side, x: at[0]!, y: at[1]! };\n };\n const out = new Set<number>();\n if (full.ports === \"fixed\") {\n input.boxes.forEach((box, i) => {\n if (rp() >= FIXED_SHARE) return;\n const side = SIDES[randomInt(rp, 0, 3)]!;\n ports[i]!.push(portOn(box, \"out\", side, true));\n out.add(i);\n });\n }\n const edges: LayoutEdge[] = pairs.map(([u, v], k) => {\n const id = `e${k}`;\n const s = input.boxes[u]!;\n const t = input.boxes[v]!;\n let ends: { sourcePort?: string; targetPort?: string } = {};\n if (full.ports === \"sides\") {\n ports[u]!.push(portOn(s, `${id}.s`, SIDES[randomInt(rp, 0, 3)]!, false));\n ports[v]!.push(portOn(t, `${id}.t`, SIDES[randomInt(rp, 0, 3)]!, false));\n ends = { sourcePort: `${id}.s`, targetPort: `${id}.t` };\n } else if (out.has(u)) {\n ends = { sourcePort: \"out\" };\n }\n return { id, source: s.id, target: t.id, ...ends, data: { collection: collectionOf[v]! } };\n });\n\n const boxes = input.boxes.map((box, i): LayoutBox => {\n const c = clusterOf[i]!;\n const group = full.groups === \"none\" ? undefined : `g${c}`;\n const path = full.groups === \"nested\" ? `G${Math.floor(c / 4)}/g${c}` : group;\n return {\n ...box,\n ...(group === undefined ? {} : { group, data: { ...box.data, group: path } }),\n ...(ports[i]!.length === 0 ? {} : { ports: ports[i]! }),\n };\n });\n const stamp: LayoutGenerator = { name: \"edges\", version: EDGE_STEP_VERSION, params: { ...full }, seed };\n const { hash: _old, ...rest } = input;\n return { ...rest, boxes, edges, steps: [...(input.steps ?? []), stamp] };\n}\n","import { RECORD_EPS } from \"./tolerance.ts\";\nimport { utf8 } from \"./utf8.ts\";\n\n/** The round constants of SHA-256. */\nconst K: readonly number[] = [\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,\n 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\n 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n];\n\n/**\n * This function gives the SHA-256 digest of the UTF-8 bytes of a string, as 64 lowercase hex characters.\n * It uses no API of Node or of the browser.\n */\nexport function sha256Hex(text: string): string {\n const bytes = utf8(text);\n const bits = bytes.length * 8;\n const total = Math.ceil((bytes.length + 9) / 64) * 64;\n const data = new Uint8Array(total);\n data.set(bytes);\n data[bytes.length] = 0x80;\n const view = new DataView(data.buffer);\n view.setUint32(total - 8, Math.floor(bits / 0x100000000));\n view.setUint32(total - 4, bits >>> 0);\n const h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];\n const w = new Uint32Array(64);\n const rotr = (x: number, n: number): number => (x >>> n) | (x << (32 - n));\n for (let off = 0; off < total; off += 64) {\n for (let i = 0; i < 16; i++) w[i] = view.getUint32(off + 4 * i);\n for (let i = 16; i < 64; i++) {\n const a = w[i - 15]!;\n const b = w[i - 2]!;\n const s0 = rotr(a, 7) ^ rotr(a, 18) ^ (a >>> 3);\n const s1 = rotr(b, 17) ^ rotr(b, 19) ^ (b >>> 10);\n w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0;\n }\n let [a, b, c, d, e, f, g, k] = h as [number, number, number, number, number, number, number, number];\n for (let i = 0; i < 64; i++) {\n const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);\n const ch = (e & f) ^ (~e & g);\n const t1 = (k + s1 + ch + K[i]! + w[i]!) >>> 0;\n const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);\n const maj = (a & b) ^ (a & c) ^ (b & c);\n const t2 = (s0 + maj) >>> 0;\n k = g;\n g = f;\n f = e;\n e = (d + t1) >>> 0;\n d = c;\n c = b;\n b = a;\n a = (t1 + t2) >>> 0;\n }\n h[0] = (h[0]! + a) >>> 0;\n h[1] = (h[1]! + b) >>> 0;\n h[2] = (h[2]! + c) >>> 0;\n h[3] = (h[3]! + d) >>> 0;\n h[4] = (h[4]! + e) >>> 0;\n h[5] = (h[5]! + f) >>> 0;\n h[6] = (h[6]! + g) >>> 0;\n h[7] = (h[7]! + k) >>> 0;\n }\n return h.map((x) => x.toString(16).padStart(8, \"0\")).join(\"\");\n}\n\n/**\n * This function gives the canonical form of a value: sorted keys and no whitespace, with the numbers of `JSON.stringify`.\n * A key with the value `undefined` is not in the form. An `undefined` in an array becomes `null`.\n */\nexport function canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\";\n if (Array.isArray(value)) return `[${value.map((v: unknown) => (v === undefined ? \"null\" : canonicalJson(v))).join(\",\")}]`;\n const o = value as Record<string, unknown>;\n const keys = Object.keys(o)\n .filter((k) => o[k] !== undefined)\n .sort();\n return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalJson(o[k])}`).join(\",\")}}`;\n}\n\n/** The options of `outputHash` and `documentHash`. */\nexport interface HashOptions {\n /**\n * The step of the grid of the numbers. The default is `RECORD_EPS`, so a number keeps 3 decimals.\n * The value `0` keeps the exact numbers. A negative value or a value that is not finite causes a `RangeError`.\n */\n readonly grid?: number;\n}\n\n/** This function gives the factor of a grid: `1 / grid`, or `undefined` for the exact numbers. */\nfunction gridFactor(options: HashOptions): number | undefined {\n const grid = options.grid ?? RECORD_EPS;\n if (!Number.isFinite(grid) || grid < 0) throw new RangeError(`The grid ${grid} is not a finite number of 0 or more.`);\n return grid === 0 ? undefined : 1 / grid;\n}\n\n/**\n * This function gives a copy of a value with each number on the grid. The value `-0` becomes `0`.\n * It throws a `RangeError` for a number that is not finite.\n */\nfunction onGrid(value: unknown, path: string, k: number | undefined): unknown {\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new RangeError(`The value has the number ${value} at ${path}. JSON has no form for it.`);\n if (k === undefined) return value;\n const r = Math.round(value * k) / k;\n if (!Number.isFinite(r)) throw new RangeError(`The number at ${path} is too large for the grid.`);\n return r === 0 ? 0 : r;\n }\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) return value.map((v: unknown, i) => onGrid(v, `${path}[${i}]`, k));\n const o = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(o)) out[key] = onGrid(o[key], `${path}.${key}`, k);\n return out;\n}\n\n/**\n * This function gives the hash of an output: the first 16 hex characters of the SHA-256 of its canonical form.\n * Before the canonical form, each number goes to the nearest point of the grid, and `-0` becomes `0`.\n * With the default grid, the rounding is `round3` of `packing`: `Math.round(x * 1000) / 1000`.\n * The function throws a `RangeError` for `NaN` and for an infinite number.\n *\n * The grid can split two outputs. Two numbers near a rounding boundary can go to two different points.\n * The grid can also merge two outputs whose numbers go to the same points. This merge is intentional: it removes the noise of floating-point numbers.\n */\nexport function outputHash(value: unknown, options: HashOptions = {}): string {\n return sha256Hex(canonicalJson(onGrid(value, \"$\", gridFactor(options)))).slice(0, 16);\n}\n\n/**\n * This function gives the hash of a document. It uses the rule of `outputHash`, but the form does not include the field `hash` of the document.\n * With the default grid, it is the input hash of `docs/FORMAT.md` of `packing`.\n */\nexport function documentHash(doc: object, options: HashOptions = {}): string {\n const { hash: _hash, ...rest } = doc as { readonly hash?: unknown };\n return outputHash(rest, options);\n}\n\n/** One output group: the candidates with the same output hash on each decision input. */\nexport interface OutputGroup {\n /** The id of the group: its first member. */\n readonly id: string;\n /** The ids of the candidates of the group, in sorted order. */\n readonly members: readonly string[];\n}\n\n/**\n * This function gives the output groups of the candidates. The key of `hashes` is the id of a candidate.\n * Its value is the list of the output hashes of the candidate, in the order of the decision inputs.\n * Candidates with equal lists make one group. The groups are in the order of their ids.\n * The function throws a `RangeError` when two lists have different lengths.\n */\nexport function outputGroups(hashes: Readonly<Record<string, readonly string[]>>): OutputGroup[] {\n const byList = new Map<string, string[]>();\n let first: string | undefined;\n for (const id of Object.keys(hashes)) {\n const list = hashes[id]!;\n if (first === undefined) first = id;\n else if (list.length !== hashes[first]!.length)\n throw new RangeError(`The candidate \"${id}\" has ${list.length} hashes, but \"${first}\" has ${hashes[first]!.length}.`);\n const key = JSON.stringify(list);\n const members = byList.get(key);\n if (members) members.push(id);\n else byList.set(key, [id]);\n }\n const groups = [...byList.values()].map((members): OutputGroup => {\n const sorted = [...members].sort();\n return { id: sorted[0]!, members: sorted };\n });\n return groups.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n}\n\n/** The evidence that a candidate is exercised on its decision inputs. */\nexport interface ExerciseEvidence {\n /** The move counts of the candidate, by name. A record keeps each one as the trace measure `move.<name>`. */\n readonly moves?: Readonly<Record<string, number>>;\n /** The output hashes of the candidate, in the order of the decision inputs. */\n readonly hashes?: readonly string[];\n /** The output hashes of the base of the candidate, in the same order. */\n readonly baseHashes?: readonly string[];\n}\n\n/**\n * This function tells if a candidate is exercised. It gives `true` when a move count is more than 0.\n * It also gives `true` when `hashes` and `baseHashes` are different at one place or more.\n * Without evidence, it gives `false`.\n * The function throws a `RangeError` when only one of the two lists is given, or when their lengths are different.\n */\nexport function exercised(evidence: ExerciseEvidence): boolean {\n const { moves, hashes, baseHashes } = evidence;\n if ((hashes === undefined) !== (baseHashes === undefined)) throw new RangeError(\"The evidence must have both hashes and baseHashes, or neither of them.\");\n if (hashes && baseHashes && hashes.length !== baseHashes.length)\n throw new RangeError(`The candidate has ${hashes.length} hashes, but its base has ${baseHashes.length}.`);\n if (moves && Object.values(moves).some((n) => n > 0)) return true;\n if (hashes && baseHashes) return hashes.some((h, i) => h !== baseHashes[i]);\n return false;\n}\n","import { outputHash } from \"./hash.ts\";\nimport { compareMeasure, type MeasureSpec } from \"./measures.ts\";\n\n/** The part of a `MeasureSpec` that a pick uses: the direction and the `minEffect`. */\nexport type PickSpec = Pick<MeasureSpec, \"direction\" | \"minEffect\">;\n\n/** A member of a portfolio: a function with an id. A portfolio is also a member. */\nexport interface Member<I, O> {\n readonly id: string;\n /** This function gives the output of the member for an input. */\n run(input: I): O;\n}\n\n/** One level of the key of a portfolio: a measure of an output. */\nexport interface PortfolioLevel<I, O> {\n /** The id of the level. The id `hard` is reserved. */\n readonly id: string;\n readonly spec: PickSpec;\n /** This function gives the value of the measure for the output of a member. The value must be finite. */\n value(input: I, output: O): number;\n}\n\n/** The key of a portfolio: the hard level, then the other levels in order. */\nexport interface PortfolioKey<I, O> {\n /** This function gives the count of hard breaks. It is level 0, with the direction `lower` and the `minEffect` 0. */\n hard(input: I, output: O): number;\n /** The levels after the hard level, in the order of the pick. */\n readonly levels: readonly PortfolioLevel<I, O>[];\n /** This function gives the hash of an output. The default is `outputHash` with the default grid. */\n hash?(output: O): string;\n}\n\n/** The options of a portfolio. */\nexport interface PortfolioOptions {\n /** The time limit in milliseconds, 0 or more. The first member always starts. A member that starts always finishes. */\n readonly budgetMs?: number;\n /** The largest count of members that run, a whole number of 1 or more. The other members are cut. */\n readonly maxMembers?: number;\n /** The clock in milliseconds. The default is `performance.now`, or `Date.now` without `performance`. */\n readonly now?: () => number;\n /**\n * The members that get an output hash. The default `all` hashes each member with the status `ran`. A hash that throws then gives the status `error`.\n * With `pick`, only member 0 and the winner get a hash, and only when the winner is not member 0. Then a hash that throws makes `pick` throw.\n */\n readonly hashes?: \"all\" | \"pick\";\n}\n\n/** The status of a member in a pick. */\nexport type MemberStatus = \"ran\" | \"cut\" | \"error\";\n\n/** The trace of one member in a pick. */\nexport interface MemberTrace {\n readonly id: string;\n readonly status: MemberStatus;\n /** The value of each level, with the key `hard` for the hard level. Only a member with the status `ran` has values. */\n readonly values?: Readonly<Record<string, number>>;\n /** The time of the run of the member, in milliseconds. */\n readonly ms?: number;\n /**\n * The hash of the output of the member. Under the option `hashes` \"all\" (the default), each member with the status `ran` has it.\n * Under `hashes` \"pick\", it is absent, except for member 0 and the winner when the winner is not member 0.\n */\n readonly outputHash?: string;\n /** The message of the error of a member with the status `error`. */\n readonly error?: string;\n}\n\n/** The trace of one pick of a portfolio. */\nexport interface PortfolioTrace {\n /** One entry for each member, in the order of the members. A cut member is also in the list. */\n readonly members: readonly MemberTrace[];\n readonly winner: string;\n /** The index of the winner in the list of the members. */\n readonly winnerIndex: number;\n /** The value `true` tells that the winner is not member 0 and has a different output hash. */\n readonly picked: boolean;\n /** The time of the full pick, in milliseconds. */\n readonly totalMs: number;\n readonly budgetMs?: number;\n readonly maxMembers?: number;\n /** The count of the cut members. */\n readonly cut: number;\n /** The value `false` tells that the time limit cut one member or more. Then a run on a different computer can give a different pick. */\n readonly deterministic: boolean;\n /** The ids of the members that stay in after each level of `selectBest`. The first list is for the hard level. */\n readonly kept: readonly (readonly string[])[];\n}\n\n/** The result of one pick of a portfolio: the output of the winner, its id and the trace. */\nexport interface PortfolioPick<O> {\n readonly output: O;\n readonly winner: string;\n readonly trace: PortfolioTrace;\n}\n\n/** A portfolio: a member that runs its members and gives the output of the best member. */\nexport interface Portfolio<I, O> extends Member<I, O> {\n /** This function starts the members on an input and gives the output of the winner with the trace. */\n pick(input: I): PortfolioPick<O>;\n}\n\n/** A candidate of `selectBest`: an id and the value of each level. */\nexport interface SelectCandidate {\n readonly id: string;\n readonly values: Readonly<Record<string, number>>;\n}\n\n/** A level of `selectBest`: the id of a value and its spec. */\nexport interface SelectLevel {\n readonly id: string;\n readonly spec: PickSpec;\n}\n\n/** The result of `selectBest`. */\nexport interface Selection {\n readonly winner: string;\n /** The ids of the candidates that stay in after each level, in the given order. */\n readonly kept: readonly (readonly string[])[];\n}\n\n/**\n * This function picks the best candidate. For each level, it finds the best value of the candidates that stay in.\n * It keeps each candidate that is not worse than that best value by `compareMeasure`.\n * The winner is the first candidate, in the given order, that stays in after the last level.\n * Without levels, the winner is the first candidate and `kept` is empty.\n *\n * The reason for the rule: a scan that compares each candidate with the current winner is not transitive, because of the `minEffect` ties.\n * Such a scan can drift away from the best value. An example: \"a\" is lower with the `minEffect` 0.005, and \"b\" is higher.\n * The candidates A (0, 1), B (0.004, 2) and C (0.008, 3) give the winner B.\n * The scan picks C, but A is better than C on \"a\".\n *\n * The function throws a `RangeError` for an empty list of candidates, for a missing value, and for a value that is not finite.\n */\nexport function selectBest(candidates: readonly SelectCandidate[], levels: readonly SelectLevel[]): Selection {\n if (candidates.length === 0) throw new RangeError(\"selectBest: the list of candidates is empty.\");\n for (const level of levels) {\n for (const c of candidates) {\n const v = c.values[level.id];\n if (typeof v !== \"number\") throw new RangeError(`selectBest: the candidate \"${c.id}\" has no value for the level \"${level.id}\".`);\n if (!Number.isFinite(v)) throw new RangeError(`selectBest: the candidate \"${c.id}\" has the value ${v} for the level \"${level.id}\".`);\n }\n }\n let alive: readonly SelectCandidate[] = candidates;\n const kept: (readonly string[])[] = [];\n for (const level of levels) {\n const at = (c: SelectCandidate): number => c.values[level.id]!;\n let best = at(alive[0]!);\n for (const c of alive) best = level.spec.direction === \"lower\" ? Math.min(best, at(c)) : Math.max(best, at(c));\n alive = alive.filter((c) => compareMeasure(at(c), best, level.spec) !== \"worse\");\n kept.push(alive.map((c) => c.id));\n }\n return { winner: alive[0]!.id, kept };\n}\n\n/** This function gives the move `pick` of a pick: 1 when `picked` is true, else 0. A record keeps it as the trace measure `move.pick`. */\nexport function pickMoves(trace: Pick<PortfolioTrace, \"picked\">): { pick: number } {\n return { pick: trace.picked ? 1 : 0 };\n}\n\n/** This function gives the default clock: `performance.now`, or `Date.now` without `performance`. */\nfunction defaultClock(): () => number {\n const perf = (globalThis as { readonly performance?: { now(): number } }).performance;\n return perf ? () => perf.now() : () => Date.now();\n}\n\n/** This function gives the message of an error value. */\nfunction messageOf(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** This function throws a `RangeError` for an empty list of members or for two members with the same id. */\nfunction checkMembers(id: string, members: readonly Member<unknown, unknown>[]): void {\n if (members.length === 0) throw new RangeError(`The portfolio \"${id}\" has no members.`);\n const seen = new Set<string>();\n for (const m of members) {\n if (seen.has(m.id)) throw new RangeError(`The portfolio \"${id}\" has two members with the id \"${m.id}\".`);\n seen.add(m.id);\n }\n}\n\n/** The result of the run of one member. */\ntype Ran<O> = { readonly ok: true; readonly output: O; readonly values: Record<string, number>; readonly hash?: string } | { readonly ok: false; readonly error: unknown };\n\n/**\n * This function makes a portfolio. Its `pick` starts the members in their order. `selectBest` picks the winner of the members with the status `ran`.\n * The first level is the hard level, then the levels of the key follow.\n * `members` is a list, or a function of the input that gives the list.\n *\n * A member that throws, or that gives a value that is not finite, gets the status `error`. It does not win.\n * When each member has an error, `pick` throws the error of the first member.\n * `docs/PORTFOLIO.md` tells the rules of the time limit, the trace and `picked`.\n *\n * The function throws a `RangeError` for a level with the id `hard`, for two levels with the same id and for a bad option.\n * It also throws a `RangeError` for an empty list of members, or for two members with the same id.\n */\nexport function portfolio<I, O>(\n id: string,\n members: readonly Member<I, O>[] | ((input: I) => readonly Member<I, O>[]),\n key: PortfolioKey<I, O>,\n options: PortfolioOptions = {},\n): Portfolio<I, O> {\n const levelIds = new Set<string>();\n for (const level of key.levels) {\n if (level.id === \"hard\") throw new RangeError(`The portfolio \"${id}\" has a level with the reserved id \"hard\".`);\n if (levelIds.has(level.id)) throw new RangeError(`The portfolio \"${id}\" has two levels with the id \"${level.id}\".`);\n levelIds.add(level.id);\n }\n const { budgetMs, maxMembers, hashes = \"all\" } = options;\n if (budgetMs !== undefined && !(budgetMs >= 0)) throw new RangeError(`The portfolio \"${id}\" has the budgetMs ${budgetMs}. It must be 0 or more.`);\n if (maxMembers !== undefined && !(Number.isInteger(maxMembers) && maxMembers >= 1))\n throw new RangeError(`The portfolio \"${id}\" has the maxMembers ${maxMembers}. It must be a whole number of 1 or more.`);\n if (hashes !== \"all\" && hashes !== \"pick\") throw new RangeError(`The portfolio \"${id}\" has the hashes ${String(hashes)}. It must be \"all\" or \"pick\".`);\n if (typeof members !== \"function\") checkMembers(id, members);\n const levels: readonly SelectLevel[] = [{ id: \"hard\", spec: { direction: \"lower\", minEffect: 0 } }, ...key.levels.map((l) => ({ id: l.id, spec: l.spec }))];\n const now = options.now ?? defaultClock();\n\n /** This function gives the hash of the output of a member. A hash that throws causes a `RangeError`. */\n const hashOf = (m: Member<I, O>, output: O): string => {\n try {\n return key.hash ? key.hash(output) : outputHash(output);\n } catch (e) {\n throw new RangeError(`The hash of the member \"${m.id}\" of the portfolio \"${id}\" throws: ${messageOf(e)}`, { cause: e });\n }\n };\n\n const evaluate = (m: Member<I, O>, input: I, output: O): Ran<O> => {\n const values: Record<string, number> = {};\n const measure = (level: string, f: () => number): void => {\n let v: number;\n try {\n v = f();\n } catch (e) {\n throw new RangeError(`The level \"${level}\" of the member \"${m.id}\" of the portfolio \"${id}\" throws: ${messageOf(e)}`, { cause: e });\n }\n if (typeof v !== \"number\" || !Number.isFinite(v))\n throw new RangeError(`The member \"${m.id}\" of the portfolio \"${id}\" has the value ${v} for the level \"${level}\".`);\n values[level] = v;\n };\n try {\n measure(\"hard\", () => key.hard(input, output));\n for (const level of key.levels) measure(level.id, () => level.value(input, output));\n if (hashes === \"pick\") return { ok: true, output, values };\n return { ok: true, output, values, hash: hashOf(m, output) };\n } catch (e) {\n return { ok: false, error: e };\n }\n };\n\n const pick = (input: I): PortfolioPick<O> => {\n const list = typeof members === \"function\" ? members(input) : members;\n if (typeof members === \"function\") checkMembers(id, list);\n const start = now();\n const traces: MemberTrace[] = [];\n const outputs = new Map<string, O>();\n const ran: SelectCandidate[] = [];\n let firstError: { readonly error: unknown } | undefined;\n let cut = 0;\n let outOfTime = false;\n for (let i = 0; i < list.length; i++) {\n const m = list[i]!;\n if (maxMembers !== undefined && i >= maxMembers) {\n traces.push({ id: m.id, status: \"cut\" });\n cut++;\n continue;\n }\n if (i > 0 && budgetMs !== undefined && (outOfTime || now() - start >= budgetMs)) {\n outOfTime = true;\n traces.push({ id: m.id, status: \"cut\" });\n cut++;\n continue;\n }\n const t0 = now();\n let result: Ran<O>;\n let ms: number;\n try {\n const output = m.run(input);\n ms = now() - t0;\n result = evaluate(m, input, output);\n } catch (e) {\n ms = now() - t0;\n result = { ok: false, error: e };\n }\n if (result.ok) {\n traces.push(\n result.hash === undefined\n ? { id: m.id, status: \"ran\", values: result.values, ms }\n : { id: m.id, status: \"ran\", values: result.values, ms, outputHash: result.hash },\n );\n outputs.set(m.id, result.output);\n ran.push({ id: m.id, values: result.values });\n } else {\n traces.push({ id: m.id, status: \"error\", ms, error: messageOf(result.error) });\n firstError ??= { error: result.error };\n }\n }\n if (ran.length === 0) throw firstError!.error;\n const { winner, kept } = selectBest(ran, levels);\n const winnerIndex = traces.findIndex((t) => t.id === winner);\n if (hashes === \"pick\" && winnerIndex > 0 && traces[0]!.status === \"ran\") {\n // Only member 0 and the winner get a hash. Their two trace entries are new objects with the hash.\n for (const i of [0, winnerIndex]) traces[i] = { ...traces[i]!, outputHash: hashOf(list[i]!, outputs.get(traces[i]!.id)!) };\n }\n const base = traces[0]!;\n const picked = winnerIndex > 0 && (base.status !== \"ran\" || traces[winnerIndex]!.outputHash !== base.outputHash);\n const trace: PortfolioTrace = {\n members: traces,\n winner,\n winnerIndex,\n picked,\n totalMs: now() - start,\n ...(budgetMs !== undefined ? { budgetMs } : {}),\n ...(maxMembers !== undefined ? { maxMembers } : {}),\n cut,\n deterministic: !outOfTime,\n kept,\n };\n return { output: outputs.get(winner)!, winner, trace };\n };\n\n return { id, pick, run: (input: I): O => pick(input).output };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/geometry.ts","../src/tolerance.ts","../src/input.ts","../src/turn.ts","../src/output.ts","../src/record.ts","../src/rules.ts","../src/measures.ts","../src/utf8.ts","../src/random.ts","../src/edges.ts","../src/hash.ts","../src/portfolio.ts","../src/corpus.ts"],"sourcesContent":["/** A side of a box. The y axis points down, so `top` has the smallest y. */\nexport type Side = \"top\" | \"right\" | \"bottom\" | \"left\";\n\n/** The sides in clockwise order, from the top. */\nexport const SIDES: readonly Side[] = [\"top\", \"right\", \"bottom\", \"left\"];\n\nexport interface Point {\n readonly x: number;\n readonly y: number;\n}\n\n/** A rectangle: its top-left corner and its size. */\nexport interface Rect {\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n}\n\n/** A value for each side of a box. */\nexport interface Sides {\n readonly top: number;\n readonly right: number;\n readonly bottom: number;\n readonly left: number;\n}\n\n/**\n * A region. The forms and the rules are those of `docs/FORMAT.md` of `packing`.\n * A ring of a polygon closes without a copy of its first point.\n */\nexport type Region =\n | { readonly kind: \"rect\"; readonly x: number; readonly y: number; readonly w: number; readonly h: number }\n | {\n readonly kind: \"polygon\";\n readonly points: readonly (readonly [number, number])[];\n readonly holes?: readonly (readonly (readonly [number, number])[])[];\n }\n | { readonly kind: \"circle\"; readonly cx: number; readonly cy: number; readonly r: number }\n | { readonly kind: \"ellipse\"; readonly cx: number; readonly cy: number; readonly rx: number; readonly ry: number };\n\n/** A margin: one value for the four sides, or one value for each side. */\nexport type Margin = number | Sides;\n\n/** This function gives the value of each side of a margin. No margin gives 0 on each side. */\nexport function marginSides(margin: Margin | undefined): Sides {\n if (margin === undefined) return { top: 0, right: 0, bottom: 0, left: 0 };\n if (typeof margin === \"number\") return { top: margin, right: margin, bottom: margin, left: margin };\n return margin;\n}\n\n/** This function gives the rectangle made larger by the margin on each side. */\nexport function grow(rect: Rect, margin: Margin | undefined): Rect {\n const m = marginSides(margin);\n return { x: rect.x - m.left, y: rect.y - m.top, w: rect.w + m.left + m.right, h: rect.h + m.top + m.bottom };\n}\n\n/** This function gives the bounding box of a region. */\nexport function boundsOf(region: Region): Rect {\n switch (region.kind) {\n case \"rect\":\n return { x: region.x, y: region.y, w: region.w, h: region.h };\n case \"circle\":\n return { x: region.cx - region.r, y: region.cy - region.r, w: 2 * region.r, h: 2 * region.r };\n case \"ellipse\":\n return { x: region.cx - region.rx, y: region.cy - region.ry, w: 2 * region.rx, h: 2 * region.ry };\n case \"polygon\": {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n for (const [x, y] of region.points) {\n x0 = Math.min(x0, x);\n y0 = Math.min(y0, y);\n x1 = Math.max(x1, x);\n y1 = Math.max(y1, y);\n }\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n }\n }\n}\n\n/** This function gives the region moved by `dx` and `dy`. */\nexport function translate(region: Region, dx: number, dy: number): Region {\n switch (region.kind) {\n case \"rect\":\n return { ...region, x: region.x + dx, y: region.y + dy };\n case \"circle\":\n case \"ellipse\":\n return { ...region, cx: region.cx + dx, cy: region.cy + dy };\n case \"polygon\": {\n const move = (ring: readonly (readonly [number, number])[]): [number, number][] => ring.map(([x, y]) => [x + dx, y + dy]);\n return region.holes === undefined\n ? { kind: \"polygon\", points: move(region.points) }\n : { kind: \"polygon\", points: move(region.points), holes: region.holes.map(move) };\n }\n }\n}\n\n/**\n * This function gives the overlap of the insides of two rectangles on each axis.\n * A value of 0 or less on an axis is no overlap. Two rectangles with a common edge have an overlap of 0.\n */\nexport function overlapOf(a: Rect, b: Rect): { readonly x: number; readonly y: number } {\n return {\n x: Math.min(a.x + a.w, b.x + b.w) - Math.max(a.x, b.x),\n y: Math.min(a.y + a.h, b.y + b.h) - Math.max(a.y, b.y),\n };\n}\n","/** The epsilon for the float compares in an engine. */\nexport const EPS = 1e-6;\n\n/**\n * The count of grid steps in one unit of a written file. A file rounds each number `v` to `Math.round(v * RECORD_SCALE) / RECORD_SCALE`.\n * Use a multiplication by this value, not a division by `RECORD_EPS`. The two differ at some half steps.\n */\nexport const RECORD_SCALE = 1000;\n\n/**\n * The epsilon for the float compares on a written file. A file rounds each number to 3 decimals,\n * so a difference of two values can move by up to 0.001. It is `1 / RECORD_SCALE`.\n */\nexport const RECORD_EPS = 1e-3;\n\n/**\n * The tolerance of each hard rule, in layout units. A record writes the tolerance that its run used,\n * in its field `tolerance`, next to `hard`.\n */\nexport interface Tolerance {\n /** Two boxes with their margins break `no-overlap` when their insides overlap by more than this on each axis. */\n readonly overlap: number;\n /** A route breaks `no-pass-through` when a part longer than this is inside a box made this much smaller. */\n readonly through: number;\n}\n\n/**\n * The default tolerance of each rule. The packer is exact, so `overlap` is one unit of the rounding.\n * Routes are sampled curves that follow the margin line, so `through` is larger.\n */\nexport const DEFAULT_TOLERANCE: Tolerance = Object.freeze({ overlap: 0.001, through: 0.5 });\n","import type { Margin, Region, Side } from \"./geometry.ts\";\n\n/**\n * A port of a box: a place where edges go into the box.\n * With `x` and `y`, the port is fixed on the border of the box, relative to its top-left corner.\n * Without them, the router places the port on its `side`. Without a side, the router picks the side.\n */\nexport interface Port {\n readonly id: string;\n readonly side?: Side;\n readonly x?: number;\n readonly y?: number;\n}\n\n/** A box of an input. In the packer, its name is item. */\nexport interface LayoutBox {\n readonly id: string;\n readonly w: number;\n readonly h: number;\n /** The packer writes the position. The router reads it. */\n readonly x?: number;\n readonly y?: number;\n /** A locked box keeps `x` and `y`. The packer reads it as an obstacle. */\n readonly locked?: boolean;\n /** The reading order. Without it, the order of the array is the rank. */\n readonly rank?: number;\n readonly parent?: string;\n readonly group?: string;\n /** A region relative to the origin of the box. Without it, the box is the rectangle `w` by `h`. */\n readonly shape?: Region;\n readonly ports?: readonly Port[];\n /** A ring around the box. No other box enters it. Only a route from a port of the box enters it, at a right angle. */\n readonly margin?: Margin;\n /** The packer can turn the box by 90 degrees. The output has the turned box and ports. */\n readonly turnable?: boolean;\n /** The free data of the node. The grouping rule `keys` of `highways` reads `data.group`. */\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** The packer name of a box. It is the same type. */\nexport type Item = LayoutBox;\n\n/** An edge between two boxes, with optional ports. */\nexport interface LayoutEdge {\n readonly id: string;\n readonly source: string;\n readonly target: string;\n readonly sourcePort?: string;\n readonly targetPort?: string;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/** The container. `fixed` tells which sides of the size stay. */\nexport interface LayoutContainer {\n readonly w?: number;\n readonly h?: number;\n readonly fixed: \"size\" | \"width\" | \"height\" | \"none\";\n /** The target aspect: the width divided by the height. The default is 1. */\n readonly aspect?: number;\n /** The weight of the aspect error in the objective. 0 gives the least area. The default is 1. */\n readonly aspectWeight?: number;\n /** The shape. Without it, the container is the rectangle from 0, 0 to `w`, `h`. */\n readonly shape?: Region;\n /** The space between the border and the boxes with their margins. */\n readonly inset?: number;\n}\n\n/** An area that boxes and routes avoid. Without `move`, it stays. With `move`, the packer can move it for `cost` times the distance. */\nexport interface Obstacle {\n readonly id: string;\n readonly region: Region;\n readonly move?: { readonly cost: number };\n}\n\n/** The generator of an input. The same name, version, parameters and seed give the same file, byte for byte. */\nexport interface LayoutGenerator {\n readonly name: string;\n readonly version: number;\n readonly params: Readonly<Record<string, unknown>>;\n readonly seed: number;\n}\n\n/** The cell of an input in the taxonomy: one value for each dimension. The dimensions are in `docs/FORMAT.md` of `packing`. */\nexport interface LayoutCell {\n readonly containerSize?: \"fixed\" | \"freeHeight\" | \"freeWidth\" | \"freeAspect\" | \"freeArea\";\n readonly containerShape?: \"rect\" | \"convex\" | \"polygon\" | \"circle\" | \"ellipse\" | \"holes\";\n readonly obstacles?: \"none\" | \"center\" | \"scattered\" | \"wall\" | \"corridors\" | \"touching\" | \"edge\";\n readonly sizes?: \"identical\" | \"uniform\" | \"heavyTail\" | \"bimodal\" | \"extremeAspect\" | \"nearIdentical\";\n readonly count?: \"1\" | \"10\" | \"100\" | \"1k\" | \"10k\";\n readonly mode?: \"offline\" | \"online\" | \"incremental\";\n readonly edgeDensity?: \"sparse\" | \"medium\" | \"dense\";\n readonly edgeShape?: \"random\" | \"clustered\" | \"hubChain\" | \"longRange\" | \"tree\" | \"bundled\";\n readonly groups?: \"none\" | \"flat\" | \"nested\";\n readonly ports?: \"free\" | \"sides\" | \"fixed\";\n}\n\n/** An input of the corpus: the format `layout-input/1`. */\nexport interface LayoutInput {\n readonly schema: \"layout-input/1\";\n readonly id: string;\n readonly set?: string;\n readonly family?: string;\n readonly seed?: number;\n /** The origin: `made-up`, `published:<set>` or `known-best:<construction>`. */\n readonly source?: string;\n /** The first 16 hex characters of the SHA-256 of the canonical file without this field. */\n readonly hash?: string;\n /** The generator of the input. `null` or no value tells that a person made the input. */\n readonly generator?: LayoutGenerator | null;\n /** The steps that changed the input after its generator, in their order. `edgeStep` adds one. */\n readonly steps?: readonly LayoutGenerator[];\n readonly cell?: LayoutCell;\n /** The place of the input in a sequence of changes. */\n readonly step?: number;\n /** A router input can have no container. */\n readonly container?: LayoutContainer;\n /** The free space between two boxes with their margins. Routes use it. */\n readonly gap?: number;\n readonly boxes: readonly LayoutBox[];\n readonly edges?: readonly LayoutEdge[];\n readonly obstacles?: readonly Obstacle[];\n /**\n * A variant names its base input and its change.\n * With `packed`, the variant is the packed output of its base input: the router routes the positions of that pack.\n */\n readonly base?: string;\n readonly change?: \"add\" | \"remove\" | \"resize\" | \"reorder\" | \"packed\";\n}\n\n/** The input of a packer: a `layout-input/1` file without the edges. */\nexport interface PackInput {\n readonly container: LayoutContainer;\n readonly items: readonly Item[];\n readonly obstacles?: readonly Obstacle[];\n readonly gap?: number;\n}\n\n/** This function gives the packer input of a file. An input without a container gets `{ fixed: \"none\" }`, so the packer picks the size. */\nexport function toPackInput(input: LayoutInput): PackInput {\n return {\n container: input.container ?? { fixed: \"none\" },\n items: input.boxes,\n ...(input.obstacles === undefined ? {} : { obstacles: input.obstacles }),\n ...(input.gap === undefined ? {} : { gap: input.gap }),\n };\n}\n","import { SIDES, marginSides, type Margin, type Region, type Side } from \"./geometry.ts\";\nimport type { LayoutBox, Port } from \"./input.ts\";\n\n/*\n * The turn: 90 degrees clockwise, with the y axis down. The turned box has `w` and `h` swapped,\n * and its top-left corner stays at the position of the box. A point (px, py) of a box of height h\n * goes to (h - py, px). Thus the top-left corner goes to the top-right corner, and each side moves\n * one step clockwise: top to right, right to bottom, bottom to left, left to top.\n */\n\n/** This function gives the side after a turn of 90 degrees clockwise. */\nexport function turnSide(side: Side): Side {\n return SIDES[(SIDES.indexOf(side) + 1) % 4]!;\n}\n\n/** This function gives a point of a box of height `h` after the turn. */\nexport function turnPoint(x: number, y: number, h: number): [number, number] {\n return [h - y, x];\n}\n\n/** This function gives a port of a box of height `h` after the turn. Each value of the port turns, also a port with only `x` or only `y`. */\nexport function turnPort(port: Port, h: number): Port {\n const { side, x, y, ...rest } = port;\n return {\n ...rest,\n ...(side === undefined ? {} : { side: turnSide(side) }),\n ...(y === undefined ? {} : { x: h - y }),\n ...(x === undefined ? {} : { y: x }),\n };\n}\n\n/** This function gives a margin after the turn: the value of each side moves one side clockwise. */\nexport function turnMargin(margin: Margin): Margin {\n if (typeof margin === \"number\") return margin;\n const m = marginSides(margin);\n return { top: m.left, right: m.top, bottom: m.right, left: m.bottom };\n}\n\n/** This function gives a region relative to the origin of a box of height `h` after the turn. */\nexport function turnRegion(region: Region, h: number): Region {\n switch (region.kind) {\n case \"rect\":\n return { kind: \"rect\", x: h - region.y - region.h, y: region.x, w: region.h, h: region.w };\n case \"circle\":\n return { ...region, cx: h - region.cy, cy: region.cx };\n case \"ellipse\":\n return { kind: \"ellipse\", cx: h - region.cy, cy: region.cx, rx: region.ry, ry: region.rx };\n case \"polygon\": {\n const turn = (ring: readonly (readonly [number, number])[]): [number, number][] => ring.map(([x, y]) => turnPoint(x, y, h));\n return region.holes === undefined\n ? { kind: \"polygon\", points: turn(region.points) }\n : { kind: \"polygon\", points: turn(region.points), holes: region.holes.map(turn) };\n }\n }\n}\n\n/** This function gives a box after the turn: the size, the ports, the margin and the shape turn. The position stays. */\nexport function turnBox(box: LayoutBox): LayoutBox {\n return {\n ...box,\n w: box.h,\n h: box.w,\n ...(box.ports === undefined ? {} : { ports: box.ports.map((p) => turnPort(p, box.h)) }),\n ...(box.margin === undefined ? {} : { margin: turnMargin(box.margin) }),\n ...(box.shape === undefined ? {} : { shape: turnRegion(box.shape, box.h) }),\n };\n}\n","import { boundsOf, translate } from \"./geometry.ts\";\nimport type { LayoutInput } from \"./input.ts\";\nimport { turnBox } from \"./turn.ts\";\n\n/** The position of one item. `turn` is 90 when the packer turned a turnable item. */\nexport interface Placement {\n readonly id: string;\n readonly x: number;\n readonly y: number;\n readonly turn?: 0 | 90;\n}\n\n/** The facts of one stage of a strategy, for the records and the site. */\nexport interface StageTrace {\n readonly id: string;\n readonly ms?: number;\n readonly measures?: Readonly<Record<string, number>>;\n}\n\n/** The output of a packer. It does not change the input. */\nexport interface PackOutput {\n readonly placements: readonly Placement[];\n /** The ids of the items that the packer did not place. */\n readonly overflow: readonly string[];\n /** The size of the container after the pack. For a free size, the size that the search found. */\n readonly size: { readonly w: number; readonly h: number };\n /** The new top-left corner of the bounding box of each obstacle that moved. */\n readonly moved: readonly { readonly id: string; readonly x: number; readonly y: number }[];\n readonly trace?: readonly StageTrace[];\n}\n\n/**\n * This function gives the input with the output of a packer applied. Each placed box gets its position.\n * A turned box gets its turned size, ports, margin and shape. Each moved obstacle moves.\n * The container gets the size of the output. The router reads this result. It does not read `turn`.\n */\nexport function applyPack(input: LayoutInput, output: PackOutput): LayoutInput {\n const at = new Map(output.placements.map((p) => [p.id, p]));\n const moved = new Map(output.moved.map((m) => [m.id, m]));\n const boxes = input.boxes.map((box) => {\n const p = at.get(box.id);\n if (p === undefined) return box;\n const turned = p.turn === 90 ? turnBox(box) : box;\n return { ...turned, x: p.x, y: p.y };\n });\n const obstacles = input.obstacles?.map((o) => {\n const m = moved.get(o.id);\n if (m === undefined) return o;\n const b = boundsOf(o.region);\n return { ...o, region: translate(o.region, m.x - b.x, m.y - b.y) };\n });\n return {\n ...input,\n container: { ...(input.container ?? { fixed: \"none\" }), w: output.size.w, h: output.size.h },\n boxes,\n ...(obstacles === undefined ? {} : { obstacles }),\n };\n}\n","import type { Tolerance } from \"./tolerance.ts\";\nimport type { LayoutInput } from \"./input.ts\";\n\n/** The stage of a record: the packer, the router, or both together. */\nexport type Stage = \"pack\" | \"route\" | \"joint\";\n\n/** One run of one strategy on one input and seed: the format `layout-record/1`. A run writes one line of JSON Lines. */\nexport interface LayoutRecord {\n readonly schema: \"layout-record/1\";\n readonly stage: Stage;\n readonly step: string;\n readonly strategy: string;\n /** The options in full, with the defaults. */\n readonly options: Readonly<Record<string, unknown>>;\n readonly corpus: string;\n /** The id of the input. */\n readonly input: string;\n /** The `hash` of the input file. */\n readonly inputHash: string;\n readonly set: string;\n readonly seed: number;\n readonly nodes: number;\n readonly edges: number;\n /** The value of each measure, by its name: `pack.*`, `route.*` or `joint.*`. */\n readonly measures: Readonly<Record<string, number>>;\n /** The count of the breaks of each hard rule. A good run has 0 for each rule. */\n readonly hard: Readonly<Record<string, number>>;\n /** The tolerance of each hard rule of the run. */\n readonly tolerance?: Readonly<Partial<Tolerance>>;\n /** `true` when two runs with the same seed give the same positions. */\n readonly deterministic: boolean;\n /** The id of the prediction that was written before the run. */\n readonly prediction?: string;\n /** The median of `msRuns`, or the time of the one run. */\n readonly ms: number;\n /** The time of each timed repeat, in milliseconds. */\n readonly msRuns?: readonly number[];\n /**\n * The first 16 hex characters of the SHA-256 of the canonical output of the stage.\n * The packer hashes its placements by the order of the ids. The router hashes its routes by the order of the edge ids.\n */\n readonly outputHash?: string;\n /** The facts of the computer of the run. */\n readonly env?: RunEnv;\n /** The reason when the strategy did not run, for example an input over its `maxNodes`. Then the record has no measures. */\n readonly skipped?: string;\n readonly commit?: string;\n}\n\n/**\n * The values that a strategy supports, for each dimension of a taxonomy.\n * The dimension names are in `docs/FORMAT.md` of `packing` and `docs/LAYOUT-RECORDS.md` of `highways`.\n */\nexport type Supports = Readonly<Record<string, readonly string[]>>;\n\n/** The facts of the computer of a run. */\nexport interface RunEnv {\n readonly node: string;\n readonly os: string;\n readonly arch: string;\n /** The name of the runner, for example `ubuntu-latest` or `local`. */\n readonly runner: string;\n /** The model of the processor. */\n readonly cpu: string;\n /** The count of the logical processors. */\n readonly cpus: number;\n}\n\n/** The facts of a run that the input does not give. */\nexport type RunFacts = Omit<LayoutRecord, \"schema\" | \"input\" | \"inputHash\" | \"set\" | \"nodes\" | \"edges\">;\n\n/** This function gives the record of a run. The input gives its id, its hash, its set and the counts of the nodes and the edges. */\nexport function toLayoutRecord(input: LayoutInput, run: RunFacts): LayoutRecord {\n return {\n schema: \"layout-record/1\",\n ...run,\n input: input.id,\n inputHash: input.hash ?? \"\",\n set: input.set ?? \"\",\n nodes: input.boxes.length,\n edges: input.edges?.length ?? 0,\n };\n}\n","import { boundsOf, grow, overlapOf, type Rect, type Region } from \"./geometry.ts\";\nimport type { LayoutBox, LayoutInput, Obstacle } from \"./input.ts\";\nimport { applyPack, type PackOutput } from \"./output.ts\";\nimport { DEFAULT_TOLERANCE, EPS, RECORD_EPS } from \"./tolerance.ts\";\n\n/** This function gives the area of a placed box: its shape or its rectangle, at its position. A box without a position gives `undefined`. */\nexport function placedRect(box: LayoutBox): Rect | undefined {\n if (box.x === undefined || box.y === undefined) return undefined;\n if (box.shape === undefined) return { x: box.x, y: box.y, w: box.w, h: box.h };\n const b = boundsOf(box.shape);\n return { x: box.x + b.x, y: box.y + b.y, w: b.w, h: b.h };\n}\n\n/**\n * This function counts the pairs of placed boxes whose insides, with their margins, overlap by more than `tolerance` on each axis.\n * A box with a shape counts as its bounding box. That area is larger, thus the count is safe.\n */\nexport function countOverlaps(boxes: readonly LayoutBox[], tolerance: number = DEFAULT_TOLERANCE.overlap): number {\n const rects: Rect[] = [];\n for (const box of boxes) {\n const r = placedRect(box);\n if (r !== undefined) rects.push(grow(r, box.margin));\n }\n rects.sort((a, b) => a.x - b.x);\n let count = 0;\n for (let i = 0; i < rects.length; i++) {\n const a = rects[i]!;\n for (let j = i + 1; j < rects.length; j++) {\n const b = rects[j]!;\n if (b.x >= a.x + a.w - tolerance) break;\n const o = overlapOf(a, b);\n if (o.x > tolerance && o.y > tolerance) count++;\n }\n }\n return count;\n}\n\n/** The options of the container test of `countOutside` and `packHard`. */\nexport interface ContainerTest {\n /**\n * With `true`, a box of a shaped container with the size `fixed` must stay inside the shape, not only inside its bounding box.\n * The default is `false`. The default changes to `true` at the next breaking version.\n */\n readonly exactContainer?: boolean;\n}\n\n/**\n * This function counts the placed boxes that go out of the container.\n * Each box with its margin must stay inside the container made smaller by `inset`. Only the fixed sides of the size count. A shaped container counts as its bounding box.\n *\n * With `exactContainer`, a box of a shaped container with the size `fixed` also counts when `rectInRegion` tells that it is not inside the shape.\n * For that test, the box grows by `inset` and becomes smaller by `tolerance` on each side. A shaped container with a free side keeps the bounding test only.\n * An input without a container gives 0.\n */\nexport function countOutside(input: LayoutInput, tolerance: number = DEFAULT_TOLERANCE.overlap, options: ContainerTest = {}): number {\n const c = input.container;\n if (c === undefined) return 0;\n const shape = options.exactContainer === true && c.fixed === \"size\" ? c.shape : undefined;\n const area = c.shape === undefined ? { x: 0, y: 0, w: c.w ?? Infinity, h: c.h ?? Infinity } : boundsOf(c.shape);\n const inset = c.inset ?? 0;\n const fixW = c.fixed === \"size\" || c.fixed === \"width\";\n const fixH = c.fixed === \"size\" || c.fixed === \"height\";\n let count = 0;\n for (const box of input.boxes) {\n const r0 = placedRect(box);\n if (r0 === undefined) continue;\n const r = grow(r0, box.margin);\n const outX = r.x < area.x + inset - tolerance || r.x + r.w > area.x + area.w - inset + tolerance;\n const outY = r.y < area.y + inset - tolerance || r.y + r.h > area.y + area.h - inset + tolerance;\n if ((fixW && outX) || (fixH && outY)) count++;\n else if (shape !== undefined && !rectInRegion(shape, shrink(grow(r, inset), tolerance))) count++;\n }\n return count;\n}\n\n/** This function counts the fixed ports that are not on the border of their box, with the epsilon of a written file. A port without a side does not count. */\nexport function countPortsOffBorder(boxes: readonly LayoutBox[], eps: number = RECORD_EPS): number {\n let count = 0;\n for (const box of boxes) {\n for (const p of box.ports ?? []) {\n if (p.x === undefined || p.y === undefined || p.side === undefined) continue;\n const along = p.side === \"top\" || p.side === \"bottom\" ? p.x : p.y;\n const length = p.side === \"top\" || p.side === \"bottom\" ? box.w : box.h;\n const across = { top: p.y, bottom: p.y - box.h, left: p.x, right: p.x - box.w }[p.side];\n if (Math.abs(across) > eps || along < -eps || along > length + eps) count++;\n }\n }\n return count;\n}\n\n/** The count of the breaks of each hard rule of a pack. */\nexport interface PackHard {\n readonly \"no-overlap\": number;\n readonly \"in-container\": number;\n readonly \"locked-kept\": number;\n readonly complete: number;\n}\n\n/** This function tells if the inside of `region` and the inside of `rect` have a common point. */\nexport function regionHitsRect(region: Region, rect: Rect): boolean {\n if (rect.w <= 0 || rect.h <= 0) return false;\n switch (region.kind) {\n case \"rect\": {\n const o = overlapOf(region, rect);\n return o.x > 0 && o.y > 0;\n }\n case \"circle\":\n return circleHitsRect(region.cx, region.cy, region.r, region.r, rect);\n case \"ellipse\":\n return circleHitsRect(region.cx, region.cy, region.rx, region.ry, rect);\n case \"polygon\": {\n const rings = [region.points, ...(region.holes ?? [])];\n const inside = (x: number, y: number): boolean => x > rect.x && x < rect.x + rect.w && y > rect.y && y < rect.y + rect.h;\n if (region.points.some(([x, y]) => inside(x, y))) return true;\n for (const ring of rings) {\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!;\n const b = ring[(i + 1) % ring.length]!;\n const m = clipMid(a[0], a[1], b[0], b[1], rect);\n if (m !== undefined && inside(m[0], m[1])) return true;\n }\n }\n return pointInRings(rect.x + rect.w / 2, rect.y + rect.h / 2, rings);\n }\n }\n}\n\n/**\n * This function tells if all of `rect` is inside `region`. A point on the border counts as inside. No part of `rect` can overlap a hole.\n * The test of a circle, an ellipse or a polygon accepts an error of `EPS` on the border. A polygon can be concave.\n */\nexport function rectInRegion(region: Region, rect: Rect): boolean {\n const x1 = rect.x + rect.w;\n const y1 = rect.y + rect.h;\n const corners: readonly (readonly [number, number])[] = [\n [rect.x, rect.y],\n [x1, rect.y],\n [x1, y1],\n [rect.x, y1],\n ];\n switch (region.kind) {\n case \"rect\":\n return rect.x >= region.x && rect.y >= region.y && x1 <= region.x + region.w && y1 <= region.y + region.h;\n case \"circle\":\n return corners.every(([x, y]) => inEllipse(region.cx, region.cy, region.r, region.r, x, y));\n case \"ellipse\":\n return corners.every(([x, y]) => inEllipse(region.cx, region.cy, region.rx, region.ry, x, y));\n case \"polygon\": {\n const ring = region.points;\n if (ring.length < 3) return false;\n const points = [...corners, [rect.x + rect.w / 2, rect.y + rect.h / 2] as const];\n if (!points.every(([x, y]) => onRing(x, y, ring) || pointInRings(x, y, [ring]))) return false;\n const deep = (x: number, y: number): boolean => x > rect.x + EPS && x < x1 - EPS && y > rect.y + EPS && y < y1 - EPS;\n for (let i = 0; i < ring.length; i++) {\n const a = ring[i]!;\n const b = ring[(i + 1) % ring.length]!;\n const m = clipMid(a[0], a[1], b[0], b[1], rect);\n if (m !== undefined && deep(m[0], m[1])) return false;\n }\n return (region.holes ?? []).every((hole) => !regionHitsRect({ kind: \"polygon\", points: hole }, rect));\n }\n }\n}\n\n/** This function gives the rectangle made smaller by `d` on each side. A side does not become smaller than 0. */\nfunction shrink(r: Rect, d: number): Rect {\n const dx = Math.min(d, r.w / 2);\n const dy = Math.min(d, r.h / 2);\n return { x: r.x + dx, y: r.y + dy, w: r.w - 2 * dx, h: r.h - 2 * dy };\n}\n\n/** This function tells if a point is inside an ellipse or on its border, with an error of `EPS`. */\nfunction inEllipse(cx: number, cy: number, rx: number, ry: number, x: number, y: number): boolean {\n if (rx <= 0 || ry <= 0) return false;\n const u = (x - cx) / rx;\n const v = (y - cy) / ry;\n return u * u + v * v <= 1 + EPS;\n}\n\n/** This function tells if a point is on a ring of a polygon, with an error of `EPS`. */\nfunction onRing(x: number, y: number, ring: readonly (readonly [number, number])[]): boolean {\n for (let i = 0; i < ring.length; i++) {\n const [ax, ay] = ring[i]!;\n const [bx, by] = ring[(i + 1) % ring.length]!;\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((x - ax) * dx + (y - ay) * dy) / len2));\n if (Math.hypot(x - (ax + t * dx), y - (ay + t * dy)) <= EPS) return true;\n }\n return false;\n}\n\n/** An ellipse with the radii `rx` and `ry` scales to a unit circle. The rectangle scales with it. */\nfunction circleHitsRect(cx: number, cy: number, rx: number, ry: number, rect: Rect): boolean {\n if (rx <= 0 || ry <= 0) return false;\n const x0 = (rect.x - cx) / rx;\n const x1 = (rect.x + rect.w - cx) / rx;\n const y0 = (rect.y - cy) / ry;\n const y1 = (rect.y + rect.h - cy) / ry;\n const dx = Math.max(x0, 0, -x1);\n const dy = Math.max(y0, 0, -y1);\n return dx * dx + dy * dy < 1;\n}\n\n/** This function gives the middle of the part of a segment inside a rectangle, or `undefined` when that part is a point or empty. */\nfunction clipMid(ax: number, ay: number, bx: number, by: number, r: Rect): readonly [number, number] | undefined {\n let t0 = 0;\n let t1 = 1;\n const dx = bx - ax;\n const dy = by - ay;\n const edges: readonly (readonly [number, number])[] = [\n [-dx, ax - r.x],\n [dx, r.x + r.w - ax],\n [-dy, ay - r.y],\n [dy, r.y + r.h - ay],\n ];\n for (const [p, q] of edges) {\n if (p === 0) {\n if (q < 0) return undefined;\n } else if (p < 0) {\n t0 = Math.max(t0, q / p);\n } else {\n t1 = Math.min(t1, q / p);\n }\n }\n if (t1 <= t0) return undefined;\n const t = (t0 + t1) / 2;\n return [ax + t * dx, ay + t * dy];\n}\n\n/** The even-odd rule over the outer ring and the holes. */\nfunction pointInRings(x: number, y: number, rings: readonly (readonly (readonly [number, number])[])[]): boolean {\n let inside = false;\n for (const ring of rings) {\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n const [xi, yi] = ring[i]!;\n const [xj, yj] = ring[j]!;\n if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi) inside = !inside;\n }\n }\n return inside;\n}\n\n/**\n * This function counts the pairs of a placed box and an obstacle that overlap by more than `tolerance`.\n * The box counts with its margin. A box with a shape counts as its bounding box.\n */\nexport function countObstacleHits(\n boxes: readonly LayoutBox[],\n obstacles: readonly Obstacle[] | undefined,\n tolerance: number = DEFAULT_TOLERANCE.overlap,\n): number {\n if (obstacles === undefined || obstacles.length === 0) return 0;\n let count = 0;\n for (const box of boxes) {\n const r0 = placedRect(box);\n if (r0 === undefined) continue;\n const r = grow(r0, box.margin);\n const small = { x: r.x + tolerance, y: r.y + tolerance, w: r.w - 2 * tolerance, h: r.h - 2 * tolerance };\n for (const o of obstacles) if (regionHitsRect(o.region, small)) count++;\n }\n return count;\n}\n\n/**\n * This function gives the count of each hard rule of the output of a packer.\n * It applies the output with `applyPack`. Only the placed boxes and the locked boxes count for the overlaps and the container.\n * `no-overlap` counts the pairs of boxes and the pairs of a box and an obstacle.\n * A locked box without a placement, or with a move of more than `RECORD_EPS`, breaks `locked-kept`.\n * A locked box without a position in the input is a bad input, not a break. `checkInput` finds it.\n * Another box without a placement that is not in `overflow` breaks `complete`.\n *\n * `options` goes to `countOutside` for `in-container`.\n */\nexport function packHard(input: LayoutInput, output: PackOutput, tolerance: number = DEFAULT_TOLERANCE.overlap, options: ContainerTest = {}): PackHard {\n const after = applyPack(input, output);\n const placed = new Set(output.placements.map((p) => p.id));\n const out = new Set(output.overflow);\n const was = new Map(input.boxes.map((b) => [b.id, b]));\n let lockedMoved = 0;\n let incomplete = 0;\n const kept: LayoutBox[] = [];\n for (const box of after.boxes) {\n const old = was.get(box.id);\n if (old?.locked === true) {\n if (old.x === undefined || old.y === undefined) continue;\n const moved = Math.abs(old.x - (box.x ?? old.x)) > RECORD_EPS || Math.abs(old.y - (box.y ?? old.y)) > RECORD_EPS;\n if (!placed.has(box.id) || moved) lockedMoved++;\n kept.push(box);\n } else if (placed.has(box.id)) {\n kept.push(box);\n } else if (!out.has(box.id)) {\n incomplete++;\n }\n }\n return {\n \"no-overlap\": countOverlaps(kept, tolerance) + countObstacleHits(kept, after.obstacles, tolerance),\n \"in-container\": countOutside({ ...after, boxes: kept }, tolerance, options),\n \"locked-kept\": lockedMoved,\n complete: incomplete,\n };\n}\n\n/**\n * This function gives the problems of an input file. An empty list tells that the file is good.\n * A problem is a bad input, not a break of a hard rule. Thus an engine refuses the input.\n */\nexport function checkInput(input: LayoutInput): readonly string[] {\n const problems: string[] = [];\n const ids = new Set<string>();\n for (const box of input.boxes) {\n if (ids.has(box.id)) problems.push(`box ${box.id}: the id is not unique`);\n ids.add(box.id);\n if (!(box.w > 0 && box.h > 0 && Number.isFinite(box.w) && Number.isFinite(box.h))) problems.push(`box ${box.id}: the size is not positive and finite`);\n if (box.locked === true && (box.x === undefined || box.y === undefined)) problems.push(`box ${box.id}: a locked box has no position`);\n }\n if (countPortsOffBorder(input.boxes) > 0) problems.push(\"a fixed port is not on the border of its box\");\n for (const edge of input.edges ?? []) {\n if (!ids.has(edge.source) || !ids.has(edge.target)) problems.push(`edge ${edge.id}: a box of the edge is not in the input`);\n }\n return problems;\n}\n","import { RECORD_EPS, RECORD_SCALE } from \"./tolerance.ts\";\n\n/** The direction of a measure: the side of the better values. */\nexport type Direction = \"lower\" | \"higher\";\n\n/**\n * The facts of one measure: its unit, its direction and its range.\n * `floor` and `tol` are the parameters of the floor rule of the promotion rule (`docs/PROMOTION.md` of `highways`).\n * Each engine exports the specs of its own measures. This package exports the specs of the `joint.*` measures.\n */\nexport interface MeasureSpec<Id extends string = string> {\n readonly id: Id;\n readonly unit: string;\n readonly direction: Direction;\n /** The lowest value. */\n readonly min: number;\n /** The highest value. The value `Infinity` tells that the measure has no upper limit. */\n readonly max: number;\n /** The family of the measure in the measure note of its engine. */\n readonly family?: string;\n /** The best value. Without it, the measure has no floor. */\n readonly floor?: number;\n /** The absolute tolerance at the floor. */\n readonly tol?: number;\n /**\n * The smallest change that counts as better or worse. A number is an absolute change. `{ rel }` is a share of the larger of the two values.\n * `docs/JOINT-MEASURES.md` gives the reason of each joint value.\n */\n readonly minEffect?: number | { readonly rel: number };\n /** The role of the measure in the joint selector. */\n readonly role?: \"guard\" | \"change-guard\" | \"diagnostic\" | \"time\";\n}\n\n/** The id of a joint measure. `docs/JOINT-MEASURES.md` gives the definitions. */\nexport type JointMeasureId =\n | \"joint.fill\"\n | \"joint.aspectError\"\n | \"joint.spill\"\n | \"joint.straight.crossings\"\n | \"joint.straight.length\"\n | \"joint.stability.mean\"\n | \"joint.stability.moved\"\n | \"joint.proxy.rank\"\n | \"joint.ms\";\n\n/** The specs of the joint measures, in the order of `docs/JOINT-MEASURES.md`. */\nexport const JOINT_MEASURES: readonly MeasureSpec<JointMeasureId>[] = Object.freeze([\n { id: \"joint.fill\", minEffect: 0.001, unit: \"0 to 1\", direction: \"higher\", min: 0, max: 1, floor: 1, role: \"guard\" },\n { id: \"joint.aspectError\", minEffect: 0.01, unit: \"natural log\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0.01, role: \"guard\" },\n { id: \"joint.spill\", minEffect: 0.001, unit: \"0 to 1\", direction: \"lower\", min: 0, max: 1, floor: 0, tol: 0.001, role: \"guard\" },\n { id: \"joint.straight.crossings\", minEffect: 0, unit: \"count\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0, role: \"guard\" },\n { id: \"joint.straight.length\", minEffect: 0.01, unit: \"S for each edge\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0.01, role: \"guard\" },\n { id: \"joint.stability.mean\", minEffect: 0.005, unit: \"W\", direction: \"lower\", min: 0, max: Infinity, floor: 0, tol: 0.005, role: \"change-guard\" },\n { id: \"joint.stability.moved\", minEffect: 0.02, unit: \"0 to 1\", direction: \"lower\", min: 0, max: 1, floor: 0, tol: 0.02, role: \"change-guard\" },\n { id: \"joint.proxy.rank\", unit: \"-1 to 1\", direction: \"higher\", min: -1, max: 1, role: \"diagnostic\" },\n { id: \"joint.ms\", unit: \"milliseconds\", direction: \"lower\", min: 0, max: Infinity, role: \"time\" },\n] as const);\n\n/** The threshold of `joint.stability.moved`, in widths `W` of the base. */\nexport const JOINT_MOVED_MIN = 0.01;\n\n/** The result of a compare of a candidate with a baseline on one measure. A tie is not better. */\nexport type Verdict = \"better\" | \"worse\" | \"tie\";\n\n/**\n * This function gives the smallest change of a measure that counts between the values `a` and `b`.\n * The value is `max(RECORD_EPS, minEffect)`, or `max(RECORD_EPS, rel * max(|a|, |b|))` for a relative `minEffect`.\n * The larger value makes the threshold the same after a swap of `a` and `b`.\n */\nexport function minEffectOf(spec: Pick<MeasureSpec, \"minEffect\">, a = 0, b = 0): number {\n const m = spec.minEffect ?? 0;\n const t = typeof m === \"number\" ? m : m.rel * Math.max(Math.abs(a), Math.abs(b));\n return Math.max(RECORD_EPS, Number.isFinite(t) ? t : 0);\n}\n\n/** The slack of the threshold in grid steps. It absorbs only the float noise of the threshold, because the change is a whole number. */\nconst STEP_NOISE = 1e-6;\n\n/**\n * This function compares the value `candidate` with the value `baseline` of one measure on one input.\n * The compare uses whole grid steps of `RECORD_EPS`. Thus a live value and its rounded record give the same verdict.\n * A change of at most the threshold of `minEffectOf` in grid steps is a tie. A swap of the two values swaps better and worse.\n * Two equal values are a tie, also two infinite values. A value `NaN` is an error.\n */\nexport function compareMeasure(candidate: number, baseline: number, spec: Pick<MeasureSpec, \"direction\" | \"minEffect\">): Verdict {\n if (Number.isNaN(candidate) || Number.isNaN(baseline)) throw new RangeError(\"compareMeasure: a value is NaN\");\n if (candidate === baseline) return \"tie\";\n const a = Math.round(candidate * RECORD_SCALE);\n const b = Math.round(baseline * RECORD_SCALE);\n let delta: number;\n if (Number.isSafeInteger(a) && Number.isSafeInteger(b)) {\n delta = a - b;\n const m = spec.minEffect ?? 0;\n const t = typeof m === \"number\" ? m * RECORD_SCALE : m.rel * Math.max(Math.abs(a), Math.abs(b));\n if (Math.abs(delta) <= Math.max(1, Number.isFinite(t) ? t : 0) + STEP_NOISE) return \"tie\";\n } else {\n delta = candidate - baseline;\n if (!(Math.abs(delta) > minEffectOf(spec, candidate, baseline))) return \"tie\";\n }\n const better = spec.direction === \"lower\" ? delta < 0 : delta > 0;\n return better ? \"better\" : \"worse\";\n}\n","/** This function gives the UTF-8 bytes of a string. The package has no runtime dependencies, thus it does not use `TextEncoder`. */\nexport function utf8(text: string): number[] {\n const bytes: number[] = [];\n for (const ch of text) {\n const c = ch.codePointAt(0)!;\n if (c < 0x80) bytes.push(c);\n else if (c < 0x800) bytes.push(0xc0 | (c >> 6), 0x80 | (c & 63));\n else if (c < 0x10000) bytes.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63));\n else bytes.push(0xf0 | (c >> 18), 0x80 | ((c >> 12) & 63), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63));\n }\n return bytes;\n}\n","import { utf8 } from \"./utf8.ts\";\n\n/** This function gives a generator of random numbers in [0, 1). It is `mulberry32`, as in `docs/FORMAT.md` of `packing`. */\nexport function mulberry32(seed: number): () => number {\n let s = seed >>> 0;\n return () => {\n s = (s + 0x6d2b79f5) | 0;\n let t = Math.imul(s ^ (s >>> 15), 1 | s);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** This function gives the FNV-1a hash of 32 bits of the UTF-8 bytes of a string. */\nexport function fnv1a32(text: string): number {\n let h = 0x811c9dc5;\n for (const b of utf8(text)) h = Math.imul(h ^ b, 0x01000193) >>> 0;\n return h;\n}\n\n/** This function gives the generator of one step of a seeded generator: `mulberry32(fnv1a32(\"<seed>:<step>\"))`. */\nexport function stepRandom(seed: number, step: string): () => number {\n return mulberry32(fnv1a32(`${seed}:${step}`));\n}\n\n/** This function gives a whole number from `lo` to `hi`, both included. */\nexport function randomInt(r: () => number, lo: number, hi: number): number {\n return lo + Math.floor(r() * (hi - lo + 1));\n}\n","import { SIDES, type Side } from \"./geometry.ts\";\nimport type { LayoutBox, LayoutEdge, LayoutGenerator, LayoutInput, Port } from \"./input.ts\";\nimport { randomInt, stepRandom } from \"./random.ts\";\n\n/**\n * The shape of the edges of `edgeStep`. The values are the cells of `edgeShape`, and `hubs`.\n * `hubs` waits for the next breaking change to become a value of `LayoutCell.edgeShape`.\n */\nexport type EdgeShape = \"random\" | \"clustered\" | \"hubChain\" | \"hubs\" | \"longRange\" | \"tree\" | \"bundled\";\n\n/** The parameters of `edgeStep`. */\nexport interface EdgeStepParams {\n readonly edgeDensity: \"sparse\" | \"medium\" | \"dense\";\n readonly edgeShape: EdgeShape;\n /** The default is `none`. */\n readonly groups?: \"none\" | \"flat\" | \"nested\";\n /** The default is `free`. */\n readonly ports?: \"free\" | \"sides\" | \"fixed\";\n /** The order of the hubs of `hubs` and `tree`: the largest box first, or a random order. The default is `area`. */\n readonly hubBy?: \"area\" | \"random\";\n}\n\n/** The mean count of the edges of each box for each value of `edgeDensity`. */\nexport const EDGE_DENSITY: Readonly<Record<EdgeStepParams[\"edgeDensity\"], number>> = Object.freeze({ sparse: 0.5, medium: 1.5, dense: 4 });\n\n/** The version of `edgeStep`. A change of its output gives a new version. */\nexport const EDGE_STEP_VERSION = 1;\n\nconst CLUSTER = 8;\nconst CHAIN = 32;\nconst INSIDE = 0.85;\nconst FAN_SHARE = 0.6;\nconst FIXED_SHARE = 0.2;\nconst COLLECTIONS = [\"users\", \"orders\", \"items\", \"events\"] as const;\n\nconst round3 = (x: number): number => Math.round(x * 1000) / 1000;\n\n/**\n * This function gives the input with edges, groups and ports from its topology alone: a joint input has no positions before the pack.\n * The random numbers come from the steps `edges` and `ports` of `seed`. The function appends its stamp to `steps`, and removes the old `hash`.\n * The rules of each shape are in `docs/JOINT-CORPUS.md`.\n */\nexport function edgeStep(input: LayoutInput, params: EdgeStepParams, seed: number = input.seed ?? 0): LayoutInput {\n if ((input.edges?.length ?? 0) > 0) throw new RangeError(\"edgeStep: the input has edges already\");\n const full: Required<EdgeStepParams> = { groups: \"none\", ports: \"free\", hubBy: \"area\", ...params };\n const n = input.boxes.length;\n const r = stepRandom(seed, \"edges\");\n\n const perm = input.boxes.map((_, i) => i);\n for (let i = n - 1; i > 0; i--) {\n const j = randomInt(r, 0, i);\n [perm[i], perm[j]] = [perm[j]!, perm[i]!];\n }\n const clusterOf: number[] = new Array<number>(n);\n perm.forEach((box, p) => (clusterOf[box] = Math.floor(p / CLUSTER)));\n const clusters = Math.ceil(n / CLUSTER);\n const members = (c: number): readonly number[] => perm.slice(c * CLUSTER, (c + 1) * CLUSTER);\n const collectionOf =\n full.edgeShape === \"bundled\"\n ? clusterOf.map((c) => `${COLLECTIONS[c % COLLECTIONS.length]!}-${c}`)\n : input.boxes.map(() => COLLECTIONS[randomInt(r, 0, COLLECTIONS.length - 1)]!);\n const area = (i: number): number => input.boxes[i]!.w * input.boxes[i]!.h;\n const rank = full.hubBy === \"area\" ? input.boxes.map((_, i) => i).sort((a, b) => area(b) - area(a) || a - b) : perm;\n\n const pairs: [number, number][] = [];\n const seen = new Set<string>();\n const add = (u: number, v: number): void => {\n const key = u < v ? `${u}-${v}` : `${v}-${u}`;\n if (u === v || seen.has(key)) return;\n seen.add(key);\n pairs.push([u, v]);\n };\n const anyBox = (): number => randomInt(r, 0, n - 1);\n const inCluster = (c: number): number => {\n const m = members(c);\n return m[randomInt(r, 0, m.length - 1)]!;\n };\n const otherCluster = (c: number): number => {\n const o = randomInt(r, 0, clusters - 2);\n return o >= c ? o + 1 : o;\n };\n const target = Math.min(Math.round(n * EDGE_DENSITY[full.edgeDensity]), (n * (n - 1)) / 2);\n const fill = (pick: () => [number, number]): void => {\n for (let tries = 0; pairs.length < target && tries < target * 30; tries++) add(...pick());\n };\n const clustered = (): [number, number] => {\n const u = anyBox();\n return [u, r() < INSIDE ? inCluster(clusterOf[u]!) : anyBox()];\n };\n\n if (n >= 2) {\n switch (full.edgeShape) {\n case \"random\":\n fill(() => [anyBox(), anyBox()]);\n break;\n case \"clustered\":\n fill(clustered);\n break;\n case \"longRange\":\n fill(() => {\n const u = anyBox();\n return [u, clusters > 1 ? inCluster(otherCluster(clusterOf[u]!)) : anyBox()];\n });\n break;\n case \"hubs\":\n fill(() => [anyBox(), rank[Math.floor(n * r() ** 3)]!]);\n break;\n case \"tree\":\n for (let i = 1; i < n; i++) add(rank[randomInt(r, 0, i - 1)]!, rank[i]!);\n break;\n case \"hubChain\": {\n const k = Math.ceil(n / CHAIN);\n const length = Math.ceil(n / k);\n const chains = Array.from({ length: k }, (_, c) => perm.slice(c * length, (c + 1) * length));\n for (const chain of chains) for (let i = 0; i + 1 < chain.length; i++) add(chain[i]!, chain[i + 1]!);\n const skips = Math.max(0, target - pairs.length);\n for (let s = 0; s < skips; s++) {\n const c = k > 1 ? randomInt(r, 0, k - 2) : 0;\n const from = chains[c]!;\n const to = chains[k > 1 ? c + 1 : 0]!;\n const i = randomInt(r, 0, from.length - 1);\n const j = i + Math.floor(from.length / 8) + randomInt(r, 0, Math.floor(from.length / 2));\n if (j < to.length) add(from[i]!, to[j]!);\n }\n break;\n }\n case \"bundled\":\n for (let rounds = 0; pairs.length < target * FAN_SHARE && clusters > 1 && rounds < target; rounds++) {\n const u = anyBox();\n const c = otherCluster(clusterOf[u]!);\n const fan = randomInt(r, 4, 15);\n for (let f = 0; f < fan && pairs.length < target; f++) add(u, inCluster(c));\n }\n fill(clustered);\n break;\n }\n }\n\n const rp = stepRandom(seed, \"ports\");\n const ports: Port[][] = input.boxes.map((b) => [...(b.ports ?? [])]);\n const portOn = (box: LayoutBox, id: string, side: Side, fixed: boolean): Port => {\n if (!fixed) return { id, side };\n const along = round3(rp() * (side === \"top\" || side === \"bottom\" ? box.w : box.h));\n const at = { top: [along, 0], bottom: [along, box.h], left: [0, along], right: [box.w, along] }[side];\n return { id, side, x: at[0]!, y: at[1]! };\n };\n const out = new Set<number>();\n if (full.ports === \"fixed\") {\n input.boxes.forEach((box, i) => {\n if (rp() >= FIXED_SHARE) return;\n const side = SIDES[randomInt(rp, 0, 3)]!;\n ports[i]!.push(portOn(box, \"out\", side, true));\n out.add(i);\n });\n }\n const edges: LayoutEdge[] = pairs.map(([u, v], k) => {\n const id = `e${k}`;\n const s = input.boxes[u]!;\n const t = input.boxes[v]!;\n let ends: { sourcePort?: string; targetPort?: string } = {};\n if (full.ports === \"sides\") {\n ports[u]!.push(portOn(s, `${id}.s`, SIDES[randomInt(rp, 0, 3)]!, false));\n ports[v]!.push(portOn(t, `${id}.t`, SIDES[randomInt(rp, 0, 3)]!, false));\n ends = { sourcePort: `${id}.s`, targetPort: `${id}.t` };\n } else if (out.has(u)) {\n ends = { sourcePort: \"out\" };\n }\n return { id, source: s.id, target: t.id, ...ends, data: { collection: collectionOf[v]! } };\n });\n\n const boxes = input.boxes.map((box, i): LayoutBox => {\n const c = clusterOf[i]!;\n const group = full.groups === \"none\" ? undefined : `g${c}`;\n const path = full.groups === \"nested\" ? `G${Math.floor(c / 4)}/g${c}` : group;\n return {\n ...box,\n ...(group === undefined ? {} : { group, data: { ...box.data, group: path } }),\n ...(ports[i]!.length === 0 ? {} : { ports: ports[i]! }),\n };\n });\n const stamp: LayoutGenerator = { name: \"edges\", version: EDGE_STEP_VERSION, params: { ...full }, seed };\n const { hash: _old, ...rest } = input;\n return { ...rest, boxes, edges, steps: [...(input.steps ?? []), stamp] };\n}\n","import { RECORD_EPS } from \"./tolerance.ts\";\nimport { utf8 } from \"./utf8.ts\";\n\n/** The round constants of SHA-256. */\nconst K: readonly number[] = [\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe,\n 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\n 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n];\n\n/**\n * This function gives the SHA-256 digest of the UTF-8 bytes of a string, as 64 lowercase hex characters.\n * It uses no API of Node or of the browser.\n */\nexport function sha256Hex(text: string): string {\n const bytes = utf8(text);\n const bits = bytes.length * 8;\n const total = Math.ceil((bytes.length + 9) / 64) * 64;\n const data = new Uint8Array(total);\n data.set(bytes);\n data[bytes.length] = 0x80;\n const view = new DataView(data.buffer);\n view.setUint32(total - 8, Math.floor(bits / 0x100000000));\n view.setUint32(total - 4, bits >>> 0);\n const h = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];\n const w = new Uint32Array(64);\n const rotr = (x: number, n: number): number => (x >>> n) | (x << (32 - n));\n for (let off = 0; off < total; off += 64) {\n for (let i = 0; i < 16; i++) w[i] = view.getUint32(off + 4 * i);\n for (let i = 16; i < 64; i++) {\n const a = w[i - 15]!;\n const b = w[i - 2]!;\n const s0 = rotr(a, 7) ^ rotr(a, 18) ^ (a >>> 3);\n const s1 = rotr(b, 17) ^ rotr(b, 19) ^ (b >>> 10);\n w[i] = (w[i - 16]! + s0 + w[i - 7]! + s1) >>> 0;\n }\n let [a, b, c, d, e, f, g, k] = h as [number, number, number, number, number, number, number, number];\n for (let i = 0; i < 64; i++) {\n const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);\n const ch = (e & f) ^ (~e & g);\n const t1 = (k + s1 + ch + K[i]! + w[i]!) >>> 0;\n const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);\n const maj = (a & b) ^ (a & c) ^ (b & c);\n const t2 = (s0 + maj) >>> 0;\n k = g;\n g = f;\n f = e;\n e = (d + t1) >>> 0;\n d = c;\n c = b;\n b = a;\n a = (t1 + t2) >>> 0;\n }\n h[0] = (h[0]! + a) >>> 0;\n h[1] = (h[1]! + b) >>> 0;\n h[2] = (h[2]! + c) >>> 0;\n h[3] = (h[3]! + d) >>> 0;\n h[4] = (h[4]! + e) >>> 0;\n h[5] = (h[5]! + f) >>> 0;\n h[6] = (h[6]! + g) >>> 0;\n h[7] = (h[7]! + k) >>> 0;\n }\n return h.map((x) => x.toString(16).padStart(8, \"0\")).join(\"\");\n}\n\n/**\n * This function gives the canonical form of a value: sorted keys and no whitespace, with the numbers of `JSON.stringify`.\n * A key with the value `undefined` is not in the form. An `undefined` in an array becomes `null`.\n */\nexport function canonicalJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value) ?? \"null\";\n if (Array.isArray(value)) return `[${value.map((v: unknown) => (v === undefined ? \"null\" : canonicalJson(v))).join(\",\")}]`;\n const o = value as Record<string, unknown>;\n const keys = Object.keys(o)\n .filter((k) => o[k] !== undefined)\n .sort();\n return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalJson(o[k])}`).join(\",\")}}`;\n}\n\n/** The options of `outputHash` and `documentHash`. */\nexport interface HashOptions {\n /**\n * The step of the grid of the numbers. The default is `RECORD_EPS`, so a number keeps 3 decimals.\n * The value `0` keeps the exact numbers. A negative value or a value that is not finite causes a `RangeError`.\n */\n readonly grid?: number;\n}\n\n/** This function gives the factor of a grid: `1 / grid`, or `undefined` for the exact numbers. */\nfunction gridFactor(options: HashOptions): number | undefined {\n const grid = options.grid ?? RECORD_EPS;\n if (!Number.isFinite(grid) || grid < 0) throw new RangeError(`The grid ${grid} is not a finite number of 0 or more.`);\n return grid === 0 ? undefined : 1 / grid;\n}\n\n/**\n * This function gives a copy of a value with each number on the grid. The value `-0` becomes `0`.\n * It throws a `RangeError` for a number that is not finite.\n */\nfunction onGrid(value: unknown, path: string, k: number | undefined): unknown {\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new RangeError(`The value has the number ${value} at ${path}. JSON has no form for it.`);\n if (k === undefined) return value;\n const r = Math.round(value * k) / k;\n if (!Number.isFinite(r)) throw new RangeError(`The number at ${path} is too large for the grid.`);\n return r === 0 ? 0 : r;\n }\n if (value === null || typeof value !== \"object\") return value;\n if (Array.isArray(value)) return value.map((v: unknown, i) => onGrid(v, `${path}[${i}]`, k));\n const o = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(o)) out[key] = onGrid(o[key], `${path}.${key}`, k);\n return out;\n}\n\n/**\n * This function gives the hash of an output: the first 16 hex characters of the SHA-256 of its canonical form.\n * Before the canonical form, each number goes to the nearest point of the grid, and `-0` becomes `0`.\n * With the default grid, the rounding is `round3` of `packing`: `Math.round(x * 1000) / 1000`.\n * The function throws a `RangeError` for `NaN` and for an infinite number.\n *\n * The grid can split two outputs. Two numbers near a rounding boundary can go to two different points.\n * The grid can also merge two outputs whose numbers go to the same points. This merge is intentional: it removes the noise of floating-point numbers.\n */\nexport function outputHash(value: unknown, options: HashOptions = {}): string {\n return sha256Hex(canonicalJson(onGrid(value, \"$\", gridFactor(options)))).slice(0, 16);\n}\n\n/**\n * This function gives the hash of a document. It uses the rule of `outputHash`, but the form does not include the field `hash` of the document.\n * With the default grid, it is the input hash of `docs/FORMAT.md` of `packing`.\n */\nexport function documentHash(doc: object, options: HashOptions = {}): string {\n const { hash: _hash, ...rest } = doc as { readonly hash?: unknown };\n return outputHash(rest, options);\n}\n\n/** One output group: the candidates with the same output hash on each decision input. */\nexport interface OutputGroup {\n /** The id of the group: its first member. */\n readonly id: string;\n /** The ids of the candidates of the group, in sorted order. */\n readonly members: readonly string[];\n}\n\n/**\n * This function gives the output groups of the candidates. The key of `hashes` is the id of a candidate.\n * Its value is the list of the output hashes of the candidate, in the order of the decision inputs.\n * Candidates with equal lists make one group. The groups are in the order of their ids.\n * The function throws a `RangeError` when two lists have different lengths.\n */\nexport function outputGroups(hashes: Readonly<Record<string, readonly string[]>>): OutputGroup[] {\n const byList = new Map<string, string[]>();\n let first: string | undefined;\n for (const id of Object.keys(hashes)) {\n const list = hashes[id]!;\n if (first === undefined) first = id;\n else if (list.length !== hashes[first]!.length)\n throw new RangeError(`The candidate \"${id}\" has ${list.length} hashes, but \"${first}\" has ${hashes[first]!.length}.`);\n const key = JSON.stringify(list);\n const members = byList.get(key);\n if (members) members.push(id);\n else byList.set(key, [id]);\n }\n const groups = [...byList.values()].map((members): OutputGroup => {\n const sorted = [...members].sort();\n return { id: sorted[0]!, members: sorted };\n });\n return groups.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));\n}\n\n/** The evidence that a candidate is exercised on its decision inputs. */\nexport interface ExerciseEvidence {\n /** The move counts of the candidate, by name. A record keeps each one as the trace measure `move.<name>`. */\n readonly moves?: Readonly<Record<string, number>>;\n /** The output hashes of the candidate, in the order of the decision inputs. */\n readonly hashes?: readonly string[];\n /** The output hashes of the base of the candidate, in the same order. */\n readonly baseHashes?: readonly string[];\n}\n\n/**\n * This function tells if a candidate is exercised. It gives `true` when a move count is more than 0.\n * It also gives `true` when `hashes` and `baseHashes` are different at one place or more.\n * Without evidence, it gives `false`.\n * The function throws a `RangeError` when only one of the two lists is given, or when their lengths are different.\n */\nexport function exercised(evidence: ExerciseEvidence): boolean {\n const { moves, hashes, baseHashes } = evidence;\n if ((hashes === undefined) !== (baseHashes === undefined)) throw new RangeError(\"The evidence must have both hashes and baseHashes, or neither of them.\");\n if (hashes && baseHashes && hashes.length !== baseHashes.length)\n throw new RangeError(`The candidate has ${hashes.length} hashes, but its base has ${baseHashes.length}.`);\n if (moves && Object.values(moves).some((n) => n > 0)) return true;\n if (hashes && baseHashes) return hashes.some((h, i) => h !== baseHashes[i]);\n return false;\n}\n","import { outputHash } from \"./hash.ts\";\nimport { compareMeasure, type MeasureSpec } from \"./measures.ts\";\n\n/** The part of a `MeasureSpec` that a pick uses: the direction and the `minEffect`. */\nexport type PickSpec = Pick<MeasureSpec, \"direction\" | \"minEffect\">;\n\n/** A member of a portfolio: a function with an id. A portfolio is also a member. */\nexport interface Member<I, O> {\n readonly id: string;\n /** This function gives the output of the member for an input. */\n run(input: I): O;\n}\n\n/** One level of the key of a portfolio: a measure of an output. */\nexport interface PortfolioLevel<I, O> {\n /** The id of the level. The id `hard` is reserved. */\n readonly id: string;\n readonly spec: PickSpec;\n /** This function gives the value of the measure for the output of a member. The value must be finite. */\n value(input: I, output: O): number;\n}\n\n/** The key of a portfolio: the hard level, then the other levels in order. */\nexport interface PortfolioKey<I, O> {\n /** This function gives the count of hard breaks. It is level 0, with the direction `lower` and the `minEffect` 0. */\n hard(input: I, output: O): number;\n /** The levels after the hard level, in the order of the pick. */\n readonly levels: readonly PortfolioLevel<I, O>[];\n /** This function gives the hash of an output. The default is `outputHash` with the default grid. */\n hash?(output: O): string;\n}\n\n/** The options of a portfolio. */\nexport interface PortfolioOptions {\n /** The time limit in milliseconds, 0 or more. The first member always starts. A member that starts always finishes. */\n readonly budgetMs?: number;\n /** The largest count of members that run, a whole number of 1 or more. The other members are cut. */\n readonly maxMembers?: number;\n /** The clock in milliseconds. The default is `performance.now`, or `Date.now` without `performance`. */\n readonly now?: () => number;\n /**\n * The members that get an output hash. The default `all` hashes each member with the status `ran`. A hash that throws then gives the status `error`.\n * With `pick`, only member 0 and the winner get a hash, and only when the winner is not member 0. Then a hash that throws makes `pick` throw.\n */\n readonly hashes?: \"all\" | \"pick\";\n}\n\n/** The status of a member in a pick. */\nexport type MemberStatus = \"ran\" | \"cut\" | \"error\";\n\n/** The trace of one member in a pick. */\nexport interface MemberTrace {\n readonly id: string;\n readonly status: MemberStatus;\n /** The value of each level, with the key `hard` for the hard level. Only a member with the status `ran` has values. */\n readonly values?: Readonly<Record<string, number>>;\n /** The time of the run of the member, in milliseconds. */\n readonly ms?: number;\n /**\n * The hash of the output of the member. Under the option `hashes` \"all\" (the default), each member with the status `ran` has it.\n * Under `hashes` \"pick\", it is absent, except for member 0 and the winner when the winner is not member 0.\n */\n readonly outputHash?: string;\n /** The message of the error of a member with the status `error`. */\n readonly error?: string;\n}\n\n/** The trace of one pick of a portfolio. */\nexport interface PortfolioTrace {\n /** One entry for each member, in the order of the members. A cut member is also in the list. */\n readonly members: readonly MemberTrace[];\n readonly winner: string;\n /** The index of the winner in the list of the members. */\n readonly winnerIndex: number;\n /** The value `true` tells that the winner is not member 0 and has a different output hash. */\n readonly picked: boolean;\n /** The time of the full pick, in milliseconds. */\n readonly totalMs: number;\n readonly budgetMs?: number;\n readonly maxMembers?: number;\n /** The count of the cut members. */\n readonly cut: number;\n /** The value `false` tells that the time limit cut one member or more. Then a run on a different computer can give a different pick. */\n readonly deterministic: boolean;\n /** The ids of the members that stay in after each level of `selectBest`. The first list is for the hard level. */\n readonly kept: readonly (readonly string[])[];\n}\n\n/** The result of one pick of a portfolio: the output of the winner, its id and the trace. */\nexport interface PortfolioPick<O> {\n readonly output: O;\n readonly winner: string;\n readonly trace: PortfolioTrace;\n}\n\n/** A portfolio: a member that runs its members and gives the output of the best member. */\nexport interface Portfolio<I, O> extends Member<I, O> {\n /** This function starts the members on an input and gives the output of the winner with the trace. */\n pick(input: I): PortfolioPick<O>;\n}\n\n/** A candidate of `selectBest`: an id and the value of each level. */\nexport interface SelectCandidate {\n readonly id: string;\n readonly values: Readonly<Record<string, number>>;\n}\n\n/** A level of `selectBest`: the id of a value and its spec. */\nexport interface SelectLevel {\n readonly id: string;\n readonly spec: PickSpec;\n}\n\n/** The result of `selectBest`. */\nexport interface Selection {\n readonly winner: string;\n /** The ids of the candidates that stay in after each level, in the given order. */\n readonly kept: readonly (readonly string[])[];\n}\n\n/**\n * This function picks the best candidate. For each level, it finds the best value of the candidates that stay in.\n * It keeps each candidate that is not worse than that best value by `compareMeasure`.\n * The winner is the first candidate, in the given order, that stays in after the last level.\n * Without levels, the winner is the first candidate and `kept` is empty.\n *\n * The reason for the rule: a scan that compares each candidate with the current winner is not transitive, because of the `minEffect` ties.\n * Such a scan can drift away from the best value. An example: \"a\" is lower with the `minEffect` 0.005, and \"b\" is higher.\n * The candidates A (0, 1), B (0.004, 2) and C (0.008, 3) give the winner B.\n * The scan picks C, but A is better than C on \"a\".\n *\n * The function throws a `RangeError` for an empty list of candidates, for a missing value, and for a value that is not finite.\n */\nexport function selectBest(candidates: readonly SelectCandidate[], levels: readonly SelectLevel[]): Selection {\n if (candidates.length === 0) throw new RangeError(\"selectBest: the list of candidates is empty.\");\n for (const level of levels) {\n for (const c of candidates) {\n const v = c.values[level.id];\n if (typeof v !== \"number\") throw new RangeError(`selectBest: the candidate \"${c.id}\" has no value for the level \"${level.id}\".`);\n if (!Number.isFinite(v)) throw new RangeError(`selectBest: the candidate \"${c.id}\" has the value ${v} for the level \"${level.id}\".`);\n }\n }\n let alive: readonly SelectCandidate[] = candidates;\n const kept: (readonly string[])[] = [];\n for (const level of levels) {\n const at = (c: SelectCandidate): number => c.values[level.id]!;\n let best = at(alive[0]!);\n for (const c of alive) best = level.spec.direction === \"lower\" ? Math.min(best, at(c)) : Math.max(best, at(c));\n alive = alive.filter((c) => compareMeasure(at(c), best, level.spec) !== \"worse\");\n kept.push(alive.map((c) => c.id));\n }\n return { winner: alive[0]!.id, kept };\n}\n\n/** This function gives the move `pick` of a pick: 1 when `picked` is true, else 0. A record keeps it as the trace measure `move.pick`. */\nexport function pickMoves(trace: Pick<PortfolioTrace, \"picked\">): { pick: number } {\n return { pick: trace.picked ? 1 : 0 };\n}\n\n/** This function gives the default clock: `performance.now`, or `Date.now` without `performance`. */\nfunction defaultClock(): () => number {\n const perf = (globalThis as { readonly performance?: { now(): number } }).performance;\n return perf ? () => perf.now() : () => Date.now();\n}\n\n/** This function gives the message of an error value. */\nfunction messageOf(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** This function throws a `RangeError` for an empty list of members or for two members with the same id. */\nfunction checkMembers(id: string, members: readonly Member<unknown, unknown>[]): void {\n if (members.length === 0) throw new RangeError(`The portfolio \"${id}\" has no members.`);\n const seen = new Set<string>();\n for (const m of members) {\n if (seen.has(m.id)) throw new RangeError(`The portfolio \"${id}\" has two members with the id \"${m.id}\".`);\n seen.add(m.id);\n }\n}\n\n/** The result of the run of one member. */\ntype Ran<O> = { readonly ok: true; readonly output: O; readonly values: Record<string, number>; readonly hash?: string } | { readonly ok: false; readonly error: unknown };\n\n/**\n * This function makes a portfolio. Its `pick` starts the members in their order. `selectBest` picks the winner of the members with the status `ran`.\n * The first level is the hard level, then the levels of the key follow.\n * `members` is a list, or a function of the input that gives the list.\n *\n * A member that throws, or that gives a value that is not finite, gets the status `error`. It does not win.\n * When each member has an error, `pick` throws the error of the first member.\n * `docs/PORTFOLIO.md` tells the rules of the time limit, the trace and `picked`.\n *\n * The function throws a `RangeError` for a level with the id `hard`, for two levels with the same id and for a bad option.\n * It also throws a `RangeError` for an empty list of members, or for two members with the same id.\n */\nexport function portfolio<I, O>(\n id: string,\n members: readonly Member<I, O>[] | ((input: I) => readonly Member<I, O>[]),\n key: PortfolioKey<I, O>,\n options: PortfolioOptions = {},\n): Portfolio<I, O> {\n const levelIds = new Set<string>();\n for (const level of key.levels) {\n if (level.id === \"hard\") throw new RangeError(`The portfolio \"${id}\" has a level with the reserved id \"hard\".`);\n if (levelIds.has(level.id)) throw new RangeError(`The portfolio \"${id}\" has two levels with the id \"${level.id}\".`);\n levelIds.add(level.id);\n }\n const { budgetMs, maxMembers, hashes = \"all\" } = options;\n if (budgetMs !== undefined && !(budgetMs >= 0)) throw new RangeError(`The portfolio \"${id}\" has the budgetMs ${budgetMs}. It must be 0 or more.`);\n if (maxMembers !== undefined && !(Number.isInteger(maxMembers) && maxMembers >= 1))\n throw new RangeError(`The portfolio \"${id}\" has the maxMembers ${maxMembers}. It must be a whole number of 1 or more.`);\n if (hashes !== \"all\" && hashes !== \"pick\") throw new RangeError(`The portfolio \"${id}\" has the hashes ${String(hashes)}. It must be \"all\" or \"pick\".`);\n if (typeof members !== \"function\") checkMembers(id, members);\n const levels: readonly SelectLevel[] = [{ id: \"hard\", spec: { direction: \"lower\", minEffect: 0 } }, ...key.levels.map((l) => ({ id: l.id, spec: l.spec }))];\n const now = options.now ?? defaultClock();\n\n /** This function gives the hash of the output of a member. A hash that throws causes a `RangeError`. */\n const hashOf = (m: Member<I, O>, output: O): string => {\n try {\n return key.hash ? key.hash(output) : outputHash(output);\n } catch (e) {\n throw new RangeError(`The hash of the member \"${m.id}\" of the portfolio \"${id}\" throws: ${messageOf(e)}`, { cause: e });\n }\n };\n\n const evaluate = (m: Member<I, O>, input: I, output: O): Ran<O> => {\n const values: Record<string, number> = {};\n const measure = (level: string, f: () => number): void => {\n let v: number;\n try {\n v = f();\n } catch (e) {\n throw new RangeError(`The level \"${level}\" of the member \"${m.id}\" of the portfolio \"${id}\" throws: ${messageOf(e)}`, { cause: e });\n }\n if (typeof v !== \"number\" || !Number.isFinite(v))\n throw new RangeError(`The member \"${m.id}\" of the portfolio \"${id}\" has the value ${v} for the level \"${level}\".`);\n values[level] = v;\n };\n try {\n measure(\"hard\", () => key.hard(input, output));\n for (const level of key.levels) measure(level.id, () => level.value(input, output));\n if (hashes === \"pick\") return { ok: true, output, values };\n return { ok: true, output, values, hash: hashOf(m, output) };\n } catch (e) {\n return { ok: false, error: e };\n }\n };\n\n const pick = (input: I): PortfolioPick<O> => {\n const list = typeof members === \"function\" ? members(input) : members;\n if (typeof members === \"function\") checkMembers(id, list);\n const start = now();\n const traces: MemberTrace[] = [];\n const outputs = new Map<string, O>();\n const ran: SelectCandidate[] = [];\n let firstError: { readonly error: unknown } | undefined;\n let cut = 0;\n let outOfTime = false;\n for (let i = 0; i < list.length; i++) {\n const m = list[i]!;\n if (maxMembers !== undefined && i >= maxMembers) {\n traces.push({ id: m.id, status: \"cut\" });\n cut++;\n continue;\n }\n if (i > 0 && budgetMs !== undefined && (outOfTime || now() - start >= budgetMs)) {\n outOfTime = true;\n traces.push({ id: m.id, status: \"cut\" });\n cut++;\n continue;\n }\n const t0 = now();\n let result: Ran<O>;\n let ms: number;\n try {\n const output = m.run(input);\n ms = now() - t0;\n result = evaluate(m, input, output);\n } catch (e) {\n ms = now() - t0;\n result = { ok: false, error: e };\n }\n if (result.ok) {\n traces.push(\n result.hash === undefined\n ? { id: m.id, status: \"ran\", values: result.values, ms }\n : { id: m.id, status: \"ran\", values: result.values, ms, outputHash: result.hash },\n );\n outputs.set(m.id, result.output);\n ran.push({ id: m.id, values: result.values });\n } else {\n traces.push({ id: m.id, status: \"error\", ms, error: messageOf(result.error) });\n firstError ??= { error: result.error };\n }\n }\n if (ran.length === 0) throw firstError!.error;\n const { winner, kept } = selectBest(ran, levels);\n const winnerIndex = traces.findIndex((t) => t.id === winner);\n if (hashes === \"pick\" && winnerIndex > 0 && traces[0]!.status === \"ran\") {\n // Only member 0 and the winner get a hash. Their two trace entries are new objects with the hash.\n for (const i of [0, winnerIndex]) traces[i] = { ...traces[i]!, outputHash: hashOf(list[i]!, outputs.get(traces[i]!.id)!) };\n }\n const base = traces[0]!;\n const picked = winnerIndex > 0 && (base.status !== \"ran\" || traces[winnerIndex]!.outputHash !== base.outputHash);\n const trace: PortfolioTrace = {\n members: traces,\n winner,\n winnerIndex,\n picked,\n totalMs: now() - start,\n ...(budgetMs !== undefined ? { budgetMs } : {}),\n ...(maxMembers !== undefined ? { maxMembers } : {}),\n cut,\n deterministic: !outOfTime,\n kept,\n };\n return { output: outputs.get(winner)!, winner, trace };\n };\n\n return { id, pick, run: (input: I): O => pick(input).output };\n}\n","// The checks of the claims of a corpus (`docs/CORPUS-CHECKS.md`). The joint corpus, `packing` and `highways` use the same checks.\nimport { canonicalJson, sha256Hex } from \"./hash.ts\";\n\n/** One broken claim of a corpus, with the ids of the inputs that break it. */\nexport interface ClaimBreak {\n /** The name of the claim, for example `declared`, `split` or `index`. */\n readonly claim: string;\n /** The text of the break. */\n readonly detail: string;\n /** The ids of the inputs that break the claim. The list is empty when the break has no input. */\n readonly inputs: readonly string[];\n}\n\n/** The claim `claims.declared` of a manifest: the count of the inputs for each declared property. */\nexport interface DeclaredClaim {\n /** A property with fewer inputs than this count is thin. */\n readonly minCount: number;\n /** The ids of the properties with a count below `minCount`. */\n readonly thin: readonly string[];\n /** The count of the inputs for each property id. */\n readonly counts: Readonly<Record<string, number>>;\n}\n\n/** The hook that gives the ids of the properties that one input declares. */\nexport type Declares<I> = (input: I) => readonly string[];\n\n/**\n * This function gives the count of the inputs for each property id. Each id of `ids` has a count, also when the count is 0.\n * An id from `declares` that is not in `ids` comes after the ids of `ids`, in the order of the first input that declares it.\n */\nexport function declaredCounts<I>(inputs: Iterable<I>, declares: Declares<I>, ids: readonly string[] = []): Record<string, number> {\n const out: Record<string, number> = Object.fromEntries(ids.map((id) => [id, 0]));\n for (const input of inputs) for (const id of declares(input)) out[id] = (out[id] ?? 0) + 1;\n return out;\n}\n\n/** This function tells if a value is a plain object. */\nconst isObject = (value: unknown): value is Record<string, unknown> => value !== null && typeof value === \"object\" && !Array.isArray(value);\n\n/**\n * This function reads the field `claims.declared` of a manifest. A manifest without it gives `undefined`.\n * It throws an `Error` for a claim without a whole `minCount`, a list `thin` of ids and a whole count for each id.\n */\nexport function declaredClaimOf(manifest: object): DeclaredClaim | undefined {\n const claims = (manifest as Record<string, unknown>)[\"claims\"];\n if (claims === undefined) return undefined;\n if (!isObject(claims)) throw new Error(\"The field claims of a corpus file is an object.\");\n const declared = claims[\"declared\"];\n if (declared === undefined) return undefined;\n if (!isObject(declared)) throw new Error(\"The field claims.declared of a corpus file is an object.\");\n const { minCount, thin, counts } = declared;\n if (!Number.isInteger(minCount) || (minCount as number) < 0) throw new Error(\"The field claims.declared.minCount is a whole number of 0 or more.\");\n if (!Array.isArray(thin) || !thin.every((id) => typeof id === \"string\")) throw new Error(\"The field claims.declared.thin is a list of property ids.\");\n if (!isObject(counts) || !Object.values(counts).every((n) => Number.isInteger(n) && (n as number) >= 0)) {\n throw new Error(\"The field claims.declared.counts gives a whole count for each property id.\");\n }\n return { minCount: minCount as number, thin: [...(thin as string[])], counts: { ...(counts as Record<string, number>) } };\n}\n\n/**\n * This function checks the claim `claims.declared` against the inputs. It gives one break `declared` for each problem. An empty list tells that the claim is true.\n *\n * - `ids` are the property ids. The default is the ids of `claim.counts`.\n * - Each id of `ids` has a count in `claim.counts`, and `claim.counts` has no other id. Each count is the count of the inputs.\n * - An id with a count below `minCount` is in `thin`. Each id of `thin` is an id of `ids`.\n * - Each id that `declares` gives is an id of `ids`.\n */\nexport function checkDeclared<I>(inputs: Iterable<I>, declares: Declares<I>, claim: DeclaredClaim, ids: readonly string[] = Object.keys(claim.counts)): ClaimBreak[] {\n const computed = declaredCounts(inputs, declares, ids);\n const out: string[] = [];\n for (const id of ids) {\n if (!(id in claim.counts)) out.push(`the property \"${id}\" has no count`);\n else if (claim.counts[id] !== computed[id]) out.push(`the property \"${id}\" has the count ${claim.counts[id]}, but the inputs give ${computed[id]}`);\n }\n for (const id of Object.keys(claim.counts)) if (!ids.includes(id)) out.push(`\"${id}\" is not a declared property`);\n for (const id of ids) {\n const thin = (computed[id] ?? 0) < claim.minCount;\n if (thin && !claim.thin.includes(id)) out.push(`the property \"${id}\" has ${computed[id]} inputs, below minCount ${claim.minCount}, and it is not in thin`);\n }\n for (const id of claim.thin) if (!ids.includes(id)) out.push(`\"${id}\" of thin is not a declared property`);\n for (const id of Object.keys(computed)) if (!ids.includes(id)) out.push(`${computed[id]} inputs declare \"${id}\", which is not a declared property`);\n return out.map((detail) => ({ claim: \"declared\", detail, inputs: [] }));\n}\n\n/** The id and the hash of one input of a corpus. */\nexport interface CorpusEntry {\n readonly id: string;\n readonly hash: string;\n}\n\n/**\n * This function gives the hash of a corpus: the first 16 hex characters of a SHA-256. The text of the SHA-256 is `canonicalJson`\n * of the corpus id and the `[id, hash]` of each input, in the order of the manifest. A change of one input changes the hash.\n */\nexport function corpusHashOf(corpus: string, inputs: readonly CorpusEntry[]): string {\n return sha256Hex(canonicalJson({ corpus, inputs: inputs.map((i) => [i.id, i.hash]) })).slice(0, 16);\n}\n\n/** The schema of a split file. */\nexport const SPLIT_SCHEMA = \"corpus-split/1\";\n\n/** One fold of a split: the seeds that fit a selector and the seeds that score it. */\nexport interface SplitFold {\n readonly train: readonly number[];\n readonly heldOut: readonly number[];\n}\n\n/** A split file `corpus-split/1`. Its name is `<corpus id>.<corpus hash>.json`. It is beside the corpus, so the corpus does not change. */\nexport interface CorpusSplit {\n readonly schema: typeof SPLIT_SCHEMA;\n readonly corpus: string;\n /** The hash of the corpus: `corpusHashOf` of its manifest. */\n readonly corpusHash: string;\n /** The splits by name. Each split has one fold or more. */\n readonly splits: Readonly<Record<string, { readonly folds: readonly SplitFold[] }>>;\n}\n\n/** The fields of a manifest that the split check reads. */\nexport interface SplitCorpus {\n readonly corpus: string;\n readonly specs: readonly { readonly seeds: readonly number[] }[];\n readonly inputs: readonly CorpusEntry[];\n}\n\n/** This function gives the name of the split file of a corpus. */\nexport function splitFileName(corpus: string, hash: string): string {\n return `${corpus}.${hash}.json`;\n}\n\n/** This function tells if a value is a list of whole numbers. */\nconst isSeeds = (value: unknown): value is number[] => Array.isArray(value) && value.every((s) => Number.isInteger(s));\n\n/**\n * This function checks a split file against a manifest. It gives one break `split` for each problem. An empty list tells that the file is good.\n *\n * - The schema is `corpus-split/1`, the corpus is the id of the manifest and `corpusHash` is `corpusHashOf` of the manifest.\n * - Each split has one fold or more. In each fold, `train` and `heldOut` are lists of seeds, not empty and with no common seed.\n * - Each seed is a seed of a spec of the manifest.\n * - With `name`, the file has the split `name`.\n */\nexport function checkSplit(split: unknown, corpus: SplitCorpus, name?: string): ClaimBreak[] {\n const out: string[] = [];\n const done = (): ClaimBreak[] => out.map((detail) => ({ claim: \"split\", detail, inputs: [] }));\n const f = split as Partial<CorpusSplit> | null;\n if (f === null || typeof f !== \"object\") {\n out.push(\"the split file is not an object\");\n return done();\n }\n if (f.schema !== SPLIT_SCHEMA) out.push(`the schema is ${String(f.schema)}, not ${SPLIT_SCHEMA}`);\n if (f.corpus !== corpus.corpus) out.push(`the corpus is ${String(f.corpus)}, not ${corpus.corpus}`);\n const hash = corpusHashOf(corpus.corpus, corpus.inputs);\n if (f.corpusHash !== hash) out.push(`the corpusHash is ${String(f.corpusHash)}, but the corpus gives ${hash}`);\n const seeds = new Set(corpus.specs.flatMap((s) => s.seeds));\n if (f.splits === null || typeof f.splits !== \"object\") {\n out.push(\"the field splits is not an object\");\n return done();\n }\n for (const [key, value] of Object.entries(f.splits)) {\n const folds = (value as { folds?: unknown } | null)?.folds;\n if (!Array.isArray(folds) || folds.length === 0) {\n out.push(`the split ${key} has no folds`);\n continue;\n }\n folds.forEach((fold: Partial<SplitFold> | null, k) => {\n const at = `the fold ${k} of the split ${key}`;\n const { train, heldOut } = fold ?? {};\n if (!isSeeds(train) || train.length === 0) out.push(`${at} has no train seeds`);\n if (!isSeeds(heldOut) || heldOut.length === 0) out.push(`${at} has no heldOut seeds`);\n if (!isSeeds(train) || !isSeeds(heldOut)) return;\n const common = train.filter((s) => heldOut.includes(s));\n if (common.length > 0) out.push(`${at} has the seeds ${common.join(\", \")} in train and in heldOut`);\n const unknown = [...train, ...heldOut].filter((s) => !seeds.has(s));\n if (unknown.length > 0) out.push(`${at} has the seeds ${unknown.join(\", \")}, which are not in the corpus`);\n });\n }\n if (name !== undefined && !Object.hasOwn(f.splits, name)) out.push(`the split file has no split ${name}. Its splits are ${Object.keys(f.splits).join(\", \")}`);\n return done();\n}\n\n/**\n * This function gives a copy of the folds of the split `name` of a split file. `where` names the file in the text of an error.\n * It throws an `Error` for each problem of `checkSplit`, and then for an unknown split name.\n */\nexport function splitFolds(split: unknown, corpus: SplitCorpus, name: string, where: string = \"The split file\"): SplitFold[] {\n const breaks = checkSplit(split, corpus);\n if (breaks.length > 0) throw new Error(`${where} is not good: ${breaks.map((b) => b.detail).join(\"; \")}.`);\n const splits = (split as CorpusSplit).splits;\n const found = Object.hasOwn(splits, name) ? splits[name] : undefined;\n if (found === undefined) throw new Error(`${where} has no split ${name}. Its splits are ${Object.keys(splits).join(\", \")}.`);\n return found.folds.map((f) => ({ train: [...f.train], heldOut: [...f.heldOut] }));\n}\n\n/** This function gives the folds that hold out one seed each, in the order of the seeds. Each fold trains on the other seeds. */\nexport function leaveOneSeedOut(seeds: readonly number[]): SplitFold[] {\n const sorted = [...new Set(seeds)].sort((a, b) => a - b);\n return sorted.map((s) => ({ train: sorted.filter((t) => t !== s), heldOut: [s] }));\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/layout-contract",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.9",
|
|
5
5
|
"description": "The shared contract of the packing and highways layout engines: the input and record formats, the turn rule, margins, tolerances and hard rules.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"layout",
|
package/src/corpus.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// The checks of the claims of a corpus (`docs/CORPUS-CHECKS.md`). The joint corpus, `packing` and `highways` use the same checks.
|
|
2
|
+
import { canonicalJson, sha256Hex } from "./hash.ts";
|
|
3
|
+
|
|
4
|
+
/** One broken claim of a corpus, with the ids of the inputs that break it. */
|
|
5
|
+
export interface ClaimBreak {
|
|
6
|
+
/** The name of the claim, for example `declared`, `split` or `index`. */
|
|
7
|
+
readonly claim: string;
|
|
8
|
+
/** The text of the break. */
|
|
9
|
+
readonly detail: string;
|
|
10
|
+
/** The ids of the inputs that break the claim. The list is empty when the break has no input. */
|
|
11
|
+
readonly inputs: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** The claim `claims.declared` of a manifest: the count of the inputs for each declared property. */
|
|
15
|
+
export interface DeclaredClaim {
|
|
16
|
+
/** A property with fewer inputs than this count is thin. */
|
|
17
|
+
readonly minCount: number;
|
|
18
|
+
/** The ids of the properties with a count below `minCount`. */
|
|
19
|
+
readonly thin: readonly string[];
|
|
20
|
+
/** The count of the inputs for each property id. */
|
|
21
|
+
readonly counts: Readonly<Record<string, number>>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The hook that gives the ids of the properties that one input declares. */
|
|
25
|
+
export type Declares<I> = (input: I) => readonly string[];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* This function gives the count of the inputs for each property id. Each id of `ids` has a count, also when the count is 0.
|
|
29
|
+
* An id from `declares` that is not in `ids` comes after the ids of `ids`, in the order of the first input that declares it.
|
|
30
|
+
*/
|
|
31
|
+
export function declaredCounts<I>(inputs: Iterable<I>, declares: Declares<I>, ids: readonly string[] = []): Record<string, number> {
|
|
32
|
+
const out: Record<string, number> = Object.fromEntries(ids.map((id) => [id, 0]));
|
|
33
|
+
for (const input of inputs) for (const id of declares(input)) out[id] = (out[id] ?? 0) + 1;
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** This function tells if a value is a plain object. */
|
|
38
|
+
const isObject = (value: unknown): value is Record<string, unknown> => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* This function reads the field `claims.declared` of a manifest. A manifest without it gives `undefined`.
|
|
42
|
+
* It throws an `Error` for a claim without a whole `minCount`, a list `thin` of ids and a whole count for each id.
|
|
43
|
+
*/
|
|
44
|
+
export function declaredClaimOf(manifest: object): DeclaredClaim | undefined {
|
|
45
|
+
const claims = (manifest as Record<string, unknown>)["claims"];
|
|
46
|
+
if (claims === undefined) return undefined;
|
|
47
|
+
if (!isObject(claims)) throw new Error("The field claims of a corpus file is an object.");
|
|
48
|
+
const declared = claims["declared"];
|
|
49
|
+
if (declared === undefined) return undefined;
|
|
50
|
+
if (!isObject(declared)) throw new Error("The field claims.declared of a corpus file is an object.");
|
|
51
|
+
const { minCount, thin, counts } = declared;
|
|
52
|
+
if (!Number.isInteger(minCount) || (minCount as number) < 0) throw new Error("The field claims.declared.minCount is a whole number of 0 or more.");
|
|
53
|
+
if (!Array.isArray(thin) || !thin.every((id) => typeof id === "string")) throw new Error("The field claims.declared.thin is a list of property ids.");
|
|
54
|
+
if (!isObject(counts) || !Object.values(counts).every((n) => Number.isInteger(n) && (n as number) >= 0)) {
|
|
55
|
+
throw new Error("The field claims.declared.counts gives a whole count for each property id.");
|
|
56
|
+
}
|
|
57
|
+
return { minCount: minCount as number, thin: [...(thin as string[])], counts: { ...(counts as Record<string, number>) } };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* This function checks the claim `claims.declared` against the inputs. It gives one break `declared` for each problem. An empty list tells that the claim is true.
|
|
62
|
+
*
|
|
63
|
+
* - `ids` are the property ids. The default is the ids of `claim.counts`.
|
|
64
|
+
* - Each id of `ids` has a count in `claim.counts`, and `claim.counts` has no other id. Each count is the count of the inputs.
|
|
65
|
+
* - An id with a count below `minCount` is in `thin`. Each id of `thin` is an id of `ids`.
|
|
66
|
+
* - Each id that `declares` gives is an id of `ids`.
|
|
67
|
+
*/
|
|
68
|
+
export function checkDeclared<I>(inputs: Iterable<I>, declares: Declares<I>, claim: DeclaredClaim, ids: readonly string[] = Object.keys(claim.counts)): ClaimBreak[] {
|
|
69
|
+
const computed = declaredCounts(inputs, declares, ids);
|
|
70
|
+
const out: string[] = [];
|
|
71
|
+
for (const id of ids) {
|
|
72
|
+
if (!(id in claim.counts)) out.push(`the property "${id}" has no count`);
|
|
73
|
+
else if (claim.counts[id] !== computed[id]) out.push(`the property "${id}" has the count ${claim.counts[id]}, but the inputs give ${computed[id]}`);
|
|
74
|
+
}
|
|
75
|
+
for (const id of Object.keys(claim.counts)) if (!ids.includes(id)) out.push(`"${id}" is not a declared property`);
|
|
76
|
+
for (const id of ids) {
|
|
77
|
+
const thin = (computed[id] ?? 0) < claim.minCount;
|
|
78
|
+
if (thin && !claim.thin.includes(id)) out.push(`the property "${id}" has ${computed[id]} inputs, below minCount ${claim.minCount}, and it is not in thin`);
|
|
79
|
+
}
|
|
80
|
+
for (const id of claim.thin) if (!ids.includes(id)) out.push(`"${id}" of thin is not a declared property`);
|
|
81
|
+
for (const id of Object.keys(computed)) if (!ids.includes(id)) out.push(`${computed[id]} inputs declare "${id}", which is not a declared property`);
|
|
82
|
+
return out.map((detail) => ({ claim: "declared", detail, inputs: [] }));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The id and the hash of one input of a corpus. */
|
|
86
|
+
export interface CorpusEntry {
|
|
87
|
+
readonly id: string;
|
|
88
|
+
readonly hash: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* This function gives the hash of a corpus: the first 16 hex characters of a SHA-256. The text of the SHA-256 is `canonicalJson`
|
|
93
|
+
* of the corpus id and the `[id, hash]` of each input, in the order of the manifest. A change of one input changes the hash.
|
|
94
|
+
*/
|
|
95
|
+
export function corpusHashOf(corpus: string, inputs: readonly CorpusEntry[]): string {
|
|
96
|
+
return sha256Hex(canonicalJson({ corpus, inputs: inputs.map((i) => [i.id, i.hash]) })).slice(0, 16);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The schema of a split file. */
|
|
100
|
+
export const SPLIT_SCHEMA = "corpus-split/1";
|
|
101
|
+
|
|
102
|
+
/** One fold of a split: the seeds that fit a selector and the seeds that score it. */
|
|
103
|
+
export interface SplitFold {
|
|
104
|
+
readonly train: readonly number[];
|
|
105
|
+
readonly heldOut: readonly number[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** A split file `corpus-split/1`. Its name is `<corpus id>.<corpus hash>.json`. It is beside the corpus, so the corpus does not change. */
|
|
109
|
+
export interface CorpusSplit {
|
|
110
|
+
readonly schema: typeof SPLIT_SCHEMA;
|
|
111
|
+
readonly corpus: string;
|
|
112
|
+
/** The hash of the corpus: `corpusHashOf` of its manifest. */
|
|
113
|
+
readonly corpusHash: string;
|
|
114
|
+
/** The splits by name. Each split has one fold or more. */
|
|
115
|
+
readonly splits: Readonly<Record<string, { readonly folds: readonly SplitFold[] }>>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The fields of a manifest that the split check reads. */
|
|
119
|
+
export interface SplitCorpus {
|
|
120
|
+
readonly corpus: string;
|
|
121
|
+
readonly specs: readonly { readonly seeds: readonly number[] }[];
|
|
122
|
+
readonly inputs: readonly CorpusEntry[];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** This function gives the name of the split file of a corpus. */
|
|
126
|
+
export function splitFileName(corpus: string, hash: string): string {
|
|
127
|
+
return `${corpus}.${hash}.json`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** This function tells if a value is a list of whole numbers. */
|
|
131
|
+
const isSeeds = (value: unknown): value is number[] => Array.isArray(value) && value.every((s) => Number.isInteger(s));
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* This function checks a split file against a manifest. It gives one break `split` for each problem. An empty list tells that the file is good.
|
|
135
|
+
*
|
|
136
|
+
* - The schema is `corpus-split/1`, the corpus is the id of the manifest and `corpusHash` is `corpusHashOf` of the manifest.
|
|
137
|
+
* - Each split has one fold or more. In each fold, `train` and `heldOut` are lists of seeds, not empty and with no common seed.
|
|
138
|
+
* - Each seed is a seed of a spec of the manifest.
|
|
139
|
+
* - With `name`, the file has the split `name`.
|
|
140
|
+
*/
|
|
141
|
+
export function checkSplit(split: unknown, corpus: SplitCorpus, name?: string): ClaimBreak[] {
|
|
142
|
+
const out: string[] = [];
|
|
143
|
+
const done = (): ClaimBreak[] => out.map((detail) => ({ claim: "split", detail, inputs: [] }));
|
|
144
|
+
const f = split as Partial<CorpusSplit> | null;
|
|
145
|
+
if (f === null || typeof f !== "object") {
|
|
146
|
+
out.push("the split file is not an object");
|
|
147
|
+
return done();
|
|
148
|
+
}
|
|
149
|
+
if (f.schema !== SPLIT_SCHEMA) out.push(`the schema is ${String(f.schema)}, not ${SPLIT_SCHEMA}`);
|
|
150
|
+
if (f.corpus !== corpus.corpus) out.push(`the corpus is ${String(f.corpus)}, not ${corpus.corpus}`);
|
|
151
|
+
const hash = corpusHashOf(corpus.corpus, corpus.inputs);
|
|
152
|
+
if (f.corpusHash !== hash) out.push(`the corpusHash is ${String(f.corpusHash)}, but the corpus gives ${hash}`);
|
|
153
|
+
const seeds = new Set(corpus.specs.flatMap((s) => s.seeds));
|
|
154
|
+
if (f.splits === null || typeof f.splits !== "object") {
|
|
155
|
+
out.push("the field splits is not an object");
|
|
156
|
+
return done();
|
|
157
|
+
}
|
|
158
|
+
for (const [key, value] of Object.entries(f.splits)) {
|
|
159
|
+
const folds = (value as { folds?: unknown } | null)?.folds;
|
|
160
|
+
if (!Array.isArray(folds) || folds.length === 0) {
|
|
161
|
+
out.push(`the split ${key} has no folds`);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
folds.forEach((fold: Partial<SplitFold> | null, k) => {
|
|
165
|
+
const at = `the fold ${k} of the split ${key}`;
|
|
166
|
+
const { train, heldOut } = fold ?? {};
|
|
167
|
+
if (!isSeeds(train) || train.length === 0) out.push(`${at} has no train seeds`);
|
|
168
|
+
if (!isSeeds(heldOut) || heldOut.length === 0) out.push(`${at} has no heldOut seeds`);
|
|
169
|
+
if (!isSeeds(train) || !isSeeds(heldOut)) return;
|
|
170
|
+
const common = train.filter((s) => heldOut.includes(s));
|
|
171
|
+
if (common.length > 0) out.push(`${at} has the seeds ${common.join(", ")} in train and in heldOut`);
|
|
172
|
+
const unknown = [...train, ...heldOut].filter((s) => !seeds.has(s));
|
|
173
|
+
if (unknown.length > 0) out.push(`${at} has the seeds ${unknown.join(", ")}, which are not in the corpus`);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (name !== undefined && !Object.hasOwn(f.splits, name)) out.push(`the split file has no split ${name}. Its splits are ${Object.keys(f.splits).join(", ")}`);
|
|
177
|
+
return done();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* This function gives a copy of the folds of the split `name` of a split file. `where` names the file in the text of an error.
|
|
182
|
+
* It throws an `Error` for each problem of `checkSplit`, and then for an unknown split name.
|
|
183
|
+
*/
|
|
184
|
+
export function splitFolds(split: unknown, corpus: SplitCorpus, name: string, where: string = "The split file"): SplitFold[] {
|
|
185
|
+
const breaks = checkSplit(split, corpus);
|
|
186
|
+
if (breaks.length > 0) throw new Error(`${where} is not good: ${breaks.map((b) => b.detail).join("; ")}.`);
|
|
187
|
+
const splits = (split as CorpusSplit).splits;
|
|
188
|
+
const found = Object.hasOwn(splits, name) ? splits[name] : undefined;
|
|
189
|
+
if (found === undefined) throw new Error(`${where} has no split ${name}. Its splits are ${Object.keys(splits).join(", ")}.`);
|
|
190
|
+
return found.folds.map((f) => ({ train: [...f.train], heldOut: [...f.heldOut] }));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** This function gives the folds that hold out one seed each, in the order of the seeds. Each fold trains on the other seeds. */
|
|
194
|
+
export function leaveOneSeedOut(seeds: readonly number[]): SplitFold[] {
|
|
195
|
+
const sorted = [...new Set(seeds)].sort((a, b) => a - b);
|
|
196
|
+
return sorted.map((s) => ({ train: sorted.filter((t) => t !== s), heldOut: [s] }));
|
|
197
|
+
}
|
package/src/index.ts
CHANGED