@suss/datalog 0.31.0 → 0.31.2
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/dist/index.cjs +237 -96
- package/dist/index.d.cts +89 -7
- package/dist/index.d.ts +89 -7
- package/dist/index.js +233 -96
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -90,9 +90,32 @@ interface RuleCost {
|
|
|
90
90
|
ms: number;
|
|
91
91
|
/** Tuples this rule added that no earlier derivation had reached. */
|
|
92
92
|
derived: number;
|
|
93
|
+
/**
|
|
94
|
+
* Rows the join read for this rule. A rule that examines a hundred
|
|
95
|
+
* thousand rows to derive a dozen tuples is doing a walk somebody
|
|
96
|
+
* meant to be a lookup, and `derived` alone never shows that.
|
|
97
|
+
*/
|
|
98
|
+
examined: number;
|
|
93
99
|
/** How many times the rule was evaluated, over all rounds and deltas. */
|
|
94
100
|
attempts: number;
|
|
95
101
|
}
|
|
102
|
+
/** A question the engine gave up on, and how much it had read by then. */
|
|
103
|
+
interface AbandonedQuestion {
|
|
104
|
+
/** What the caller was asking, in whatever words the caller uses. */
|
|
105
|
+
question: string;
|
|
106
|
+
examined: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* How a caller that asks one question at a time got on. `skipped` are
|
|
110
|
+
* the ones it never put, because what it had already spent was gone.
|
|
111
|
+
*/
|
|
112
|
+
interface QuestionTally {
|
|
113
|
+
asked: number;
|
|
114
|
+
abandoned: number;
|
|
115
|
+
skipped: number;
|
|
116
|
+
}
|
|
117
|
+
/** How one question ended, for the tally. */
|
|
118
|
+
type QuestionOutcome = keyof Omit<QuestionTally, "asked">;
|
|
96
119
|
/**
|
|
97
120
|
* How big a relation grew. `derived` separates the relations rules
|
|
98
121
|
* concluded from the base facts an adapter emitted, because "derive fewer
|
|
@@ -130,6 +153,18 @@ interface EvaluationProfile {
|
|
|
130
153
|
* corpus size is worth more attention than the rule table.
|
|
131
154
|
*/
|
|
132
155
|
evaluations: number;
|
|
156
|
+
/** Rows every join read, summed over every rule set. */
|
|
157
|
+
examined: number;
|
|
158
|
+
/**
|
|
159
|
+
* The most rows any one `evaluate` call read. A caller that asks a
|
|
160
|
+
* question at a time sizes a per-question budget off this, where the
|
|
161
|
+
* total only says how many questions it asked.
|
|
162
|
+
*/
|
|
163
|
+
largestEvaluation: number;
|
|
164
|
+
/** Every question abandoned on its budget, in the order they were given up. */
|
|
165
|
+
abandoned: AbandonedQuestion[];
|
|
166
|
+
/** How many questions a one-at-a-time caller asked, and how they went. */
|
|
167
|
+
questions: QuestionTally;
|
|
133
168
|
/** Final tuple count per relation, largest first. */
|
|
134
169
|
relations: RelationSize[];
|
|
135
170
|
/** Per-rule cost across every rule set, most expensive first. */
|
|
@@ -137,6 +172,17 @@ interface EvaluationProfile {
|
|
|
137
172
|
/** The same time, split by the rule set that spent it. */
|
|
138
173
|
ruleSets: RuleSetCost[];
|
|
139
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Note that a question was given up on. A caller reading this in a
|
|
177
|
+
* profile is looking at the reason an answer came back empty, so the
|
|
178
|
+
* question is recorded in the caller's own words.
|
|
179
|
+
*/
|
|
180
|
+
declare function chargeAbandoned(question: string, examined: number): void;
|
|
181
|
+
/**
|
|
182
|
+
* Note that a caller put one question. `outcome` says whether it was
|
|
183
|
+
* given up part way or never put at all; leave it out when it answered.
|
|
184
|
+
*/
|
|
185
|
+
declare function chargeQuestion(outcome?: QuestionOutcome): void;
|
|
140
186
|
/**
|
|
141
187
|
* Run `fn` with evaluation profiling on, and hand back what it returned
|
|
142
188
|
* alongside the numbers. Nested calls share the outer collector, so a
|
|
@@ -403,18 +449,54 @@ interface Derivation {
|
|
|
403
449
|
* stratified, so this throws.
|
|
404
450
|
*/
|
|
405
451
|
declare function stratify(rules: Rule[]): Rule[][];
|
|
452
|
+
/**
|
|
453
|
+
* How many rows the joins of one evaluation may read, and how many they
|
|
454
|
+
* have read so far. Counting rows rather than new tuples is what catches
|
|
455
|
+
* a question that walks: the walk finds the same conclusions over and
|
|
456
|
+
* over, so nothing new arrives while the reading runs away.
|
|
457
|
+
*
|
|
458
|
+
* The caller builds one with `rowBudget` and reads `examined` back after
|
|
459
|
+
* the call, which is how it learns what a question cost whether or not
|
|
460
|
+
* the question settled. An evaluation with no budget gets a limit of
|
|
461
|
+
* Infinity, so the hot loop does the same increment and the same
|
|
462
|
+
* compare either way.
|
|
463
|
+
*/
|
|
464
|
+
interface RowBudget {
|
|
465
|
+
examined: number;
|
|
466
|
+
limit: number;
|
|
467
|
+
}
|
|
468
|
+
/** A budget for one evaluation, ready to hand to `evaluate`. */
|
|
469
|
+
declare const rowBudget: (limit: number) => RowBudget;
|
|
470
|
+
/**
|
|
471
|
+
* What `evaluate` throws when a row budget runs out.
|
|
472
|
+
*
|
|
473
|
+
* By the time this reaches a caller the database is back where it
|
|
474
|
+
* started: every fact that evaluation derived has been retracted, and
|
|
475
|
+
* the rule set will start over from the base facts next time rather
|
|
476
|
+
* than from a delta that was never worked through. The caller's own
|
|
477
|
+
* facts, the question it asked among them, are still there for it to
|
|
478
|
+
* take back.
|
|
479
|
+
*/
|
|
480
|
+
declare class BudgetExhausted extends Error {
|
|
481
|
+
readonly ruleSet: string;
|
|
482
|
+
readonly examined: number;
|
|
483
|
+
constructor(ruleSet: string, examined: number);
|
|
484
|
+
}
|
|
406
485
|
/**
|
|
407
486
|
* Evaluate `rules` over `db` to fixpoint, adding derived facts in
|
|
408
487
|
* place. Rules are stratified first; within a stratum, semi-naïve
|
|
409
|
-
* iteration joins each rule against the last round's delta so work
|
|
410
|
-
* proportional to new facts
|
|
488
|
+
* iteration joins each rule against the last round's delta, so work
|
|
489
|
+
* is proportional to new facts rather than to all facts.
|
|
411
490
|
*
|
|
412
491
|
* With an `algebra`, every derivation also tags its conclusion (see
|
|
413
|
-
* `TagAlgebra`). Supply the same algebra
|
|
414
|
-
*
|
|
415
|
-
*
|
|
492
|
+
* `TagAlgebra`). Supply the same algebra every time over one
|
|
493
|
+
* database: a resumed run tags only what the new facts reach.
|
|
494
|
+
*
|
|
495
|
+
* With a `budget`, evaluation gives up once its joins have read that
|
|
496
|
+
* many rows and throws `BudgetExhausted`. Either way the budget says
|
|
497
|
+
* afterwards what the evaluation cost.
|
|
416
498
|
*/
|
|
417
|
-
declare function evaluate<Tag = never>(db: Database, rules: Rule[], algebra?: TagAlgebra<Tag
|
|
499
|
+
declare function evaluate<Tag = never>(db: Database, rules: Rule[], algebra?: TagAlgebra<Tag>, budget?: RowBudget): Database;
|
|
418
500
|
/**
|
|
419
501
|
* Empty these relations, and leave `rules` able to carry on from where
|
|
420
502
|
* it got to.
|
|
@@ -438,4 +520,4 @@ declare function evaluate<Tag = never>(db: Database, rules: Rule[], algebra?: Ta
|
|
|
438
520
|
*/
|
|
439
521
|
declare function clearRelations(db: Database, rules: Rule[], relations: readonly string[]): void;
|
|
440
522
|
|
|
441
|
-
export { type AddOutcome, type Atom, type BodyMatch, type ConfidenceLevel, Database, type Demand, type Derivation, type EvaluationProfile, type Literal, type OnDemandRules, type Proof, type ProofDerived, type ProofOptions, type Rule, type RuleCost, type TagAlgebra, type Term, type Tuple, Witness, type WitnessTag, clearRelations, confidence, confidenceWith, constant, deriveOnDemand, evaluate, formatProfile, lit, notLit, profileEvaluation, profileEvaluationAsync, proofOf, rule, ruleLabel, stratify, tupleKey, tupleKeyParts, variable, witnesses };
|
|
523
|
+
export { type AbandonedQuestion, type AddOutcome, type Atom, type BodyMatch, BudgetExhausted, type ConfidenceLevel, Database, type Demand, type Derivation, type EvaluationProfile, type Literal, type OnDemandRules, type Proof, type ProofDerived, type ProofOptions, type QuestionOutcome, type QuestionTally, type RowBudget, type Rule, type RuleCost, type TagAlgebra, type Term, type Tuple, Witness, type WitnessTag, chargeAbandoned, chargeQuestion, clearRelations, confidence, confidenceWith, constant, deriveOnDemand, evaluate, formatProfile, lit, notLit, profileEvaluation, profileEvaluationAsync, proofOf, rowBudget, rule, ruleLabel, stratify, tupleKey, tupleKeyParts, variable, witnesses };
|
package/dist/index.d.ts
CHANGED
|
@@ -90,9 +90,32 @@ interface RuleCost {
|
|
|
90
90
|
ms: number;
|
|
91
91
|
/** Tuples this rule added that no earlier derivation had reached. */
|
|
92
92
|
derived: number;
|
|
93
|
+
/**
|
|
94
|
+
* Rows the join read for this rule. A rule that examines a hundred
|
|
95
|
+
* thousand rows to derive a dozen tuples is doing a walk somebody
|
|
96
|
+
* meant to be a lookup, and `derived` alone never shows that.
|
|
97
|
+
*/
|
|
98
|
+
examined: number;
|
|
93
99
|
/** How many times the rule was evaluated, over all rounds and deltas. */
|
|
94
100
|
attempts: number;
|
|
95
101
|
}
|
|
102
|
+
/** A question the engine gave up on, and how much it had read by then. */
|
|
103
|
+
interface AbandonedQuestion {
|
|
104
|
+
/** What the caller was asking, in whatever words the caller uses. */
|
|
105
|
+
question: string;
|
|
106
|
+
examined: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* How a caller that asks one question at a time got on. `skipped` are
|
|
110
|
+
* the ones it never put, because what it had already spent was gone.
|
|
111
|
+
*/
|
|
112
|
+
interface QuestionTally {
|
|
113
|
+
asked: number;
|
|
114
|
+
abandoned: number;
|
|
115
|
+
skipped: number;
|
|
116
|
+
}
|
|
117
|
+
/** How one question ended, for the tally. */
|
|
118
|
+
type QuestionOutcome = keyof Omit<QuestionTally, "asked">;
|
|
96
119
|
/**
|
|
97
120
|
* How big a relation grew. `derived` separates the relations rules
|
|
98
121
|
* concluded from the base facts an adapter emitted, because "derive fewer
|
|
@@ -130,6 +153,18 @@ interface EvaluationProfile {
|
|
|
130
153
|
* corpus size is worth more attention than the rule table.
|
|
131
154
|
*/
|
|
132
155
|
evaluations: number;
|
|
156
|
+
/** Rows every join read, summed over every rule set. */
|
|
157
|
+
examined: number;
|
|
158
|
+
/**
|
|
159
|
+
* The most rows any one `evaluate` call read. A caller that asks a
|
|
160
|
+
* question at a time sizes a per-question budget off this, where the
|
|
161
|
+
* total only says how many questions it asked.
|
|
162
|
+
*/
|
|
163
|
+
largestEvaluation: number;
|
|
164
|
+
/** Every question abandoned on its budget, in the order they were given up. */
|
|
165
|
+
abandoned: AbandonedQuestion[];
|
|
166
|
+
/** How many questions a one-at-a-time caller asked, and how they went. */
|
|
167
|
+
questions: QuestionTally;
|
|
133
168
|
/** Final tuple count per relation, largest first. */
|
|
134
169
|
relations: RelationSize[];
|
|
135
170
|
/** Per-rule cost across every rule set, most expensive first. */
|
|
@@ -137,6 +172,17 @@ interface EvaluationProfile {
|
|
|
137
172
|
/** The same time, split by the rule set that spent it. */
|
|
138
173
|
ruleSets: RuleSetCost[];
|
|
139
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Note that a question was given up on. A caller reading this in a
|
|
177
|
+
* profile is looking at the reason an answer came back empty, so the
|
|
178
|
+
* question is recorded in the caller's own words.
|
|
179
|
+
*/
|
|
180
|
+
declare function chargeAbandoned(question: string, examined: number): void;
|
|
181
|
+
/**
|
|
182
|
+
* Note that a caller put one question. `outcome` says whether it was
|
|
183
|
+
* given up part way or never put at all; leave it out when it answered.
|
|
184
|
+
*/
|
|
185
|
+
declare function chargeQuestion(outcome?: QuestionOutcome): void;
|
|
140
186
|
/**
|
|
141
187
|
* Run `fn` with evaluation profiling on, and hand back what it returned
|
|
142
188
|
* alongside the numbers. Nested calls share the outer collector, so a
|
|
@@ -403,18 +449,54 @@ interface Derivation {
|
|
|
403
449
|
* stratified, so this throws.
|
|
404
450
|
*/
|
|
405
451
|
declare function stratify(rules: Rule[]): Rule[][];
|
|
452
|
+
/**
|
|
453
|
+
* How many rows the joins of one evaluation may read, and how many they
|
|
454
|
+
* have read so far. Counting rows rather than new tuples is what catches
|
|
455
|
+
* a question that walks: the walk finds the same conclusions over and
|
|
456
|
+
* over, so nothing new arrives while the reading runs away.
|
|
457
|
+
*
|
|
458
|
+
* The caller builds one with `rowBudget` and reads `examined` back after
|
|
459
|
+
* the call, which is how it learns what a question cost whether or not
|
|
460
|
+
* the question settled. An evaluation with no budget gets a limit of
|
|
461
|
+
* Infinity, so the hot loop does the same increment and the same
|
|
462
|
+
* compare either way.
|
|
463
|
+
*/
|
|
464
|
+
interface RowBudget {
|
|
465
|
+
examined: number;
|
|
466
|
+
limit: number;
|
|
467
|
+
}
|
|
468
|
+
/** A budget for one evaluation, ready to hand to `evaluate`. */
|
|
469
|
+
declare const rowBudget: (limit: number) => RowBudget;
|
|
470
|
+
/**
|
|
471
|
+
* What `evaluate` throws when a row budget runs out.
|
|
472
|
+
*
|
|
473
|
+
* By the time this reaches a caller the database is back where it
|
|
474
|
+
* started: every fact that evaluation derived has been retracted, and
|
|
475
|
+
* the rule set will start over from the base facts next time rather
|
|
476
|
+
* than from a delta that was never worked through. The caller's own
|
|
477
|
+
* facts, the question it asked among them, are still there for it to
|
|
478
|
+
* take back.
|
|
479
|
+
*/
|
|
480
|
+
declare class BudgetExhausted extends Error {
|
|
481
|
+
readonly ruleSet: string;
|
|
482
|
+
readonly examined: number;
|
|
483
|
+
constructor(ruleSet: string, examined: number);
|
|
484
|
+
}
|
|
406
485
|
/**
|
|
407
486
|
* Evaluate `rules` over `db` to fixpoint, adding derived facts in
|
|
408
487
|
* place. Rules are stratified first; within a stratum, semi-naïve
|
|
409
|
-
* iteration joins each rule against the last round's delta so work
|
|
410
|
-
* proportional to new facts
|
|
488
|
+
* iteration joins each rule against the last round's delta, so work
|
|
489
|
+
* is proportional to new facts rather than to all facts.
|
|
411
490
|
*
|
|
412
491
|
* With an `algebra`, every derivation also tags its conclusion (see
|
|
413
|
-
* `TagAlgebra`). Supply the same algebra
|
|
414
|
-
*
|
|
415
|
-
*
|
|
492
|
+
* `TagAlgebra`). Supply the same algebra every time over one
|
|
493
|
+
* database: a resumed run tags only what the new facts reach.
|
|
494
|
+
*
|
|
495
|
+
* With a `budget`, evaluation gives up once its joins have read that
|
|
496
|
+
* many rows and throws `BudgetExhausted`. Either way the budget says
|
|
497
|
+
* afterwards what the evaluation cost.
|
|
416
498
|
*/
|
|
417
|
-
declare function evaluate<Tag = never>(db: Database, rules: Rule[], algebra?: TagAlgebra<Tag
|
|
499
|
+
declare function evaluate<Tag = never>(db: Database, rules: Rule[], algebra?: TagAlgebra<Tag>, budget?: RowBudget): Database;
|
|
418
500
|
/**
|
|
419
501
|
* Empty these relations, and leave `rules` able to carry on from where
|
|
420
502
|
* it got to.
|
|
@@ -438,4 +520,4 @@ declare function evaluate<Tag = never>(db: Database, rules: Rule[], algebra?: Ta
|
|
|
438
520
|
*/
|
|
439
521
|
declare function clearRelations(db: Database, rules: Rule[], relations: readonly string[]): void;
|
|
440
522
|
|
|
441
|
-
export { type AddOutcome, type Atom, type BodyMatch, type ConfidenceLevel, Database, type Demand, type Derivation, type EvaluationProfile, type Literal, type OnDemandRules, type Proof, type ProofDerived, type ProofOptions, type Rule, type RuleCost, type TagAlgebra, type Term, type Tuple, Witness, type WitnessTag, clearRelations, confidence, confidenceWith, constant, deriveOnDemand, evaluate, formatProfile, lit, notLit, profileEvaluation, profileEvaluationAsync, proofOf, rule, ruleLabel, stratify, tupleKey, tupleKeyParts, variable, witnesses };
|
|
523
|
+
export { type AbandonedQuestion, type AddOutcome, type Atom, type BodyMatch, BudgetExhausted, type ConfidenceLevel, Database, type Demand, type Derivation, type EvaluationProfile, type Literal, type OnDemandRules, type Proof, type ProofDerived, type ProofOptions, type QuestionOutcome, type QuestionTally, type RowBudget, type Rule, type RuleCost, type TagAlgebra, type Term, type Tuple, Witness, type WitnessTag, chargeAbandoned, chargeQuestion, clearRelations, confidence, confidenceWith, constant, deriveOnDemand, evaluate, formatProfile, lit, notLit, profileEvaluation, profileEvaluationAsync, proofOf, rowBudget, rule, ruleLabel, stratify, tupleKey, tupleKeyParts, variable, witnesses };
|