@nshiab/simple-data-analysis-core 2.1.6 → 2.1.8
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 +399 -90
- package/esm/class/SimpleTable.d.ts.map +1 -1
- package/esm/class/SimpleTable.js +393 -90
- 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 +4 -3
- package/esm/helpers/graphRouteResultSelect.d.ts +1 -1
- package/esm/helpers/graphRouteResultSelect.d.ts.map +1 -1
- package/esm/helpers/graphRouteResultSelect.js +5 -2
- package/esm/helpers/prepareGraphMetricOptions.d.ts +14 -0
- package/esm/helpers/prepareGraphMetricOptions.d.ts.map +1 -0
- package/esm/helpers/prepareGraphMetricOptions.js +41 -0
- 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/prepareGraphTemporalSql.d.ts +3 -0
- package/esm/helpers/prepareGraphTemporalSql.d.ts.map +1 -1
- package/esm/helpers/prepareGraphTemporalSql.js +7 -0
- 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 +2 -0
- package/esm/methods/distances.d.ts.map +1 -1
- package/esm/methods/distances.js +274 -20
- package/esm/methods/findCycles.d.ts +1 -0
- package/esm/methods/findCycles.d.ts.map +1 -1
- package/esm/methods/findCycles.js +22 -15
- package/esm/methods/paths.d.ts +1 -0
- package/esm/methods/paths.d.ts.map +1 -1
- package/esm/methods/paths.js +21 -14
- package/esm/methods/shortestPath.d.ts +2 -0
- package/esm/methods/shortestPath.d.ts.map +1 -1
- package/esm/methods/shortestPath.js +155 -34
- package/llm.md +428 -108
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/script/class/SimpleTable.d.ts +399 -90
- package/script/class/SimpleTable.d.ts.map +1 -1
- package/script/class/SimpleTable.js +393 -90
- 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 +4 -3
- package/script/helpers/graphRouteResultSelect.d.ts +1 -1
- package/script/helpers/graphRouteResultSelect.d.ts.map +1 -1
- package/script/helpers/graphRouteResultSelect.js +5 -2
- package/script/helpers/prepareGraphMetricOptions.d.ts +14 -0
- package/script/helpers/prepareGraphMetricOptions.d.ts.map +1 -0
- package/script/helpers/prepareGraphMetricOptions.js +44 -0
- 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/prepareGraphTemporalSql.d.ts +3 -0
- package/script/helpers/prepareGraphTemporalSql.d.ts.map +1 -1
- package/script/helpers/prepareGraphTemporalSql.js +7 -0
- 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 +2 -0
- package/script/methods/distances.d.ts.map +1 -1
- package/script/methods/distances.js +274 -20
- package/script/methods/findCycles.d.ts +1 -0
- package/script/methods/findCycles.d.ts.map +1 -1
- package/script/methods/findCycles.js +22 -15
- package/script/methods/paths.d.ts +1 -0
- package/script/methods/paths.d.ts.map +1 -1
- package/script/methods/paths.js +21 -14
- package/script/methods/shortestPath.d.ts +2 -0
- package/script/methods/shortestPath.d.ts.map +1 -1
- package/script/methods/shortestPath.js +155 -34
package/esm/methods/distances.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import buildGraphTemporalCostStateSql from "../helpers/buildGraphTemporalCostStateSql.js";
|
|
2
2
|
import getGraphWeightColumn from "../helpers/getGraphWeightColumn.js";
|
|
3
|
+
import prepareGraphMetricOptions from "../helpers/prepareGraphMetricOptions.js";
|
|
3
4
|
import prepareGraphTemporalSql, { prepareGraphTemporalOptions, } from "../helpers/prepareGraphTemporalSql.js";
|
|
4
5
|
import prepareGraphStarts from "../helpers/prepareGraphStarts.js";
|
|
5
6
|
import prepareGraphTraversal, { validateGraphStarts, } from "../helpers/prepareGraphTraversal.js";
|
|
@@ -28,6 +29,7 @@ export default function distances(simpleTable, sourceColumn, targetColumn, start
|
|
|
28
29
|
typeof options.outputTable !== "boolean") {
|
|
29
30
|
throw new TypeError("distances() options.outputTable must be a string or boolean.");
|
|
30
31
|
}
|
|
32
|
+
const metrics = prepareGraphMetricOptions(options, "distances()", true);
|
|
31
33
|
const preparedStarts = prepareGraphStarts(startNodes, "distances()", "startNodes");
|
|
32
34
|
const direction = options.direction ?? "outgoing";
|
|
33
35
|
const temporalOptions = prepareGraphTemporalOptions(options, direction, "distances()");
|
|
@@ -51,13 +53,17 @@ export default function distances(simpleTable, sourceColumn, targetColumn, start
|
|
|
51
53
|
? preparedStarts.values
|
|
52
54
|
: [temporal.gapParameter, ...preparedStarts.values];
|
|
53
55
|
},
|
|
54
|
-
buildSelect: (input, schema) => distancesSelect(input, schema, sourceColumn, targetColumn, preparedStarts, direction, options.weight, temporalOptions),
|
|
56
|
+
buildSelect: (input, schema) => distancesSelect(input, schema, sourceColumn, targetColumn, preparedStarts, direction, options.weight, temporalOptions, metrics),
|
|
55
57
|
outputSchema: (schema) => {
|
|
56
58
|
const validated = validateDistanceInputs(schema, sourceColumn, targetColumn, preparedStarts, options.weight, temporalOptions);
|
|
57
59
|
return {
|
|
58
60
|
start: validated.idType,
|
|
59
61
|
node: validated.idType,
|
|
60
|
-
|
|
62
|
+
steps: "BIGINT",
|
|
63
|
+
...(options.weight === undefined
|
|
64
|
+
? {}
|
|
65
|
+
: { total: validated.distanceType }),
|
|
66
|
+
...(metrics.elapsedTime ? { elapsedTimeMs: "DOUBLE" } : {}),
|
|
61
67
|
};
|
|
62
68
|
},
|
|
63
69
|
});
|
|
@@ -72,7 +78,7 @@ function validateDistanceInputs(schema, source, target, starts, weight, temporal
|
|
|
72
78
|
: prepareGraphTemporalSql(schema, temporalOptions, "distances()");
|
|
73
79
|
return { idType: endpoints.idType, distanceType, temporal };
|
|
74
80
|
}
|
|
75
|
-
function distancesSelect(input, schema, source, target, starts, direction, weight, temporalOptions) {
|
|
81
|
+
function distancesSelect(input, schema, source, target, starts, direction, weight, temporalOptions, metrics) {
|
|
76
82
|
const prepared = prepareGraphTraversal(input, schema, source, target, starts, "distances()", "startNodes");
|
|
77
83
|
const weightColumn = weight === undefined
|
|
78
84
|
? undefined
|
|
@@ -81,9 +87,14 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
81
87
|
const edgeWeight = weightColumn === undefined
|
|
82
88
|
? `CAST(1 AS ${distanceType})`
|
|
83
89
|
: `CAST(${quoteIdentifier("edges")}.${quoteIdentifier(weightColumn.column)} AS ${distanceType})`;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
const temporal = temporalOptions === undefined
|
|
91
|
+
? undefined
|
|
92
|
+
: prepareGraphTemporalSql(schema, temporalOptions, "distances()");
|
|
93
|
+
if (weight !== undefined || metrics.elapsedTime) {
|
|
94
|
+
return summaryDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics, weight !== undefined, weightColumn?.type === "FLOAT" || weightColumn?.type === "DOUBLE");
|
|
95
|
+
}
|
|
96
|
+
if (temporal !== undefined) {
|
|
97
|
+
return temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, "steps", false);
|
|
87
98
|
}
|
|
88
99
|
const relations = prepared.relationNames([
|
|
89
100
|
"graph_start_values",
|
|
@@ -107,6 +118,14 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
107
118
|
const edgeCost = `${quoteIdentifier("edges")}.${quoteIdentifier("__weight")}`;
|
|
108
119
|
const bestDistance = `${quoteIdentifier("best")}.${quoteIdentifier("distance")}`;
|
|
109
120
|
const candidateDistance = `CAST(${reachedDistance} + ${edgeCost} AS ${distanceType})`;
|
|
121
|
+
const candidateSteps = `${quoteIdentifier("reached")}.${quoteIdentifier("steps")} + 1`;
|
|
122
|
+
const bestSteps = `${quoteIdentifier("best")}.${quoteIdentifier("steps")}`;
|
|
123
|
+
const order = (distance, steps) => metrics.minimize === "steps"
|
|
124
|
+
? `ROW(${steps}, ${distance})`
|
|
125
|
+
: `ROW(${distance}, ${steps})`;
|
|
126
|
+
const candidateOrder = order(candidateDistance, candidateSteps);
|
|
127
|
+
const selectedDistance = `arg_min(${candidateDistance}, ${candidateOrder})`;
|
|
128
|
+
const selectedSteps = `arg_min(${candidateSteps}, ${candidateOrder})`;
|
|
110
129
|
return `WITH RECURSIVE ${startValuesRelation}(${quoteIdentifier("start")}) AS (
|
|
111
130
|
VALUES ${prepared.startValues}
|
|
112
131
|
), ${startsRelation} AS (
|
|
@@ -120,19 +139,20 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
120
139
|
), ${distancesRelation}(
|
|
121
140
|
${quoteIdentifier("start")}, ${quoteIdentifier("node")},
|
|
122
141
|
${quoteIdentifier("__start_key")}, ${quoteIdentifier("__node_key")},
|
|
123
|
-
${quoteIdentifier("distance")}
|
|
142
|
+
${quoteIdentifier("distance")}, ${quoteIdentifier("steps")}
|
|
124
143
|
) USING KEY(
|
|
125
144
|
${quoteIdentifier("__start_key")}, ${quoteIdentifier("__node_key")}
|
|
126
145
|
) AS (
|
|
127
146
|
SELECT ${start}, ${edgeTo}, ${startKey}, ${edgeToKey},
|
|
128
|
-
MIN(${edgeCost}) AS ${quoteIdentifier("distance")}
|
|
147
|
+
MIN(${edgeCost}) AS ${quoteIdentifier("distance")}, CAST(1 AS BIGINT)
|
|
129
148
|
FROM ${startsRelation} AS ${quoteIdentifier("starts")}
|
|
130
149
|
INNER JOIN ${edgesRelation} AS ${quoteIdentifier("edges")}
|
|
131
150
|
ON ${startKey} = ${edgeFromKey}
|
|
132
151
|
GROUP BY ${start}, ${edgeTo}, ${startKey}, ${edgeToKey}
|
|
133
152
|
UNION
|
|
134
153
|
SELECT ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},
|
|
135
|
-
|
|
154
|
+
${selectedDistance} AS ${quoteIdentifier("distance")},
|
|
155
|
+
${selectedSteps} AS ${quoteIdentifier("steps")}
|
|
136
156
|
FROM ${distancesRelation} AS ${quoteIdentifier("reached")}
|
|
137
157
|
INNER JOIN ${edgesRelation} AS ${quoteIdentifier("edges")}
|
|
138
158
|
ON ${reachedNodeKey} = ${edgeFromKey}
|
|
@@ -140,25 +160,259 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
|
|
|
140
160
|
ON ${reachedStartKey} = ${quoteIdentifier("best")}.${quoteIdentifier("__start_key")}
|
|
141
161
|
AND ${edgeToKey} = ${quoteIdentifier("best")}.${quoteIdentifier("__node_key")}
|
|
142
162
|
GROUP BY ${reachedStart}, ${edgeTo}, ${reachedStartKey}, ${edgeToKey},
|
|
143
|
-
${bestDistance}
|
|
144
|
-
HAVING ${bestDistance} IS NULL OR
|
|
163
|
+
${bestDistance}, ${bestSteps}
|
|
164
|
+
HAVING ${bestDistance} IS NULL OR
|
|
165
|
+
${order(selectedDistance, selectedSteps)} < ${order(bestDistance, bestSteps)}
|
|
145
166
|
)
|
|
146
167
|
SELECT ${quoteIdentifier("start")}, ${quoteIdentifier("node")},
|
|
147
|
-
${quoteIdentifier("
|
|
168
|
+
${quoteIdentifier("steps")}${weight === undefined
|
|
169
|
+
? ""
|
|
170
|
+
: `, ${quoteIdentifier("distance")} AS ${quoteIdentifier("total")}`}
|
|
148
171
|
FROM ${distancesRelation}
|
|
149
|
-
ORDER BY ${quoteIdentifier("__start_key")}, ${quoteIdentifier("distance")}, ${quoteIdentifier("__node_key")}`;
|
|
172
|
+
ORDER BY ${quoteIdentifier("__start_key")}, ${quoteIdentifier(metrics.minimize === "steps" ? "steps" : "distance")}, ${quoteIdentifier("__node_key")}`;
|
|
150
173
|
}
|
|
151
|
-
function temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight) {
|
|
174
|
+
function temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, minimize, includeTotal) {
|
|
152
175
|
const q = quoteIdentifier;
|
|
153
176
|
const startsSelect = `SELECT ${q("start")},
|
|
154
177
|
${prepared.key(q("start"))} AS ${q("__key")}
|
|
155
178
|
FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})`;
|
|
156
|
-
const costStates = buildGraphTemporalCostStateSql(prepared, startsSelect, direction, temporal, distanceType, edgeWeight);
|
|
179
|
+
const costStates = buildGraphTemporalCostStateSql(prepared, startsSelect, direction, temporal, distanceType, edgeWeight, [], minimize);
|
|
180
|
+
const order = minimize === "steps"
|
|
181
|
+
? `${q("steps")}, ${q("distance")}`
|
|
182
|
+
: `${q("distance")}, ${q("steps")}`;
|
|
157
183
|
return `${costStates.withClause}
|
|
158
|
-
SELECT ${q("start")}, ${q("node")},
|
|
159
|
-
MIN(${q("distance")}) AS ${q("distance")}
|
|
184
|
+
SELECT ${q("start")}, ${q("node")}, ${q("steps")}${includeTotal ? `, ${q("distance")} AS ${q("total")}` : ""}
|
|
160
185
|
FROM ${costStates.costRelation}
|
|
161
|
-
|
|
162
|
-
${q("__node_key")}
|
|
163
|
-
|
|
186
|
+
QUALIFY row_number() OVER (
|
|
187
|
+
PARTITION BY ${q("__start_key")}, ${q("__node_key")}
|
|
188
|
+
ORDER BY ${order}
|
|
189
|
+
) = 1
|
|
190
|
+
ORDER BY ${q("__start_key")}, ${q(minimize === "steps" ? "steps" : "distance")}, ${q("__node_key")}`;
|
|
191
|
+
}
|
|
192
|
+
// Distinct visited sets, metrics, and temporal boundaries are enough to extend
|
|
193
|
+
// summaries. No edge IDs or full connection sequences are needed. Keeping the
|
|
194
|
+
// visited set is necessary: equal summaries can have different legal extensions.
|
|
195
|
+
function summaryDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics, includeTotal, floatingWeight) {
|
|
196
|
+
const q = quoteIdentifier;
|
|
197
|
+
const relations = prepared.relationNames([
|
|
198
|
+
"graph_starts",
|
|
199
|
+
"graph_temporal_settings",
|
|
200
|
+
"graph_event_rows",
|
|
201
|
+
"graph_edges",
|
|
202
|
+
"graph_summaries",
|
|
203
|
+
"graph_metric_results",
|
|
204
|
+
"graph_tied_summaries",
|
|
205
|
+
"graph_best_metrics",
|
|
206
|
+
"graph_metric_bounds",
|
|
207
|
+
]);
|
|
208
|
+
const starts = relations.graph_starts;
|
|
209
|
+
const settings = relations.graph_temporal_settings;
|
|
210
|
+
const events = relations.graph_event_rows;
|
|
211
|
+
const edges = relations.graph_edges;
|
|
212
|
+
const summaries = relations.graph_summaries;
|
|
213
|
+
const results = relations.graph_metric_results;
|
|
214
|
+
const tied = relations.graph_tied_summaries;
|
|
215
|
+
const ref = (alias, column) => `${q(alias)}.${q(column)}`;
|
|
216
|
+
const searchDirection = direction;
|
|
217
|
+
const firstAnchor = temporal?.journeyAnchor("edges", searchDirection);
|
|
218
|
+
const sum = `CAST(${ref("reached", "distance")} + ${ref("edges", "__weight")} AS ${distanceType})`;
|
|
219
|
+
// Reported costs must not reject routes before the primary objective has
|
|
220
|
+
// selected its results. NULL marks overflow and propagates through sums;
|
|
221
|
+
// non-negative weights cannot bring an overflowing total back into range.
|
|
222
|
+
const nextDistance = metrics.minimize === "weight" ? sum : `TRY(${sum})`;
|
|
223
|
+
const temporalColumns = temporal === undefined
|
|
224
|
+
? ""
|
|
225
|
+
: `, ${q("__event_start")}, ${q("__event_end")}`;
|
|
226
|
+
const eventValues = temporal === undefined
|
|
227
|
+
? ""
|
|
228
|
+
: `, ${ref("edges", "__event_start")}, ${ref("edges", "__event_end")}`;
|
|
229
|
+
const metric = metrics.minimize === "steps"
|
|
230
|
+
? q("steps")
|
|
231
|
+
: metrics.minimize === "weight"
|
|
232
|
+
? q("distance")
|
|
233
|
+
: q("__elapsed");
|
|
234
|
+
// Use native time precision for selection. Collapse equal reported values
|
|
235
|
+
// after conversion to milliseconds, since these are summary rows.
|
|
236
|
+
const reportedElapsed = metrics.elapsedTime
|
|
237
|
+
? `, ${temporal.elapsedMilliseconds(q("__elapsed"))} AS ${q("elapsedTimeMs")}`
|
|
238
|
+
: "";
|
|
239
|
+
const order = metrics.minimize === "steps"
|
|
240
|
+
? [
|
|
241
|
+
q("steps"),
|
|
242
|
+
q("__node_key"),
|
|
243
|
+
...(includeTotal ? [q("total")] : []),
|
|
244
|
+
...(metrics.elapsedTime ? [q("elapsedTimeMs")] : []),
|
|
245
|
+
]
|
|
246
|
+
: metrics.minimize === "weight"
|
|
247
|
+
? [
|
|
248
|
+
q("total"),
|
|
249
|
+
q("__node_key"),
|
|
250
|
+
q("steps"),
|
|
251
|
+
...(metrics.elapsedTime ? [q("elapsedTimeMs")] : []),
|
|
252
|
+
]
|
|
253
|
+
: [
|
|
254
|
+
q("elapsedTimeMs"),
|
|
255
|
+
q("__node_key"),
|
|
256
|
+
q("steps"),
|
|
257
|
+
...(includeTotal ? [q("total")] : []),
|
|
258
|
+
];
|
|
259
|
+
const bounds = summaryBoundsSql(relations.graph_best_metrics, relations.graph_metric_bounds, starts, edges, settings, temporal, searchDirection, metrics.minimize, distanceType, floatingWeight);
|
|
260
|
+
return `WITH RECURSIVE ${settings} AS (
|
|
261
|
+
${temporal === undefined
|
|
262
|
+
? `SELECT 0 AS ${q("__gap")}`
|
|
263
|
+
: `SELECT CAST(? AS HUGEINT) AS ${q("__gap")}`}
|
|
264
|
+
), ${events} AS MATERIALIZED (
|
|
265
|
+
${prepared.edges(direction, [
|
|
266
|
+
`${edgeWeight} AS ${q("__weight")}`,
|
|
267
|
+
...(temporal?.eventSelections("edges") ?? []),
|
|
268
|
+
])}
|
|
269
|
+
), ${edges} AS MATERIALIZED (
|
|
270
|
+
SELECT DISTINCT ${q("__from")}, ${q("__to")}, ${q("__from_key")},
|
|
271
|
+
${q("__to_key")}, ${q("__weight")}${temporalColumns}
|
|
272
|
+
FROM ${events} AS ${q("events")}
|
|
273
|
+
${temporal === undefined ? "" : `WHERE ${temporal.eventValidity("events")}`}
|
|
274
|
+
), ${starts} AS (
|
|
275
|
+
SELECT ${q("start")}, ${prepared.key(q("start"))} AS ${q("__key")}
|
|
276
|
+
FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})
|
|
277
|
+
), ${bounds.ctes}, ${summaries}(
|
|
278
|
+
${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
|
|
279
|
+
${q("__visited")}, ${q("steps")}, ${q("distance")}${temporalColumns}${metrics.elapsedTime ? `, ${q("__anchor")}` : ""}
|
|
280
|
+
) AS (
|
|
281
|
+
SELECT ${ref("starts", "start")}, ${ref("edges", "__to")},
|
|
282
|
+
${ref("starts", "__key")}, ${ref("edges", "__to_key")},
|
|
283
|
+
list_sort(list_distinct([${ref("starts", "__key")}, ${ref("edges", "__to_key")}])),
|
|
284
|
+
CAST(1 AS BIGINT), ${ref("edges", "__weight")}${eventValues}${metrics.elapsedTime ? `, ${firstAnchor}` : ""}
|
|
285
|
+
FROM ${starts} AS ${q("starts")}
|
|
286
|
+
INNER JOIN ${edges} AS ${q("edges")}
|
|
287
|
+
ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
|
|
288
|
+
${bounds.join(ref("starts", "__key"))}
|
|
289
|
+
WHERE ${bounds.test("CAST(1 AS BIGINT)", ref("edges", "__weight"), firstAnchor)}
|
|
290
|
+
UNION
|
|
291
|
+
SELECT ${ref("reached", "start")}, ${ref("edges", "__to")},
|
|
292
|
+
${ref("reached", "__start_key")}, ${ref("edges", "__to_key")},
|
|
293
|
+
list_sort(list_distinct(list_append(${ref("reached", "__visited")}, ${ref("edges", "__to_key")}))),
|
|
294
|
+
${ref("reached", "steps")} + 1, ${nextDistance}${eventValues}${metrics.elapsedTime ? `, ${ref("reached", "__anchor")}` : ""}
|
|
295
|
+
FROM ${summaries} AS ${q("reached")}
|
|
296
|
+
INNER JOIN ${edges} AS ${q("edges")}
|
|
297
|
+
ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
|
|
298
|
+
CROSS JOIN ${settings} AS ${q("settings")}
|
|
299
|
+
${bounds.join(ref("reached", "__start_key"))}
|
|
300
|
+
WHERE ${bounds.test(`${ref("reached", "steps")} + 1`, nextDistance, ref("reached", "__anchor"))}
|
|
301
|
+
AND ${ref("reached", "__node_key")} <> ${ref("reached", "__start_key")}
|
|
302
|
+
AND (NOT list_contains(${ref("reached", "__visited")}, ${ref("edges", "__to_key")})
|
|
303
|
+
OR ${ref("edges", "__to_key")} = ${ref("reached", "__start_key")})
|
|
304
|
+
${temporal === undefined ? "" : `AND ${temporal.transition("reached", "edges", searchDirection, ref("settings", "__gap"))}`}
|
|
305
|
+
), ${results} AS (
|
|
306
|
+
SELECT *${metrics.elapsedTime
|
|
307
|
+
? `, ${temporal.journeyElapsed("summaries", ref("summaries", "__anchor"), searchDirection)} AS ${q("__elapsed")}`
|
|
308
|
+
: ""}
|
|
309
|
+
FROM ${summaries} AS ${q("summaries")}
|
|
310
|
+
), ${tied} AS MATERIALIZED (
|
|
311
|
+
SELECT DISTINCT ${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
|
|
312
|
+
${q("steps")}${includeTotal ? `, ${q("distance")} AS ${q("total")}` : ""}${reportedElapsed}
|
|
313
|
+
FROM ${results}
|
|
314
|
+
QUALIFY ${metric} = MIN(${metric}) OVER (
|
|
315
|
+
PARTITION BY ${q("__start_key")}, ${q("__node_key")}
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
SELECT ${q("start")}, ${q("node")}, ${q("steps")}${includeTotal
|
|
319
|
+
? `, CASE WHEN ${q("total")} IS NULL
|
|
320
|
+
THEN error('distances() total exceeds the supported ${distanceType} range for an optimal route.')
|
|
321
|
+
ELSE ${q("total")} END AS ${q("total")}`
|
|
322
|
+
: ""}${metrics.elapsedTime ? `, ${q("elapsedTimeMs")}` : ""}
|
|
323
|
+
FROM ${tied}
|
|
324
|
+
ORDER BY ${q("__start_key")}, ${order.join(", ")}`;
|
|
325
|
+
}
|
|
326
|
+
// Compute primary optima without enumerating visited sets. Exact additive
|
|
327
|
+
// objectives have optimal prefixes (at the same event boundary in temporal
|
|
328
|
+
// traversal). Floating addition can erase prefix differences, and elapsed
|
|
329
|
+
// optima can depend on a later departure, so those use a per-start upper bound.
|
|
330
|
+
function summaryBoundsSql(best, limits, starts, edges, settings, temporal, direction, minimize, distanceType, floatingWeight) {
|
|
331
|
+
const q = quoteIdentifier;
|
|
332
|
+
const ref = (alias, column) => `${q(alias)}.${q(column)}`;
|
|
333
|
+
const elapsed = minimize === "elapsedTime";
|
|
334
|
+
const globalBound = elapsed || (minimize === "weight" && floatingWeight);
|
|
335
|
+
const boundaries = temporal === undefined
|
|
336
|
+
? []
|
|
337
|
+
: ["__event_start", "__event_end"];
|
|
338
|
+
const keys = [
|
|
339
|
+
"__start_key",
|
|
340
|
+
"__node_key",
|
|
341
|
+
...boundaries,
|
|
342
|
+
...(elapsed ? ["__anchor"] : []),
|
|
343
|
+
];
|
|
344
|
+
const firstAnchor = elapsed
|
|
345
|
+
? temporal.journeyAnchor("edges", direction)
|
|
346
|
+
: undefined;
|
|
347
|
+
const firstKeys = [
|
|
348
|
+
ref("starts", "__key"),
|
|
349
|
+
ref("edges", "__to_key"),
|
|
350
|
+
...boundaries.map((key) => ref("edges", key)),
|
|
351
|
+
...(elapsed ? [firstAnchor] : []),
|
|
352
|
+
];
|
|
353
|
+
const nextKeys = [
|
|
354
|
+
ref("reached", "__start_key"),
|
|
355
|
+
ref("edges", "__to_key"),
|
|
356
|
+
...boundaries.map((key) => ref("edges", key)),
|
|
357
|
+
...(elapsed ? [ref("reached", "__anchor")] : []),
|
|
358
|
+
];
|
|
359
|
+
const firstMetric = minimize === "steps"
|
|
360
|
+
? "CAST(1 AS BIGINT)"
|
|
361
|
+
: elapsed
|
|
362
|
+
? temporal.journeyElapsed("edges", firstAnchor, direction)
|
|
363
|
+
: ref("edges", "__weight");
|
|
364
|
+
const nextMetric = minimize === "steps"
|
|
365
|
+
? `${ref("reached", "__metric")} + 1`
|
|
366
|
+
: elapsed
|
|
367
|
+
? temporal.journeyElapsed("edges", ref("reached", "__anchor"), direction)
|
|
368
|
+
: `CAST(${ref("reached", "__metric")} + ${ref("edges", "__weight")} AS ${distanceType})`;
|
|
369
|
+
const minimum = `MIN(${nextMetric})`;
|
|
370
|
+
const bestMetric = ref("best", "__metric");
|
|
371
|
+
const ctes = `${best}(${keys.map(q).join(", ")}, ${q("__metric")})
|
|
372
|
+
USING KEY(${keys.map(q).join(", ")}) AS (
|
|
373
|
+
SELECT ${firstKeys.join(", ")}, MIN(${firstMetric})
|
|
374
|
+
FROM ${starts} AS ${q("starts")}
|
|
375
|
+
INNER JOIN ${edges} AS ${q("edges")}
|
|
376
|
+
ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
|
|
377
|
+
GROUP BY ${firstKeys.join(", ")}
|
|
378
|
+
UNION
|
|
379
|
+
SELECT ${nextKeys.join(", ")}, ${minimum}
|
|
380
|
+
FROM ${best} AS ${q("reached")}
|
|
381
|
+
INNER JOIN ${edges} AS ${q("edges")}
|
|
382
|
+
ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
|
|
383
|
+
CROSS JOIN ${settings} AS ${q("settings")}
|
|
384
|
+
LEFT JOIN recurring.${best} AS ${q("best")}
|
|
385
|
+
ON ${keys.map((key, i) => `${ref("best", key)} = ${nextKeys[i]}`).join(" AND ")}
|
|
386
|
+
WHERE ${ref("reached", "__node_key")} <> ${ref("reached", "__start_key")}
|
|
387
|
+
${temporal === undefined ? "" : `AND ${temporal.transition("reached", "edges", direction, ref("settings", "__gap"))}`}
|
|
388
|
+
GROUP BY ${nextKeys.join(", ")}, ${bestMetric}
|
|
389
|
+
HAVING ${bestMetric} IS NULL OR ${minimum} < ${bestMetric}
|
|
390
|
+
)${globalBound
|
|
391
|
+
? `, ${limits} AS (
|
|
392
|
+
SELECT ${q("__start_key")}, MAX(${q("__minimum")}) AS ${q("__metric")}
|
|
393
|
+
FROM (
|
|
394
|
+
SELECT ${q("__start_key")}, ${q("__node_key")}, MIN(${q("__metric")}) AS ${q("__minimum")}
|
|
395
|
+
FROM ${best}
|
|
396
|
+
GROUP BY ${q("__start_key")}, ${q("__node_key")}
|
|
397
|
+
) AS ${q("minima")}
|
|
398
|
+
GROUP BY ${q("__start_key")}
|
|
399
|
+
)`
|
|
400
|
+
: ""}`;
|
|
401
|
+
return {
|
|
402
|
+
ctes,
|
|
403
|
+
join: (startKey) => `INNER JOIN ${globalBound ? limits : best} AS ${q("bounds")}
|
|
404
|
+
ON ${ref("bounds", "__start_key")} = ${startKey}
|
|
405
|
+
${globalBound
|
|
406
|
+
? ""
|
|
407
|
+
: `AND ${ref("bounds", "__node_key")} = ${ref("edges", "__to_key")}
|
|
408
|
+
${boundaries.map((key) => `AND ${ref("bounds", key)} = ${ref("edges", key)}`).join(" ")}`}`,
|
|
409
|
+
test: (steps, distance, anchor) => {
|
|
410
|
+
const metric = minimize === "steps"
|
|
411
|
+
? steps
|
|
412
|
+
: elapsed
|
|
413
|
+
? temporal.journeyElapsed("edges", anchor, direction)
|
|
414
|
+
: distance;
|
|
415
|
+
return `${metric} ${globalBound ? "<=" : "="} ${ref("bounds", "__metric")}`;
|
|
416
|
+
},
|
|
417
|
+
};
|
|
164
418
|
}
|
|
@@ -3,6 +3,7 @@ import { type GraphTemporalOptions } from "../helpers/prepareGraphTemporalSql.js
|
|
|
3
3
|
import { type GraphId } from "../helpers/prepareGraphStarts.js";
|
|
4
4
|
import { type GraphDirection } from "../helpers/prepareGraphTraversal.js";
|
|
5
5
|
type FindCyclesOptions = GraphTemporalOptions & {
|
|
6
|
+
elapsedTime?: boolean;
|
|
6
7
|
direction?: GraphDirection;
|
|
7
8
|
outputTable?: string | boolean;
|
|
8
9
|
weight?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findCycles.d.ts","sourceRoot":"","sources":["../../src/methods/findCycles.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"findCycles.d.ts","sourceRoot":"","sources":["../../src/methods/findCycles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAMvD,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;AAM7C,KAAK,iBAAiB,GAAG,oBAAoB,GAAG;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,GAAG,OAAO,EAAE,EAC/B,OAAO,GAAE,iBAAsB,GAC9B,WAAW,CAgIb"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import prepareGraphMetricOptions from "../helpers/prepareGraphMetricOptions.js";
|
|
1
2
|
import getGraphEdgeIdColumn from "../helpers/getGraphEdgeIdColumn.js";
|
|
2
3
|
import getGraphWeightColumn from "../helpers/getGraphWeightColumn.js";
|
|
3
4
|
import graphRouteResultSchema from "../helpers/graphRouteResultSchema.js";
|
|
@@ -35,6 +36,7 @@ export default function findCycles(simpleTable, sourceColumn, targetColumn, edge
|
|
|
35
36
|
typeof options.outputTable !== "boolean") {
|
|
36
37
|
throw new TypeError("findCycles() options.outputTable must be a string or boolean.");
|
|
37
38
|
}
|
|
39
|
+
const metric = prepareGraphMetricOptions(options, "findCycles()", false);
|
|
38
40
|
const direction = options.direction ?? "outgoing";
|
|
39
41
|
const temporalOptions = prepareGraphTemporalOptions(options, direction, "findCycles()");
|
|
40
42
|
options = structuredClone(options);
|
|
@@ -53,7 +55,8 @@ export default function findCycles(simpleTable, sourceColumn, targetColumn, edge
|
|
|
53
55
|
? undefined
|
|
54
56
|
: (input) => validateGraphTemporalEvents(input, temporalOptions, "findCycles()", parameters),
|
|
55
57
|
values: (schema) => {
|
|
56
|
-
validateFindCyclesInputs(schema, sourceColumn, targetColumn, edgeId, preparedStarts, options.weight);
|
|
58
|
+
const validated = validateFindCyclesInputs(schema, sourceColumn, targetColumn, edgeId, preparedStarts, options.weight);
|
|
59
|
+
graphRouteResultSchema(schema, validated.distanceType, "findCycles()", metric.elapsedTime);
|
|
57
60
|
const temporal = temporalOptions === undefined
|
|
58
61
|
? undefined
|
|
59
62
|
: prepareGraphTemporalSql(schema, temporalOptions, "findCycles()");
|
|
@@ -61,7 +64,7 @@ export default function findCycles(simpleTable, sourceColumn, targetColumn, edge
|
|
|
61
64
|
? preparedStarts.values
|
|
62
65
|
: [temporal.gapParameter, ...preparedStarts.values];
|
|
63
66
|
},
|
|
64
|
-
buildSelect: (input, schema) => findCyclesSelect(input, schema, sourceColumn, targetColumn, edgeId, preparedStarts, direction, options.weight, temporalOptions),
|
|
67
|
+
buildSelect: (input, schema) => findCyclesSelect(input, schema, sourceColumn, targetColumn, edgeId, preparedStarts, direction, options.weight, temporalOptions, metric.elapsedTime),
|
|
65
68
|
outputSchema: (schema) => {
|
|
66
69
|
const validated = validateFindCyclesInputs(schema, sourceColumn, targetColumn, edgeId, preparedStarts, options.weight);
|
|
67
70
|
if (temporalOptions !== undefined) {
|
|
@@ -69,7 +72,7 @@ export default function findCycles(simpleTable, sourceColumn, targetColumn, edge
|
|
|
69
72
|
}
|
|
70
73
|
return {
|
|
71
74
|
start: validated.nodeIdType,
|
|
72
|
-
...graphRouteResultSchema(schema, validated.distanceType, "findCycles()"),
|
|
75
|
+
...graphRouteResultSchema(schema, validated.distanceType, "findCycles()", metric.elapsedTime),
|
|
73
76
|
};
|
|
74
77
|
},
|
|
75
78
|
});
|
|
@@ -87,7 +90,7 @@ function validateFindCyclesInputs(schema, source, target, edgeId, starts, weight
|
|
|
87
90
|
nodeIdType: endpoints.idType,
|
|
88
91
|
};
|
|
89
92
|
}
|
|
90
|
-
function findCyclesSelect(input, schema, source, target, edgeId, starts, direction, weight, temporalOptions) {
|
|
93
|
+
function findCyclesSelect(input, schema, source, target, edgeId, starts, direction, weight, temporalOptions, elapsedTime) {
|
|
91
94
|
const prepared = prepareGraphTraversal(input, schema, source, target, starts, "findCycles()", "startNodes");
|
|
92
95
|
const edgeIdColumn = getGraphEdgeIdColumn(schema, edgeId, "findCycles()");
|
|
93
96
|
const weightColumn = weight === undefined
|
|
@@ -103,10 +106,10 @@ function findCyclesSelect(input, schema, source, target, edgeId, starts, directi
|
|
|
103
106
|
const edgeWeight = weightColumn === undefined
|
|
104
107
|
? `CAST(1 AS ${distanceType})`
|
|
105
108
|
: `CAST(${q("edges")}.${q(weightColumn.column)} AS ${distanceType})`;
|
|
106
|
-
const stepType = `STRUCT(${q("edgeId")} ${edgeIdColumn.idType}, ${q("source")} ${prepared.endpoints.idType}, ${q("target")} ${prepared.endpoints.idType}, ${q("weight")} ${distanceType}, ${q("distance")} ${distanceType})`;
|
|
109
|
+
const stepType = `STRUCT(${q("edgeId")} ${edgeIdColumn.idType}, ${q("source")} ${prepared.endpoints.idType}, ${q("target")} ${prepared.endpoints.idType}, ${q("weight")} ${distanceType}, ${q("distance")} ${distanceType}${elapsedTime ? `, ${q("elapsedTimeMs")} DOUBLE` : ""})`;
|
|
107
110
|
if (temporalOptions !== undefined) {
|
|
108
111
|
const temporal = prepareGraphTemporalSql(schema, temporalOptions, "findCycles()");
|
|
109
|
-
return temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn);
|
|
112
|
+
return temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn, elapsedTime);
|
|
110
113
|
}
|
|
111
114
|
const relations = prepared.relationNames([
|
|
112
115
|
"graph_start_values",
|
|
@@ -210,7 +213,7 @@ function findCyclesSelect(input, schema, source, target, edgeId, starts, directi
|
|
|
210
213
|
)
|
|
211
214
|
${graphRouteResultSelect(rankedRelation, input, edgeIdColumn, true)}`;
|
|
212
215
|
}
|
|
213
|
-
function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn) {
|
|
216
|
+
function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn, elapsedTime) {
|
|
214
217
|
const q = quoteIdentifier;
|
|
215
218
|
const relations = prepared.relationNames([
|
|
216
219
|
"graph_start_values",
|
|
@@ -240,12 +243,16 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
|
|
|
240
243
|
const walkDistance = `${q("walks")}.${q("distance")}`;
|
|
241
244
|
const candidateDistance = `CAST(${walkDistance} + ${edgeCost} AS ${distanceType})`;
|
|
242
245
|
const gap = `${q("settings")}.${q("__gap")}`;
|
|
243
|
-
const
|
|
246
|
+
const firstAnchor = temporal.journeyAnchor("edges", direction);
|
|
247
|
+
const anchor = `${q("walks")}.${q("__journey_anchor")}`;
|
|
248
|
+
const step = (distance, journeyAnchor) => `struct_pack(
|
|
244
249
|
${q("edgeId")} := ${edgeIdentity},
|
|
245
250
|
${q("source")} := ${edgeFrom},
|
|
246
251
|
${q("target")} := ${edgeTo},
|
|
247
252
|
${q("weight")} := ${edgeCost},
|
|
248
|
-
${q("distance")} := ${distance}
|
|
253
|
+
${q("distance")} := ${distance}${elapsedTime
|
|
254
|
+
? `, ${q("elapsedTimeMs")} := ${temporal.elapsedMilliseconds(temporal.journeyElapsed("edges", journeyAnchor, direction))}`
|
|
255
|
+
: ""}
|
|
249
256
|
)`;
|
|
250
257
|
return `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (
|
|
251
258
|
SELECT CAST(? AS HUGEINT) AS ${q("__gap")}
|
|
@@ -271,7 +278,7 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
|
|
|
271
278
|
${q("__node_key")}, ${q("__visited")}, ${q("__event_ids")},
|
|
272
279
|
${q("__edge_keys")}, ${q("steps")}, ${q("distance")},
|
|
273
280
|
${q("closed")}, ${q("__event_id")}, ${q("__event_start")},
|
|
274
|
-
${q("__event_end")}
|
|
281
|
+
${q("__event_end")}${elapsedTime ? `, ${q("__journey_anchor")}` : ""}
|
|
275
282
|
) AS (
|
|
276
283
|
SELECT ${q("starts")}.${q("start")},
|
|
277
284
|
${q("starts")}.${q("__start_key")}, ${edgeTo}, ${edgeToKey},
|
|
@@ -280,11 +287,11 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
|
|
|
280
287
|
ELSE [${edgeFromKey}, ${edgeToKey}]
|
|
281
288
|
END,
|
|
282
289
|
[${q("edges")}.${q("__event_id")}], [${edgeIdentityKey}],
|
|
283
|
-
[${step(edgeCost)}]::${stepType}[], ${edgeCost},
|
|
290
|
+
[${step(edgeCost, firstAnchor)}]::${stepType}[], ${edgeCost},
|
|
284
291
|
${edgeFromKey} = ${edgeToKey},
|
|
285
292
|
${q("edges")}.${q("__event_id")},
|
|
286
293
|
${q("edges")}.${q("__event_start")},
|
|
287
|
-
${q("edges")}.${q("__event_end")}
|
|
294
|
+
${q("edges")}.${q("__event_end")}${elapsedTime ? `, ${firstAnchor}` : ""}
|
|
288
295
|
FROM ${edgesRelation} AS ${q("edges")}
|
|
289
296
|
INNER JOIN ${startsRelation} AS ${q("starts")}
|
|
290
297
|
ON ${q("starts")}.${q("__start_key")} = ${edgeFromKey}
|
|
@@ -295,12 +302,12 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
|
|
|
295
302
|
list_append(${q("walks")}.${q("__event_ids")},
|
|
296
303
|
${q("edges")}.${q("__event_id")}),
|
|
297
304
|
list_append(${q("walks")}.${q("__edge_keys")}, ${edgeIdentityKey}),
|
|
298
|
-
list_append(${q("walks")}.${q("steps")}, ${step(candidateDistance)}),
|
|
305
|
+
list_append(${q("walks")}.${q("steps")}, ${step(candidateDistance, anchor)}),
|
|
299
306
|
${candidateDistance},
|
|
300
307
|
${edgeToKey} = ${q("walks")}.${q("__start_key")},
|
|
301
308
|
${q("edges")}.${q("__event_id")},
|
|
302
309
|
${q("edges")}.${q("__event_start")},
|
|
303
|
-
${q("edges")}.${q("__event_end")}
|
|
310
|
+
${q("edges")}.${q("__event_end")}${elapsedTime ? `, ${anchor}` : ""}
|
|
304
311
|
FROM ${walksRelation} AS ${q("walks")}
|
|
305
312
|
INNER JOIN ${edgesRelation} AS ${q("edges")}
|
|
306
313
|
ON ${q("walks")}.${q("__node_key")} = ${edgeFromKey}
|
|
@@ -326,5 +333,5 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
|
|
|
326
333
|
AS BIGINT) AS ${q("pathId")}, ${q("steps")}
|
|
327
334
|
FROM ${completeRelation}
|
|
328
335
|
)
|
|
329
|
-
${graphRouteResultSelect(rankedRelation, input, edgeIdColumn, true)}`;
|
|
336
|
+
${graphRouteResultSelect(rankedRelation, input, edgeIdColumn, true, elapsedTime)}`;
|
|
330
337
|
}
|
package/esm/methods/paths.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { GraphId } from "../helpers/prepareGraphStarts.js";
|
|
|
3
3
|
import { type GraphTemporalOptions } from "../helpers/prepareGraphTemporalSql.js";
|
|
4
4
|
import type { GraphDirection } from "../helpers/prepareGraphTraversal.js";
|
|
5
5
|
type PathsOptions = GraphTemporalOptions & {
|
|
6
|
+
elapsedTime?: boolean;
|
|
6
7
|
direction?: GraphDirection;
|
|
7
8
|
outputTable?: string | boolean;
|
|
8
9
|
weight?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/methods/paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/methods/paths.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AASvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAgC,EAC9B,KAAK,oBAAoB,EAG1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAM1E,KAAK,YAAY,GAAG,oBAAoB,GAAG;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,KAAK,CAC3B,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,YAAiB,GACzB,WAAW,CA4Hb"}
|