@hviana/sema 0.2.6 → 0.2.7
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/example/demo.d.ts +1 -0
- package/dist/example/demo.js +39 -0
- package/dist/example/train_base.d.ts +87 -0
- package/dist/example/train_base.js +2252 -0
- package/dist/src/alphabet.d.ts +7 -0
- package/dist/src/alphabet.js +33 -0
- package/dist/src/alu/src/alu.d.ts +185 -0
- package/dist/src/alu/src/alu.js +440 -0
- package/dist/src/alu/src/expr.d.ts +61 -0
- package/dist/src/alu/src/expr.js +318 -0
- package/dist/src/alu/src/index.d.ts +11 -0
- package/dist/src/alu/src/index.js +19 -0
- package/dist/src/alu/src/kernel-arith.d.ts +16 -0
- package/dist/src/alu/src/kernel-arith.js +264 -0
- package/dist/src/alu/src/kernel-bits.d.ts +19 -0
- package/dist/src/alu/src/kernel-bits.js +152 -0
- package/dist/src/alu/src/kernel-logic.d.ts +4 -0
- package/dist/src/alu/src/kernel-logic.js +60 -0
- package/dist/src/alu/src/kernel-nd.d.ts +3 -0
- package/dist/src/alu/src/kernel-nd.js +208 -0
- package/dist/src/alu/src/kernel-numeric.d.ts +54 -0
- package/dist/src/alu/src/kernel-numeric.js +366 -0
- package/dist/src/alu/src/operation.d.ts +168 -0
- package/dist/src/alu/src/operation.js +189 -0
- package/dist/src/alu/src/parser.d.ts +221 -0
- package/dist/src/alu/src/parser.js +577 -0
- package/dist/src/alu/src/resonance.d.ts +55 -0
- package/dist/src/alu/src/resonance.js +126 -0
- package/dist/src/alu/src/text.d.ts +31 -0
- package/dist/src/alu/src/text.js +73 -0
- package/dist/src/alu/src/value.d.ts +109 -0
- package/dist/src/alu/src/value.js +300 -0
- package/dist/src/alu/test/alu.test.d.ts +1 -0
- package/dist/src/alu/test/alu.test.js +764 -0
- package/dist/src/bytes.d.ts +14 -0
- package/dist/src/bytes.js +59 -0
- package/dist/src/canon.d.ts +26 -0
- package/dist/src/canon.js +57 -0
- package/dist/src/config.d.ts +111 -0
- package/dist/src/config.js +91 -0
- package/dist/src/derive/src/deduction.d.ts +125 -0
- package/dist/src/derive/src/deduction.js +155 -0
- package/dist/src/derive/src/index.d.ts +7 -0
- package/dist/src/derive/src/index.js +11 -0
- package/dist/src/derive/src/priority-queue.d.ts +20 -0
- package/dist/src/derive/src/priority-queue.js +73 -0
- package/dist/src/derive/src/rewrite.d.ts +56 -0
- package/dist/src/derive/src/rewrite.js +100 -0
- package/dist/src/derive/src/trie.d.ts +90 -0
- package/dist/src/derive/src/trie.js +217 -0
- package/dist/src/derive/test/derive.test.d.ts +1 -0
- package/dist/src/derive/test/derive.test.js +122 -0
- package/dist/src/extension.d.ts +37 -0
- package/dist/src/extension.js +7 -0
- package/dist/src/geometry.d.ts +202 -0
- package/dist/src/geometry.js +575 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +18 -0
- package/dist/src/ingest-cache.d.ts +41 -0
- package/dist/src/ingest-cache.js +161 -0
- package/dist/src/mind/articulation.d.ts +6 -0
- package/dist/src/mind/articulation.js +99 -0
- package/dist/src/mind/attention.d.ts +400 -0
- package/dist/src/mind/attention.js +1763 -0
- package/dist/src/mind/bridge.d.ts +30 -0
- package/dist/src/mind/bridge.js +569 -0
- package/dist/src/mind/canonical.d.ts +29 -0
- package/dist/src/mind/canonical.js +88 -0
- package/dist/src/mind/graph-search.d.ts +285 -0
- package/dist/src/mind/graph-search.js +956 -0
- package/dist/src/mind/index.d.ts +7 -0
- package/dist/src/mind/index.js +5 -0
- package/dist/src/mind/junction.d.ts +124 -0
- package/dist/src/mind/junction.js +317 -0
- package/dist/src/mind/learning.d.ts +47 -0
- package/dist/src/mind/learning.js +248 -0
- package/dist/src/mind/match.d.ts +126 -0
- package/dist/src/mind/match.js +441 -0
- package/dist/src/mind/mechanisms/alu.d.ts +4 -0
- package/dist/src/mind/mechanisms/alu.js +36 -0
- package/dist/src/mind/mechanisms/cast.d.ts +89 -0
- package/dist/src/mind/mechanisms/cast.js +716 -0
- package/dist/src/mind/mechanisms/confluence.d.ts +24 -0
- package/dist/src/mind/mechanisms/confluence.js +225 -0
- package/dist/src/mind/mechanisms/cover.d.ts +6 -0
- package/dist/src/mind/mechanisms/cover.js +203 -0
- package/dist/src/mind/mechanisms/extraction.d.ts +67 -0
- package/dist/src/mind/mechanisms/extraction.js +387 -0
- package/dist/src/mind/mechanisms/recall.d.ts +13 -0
- package/dist/src/mind/mechanisms/recall.js +325 -0
- package/dist/src/mind/mind.d.ts +276 -0
- package/dist/src/mind/mind.js +572 -0
- package/dist/src/mind/pipeline-mechanism.d.ts +142 -0
- package/dist/src/mind/pipeline-mechanism.js +213 -0
- package/dist/src/mind/pipeline.d.ts +20 -0
- package/dist/src/mind/pipeline.js +217 -0
- package/dist/src/mind/primitives.d.ts +70 -0
- package/dist/src/mind/primitives.js +287 -0
- package/dist/src/mind/rationale.d.ts +139 -0
- package/dist/src/mind/rationale.js +163 -0
- package/dist/src/mind/reasoning.d.ts +34 -0
- package/dist/src/mind/reasoning.js +240 -0
- package/dist/src/mind/recognition.d.ts +20 -0
- package/dist/src/mind/recognition.js +390 -0
- package/dist/src/mind/resonance.d.ts +23 -0
- package/dist/src/mind/resonance.js +0 -0
- package/dist/src/mind/trace.d.ts +15 -0
- package/dist/src/mind/trace.js +73 -0
- package/dist/src/mind/traverse.d.ts +113 -0
- package/dist/src/mind/traverse.js +568 -0
- package/dist/src/mind/types.d.ts +289 -0
- package/dist/src/mind/types.js +130 -0
- package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
- package/dist/src/rabitq-ivf/src/database.js +201 -0
- package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
- package/dist/src/rabitq-ivf/src/index.js +4 -0
- package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
- package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
- package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
- package/dist/src/rabitq-ivf/src/prng.js +36 -0
- package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
- package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
- package/dist/src/sema.d.ts +31 -0
- package/dist/src/sema.js +63 -0
- package/dist/src/store-sqlite.d.ts +184 -0
- package/dist/src/store-sqlite.js +942 -0
- package/dist/src/store.d.ts +663 -0
- package/dist/src/store.js +1618 -0
- package/dist/src/vec.d.ts +31 -0
- package/dist/src/vec.js +109 -0
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// canonical.ts — THE canonical-segmentation convention, defined once.
|
|
2
|
+
//
|
|
3
|
+
// The store's canonical reading of a byte stream — "the id of each single-byte
|
|
4
|
+
// leaf, chained into flat branches" — is a WRITE/READ CONTRACT split across
|
|
5
|
+
// four consumers that previously each re-implemented the chaining loop:
|
|
6
|
+
//
|
|
7
|
+
// WRITE side (training):
|
|
8
|
+
// • learning.indexSubSpans — interns sliding windows of the two
|
|
9
|
+
// {@link canonicalWindows} lengths over the stream's leaf ids;
|
|
10
|
+
// • learning.deposit — interns the WHOLE stream as one flat branch
|
|
11
|
+
// (via {@link leafIdPrefix}) so every deposit has a byte-level identity.
|
|
12
|
+
// READ side (inference):
|
|
13
|
+
// • recognition's canonical pass — chains leaf ids from every position and
|
|
14
|
+
// probes each growing prefix as a flat branch, up to {@link chainReach};
|
|
15
|
+
// • attention.canonicalChunkId — reads a chunk's window of leaf ids
|
|
16
|
+
// (via {@link leafIdRun}) and probes its prefixes for the best anchor.
|
|
17
|
+
// (geometry.knownPrefixLength is the same convention below the store layer,
|
|
18
|
+
// expressed through injected `leafAt`/`lookup` capabilities — it cannot
|
|
19
|
+
// import this module without inverting the dependency spine, so its header
|
|
20
|
+
// cross-references this file instead.)
|
|
21
|
+
//
|
|
22
|
+
// If the write side's windows or the read side's reach ever change, they must
|
|
23
|
+
// change HERE — a drift between them silently makes recognition stop finding
|
|
24
|
+
// what training indexed, which no type checker catches.
|
|
25
|
+
/** The two sliding-window lengths the WRITE side interns over a stream's leaf
|
|
26
|
+
* ids: W−1 and W (the river's grouping quantum and its off-by-one neighbour,
|
|
27
|
+
* so a form straddling a group boundary is reachable from either cut). */
|
|
28
|
+
export function canonicalWindows(W) {
|
|
29
|
+
return [W - 1, W];
|
|
30
|
+
}
|
|
31
|
+
/** The READ side's chain reach: how many leaf ids a canonical chain may grow
|
|
32
|
+
* to from one position — W², the deepest two-level composite the write side's
|
|
33
|
+
* windows can spell. */
|
|
34
|
+
export function chainReach(W) {
|
|
35
|
+
return W * W;
|
|
36
|
+
}
|
|
37
|
+
/** The id of the single-byte leaf at position `p`, or null when that byte was
|
|
38
|
+
* never interned. */
|
|
39
|
+
export function leafIdAt(ctx, bytes, p) {
|
|
40
|
+
return ctx.store.findLeaf(bytes.subarray(p, p + 1));
|
|
41
|
+
}
|
|
42
|
+
/** The leaf ids of the window `[from, to)`, or null the moment ANY byte in it
|
|
43
|
+
* is unknown — the all-or-nothing read {@link canonicalChunkId} anchors on. */
|
|
44
|
+
export function leafIdRun(ctx, bytes, from, to) {
|
|
45
|
+
const ids = [];
|
|
46
|
+
for (let i = from; i < to; i++) {
|
|
47
|
+
const lid = leafIdAt(ctx, bytes, i);
|
|
48
|
+
if (lid === null)
|
|
49
|
+
return null;
|
|
50
|
+
ids.push(lid);
|
|
51
|
+
}
|
|
52
|
+
return ids;
|
|
53
|
+
}
|
|
54
|
+
/** The leaf ids of the LONGEST KNOWN PREFIX of `bytes` — stops at the first
|
|
55
|
+
* unknown byte and returns what it has (possibly empty). The caller decides
|
|
56
|
+
* what a partial prefix means (deposit only interns the whole-stream flat
|
|
57
|
+
* branch when the prefix covers everything). */
|
|
58
|
+
export function leafIdPrefix(ctx, bytes) {
|
|
59
|
+
const ids = [];
|
|
60
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
61
|
+
const lid = leafIdAt(ctx, bytes, i);
|
|
62
|
+
if (lid === null)
|
|
63
|
+
break;
|
|
64
|
+
ids.push(lid);
|
|
65
|
+
}
|
|
66
|
+
return ids;
|
|
67
|
+
}
|
|
68
|
+
/** The canonical W-window node ids of a byte stream, offset → id — the
|
|
69
|
+
* CONTENT-ADDRESSED IDENTITY of every W-sized slice, under which any content
|
|
70
|
+
* two deposits share IS the same node (hash-consing paid the comparison at
|
|
71
|
+
* write time). The read side of the {@link canonicalWindows} contract asked
|
|
72
|
+
* at every offset: a window over unknown bytes, or one never interned as a
|
|
73
|
+
* flat branch, has no identity and is skipped. Confluence's meet and CAST's
|
|
74
|
+
* frame detection both read shared/common content through this — never
|
|
75
|
+
* through a byte scan. */
|
|
76
|
+
export function windowIds(ctx, bytes) {
|
|
77
|
+
const W = ctx.space.maxGroup;
|
|
78
|
+
const out = new Map();
|
|
79
|
+
for (let off = 0; off + W <= bytes.length; off++) {
|
|
80
|
+
const ids = leafIdRun(ctx, bytes, off, off + W);
|
|
81
|
+
if (ids === null)
|
|
82
|
+
continue;
|
|
83
|
+
const wid = ctx.store.findBranch(ids);
|
|
84
|
+
if (wid !== null)
|
|
85
|
+
out.set(off, wid);
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import type { Store } from "../store.js";
|
|
2
|
+
import type { GraphSearchHost } from "./types.js";
|
|
3
|
+
/** A recognised form: a span of the query that names a node already in the
|
|
4
|
+
* store. `payload` is that node id. */
|
|
5
|
+
export interface Site {
|
|
6
|
+
start: number;
|
|
7
|
+
end: number;
|
|
8
|
+
payload: number;
|
|
9
|
+
}
|
|
10
|
+
/** A perceived leaf of the query tree, carrying the node id it resolves to. */
|
|
11
|
+
export interface Leaf {
|
|
12
|
+
start: number;
|
|
13
|
+
end: number;
|
|
14
|
+
bytes: Uint8Array;
|
|
15
|
+
node: number | null;
|
|
16
|
+
}
|
|
17
|
+
/** A COMPUTED span: the result of applying a manual rule (an extension's
|
|
18
|
+
* operation — e.g. the `alu` extension's arithmetic) to a recognised stretch
|
|
19
|
+
* of the query. Every
|
|
20
|
+
* bit of the intelligence — recognising the operator (literally or by
|
|
21
|
+
* resonance), parsing the operands, evaluating the operation — is done by the
|
|
22
|
+
* caller (src/mind/pipeline.ts), which hands the search the finished result span; the search
|
|
23
|
+
* treats it exactly like any other recognised completion (a learned fact that
|
|
24
|
+
* happens to be computed rather than stored). `node` is the canonical id of
|
|
25
|
+
* the result bytes when the store already holds them, else undefined. */
|
|
26
|
+
export interface ComputedResult {
|
|
27
|
+
i: number;
|
|
28
|
+
j: number;
|
|
29
|
+
bytes: Uint8Array;
|
|
30
|
+
node?: number;
|
|
31
|
+
}
|
|
32
|
+
export type GItem = {
|
|
33
|
+
kind: "cover";
|
|
34
|
+
p: number;
|
|
35
|
+
} | {
|
|
36
|
+
kind: "form";
|
|
37
|
+
i: number;
|
|
38
|
+
j: number;
|
|
39
|
+
node: number;
|
|
40
|
+
via: boolean;
|
|
41
|
+
/** Set when this form was born by RECOMPOSING rewritten parts into a deeper
|
|
42
|
+
* learned whole (the fuse of ≥2 recognised completions that names an
|
|
43
|
+
* edge-bearing node). Its onward continuation is charged at MICRO, not
|
|
44
|
+
* STEP: once parts are recomposed into a learned form, following that form
|
|
45
|
+
* to its grounded answer is the recomposition completing — so the
|
|
46
|
+
* consolidated, more-explanatory reading wins over leaving the parts split.
|
|
47
|
+
* See {@link GraphSearch.fuse} and {@link GraphSearch.formRules}. */
|
|
48
|
+
rcmp?: boolean;
|
|
49
|
+
} | {
|
|
50
|
+
kind: "out";
|
|
51
|
+
i: number;
|
|
52
|
+
j: number;
|
|
53
|
+
bytes: Uint8Array;
|
|
54
|
+
cover: boolean;
|
|
55
|
+
rec: boolean;
|
|
56
|
+
node?: number;
|
|
57
|
+
/** Set only for a {@link ComputedResult} axiom (an extension's derived
|
|
58
|
+
* value, e.g. ALU arithmetic) — as opposed to a genuinely RECOGNISED
|
|
59
|
+
* learned form. Both set `rec: true` (a computation bridges the cover
|
|
60
|
+
* exactly like a learned terminal answer), but they mean different
|
|
61
|
+
* things for `i..j`'s WIDTH: a recognised form's query-span width is
|
|
62
|
+
* real evidence of how much of the query's meaning it accounts for
|
|
63
|
+
* (liftAnswer's half-dominance framing decision); a computed span's
|
|
64
|
+
* width is operand digit-count, uncorrelated with meaning ("1000 - 421"
|
|
65
|
+
* is wider than "15 * 7" only because the numbers are bigger, not
|
|
66
|
+
* because subtraction is more "the point" of its query). See
|
|
67
|
+
* {@link liftAnswer}. */
|
|
68
|
+
computed?: boolean;
|
|
69
|
+
};
|
|
70
|
+
export declare const STEP = 1;
|
|
71
|
+
export declare const CONCEPT = 10;
|
|
72
|
+
export declare const PASS = 1000;
|
|
73
|
+
/** The cheapest local cost in the ladder: a recognised completion bridging into
|
|
74
|
+
* the cover. Far below STEP, so connecting two recognised spans never disturbs
|
|
75
|
+
* the ordering — and, being the minimum per-position cost, it is the per-byte
|
|
76
|
+
* unit of the admissible search heuristic (see {@link GraphSearch.buildSearch}). */
|
|
77
|
+
export declare const MICRO = 0.001;
|
|
78
|
+
/** One chosen span of the cover, left to right. `node` is the graph node the
|
|
79
|
+
* span resolved to (when known) — for a recognised completion it is the chain's
|
|
80
|
+
* terminal node, the foothold the bridge walks edges from. */
|
|
81
|
+
export interface Seg {
|
|
82
|
+
i: number;
|
|
83
|
+
j: number;
|
|
84
|
+
bytes: Uint8Array;
|
|
85
|
+
rec: boolean;
|
|
86
|
+
node?: number;
|
|
87
|
+
/** See the `computed` field of the "out" {@link GItem} — set only for an
|
|
88
|
+
* extension's derived value, never a genuinely recognised learned form. */
|
|
89
|
+
computed?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/** One rule application inside the cover's lightest derivation — the FINEST
|
|
92
|
+
* grain of Sema's core reasoning, one node of the adapted A*LD proof tree. `move`
|
|
93
|
+
* names which deduction rule fired (the reasoning act); `premises` and
|
|
94
|
+
* `conclusion` are the items it consumed and produced, each rendered as a
|
|
95
|
+
* positioned, possibly-node-bearing span; `cost` is the rule's local weight
|
|
96
|
+
* (STEP for a learned edge, CONCEPT for a synonym hop, 0 for a free fuse, …);
|
|
97
|
+
* `order` is its post-order position so a tracer can replay the proof in the
|
|
98
|
+
* order it was built (premises before conclusion). */
|
|
99
|
+
export interface DerivationStep {
|
|
100
|
+
order: number;
|
|
101
|
+
move: DerivationMove;
|
|
102
|
+
premises: DerivationItem[];
|
|
103
|
+
conclusion: DerivationItem;
|
|
104
|
+
cost: number;
|
|
105
|
+
/** The `order`s of the steps that produced this one's premises — the EXACT
|
|
106
|
+
* data-flow edges of the proof tree (a `bridge` names the `ground` whose
|
|
107
|
+
* `out` it crossed and the earlier `cover` it extended). A premise that is
|
|
108
|
+
* an axiom (a seed leaf/form/computed result, never a rule conclusion) has no
|
|
109
|
+
* producer and contributes no edge, so this lists only the derived premises —
|
|
110
|
+
* the finest dependency structure the inference holds. */
|
|
111
|
+
producers: number[];
|
|
112
|
+
}
|
|
113
|
+
/** A premise or conclusion of a {@link DerivationStep}, flattened from a {@link
|
|
114
|
+
* GItem} into the fields a rationale cares about. */
|
|
115
|
+
export interface DerivationItem {
|
|
116
|
+
kind: "cover" | "form" | "out";
|
|
117
|
+
/** `[i, j)` span for a form/out; for a cover item, `[p, p]`. */
|
|
118
|
+
span: [number, number];
|
|
119
|
+
/** The bytes an `out` carries (the only item kind that holds output bytes). */
|
|
120
|
+
bytes?: Uint8Array;
|
|
121
|
+
/** The graph node a form/out resolves to, when known. */
|
|
122
|
+
node?: number;
|
|
123
|
+
}
|
|
124
|
+
/** The reasoning act a derivation rule performs — the human name for which of
|
|
125
|
+
* {@link GraphSearch}'s rules fired, recovered from the rule's premise/
|
|
126
|
+
* conclusion shape (the rules carry no label, so this classifies by structure,
|
|
127
|
+
* the single place that maps rule geometry to a name). */
|
|
128
|
+
export type DerivationMove = "axiom" | "follow-edge" | "concept-hop" | "voice" | "ground" | "splice-connector" | "split" | "fuse" | "recompose" | "bridge" | "pool-vote" | "step";
|
|
129
|
+
/** The lightest-derivation search over the Sema graph. One instance binds the
|
|
130
|
+
* store, `maxGroup` (the fusible span ceiling), and the canonical
|
|
131
|
+
* {@link resolve} callback; {@link cover} then solves one query. */
|
|
132
|
+
export declare class GraphSearch {
|
|
133
|
+
private readonly store;
|
|
134
|
+
private readonly maxGroup;
|
|
135
|
+
/** The host whose capabilities the search consults: resolve (canonical node
|
|
136
|
+
* id of a byte span), recogniseSpan (content-addressed graph lookup for
|
|
137
|
+
* recursive completion), and chooseNext (distributional-evidence edge
|
|
138
|
+
* disambiguation when a recognised form has multiple continuations). */
|
|
139
|
+
private readonly host;
|
|
140
|
+
constructor(store: Store, maxGroup: number,
|
|
141
|
+
/** The host whose capabilities the search consults: resolve (canonical node
|
|
142
|
+
* id of a byte span), recogniseSpan (content-addressed graph lookup for
|
|
143
|
+
* recursive completion), and chooseNext (distributional-evidence edge
|
|
144
|
+
* disambiguation when a recognised form has multiple continuations). */
|
|
145
|
+
host: GraphSearchHost);
|
|
146
|
+
/** Explore the Sema graph for the lightest cover of the query and return its
|
|
147
|
+
* chosen spans left-to-right — WITH the derivation's total weight (the g
|
|
148
|
+
* value of the goal item, in the exported cost ladder), which think's
|
|
149
|
+
* grounding decider compares against the other mechanisms' candidates —
|
|
150
|
+
* or null if the query cannot be covered.
|
|
151
|
+
*
|
|
152
|
+
* The search runs on the query's tree leaves, not flat bytes — leaf-level
|
|
153
|
+
* cover axioms, recognised forms as graph entry points — and discovers
|
|
154
|
+
* cross-leaf forms by fusing adjacent fragments on demand (the only
|
|
155
|
+
* byte-processing it does, and only where a derivation needs it). When
|
|
156
|
+
* `substitutions` is given, recognised forms emit substitute bytes directly
|
|
157
|
+
* (cost 0) — articulation splicing the asker's wording in.
|
|
158
|
+
*
|
|
159
|
+
* Any learnt connector between two rewrites is spliced IN by the in-search
|
|
160
|
+
* connector rule (see {@link outRules}), so the returned spans already carry
|
|
161
|
+
* it — there is no post-pass. */
|
|
162
|
+
cover(queryLen: number, sites: ReadonlyArray<Site>, conceptTarget: ReadonlyMap<number, number>, leaves: ReadonlyArray<Leaf>, splits: ReadonlySet<number>, starts: ReadonlySet<number>, substitutions?: ReadonlyMap<number, Uint8Array>, connectors?: ReadonlyMap<string, Uint8Array>, computedResults?: ReadonlyArray<ComputedResult>,
|
|
163
|
+
/** When given, receives the lightest derivation's rule applications — the
|
|
164
|
+
* full adapted A*LD proof tree as classified {@link DerivationStep}s — for the TOP
|
|
165
|
+
* cover only (a recursive recompletion solves its own sub-cover and is not
|
|
166
|
+
* reported here, to keep the trace one layer per think). Off by default,
|
|
167
|
+
* so the search pays nothing when no one inspects. */
|
|
168
|
+
onDerivation?: (steps: DerivationStep[]) => void): {
|
|
169
|
+
segs: Seg[];
|
|
170
|
+
cost: number;
|
|
171
|
+
} | null;
|
|
172
|
+
/** Build the deduction system for one span and return its lightest cover's
|
|
173
|
+
* chosen spans — the SINGLE routine the query and every produced composite
|
|
174
|
+
* run through. `recognition` carries the span's recognised forms; the query
|
|
175
|
+
* brings its own (with pre-resolved concepts/connectors), a recursive
|
|
176
|
+
* completion re-recognises the produced bytes (edge/fuse only).
|
|
177
|
+
*
|
|
178
|
+
* No depth limit governs nesting — convergence is INTRINSIC, exactly as in the
|
|
179
|
+
* adapted A*LD chart and {@link completeForward}: a completion only recurses into a
|
|
180
|
+
* node it has not already entered ({@link recompleteNode}'s cycle guard), and
|
|
181
|
+
* the node ids are finite, so the recursion must terminate on its own. A
|
|
182
|
+
* decomposition may therefore run as deep as the graph licenses — three
|
|
183
|
+
* decomposes, two recomposes, any mix — and stops only when it reaches a node
|
|
184
|
+
* that leads nowhere new, never at an arbitrary count. */
|
|
185
|
+
private solve;
|
|
186
|
+
/** The weighted deduction system the graph exploration solves (the four
|
|
187
|
+
* reductions of adapted A*LD live in {@link lightestDerivation}; this only states the
|
|
188
|
+
* items, axioms, goal, and rules — see {@link GItem} for the item kinds).
|
|
189
|
+
*
|
|
190
|
+
* Forms that span across leaves are discovered BY the rules, which fuse
|
|
191
|
+
* adjacent fragments toward a known leaf (findLeaf) or branch (findBranch);
|
|
192
|
+
* a completion fused with its neighbour may spell a deeper learned form the
|
|
193
|
+
* flat probes can't name, recovered canonically by {@link resolve}. */
|
|
194
|
+
private buildSearch;
|
|
195
|
+
/** cover(p): the BRIDGE rule — extend the cover across any coverable out that
|
|
196
|
+
* begins at p, stepping the frontier from p to that out's end.
|
|
197
|
+
*
|
|
198
|
+
* This is what links the rewritten parts of a multi-form answer. An out is
|
|
199
|
+
* either a recognised completion (`rec`, free) or a literal span the query
|
|
200
|
+
* carried between known forms — the connective: a space, comma, period,
|
|
201
|
+
* newline, or any run of bytes that was never recognised. Bridging a literal
|
|
202
|
+
* costs PASS per byte (so the search still prefers to recognise), but it is
|
|
203
|
+
* the cheapest — indeed only — way to cross a gap that has no learned form,
|
|
204
|
+
* and it KEEPS that connective in the cover chain, so the asker's own linking
|
|
205
|
+
* material reappears when it still coheres ("ice, fire" → "cold, hot", not
|
|
206
|
+
* "coldhot"). A recognised completion bridges for a tiny ε (1e-3, far below
|
|
207
|
+
* STEP), so a single connected span beats two separate ones on coherence
|
|
208
|
+
* without disturbing the cost ladder's ordering.
|
|
209
|
+
*
|
|
210
|
+
* Marks p finalised so the symmetric out-side bridge ({@link outRules}) can
|
|
211
|
+
* fire for outs that arrive after their start position is covered. */
|
|
212
|
+
private coverRules;
|
|
213
|
+
/** The BRIDGE rule, built once for its two arrival orders (cover-first in
|
|
214
|
+
* {@link coverRules}, out-first in {@link outRules}): ε for a recognised
|
|
215
|
+
* completion; PASS per byte for a literal connective — kept in the cover
|
|
216
|
+
* so the asker's own connector survives where it fits. ONE definition of
|
|
217
|
+
* the cost expression, so the ladder's application cannot drift between
|
|
218
|
+
* the two sides. */
|
|
219
|
+
private bridgeRule;
|
|
220
|
+
/** The connector-SPLICE rule for an oriented (l, r) pair, or null when the
|
|
221
|
+
* pair does not qualify — the ONE body behind {@link outRules}' two
|
|
222
|
+
* mirror loops (this-as-left over resolved right partners, this-as-right
|
|
223
|
+
* over resolved left partners). Fires only when both sides are
|
|
224
|
+
* recognised, r starts at or after l ends, and the gap between them is
|
|
225
|
+
* empty or wholly recognised — never across the asker's own literal
|
|
226
|
+
* separator. */
|
|
227
|
+
private trySplice;
|
|
228
|
+
/** form(i,j,node,via): follow the graph out of `node`, or (in articulation)
|
|
229
|
+
* emit its substitute voice directly. */
|
|
230
|
+
private formRules;
|
|
231
|
+
/** Complete a node that an edge produced but that bears no further whole-edge,
|
|
232
|
+
* by COVERING ITS OWN BYTES — the very same operation the top query runs.
|
|
233
|
+
* Completion is not a special pass: a produced composite ("p1 p2") is just
|
|
234
|
+
* another span to cover, and covering it re-applies recognition, edge-follow,
|
|
235
|
+
* fusion and recomposition to discover that its parts continue (p1→R1, p2→R2)
|
|
236
|
+
* and recompose into a deeper learnt form (→ FINAL). This is why a single
|
|
237
|
+
* edge-target needs no bespoke logic — it routes back through {@link solve}.
|
|
238
|
+
*
|
|
239
|
+
* Re-recognition (not the node's tree children) is what surfaces the learnt
|
|
240
|
+
* parts: content-defined chunking may cut "p1 p2" as "p1 p"|"2", so only
|
|
241
|
+
* recognising the bytes recovers p1 and p2 as the forms the graph knows.
|
|
242
|
+
*
|
|
243
|
+
* The recovered answer is accepted only when it MOVED and names a LEARNT node
|
|
244
|
+
* ({@link resolve}) — the graph itself gates against re-expanding a contained
|
|
245
|
+
* form ("ice is cold" ⊅→ "ice is cold is cold").
|
|
246
|
+
*
|
|
247
|
+
* Termination is INTRINSIC, not a depth limit: a node already on the
|
|
248
|
+
* completion stack ({@link recompleteOpen}) is not re-entered — a self-
|
|
249
|
+
* referential recomposition is a cycle that can yield nothing new, so it
|
|
250
|
+
* stops there, exactly as {@link completeForward} stops on a revisited edge.
|
|
251
|
+
* Distinct node ids are finite and each finished completion is memoised, so a
|
|
252
|
+
* legitimate chain runs as deep as the graph licenses and no further. */
|
|
253
|
+
private recompleteNode;
|
|
254
|
+
/** Per-cover memo of each produced node's completion (so the many terminal
|
|
255
|
+
* outs of a long query re-cover each distinct node at most once); reset at the
|
|
256
|
+
* top of {@link cover}. */
|
|
257
|
+
private recompleteMemo;
|
|
258
|
+
/** The nodes currently being re-completed — the recursion stack. A node in
|
|
259
|
+
* this set is not re-entered, so a cyclic recomposition terminates naturally
|
|
260
|
+
* (the same cycle guard {@link completeForward} uses), with no depth cap. */
|
|
261
|
+
private recompleteOpen;
|
|
262
|
+
/** out(i,j,bytes,…): index it for the binary rules, then offer splicing a
|
|
263
|
+
* learnt connector (the in-search bridge), splitting (at a sub-leaf form
|
|
264
|
+
* boundary), bridging (cover(i) ∧ this → cover(j)), and fusing with an
|
|
265
|
+
* adjacent finalised out. */
|
|
266
|
+
private outRules;
|
|
267
|
+
/** Whether the query span [from, to) is wholly covered by RECOGNISED outs —
|
|
268
|
+
* the test that lets a connector jump across INTERIOR answers (an N-ary whole)
|
|
269
|
+
* but never across the asker's own unrecognised framing (a space or comma the
|
|
270
|
+
* asker wrote between parts). Empty span (from === to, the adjacent case) is
|
|
271
|
+
* trivially recognised. Otherwise step right-to-left: from `to`, find a
|
|
272
|
+
* recognised out ending there and continue from its start, until reaching
|
|
273
|
+
* `from`. Greedy-longest is sufficient here — the spans in play are the few
|
|
274
|
+
* recognised answers of one query, not a general interval cover. */
|
|
275
|
+
private gapRecognised;
|
|
276
|
+
/** Fuse two adjacent finalised outs — the search's own discovery of forms
|
|
277
|
+
* that cross leaf boundaries. The concatenation may be a known leaf
|
|
278
|
+
* (findLeaf, when short enough), or — when both sides resolved — their pair a
|
|
279
|
+
* known branch (findBranch); a completion fused with its neighbour may spell
|
|
280
|
+
* a deeper learned form, recovered canonically by {@link resolve} (gated on a
|
|
281
|
+
* completion being present, so it only runs along chains). The fused span
|
|
282
|
+
* lives on as an intermediate out while it could still grow into a form, and
|
|
283
|
+
* enters the graph as a form the moment it names a node. */
|
|
284
|
+
private fuse;
|
|
285
|
+
}
|