@mark1russell7/layout-contract 0.2.11 → 0.2.12

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/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.11",
4
+ "version": "0.2.12",
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/verdict.ts CHANGED
@@ -91,6 +91,25 @@ export interface VerdictSignTest {
91
91
  /** The label of a verdict. `better` and `worse` tell the side of `b`. */
92
92
  export type VerdictLabel = "better" | "worse" | "depends on the mix" | "no verdict";
93
93
 
94
+ /**
95
+ * The scope of a verdict. The test keeps the families of the corpus as fixed, so its claim is about these families only.
96
+ * It is not a claim about a new kind of input.
97
+ */
98
+ export type VerdictScope = "these families";
99
+
100
+ /**
101
+ * The breadth of a verdict: the count of the families against its side.
102
+ * The side is the side of the label. For `depends on the mix` and `no verdict`, it is the sign of the stratified mean.
103
+ */
104
+ export interface VerdictBreadth {
105
+ /** The count of the families with a sign against the side. A stratified mean of exactly 0 has no side, so this count is 0. */
106
+ readonly against: number;
107
+ /** The count of the families. */
108
+ readonly of: number;
109
+ /** The count of the families with the sign 0. */
110
+ readonly ties: number;
111
+ }
112
+
94
113
  /** The result of `verdict`. */
95
114
  export interface VerdictResult {
96
115
  readonly measure: string;
@@ -107,6 +126,12 @@ export interface VerdictResult {
107
126
  /** `true` only when the two means have the same sign, the two intervals are clear of 0 and the permutation p is below `level`. */
108
127
  readonly agree: boolean;
109
128
  readonly label: VerdictLabel;
129
+ /** The scope of the claim: the families of the corpus, not a new kind of input. */
130
+ readonly scope: VerdictScope;
131
+ /** The count of the families against the side of the verdict, of all the families and of the ties. */
132
+ readonly breadth: VerdictBreadth;
133
+ /** The label, the scope and the breadth in one line, for example `better on these families, worse on 2 of 6 (1 tie)`. */
134
+ readonly summary: string;
110
135
  /** The inputs without a pair: one side has no record, a skipped record or no value of the measure. */
111
136
  readonly dropped: readonly string[];
112
137
  }
@@ -154,6 +179,24 @@ function signP(wins: number, losses: number): number {
154
179
  return Math.min(1, (2 * tail) / 2 ** n);
155
180
  }
156
181
 
182
+ /** This function gives the breadth of a verdict with the side `side`: 1, -1, or 0 for no side. */
183
+ function breadthOf(families: readonly FamilyVerdict[], side: number): VerdictBreadth {
184
+ const ties = families.filter((f) => f.sign === 0).length;
185
+ const against = side === 0 ? 0 : families.filter((f) => f.sign === -side).length;
186
+ return { against, of: families.length, ties };
187
+ }
188
+
189
+ /** This function gives the line of a verdict: its label, its scope and its breadth (`docs/VERDICT.md`). */
190
+ function summaryOf(label: VerdictLabel, side: number, breadth: VerdictBreadth): string {
191
+ const ties = breadth.ties === 0 ? "" : ` (${breadth.ties} ${breadth.ties === 1 ? "tie" : "ties"})`;
192
+ const word = side > 0 ? "better" : "worse";
193
+ const other = side > 0 ? "worse" : "better";
194
+ const count = breadth.against === 0 ? "none" : String(breadth.against);
195
+ if (label === "better" || label === "worse") return `${label} on these families, ${other} on ${count} of ${breadth.of}${ties}`;
196
+ if (side === 0) return `${label}: the family mean is 0, on ${breadth.of} families${ties}`;
197
+ return `${label}: ${word} on the family mean, ${other} on ${count} of ${breadth.of}${ties}`;
198
+ }
199
+
157
200
  /** This function tells if a value is a positive whole number. */
158
201
  const isCount = (v: number): boolean => Number.isInteger(v) && v > 0;
159
202
 
@@ -206,6 +249,7 @@ function pairsOf<R extends VerdictRecord>(records: Iterable<R>, options: Verdict
206
249
  * - `stratified` is the mean of the family means. Its bootstrap draws the seeds inside each family. `pooled` is the mean of the inputs.
207
250
  * - The permutation test changes the sign of each difference inside its family. Its statistic is the mean of the family means.
208
251
  * - The label is `better` or `worse` only when `agree` is `true`. Opposite signs of the two means give `depends on the mix`.
252
+ * - `scope`, `breadth` and `summary` tell that the claim is about these families, and how many families are against it.
209
253
  *
210
254
  * It throws a `RangeError` for a missing `tie` or `level`, and for no pair. Two records of one side and input, or a value that is not finite, also cause a `RangeError`.
211
255
  */
@@ -292,5 +336,7 @@ export function verdict<R extends VerdictRecord>(records: Iterable<R>, options:
292
336
  const sign = Math.sign(stratified.mean);
293
337
  const agree = sign !== 0 && sign === Math.sign(pooled.mean) && clearOn(stratified, sign) && clearOn(pooled, sign) && permutation.p < level;
294
338
  const label: VerdictLabel = agree ? (sign > 0 ? "better" : "worse") : sign * Math.sign(pooled.mean) < 0 ? "depends on the mix" : "no verdict";
295
- return { measure: measure.id, n, stratified, pooled, permutation, families, signTest, agree, label, dropped };
339
+ const breadth = breadthOf(families, sign);
340
+ const summary = summaryOf(label, sign, breadth);
341
+ return { measure: measure.id, n, stratified, pooled, permutation, families, signTest, agree, label, scope: "these families", breadth, summary, dropped };
296
342
  }