@nshiab/simple-data-analysis-core 2.1.7 → 2.1.9
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/esm/class/SimpleTable.d.ts +191 -108
- package/esm/class/SimpleTable.d.ts.map +1 -1
- package/esm/class/SimpleTable.js +188 -105
- package/esm/helpers/buildGraphTemporalCostStateSql.d.ts +1 -1
- package/esm/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -1
- package/esm/helpers/buildGraphTemporalCostStateSql.js +23 -9
- package/esm/helpers/graphRouteResultSchema.d.ts +1 -1
- package/esm/helpers/graphRouteResultSchema.d.ts.map +1 -1
- package/esm/helpers/graphRouteResultSchema.js +3 -3
- package/esm/helpers/graphRouteResultSelect.d.ts +1 -1
- package/esm/helpers/graphRouteResultSelect.d.ts.map +1 -1
- package/esm/helpers/graphRouteResultSelect.js +2 -2
- package/esm/helpers/prepareGraphMetricOptions.d.ts +2 -2
- package/esm/helpers/prepareGraphMetricOptions.d.ts.map +1 -1
- package/esm/helpers/prepareGraphMetricOptions.js +5 -4
- package/esm/helpers/prepareGraphRouteSql.d.ts +2 -2
- package/esm/helpers/prepareGraphRouteSql.d.ts.map +1 -1
- package/esm/helpers/prepareGraphRouteSql.js +4 -4
- package/esm/helpers/validateGraphRouteResultSchema.d.ts +1 -1
- package/esm/helpers/validateGraphRouteResultSchema.d.ts.map +1 -1
- package/esm/helpers/validateGraphRouteResultSchema.js +3 -1
- package/esm/methods/distances.d.ts +1 -1
- package/esm/methods/distances.d.ts.map +1 -1
- package/esm/methods/distances.js +235 -73
- package/esm/methods/shortestPath.d.ts +1 -1
- package/esm/methods/shortestPath.d.ts.map +1 -1
- package/esm/methods/shortestPath.js +44 -28
- package/esm/methods/similarityMahalanobis.js +3 -3
- package/llm.md +214 -119
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/script/class/SimpleTable.d.ts +191 -108
- package/script/class/SimpleTable.d.ts.map +1 -1
- package/script/class/SimpleTable.js +188 -105
- package/script/helpers/buildGraphTemporalCostStateSql.d.ts +1 -1
- package/script/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -1
- package/script/helpers/buildGraphTemporalCostStateSql.js +23 -9
- package/script/helpers/graphRouteResultSchema.d.ts +1 -1
- package/script/helpers/graphRouteResultSchema.d.ts.map +1 -1
- package/script/helpers/graphRouteResultSchema.js +3 -3
- package/script/helpers/graphRouteResultSelect.d.ts +1 -1
- package/script/helpers/graphRouteResultSelect.d.ts.map +1 -1
- package/script/helpers/graphRouteResultSelect.js +2 -2
- package/script/helpers/prepareGraphMetricOptions.d.ts +2 -2
- package/script/helpers/prepareGraphMetricOptions.d.ts.map +1 -1
- package/script/helpers/prepareGraphMetricOptions.js +5 -4
- package/script/helpers/prepareGraphRouteSql.d.ts +2 -2
- package/script/helpers/prepareGraphRouteSql.d.ts.map +1 -1
- package/script/helpers/prepareGraphRouteSql.js +4 -4
- package/script/helpers/validateGraphRouteResultSchema.d.ts +1 -1
- package/script/helpers/validateGraphRouteResultSchema.d.ts.map +1 -1
- package/script/helpers/validateGraphRouteResultSchema.js +3 -1
- package/script/methods/distances.d.ts +1 -1
- package/script/methods/distances.d.ts.map +1 -1
- package/script/methods/distances.js +235 -73
- package/script/methods/shortestPath.d.ts +1 -1
- package/script/methods/shortestPath.d.ts.map +1 -1
- package/script/methods/shortestPath.js +44 -28
- package/script/methods/similarityMahalanobis.js +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepareGraphMetricOptions.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphMetricOptions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"prepareGraphMetricOptions.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphMetricOptions.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;CAC9C,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,GAChB,0BAA0B,CA2D5B"}
|
|
@@ -17,8 +17,9 @@ function prepareGraphMetricOptions(options, method, optimize) {
|
|
|
17
17
|
if (!optimize) {
|
|
18
18
|
throw new TypeError(`${method} options.minimize is not supported because this method returns all routes.`);
|
|
19
19
|
}
|
|
20
|
-
if (options.minimize !== "
|
|
21
|
-
|
|
20
|
+
if (options.minimize !== "steps" && options.minimize !== "weight" &&
|
|
21
|
+
options.minimize !== "elapsedTime") {
|
|
22
|
+
throw new TypeError(`${method} options.minimize must be "steps", "weight", or "elapsedTime".`);
|
|
22
23
|
}
|
|
23
24
|
if (options.minimize === "weight" && options.weight === undefined) {
|
|
24
25
|
throw new TypeError(`${method} options.minimize: "weight" requires options.weight.`);
|
|
@@ -29,7 +30,7 @@ function prepareGraphMetricOptions(options, method, optimize) {
|
|
|
29
30
|
}
|
|
30
31
|
if (optimize && elapsedTime && options.weight !== undefined &&
|
|
31
32
|
options.minimize === undefined) {
|
|
32
|
-
throw new TypeError(`${method} when weight and elapsedTime are both enabled, specify options.minimize: "weight" or "elapsedTime".`);
|
|
33
|
+
throw new TypeError(`${method} when weight and elapsedTime are both enabled, specify options.minimize: "steps", "weight", or "elapsedTime".`);
|
|
33
34
|
}
|
|
34
35
|
return {
|
|
35
36
|
elapsedTime,
|
|
@@ -38,6 +39,6 @@ function prepareGraphMetricOptions(options, method, optimize) {
|
|
|
38
39
|
? "weight"
|
|
39
40
|
: elapsedTime
|
|
40
41
|
? "elapsedTime"
|
|
41
|
-
: "
|
|
42
|
+
: "steps"),
|
|
42
43
|
};
|
|
43
44
|
}
|
|
@@ -8,13 +8,13 @@ export type PreparedGraphRouteEndpoints = {
|
|
|
8
8
|
/** Prepares and validates the two scalar endpoints shared by route methods. */
|
|
9
9
|
export declare function prepareGraphRouteEndpoints(start: GraphId, end: GraphId, method: string): PreparedGraphRouteEndpoints;
|
|
10
10
|
/** Validates the columns shared by edge-route methods from queued schema data. */
|
|
11
|
-
export declare function validateGraphRouteInputs(schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string): {
|
|
11
|
+
export declare function validateGraphRouteInputs(schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string, includeTotal?: boolean): {
|
|
12
12
|
distanceType: string;
|
|
13
13
|
edgeIdType: string;
|
|
14
14
|
nodeIdType: string;
|
|
15
15
|
};
|
|
16
16
|
/** Prepares the typed SQL expressions shared by edge-route enumeration. */
|
|
17
|
-
export declare function prepareGraphRouteSql(input: string, schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string): {
|
|
17
|
+
export declare function prepareGraphRouteSql(input: string, schema: TableSchema, source: string, target: string, edgeId: string, endpoints: PreparedGraphRouteEndpoints, weight: string | undefined, method: string, includeTotal?: boolean): {
|
|
18
18
|
distanceType: string;
|
|
19
19
|
edgeIdColumn: import("./getGraphEdgeIdColumn.js").GraphEdgeIdColumn;
|
|
20
20
|
edgeKey: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepareGraphRouteSql.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphRouteSql.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAA2B,EACzB,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,EAAE,mBAAmB,CAAC;IACzB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACb,2BAA2B,CA+B7B;AAED,kFAAkF;AAClF,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM;;;;
|
|
1
|
+
{"version":3,"file":"prepareGraphRouteSql.d.ts","sourceRoot":"","sources":["../../src/helpers/prepareGraphRouteSql.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAA2B,EACzB,KAAK,OAAO,EACZ,KAAK,mBAAmB,EACzB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,MAAM,2BAA2B,GAAG;IACxC,GAAG,EAAE,mBAAmB,CAAC;IACzB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACb,2BAA2B,CA+B7B;AAED,kFAAkF;AAClF,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,EACd,YAAY,UAAO;;;;EAmBpB;AAED,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,2BAA2B,EACtC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,EACd,YAAY,UAAO;;;;;;;;;;;;;EAkDpB"}
|
|
@@ -75,13 +75,13 @@ function prepareGraphRouteEndpoints(start, end, method) {
|
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
/** Validates the columns shared by edge-route methods from queued schema data. */
|
|
78
|
-
function validateGraphRouteInputs(schema, source, target, edgeId, endpoints, weight, method) {
|
|
78
|
+
function validateGraphRouteInputs(schema, source, target, edgeId, endpoints, weight, method, includeTotal = true) {
|
|
79
79
|
const nodes = (0, prepareGraphTraversal_js_1.validateGraphStarts)(schema, source, target, endpoints.values, method);
|
|
80
80
|
const edges = (0, getGraphEdgeIdColumn_js_1.default)(schema, edgeId, method);
|
|
81
81
|
const weightColumn = weight === undefined
|
|
82
82
|
? undefined
|
|
83
83
|
: (0, getGraphWeightColumn_js_1.default)(schema, weight, method);
|
|
84
|
-
(0, validateGraphRouteResultSchema_js_1.default)(schema, method);
|
|
84
|
+
(0, validateGraphRouteResultSchema_js_1.default)(schema, method, [], includeTotal);
|
|
85
85
|
return {
|
|
86
86
|
distanceType: weightColumn?.distanceType ?? "BIGINT",
|
|
87
87
|
edgeIdType: edges.idType,
|
|
@@ -89,8 +89,8 @@ function validateGraphRouteInputs(schema, source, target, edgeId, endpoints, wei
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
/** Prepares the typed SQL expressions shared by edge-route enumeration. */
|
|
92
|
-
function prepareGraphRouteSql(input, schema, source, target, edgeId, endpoints, weight, method) {
|
|
93
|
-
(0, validateGraphRouteResultSchema_js_1.default)(schema, method);
|
|
92
|
+
function prepareGraphRouteSql(input, schema, source, target, edgeId, endpoints, weight, method, includeTotal = true) {
|
|
93
|
+
(0, validateGraphRouteResultSchema_js_1.default)(schema, method, [], includeTotal);
|
|
94
94
|
const traversal = (0, prepareGraphTraversal_js_1.default)(input, schema, source, target, endpoints.values, method);
|
|
95
95
|
const edgeIdColumn = (0, getGraphEdgeIdColumn_js_1.default)(schema, edgeId, method);
|
|
96
96
|
const weightColumn = weight === undefined
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { TableSchema } from "./pendingOps.js";
|
|
2
2
|
/** Validates that route result columns do not replace original input columns. */
|
|
3
|
-
export default function validateGraphRouteResultSchema(schema: TableSchema, method: string, additionalResultColumns?: readonly string[]): void;
|
|
3
|
+
export default function validateGraphRouteResultSchema(schema: TableSchema, method: string, additionalResultColumns?: readonly string[], includeTotal?: boolean): void;
|
|
4
4
|
//# sourceMappingURL=validateGraphRouteResultSchema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateGraphRouteResultSchema.d.ts","sourceRoot":"","sources":["../../src/helpers/validateGraphRouteResultSchema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,iFAAiF;AACjF,MAAM,CAAC,OAAO,UAAU,8BAA8B,CACpD,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,uBAAuB,GAAE,SAAS,MAAM,EAAO,
|
|
1
|
+
{"version":3,"file":"validateGraphRouteResultSchema.d.ts","sourceRoot":"","sources":["../../src/helpers/validateGraphRouteResultSchema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,iFAAiF;AACjF,MAAM,CAAC,OAAO,UAAU,8BAA8B,CACpD,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,uBAAuB,GAAE,SAAS,MAAM,EAAO,EAC/C,YAAY,UAAO,GAClB,IAAI,CAmBN"}
|
|
@@ -8,8 +8,10 @@ const foldIdentifier_js_1 = __importDefault(require("./foldIdentifier.js"));
|
|
|
8
8
|
const quoteIdentifier_js_1 = __importDefault(require("./quoteIdentifier.js"));
|
|
9
9
|
const resultColumns = ["pathId", "step", "weight", "total"];
|
|
10
10
|
/** Validates that route result columns do not replace original input columns. */
|
|
11
|
-
function validateGraphRouteResultSchema(schema, method, additionalResultColumns = []) {
|
|
11
|
+
function validateGraphRouteResultSchema(schema, method, additionalResultColumns = [], includeTotal = true) {
|
|
12
12
|
for (const resultColumn of [...resultColumns, ...additionalResultColumns]) {
|
|
13
|
+
if (resultColumn === "total" && !includeTotal)
|
|
14
|
+
continue;
|
|
13
15
|
const folded = (0, foldIdentifier_js_1.default)(resultColumn);
|
|
14
16
|
const inputColumn = Object.keys(schema).find((column) => (0, foldIdentifier_js_1.default)(column) === folded);
|
|
15
17
|
if (inputColumn !== undefined) {
|
|
@@ -7,7 +7,7 @@ type DistancesOptions = GraphTemporalOptions & {
|
|
|
7
7
|
outputTable?: string | boolean;
|
|
8
8
|
weight?: string;
|
|
9
9
|
elapsedTime?: boolean;
|
|
10
|
-
minimize?: "weight" | "elapsedTime";
|
|
10
|
+
minimize?: "steps" | "weight" | "elapsedTime";
|
|
11
11
|
};
|
|
12
12
|
export default function distances(simpleTable: SimpleTable, sourceColumn: string, targetColumn: string, startNodes: GraphId | GraphId[], options?: DistancesOptions): SimpleTable;
|
|
13
13
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distances.d.ts","sourceRoot":"","sources":["../../src/methods/distances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAOvD,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAA2B,EACzB,KAAK,OAAO,EAEb,MAAM,kCAAkC,CAAC;AAC1C,OAA8B,EAC5B,KAAK,cAAc,EAEpB,MAAM,qCAAqC,CAAC;AAK7C,KAAK,gBAAgB,GAAG,oBAAoB,GAAG;IAC7C,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"distances.d.ts","sourceRoot":"","sources":["../../src/methods/distances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAOvD,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAA2B,EACzB,KAAK,OAAO,EAEb,MAAM,kCAAkC,CAAC;AAC1C,OAA8B,EAC5B,KAAK,cAAc,EAEpB,MAAM,qCAAqC,CAAC;AAK7C,KAAK,gBAAgB,GAAG,oBAAoB,GAAG;IAC7C,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,OAAO,GAAG,OAAO,EAAE,EAC/B,OAAO,GAAE,gBAAqB,GAC7B,WAAW,CA+Gb"}
|
|
@@ -98,7 +98,10 @@ function distances(simpleTable, sourceColumn, targetColumn, startNodes, options
|
|
|
98
98
|
return {
|
|
99
99
|
start: validated.idType,
|
|
100
100
|
node: validated.idType,
|
|
101
|
-
|
|
101
|
+
steps: "BIGINT",
|
|
102
|
+
...(options.weight === undefined
|
|
103
|
+
? {}
|
|
104
|
+
: { total: validated.distanceType }),
|
|
102
105
|
...(metrics.elapsedTime ? { elapsedTimeMs: "DOUBLE" } : {}),
|
|
103
106
|
};
|
|
104
107
|
},
|
|
@@ -123,12 +126,14 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
123
126
|
const edgeWeight = weightColumn === undefined
|
|
124
127
|
? `CAST(1 AS ${distanceType})`
|
|
125
128
|
: `CAST(${(0, quoteIdentifier_js_1.default)("edges")}.${(0, quoteIdentifier_js_1.default)(weightColumn.column)} AS ${distanceType})`;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
const temporal = temporalOptions === undefined
|
|
130
|
+
? undefined
|
|
131
|
+
: (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "distances()");
|
|
132
|
+
if (weight !== undefined || metrics.elapsedTime) {
|
|
133
|
+
return summaryDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics, weight !== undefined, weightColumn?.type === "FLOAT" || weightColumn?.type === "DOUBLE");
|
|
134
|
+
}
|
|
135
|
+
if (temporal !== undefined) {
|
|
136
|
+
return temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, "steps", false);
|
|
132
137
|
}
|
|
133
138
|
const relations = prepared.relationNames([
|
|
134
139
|
"graph_start_values",
|
|
@@ -152,6 +157,14 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
152
157
|
const edgeCost = `${(0, quoteIdentifier_js_1.default)("edges")}.${(0, quoteIdentifier_js_1.default)("__weight")}`;
|
|
153
158
|
const bestDistance = `${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("distance")}`;
|
|
154
159
|
const candidateDistance = `CAST(${reachedDistance} + ${edgeCost} AS ${distanceType})`;
|
|
160
|
+
const candidateSteps = `${(0, quoteIdentifier_js_1.default)("reached")}.${(0, quoteIdentifier_js_1.default)("steps")} + 1`;
|
|
161
|
+
const bestSteps = `${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("steps")}`;
|
|
162
|
+
const order = (distance, steps) => metrics.minimize === "steps"
|
|
163
|
+
? `ROW(${steps}, ${distance})`
|
|
164
|
+
: `ROW(${distance}, ${steps})`;
|
|
165
|
+
const candidateOrder = order(candidateDistance, candidateSteps);
|
|
166
|
+
const selectedDistance = `arg_min(${candidateDistance}, ${candidateOrder})`;
|
|
167
|
+
const selectedSteps = `arg_min(${candidateSteps}, ${candidateOrder})`;
|
|
155
168
|
return `WITH RECURSIVE ${startValuesRelation}(${(0, quoteIdentifier_js_1.default)("start")}) AS (
|
|
156
169
|
VALUES ${prepared.startValues}
|
|
157
170
|
), ${startsRelation} AS (
|
|
@@ -165,19 +178,20 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
165
178
|
), ${distancesRelation}(
|
|
166
179
|
${(0, quoteIdentifier_js_1.default)("start")}, ${(0, quoteIdentifier_js_1.default)("node")},
|
|
167
180
|
${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("__node_key")},
|
|
168
|
-
${(0, quoteIdentifier_js_1.default)("distance")}
|
|
181
|
+
${(0, quoteIdentifier_js_1.default)("distance")}, ${(0, quoteIdentifier_js_1.default)("steps")}
|
|
169
182
|
) USING KEY(
|
|
170
183
|
${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}
|
|
171
184
|
) AS (
|
|
172
185
|
SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},
|
|
173
|
-
MIN(${edgeCost}) AS ${(0, quoteIdentifier_js_1.default)("distance")}
|
|
186
|
+
MIN(${edgeCost}) AS ${(0, quoteIdentifier_js_1.default)("distance")}, CAST(1 AS BIGINT)
|
|
174
187
|
FROM ${startsRelation} AS ${(0, quoteIdentifier_js_1.default)("starts")}
|
|
175
188
|
INNER JOIN ${edgesRelation} AS ${(0, quoteIdentifier_js_1.default)("edges")}
|
|
176
189
|
ON ${startKey} = ${edgeFromKey}
|
|
177
190
|
GROUP BY ${start}, ${edgeTo}, ${startKey}, ${edgeToKey}
|
|
178
191
|
UNION
|
|
179
192
|
SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},
|
|
180
|
-
|
|
193
|
+
${selectedDistance} AS ${(0, quoteIdentifier_js_1.default)("distance")},
|
|
194
|
+
${selectedSteps} AS ${(0, quoteIdentifier_js_1.default)("steps")}
|
|
181
195
|
FROM ${distancesRelation} AS ${(0, quoteIdentifier_js_1.default)("reached")}
|
|
182
196
|
INNER JOIN ${edgesRelation} AS ${(0, quoteIdentifier_js_1.default)("edges")}
|
|
183
197
|
ON ${reachedNodeKey} = ${edgeFromKey}
|
|
@@ -185,111 +199,259 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
185
199
|
ON ${reachedStartKey} = ${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("__start_key")}
|
|
186
200
|
AND ${edgeToKey} = ${(0, quoteIdentifier_js_1.default)("best")}.${(0, quoteIdentifier_js_1.default)("__node_key")}
|
|
187
201
|
GROUP BY ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},
|
|
188
|
-
${bestDistance}
|
|
189
|
-
HAVING ${bestDistance} IS NULL OR
|
|
202
|
+
${bestDistance}, ${bestSteps}
|
|
203
|
+
HAVING ${bestDistance} IS NULL OR
|
|
204
|
+
${order(selectedDistance, selectedSteps)} < ${order(bestDistance, bestSteps)}
|
|
190
205
|
)
|
|
191
206
|
SELECT ${(0, quoteIdentifier_js_1.default)("start")}, ${(0, quoteIdentifier_js_1.default)("node")},
|
|
192
|
-
${(0, quoteIdentifier_js_1.default)("
|
|
207
|
+
${(0, quoteIdentifier_js_1.default)("steps")}${weight === undefined
|
|
208
|
+
? ""
|
|
209
|
+
: `, ${(0, quoteIdentifier_js_1.default)("distance")} AS ${(0, quoteIdentifier_js_1.default)("total")}`}
|
|
193
210
|
FROM ${distancesRelation}
|
|
194
|
-
ORDER BY ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("distance")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}`;
|
|
211
|
+
ORDER BY ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)(metrics.minimize === "steps" ? "steps" : "distance")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}`;
|
|
195
212
|
}
|
|
196
|
-
function temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight) {
|
|
213
|
+
function temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, minimize, includeTotal) {
|
|
197
214
|
const q = quoteIdentifier_js_1.default;
|
|
198
215
|
const startsSelect = `SELECT ${q("start")},
|
|
199
216
|
${prepared.key(q("start"))} AS ${q("__key")}
|
|
200
217
|
FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})`;
|
|
201
|
-
const costStates = (0, buildGraphTemporalCostStateSql_js_1.default)(prepared, startsSelect, direction, temporal, distanceType, edgeWeight);
|
|
218
|
+
const costStates = (0, buildGraphTemporalCostStateSql_js_1.default)(prepared, startsSelect, direction, temporal, distanceType, edgeWeight, [], minimize);
|
|
219
|
+
const order = minimize === "steps"
|
|
220
|
+
? `${q("steps")}, ${q("distance")}`
|
|
221
|
+
: `${q("distance")}, ${q("steps")}`;
|
|
202
222
|
return `${costStates.withClause}
|
|
203
|
-
SELECT ${q("start")}, ${q("node")},
|
|
204
|
-
MIN(${q("distance")}) AS ${q("total")}
|
|
223
|
+
SELECT ${q("start")}, ${q("node")}, ${q("steps")}${includeTotal ? `, ${q("distance")} AS ${q("total")}` : ""}
|
|
205
224
|
FROM ${costStates.costRelation}
|
|
206
|
-
|
|
207
|
-
${q("__node_key")}
|
|
208
|
-
|
|
225
|
+
QUALIFY row_number() OVER (
|
|
226
|
+
PARTITION BY ${q("__start_key")}, ${q("__node_key")}
|
|
227
|
+
ORDER BY ${order}
|
|
228
|
+
) = 1
|
|
229
|
+
ORDER BY ${q("__start_key")}, ${q(minimize === "steps" ? "steps" : "distance")}, ${q("__node_key")}`;
|
|
209
230
|
}
|
|
210
|
-
|
|
231
|
+
// Distinct visited sets, metrics, and temporal boundaries are enough to extend
|
|
232
|
+
// summaries. No edge IDs or full connection sequences are needed. Keeping the
|
|
233
|
+
// visited set is necessary: equal summaries can have different legal extensions.
|
|
234
|
+
function summaryDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics, includeTotal, floatingWeight) {
|
|
211
235
|
const q = quoteIdentifier_js_1.default;
|
|
212
236
|
const relations = prepared.relationNames([
|
|
213
237
|
"graph_starts",
|
|
214
238
|
"graph_temporal_settings",
|
|
215
239
|
"graph_event_rows",
|
|
216
240
|
"graph_edges",
|
|
217
|
-
"
|
|
218
|
-
"
|
|
241
|
+
"graph_summaries",
|
|
242
|
+
"graph_metric_results",
|
|
243
|
+
"graph_tied_summaries",
|
|
244
|
+
"graph_best_metrics",
|
|
245
|
+
"graph_metric_bounds",
|
|
219
246
|
]);
|
|
220
247
|
const starts = relations.graph_starts;
|
|
221
248
|
const settings = relations.graph_temporal_settings;
|
|
222
249
|
const events = relations.graph_event_rows;
|
|
223
250
|
const edges = relations.graph_edges;
|
|
224
|
-
const
|
|
225
|
-
const results = relations.
|
|
251
|
+
const summaries = relations.graph_summaries;
|
|
252
|
+
const results = relations.graph_metric_results;
|
|
253
|
+
const tied = relations.graph_tied_summaries;
|
|
226
254
|
const ref = (alias, column) => `${q(alias)}.${q(column)}`;
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
255
|
+
const searchDirection = direction;
|
|
256
|
+
const firstAnchor = temporal?.journeyAnchor("edges", searchDirection);
|
|
257
|
+
const sum = `CAST(${ref("reached", "distance")} + ${ref("edges", "__weight")} AS ${distanceType})`;
|
|
258
|
+
// Reported costs must not reject routes before the primary objective has
|
|
259
|
+
// selected its results. NULL marks overflow and propagates through sums;
|
|
260
|
+
// non-negative weights cannot bring an overflowing total back into range.
|
|
261
|
+
const nextDistance = metrics.minimize === "weight" ? sum : `TRY(${sum})`;
|
|
262
|
+
const temporalColumns = temporal === undefined
|
|
263
|
+
? ""
|
|
264
|
+
: `, ${q("__event_start")}, ${q("__event_end")}`;
|
|
265
|
+
const eventValues = temporal === undefined
|
|
266
|
+
? ""
|
|
267
|
+
: `, ${ref("edges", "__event_start")}, ${ref("edges", "__event_end")}`;
|
|
268
|
+
const metric = metrics.minimize === "steps"
|
|
269
|
+
? q("steps")
|
|
270
|
+
: metrics.minimize === "weight"
|
|
271
|
+
? q("distance")
|
|
272
|
+
: q("__elapsed");
|
|
273
|
+
// Use native time precision for selection. Collapse equal reported values
|
|
274
|
+
// after conversion to milliseconds, since these are summary rows.
|
|
275
|
+
const reportedElapsed = metrics.elapsedTime
|
|
276
|
+
? `, ${temporal.elapsedMilliseconds(q("__elapsed"))} AS ${q("elapsedTimeMs")}`
|
|
277
|
+
: "";
|
|
278
|
+
const order = metrics.minimize === "steps"
|
|
279
|
+
? [
|
|
280
|
+
q("steps"),
|
|
281
|
+
q("__node_key"),
|
|
282
|
+
...(includeTotal ? [q("total")] : []),
|
|
283
|
+
...(metrics.elapsedTime ? [q("elapsedTimeMs")] : []),
|
|
284
|
+
]
|
|
285
|
+
: metrics.minimize === "weight"
|
|
286
|
+
? [
|
|
287
|
+
q("total"),
|
|
288
|
+
q("__node_key"),
|
|
289
|
+
q("steps"),
|
|
290
|
+
...(metrics.elapsedTime ? [q("elapsedTimeMs")] : []),
|
|
291
|
+
]
|
|
292
|
+
: [
|
|
293
|
+
q("elapsedTimeMs"),
|
|
294
|
+
q("__node_key"),
|
|
295
|
+
q("steps"),
|
|
296
|
+
...(includeTotal ? [q("total")] : []),
|
|
297
|
+
];
|
|
298
|
+
const bounds = summaryBoundsSql(relations.graph_best_metrics, relations.graph_metric_bounds, starts, edges, settings, temporal, searchDirection, metrics.minimize, distanceType, floatingWeight);
|
|
299
|
+
return `WITH RECURSIVE ${settings} AS (
|
|
300
|
+
${temporal === undefined
|
|
301
|
+
? `SELECT 0 AS ${q("__gap")}`
|
|
302
|
+
: `SELECT CAST(? AS HUGEINT) AS ${q("__gap")}`}
|
|
239
303
|
), ${events} AS MATERIALIZED (
|
|
240
304
|
${prepared.edges(direction, [
|
|
241
305
|
`${edgeWeight} AS ${q("__weight")}`,
|
|
242
|
-
...temporal
|
|
306
|
+
...(temporal?.eventSelections("edges") ?? []),
|
|
243
307
|
])}
|
|
244
308
|
), ${edges} AS MATERIALIZED (
|
|
245
|
-
SELECT
|
|
246
|
-
|
|
247
|
-
|
|
309
|
+
SELECT DISTINCT ${q("__from")}, ${q("__to")}, ${q("__from_key")},
|
|
310
|
+
${q("__to_key")}, ${q("__weight")}${temporalColumns}
|
|
311
|
+
FROM ${events} AS ${q("events")}
|
|
312
|
+
${temporal === undefined ? "" : `WHERE ${temporal.eventValidity("events")}`}
|
|
313
|
+
), ${starts} AS (
|
|
248
314
|
SELECT ${q("start")}, ${prepared.key(q("start"))} AS ${q("__key")}
|
|
249
315
|
FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})
|
|
250
|
-
), ${
|
|
316
|
+
), ${bounds.ctes}, ${summaries}(
|
|
251
317
|
${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
|
|
252
|
-
${q("
|
|
253
|
-
|
|
254
|
-
) USING KEY(${q("__start_key")}, ${q("__event_id")}, ${q("__anchor")}) AS (
|
|
318
|
+
${q("__visited")}, ${q("steps")}, ${q("distance")}${temporalColumns}${metrics.elapsedTime ? `, ${q("__anchor")}` : ""}
|
|
319
|
+
) AS (
|
|
255
320
|
SELECT ${ref("starts", "start")}, ${ref("edges", "__to")},
|
|
256
321
|
${ref("starts", "__key")}, ${ref("edges", "__to_key")},
|
|
257
|
-
${ref("
|
|
258
|
-
${ref("edges", "
|
|
322
|
+
list_sort(list_distinct([${ref("starts", "__key")}, ${ref("edges", "__to_key")}])),
|
|
323
|
+
CAST(1 AS BIGINT), ${ref("edges", "__weight")}${eventValues}${metrics.elapsedTime ? `, ${firstAnchor}` : ""}
|
|
259
324
|
FROM ${starts} AS ${q("starts")}
|
|
260
325
|
INNER JOIN ${edges} AS ${q("edges")}
|
|
261
326
|
ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
|
|
327
|
+
${bounds.join(ref("starts", "__key"))}
|
|
328
|
+
WHERE ${bounds.test("CAST(1 AS BIGINT)", ref("edges", "__weight"), firstAnchor)}
|
|
262
329
|
UNION
|
|
263
330
|
SELECT ${ref("reached", "start")}, ${ref("edges", "__to")},
|
|
264
331
|
${ref("reached", "__start_key")}, ${ref("edges", "__to_key")},
|
|
265
|
-
${ref("
|
|
266
|
-
${ref("
|
|
267
|
-
|
|
268
|
-
FROM ${states} AS ${q("reached")}
|
|
332
|
+
list_sort(list_distinct(list_append(${ref("reached", "__visited")}, ${ref("edges", "__to_key")}))),
|
|
333
|
+
${ref("reached", "steps")} + 1, ${nextDistance}${eventValues}${metrics.elapsedTime ? `, ${ref("reached", "__anchor")}` : ""}
|
|
334
|
+
FROM ${summaries} AS ${q("reached")}
|
|
269
335
|
INNER JOIN ${edges} AS ${q("edges")}
|
|
270
336
|
ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
|
|
271
337
|
CROSS JOIN ${settings} AS ${q("settings")}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
AND ${ref("
|
|
275
|
-
AND ${
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
${ref("reached", "__start_key")}, ${ref("edges", "__to_key")},
|
|
279
|
-
${ref("edges", "__event_id")}, ${ref("edges", "__event_start")},
|
|
280
|
-
${ref("edges", "__event_end")}, ${reachedAnchor}, ${ref("best", "distance")}
|
|
281
|
-
HAVING ${ref("best", "distance")} IS NULL OR
|
|
282
|
-
MIN(${candidateDistance}) < ${ref("best", "distance")}
|
|
338
|
+
${bounds.join(ref("reached", "__start_key"))}
|
|
339
|
+
WHERE ${bounds.test(`${ref("reached", "steps")} + 1`, nextDistance, ref("reached", "__anchor"))}
|
|
340
|
+
AND ${ref("reached", "__node_key")} <> ${ref("reached", "__start_key")}
|
|
341
|
+
AND (NOT list_contains(${ref("reached", "__visited")}, ${ref("edges", "__to_key")})
|
|
342
|
+
OR ${ref("edges", "__to_key")} = ${ref("reached", "__start_key")})
|
|
343
|
+
${temporal === undefined ? "" : `AND ${temporal.transition("reached", "edges", searchDirection, ref("settings", "__gap"))}`}
|
|
283
344
|
), ${results} AS (
|
|
284
|
-
SELECT
|
|
285
|
-
|
|
345
|
+
SELECT *${metrics.elapsedTime
|
|
346
|
+
? `, ${temporal.journeyElapsed("summaries", ref("summaries", "__anchor"), searchDirection)} AS ${q("__elapsed")}`
|
|
347
|
+
: ""}
|
|
348
|
+
FROM ${summaries} AS ${q("summaries")}
|
|
349
|
+
), ${tied} AS MATERIALIZED (
|
|
350
|
+
SELECT DISTINCT ${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
|
|
351
|
+
${q("steps")}${includeTotal ? `, ${q("distance")} AS ${q("total")}` : ""}${reportedElapsed}
|
|
352
|
+
FROM ${results}
|
|
353
|
+
QUALIFY ${metric} = MIN(${metric}) OVER (
|
|
354
|
+
PARTITION BY ${q("__start_key")}, ${q("__node_key")}
|
|
355
|
+
)
|
|
286
356
|
)
|
|
287
|
-
SELECT ${q("start")}, ${q("node")}, ${q("
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
)
|
|
294
|
-
|
|
357
|
+
SELECT ${q("start")}, ${q("node")}, ${q("steps")}${includeTotal
|
|
358
|
+
? `, CASE WHEN ${q("total")} IS NULL
|
|
359
|
+
THEN error('distances() total exceeds the supported ${distanceType} range for an optimal route.')
|
|
360
|
+
ELSE ${q("total")} END AS ${q("total")}`
|
|
361
|
+
: ""}${metrics.elapsedTime ? `, ${q("elapsedTimeMs")}` : ""}
|
|
362
|
+
FROM ${tied}
|
|
363
|
+
ORDER BY ${q("__start_key")}, ${order.join(", ")}`;
|
|
364
|
+
}
|
|
365
|
+
// Compute primary optima without enumerating visited sets. Exact additive
|
|
366
|
+
// objectives have optimal prefixes (at the same event boundary in temporal
|
|
367
|
+
// traversal). Floating addition can erase prefix differences, and elapsed
|
|
368
|
+
// optima can depend on a later departure, so those use a per-start upper bound.
|
|
369
|
+
function summaryBoundsSql(best, limits, starts, edges, settings, temporal, direction, minimize, distanceType, floatingWeight) {
|
|
370
|
+
const q = quoteIdentifier_js_1.default;
|
|
371
|
+
const ref = (alias, column) => `${q(alias)}.${q(column)}`;
|
|
372
|
+
const elapsed = minimize === "elapsedTime";
|
|
373
|
+
const globalBound = elapsed || (minimize === "weight" && floatingWeight);
|
|
374
|
+
const boundaries = temporal === undefined
|
|
375
|
+
? []
|
|
376
|
+
: ["__event_start", "__event_end"];
|
|
377
|
+
const keys = [
|
|
378
|
+
"__start_key",
|
|
379
|
+
"__node_key",
|
|
380
|
+
...boundaries,
|
|
381
|
+
...(elapsed ? ["__anchor"] : []),
|
|
382
|
+
];
|
|
383
|
+
const firstAnchor = elapsed
|
|
384
|
+
? temporal.journeyAnchor("edges", direction)
|
|
385
|
+
: undefined;
|
|
386
|
+
const firstKeys = [
|
|
387
|
+
ref("starts", "__key"),
|
|
388
|
+
ref("edges", "__to_key"),
|
|
389
|
+
...boundaries.map((key) => ref("edges", key)),
|
|
390
|
+
...(elapsed ? [firstAnchor] : []),
|
|
391
|
+
];
|
|
392
|
+
const nextKeys = [
|
|
393
|
+
ref("reached", "__start_key"),
|
|
394
|
+
ref("edges", "__to_key"),
|
|
395
|
+
...boundaries.map((key) => ref("edges", key)),
|
|
396
|
+
...(elapsed ? [ref("reached", "__anchor")] : []),
|
|
397
|
+
];
|
|
398
|
+
const firstMetric = minimize === "steps"
|
|
399
|
+
? "CAST(1 AS BIGINT)"
|
|
400
|
+
: elapsed
|
|
401
|
+
? temporal.journeyElapsed("edges", firstAnchor, direction)
|
|
402
|
+
: ref("edges", "__weight");
|
|
403
|
+
const nextMetric = minimize === "steps"
|
|
404
|
+
? `${ref("reached", "__metric")} + 1`
|
|
405
|
+
: elapsed
|
|
406
|
+
? temporal.journeyElapsed("edges", ref("reached", "__anchor"), direction)
|
|
407
|
+
: `CAST(${ref("reached", "__metric")} + ${ref("edges", "__weight")} AS ${distanceType})`;
|
|
408
|
+
const minimum = `MIN(${nextMetric})`;
|
|
409
|
+
const bestMetric = ref("best", "__metric");
|
|
410
|
+
const ctes = `${best}(${keys.map(q).join(", ")}, ${q("__metric")})
|
|
411
|
+
USING KEY(${keys.map(q).join(", ")}) AS (
|
|
412
|
+
SELECT ${firstKeys.join(", ")}, MIN(${firstMetric})
|
|
413
|
+
FROM ${starts} AS ${q("starts")}
|
|
414
|
+
INNER JOIN ${edges} AS ${q("edges")}
|
|
415
|
+
ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
|
|
416
|
+
GROUP BY ${firstKeys.join(", ")}
|
|
417
|
+
UNION
|
|
418
|
+
SELECT ${nextKeys.join(", ")}, ${minimum}
|
|
419
|
+
FROM ${best} AS ${q("reached")}
|
|
420
|
+
INNER JOIN ${edges} AS ${q("edges")}
|
|
421
|
+
ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
|
|
422
|
+
CROSS JOIN ${settings} AS ${q("settings")}
|
|
423
|
+
LEFT JOIN recurring.${best} AS ${q("best")}
|
|
424
|
+
ON ${keys.map((key, i) => `${ref("best", key)} = ${nextKeys[i]}`).join(" AND ")}
|
|
425
|
+
WHERE ${ref("reached", "__node_key")} <> ${ref("reached", "__start_key")}
|
|
426
|
+
${temporal === undefined ? "" : `AND ${temporal.transition("reached", "edges", direction, ref("settings", "__gap"))}`}
|
|
427
|
+
GROUP BY ${nextKeys.join(", ")}, ${bestMetric}
|
|
428
|
+
HAVING ${bestMetric} IS NULL OR ${minimum} < ${bestMetric}
|
|
429
|
+
)${globalBound
|
|
430
|
+
? `, ${limits} AS (
|
|
431
|
+
SELECT ${q("__start_key")}, MAX(${q("__minimum")}) AS ${q("__metric")}
|
|
432
|
+
FROM (
|
|
433
|
+
SELECT ${q("__start_key")}, ${q("__node_key")}, MIN(${q("__metric")}) AS ${q("__minimum")}
|
|
434
|
+
FROM ${best}
|
|
435
|
+
GROUP BY ${q("__start_key")}, ${q("__node_key")}
|
|
436
|
+
) AS ${q("minima")}
|
|
437
|
+
GROUP BY ${q("__start_key")}
|
|
438
|
+
)`
|
|
439
|
+
: ""}`;
|
|
440
|
+
return {
|
|
441
|
+
ctes,
|
|
442
|
+
join: (startKey) => `INNER JOIN ${globalBound ? limits : best} AS ${q("bounds")}
|
|
443
|
+
ON ${ref("bounds", "__start_key")} = ${startKey}
|
|
444
|
+
${globalBound
|
|
445
|
+
? ""
|
|
446
|
+
: `AND ${ref("bounds", "__node_key")} = ${ref("edges", "__to_key")}
|
|
447
|
+
${boundaries.map((key) => `AND ${ref("bounds", key)} = ${ref("edges", key)}`).join(" ")}`}`,
|
|
448
|
+
test: (steps, distance, anchor) => {
|
|
449
|
+
const metric = minimize === "steps"
|
|
450
|
+
? steps
|
|
451
|
+
: elapsed
|
|
452
|
+
? temporal.journeyElapsed("edges", anchor, direction)
|
|
453
|
+
: distance;
|
|
454
|
+
return `${metric} ${globalBound ? "<=" : "="} ${ref("bounds", "__metric")}`;
|
|
455
|
+
},
|
|
456
|
+
};
|
|
295
457
|
}
|
|
@@ -7,7 +7,7 @@ type ShortestPathOptions = GraphTemporalOptions & {
|
|
|
7
7
|
outputTable?: string | boolean;
|
|
8
8
|
weight?: string;
|
|
9
9
|
elapsedTime?: boolean;
|
|
10
|
-
minimize?: "weight" | "elapsedTime";
|
|
10
|
+
minimize?: "steps" | "weight" | "elapsedTime";
|
|
11
11
|
};
|
|
12
12
|
export default function shortestPath(simpleTable: SimpleTable, sourceColumn: string, targetColumn: string, edgeId: string, start: GraphId, end: GraphId, options?: ShortestPathOptions): SimpleTable;
|
|
13
13
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shortestPath.d.ts","sourceRoot":"","sources":["../../src/methods/shortestPath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAMvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAShE,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAK1E,KAAK,mBAAmB,GAAG,oBAAoB,GAAG;IAChD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"shortestPath.d.ts","sourceRoot":"","sources":["../../src/methods/shortestPath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAMvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAShE,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAK1E,KAAK,mBAAmB,GAAG,oBAAoB,GAAG;IAChD,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,CAAC;CAC/C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAClC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,mBAAwB,GAChC,WAAW,CAyHb"}
|