@nshiab/simple-data-analysis-core 2.1.5 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/esm/class/SimpleTable.d.ts +254 -27
  2. package/esm/class/SimpleTable.d.ts.map +1 -1
  3. package/esm/class/SimpleTable.js +248 -27
  4. package/esm/helpers/graphRouteResultSchema.d.ts +1 -1
  5. package/esm/helpers/graphRouteResultSchema.d.ts.map +1 -1
  6. package/esm/helpers/graphRouteResultSchema.js +3 -2
  7. package/esm/helpers/graphRouteResultSelect.d.ts +1 -1
  8. package/esm/helpers/graphRouteResultSelect.d.ts.map +1 -1
  9. package/esm/helpers/graphRouteResultSelect.js +4 -1
  10. package/esm/helpers/prepareGraphMetricOptions.d.ts +14 -0
  11. package/esm/helpers/prepareGraphMetricOptions.d.ts.map +1 -0
  12. package/esm/helpers/prepareGraphMetricOptions.js +40 -0
  13. package/esm/helpers/prepareGraphTemporalSql.d.ts +3 -0
  14. package/esm/helpers/prepareGraphTemporalSql.d.ts.map +1 -1
  15. package/esm/helpers/prepareGraphTemporalSql.js +7 -0
  16. package/esm/methods/distances.d.ts +2 -0
  17. package/esm/methods/distances.d.ts.map +1 -1
  18. package/esm/methods/distances.js +98 -6
  19. package/esm/methods/findCycles.d.ts +1 -0
  20. package/esm/methods/findCycles.d.ts.map +1 -1
  21. package/esm/methods/findCycles.js +22 -15
  22. package/esm/methods/paths.d.ts +1 -0
  23. package/esm/methods/paths.d.ts.map +1 -1
  24. package/esm/methods/paths.js +21 -14
  25. package/esm/methods/shortestPath.d.ts +2 -0
  26. package/esm/methods/shortestPath.d.ts.map +1 -1
  27. package/esm/methods/shortestPath.js +125 -20
  28. package/llm.md +284 -58
  29. package/llms.txt +1 -1
  30. package/package.json +1 -1
  31. package/script/class/SimpleTable.d.ts +254 -27
  32. package/script/class/SimpleTable.d.ts.map +1 -1
  33. package/script/class/SimpleTable.js +248 -27
  34. package/script/helpers/graphRouteResultSchema.d.ts +1 -1
  35. package/script/helpers/graphRouteResultSchema.d.ts.map +1 -1
  36. package/script/helpers/graphRouteResultSchema.js +3 -2
  37. package/script/helpers/graphRouteResultSelect.d.ts +1 -1
  38. package/script/helpers/graphRouteResultSelect.d.ts.map +1 -1
  39. package/script/helpers/graphRouteResultSelect.js +4 -1
  40. package/script/helpers/prepareGraphMetricOptions.d.ts +14 -0
  41. package/script/helpers/prepareGraphMetricOptions.d.ts.map +1 -0
  42. package/script/helpers/prepareGraphMetricOptions.js +43 -0
  43. package/script/helpers/prepareGraphTemporalSql.d.ts +3 -0
  44. package/script/helpers/prepareGraphTemporalSql.d.ts.map +1 -1
  45. package/script/helpers/prepareGraphTemporalSql.js +7 -0
  46. package/script/methods/distances.d.ts +2 -0
  47. package/script/methods/distances.d.ts.map +1 -1
  48. package/script/methods/distances.js +98 -6
  49. package/script/methods/findCycles.d.ts +1 -0
  50. package/script/methods/findCycles.d.ts.map +1 -1
  51. package/script/methods/findCycles.js +22 -15
  52. package/script/methods/paths.d.ts +1 -0
  53. package/script/methods/paths.d.ts.map +1 -1
  54. package/script/methods/paths.js +21 -14
  55. package/script/methods/shortestPath.d.ts +2 -0
  56. package/script/methods/shortestPath.d.ts.map +1 -1
  57. package/script/methods/shortestPath.js +125 -20
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = distances;
40
40
  const buildGraphTemporalCostStateSql_js_1 = __importDefault(require("../helpers/buildGraphTemporalCostStateSql.js"));
41
41
  const getGraphWeightColumn_js_1 = __importDefault(require("../helpers/getGraphWeightColumn.js"));
42
+ const prepareGraphMetricOptions_js_1 = __importDefault(require("../helpers/prepareGraphMetricOptions.js"));
42
43
  const prepareGraphTemporalSql_js_1 = __importStar(require("../helpers/prepareGraphTemporalSql.js"));
