@mark1russell7/layout-contract 0.2.15 → 0.2.16
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 +8 -2
- package/build/index.d.ts +57 -5
- package/build/index.d.ts.map +1 -1
- package/build/index.js +159 -27
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/families.ts +36 -6
- package/src/geometry.ts +28 -0
- package/src/rules.ts +3 -2
- package/src/shapes.ts +76 -8
- package/src/strategy-space.ts +56 -11
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ The package has no runtime dependencies.
|
|
|
8
8
|
|
|
9
9
|
| Part | Exports |
|
|
10
10
|
|---|---|
|
|
11
|
-
| Geometry | `Point`, `Rect`, `Region`, `Side`, `Sides`, `Margin`, `marginSides`, `grow`, `boundsOf`, `translate`, `overlapOf` |
|
|
12
|
-
| The shape kinds | `ShapeKind`, `SHAPE_KINDS`, `SHAPE_KIND_IDS`, `ShapeKindSpec`, `ShapeGeometry`, `DEFAULT_SHAPES`, `ShapeSupport`, `isShapeKind`, `shapeKindOf`, `shapeKindsOf`, `itemShapeOf`, `shapeKindProblem`, `shapesOf`, `checkShapes` |
|
|
11
|
+
| Geometry | `Point`, `Rect`, `Region`, `Side`, `Sides`, `Margin`, `marginSides`, `grow`, `boundsOf`, `regionArea`, `translate`, `overlapOf` |
|
|
12
|
+
| The shape kinds | `ShapeKind`, `SHAPE_KINDS`, `SHAPE_KIND_IDS`, `ShapeKindSpec`, `ShapeGeometry`, `DEFAULT_SHAPES`, `ShapeSupport`, `RuleLevel`, `ShapeCheck`, `isShapeKind`, `shapeKindOf`, `shapeKindsOf`, `itemShapeOf`, `shapeKindProblem`, `shapesOf`, `ruleLevel`, `shapeSupportProblems`, `boxArea`, `checkShapes` |
|
|
13
13
|
| The input `layout-input/1` | `LayoutInput`, `LayoutBox` (`Item` for the packer), `Port`, `portPoint`, `LayoutEdge`, `LayoutContainer`, `Obstacle`, `LayoutCell`, `LayoutGenerator`, `PairGap`, `canonicalInput` |
|
|
14
14
|
| The packer | `PackInput`, `toPackInput`, `Placement`, `PackOutput`, `StageTrace`, `applyPack` |
|
|
15
15
|
| The record `layout-record/1` | `LayoutRecord`, `Stage`, `Supports`, `RunFacts`, `RunEnv`, `toLayoutRecord` |
|
|
@@ -54,6 +54,12 @@ The package has no runtime dependencies.
|
|
|
54
54
|
- **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.
|
|
55
55
|
- **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.
|
|
56
56
|
- **The shape kinds.** An item is a `rect`, a `polygon`, a `circle` or a `free` shape. Each measure and rule declares its kinds. `checkShapes` refuses the other kinds. `docs/SHAPES.md` tells the rules.
|
|
57
|
+
- `regionArea(region)` gives the exact area of a region. `boxArea(box)` gives the exact area of a box, or `undefined` for a `free` box. A box with an ellipse shape is `free`.
|
|
58
|
+
- `ShapeSupport.safe` lists the kinds with a safe count: an upper bound that does not miss a break. `ruleLevel(rule, kind)` gives `exact`, `safe` or `none`.
|
|
59
|
+
- `no-overlap` and `in-container` are safe on `polygon`, `circle` and `free`. `checkShapes` accepts a safe kind only with `{ level: "safe" }`.
|
|
60
|
+
- `shapeSupportProblems(uses)` refuses a kind in `shapes` and in `safe`.
|
|
61
|
+
- `MemberRule.view: "bounds"` gives the members of a meta option the bounding box of each item. A shape filter then checks the members with `rect`.
|
|
62
|
+
- **The corpus dimensions.** `CorpusDimension.precision` is the count of decimal places of a numeric value of a family. The registry rounds the value and the default to it before the `invalidates` compare. `docs/CORPUS.md` tells the rules.
|
|
57
63
|
- **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.
|
|
58
64
|
- **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`.
|
|
59
65
|
- **The verdict.** `verdict` compares two strategies on one measure, with the family as the unit. A verdict counts only when it holds for the mean of the family means and for the mean of the inputs.
|
package/build/index.d.ts
CHANGED
|
@@ -54,6 +54,11 @@ export declare function marginSides(margin: Margin | undefined): Sides;
|
|
|
54
54
|
export declare function grow(rect: Rect, margin: Margin | undefined): Rect;
|
|
55
55
|
/** This function gives the bounding box of a region. */
|
|
56
56
|
export declare function boundsOf(region: Region): Rect;
|
|
57
|
+
/**
|
|
58
|
+
* This function gives the exact area of a region. A `rect` gives `w` by `h`, a circle gives `PI * r * r`, and an ellipse gives `PI * rx * ry`.
|
|
59
|
+
* A polygon gives the absolute value of the shoelace formula, less the area of each hole. A ring with fewer than 3 points has the area 0.
|
|
60
|
+
*/
|
|
61
|
+
export declare function regionArea(region: Region): number;
|
|
57
62
|
/** This function gives the region moved by `dx` and `dy`. */
|
|
58
63
|
export declare function translate(region: Region, dx: number, dy: number): Region;
|
|
59
64
|
/**
|
|
@@ -370,7 +375,7 @@ export type ShapeKind = "rect" | "polygon" | "circle" | "free";
|
|
|
370
375
|
export interface ShapeGeometry {
|
|
371
376
|
/** The bounding box: `boundsOf` and `placedRect`. */
|
|
372
377
|
readonly bounds: boolean;
|
|
373
|
-
/** The area of the shape
|
|
378
|
+
/** The area of the shape: `regionArea` and `boxArea`. */
|
|
374
379
|
readonly area: boolean;
|
|
375
380
|
/** The test that the shape is inside a region: `rectInRegion` for a `rect`. */
|
|
376
381
|
readonly contains: boolean;
|
|
@@ -386,7 +391,10 @@ export interface ShapeKindSpec {
|
|
|
386
391
|
readonly regions: readonly Region["kind"][];
|
|
387
392
|
readonly geometry: ShapeGeometry;
|
|
388
393
|
}
|
|
389
|
-
/**
|
|
394
|
+
/**
|
|
395
|
+
* The declared shape kinds, in their order. Only `rect` has all of its geometry.
|
|
396
|
+
* `polygon` and `circle` have their bounding box and their exact area. `free` has its bounding box only.
|
|
397
|
+
*/
|
|
390
398
|
export declare const SHAPE_KINDS: readonly ShapeKindSpec[];
|
|
391
399
|
/** The ids of `SHAPE_KINDS`, in their order. */
|
|
392
400
|
export declare const SHAPE_KIND_IDS: readonly ShapeKind[];
|
|
@@ -395,8 +403,23 @@ export declare const DEFAULT_SHAPES: readonly ShapeKind[];
|
|
|
395
403
|
/** A measure or a rule, with the shape kinds that it supports. Without `shapes`, it supports `DEFAULT_SHAPES`. */
|
|
396
404
|
export interface ShapeSupport<Id extends string = string> {
|
|
397
405
|
readonly id: Id;
|
|
406
|
+
/** The kinds with an exact count or value. */
|
|
398
407
|
readonly shapes?: readonly ShapeKind[];
|
|
408
|
+
/**
|
|
409
|
+
* The kinds with a safe count: the rule can count a break that is not real, but it does not miss a real break.
|
|
410
|
+
* Thus a safe count of 0 tells that the rule has no break. A kind is in `shapes` or in `safe`, not in the two lists.
|
|
411
|
+
*/
|
|
412
|
+
readonly safe?: readonly ShapeKind[];
|
|
399
413
|
}
|
|
414
|
+
/** The level of a rule on a shape kind: an exact count, a safe count (an upper bound), or no support. */
|
|
415
|
+
export type RuleLevel = "exact" | "safe" | "none";
|
|
416
|
+
/** This function gives the level of a rule on a shape kind. A kind of `shapesOf` is `exact`, a kind of `safe` is `safe`, and another kind is `none`. */
|
|
417
|
+
export declare function ruleLevel(rule: Pick<ShapeSupport, "shapes" | "safe">, kind: ShapeKind): RuleLevel;
|
|
418
|
+
/**
|
|
419
|
+
* This function gives the problems of a list of measures and rules. An empty list tells that the list is good.
|
|
420
|
+
* It refuses an unknown kind, a kind two times in one list, and a kind in `safe` that is also in `shapesOf`.
|
|
421
|
+
*/
|
|
422
|
+
export declare function shapeSupportProblems(uses: readonly ShapeSupport[]): string[];
|
|
400
423
|
/** This function tells if a value is a declared shape kind. */
|
|
401
424
|
export declare function isShapeKind(value: unknown): value is ShapeKind;
|
|
402
425
|
/**
|
|
@@ -404,6 +427,13 @@ export declare function isShapeKind(value: unknown): value is ShapeKind;
|
|
|
404
427
|
* Without it, the kind comes from `shape`: no shape is a `rect`, and an ellipse is `free`.
|
|
405
428
|
*/
|
|
406
429
|
export declare function shapeKindOf(box: LayoutBox): ShapeKind;
|
|
430
|
+
/**
|
|
431
|
+
* This function gives the exact area of a box, or `undefined` when the contract knows only its bounding box.
|
|
432
|
+
* A box with `shape` gives `regionArea` of the shape. A `rect` box without `shape` gives `w` by `h`.
|
|
433
|
+
* A box of the kind `free` gives `undefined`, also with a shape. Thus a box with an ellipse shape gives `undefined`, because `shapeKindOf` makes an ellipse `free`.
|
|
434
|
+
* A box of another kind without `shape` is a bad input, and gives `undefined`.
|
|
435
|
+
*/
|
|
436
|
+
export declare function boxArea(box: LayoutBox): number | undefined;
|
|
407
437
|
/** This function gives the shape kinds of the boxes of an input, in the order of `SHAPE_KINDS`. An input without boxes gives an empty list. */
|
|
408
438
|
export declare function shapeKindsOf(input: Pick<LayoutInput, "boxes">): ShapeKind[];
|
|
409
439
|
/** This function gives the value of the cell dimension `itemShape` of an input: its one kind, `mixed` for more kinds, or `rect` without boxes. */
|
|
@@ -412,11 +442,20 @@ export declare function itemShapeOf(input: Pick<LayoutInput, "boxes">): ShapeKin
|
|
|
412
442
|
export declare function shapeKindProblem(box: LayoutBox): string | undefined;
|
|
413
443
|
/** This function gives the shape kinds that a measure or a rule supports. */
|
|
414
444
|
export declare function shapesOf(use: Pick<ShapeSupport, "shapes">): readonly ShapeKind[];
|
|
445
|
+
/** The options of `checkShapes`. */
|
|
446
|
+
export interface ShapeCheck {
|
|
447
|
+
/**
|
|
448
|
+
* The lowest level of a rule that `checkShapes` accepts. The default `exact` refuses a kind with only a safe count.
|
|
449
|
+
* The value `safe` also accepts a kind of `safe`. Use it only when the run claims that a rule has no break.
|
|
450
|
+
*/
|
|
451
|
+
readonly level?: "exact" | "safe";
|
|
452
|
+
}
|
|
415
453
|
/**
|
|
416
454
|
* This function checks that each measure and each rule of a run supports each shape kind of the input. An empty list tells that the run is good.
|
|
417
455
|
* Each break has the claim `shape`, the id of the input, and the first 5 ids of the boxes of the kind.
|
|
456
|
+
* By default, a kind of `safe` is a break, because the count of the rule is not exact. With the level `safe`, it is not a break.
|
|
418
457
|
*/
|
|
419
|
-
export declare function checkShapes(input: Pick<LayoutInput, "id" | "boxes">, uses: readonly ShapeSupport[]): ClaimBreak[];
|
|
458
|
+
export declare function checkShapes(input: Pick<LayoutInput, "id" | "boxes">, uses: readonly ShapeSupport[], options?: ShapeCheck): ClaimBreak[];
|
|
420
459
|
/** The epsilon for the float compares in an engine. */
|
|
421
460
|
export declare const EPS = 1e-6;
|
|
422
461
|
/**
|
|
@@ -590,6 +629,7 @@ export interface PackHard {
|
|
|
590
629
|
/**
|
|
591
630
|
* The hard rules of a pack, with the shape kinds that each rule supports.
|
|
592
631
|
* `no-overlap` and `in-container` test the bounding box of a shape. That count is exact only for a `rect`.
|
|
632
|
+
* For the other kinds, the count is safe: a shape is inside its bounding box, so the count is an upper bound. A count of 0 tells that the rule has no break.
|
|
593
633
|
* `locked-kept` and `complete` read only the positions and the ids, so they support each kind.
|
|
594
634
|
*/
|
|
595
635
|
export declare const PACK_HARD_RULES: readonly ShapeSupport<keyof PackHard>[];
|
|
@@ -991,6 +1031,11 @@ export interface MemberRule {
|
|
|
991
1031
|
* With `pool`, a config of the option has the members of one entry, and `spaceSize` counts each entry one time.
|
|
992
1032
|
*/
|
|
993
1033
|
readonly pool?: readonly (readonly StrategyConfig[])[];
|
|
1034
|
+
/**
|
|
1035
|
+
* The view of the items that the members get. With `bounds`, the option gives its members the bounding box of each item.
|
|
1036
|
+
* Then a shape filter checks the members with the kind `rect`, and the option itself with the kinds of the input. Without `view`, the members get the kinds of the input.
|
|
1037
|
+
*/
|
|
1038
|
+
readonly view?: "bounds";
|
|
994
1039
|
}
|
|
995
1040
|
/** The inputs that an option supports. A missing field supports each value. */
|
|
996
1041
|
export interface OptionSupports {
|
|
@@ -1102,6 +1147,7 @@ export declare function paramValue(param: SpaceParam, value: ParamValue): ParamV
|
|
|
1102
1147
|
*
|
|
1103
1148
|
* A member list that is not an entry of the `pool` of its option gives the claim `pool`.
|
|
1104
1149
|
* With `shapes`, an option that does not support a kind of the list gives the claim `shape`. A member of a meta option gets the same check.
|
|
1150
|
+
* A member of an option with `view: "bounds"` gets the check with the kind `rect`.
|
|
1105
1151
|
*/
|
|
1106
1152
|
export declare function checkConfig(space: StrategySpace, config: StrategyConfig, options?: ShapeFilter): ClaimBreak[];
|
|
1107
1153
|
/**
|
|
@@ -1316,6 +1362,12 @@ export interface CorpusDimension extends SpaceParam {
|
|
|
1316
1362
|
* Then `generate` of a registry removes these fields from the output, and lists them in `invalidated`.
|
|
1317
1363
|
*/
|
|
1318
1364
|
readonly invalidates?: readonly string[];
|
|
1365
|
+
/**
|
|
1366
|
+
* The count of decimal places that the family uses for a value of a numeric dimension: a whole number of 0 or more.
|
|
1367
|
+
* Only the `invalidates` compare reads it. The registry rounds the value and the default to it before the compare.
|
|
1368
|
+
* The cells, the cell keys, `rngOf` and the value that `generate` gets do not change.
|
|
1369
|
+
*/
|
|
1370
|
+
readonly precision?: number;
|
|
1319
1371
|
}
|
|
1320
1372
|
/**
|
|
1321
1373
|
* The supported values of a dimension (`CorpusDimension.supported`).
|
|
@@ -1446,14 +1498,14 @@ export declare const DEFAULT_FAMILY_BY: FamilyBy;
|
|
|
1446
1498
|
export declare const CORPUS_DIMENSIONS: Readonly<Record<string, CorpusDimension>>;
|
|
1447
1499
|
/**
|
|
1448
1500
|
* This function gives a dimension of `CORPUS_DIMENSIONS`, with the fields of `patch` over it. It throws a `RangeError` for an unknown name.
|
|
1449
|
-
* With `supported` or `
|
|
1501
|
+
* With `supported`, `invalidates` or `precision` in the patch, it also throws a `RangeError` for a bad dimension, as `ownerDimension` does.
|
|
1450
1502
|
*/
|
|
1451
1503
|
export declare function sharedDimension(name: string, patch?: Partial<CorpusDimension>): CorpusDimension;
|
|
1452
1504
|
/** The fields of a dimension that the owner declares: each field of `CorpusDimension` but the name. */
|
|
1453
1505
|
export type OwnerDimensionSpec = Omit<CorpusDimension, "name">;
|
|
1454
1506
|
/**
|
|
1455
1507
|
* This function gives a dimension that only its owner declares, for example `cut` of a family of `packing`.
|
|
1456
|
-
* It throws a `RangeError` for a name of `CORPUS_DIMENSIONS`, the reserved name `kind`, or a bad default, level, `supported` or `
|
|
1508
|
+
* It throws a `RangeError` for a name of `CORPUS_DIMENSIONS`, the reserved name `kind`, or a bad default, level, `supported`, `invalidates` or `precision`.
|
|
1457
1509
|
* The registry examines the `when` of the dimension, because it needs the earlier dimensions.
|
|
1458
1510
|
*/
|
|
1459
1511
|
export declare function ownerDimension(name: string, spec: OwnerDimensionSpec): CorpusDimension;
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/geometry.ts","../src/corpus.ts","../src/input.ts","../src/shapes.ts","../src/tolerance.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/strategy-space.ts","../src/verdict.ts","../src/families.ts"],"mappings":";YACY;;qBAGC,gBAAgB;iBAEZ;WACN;WACA;;;iBAIM;WACN;WACA;WACA;WACA;;;iBAIM;WACN;WACA;WACA;WACA;;;;;;YAOC;WACG;WAAuB;WAAoB;WAAoB;WAAoB;;WAEnF;WACA;WACA;;WAEA;WAAyB;WAAqB;WAAqB;;WACnE;WAA0B;WAAqB;WAAqB;WAAqB;;;YAG5F,kBAAkB;;wBAGd,YAAY,QAAQ,qBAAqB;;wBAOzC,KAAK,MAAM,MAAM,QAAQ,qBAAqB;;wBAM9C,SAAS,QAAQ,SAAS;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/geometry.ts","../src/corpus.ts","../src/input.ts","../src/shapes.ts","../src/tolerance.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/strategy-space.ts","../src/verdict.ts","../src/families.ts"],"mappings":"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"}
|
package/build/index.js
CHANGED
|
@@ -73,6 +73,28 @@ function boundsOf(region) {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* This function gives the exact area of a region. A `rect` gives `w` by `h`, a circle gives `PI * r * r`, and an ellipse gives `PI * rx * ry`.
|
|
78
|
+
* A polygon gives the absolute value of the shoelace formula, less the area of each hole. A ring with fewer than 3 points has the area 0.
|
|
79
|
+
*/
|
|
80
|
+
function regionArea(region) {
|
|
81
|
+
switch (region.kind) {
|
|
82
|
+
case "rect": return region.w * region.h;
|
|
83
|
+
case "circle": return Math.PI * region.r * region.r;
|
|
84
|
+
case "ellipse": return Math.PI * region.rx * region.ry;
|
|
85
|
+
case "polygon": return (region.holes ?? []).reduce((area, hole) => area - ringArea(hole), ringArea(region.points));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** This function gives the area of one ring of a polygon: the absolute value of the shoelace formula. */
|
|
89
|
+
function ringArea(ring) {
|
|
90
|
+
let twice = 0;
|
|
91
|
+
for (let i = 0; i < ring.length; i++) {
|
|
92
|
+
const [ax, ay] = ring[i];
|
|
93
|
+
const [bx, by] = ring[(i + 1) % ring.length];
|
|
94
|
+
twice += ax * by - bx * ay;
|
|
95
|
+
}
|
|
96
|
+
return Math.abs(twice) / 2;
|
|
97
|
+
}
|
|
76
98
|
/** This function gives the region moved by `dx` and `dy`. */
|
|
77
99
|
function translate(region, dx, dy) {
|
|
78
100
|
switch (region.kind) {
|
|
@@ -111,7 +133,10 @@ function overlapOf(a, b) {
|
|
|
111
133
|
};
|
|
112
134
|
}
|
|
113
135
|
// src/shapes.ts
|
|
114
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* The declared shape kinds, in their order. Only `rect` has all of its geometry.
|
|
138
|
+
* `polygon` and `circle` have their bounding box and their exact area. `free` has its bounding box only.
|
|
139
|
+
*/
|
|
115
140
|
const SHAPE_KINDS = Object.freeze([
|
|
116
141
|
{
|
|
117
142
|
id: "rect",
|
|
@@ -130,7 +155,7 @@ const SHAPE_KINDS = Object.freeze([
|
|
|
130
155
|
regions: ["polygon"],
|
|
131
156
|
geometry: {
|
|
132
157
|
bounds: true,
|
|
133
|
-
area:
|
|
158
|
+
area: true,
|
|
134
159
|
contains: false,
|
|
135
160
|
overlap: false
|
|
136
161
|
}
|
|
@@ -145,7 +170,7 @@ const SHAPE_KINDS = Object.freeze([
|
|
|
145
170
|
regions: ["circle"],
|
|
146
171
|
geometry: {
|
|
147
172
|
bounds: true,
|
|
148
|
-
area:
|
|
173
|
+
area: true,
|
|
149
174
|
contains: false,
|
|
150
175
|
overlap: false
|
|
151
176
|
}
|
|
@@ -175,6 +200,35 @@ const SHAPE_KINDS = Object.freeze([
|
|
|
175
200
|
const SHAPE_KIND_IDS = Object.freeze(SHAPE_KINDS.map((k) => k.id));
|
|
176
201
|
/** The shape kinds of a measure or a rule without `shapes`. The contract measured only rectangles before L46. */
|
|
177
202
|
const DEFAULT_SHAPES = Object.freeze(["rect"]);
|
|
203
|
+
/** This function gives the level of a rule on a shape kind. A kind of `shapesOf` is `exact`, a kind of `safe` is `safe`, and another kind is `none`. */
|
|
204
|
+
function ruleLevel(rule, kind) {
|
|
205
|
+
if (shapesOf(rule).includes(kind)) return "exact";
|
|
206
|
+
return rule.safe?.includes(kind) === true ? "safe" : "none";
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* This function gives the problems of a list of measures and rules. An empty list tells that the list is good.
|
|
210
|
+
* It refuses an unknown kind, a kind two times in one list, and a kind in `safe` that is also in `shapesOf`.
|
|
211
|
+
*/
|
|
212
|
+
function shapeSupportProblems(uses) {
|
|
213
|
+
const out = [];
|
|
214
|
+
for (const use of uses) {
|
|
215
|
+
for (const [name, list] of [["shapes", use.shapes], ["safe", use.safe]]) {
|
|
216
|
+
if (list === void 0) continue;
|
|
217
|
+
if (!Array.isArray(list)) {
|
|
218
|
+
out.push(`${use.id}: the ${name} value is not a list of shape kinds`);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
list.forEach((k, i) => {
|
|
222
|
+
if (!isShapeKind(k)) out.push(`${use.id}: the ${name} kind ${String(k)} is not a declared kind`);
|
|
223
|
+
else if (list.indexOf(k) !== i) out.push(`${use.id}: the ${name} list has the kind ${k} two times`);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
if (!Array.isArray(use.safe)) continue;
|
|
227
|
+
const exact = use.shapes === void 0 ? DEFAULT_SHAPES : Array.isArray(use.shapes) ? use.shapes : [];
|
|
228
|
+
for (const k of new Set(use.safe)) if (exact.includes(k)) out.push(`${use.id}: the kind ${String(k)} is in shapes and in safe`);
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
178
232
|
const REGION_KIND = {
|
|
179
233
|
rect: "rect",
|
|
180
234
|
polygon: "polygon",
|
|
@@ -193,6 +247,18 @@ function shapeKindOf(box) {
|
|
|
193
247
|
if (box.shapeKind !== void 0) return box.shapeKind;
|
|
194
248
|
return box.shape === void 0 ? "rect" : REGION_KIND[box.shape.kind];
|
|
195
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* This function gives the exact area of a box, or `undefined` when the contract knows only its bounding box.
|
|
252
|
+
* A box with `shape` gives `regionArea` of the shape. A `rect` box without `shape` gives `w` by `h`.
|
|
253
|
+
* A box of the kind `free` gives `undefined`, also with a shape. Thus a box with an ellipse shape gives `undefined`, because `shapeKindOf` makes an ellipse `free`.
|
|
254
|
+
* A box of another kind without `shape` is a bad input, and gives `undefined`.
|
|
255
|
+
*/
|
|
256
|
+
function boxArea(box) {
|
|
257
|
+
const kind = shapeKindOf(box);
|
|
258
|
+
if (kind === "free") return void 0;
|
|
259
|
+
if (box.shape !== void 0) return regionArea(box.shape);
|
|
260
|
+
return kind === "rect" ? box.w * box.h : void 0;
|
|
261
|
+
}
|
|
196
262
|
/** This function gives the shape kinds of the boxes of an input, in the order of `SHAPE_KINDS`. An input without boxes gives an empty list. */
|
|
197
263
|
function shapeKindsOf(input) {
|
|
198
264
|
const seen = new Set(input.boxes.map(shapeKindOf));
|
|
@@ -219,19 +285,22 @@ function shapesOf(use) {
|
|
|
219
285
|
/**
|
|
220
286
|
* This function checks that each measure and each rule of a run supports each shape kind of the input. An empty list tells that the run is good.
|
|
221
287
|
* Each break has the claim `shape`, the id of the input, and the first 5 ids of the boxes of the kind.
|
|
288
|
+
* By default, a kind of `safe` is a break, because the count of the rule is not exact. With the level `safe`, it is not a break.
|
|
222
289
|
*/
|
|
223
|
-
function checkShapes(input, uses) {
|
|
290
|
+
function checkShapes(input, uses, options = {}) {
|
|
224
291
|
const kinds = shapeKindsOf(input);
|
|
225
292
|
const out = [];
|
|
226
293
|
for (const use of uses) {
|
|
227
294
|
const shapes = shapesOf(use);
|
|
228
295
|
for (const kind of kinds) {
|
|
229
|
-
|
|
296
|
+
const level = ruleLevel(use, kind);
|
|
297
|
+
if (level === "exact" || level === "safe" && options.level === "safe") continue;
|
|
230
298
|
const ids = input.boxes.filter((b) => shapeKindOf(b) === kind).map((b) => b.id);
|
|
231
299
|
const shown = ids.slice(0, 5).join(", ") + (ids.length > 5 ? `, and ${ids.length - 5} more` : "");
|
|
300
|
+
const safe = level === "safe" ? `. The count of ${use.id} on ${kind} is only safe` : "";
|
|
232
301
|
out.push({
|
|
233
302
|
claim: "shape",
|
|
234
|
-
detail: `${use.id} supports only the shape kinds ${shapes.join(", ") || "(none)"}, but the input ${input.id} has ${kind} boxes: ${shown}`,
|
|
303
|
+
detail: `${use.id} supports only the shape kinds ${shapes.join(", ") || "(none)"}, but the input ${input.id} has ${kind} boxes: ${shown}${safe}`,
|
|
235
304
|
inputs: [input.id]
|
|
236
305
|
});
|
|
237
306
|
}
|
|
@@ -585,16 +654,27 @@ function countPortsOffBorder(boxes, eps = RECORD_EPS) {
|
|
|
585
654
|
/**
|
|
586
655
|
* The hard rules of a pack, with the shape kinds that each rule supports.
|
|
587
656
|
* `no-overlap` and `in-container` test the bounding box of a shape. That count is exact only for a `rect`.
|
|
657
|
+
* For the other kinds, the count is safe: a shape is inside its bounding box, so the count is an upper bound. A count of 0 tells that the rule has no break.
|
|
588
658
|
* `locked-kept` and `complete` read only the positions and the ids, so they support each kind.
|
|
589
659
|
*/
|
|
590
660
|
const PACK_HARD_RULES = Object.freeze([
|
|
591
661
|
{
|
|
592
662
|
id: "no-overlap",
|
|
593
|
-
shapes: ["rect"]
|
|
663
|
+
shapes: ["rect"],
|
|
664
|
+
safe: [
|
|
665
|
+
"polygon",
|
|
666
|
+
"circle",
|
|
667
|
+
"free"
|
|
668
|
+
]
|
|
594
669
|
},
|
|
595
670
|
{
|
|
596
671
|
id: "in-container",
|
|
597
|
-
shapes: ["rect"]
|
|
672
|
+
shapes: ["rect"],
|
|
673
|
+
safe: [
|
|
674
|
+
"polygon",
|
|
675
|
+
"circle",
|
|
676
|
+
"free"
|
|
677
|
+
]
|
|
598
678
|
},
|
|
599
679
|
{
|
|
600
680
|
id: "locked-kept",
|
|
@@ -2085,6 +2165,8 @@ function optionProblems(stage, o) {
|
|
|
2085
2165
|
if (!Number.isInteger(min) || !Number.isInteger(max) || min < 1 || min > max || typeof ordered !== "boolean") out.push(["members", `${at} has a member rule without whole counts 1 <= min <= max and a boolean ordered`]);
|
|
2086
2166
|
const pool = o.members.pool;
|
|
2087
2167
|
if (pool !== void 0 && (!Array.isArray(pool) || pool.length === 0 || !pool.every((entry) => Array.isArray(entry)))) out.push(["pool", `${at} has a pool that is not a list of one or more member lists`]);
|
|
2168
|
+
const view = o.members.view;
|
|
2169
|
+
if (view !== void 0 && view !== "bounds") out.push(["view", `${at} has the member view ${show(view)}, not "bounds"`]);
|
|
2088
2170
|
}
|
|
2089
2171
|
return out;
|
|
2090
2172
|
}
|
|
@@ -2103,6 +2185,15 @@ function supportsProblems(supports, at) {
|
|
|
2103
2185
|
}
|
|
2104
2186
|
/** This function tells if an option supports each shape kind of the list. */
|
|
2105
2187
|
const supportsShapes = (o, shapes) => shapes === void 0 || o.supports?.shape === void 0 || shapes.every((k) => o.supports.shape.includes(k));
|
|
2188
|
+
/** The shape kinds that the members of an option with `view: "bounds"` see: a bounding box is a `rect`. */
|
|
2189
|
+
const BOUNDS_VIEW = Object.freeze(["rect"]);
|
|
2190
|
+
/**
|
|
2191
|
+
* This function gives the shape kinds of the members of a meta option. With `view: "bounds"`, a list with a kind becomes `BOUNDS_VIEW`.
|
|
2192
|
+
* Without a list, or with an empty list, the value does not change.
|
|
2193
|
+
*/
|
|
2194
|
+
const memberShapes = (rule, shapes) => rule.view === "bounds" && shapes !== void 0 && shapes.length > 0 ? BOUNDS_VIEW : shapes;
|
|
2195
|
+
/** This function tells if two lists have the same shape kinds. */
|
|
2196
|
+
const sameKinds = (a, b) => a.every((k) => b.includes(k)) && b.every((k) => a.includes(k));
|
|
2106
2197
|
/** This function gives the problems of the params of one stage choice. */
|
|
2107
2198
|
function choiceParamProblems(o, params, at) {
|
|
2108
2199
|
if (params !== void 0 && !isObject(params)) return [["config", `the params of ${at} are not an object`]];
|
|
@@ -2176,7 +2267,7 @@ function configProblems(space, config, member, shapes) {
|
|
|
2176
2267
|
out.push(["depth", `a member has the meta option ${s.name}.${o.id}. The depth of a meta config is 1`]);
|
|
2177
2268
|
continue;
|
|
2178
2269
|
}
|
|
2179
|
-
out.push(...memberProblems(partOf(space, s.name).space, o.members, c["members"], at, shapes));
|
|
2270
|
+
out.push(...memberProblems(partOf(space, s.name).space, o.members, c["members"], at, memberShapes(o.members, shapes)));
|
|
2180
2271
|
}
|
|
2181
2272
|
for (const c of space.constraints ?? []) if (!holds(c, chosen)) out.push(["constraint", `the config breaks the constraint ${describe(c)}`]);
|
|
2182
2273
|
return out;
|
|
@@ -2239,6 +2330,7 @@ const toBreaks = (problems, inputs = []) => problems.map(([claim, detail]) => ({
|
|
|
2239
2330
|
*
|
|
2240
2331
|
* A member list that is not an entry of the `pool` of its option gives the claim `pool`.
|
|
2241
2332
|
* With `shapes`, an option that does not support a kind of the list gives the claim `shape`. A member of a meta option gets the same check.
|
|
2333
|
+
* A member of an option with `view: "bounds"` gets the check with the kind `rect`.
|
|
2242
2334
|
*/
|
|
2243
2335
|
function checkConfig(space, config, options = {}) {
|
|
2244
2336
|
return toBreaks(configProblems(space, config, false, options.shapes));
|
|
@@ -2499,7 +2591,9 @@ function combos(space, levels, meta, limit) {
|
|
|
2499
2591
|
for (const s of stages) for (const o of s.options) {
|
|
2500
2592
|
if (o.members === void 0) continue;
|
|
2501
2593
|
const choices = new Map(stages.map((x) => [x.name, x === s ? o : null]));
|
|
2502
|
-
const
|
|
2594
|
+
const own = memberSpaces.get(o);
|
|
2595
|
+
const from = own === void 0 ? base : baseCount(own, levels, limit);
|
|
2596
|
+
const lists = o.members.pool === void 0 ? memberLists(from, o.members, limit) : BigInt(o.members.pool.length);
|
|
2503
2597
|
if (keeps(space, choices)) out.push({
|
|
2504
2598
|
choices,
|
|
2505
2599
|
base: false,
|
|
@@ -2524,6 +2618,8 @@ function spaceSize(space, options) {
|
|
|
2524
2618
|
* This function gives the space with only the options that support each shape kind of `shapes`. Without `shapes`, it gives the same space.
|
|
2525
2619
|
* A stage can lose all of its options. Then the space has no config with that stage.
|
|
2526
2620
|
* A pool keeps only the entries whose members fit the smaller space. A meta option without such an entry goes out.
|
|
2621
|
+
*
|
|
2622
|
+
* The members of an option with `view: "bounds"` come from the space for the kinds of `memberShapes`. `memberSpaces` keeps that space.
|
|
2527
2623
|
*/
|
|
2528
2624
|
function restrict(space, shapes) {
|
|
2529
2625
|
if (shapes === void 0) return space;
|
|
@@ -2536,16 +2632,23 @@ function restrict(space, shapes) {
|
|
|
2536
2632
|
...space.parts === void 0 ? {} : { parts: space.parts.map((p) => restrict(p, shapes)) }
|
|
2537
2633
|
};
|
|
2538
2634
|
const withPool = (s, o) => {
|
|
2539
|
-
if (o.members
|
|
2540
|
-
const
|
|
2635
|
+
if (o.members === void 0) return [o];
|
|
2636
|
+
const inner = memberShapes(o.members, shapes);
|
|
2637
|
+
const own = sameKinds(inner, shapes) ? void 0 : restrict(partOf(space, s.name).space, inner);
|
|
2638
|
+
const mark = (option) => {
|
|
2639
|
+
if (own !== void 0) memberSpaces.set(option, own);
|
|
2640
|
+
return [option];
|
|
2641
|
+
};
|
|
2642
|
+
if (o.members.pool === void 0) return own === void 0 ? [o] : mark({ ...o });
|
|
2643
|
+
const part = own ?? partOf(kept, s.name).space;
|
|
2541
2644
|
const pool = o.members.pool.filter((entry) => fits(part, entry));
|
|
2542
|
-
return pool.length === 0 ? [] :
|
|
2645
|
+
return pool.length === 0 ? [] : mark({
|
|
2543
2646
|
...o,
|
|
2544
2647
|
members: {
|
|
2545
2648
|
...o.members,
|
|
2546
2649
|
pool
|
|
2547
2650
|
}
|
|
2548
|
-
}
|
|
2651
|
+
});
|
|
2549
2652
|
};
|
|
2550
2653
|
return {
|
|
2551
2654
|
...kept,
|
|
@@ -2555,6 +2658,10 @@ function restrict(space, shapes) {
|
|
|
2555
2658
|
}))
|
|
2556
2659
|
};
|
|
2557
2660
|
}
|
|
2661
|
+
/** The space of the members of a meta option of a restricted space, when it is not the part of the option. Only `view: "bounds"` makes such a space. */
|
|
2662
|
+
const memberSpaces = /* @__PURE__ */ new WeakMap();
|
|
2663
|
+
/** This function gives the count of the base configs of a space that is known to be good. */
|
|
2664
|
+
const baseCount = (space, levels, limit) => combos(space, levels, false, limit).reduce((sum, c) => sum + c.weight, 0n);
|
|
2558
2665
|
/** This function throws a `RangeError` for a list of shape kinds with a kind that is not declared. */
|
|
2559
2666
|
function assertShapes(shapes) {
|
|
2560
2667
|
if (shapes === void 0) return;
|
|
@@ -2631,13 +2738,18 @@ function sampleValue(p, u) {
|
|
|
2631
2738
|
}
|
|
2632
2739
|
/** This function gives a seed of 32 bits from a seed and a step name. */
|
|
2633
2740
|
const subSeed = (seed, step) => Math.floor(stepRandom(seed, step)() * 4294967296);
|
|
2634
|
-
/**
|
|
2635
|
-
function
|
|
2741
|
+
/**
|
|
2742
|
+
* This function gives a sample of a space: Latin hypercube strata over the options, the params and the member counts.
|
|
2743
|
+
* `canon` is the space of `canonicalConfig`: the space before a shape filter. A member of an option with `view: "bounds"` can have an option that the filter removed.
|
|
2744
|
+
*/
|
|
2745
|
+
function sampleConfigs(space, n, seed, meta, maxTries, canon = space) {
|
|
2636
2746
|
const stages = space.stages;
|
|
2637
2747
|
const prefix = prefixes(space);
|
|
2748
|
+
const bounded = new Set(stages.filter((s) => meta && s.options.some((o) => memberSpaces.has(o))).map((s) => prefix.get(s.name)));
|
|
2638
2749
|
const lists = stages.map((s) => {
|
|
2639
2750
|
const list = s.options.filter((o) => meta || o.members === void 0);
|
|
2640
2751
|
if (s.optional) list.push(null);
|
|
2752
|
+
if (list.length === 0 && bounded.has(prefix.get(s.name))) list.push(null);
|
|
2641
2753
|
if (list.length === 0) throw new Error(`The stage ${s.name} of the space ${space.engine} has no option for a sample. A shape filter can remove all of its options.`);
|
|
2642
2754
|
return list;
|
|
2643
2755
|
});
|
|
@@ -2656,7 +2768,7 @@ function sampleConfigs(space, n, seed, meta, maxTries) {
|
|
|
2656
2768
|
const m = metaPart.get(prefix.get(s.name));
|
|
2657
2769
|
if (m !== void 0 && m !== s.name) choices.set(s.name, null);
|
|
2658
2770
|
}
|
|
2659
|
-
if (keeps(space, choices)) points.push(choices);
|
|
2771
|
+
if (stages.every((s) => s.optional === true || choices.get(s.name) !== null || metaPart.has(prefix.get(s.name))) && keeps(space, choices)) points.push(choices);
|
|
2660
2772
|
}
|
|
2661
2773
|
}
|
|
2662
2774
|
const values = points.map(() => stages.map(() => ({})));
|
|
@@ -2681,7 +2793,7 @@ function sampleConfigs(space, n, seed, meta, maxTries) {
|
|
|
2681
2793
|
});
|
|
2682
2794
|
continue;
|
|
2683
2795
|
}
|
|
2684
|
-
const part = partOf(space, s.name).space;
|
|
2796
|
+
const part = memberSpaces.get(o) ?? partOf(space, s.name).space;
|
|
2685
2797
|
const poolSize = Math.max(n, 4 * o.members.max, 8);
|
|
2686
2798
|
const seen = /* @__PURE__ */ new Set();
|
|
2687
2799
|
const pool = sampleConfigs(part, poolSize, subSeed(seed, `pool:${s.name}:${o.id}`), false, Math.max(1e3, 100 * poolSize)).filter((c) => {
|
|
@@ -2711,7 +2823,7 @@ function sampleConfigs(space, n, seed, meta, maxTries) {
|
|
|
2711
2823
|
members: members[i][k]
|
|
2712
2824
|
};
|
|
2713
2825
|
});
|
|
2714
|
-
return canonicalConfig(
|
|
2826
|
+
return canonicalConfig(canon, {
|
|
2715
2827
|
space: space.engine,
|
|
2716
2828
|
stages: out
|
|
2717
2829
|
});
|
|
@@ -2739,7 +2851,7 @@ function enumerateSpace(space, options) {
|
|
|
2739
2851
|
const meta = options.meta ?? "skip";
|
|
2740
2852
|
if (meta !== "skip" && meta !== "sample") throw new RangeError(`The option meta is ${String(meta)}, not skip or sample.`);
|
|
2741
2853
|
if (options.n === 0) return [];
|
|
2742
|
-
return sampleConfigs(restrict(space, options.shapes), options.n, options.seed, meta === "sample", options.maxTries ?? Math.max(1e3, 100 * options.n));
|
|
2854
|
+
return sampleConfigs(restrict(space, options.shapes), options.n, options.seed, meta === "sample", options.maxTries ?? Math.max(1e3, 100 * options.n), space);
|
|
2743
2855
|
}
|
|
2744
2856
|
/**
|
|
2745
2857
|
* This function gives the shape kinds that a space accepts, in the order of `SHAPE_KINDS`. The value comes from the `supports` of the options.
|
|
@@ -3193,7 +3305,7 @@ const CORPUS_DIMENSIONS = Object.freeze({
|
|
|
3193
3305
|
});
|
|
3194
3306
|
/**
|
|
3195
3307
|
* This function gives a dimension of `CORPUS_DIMENSIONS`, with the fields of `patch` over it. It throws a `RangeError` for an unknown name.
|
|
3196
|
-
* With `supported` or `
|
|
3308
|
+
* With `supported`, `invalidates` or `precision` in the patch, it also throws a `RangeError` for a bad dimension, as `ownerDimension` does.
|
|
3197
3309
|
*/
|
|
3198
3310
|
function sharedDimension(name, patch = {}) {
|
|
3199
3311
|
const base = Object.hasOwn(CORPUS_DIMENSIONS, name) ? CORPUS_DIMENSIONS[name] : void 0;
|
|
@@ -3203,12 +3315,12 @@ function sharedDimension(name, patch = {}) {
|
|
|
3203
3315
|
...patch,
|
|
3204
3316
|
name
|
|
3205
3317
|
});
|
|
3206
|
-
if (patch.supported !== void 0 || patch.invalidates !== void 0) throwProblems(`sharedDimension: the dimension "${name}"`, ownProblems(dim));
|
|
3318
|
+
if (patch.supported !== void 0 || patch.invalidates !== void 0 || patch.precision !== void 0) throwProblems(`sharedDimension: the dimension "${name}"`, ownProblems(dim));
|
|
3207
3319
|
return dim;
|
|
3208
3320
|
}
|
|
3209
3321
|
/**
|
|
3210
3322
|
* This function gives a dimension that only its owner declares, for example `cut` of a family of `packing`.
|
|
3211
|
-
* It throws a `RangeError` for a name of `CORPUS_DIMENSIONS`, the reserved name `kind`, or a bad default, level, `supported` or `
|
|
3323
|
+
* It throws a `RangeError` for a name of `CORPUS_DIMENSIONS`, the reserved name `kind`, or a bad default, level, `supported`, `invalidates` or `precision`.
|
|
3212
3324
|
* The registry examines the `when` of the dimension, because it needs the earlier dimensions.
|
|
3213
3325
|
*/
|
|
3214
3326
|
function ownerDimension(name, spec) {
|
|
@@ -3252,7 +3364,7 @@ function supportedText(dim) {
|
|
|
3252
3364
|
if (isSupportedList(s)) return s.map((v) => JSON.stringify(v)).join(", ");
|
|
3253
3365
|
return `the values from ${s.min ?? dim.min} to ${s.max ?? dim.max}`;
|
|
3254
3366
|
}
|
|
3255
|
-
/** This function gives the problems of one dimension that need no other dimension: the default, the levels, `supported` and `
|
|
3367
|
+
/** This function gives the problems of one dimension that need no other dimension: the default, the levels, `supported`, `invalidates` and `precision`. */
|
|
3256
3368
|
function ownProblems(d) {
|
|
3257
3369
|
const out = [];
|
|
3258
3370
|
const bad = paramProblem(d, d.default);
|
|
@@ -3263,6 +3375,7 @@ function ownProblems(d) {
|
|
|
3263
3375
|
}
|
|
3264
3376
|
out.push(...supportProblems(d, bad === void 0));
|
|
3265
3377
|
out.push(...invalidatesProblems(d));
|
|
3378
|
+
out.push(...precisionProblems(d));
|
|
3266
3379
|
return out;
|
|
3267
3380
|
}
|
|
3268
3381
|
/** This function gives the problems of the `supported` values of a dimension. `goodDefault` tells that the default is a good value. */
|
|
@@ -3304,6 +3417,22 @@ function invalidatesProblems(d) {
|
|
|
3304
3417
|
for (const f of ["hash", INVALIDATED_FIELD]) if (list.includes(f)) out.push(`the invalidates of "${d.name}" has the field "${f}", which the registry writes`);
|
|
3305
3418
|
return out;
|
|
3306
3419
|
}
|
|
3420
|
+
/** This function gives the problems of the `precision` of a dimension. A bad value and a dimension that is not numeric are problems. */
|
|
3421
|
+
function precisionProblems(d) {
|
|
3422
|
+
const p = d.precision;
|
|
3423
|
+
if (p === void 0) return [];
|
|
3424
|
+
if (typeof p !== "number" || !Number.isInteger(p) || p < 0) return [`the precision of "${d.name}" is ${JSON.stringify(p)}, not a whole number of 0 or more`];
|
|
3425
|
+
if (d.kind !== "int" && d.kind !== "real") return [`the precision of "${d.name}" is for a numeric dimension, but the dimension is a ${d.kind}`];
|
|
3426
|
+
return [];
|
|
3427
|
+
}
|
|
3428
|
+
/** This function rounds a number to `places` decimal places: `Math.round(v * 10 ** places) / 10 ** places`. */
|
|
3429
|
+
const roundTo = (v, places) => Math.round(v * 10 ** places) / 10 ** places;
|
|
3430
|
+
/** This function tells if a value is the default of a dimension. With `precision`, it compares the two numbers after it rounds them. */
|
|
3431
|
+
function isDefault(d, value) {
|
|
3432
|
+
const def = paramValue(d, d.default);
|
|
3433
|
+
if (d.precision === void 0 || typeof value !== "number" || typeof def !== "number") return value === def;
|
|
3434
|
+
return roundTo(value, d.precision) === roundTo(def, d.precision);
|
|
3435
|
+
}
|
|
3307
3436
|
/** This function tells if a log scale of a range starts at 0. Then the scale is the log of `1 + x - min`. */
|
|
3308
3437
|
const fromZero = (d) => d.scale === "log" && (d.min ?? 0) <= 0;
|
|
3309
3438
|
/**
|
|
@@ -3459,12 +3588,15 @@ function sweepLevels(dimensions, options, where, by) {
|
|
|
3459
3588
|
return lv;
|
|
3460
3589
|
});
|
|
3461
3590
|
}
|
|
3462
|
-
/**
|
|
3591
|
+
/**
|
|
3592
|
+
* This function gives the output fields that the values make wrong: the `invalidates` of each dimension with a value other than its default, sorted.
|
|
3593
|
+
* A dimension with `precision` compares the rounded value with the rounded default.
|
|
3594
|
+
*/
|
|
3463
3595
|
function invalidFields(dimensions, full) {
|
|
3464
3596
|
const out = /* @__PURE__ */ new Set();
|
|
3465
3597
|
for (const d of dimensions) {
|
|
3466
3598
|
if (d.invalidates === void 0 || d.invalidates.length === 0) continue;
|
|
3467
|
-
if (full[d.name]
|
|
3599
|
+
if (!isDefault(d, full[d.name])) for (const f of d.invalidates) out.add(f);
|
|
3468
3600
|
}
|
|
3469
3601
|
return [...out].sort(byCode);
|
|
3470
3602
|
}
|
|
@@ -3795,6 +3927,6 @@ const RECT_SCATTERED = Object.freeze({
|
|
|
3795
3927
|
};
|
|
3796
3928
|
}
|
|
3797
3929
|
});
|
|
3798
|
-
export { CORPUS_DIMENSIONS, DEFAULT_FAMILY_BY, DEFAULT_RNG, DEFAULT_SHAPES, DEFAULT_TOLERANCE, EDGES_STEP, EDGE_DENSITY, EDGE_STEP_VERSION, EPS, FAMILY_ANY_KIND, INVALIDATED_FIELD, JOINT_MEASURES, JOINT_MOVED_MIN, PACK_HARD_RULES, RECORD_EPS, RECORD_SCALE, RECT_SCATTERED, SHAPE_KINDS, SHAPE_KIND_IDS, SIDES, SPLIT_SCHEMA, STRATEGY_SPACE_SCHEMA, VERDICT_DRAWS, VERDICT_EXACT_CAP, VERDICT_EXACT_MAX, VERDICT_RUNS, VERDICT_SEED, applyPack, boundsOf, canonicalConfig, canonicalInput, canonicalJson, checkConfig, checkDeclared, checkInput, checkShapes, checkSpace, checkSplit, compareMeasure, composeFamily, configId, corpusHashOf, countObstacleHits, countOutside, countOverlaps, countPortsOffBorder, createFamilyRegistry, declaredClaimOf, declaredCounts, dimensionAt, dimensionSupports, dimensionUnit, documentHash, edgeStep, enumerateSpace, exercised, familyKind, familyOf, fnv1a32, grow, isShapeKind, itemShapeOf, joinConfigs, leaveOneSeedOut, levelsOf, marginSides, minEffectOf, mulberry32, outputGroups, outputHash, overlapOf, ownerDimension, packHard, paramActive, paramLevels, paramProblem, paramValue, pickMoves, placedRect, portPoint, portfolio, productSpace, randomInt, rectInRegion, regionHitsRect, resolveDimensions, selectBest, sha256Hex, shapeKindOf, shapeKindProblem, shapeKindsOf, shapesOf, sharedDimension, spaceShapeKinds, spaceSize, splitConfig, splitFileName, splitFolds, stepRandom, toLayoutRecord, toPackInput, translate, turnBox, turnMargin, turnPoint, turnPort, turnRegion, turnSide, verdict };
|
|
3930
|
+
export { CORPUS_DIMENSIONS, DEFAULT_FAMILY_BY, DEFAULT_RNG, DEFAULT_SHAPES, DEFAULT_TOLERANCE, EDGES_STEP, EDGE_DENSITY, EDGE_STEP_VERSION, EPS, FAMILY_ANY_KIND, INVALIDATED_FIELD, JOINT_MEASURES, JOINT_MOVED_MIN, PACK_HARD_RULES, RECORD_EPS, RECORD_SCALE, RECT_SCATTERED, SHAPE_KINDS, SHAPE_KIND_IDS, SIDES, SPLIT_SCHEMA, STRATEGY_SPACE_SCHEMA, VERDICT_DRAWS, VERDICT_EXACT_CAP, VERDICT_EXACT_MAX, VERDICT_RUNS, VERDICT_SEED, applyPack, boundsOf, boxArea, canonicalConfig, canonicalInput, canonicalJson, checkConfig, checkDeclared, checkInput, checkShapes, checkSpace, checkSplit, compareMeasure, composeFamily, configId, corpusHashOf, countObstacleHits, countOutside, countOverlaps, countPortsOffBorder, createFamilyRegistry, declaredClaimOf, declaredCounts, dimensionAt, dimensionSupports, dimensionUnit, documentHash, edgeStep, enumerateSpace, exercised, familyKind, familyOf, fnv1a32, grow, isShapeKind, itemShapeOf, joinConfigs, leaveOneSeedOut, levelsOf, marginSides, minEffectOf, mulberry32, outputGroups, outputHash, overlapOf, ownerDimension, packHard, paramActive, paramLevels, paramProblem, paramValue, pickMoves, placedRect, portPoint, portfolio, productSpace, randomInt, rectInRegion, regionArea, regionHitsRect, resolveDimensions, ruleLevel, selectBest, sha256Hex, shapeKindOf, shapeKindProblem, shapeKindsOf, shapeSupportProblems, shapesOf, sharedDimension, spaceShapeKinds, spaceSize, splitConfig, splitFileName, splitFolds, stepRandom, toLayoutRecord, toPackInput, translate, turnBox, turnMargin, turnPoint, turnPort, turnRegion, turnSide, verdict };
|
|
3799
3931
|
|
|
3800
3932
|
//# sourceMappingURL=index.js.map
|