simple-graph-query 2.3.0 → 2.5.0
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 +28 -0
- package/dist/SelectorSynthesizer.d.ts +48 -0
- package/dist/index.d.ts +1 -0
- package/dist/simple-graph-query.bundle.js +395 -60
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,3 +6,31 @@ A TypeScript library for evaluating relational + some more expressions with a br
|
|
|
6
6
|
|
|
7
7
|
MIT
|
|
8
8
|
|
|
9
|
+
## Selector synthesis overview
|
|
10
|
+
|
|
11
|
+
The selector synthesizer infers a relational expression that returns exactly the atoms supplied in a set of training examples (pairs of `Set<IAtom>` and `IDataInstance`). The current implementation uses a bounded, enumerative search over a compact expression grammar (identifiers, unions/intersections/differences, joins, and transitive closure) that mirrors a lightweight Alloy fragment. The search works breadth-first by depth so that the first solution found is the simplest expression within the bound, and it only explores identifiers shared by every example plus Alloy built-ins like `univ` and `iden`.
|
|
12
|
+
|
|
13
|
+
Although the implementation is enumerative, it follows the same spirit as CEGIS and FOIL-style learners: each candidate expression is validated against every provided example, immediately pruning failures before expanding the search frontier. This tight feedback loop keeps the search space tractable in bounded instances while still allowing compositional operators (e.g., joins composed under closure) to satisfy more relational targets. Raising the `maxDepth` parameter broadens the hypothesis space when more complex solutions are needed, while lower depths keep synthesis fast for simple selectors.
|
|
14
|
+
|
|
15
|
+
### Synthesis "why" explanations
|
|
16
|
+
|
|
17
|
+
The `synthesizeSelectorWithWhy` and `synthesizeBinaryRelationWithWhy` helpers return a provenance tree alongside the synthesized expression. Each returned `examples[i].why` value mirrors the final expression: every node records the operator kind, the textual subexpression, and the evaluated result for that subexpression in the corresponding datum. Binary operators (union, intersection, difference, join) list two children, closures list one, and identifiers are leaves.
|
|
18
|
+
|
|
19
|
+
For example, synthesizing a selector for `{a1, a2}` and `{b1}` produces:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
const { expression, examples } = synthesizeSelectorWithWhy([
|
|
23
|
+
{ atoms: new Set([a1, a2]), datum: datumA },
|
|
24
|
+
{ atoms: new Set([b1]), datum: datumB },
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
// expression === "Thing"
|
|
28
|
+
// examples[0].why === {
|
|
29
|
+
// kind: "identifier",
|
|
30
|
+
// expression: "Thing",
|
|
31
|
+
// result: new Set(["a1", "a2"]),
|
|
32
|
+
// }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Synthesizing a binary relation explanation yields the same structure, but `result` contains normalized tuple identifiers (e.g., `"n1\u0000n3"`) for each subexpression. For a two-hop reachability example, the root `why` node would have `kind: "join"` with two child nodes describing the `edge` relations on the left and right of the join.
|
|
36
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { IAtom, IDataInstance } from "./types";
|
|
2
|
+
export type AtomSelectionExample = {
|
|
3
|
+
atoms: Set<IAtom>;
|
|
4
|
+
datum: IDataInstance;
|
|
5
|
+
};
|
|
6
|
+
export type AtomPair = readonly [IAtom, IAtom];
|
|
7
|
+
export type BinaryRelationExample = {
|
|
8
|
+
pairs: Set<AtomPair>;
|
|
9
|
+
datum: IDataInstance;
|
|
10
|
+
};
|
|
11
|
+
type ExpressionNode = {
|
|
12
|
+
kind: "identifier";
|
|
13
|
+
name: string;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "union" | "intersection" | "difference";
|
|
16
|
+
left: ExpressionNode;
|
|
17
|
+
right: ExpressionNode;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "join";
|
|
20
|
+
left: ExpressionNode;
|
|
21
|
+
right: ExpressionNode;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "closure";
|
|
24
|
+
child: ExpressionNode;
|
|
25
|
+
};
|
|
26
|
+
export type WhyNode = {
|
|
27
|
+
kind: ExpressionNode["kind"];
|
|
28
|
+
expression: string;
|
|
29
|
+
result: Set<string> | null;
|
|
30
|
+
children?: WhyNode[];
|
|
31
|
+
};
|
|
32
|
+
export declare class SelectorSynthesisError extends Error {
|
|
33
|
+
}
|
|
34
|
+
export declare function synthesizeSelector(examples: AtomSelectionExample[], maxDepth?: number): string;
|
|
35
|
+
export declare function synthesizeBinaryRelation(examples: BinaryRelationExample[], maxDepth?: number): string;
|
|
36
|
+
export type SynthesisWhyExample = {
|
|
37
|
+
datum: IDataInstance;
|
|
38
|
+
target: Set<string>;
|
|
39
|
+
result: Set<string> | null;
|
|
40
|
+
why: WhyNode;
|
|
41
|
+
};
|
|
42
|
+
export type SynthesisWhy = {
|
|
43
|
+
expression: string;
|
|
44
|
+
examples: SynthesisWhyExample[];
|
|
45
|
+
};
|
|
46
|
+
export declare function synthesizeSelectorWithWhy(examples: AtomSelectionExample[], maxDepth?: number): SynthesisWhy;
|
|
47
|
+
export declare function synthesizeBinaryRelationWithWhy(examples: BinaryRelationExample[], maxDepth?: number): SynthesisWhy;
|
|
48
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -16,3 +16,4 @@ export declare class SimpleGraphQueryEvaluator {
|
|
|
16
16
|
getExpressionParseTree(forgeExpr: string): import("./forge-antlr/ForgeParser").ParseExprContext;
|
|
17
17
|
evaluateExpression(forgeExpr: string): EvaluationResult;
|
|
18
18
|
}
|
|
19
|
+
export { synthesizeSelector, synthesizeBinaryRelation, synthesizeBinaryRelationWithWhy, synthesizeSelectorWithWhy, AtomSelectionExample, BinaryRelationExample, SelectorSynthesisError, SynthesisWhy, SynthesisWhyExample, WhyNode, } from './SelectorSynthesizer';
|
|
@@ -50931,6 +50931,329 @@ function cartesianProduct(arrays) {
|
|
|
50931
50931
|
}
|
|
50932
50932
|
|
|
50933
50933
|
|
|
50934
|
+
/***/ }),
|
|
50935
|
+
|
|
50936
|
+
/***/ "./src/SelectorSynthesizer.ts":
|
|
50937
|
+
/*!************************************!*\
|
|
50938
|
+
!*** ./src/SelectorSynthesizer.ts ***!
|
|
50939
|
+
\************************************/
|
|
50940
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
50941
|
+
|
|
50942
|
+
"use strict";
|
|
50943
|
+
|
|
50944
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
50945
|
+
exports.SelectorSynthesisError = void 0;
|
|
50946
|
+
exports.synthesizeSelector = synthesizeSelector;
|
|
50947
|
+
exports.synthesizeBinaryRelation = synthesizeBinaryRelation;
|
|
50948
|
+
exports.synthesizeSelectorWithWhy = synthesizeSelectorWithWhy;
|
|
50949
|
+
exports.synthesizeBinaryRelationWithWhy = synthesizeBinaryRelationWithWhy;
|
|
50950
|
+
const index_1 = __webpack_require__(/*! ./index */ "./src/index.ts");
|
|
50951
|
+
class SelectorSynthesisError extends Error {
|
|
50952
|
+
}
|
|
50953
|
+
exports.SelectorSynthesisError = SelectorSynthesisError;
|
|
50954
|
+
function nodeToString(node) {
|
|
50955
|
+
switch (node.kind) {
|
|
50956
|
+
case "identifier":
|
|
50957
|
+
return node.name;
|
|
50958
|
+
case "closure": {
|
|
50959
|
+
const inner = nodeToString(node.child);
|
|
50960
|
+
return `^${wrapForPrefix(inner)}`;
|
|
50961
|
+
}
|
|
50962
|
+
case "join": {
|
|
50963
|
+
const left = wrapForJoin(node.left);
|
|
50964
|
+
const right = wrapForJoin(node.right);
|
|
50965
|
+
return `${left}.${right}`;
|
|
50966
|
+
}
|
|
50967
|
+
case "union":
|
|
50968
|
+
return `(${nodeToString(node.left)} + ${nodeToString(node.right)})`;
|
|
50969
|
+
case "intersection":
|
|
50970
|
+
return `(${nodeToString(node.left)} & ${nodeToString(node.right)})`;
|
|
50971
|
+
case "difference":
|
|
50972
|
+
return `(${nodeToString(node.left)} - ${nodeToString(node.right)})`;
|
|
50973
|
+
}
|
|
50974
|
+
}
|
|
50975
|
+
function wrapForJoin(node) {
|
|
50976
|
+
if (node.kind === "identifier" || node.kind === "closure") {
|
|
50977
|
+
return nodeToString(node);
|
|
50978
|
+
}
|
|
50979
|
+
return `(${nodeToString(node)})`;
|
|
50980
|
+
}
|
|
50981
|
+
function wrapForPrefix(expr) {
|
|
50982
|
+
return expr.startsWith("(") && expr.endsWith(")") ? expr : `(${expr})`;
|
|
50983
|
+
}
|
|
50984
|
+
function normalizeUnaryResult(result) {
|
|
50985
|
+
// We only consider unary tuple results or single string values as valid atom selections
|
|
50986
|
+
if (typeof result === "string") {
|
|
50987
|
+
return new Set([result]);
|
|
50988
|
+
}
|
|
50989
|
+
if (!Array.isArray(result)) {
|
|
50990
|
+
return null;
|
|
50991
|
+
}
|
|
50992
|
+
// Expect an array of tuples
|
|
50993
|
+
const tuples = result;
|
|
50994
|
+
const ids = new Set();
|
|
50995
|
+
for (const tuple of tuples) {
|
|
50996
|
+
if (!Array.isArray(tuple) || tuple.length !== 1) {
|
|
50997
|
+
return null;
|
|
50998
|
+
}
|
|
50999
|
+
const value = tuple[0];
|
|
51000
|
+
if (typeof value !== "string") {
|
|
51001
|
+
return null;
|
|
51002
|
+
}
|
|
51003
|
+
ids.add(value);
|
|
51004
|
+
}
|
|
51005
|
+
return ids;
|
|
51006
|
+
}
|
|
51007
|
+
function normalizeBinaryResult(result) {
|
|
51008
|
+
if (!Array.isArray(result)) {
|
|
51009
|
+
return null;
|
|
51010
|
+
}
|
|
51011
|
+
const tuples = result;
|
|
51012
|
+
const ids = new Set();
|
|
51013
|
+
for (const tuple of tuples) {
|
|
51014
|
+
if (!Array.isArray(tuple) || tuple.length !== 2) {
|
|
51015
|
+
return null;
|
|
51016
|
+
}
|
|
51017
|
+
const [first, second] = tuple;
|
|
51018
|
+
if (typeof first !== "string" || typeof second !== "string") {
|
|
51019
|
+
return null;
|
|
51020
|
+
}
|
|
51021
|
+
ids.add(`${first}\u0000${second}`);
|
|
51022
|
+
}
|
|
51023
|
+
return ids;
|
|
51024
|
+
}
|
|
51025
|
+
function evaluateExpression(node, evaluator, normalizer) {
|
|
51026
|
+
const expression = nodeToString(node);
|
|
51027
|
+
const result = evaluator.evaluateExpression(expression);
|
|
51028
|
+
return normalizer(result);
|
|
51029
|
+
}
|
|
51030
|
+
function intersectNames(datums) {
|
|
51031
|
+
const identifierSets = datums.map((datum) => {
|
|
51032
|
+
const typeIds = datum.getTypes().map((t) => t.id);
|
|
51033
|
+
const relationNames = datum.getRelations().map((r) => r.name);
|
|
51034
|
+
return new Set([...typeIds, ...relationNames]);
|
|
51035
|
+
});
|
|
51036
|
+
if (identifierSets.length === 0) {
|
|
51037
|
+
return new Set();
|
|
51038
|
+
}
|
|
51039
|
+
const [first, ...rest] = identifierSets;
|
|
51040
|
+
const intersection = new Set();
|
|
51041
|
+
for (const id of first) {
|
|
51042
|
+
if (rest.every((set) => set.has(id))) {
|
|
51043
|
+
intersection.add(id);
|
|
51044
|
+
}
|
|
51045
|
+
}
|
|
51046
|
+
return intersection;
|
|
51047
|
+
}
|
|
51048
|
+
function setsEqual(a, b) {
|
|
51049
|
+
if (a.size !== b.size)
|
|
51050
|
+
return false;
|
|
51051
|
+
for (const item of a) {
|
|
51052
|
+
if (!b.has(item))
|
|
51053
|
+
return false;
|
|
51054
|
+
}
|
|
51055
|
+
return true;
|
|
51056
|
+
}
|
|
51057
|
+
function classifyIdentifier(name, datums) {
|
|
51058
|
+
if (name === "univ" || name === "iden") {
|
|
51059
|
+
return "builtin";
|
|
51060
|
+
}
|
|
51061
|
+
for (const datum of datums) {
|
|
51062
|
+
if (datum.getRelations().some((relation) => relation.name === name)) {
|
|
51063
|
+
return "relation";
|
|
51064
|
+
}
|
|
51065
|
+
if (datum.getTypes().some((type) => type.id === name)) {
|
|
51066
|
+
return "type";
|
|
51067
|
+
}
|
|
51068
|
+
}
|
|
51069
|
+
return "other";
|
|
51070
|
+
}
|
|
51071
|
+
function buildBaseNodes(datums) {
|
|
51072
|
+
const baseNames = intersectNames(datums);
|
|
51073
|
+
// Always include standard top-level identifiers when present in the language
|
|
51074
|
+
["univ", "iden"].forEach((builtin) => baseNames.add(builtin));
|
|
51075
|
+
const orderedNames = Array.from(baseNames).sort((left, right) => {
|
|
51076
|
+
const priority = {
|
|
51077
|
+
relation: 0,
|
|
51078
|
+
type: 1,
|
|
51079
|
+
builtin: 2,
|
|
51080
|
+
other: 3,
|
|
51081
|
+
};
|
|
51082
|
+
const leftPriority = priority[classifyIdentifier(left, datums)];
|
|
51083
|
+
const rightPriority = priority[classifyIdentifier(right, datums)];
|
|
51084
|
+
if (leftPriority !== rightPriority) {
|
|
51085
|
+
return leftPriority - rightPriority;
|
|
51086
|
+
}
|
|
51087
|
+
return left.localeCompare(right);
|
|
51088
|
+
});
|
|
51089
|
+
return orderedNames.map((name) => ({ kind: "identifier", name }));
|
|
51090
|
+
}
|
|
51091
|
+
function getOrCreateEvaluator(datum, cache) {
|
|
51092
|
+
const existing = cache.get(datum);
|
|
51093
|
+
if (existing) {
|
|
51094
|
+
return existing;
|
|
51095
|
+
}
|
|
51096
|
+
const evaluator = new index_1.SimpleGraphQueryEvaluator(datum);
|
|
51097
|
+
cache.set(datum, evaluator);
|
|
51098
|
+
return evaluator;
|
|
51099
|
+
}
|
|
51100
|
+
function matchesTargets(node, examples, normalizer) {
|
|
51101
|
+
for (const example of examples) {
|
|
51102
|
+
const result = evaluateExpression(node, example.evaluator, normalizer);
|
|
51103
|
+
if (!result)
|
|
51104
|
+
return false;
|
|
51105
|
+
if (!setsEqual(result, example.target)) {
|
|
51106
|
+
return false;
|
|
51107
|
+
}
|
|
51108
|
+
}
|
|
51109
|
+
return true;
|
|
51110
|
+
}
|
|
51111
|
+
function synthesizeExpressionNode(examples, normalizer, maxDepth = 3) {
|
|
51112
|
+
// Enumerative, CEGIS-style search: we BFS over the expression grammar (identifiers, set ops, joins, closure),
|
|
51113
|
+
// checking each candidate against *all* examples before allowing it to generate children. Early rejection of
|
|
51114
|
+
// incorrect hypotheses keeps the frontier small (FOIL-esque pruning), while depth-bounding curbs blowup.
|
|
51115
|
+
if (examples.length === 0) {
|
|
51116
|
+
throw new SelectorSynthesisError("No examples provided for synthesis");
|
|
51117
|
+
}
|
|
51118
|
+
const evaluatorCache = new Map();
|
|
51119
|
+
const evaluatedExamples = examples.map((example) => ({
|
|
51120
|
+
...example,
|
|
51121
|
+
evaluator: getOrCreateEvaluator(example.datum, evaluatorCache),
|
|
51122
|
+
}));
|
|
51123
|
+
const datums = evaluatedExamples.map((example) => example.datum);
|
|
51124
|
+
const baseNodes = buildBaseNodes(datums);
|
|
51125
|
+
if (baseNodes.length === 0) {
|
|
51126
|
+
throw new SelectorSynthesisError("No shared identifiers available across provided data instances");
|
|
51127
|
+
}
|
|
51128
|
+
for (const node of baseNodes) {
|
|
51129
|
+
if (matchesTargets(node, evaluatedExamples, normalizer)) {
|
|
51130
|
+
return node;
|
|
51131
|
+
}
|
|
51132
|
+
}
|
|
51133
|
+
const queue = [];
|
|
51134
|
+
const queued = new Set();
|
|
51135
|
+
const visited = new Set();
|
|
51136
|
+
const combinationPool = [...baseNodes];
|
|
51137
|
+
const enqueue = (node, depth) => {
|
|
51138
|
+
const key = nodeToString(node);
|
|
51139
|
+
if (visited.has(key) || queued.has(key))
|
|
51140
|
+
return;
|
|
51141
|
+
queue.push({ node, depth });
|
|
51142
|
+
queued.add(key);
|
|
51143
|
+
};
|
|
51144
|
+
baseNodes.forEach((node) => enqueue(node, 0));
|
|
51145
|
+
while (queue.length > 0) {
|
|
51146
|
+
const current = queue.shift();
|
|
51147
|
+
const key = nodeToString(current.node);
|
|
51148
|
+
queued.delete(key);
|
|
51149
|
+
if (visited.has(key)) {
|
|
51150
|
+
continue;
|
|
51151
|
+
}
|
|
51152
|
+
visited.add(key);
|
|
51153
|
+
if (matchesTargets(current.node, evaluatedExamples, normalizer)) {
|
|
51154
|
+
return current.node;
|
|
51155
|
+
}
|
|
51156
|
+
if (current.depth >= maxDepth) {
|
|
51157
|
+
continue;
|
|
51158
|
+
}
|
|
51159
|
+
// Unary expansions
|
|
51160
|
+
enqueue({ kind: "closure", child: current.node }, current.depth + 1);
|
|
51161
|
+
for (const other of combinationPool) {
|
|
51162
|
+
const leftKey = nodeToString(current.node);
|
|
51163
|
+
const rightKey = nodeToString(other);
|
|
51164
|
+
const [unionLeft, unionRight] = leftKey < rightKey ? [current.node, other] : [other, current.node];
|
|
51165
|
+
enqueue({ kind: "union", left: unionLeft, right: unionRight }, current.depth + 1);
|
|
51166
|
+
const [interLeft, interRight] = leftKey < rightKey ? [current.node, other] : [other, current.node];
|
|
51167
|
+
enqueue({ kind: "intersection", left: interLeft, right: interRight }, current.depth + 1);
|
|
51168
|
+
enqueue({ kind: "join", left: current.node, right: other }, current.depth + 1);
|
|
51169
|
+
enqueue({ kind: "join", left: other, right: current.node }, current.depth + 1);
|
|
51170
|
+
}
|
|
51171
|
+
}
|
|
51172
|
+
throw new SelectorSynthesisError("Unable to synthesize an expression matching all examples");
|
|
51173
|
+
}
|
|
51174
|
+
function synthesizeSelector(examples, maxDepth = 3) {
|
|
51175
|
+
const synthesisExamples = examples.map((example) => ({
|
|
51176
|
+
datum: example.datum,
|
|
51177
|
+
target: new Set(Array.from(example.atoms).map((atom) => atom.id)),
|
|
51178
|
+
}));
|
|
51179
|
+
const node = synthesizeExpressionNode(synthesisExamples, normalizeUnaryResult, maxDepth);
|
|
51180
|
+
return nodeToString(node);
|
|
51181
|
+
}
|
|
51182
|
+
function synthesizeBinaryRelation(examples, maxDepth = 3) {
|
|
51183
|
+
const synthesisExamples = examples.map((example) => {
|
|
51184
|
+
const encodedPairs = new Set(Array.from(example.pairs).map(([left, right]) => `${left.id}\u0000${right.id}`));
|
|
51185
|
+
return { datum: example.datum, target: encodedPairs };
|
|
51186
|
+
});
|
|
51187
|
+
const node = synthesizeExpressionNode(synthesisExamples, normalizeBinaryResult, maxDepth);
|
|
51188
|
+
return nodeToString(node);
|
|
51189
|
+
}
|
|
51190
|
+
function buildWhyNode(node, evaluator, normalizer) {
|
|
51191
|
+
const result = evaluateExpression(node, evaluator, normalizer);
|
|
51192
|
+
const base = {
|
|
51193
|
+
kind: node.kind,
|
|
51194
|
+
expression: nodeToString(node),
|
|
51195
|
+
result,
|
|
51196
|
+
};
|
|
51197
|
+
switch (node.kind) {
|
|
51198
|
+
case "identifier":
|
|
51199
|
+
return base;
|
|
51200
|
+
case "closure":
|
|
51201
|
+
return { ...base, children: [buildWhyNode(node.child, evaluator, normalizer)] };
|
|
51202
|
+
case "join":
|
|
51203
|
+
case "union":
|
|
51204
|
+
case "intersection":
|
|
51205
|
+
case "difference":
|
|
51206
|
+
return {
|
|
51207
|
+
...base,
|
|
51208
|
+
children: [
|
|
51209
|
+
buildWhyNode(node.left, evaluator, normalizer),
|
|
51210
|
+
buildWhyNode(node.right, evaluator, normalizer),
|
|
51211
|
+
],
|
|
51212
|
+
};
|
|
51213
|
+
default:
|
|
51214
|
+
return base;
|
|
51215
|
+
}
|
|
51216
|
+
}
|
|
51217
|
+
function synthesizeSelectorWithWhy(examples, maxDepth = 3) {
|
|
51218
|
+
const synthesisExamples = examples.map((example) => ({
|
|
51219
|
+
datum: example.datum,
|
|
51220
|
+
target: new Set(Array.from(example.atoms).map((atom) => atom.id)),
|
|
51221
|
+
}));
|
|
51222
|
+
const node = synthesizeExpressionNode(synthesisExamples, normalizeUnaryResult, maxDepth);
|
|
51223
|
+
const expression = nodeToString(node);
|
|
51224
|
+
const evaluatorCache = new Map();
|
|
51225
|
+
const explanationExamples = synthesisExamples.map((example) => {
|
|
51226
|
+
const evaluator = getOrCreateEvaluator(example.datum, evaluatorCache);
|
|
51227
|
+
return {
|
|
51228
|
+
datum: example.datum,
|
|
51229
|
+
target: example.target,
|
|
51230
|
+
result: evaluateExpression(node, evaluator, normalizeUnaryResult),
|
|
51231
|
+
why: buildWhyNode(node, evaluator, normalizeUnaryResult),
|
|
51232
|
+
};
|
|
51233
|
+
});
|
|
51234
|
+
return { expression, examples: explanationExamples };
|
|
51235
|
+
}
|
|
51236
|
+
function synthesizeBinaryRelationWithWhy(examples, maxDepth = 3) {
|
|
51237
|
+
const synthesisExamples = examples.map((example) => {
|
|
51238
|
+
const encodedPairs = new Set(Array.from(example.pairs).map(([left, right]) => `${left.id}\u0000${right.id}`));
|
|
51239
|
+
return { datum: example.datum, target: encodedPairs };
|
|
51240
|
+
});
|
|
51241
|
+
const node = synthesizeExpressionNode(synthesisExamples, normalizeBinaryResult, maxDepth);
|
|
51242
|
+
const expression = nodeToString(node);
|
|
51243
|
+
const evaluatorCache = new Map();
|
|
51244
|
+
const explanationExamples = synthesisExamples.map((example) => {
|
|
51245
|
+
const evaluator = getOrCreateEvaluator(example.datum, evaluatorCache);
|
|
51246
|
+
return {
|
|
51247
|
+
datum: example.datum,
|
|
51248
|
+
target: example.target,
|
|
51249
|
+
result: evaluateExpression(node, evaluator, normalizeBinaryResult),
|
|
51250
|
+
why: buildWhyNode(node, evaluator, normalizeBinaryResult),
|
|
51251
|
+
};
|
|
51252
|
+
});
|
|
51253
|
+
return { expression, examples: explanationExamples };
|
|
51254
|
+
}
|
|
51255
|
+
|
|
51256
|
+
|
|
50934
51257
|
/***/ }),
|
|
50935
51258
|
|
|
50936
51259
|
/***/ "./src/errorListener.ts":
|
|
@@ -61472,71 +61795,18 @@ class ConsistencyAssertionTest extends SyntaxNode {
|
|
|
61472
61795
|
exports.ConsistencyAssertionTest = ConsistencyAssertionTest;
|
|
61473
61796
|
|
|
61474
61797
|
|
|
61475
|
-
/***/ })
|
|
61798
|
+
/***/ }),
|
|
61476
61799
|
|
|
61477
|
-
|
|
61478
|
-
/************************************************************************/
|
|
61479
|
-
/******/ // The module cache
|
|
61480
|
-
/******/ var __webpack_module_cache__ = {};
|
|
61481
|
-
/******/
|
|
61482
|
-
/******/ // The require function
|
|
61483
|
-
/******/ function __webpack_require__(moduleId) {
|
|
61484
|
-
/******/ // Check if module is in cache
|
|
61485
|
-
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
61486
|
-
/******/ if (cachedModule !== undefined) {
|
|
61487
|
-
/******/ return cachedModule.exports;
|
|
61488
|
-
/******/ }
|
|
61489
|
-
/******/ // Create a new module (and put it into the cache)
|
|
61490
|
-
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
61491
|
-
/******/ id: moduleId,
|
|
61492
|
-
/******/ loaded: false,
|
|
61493
|
-
/******/ exports: {}
|
|
61494
|
-
/******/ };
|
|
61495
|
-
/******/
|
|
61496
|
-
/******/ // Execute the module function
|
|
61497
|
-
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
61498
|
-
/******/
|
|
61499
|
-
/******/ // Flag the module as loaded
|
|
61500
|
-
/******/ module.loaded = true;
|
|
61501
|
-
/******/
|
|
61502
|
-
/******/ // Return the exports of the module
|
|
61503
|
-
/******/ return module.exports;
|
|
61504
|
-
/******/ }
|
|
61505
|
-
/******/
|
|
61506
|
-
/************************************************************************/
|
|
61507
|
-
/******/ /* webpack/runtime/global */
|
|
61508
|
-
/******/ (() => {
|
|
61509
|
-
/******/ __webpack_require__.g = (function() {
|
|
61510
|
-
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
61511
|
-
/******/ try {
|
|
61512
|
-
/******/ return this || new Function('return this')();
|
|
61513
|
-
/******/ } catch (e) {
|
|
61514
|
-
/******/ if (typeof window === 'object') return window;
|
|
61515
|
-
/******/ }
|
|
61516
|
-
/******/ })();
|
|
61517
|
-
/******/ })();
|
|
61518
|
-
/******/
|
|
61519
|
-
/******/ /* webpack/runtime/node module decorator */
|
|
61520
|
-
/******/ (() => {
|
|
61521
|
-
/******/ __webpack_require__.nmd = (module) => {
|
|
61522
|
-
/******/ module.paths = [];
|
|
61523
|
-
/******/ if (!module.children) module.children = [];
|
|
61524
|
-
/******/ return module;
|
|
61525
|
-
/******/ };
|
|
61526
|
-
/******/ })();
|
|
61527
|
-
/******/
|
|
61528
|
-
/************************************************************************/
|
|
61529
|
-
var __webpack_exports__ = {};
|
|
61530
|
-
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
|
|
61531
|
-
(() => {
|
|
61532
|
-
"use strict";
|
|
61533
|
-
var exports = __webpack_exports__;
|
|
61800
|
+
/***/ "./src/index.ts":
|
|
61534
61801
|
/*!**********************!*\
|
|
61535
61802
|
!*** ./src/index.ts ***!
|
|
61536
61803
|
\**********************/
|
|
61804
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
61805
|
+
|
|
61806
|
+
"use strict";
|
|
61537
61807
|
|
|
61538
61808
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
61539
|
-
exports.SimpleGraphQueryEvaluator = void 0;
|
|
61809
|
+
exports.SelectorSynthesisError = exports.synthesizeSelectorWithWhy = exports.synthesizeBinaryRelationWithWhy = exports.synthesizeBinaryRelation = exports.synthesizeSelector = exports.SimpleGraphQueryEvaluator = void 0;
|
|
61540
61810
|
const antlr4ts_1 = __webpack_require__(/*! antlr4ts */ "./node_modules/antlr4ts/index.js");
|
|
61541
61811
|
const ForgeParser_1 = __webpack_require__(/*! ./forge-antlr/ForgeParser */ "./src/forge-antlr/ForgeParser.ts");
|
|
61542
61812
|
const ForgeLexer_1 = __webpack_require__(/*! ./forge-antlr/ForgeLexer */ "./src/forge-antlr/ForgeLexer.ts");
|
|
@@ -61619,9 +61889,74 @@ class SimpleGraphQueryEvaluator {
|
|
|
61619
61889
|
}
|
|
61620
61890
|
}
|
|
61621
61891
|
exports.SimpleGraphQueryEvaluator = SimpleGraphQueryEvaluator;
|
|
61892
|
+
var SelectorSynthesizer_1 = __webpack_require__(/*! ./SelectorSynthesizer */ "./src/SelectorSynthesizer.ts");
|
|
61893
|
+
Object.defineProperty(exports, "synthesizeSelector", ({ enumerable: true, get: function () { return SelectorSynthesizer_1.synthesizeSelector; } }));
|
|
61894
|
+
Object.defineProperty(exports, "synthesizeBinaryRelation", ({ enumerable: true, get: function () { return SelectorSynthesizer_1.synthesizeBinaryRelation; } }));
|
|
61895
|
+
Object.defineProperty(exports, "synthesizeBinaryRelationWithWhy", ({ enumerable: true, get: function () { return SelectorSynthesizer_1.synthesizeBinaryRelationWithWhy; } }));
|
|
61896
|
+
Object.defineProperty(exports, "synthesizeSelectorWithWhy", ({ enumerable: true, get: function () { return SelectorSynthesizer_1.synthesizeSelectorWithWhy; } }));
|
|
61897
|
+
Object.defineProperty(exports, "SelectorSynthesisError", ({ enumerable: true, get: function () { return SelectorSynthesizer_1.SelectorSynthesisError; } }));
|
|
61622
61898
|
|
|
61623
|
-
})();
|
|
61624
61899
|
|
|
61900
|
+
/***/ })
|
|
61901
|
+
|
|
61902
|
+
/******/ });
|
|
61903
|
+
/************************************************************************/
|
|
61904
|
+
/******/ // The module cache
|
|
61905
|
+
/******/ var __webpack_module_cache__ = {};
|
|
61906
|
+
/******/
|
|
61907
|
+
/******/ // The require function
|
|
61908
|
+
/******/ function __webpack_require__(moduleId) {
|
|
61909
|
+
/******/ // Check if module is in cache
|
|
61910
|
+
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
61911
|
+
/******/ if (cachedModule !== undefined) {
|
|
61912
|
+
/******/ return cachedModule.exports;
|
|
61913
|
+
/******/ }
|
|
61914
|
+
/******/ // Create a new module (and put it into the cache)
|
|
61915
|
+
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
61916
|
+
/******/ id: moduleId,
|
|
61917
|
+
/******/ loaded: false,
|
|
61918
|
+
/******/ exports: {}
|
|
61919
|
+
/******/ };
|
|
61920
|
+
/******/
|
|
61921
|
+
/******/ // Execute the module function
|
|
61922
|
+
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
61923
|
+
/******/
|
|
61924
|
+
/******/ // Flag the module as loaded
|
|
61925
|
+
/******/ module.loaded = true;
|
|
61926
|
+
/******/
|
|
61927
|
+
/******/ // Return the exports of the module
|
|
61928
|
+
/******/ return module.exports;
|
|
61929
|
+
/******/ }
|
|
61930
|
+
/******/
|
|
61931
|
+
/************************************************************************/
|
|
61932
|
+
/******/ /* webpack/runtime/global */
|
|
61933
|
+
/******/ (() => {
|
|
61934
|
+
/******/ __webpack_require__.g = (function() {
|
|
61935
|
+
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
61936
|
+
/******/ try {
|
|
61937
|
+
/******/ return this || new Function('return this')();
|
|
61938
|
+
/******/ } catch (e) {
|
|
61939
|
+
/******/ if (typeof window === 'object') return window;
|
|
61940
|
+
/******/ }
|
|
61941
|
+
/******/ })();
|
|
61942
|
+
/******/ })();
|
|
61943
|
+
/******/
|
|
61944
|
+
/******/ /* webpack/runtime/node module decorator */
|
|
61945
|
+
/******/ (() => {
|
|
61946
|
+
/******/ __webpack_require__.nmd = (module) => {
|
|
61947
|
+
/******/ module.paths = [];
|
|
61948
|
+
/******/ if (!module.children) module.children = [];
|
|
61949
|
+
/******/ return module;
|
|
61950
|
+
/******/ };
|
|
61951
|
+
/******/ })();
|
|
61952
|
+
/******/
|
|
61953
|
+
/************************************************************************/
|
|
61954
|
+
/******/
|
|
61955
|
+
/******/ // startup
|
|
61956
|
+
/******/ // Load entry module and return exports
|
|
61957
|
+
/******/ // This entry module is referenced by other modules so it can't be inlined
|
|
61958
|
+
/******/ var __webpack_exports__ = __webpack_require__("./src/index.ts");
|
|
61959
|
+
/******/
|
|
61625
61960
|
/******/ return __webpack_exports__;
|
|
61626
61961
|
/******/ })()
|
|
61627
61962
|
;
|
package/package.json
CHANGED