43
44
  const prepareGraphStarts_js_1 = __importDefault(require("../helpers/prepareGraphStarts.js"));
44
45
  const prepareGraphTraversal_js_1 = __importStar(require("../helpers/prepareGraphTraversal.js"));
@@ -67,6 +68,7 @@ function distances(simpleTable, sourceColumn, targetColumn, startNodes, options
67
68
  typeof options.outputTable !== "boolean") {
68
69
  throw new TypeError("distances() options.outputTable must be a string or boolean.");
69
70
  }
71
+ const metrics = (0, prepareGraphMetricOptions_js_1.default)(options, "distances()", true);
70
72
  const preparedStarts = (0, prepareGraphStarts_js_1.default)(startNodes, "distances()", "startNodes");
71
73
  const direction = options.direction ?? "outgoing";
72
74
  const temporalOptions = (0, prepareGraphTemporalSql_js_1.prepareGraphTemporalOptions)(options, direction, "distances()");
@@ -90,13 +92,14 @@ function distances(simpleTable, sourceColumn, targetColumn, startNodes, options
90
92
  ? preparedStarts.values
91
93
  : [temporal.gapParameter, ...preparedStarts.values];
92
94
  },
93
- buildSelect: (input, schema) => distancesSelect(input, schema, sourceColumn, targetColumn, preparedStarts, direction, options.weight, temporalOptions),
95
+ buildSelect: (input, schema) => distancesSelect(input, schema, sourceColumn, targetColumn, preparedStarts, direction, options.weight, temporalOptions, metrics),
94
96
  outputSchema: (schema) => {
95
97
  const validated = validateDistanceInputs(schema, sourceColumn, targetColumn, preparedStarts, options.weight, temporalOptions);
96
98
  return {
97
99
  start: validated.idType,
98
100
  node: validated.idType,
99
- distance: validated.distanceType,
101
+ total: validated.distanceType,
102
+ ...(metrics.elapsedTime ? { elapsedTimeMs: "DOUBLE" } : {}),
100
103
  };
101
104
  },
102
105
  });
@@ -111,7 +114,7 @@ function validateDistanceInputs(schema, source, target, starts, weight, temporal
111
114
  : (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "distances()");
112
115
  return { idType: endpoints.idType, distanceType, temporal };
113
116
  }
114
- function distancesSelect(input, schema, source, target, starts, direction, weight, temporalOptions) {
117
+ function distancesSelect(input, schema, source, target, starts, direction, weight, temporalOptions, metrics) {
115
118
  const prepared = (0, prepareGraphTraversal_js_1.default)(input, schema, source, target, starts, "distances()", "startNodes");
116
119
  const weightColumn = weight === undefined
117
120
  ? undefined
@@ -122,6 +125,9 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
122
125
  : `CAST(${(0, quoteIdentifier_js_1.default)("edges")}.${(0, quoteIdentifier_js_1.default)(weightColumn.column)} AS ${distanceType})`;
123
126
  if (temporalOptions !== undefined) {
124
127
  const temporal = (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "distances()");
128
+ if (metrics.elapsedTime) {
129
+ return elapsedDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, metrics.minimize);
130
+ }
125
131
  return temporalDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight);
126
132
  }
127
133
  const relations = prepared.relationNames([
@@ -183,7 +189,7 @@ function distancesSelect(input, schema, source, target, starts, direction, weigh
183
189
  HAVING ${bestDistance} IS NULL OR MIN(${candidateDistance}) < ${bestDistance}
184
190
  )
185
191
  SELECT ${(0, quoteIdentifier_js_1.default)("start")}, ${(0, quoteIdentifier_js_1.default)("node")},
186
- ${(0, quoteIdentifier_js_1.default)("distance")}
192
+ ${(0, quoteIdentifier_js_1.default)("distance")} AS ${(0, quoteIdentifier_js_1.default)("total")}
187
193
  FROM ${distancesRelation}
188
194
  ORDER BY ${(0, quoteIdentifier_js_1.default)("__start_key")}, ${(0, quoteIdentifier_js_1.default)("distance")}, ${(0, quoteIdentifier_js_1.default)("__node_key")}`;
189
195
  }
@@ -195,9 +201,95 @@ function temporalDistancesSelect(prepared, direction, temporal, distanceType, ed
195
201
  const costStates = (0, buildGraphTemporalCostStateSql_js_1.default)(prepared, startsSelect, direction, temporal, distanceType, edgeWeight);
196
202
  return `${costStates.withClause}
197
203
  SELECT ${q("start")}, ${q("node")},
198
- MIN(${q("distance")}) AS ${q("distance")}
204
+ MIN(${q("distance")}) AS ${q("total")}
199
205
  FROM ${costStates.costRelation}
200
206
  GROUP BY ${q("start")}, ${q("node")}, ${q("__start_key")},
201
207
  ${q("__node_key")}
202
- ORDER BY ${q("__start_key")}, ${q("distance")}, ${q("__node_key")}`;
208
+ ORDER BY ${q("__start_key")}, ${q("total")}, ${q("__node_key")}`;
209
+ }
210
+ function elapsedDistancesSelect(prepared, direction, temporal, distanceType, edgeWeight, minimize) {
211
+ const q = quoteIdentifier_js_1.default;
212
+ const relations = prepared.relationNames([
213
+ "graph_starts",
214
+ "graph_temporal_settings",
215
+ "graph_event_rows",
216
+ "graph_edges",
217
+ "graph_elapsed_states",
218
+ "graph_elapsed_results",
219
+ ]);
220
+ const starts = relations.graph_starts;
221
+ const settings = relations.graph_temporal_settings;
222
+ const events = relations.graph_event_rows;
223
+ const edges = relations.graph_edges;
224
+ const states = relations.graph_elapsed_states;
225
+ const results = relations.graph_elapsed_results;
226
+ const ref = (alias, column) => `${q(alias)}.${q(column)}`;
227
+ const anchor = temporal.journeyAnchor("edges", direction);
228
+ const reachedAnchor = ref("reached", "__anchor");
229
+ const candidateDistance = `CAST(${ref("reached", "distance")} + ${ref("edges", "__weight")} AS ${distanceType})`;
230
+ const order = minimize === "elapsedTime"
231
+ ? `${q("__elapsed")}, ${q("distance")}`
232
+ : `${q("distance")}, ${q("__elapsed")}`;
233
+ // A physical event and the first departure (last arrival for incoming
234
+ // traversal) fix elapsed time. Keep the cheapest cost for each such state;
235
+ // merging different anchors would lose later-departing, faster journeys.
236
+ // The state space is finite, and strict improvements terminate zero cycles.
237
+ return `WITH RECURSIVE ${settings} AS MATERIALIZED (
238
+ SELECT CAST(? AS HUGEINT) AS ${q("__gap")}
239
+ ), ${events} AS MATERIALIZED (
240
+ ${prepared.edges(direction, [
241
+ `${edgeWeight} AS ${q("__weight")}`,
242
+ ...temporal.eventSelections("edges"),
243
+ ])}
244
+ ), ${edges} AS MATERIALIZED (
245
+ SELECT * FROM ${events} AS ${q("events")}
246
+ WHERE ${temporal.eventValidity("events")}
247
+ ), ${starts} AS MATERIALIZED (
248
+ SELECT ${q("start")}, ${prepared.key(q("start"))} AS ${q("__key")}
249
+ FROM (VALUES ${prepared.startValues}) AS ${q("start_values")}(${q("start")})
250
+ ), ${states}(
251
+ ${q("start")}, ${q("node")}, ${q("__start_key")}, ${q("__node_key")},
252
+ ${q("__event_id")}, ${q("__event_start")}, ${q("__event_end")},
253
+ ${q("__anchor")}, ${q("distance")}
254
+ ) USING KEY(${q("__start_key")}, ${q("__event_id")}, ${q("__anchor")}) AS (
255
+ SELECT ${ref("starts", "start")}, ${ref("edges", "__to")},
256
+ ${ref("starts", "__key")}, ${ref("edges", "__to_key")},
257
+ ${ref("edges", "__event_id")}, ${ref("edges", "__event_start")},
258
+ ${ref("edges", "__event_end")}, ${anchor}, ${ref("edges", "__weight")}
259
+ FROM ${starts} AS ${q("starts")}
260
+ INNER JOIN ${edges} AS ${q("edges")}
261
+ ON ${ref("starts", "__key")} = ${ref("edges", "__from_key")}
262
+ UNION
263
+ SELECT ${ref("reached", "start")}, ${ref("edges", "__to")},
264
+ ${ref("reached", "__start_key")}, ${ref("edges", "__to_key")},
265
+ ${ref("edges", "__event_id")}, ${ref("edges", "__event_start")},
266
+ ${ref("edges", "__event_end")}, ${reachedAnchor},
267
+ MIN(${candidateDistance}) AS ${q("distance")}
268
+ FROM ${states} AS ${q("reached")}
269
+ INNER JOIN ${edges} AS ${q("edges")}
270
+ ON ${ref("reached", "__node_key")} = ${ref("edges", "__from_key")}
271
+ CROSS JOIN ${settings} AS ${q("settings")}
272
+ LEFT JOIN recurring.${states} AS ${q("best")}
273
+ ON ${ref("reached", "__start_key")} = ${ref("best", "__start_key")}
274
+ AND ${ref("edges", "__event_id")} = ${ref("best", "__event_id")}
275
+ AND ${reachedAnchor} = ${ref("best", "__anchor")}
276
+ WHERE ${temporal.transition("reached", "edges", direction, ref("settings", "__gap"))}
277
+ GROUP BY ${ref("reached", "start")}, ${ref("edges", "__to")},
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")}
283
+ ), ${results} AS (
284
+ SELECT *, ${temporal.journeyElapsed("states", ref("states", "__anchor"), direction)} AS ${q("__elapsed")}
285
+ FROM ${states} AS ${q("states")}
286
+ )
287
+ SELECT ${q("start")}, ${q("node")}, ${q("distance")} AS ${q("total")},
288
+ ${temporal.elapsedMilliseconds(q("__elapsed"))} AS ${q("elapsedTimeMs")}
289
+ FROM ${results}
290
+ QUALIFY row_number() OVER (
291
+ PARTITION BY ${q("__start_key")}, ${q("__node_key")}
292
+ ORDER BY ${order}, ${q("__event_id")}, ${q("__anchor")}
293
+ ) = 1
294
+ ORDER BY ${q("__start_key")}, ${order}, ${q("__node_key")}`;
203
295
  }
@@ -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":"AAAA,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,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,CAuHb"}
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"}
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = findCycles;
40
+ const prepareGraphMetricOptions_js_1 = __importDefault(require("../helpers/prepareGraphMetricOptions.js"));
40
41
  const getGraphEdgeIdColumn_js_1 = __importDefault(require("../helpers/getGraphEdgeIdColumn.js"));
41
42
  const getGraphWeightColumn_js_1 = __importDefault(require("../helpers/getGraphWeightColumn.js"));
42
43
  const graphRouteResultSchema_js_1 = __importDefault(require("../helpers/graphRouteResultSchema.js"));
@@ -74,6 +75,7 @@ function findCycles(simpleTable, sourceColumn, targetColumn, edgeId, startNodes,
74
75
  typeof options.outputTable !== "boolean") {
75
76
  throw new TypeError("findCycles() options.outputTable must be a string or boolean.");
76
77
  }
78
+ const metric = (0, prepareGraphMetricOptions_js_1.default)(options, "findCycles()", false);
77
79
  const direction = options.direction ?? "outgoing";
78
80
  const temporalOptions = (0, prepareGraphTemporalSql_js_1.prepareGraphTemporalOptions)(options, direction, "findCycles()");
79
81
  options = structuredClone(options);
@@ -92,7 +94,8 @@ function findCycles(simpleTable, sourceColumn, targetColumn, edgeId, startNodes,
92
94
  ? undefined
93
95
  : (input) => (0, validateGraphTemporalEvents_js_1.default)(input, temporalOptions, "findCycles()", parameters),
94
96
  values: (schema) => {
95
- validateFindCyclesInputs(schema, sourceColumn, targetColumn, edgeId, preparedStarts, options.weight);
97
+ const validated = validateFindCyclesInputs(schema, sourceColumn, targetColumn, edgeId, preparedStarts, options.weight);
98
+ (0, graphRouteResultSchema_js_1.default)(schema, validated.distanceType, "findCycles()", metric.elapsedTime);
96
99
  const temporal = temporalOptions === undefined
97
100
  ? undefined
98
101
  : (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "findCycles()");
@@ -100,7 +103,7 @@ function findCycles(simpleTable, sourceColumn, targetColumn, edgeId, startNodes,
100
103
  ? preparedStarts.values
101
104
  : [temporal.gapParameter, ...preparedStarts.values];
102
105
  },
103
- buildSelect: (input, schema) => findCyclesSelect(input, schema, sourceColumn, targetColumn, edgeId, preparedStarts, direction, options.weight, temporalOptions),
106
+ buildSelect: (input, schema) => findCyclesSelect(input, schema, sourceColumn, targetColumn, edgeId, preparedStarts, direction, options.weight, temporalOptions, metric.elapsedTime),
104
107
  outputSchema: (schema) => {
105
108
  const validated = validateFindCyclesInputs(schema, sourceColumn, targetColumn, edgeId, preparedStarts, options.weight);
106
109
  if (temporalOptions !== undefined) {
@@ -108,7 +111,7 @@ function findCycles(simpleTable, sourceColumn, targetColumn, edgeId, startNodes,
108
111
  }
109
112
  return {
110
113
  start: validated.nodeIdType,
111
- ...(0, graphRouteResultSchema_js_1.default)(schema, validated.distanceType, "findCycles()"),
114
+ ...(0, graphRouteResultSchema_js_1.default)(schema, validated.distanceType, "findCycles()", metric.elapsedTime),
112
115
  };
113
116
  },
114
117
  });
@@ -126,7 +129,7 @@ function validateFindCyclesInputs(schema, source, target, edgeId, starts, weight
126
129
  nodeIdType: endpoints.idType,
127
130
  };
128
131
  }
129
- function findCyclesSelect(input, schema, source, target, edgeId, starts, direction, weight, temporalOptions) {
132
+ function findCyclesSelect(input, schema, source, target, edgeId, starts, direction, weight, temporalOptions, elapsedTime) {
130
133
  const prepared = (0, prepareGraphTraversal_js_1.default)(input, schema, source, target, starts, "findCycles()", "startNodes");
131
134
  const edgeIdColumn = (0, getGraphEdgeIdColumn_js_1.default)(schema, edgeId, "findCycles()");
132
135
  const weightColumn = weight === undefined
@@ -142,10 +145,10 @@ function findCyclesSelect(input, schema, source, target, edgeId, starts, directi
142
145
  const edgeWeight = weightColumn === undefined
143
146
  ? `CAST(1 AS ${distanceType})`
144
147
  : `CAST(${q("edges")}.${q(weightColumn.column)} AS ${distanceType})`;
145
- const stepType = `STRUCT(${q("edgeId")} ${edgeIdColumn.idType}, ${q("source")} ${prepared.endpoints.idType}, ${q("target")} ${prepared.endpoints.idType}, ${q("weight")} ${distanceType}, ${q("distance")} ${distanceType})`;
148
+ 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` : ""})`;
146
149
  if (temporalOptions !== undefined) {
147
150
  const temporal = (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "findCycles()");
148
- return temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn);
151
+ return temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn, elapsedTime);
149
152
  }
150
153
  const relations = prepared.relationNames([
151
154
  "graph_start_values",
@@ -249,7 +252,7 @@ function findCyclesSelect(input, schema, source, target, edgeId, starts, directi
249
252
  )
250
253
  ${(0, graphRouteResultSelect_js_1.default)(rankedRelation, input, edgeIdColumn, true)}`;
251
254
  }
252
- function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn) {
255
+ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, edgeKey, edgeWeight, distanceType, stepType, input, edgeIdColumn, elapsedTime) {
253
256
  const q = quoteIdentifier_js_1.default;
254
257
  const relations = prepared.relationNames([
255
258
  "graph_start_values",
@@ -279,12 +282,16 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
279
282
  const walkDistance = `${q("walks")}.${q("distance")}`;
280
283
  const candidateDistance = `CAST(${walkDistance} + ${edgeCost} AS ${distanceType})`;
281
284
  const gap = `${q("settings")}.${q("__gap")}`;
282
- const step = (distance) => `struct_pack(
285
+ const firstAnchor = temporal.journeyAnchor("edges", direction);
286
+ const anchor = `${q("walks")}.${q("__journey_anchor")}`;
287
+ const step = (distance, journeyAnchor) => `struct_pack(
283
288
  ${q("edgeId")} := ${edgeIdentity},
284
289
  ${q("source")} := ${edgeFrom},
285
290
  ${q("target")} := ${edgeTo},
286
291
  ${q("weight")} := ${edgeCost},
287
- ${q("distance")} := ${distance}
292
+ ${q("distance")} := ${distance}${elapsedTime
293
+ ? `, ${q("elapsedTimeMs")} := ${temporal.elapsedMilliseconds(temporal.journeyElapsed("edges", journeyAnchor, direction))}`
294
+ : ""}
288
295
  )`;
289
296
  return `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (
290
297
  SELECT CAST(? AS HUGEINT) AS ${q("__gap")}
@@ -310,7 +317,7 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
310
317
  ${q("__node_key")}, ${q("__visited")}, ${q("__event_ids")},
311
318
  ${q("__edge_keys")}, ${q("steps")}, ${q("distance")},
312
319
  ${q("closed")}, ${q("__event_id")}, ${q("__event_start")},
313
- ${q("__event_end")}
320
+ ${q("__event_end")}${elapsedTime ? `, ${q("__journey_anchor")}` : ""}
314
321
  ) AS (
315
322
  SELECT ${q("starts")}.${q("start")},
316
323
  ${q("starts")}.${q("__start_key")}, ${edgeTo}, ${edgeToKey},
@@ -319,11 +326,11 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
319
326
  ELSE [${edgeFromKey}, ${edgeToKey}]
320
327
  END,
321
328
  [${q("edges")}.${q("__event_id")}], [${edgeIdentityKey}],
322
- [${step(edgeCost)}]::${stepType}[], ${edgeCost},
329
+ [${step(edgeCost, firstAnchor)}]::${stepType}[], ${edgeCost},
323
330
  ${edgeFromKey} = ${edgeToKey},
324
331
  ${q("edges")}.${q("__event_id")},
325
332
  ${q("edges")}.${q("__event_start")},
326
- ${q("edges")}.${q("__event_end")}
333
+ ${q("edges")}.${q("__event_end")}${elapsedTime ? `, ${firstAnchor}` : ""}
327
334
  FROM ${edgesRelation} AS ${q("edges")}
328
335
  INNER JOIN ${startsRelation} AS ${q("starts")}
329
336
  ON ${q("starts")}.${q("__start_key")} = ${edgeFromKey}
@@ -334,12 +341,12 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
334
341
  list_append(${q("walks")}.${q("__event_ids")},
335
342
  ${q("edges")}.${q("__event_id")}),
336
343
  list_append(${q("walks")}.${q("__edge_keys")}, ${edgeIdentityKey}),
337
- list_append(${q("walks")}.${q("steps")}, ${step(candidateDistance)}),
344
+ list_append(${q("walks")}.${q("steps")}, ${step(candidateDistance, anchor)}),
338
345
  ${candidateDistance},
339
346
  ${edgeToKey} = ${q("walks")}.${q("__start_key")},
340
347
  ${q("edges")}.${q("__event_id")},
341
348
  ${q("edges")}.${q("__event_start")},
342
- ${q("edges")}.${q("__event_end")}
349
+ ${q("edges")}.${q("__event_end")}${elapsedTime ? `, ${anchor}` : ""}
343
350
  FROM ${walksRelation} AS ${q("walks")}
344
351
  INNER JOIN ${edgesRelation} AS ${q("edges")}
345
352
  ON ${q("walks")}.${q("__node_key")} = ${edgeFromKey}
@@ -365,5 +372,5 @@ function temporalFindCyclesSelect(prepared, direction, temporal, typedEdgeId, ed
365
372
  AS BIGINT) AS ${q("pathId")}, ${q("steps")}
366
373
  FROM ${completeRelation}
367
374
  )
368
- ${(0, graphRouteResultSelect_js_1.default)(rankedRelation, input, edgeIdColumn, true)}`;
375
+ ${(0, graphRouteResultSelect_js_1.default)(rankedRelation, input, edgeIdColumn, true, elapsedTime)}`;
369
376
  }
@@ -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":"AAAA,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,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,CA+Gb"}
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"}
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.default = paths;
40
+ const prepareGraphMetricOptions_js_1 = __importDefault(require("../helpers/prepareGraphMetricOptions.js"));
40
41
  const prepareGraphRouteSql_js_1 = require("../helpers/prepareGraphRouteSql.js");
41
42
  const graphRouteResultSchema_js_1 = __importDefault(require("../helpers/graphRouteResultSchema.js"));
42
43
  const graphRouteResultSelect_js_1 = __importDefault(require("../helpers/graphRouteResultSelect.js"));
@@ -69,6 +70,7 @@ function paths(simpleTable, sourceColumn, targetColumn, edgeId, start, end, opti
69
70
  typeof options.outputTable !== "boolean") {
70
71
  throw new TypeError("paths() options.outputTable must be a string or boolean.");
71
72
  }
73
+ const metric = (0, prepareGraphMetricOptions_js_1.default)(options, "paths()", false);
72
74
  const endpoints = (0, prepareGraphRouteSql_js_1.prepareGraphRouteEndpoints)(start, end, "paths()");
73
75
  const direction = options.direction ?? "outgoing";
74
76
  const temporalOptions = (0, prepareGraphTemporalSql_js_1.prepareGraphTemporalOptions)(options, direction, "paths()");
@@ -89,7 +91,8 @@ function paths(simpleTable, sourceColumn, targetColumn, edgeId, start, end, opti
89
91
  ? undefined
90
92
  : (input) => (0, validateGraphTemporalEvents_js_1.default)(input, temporalOptions, "paths()", parameters),
91
93
  values: (schema) => {
92
- (0, prepareGraphRouteSql_js_1.validateGraphRouteInputs)(schema, sourceColumn, targetColumn, edgeId, endpoints, options.weight, "paths()");
94
+ const validated = (0, prepareGraphRouteSql_js_1.validateGraphRouteInputs)(schema, sourceColumn, targetColumn, edgeId, endpoints, options.weight, "paths()");
95
+ (0, graphRouteResultSchema_js_1.default)(schema, validated.distanceType, "paths()", metric.elapsedTime);
93
96
  const temporal = temporalOptions === undefined
94
97
  ? undefined
95
98
  : (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "paths()");
@@ -97,22 +100,22 @@ function paths(simpleTable, sourceColumn, targetColumn, edgeId, start, end, opti
97
100
  ? endpoints.values.values
98
101
  : [temporal.gapParameter, ...endpoints.values.values];
99
102
  },
100
- buildSelect: (input, schema) => pathsSelect(input, schema, sourceColumn, targetColumn, edgeId, endpoints, direction, options.weight, temporalOptions),
103
+ buildSelect: (input, schema) => pathsSelect(input, schema, sourceColumn, targetColumn, edgeId, endpoints, direction, options.weight, temporalOptions, metric.elapsedTime),
101
104
  outputSchema: (schema) => {
102
105
  const validated = (0, prepareGraphRouteSql_js_1.validateGraphRouteInputs)(schema, sourceColumn, targetColumn, edgeId, endpoints, options.weight, "paths()");
103
106
  if (temporalOptions !== undefined) {
104
107
  (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "paths()");
105
108
  }
106
- return (0, graphRouteResultSchema_js_1.default)(schema, validated.distanceType, "paths()");
109
+ return (0, graphRouteResultSchema_js_1.default)(schema, validated.distanceType, "paths()", metric.elapsedTime);
107
110
  },
108
111
  });
109
112
  }
110
- function pathsSelect(input, schema, source, target, edgeId, routeEndpoints, direction, weight, temporalOptions) {
113
+ function pathsSelect(input, schema, source, target, edgeId, routeEndpoints, direction, weight, temporalOptions, elapsedTime) {
111
114
  const route = (0, prepareGraphRouteSql_js_1.prepareGraphRouteSql)(input, schema, source, target, edgeId, routeEndpoints, weight, "paths()");
112
115
  const prepared = route.traversal;
113
116
  if (temporalOptions !== undefined) {
114
117
  const temporal = (0, prepareGraphTemporalSql_js_1.default)(schema, temporalOptions, "paths()");
115
- return temporalPathsSelect(route, direction, temporal);
118
+ return temporalPathsSelect(route, direction, temporal, elapsedTime);
116
119
  }
117
120
  const distanceType = route.distanceType;
118
121
  const q = quoteIdentifier_js_1.default;
@@ -205,7 +208,7 @@ function pathsSelect(input, schema, source, target, edgeId, routeEndpoints, dire
205
208
  )
206
209
  ${(0, graphRouteResultSelect_js_1.default)(rankedRelation, route.input, route.edgeIdColumn)}`;
207
210
  }
208
- function temporalPathsSelect(route, direction, temporal) {
211
+ function temporalPathsSelect(route, direction, temporal, elapsedTime) {
209
212
  const prepared = route.traversal;
210
213
  const distanceType = route.distanceType;
211
214
  const q = quoteIdentifier_js_1.default;
@@ -236,12 +239,16 @@ function temporalPathsSelect(route, direction, temporal) {
236
239
  const edgeKey = `${q("edges")}.${q("__edge_key")}`;
237
240
  const candidateDistance = `CAST(${q("routes")}.${q("distance")} + ${edgeCost} AS ${distanceType})`;
238
241
  const gap = `${q("settings")}.${q("__gap")}`;
239
- const step = (distance) => `struct_pack(
242
+ const firstAnchor = temporal.journeyAnchor("edges", direction);
243
+ const anchor = `${q("routes")}.${q("__journey_anchor")}`;
244
+ const step = (distance, journeyAnchor) => `struct_pack(
240
245
  ${q("edgeId")} := ${q("edges")}.${q("__edge_id")},
241
246
  ${q("source")} := ${q("edges")}.${q("__from")},
242
247
  ${q("target")} := ${edgeTo},
243
248
  ${q("weight")} := ${edgeCost},
244
- ${q("distance")} := ${distance}
249
+ ${q("distance")} := ${distance}${elapsedTime
250
+ ? `, ${q("elapsedTimeMs")} := ${temporal.elapsedMilliseconds(temporal.journeyElapsed("edges", journeyAnchor, direction))}`
251
+ : ""}
245
252
  )`;
246
253
  return `WITH RECURSIVE ${settingsRelation} AS MATERIALIZED (
247
254
  SELECT CAST(? AS HUGEINT) AS ${q("__gap")}
@@ -280,14 +287,14 @@ function temporalPathsSelect(route, direction, temporal) {
280
287
  ), ${routesRelation}(
281
288
  ${q("node")}, ${q("__node_key")}, ${q("__visited")},
282
289
  ${q("__edge_keys")}, ${q("steps")}, ${q("distance")},
283
- ${q("__event_id")}, ${q("__event_start")}, ${q("__event_end")}
290
+ ${q("__event_id")}, ${q("__event_start")}, ${q("__event_end")}${elapsedTime ? `, ${q("__journey_anchor")}` : ""}
284
291
  ) AS (
285
292
  SELECT ${edgeTo}, ${edgeToKey},
286
293
  [${q("__start_key")}, ${edgeToKey}], [${edgeKey}],
287
- [${step(edgeCost)}], ${edgeCost},
294
+ [${step(edgeCost, firstAnchor)}], ${edgeCost},
288
295
  ${q("edges")}.${q("__event_id")},
289
296
  ${q("edges")}.${q("__event_start")},
290
- ${q("edges")}.${q("__event_end")}
297
+ ${q("edges")}.${q("__event_end")}${elapsedTime ? `, ${firstAnchor}` : ""}
291
298
  FROM ${endpointRelation}
292
299
  INNER JOIN ${edgesRelation} AS ${q("edges")}
293
300
  ON ${q("__start_key")} = ${edgeFromKey}
@@ -298,10 +305,10 @@ function temporalPathsSelect(route, direction, temporal) {
298
305
  SELECT ${edgeTo}, ${edgeToKey},
299
306
  list_append(${q("routes")}.${q("__visited")}, ${edgeToKey}),
300
307
  list_append(${q("routes")}.${q("__edge_keys")}, ${edgeKey}),
301
- list_append(${q("routes")}.${q("steps")}, ${step(candidateDistance)}),
308
+ list_append(${q("routes")}.${q("steps")}, ${step(candidateDistance, anchor)}),
302
309
  ${candidateDistance}, ${q("edges")}.${q("__event_id")},
303
310
  ${q("edges")}.${q("__event_start")},
304
- ${q("edges")}.${q("__event_end")}
311
+ ${q("edges")}.${q("__event_end")}${elapsedTime ? `, ${anchor}` : ""}
305
312
  FROM ${routesRelation} AS ${q("routes")}
306
313
  INNER JOIN ${edgesRelation} AS ${q("edges")}
307
314
  ON ${q("routes")}.${q("__node_key")} = ${edgeFromKey}
@@ -322,5 +329,5 @@ function temporalPathsSelect(route, direction, temporal) {
322
329
  AS ${q("pathId")}, ${q("steps")}
323
330
  FROM ${completeRelation}
324
331
  )
325
- ${(0, graphRouteResultSelect_js_1.default)(rankedRelation, route.input, route.edgeIdColumn)}`;
332
+ ${(0, graphRouteResultSelect_js_1.default)(rankedRelation, route.input, route.edgeIdColumn, false, elapsedTime)}`;
326
333
  }
@@ -6,6 +6,8 @@ type ShortestPathOptions = GraphTemporalOptions & {
6
6
  direction?: GraphDirection;
7
7
  outputTable?: string | boolean;
8
8
  weight?: string;
9
+ elapsedTime?: boolean;
10
+ minimize?: "weight" | "elapsedTime";
9
11
  };
10
12
  export default function shortestPath(simpleTable: SimpleTable, sourceColumn: string, targetColumn: string, edgeId: string, start: GraphId, end: GraphId, options?: ShortestPathOptions): SimpleTable;
11
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;AAGvD,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;CACjB,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,CAmHb"}
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;CACrC,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,CAsHb"}