relationalai 0.13.5__py3-none-any.whl → 1.0.0a2__py3-none-any.whl

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 (856) hide show
  1. relationalai/__init__.py +1 -256
  2. relationalai/config/__init__.py +56 -0
  3. relationalai/config/config.py +289 -0
  4. relationalai/config/config_fields.py +86 -0
  5. relationalai/config/connections/__init__.py +46 -0
  6. relationalai/config/connections/base.py +23 -0
  7. relationalai/config/connections/duckdb.py +29 -0
  8. relationalai/config/connections/snowflake.py +243 -0
  9. relationalai/config/external/__init__.py +17 -0
  10. relationalai/config/external/dbt_converter.py +101 -0
  11. relationalai/config/external/dbt_models.py +93 -0
  12. relationalai/config/external/snowflake_converter.py +41 -0
  13. relationalai/config/external/snowflake_models.py +85 -0
  14. relationalai/config/external/utils.py +19 -0
  15. relationalai/config/shims.py +1 -0
  16. relationalai/semantics/__init__.py +146 -22
  17. relationalai/semantics/backends/lqp/annotations.py +11 -0
  18. relationalai/semantics/backends/sql/sql_compiler.py +327 -0
  19. relationalai/semantics/frontend/base.py +1719 -0
  20. relationalai/semantics/frontend/core.py +179 -0
  21. relationalai/semantics/frontend/front_compiler.py +1316 -0
  22. relationalai/semantics/frontend/pprint.py +408 -0
  23. relationalai/semantics/metamodel/__init__.py +6 -40
  24. relationalai/semantics/metamodel/builtins.py +206 -772
  25. relationalai/semantics/metamodel/metamodel.py +465 -0
  26. relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
  27. relationalai/semantics/metamodel/pprint.py +414 -0
  28. relationalai/semantics/metamodel/rewriter.py +266 -0
  29. relationalai/semantics/metamodel/typer.py +1213 -0
  30. relationalai/semantics/std/__init__.py +60 -40
  31. relationalai/semantics/std/aggregates.py +148 -0
  32. relationalai/semantics/std/common.py +44 -0
  33. relationalai/semantics/std/constraints.py +37 -43
  34. relationalai/semantics/std/datetime.py +249 -135
  35. relationalai/semantics/std/decimals.py +45 -52
  36. relationalai/semantics/std/floats.py +13 -5
  37. relationalai/semantics/std/integers.py +26 -11
  38. relationalai/semantics/std/math.py +183 -112
  39. relationalai/semantics/std/numbers.py +86 -0
  40. relationalai/semantics/std/re.py +80 -62
  41. relationalai/semantics/std/strings.py +101 -46
  42. relationalai/shims/executor.py +179 -0
  43. relationalai/shims/helpers.py +126 -0
  44. relationalai/shims/hoister.py +221 -0
  45. relationalai/shims/mm2v0.py +1394 -0
  46. relationalai/tools/cli/__init__.py +6 -0
  47. relationalai/tools/cli/cli.py +90 -0
  48. relationalai/tools/cli/components/__init__.py +5 -0
  49. relationalai/tools/cli/components/progress_reader.py +1524 -0
  50. relationalai/tools/cli/components/utils.py +58 -0
  51. relationalai/tools/cli/config_template.py +45 -0
  52. relationalai/tools/cli/dev.py +19 -0
  53. relationalai/tools/debugger.py +289 -183
  54. relationalai/tools/typer_debugger.py +93 -0
  55. relationalai/util/dataclasses.py +43 -0
  56. relationalai/util/docutils.py +40 -0
  57. relationalai/util/error.py +199 -0
  58. relationalai/util/format.py +48 -109
  59. relationalai/util/naming.py +145 -0
  60. relationalai/util/python.py +35 -0
  61. relationalai/util/runtime.py +156 -0
  62. relationalai/util/schema.py +197 -0
  63. relationalai/util/source.py +185 -0
  64. relationalai/util/structures.py +163 -0
  65. relationalai/util/tracing.py +261 -0
  66. relationalai-1.0.0a2.dist-info/METADATA +44 -0
  67. relationalai-1.0.0a2.dist-info/RECORD +489 -0
  68. relationalai-1.0.0a2.dist-info/WHEEL +5 -0
  69. relationalai-1.0.0a2.dist-info/entry_points.txt +3 -0
  70. relationalai-1.0.0a2.dist-info/top_level.txt +2 -0
  71. v0/relationalai/__init__.py +216 -0
  72. v0/relationalai/clients/__init__.py +5 -0
  73. v0/relationalai/clients/azure.py +477 -0
  74. v0/relationalai/clients/client.py +912 -0
  75. v0/relationalai/clients/config.py +673 -0
  76. v0/relationalai/clients/direct_access_client.py +118 -0
  77. v0/relationalai/clients/hash_util.py +31 -0
  78. v0/relationalai/clients/local.py +571 -0
  79. v0/relationalai/clients/profile_polling.py +73 -0
  80. v0/relationalai/clients/result_helpers.py +420 -0
  81. v0/relationalai/clients/snowflake.py +3869 -0
  82. v0/relationalai/clients/types.py +113 -0
  83. v0/relationalai/clients/use_index_poller.py +980 -0
  84. v0/relationalai/clients/util.py +356 -0
  85. v0/relationalai/debugging.py +389 -0
  86. v0/relationalai/dsl.py +1749 -0
  87. v0/relationalai/early_access/builder/__init__.py +30 -0
  88. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  89. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  90. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  91. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  93. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  94. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  95. v0/relationalai/early_access/devtools/__init__.py +12 -0
  96. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  97. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  98. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  99. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  100. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  101. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  102. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  103. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  104. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  105. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  106. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  107. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  108. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  109. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  110. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  111. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  112. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  113. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  114. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  115. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  116. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  117. v0/relationalai/early_access/dsl/core/context.py +13 -0
  118. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  119. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  120. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  121. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  122. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  123. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  124. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  125. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  126. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  127. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  128. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  129. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  130. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  131. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  132. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  133. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  135. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  136. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  137. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  138. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  139. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  140. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  141. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  142. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  143. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  144. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  145. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  146. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  147. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  148. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  149. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  150. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  151. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  152. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  153. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  154. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  155. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  156. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  157. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  158. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  159. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  160. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  161. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  162. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  163. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  164. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  165. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  166. v0/relationalai/early_access/dsl/relations.py +170 -0
  167. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  168. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  169. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  170. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  171. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  172. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  173. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  174. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  175. v0/relationalai/early_access/dsl/serialization.py +79 -0
  176. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  177. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  178. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  180. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  181. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  182. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  183. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  184. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  185. v0/relationalai/early_access/dsl/types/values.py +17 -0
  186. v0/relationalai/early_access/dsl/utils.py +102 -0
  187. v0/relationalai/early_access/graphs/__init__.py +13 -0
  188. v0/relationalai/early_access/lqp/__init__.py +12 -0
  189. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  190. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  191. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  197. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  198. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  199. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  200. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  202. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  203. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  204. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  205. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  206. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  207. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  208. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  209. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  210. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  211. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  214. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  215. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  216. v0/relationalai/early_access/solvers/__init__.py +19 -0
  217. v0/relationalai/early_access/sql/__init__.py +11 -0
  218. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  219. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  220. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  221. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  222. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  223. v0/relationalai/environments/__init__.py +35 -0
  224. v0/relationalai/environments/base.py +381 -0
  225. v0/relationalai/environments/colab.py +14 -0
  226. v0/relationalai/environments/generic.py +71 -0
  227. v0/relationalai/environments/ipython.py +68 -0
  228. v0/relationalai/environments/jupyter.py +9 -0
  229. v0/relationalai/environments/snowbook.py +169 -0
  230. v0/relationalai/errors.py +2478 -0
  231. v0/relationalai/experimental/SF.py +38 -0
  232. v0/relationalai/experimental/inspect.py +47 -0
  233. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  234. v0/relationalai/experimental/pathfinder/api.py +160 -0
  235. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  236. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  237. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  238. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  239. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  240. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  241. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  242. v0/relationalai/experimental/pathfinder/options.py +265 -0
  243. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  244. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  245. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  246. v0/relationalai/experimental/paths/api.py +143 -0
  247. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  248. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  249. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  250. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  251. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  252. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  253. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  254. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  255. v0/relationalai/experimental/paths/graph.py +185 -0
  256. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  257. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  258. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  259. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  260. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  261. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  263. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  264. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  265. v0/relationalai/experimental/paths/product_graph.py +93 -0
  266. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  267. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  268. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  272. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  273. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  276. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  277. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  279. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  280. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  283. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  284. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  285. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  286. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  287. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  288. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  289. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  290. v0/relationalai/experimental/solvers.py +1087 -0
  291. v0/relationalai/loaders/csv.py +195 -0
  292. v0/relationalai/loaders/loader.py +177 -0
  293. v0/relationalai/loaders/types.py +23 -0
  294. v0/relationalai/rel_emitter.py +373 -0
  295. v0/relationalai/rel_utils.py +185 -0
  296. v0/relationalai/semantics/__init__.py +29 -0
  297. v0/relationalai/semantics/devtools/benchmark_lqp.py +536 -0
  298. v0/relationalai/semantics/devtools/compilation_manager.py +294 -0
  299. v0/relationalai/semantics/devtools/extract_lqp.py +110 -0
  300. v0/relationalai/semantics/internal/internal.py +3785 -0
  301. v0/relationalai/semantics/internal/snowflake.py +325 -0
  302. v0/relationalai/semantics/lqp/builtins.py +16 -0
  303. v0/relationalai/semantics/lqp/compiler.py +22 -0
  304. v0/relationalai/semantics/lqp/constructors.py +68 -0
  305. v0/relationalai/semantics/lqp/executor.py +474 -0
  306. v0/relationalai/semantics/lqp/intrinsics.py +24 -0
  307. v0/relationalai/semantics/lqp/ir.py +124 -0
  308. v0/relationalai/semantics/lqp/model2lqp.py +877 -0
  309. v0/relationalai/semantics/lqp/passes.py +680 -0
  310. v0/relationalai/semantics/lqp/primitives.py +252 -0
  311. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  312. v0/relationalai/semantics/lqp/rewrite/__init__.py +18 -0
  313. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  314. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  315. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  316. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +490 -0
  317. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  318. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  319. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  320. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  321. v0/relationalai/semantics/lqp/types.py +101 -0
  322. v0/relationalai/semantics/lqp/utils.py +160 -0
  323. v0/relationalai/semantics/lqp/validators.py +57 -0
  324. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  325. v0/relationalai/semantics/metamodel/builtins.py +776 -0
  326. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  327. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  328. v0/relationalai/semantics/metamodel/executor.py +61 -0
  329. v0/relationalai/semantics/metamodel/factory.py +287 -0
  330. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  331. v0/relationalai/semantics/metamodel/ir.py +923 -0
  332. v0/relationalai/semantics/metamodel/rewrite/__init__.py +7 -0
  333. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  334. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  335. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  336. v0/relationalai/semantics/metamodel/rewrite/flatten.py +554 -0
  337. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  338. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  339. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  340. v0/relationalai/semantics/metamodel/util.py +505 -0
  341. v0/relationalai/semantics/metamodel/visitor.py +944 -0
  342. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  343. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  344. v0/relationalai/semantics/reasoners/graph/core.py +9019 -0
  345. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  346. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  347. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  348. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  349. v0/relationalai/semantics/rel/builtins.py +40 -0
  350. v0/relationalai/semantics/rel/compiler.py +989 -0
  351. v0/relationalai/semantics/rel/executor.py +359 -0
  352. v0/relationalai/semantics/rel/rel.py +482 -0
  353. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  354. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  355. v0/relationalai/semantics/sql/compiler.py +2503 -0
  356. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  357. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  358. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  359. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  360. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  361. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  362. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  363. v0/relationalai/semantics/sql/sql.py +504 -0
  364. v0/relationalai/semantics/std/__init__.py +54 -0
  365. v0/relationalai/semantics/std/constraints.py +43 -0
  366. v0/relationalai/semantics/std/datetime.py +363 -0
  367. v0/relationalai/semantics/std/decimals.py +62 -0
  368. v0/relationalai/semantics/std/floats.py +7 -0
  369. v0/relationalai/semantics/std/integers.py +22 -0
  370. v0/relationalai/semantics/std/math.py +141 -0
  371. v0/relationalai/semantics/std/pragmas.py +11 -0
  372. v0/relationalai/semantics/std/re.py +83 -0
  373. v0/relationalai/semantics/std/std.py +14 -0
  374. v0/relationalai/semantics/std/strings.py +63 -0
  375. v0/relationalai/semantics/tests/__init__.py +0 -0
  376. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  377. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  378. v0/relationalai/semantics/tests/utils.py +46 -0
  379. v0/relationalai/std/__init__.py +70 -0
  380. v0/relationalai/tools/__init__.py +0 -0
  381. v0/relationalai/tools/cli.py +1940 -0
  382. v0/relationalai/tools/cli_controls.py +1826 -0
  383. v0/relationalai/tools/cli_helpers.py +390 -0
  384. v0/relationalai/tools/debugger.py +183 -0
  385. v0/relationalai/tools/debugger_client.py +109 -0
  386. v0/relationalai/tools/debugger_server.py +302 -0
  387. v0/relationalai/tools/dev.py +685 -0
  388. v0/relationalai/tools/qb_debugger.py +425 -0
  389. v0/relationalai/util/clean_up_databases.py +95 -0
  390. v0/relationalai/util/format.py +123 -0
  391. v0/relationalai/util/list_databases.py +9 -0
  392. v0/relationalai/util/otel_configuration.py +25 -0
  393. v0/relationalai/util/otel_handler.py +484 -0
  394. v0/relationalai/util/snowflake_handler.py +88 -0
  395. v0/relationalai/util/span_format_test.py +43 -0
  396. v0/relationalai/util/span_tracker.py +207 -0
  397. v0/relationalai/util/spans_file_handler.py +72 -0
  398. v0/relationalai/util/tracing_handler.py +34 -0
  399. frontend/debugger/dist/.gitignore +0 -2
  400. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  401. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  402. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  403. frontend/debugger/dist/index.html +0 -17
  404. relationalai/clients/__init__.py +0 -18
  405. relationalai/clients/client.py +0 -946
  406. relationalai/clients/config.py +0 -673
  407. relationalai/clients/direct_access_client.py +0 -118
  408. relationalai/clients/exec_txn_poller.py +0 -153
  409. relationalai/clients/hash_util.py +0 -31
  410. relationalai/clients/local.py +0 -594
  411. relationalai/clients/profile_polling.py +0 -73
  412. relationalai/clients/resources/__init__.py +0 -8
  413. relationalai/clients/resources/azure/azure.py +0 -502
  414. relationalai/clients/resources/snowflake/__init__.py +0 -20
  415. relationalai/clients/resources/snowflake/cli_resources.py +0 -98
  416. relationalai/clients/resources/snowflake/direct_access_resources.py +0 -739
  417. relationalai/clients/resources/snowflake/engine_service.py +0 -381
  418. relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -315
  419. relationalai/clients/resources/snowflake/error_handlers.py +0 -240
  420. relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
  421. relationalai/clients/resources/snowflake/resources_factory.py +0 -99
  422. relationalai/clients/resources/snowflake/snowflake.py +0 -3193
  423. relationalai/clients/resources/snowflake/use_index_poller.py +0 -1019
  424. relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
  425. relationalai/clients/resources/snowflake/util.py +0 -387
  426. relationalai/clients/result_helpers.py +0 -420
  427. relationalai/clients/types.py +0 -118
  428. relationalai/clients/util.py +0 -356
  429. relationalai/debugging.py +0 -389
  430. relationalai/dsl.py +0 -1749
  431. relationalai/early_access/builder/__init__.py +0 -30
  432. relationalai/early_access/builder/builder/__init__.py +0 -35
  433. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  434. relationalai/early_access/builder/std/__init__.py +0 -25
  435. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  436. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  437. relationalai/early_access/builder/std/math/__init__.py +0 -12
  438. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  439. relationalai/early_access/devtools/__init__.py +0 -12
  440. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  441. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  442. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  443. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  444. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  445. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  446. relationalai/early_access/dsl/bindings/common.py +0 -402
  447. relationalai/early_access/dsl/bindings/csv.py +0 -170
  448. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  449. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  450. relationalai/early_access/dsl/codegen/binder.py +0 -411
  451. relationalai/early_access/dsl/codegen/common.py +0 -79
  452. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  453. relationalai/early_access/dsl/codegen/relations.py +0 -700
  454. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  455. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  456. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  457. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  458. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  459. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  460. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  461. relationalai/early_access/dsl/core/context.py +0 -13
  462. relationalai/early_access/dsl/core/cset.py +0 -132
  463. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  464. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  465. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  466. relationalai/early_access/dsl/core/instances.py +0 -44
  467. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  468. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  469. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  470. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  471. relationalai/early_access/dsl/core/namespaces.py +0 -32
  472. relationalai/early_access/dsl/core/relations.py +0 -276
  473. relationalai/early_access/dsl/core/rules.py +0 -112
  474. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  475. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  476. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  477. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  478. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  479. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  480. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  481. relationalai/early_access/dsl/core/types/standard.py +0 -92
  482. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  483. relationalai/early_access/dsl/core/types/variables.py +0 -203
  484. relationalai/early_access/dsl/ir/compiler.py +0 -318
  485. relationalai/early_access/dsl/ir/executor.py +0 -260
  486. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  487. relationalai/early_access/dsl/ontologies/export.py +0 -30
  488. relationalai/early_access/dsl/ontologies/models.py +0 -453
  489. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  490. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  491. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  492. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  493. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  494. relationalai/early_access/dsl/orm/constraints.py +0 -438
  495. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  496. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  497. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  498. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  499. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  500. relationalai/early_access/dsl/orm/models.py +0 -256
  501. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  502. relationalai/early_access/dsl/orm/printer.py +0 -469
  503. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  504. relationalai/early_access/dsl/orm/relations.py +0 -19
  505. relationalai/early_access/dsl/orm/relationships.py +0 -251
  506. relationalai/early_access/dsl/orm/types.py +0 -42
  507. relationalai/early_access/dsl/orm/utils.py +0 -79
  508. relationalai/early_access/dsl/orm/verb.py +0 -204
  509. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  510. relationalai/early_access/dsl/relations.py +0 -170
  511. relationalai/early_access/dsl/rulesets.py +0 -69
  512. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  513. relationalai/early_access/dsl/schemas/builder.py +0 -48
  514. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  515. relationalai/early_access/dsl/schemas/components.py +0 -203
  516. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  517. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  518. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  519. relationalai/early_access/dsl/serialization.py +0 -79
  520. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  521. relationalai/early_access/dsl/snow/api.py +0 -105
  522. relationalai/early_access/dsl/snow/common.py +0 -76
  523. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  524. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  525. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  526. relationalai/early_access/dsl/types/__init__.py +0 -40
  527. relationalai/early_access/dsl/types/concepts.py +0 -12
  528. relationalai/early_access/dsl/types/entities.py +0 -135
  529. relationalai/early_access/dsl/types/values.py +0 -17
  530. relationalai/early_access/dsl/utils.py +0 -102
  531. relationalai/early_access/graphs/__init__.py +0 -13
  532. relationalai/early_access/lqp/__init__.py +0 -12
  533. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  534. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  535. relationalai/early_access/lqp/executor/__init__.py +0 -12
  536. relationalai/early_access/lqp/ir/__init__.py +0 -12
  537. relationalai/early_access/lqp/passes/__init__.py +0 -12
  538. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  539. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  540. relationalai/early_access/lqp/types/__init__.py +0 -12
  541. relationalai/early_access/lqp/utils/__init__.py +0 -12
  542. relationalai/early_access/lqp/validators/__init__.py +0 -12
  543. relationalai/early_access/metamodel/__init__.py +0 -58
  544. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  545. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  546. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  547. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  548. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  549. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  550. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  551. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  552. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  553. relationalai/early_access/metamodel/types/__init__.py +0 -15
  554. relationalai/early_access/metamodel/util/__init__.py +0 -15
  555. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  556. relationalai/early_access/rel/__init__.py +0 -12
  557. relationalai/early_access/rel/executor/__init__.py +0 -12
  558. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  559. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  560. relationalai/early_access/solvers/__init__.py +0 -19
  561. relationalai/early_access/sql/__init__.py +0 -11
  562. relationalai/early_access/sql/executor/__init__.py +0 -3
  563. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  564. relationalai/early_access/tests/logging/__init__.py +0 -12
  565. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  566. relationalai/early_access/tests/utils/__init__.py +0 -12
  567. relationalai/environments/__init__.py +0 -35
  568. relationalai/environments/base.py +0 -381
  569. relationalai/environments/colab.py +0 -14
  570. relationalai/environments/generic.py +0 -71
  571. relationalai/environments/ipython.py +0 -68
  572. relationalai/environments/jupyter.py +0 -9
  573. relationalai/environments/snowbook.py +0 -169
  574. relationalai/errors.py +0 -2496
  575. relationalai/experimental/SF.py +0 -38
  576. relationalai/experimental/inspect.py +0 -47
  577. relationalai/experimental/pathfinder/__init__.py +0 -158
  578. relationalai/experimental/pathfinder/api.py +0 -160
  579. relationalai/experimental/pathfinder/automaton.py +0 -584
  580. relationalai/experimental/pathfinder/bridge.py +0 -226
  581. relationalai/experimental/pathfinder/compiler.py +0 -416
  582. relationalai/experimental/pathfinder/datalog.py +0 -214
  583. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  584. relationalai/experimental/pathfinder/filter.py +0 -236
  585. relationalai/experimental/pathfinder/glushkov.py +0 -439
  586. relationalai/experimental/pathfinder/options.py +0 -265
  587. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  588. relationalai/experimental/pathfinder/rpq.py +0 -344
  589. relationalai/experimental/pathfinder/transition.py +0 -200
  590. relationalai/experimental/pathfinder/utils.py +0 -26
  591. relationalai/experimental/paths/README.md +0 -107
  592. relationalai/experimental/paths/api.py +0 -143
  593. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  594. relationalai/experimental/paths/code_organization.md +0 -2
  595. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  596. relationalai/experimental/paths/examples/basic_example.py +0 -40
  597. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  598. relationalai/experimental/paths/examples/movie_example.py +0 -77
  599. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  600. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  601. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  602. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  603. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  604. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  605. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  606. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  607. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  608. relationalai/experimental/paths/examples/paths_example.py +0 -116
  609. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  610. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  611. relationalai/experimental/paths/graph.py +0 -185
  612. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  613. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  614. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  615. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  616. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  617. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  618. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  619. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  620. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  621. relationalai/experimental/paths/product_graph.py +0 -93
  622. relationalai/experimental/paths/rpq/automaton.py +0 -584
  623. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  624. relationalai/experimental/paths/rpq/rpq.py +0 -378
  625. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  626. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  627. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  628. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  629. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  630. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  631. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  632. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  633. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  634. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  635. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  636. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  637. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  638. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  639. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  640. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  641. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  642. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  643. relationalai/experimental/paths/tree_agg.py +0 -168
  644. relationalai/experimental/paths/utilities/iterators.py +0 -27
  645. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  646. relationalai/experimental/solvers.py +0 -1095
  647. relationalai/loaders/csv.py +0 -195
  648. relationalai/loaders/loader.py +0 -177
  649. relationalai/loaders/types.py +0 -23
  650. relationalai/rel_emitter.py +0 -373
  651. relationalai/rel_utils.py +0 -185
  652. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  653. relationalai/semantics/devtools/benchmark_lqp.py +0 -535
  654. relationalai/semantics/devtools/compilation_manager.py +0 -294
  655. relationalai/semantics/devtools/extract_lqp.py +0 -110
  656. relationalai/semantics/internal/internal.py +0 -3785
  657. relationalai/semantics/internal/snowflake.py +0 -329
  658. relationalai/semantics/lqp/README.md +0 -34
  659. relationalai/semantics/lqp/algorithms.py +0 -173
  660. relationalai/semantics/lqp/builtins.py +0 -213
  661. relationalai/semantics/lqp/compiler.py +0 -22
  662. relationalai/semantics/lqp/constructors.py +0 -68
  663. relationalai/semantics/lqp/executor.py +0 -518
  664. relationalai/semantics/lqp/export_rewriter.py +0 -40
  665. relationalai/semantics/lqp/intrinsics.py +0 -24
  666. relationalai/semantics/lqp/ir.py +0 -150
  667. relationalai/semantics/lqp/model2lqp.py +0 -1056
  668. relationalai/semantics/lqp/passes.py +0 -38
  669. relationalai/semantics/lqp/primitives.py +0 -252
  670. relationalai/semantics/lqp/result_helpers.py +0 -266
  671. relationalai/semantics/lqp/rewrite/__init__.py +0 -32
  672. relationalai/semantics/lqp/rewrite/algorithm.py +0 -385
  673. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -69
  674. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  675. relationalai/semantics/lqp/rewrite/constants_to_vars.py +0 -70
  676. relationalai/semantics/lqp/rewrite/deduplicate_vars.py +0 -104
  677. relationalai/semantics/lqp/rewrite/eliminate_data.py +0 -108
  678. relationalai/semantics/lqp/rewrite/extract_common.py +0 -340
  679. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -577
  680. relationalai/semantics/lqp/rewrite/flatten_script.py +0 -301
  681. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  682. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -348
  683. relationalai/semantics/lqp/rewrite/period_math.py +0 -77
  684. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -339
  685. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  686. relationalai/semantics/lqp/rewrite/unify_definitions.py +0 -323
  687. relationalai/semantics/lqp/types.py +0 -101
  688. relationalai/semantics/lqp/utils.py +0 -170
  689. relationalai/semantics/lqp/validators.py +0 -70
  690. relationalai/semantics/metamodel/compiler.py +0 -134
  691. relationalai/semantics/metamodel/dependency.py +0 -880
  692. relationalai/semantics/metamodel/executor.py +0 -78
  693. relationalai/semantics/metamodel/factory.py +0 -287
  694. relationalai/semantics/metamodel/helpers.py +0 -368
  695. relationalai/semantics/metamodel/ir.py +0 -924
  696. relationalai/semantics/metamodel/rewrite/__init__.py +0 -8
  697. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  698. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -220
  699. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  700. relationalai/semantics/metamodel/rewrite/flatten.py +0 -590
  701. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -256
  702. relationalai/semantics/metamodel/rewrite/handle_aggregations_and_ranks.py +0 -237
  703. relationalai/semantics/metamodel/typer/checker.py +0 -355
  704. relationalai/semantics/metamodel/typer/typer.py +0 -1396
  705. relationalai/semantics/metamodel/util.py +0 -506
  706. relationalai/semantics/metamodel/visitor.py +0 -945
  707. relationalai/semantics/reasoners/__init__.py +0 -10
  708. relationalai/semantics/reasoners/graph/README.md +0 -620
  709. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  710. relationalai/semantics/reasoners/graph/core.py +0 -9019
  711. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  712. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  713. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  714. relationalai/semantics/reasoners/optimization/common.py +0 -88
  715. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  716. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1407
  717. relationalai/semantics/rel/builtins.py +0 -40
  718. relationalai/semantics/rel/compiler.py +0 -994
  719. relationalai/semantics/rel/executor.py +0 -363
  720. relationalai/semantics/rel/rel.py +0 -482
  721. relationalai/semantics/rel/rel_utils.py +0 -276
  722. relationalai/semantics/snowflake/__init__.py +0 -3
  723. relationalai/semantics/sql/compiler.py +0 -2503
  724. relationalai/semantics/sql/executor/duck_db.py +0 -52
  725. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  726. relationalai/semantics/sql/executor/snowflake.py +0 -149
  727. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  728. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  729. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  730. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  731. relationalai/semantics/sql/sql.py +0 -504
  732. relationalai/semantics/std/pragmas.py +0 -11
  733. relationalai/semantics/std/std.py +0 -14
  734. relationalai/semantics/tests/lqp/algorithms.py +0 -345
  735. relationalai/semantics/tests/test_snapshot_abstract.py +0 -144
  736. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  737. relationalai/semantics/tests/utils.py +0 -46
  738. relationalai/std/__init__.py +0 -70
  739. relationalai/tools/cli.py +0 -2089
  740. relationalai/tools/cli_controls.py +0 -1975
  741. relationalai/tools/cli_helpers.py +0 -802
  742. relationalai/tools/debugger_client.py +0 -109
  743. relationalai/tools/debugger_server.py +0 -302
  744. relationalai/tools/dev.py +0 -685
  745. relationalai/tools/notes +0 -7
  746. relationalai/tools/qb_debugger.py +0 -425
  747. relationalai/tools/txn_progress.py +0 -188
  748. relationalai/util/clean_up_databases.py +0 -95
  749. relationalai/util/list_databases.py +0 -9
  750. relationalai/util/otel_configuration.py +0 -26
  751. relationalai/util/otel_handler.py +0 -484
  752. relationalai/util/snowflake_handler.py +0 -88
  753. relationalai/util/span_format_test.py +0 -43
  754. relationalai/util/span_tracker.py +0 -207
  755. relationalai/util/spans_file_handler.py +0 -72
  756. relationalai/util/tracing_handler.py +0 -34
  757. relationalai-0.13.5.dist-info/METADATA +0 -74
  758. relationalai-0.13.5.dist-info/RECORD +0 -473
  759. relationalai-0.13.5.dist-info/WHEEL +0 -4
  760. relationalai-0.13.5.dist-info/entry_points.txt +0 -3
  761. relationalai-0.13.5.dist-info/licenses/LICENSE +0 -202
  762. relationalai_test_util/__init__.py +0 -4
  763. relationalai_test_util/fixtures.py +0 -233
  764. relationalai_test_util/snapshot.py +0 -252
  765. relationalai_test_util/traceback.py +0 -118
  766. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  767. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  768. /relationalai/{early_access → shims}/__init__.py +0 -0
  769. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  771. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  772. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  774. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  775. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  776. {relationalai → v0/relationalai}/auth/util.py +0 -0
  777. {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
  778. {relationalai → v0/relationalai}/compiler.py +0 -0
  779. {relationalai → v0/relationalai}/dependencies.py +0 -0
  780. {relationalai → v0/relationalai}/docutils.py +0 -0
  781. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  783. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  784. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  785. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  786. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  787. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  788. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  789. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  790. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  791. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  792. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  794. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  796. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  797. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  798. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  799. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  800. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  801. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  802. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  803. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  804. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  805. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  806. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  807. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  808. {relationalai/semantics/tests/lqp → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  809. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  811. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  812. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  813. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  814. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  815. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  816. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  817. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  818. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  819. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  820. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  821. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  822. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  823. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  824. {relationalai/tools → v0/relationalai/loaders}/__init__.py +0 -0
  825. {relationalai → v0/relationalai}/metagen.py +0 -0
  826. {relationalai → v0/relationalai}/metamodel.py +0 -0
  827. {relationalai → v0/relationalai}/rel.py +0 -0
  828. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  829. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  830. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  831. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  832. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  833. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  834. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  835. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  836. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  837. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  838. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  839. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  840. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  841. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  842. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  843. {relationalai → v0/relationalai}/std/dates.py +0 -0
  844. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  845. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  846. {relationalai → v0/relationalai}/std/math.py +0 -0
  847. {relationalai → v0/relationalai}/std/re.py +0 -0
  848. {relationalai → v0/relationalai}/std/strings.py +0 -0
  849. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  850. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  851. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  852. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  853. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  854. {relationalai → v0/relationalai}/util/constants.py +0 -0
  855. {relationalai → v0/relationalai}/util/graph.py +0 -0
  856. {relationalai → v0/relationalai}/util/timeout.py +0 -0
@@ -0,0 +1,862 @@
1
+ """
2
+ Support for dependency analysis of metamodel IRs.
3
+ """
4
+ from __future__ import annotations
5
+ from dataclasses import dataclass, field
6
+ from typing import Iterable, Optional
7
+ from itertools import count
8
+ from more_itertools import peekable
9
+ from v0.relationalai.semantics.metamodel import builtins, ir, helpers, visitor
10
+ from v0.relationalai.semantics.metamodel.util import OrderedSet, ordered_set
11
+
12
+
13
+ #--------------------------------------------------
14
+ # Public API
15
+ #--------------------------------------------------
16
+
17
+ @dataclass
18
+ class DependencyInfo():
19
+ """
20
+ Represents the result of performing binding and dependency analysis on a metamodel tree.
21
+
22
+ All dicts are keyed by task ids.
23
+ """
24
+ # input vars for a task
25
+ input_bindings: dict[int, OrderedSet[ir.Var]] = field(default_factory=dict)
26
+ # output vars for a task
27
+ output_bindings: dict[int, OrderedSet[ir.Var]] = field(default_factory=dict)
28
+ # clusters of dependency that each task participates on
29
+ dependency_clusters: dict[int, Cluster] = field(default_factory=dict)
30
+ # keep track of the parents of each task
31
+ parent: dict[int, ir.Task] = field(default_factory=dict)
32
+ # keep track of replacements that were made during a rewrite
33
+ replacements: dict[int, ir.Task] = field(default_factory=dict)
34
+
35
+ def task_inputs(self, node: ir.Task) -> Optional[OrderedSet[ir.Var]]:
36
+ """ The input variables for this task, if any. """
37
+ if node.id in self.input_bindings:
38
+ return self.input_bindings[node.id]
39
+ return None
40
+
41
+ def has_inputs(self, node: ir.Task):
42
+ return node.id in self.input_bindings
43
+
44
+ def task_outputs(self, node: ir.Task) -> Optional[OrderedSet[ir.Var]]:
45
+ """ The output variables for this task, if any. """
46
+ if node.id in self.output_bindings:
47
+ return self.output_bindings[node.id]
48
+ return None
49
+
50
+ def has_outputs(self, node: ir.Task):
51
+ return node.id in self.output_bindings
52
+
53
+ def task_dependencies(self, task: ir.Task) -> OrderedSet[ir.Task]:
54
+ """
55
+ All dependencies for this task, if any. This includes tasks in outer contexts,
56
+ not only siblings.
57
+ """
58
+
59
+ deps = ordered_set()
60
+ cluster = self.dependency_clusters.get(task.id, None)
61
+ parent = self.parent.get(task.id)
62
+
63
+ if cluster:
64
+ self._collect_deps(cluster, deps)
65
+ while parent:
66
+ cluster = self.dependency_clusters.get(parent.id, None)
67
+ if cluster:
68
+ self._collect_deps(cluster, deps)
69
+ parent = self.parent[cluster.content[0].id]
70
+ else:
71
+ parent = None
72
+ return self._with_replacements(deps)
73
+
74
+ def local_dependencies(self, task: ir.Task) -> Optional[OrderedSet[ir.Task]]:
75
+ """ Similar to task_dependencies but returns only dependencies that are siblings. """
76
+
77
+ if task.id in self.dependency_clusters:
78
+ deps = ordered_set()
79
+ self._collect_deps(self.dependency_clusters[task.id], deps)
80
+ return self._with_replacements(deps)
81
+ return None
82
+
83
+ def replaced(self, original: ir.Task, replacement: ir.Task):
84
+ """
85
+ Inform that, during some pass, this original task was replaced with this replacement
86
+ task. This affects the info of .task_dependencies(...) since it will answer with
87
+ the replacement when the original is in the set of dependencies.
88
+ """
89
+ self.replacements[original.id] = replacement
90
+
91
+ #
92
+ # Implementation details
93
+ #
94
+ def _collect_deps(self, cluster: Cluster, deps: OrderedSet[ir.Task]):
95
+ queue = []
96
+ # start with the cluster dependencies, because cluster represents the task we
97
+ # care about
98
+ queue.extend(cluster.dependencies)
99
+ seen = set()
100
+ while queue:
101
+ cluster = queue.pop()
102
+ if cluster.id in seen:
103
+ continue
104
+ seen.add(cluster.id)
105
+ deps.update(cluster.content)
106
+ queue.extend(cluster.dependencies)
107
+
108
+ def _with_replacements(self, deps):
109
+ # Return deps with all tasks that need replacements (because they are in the
110
+ # replacements dict) replaced.
111
+ if any([dep.id in self.replacements for dep in deps]):
112
+ # Only allocate and compute replacements if there's a dep that was replaced
113
+ info = ordered_set()
114
+ for dep in deps:
115
+ info.add(self.replacements.get(dep.id, dep))
116
+ return info
117
+ return deps
118
+
119
+
120
+ def analyze_bindings(task: ir.Task) -> DependencyInfo:
121
+ """
122
+ Perform just the binding analysis, skipping the dependency analysis. This is useful
123
+ for passes that only require knowing the input/output sets for nodes, but do not need
124
+ the more expensive dependency information.
125
+
126
+ The returned DependencyInfo object will only have input and output bindings filled.
127
+ """
128
+ binding = BindingAnalysis()
129
+ task.accept(binding)
130
+ return binding.info
131
+
132
+ def analyze(task: ir.Task) -> DependencyInfo:
133
+ """
134
+ Perform binding and dependency analysis on this task.
135
+
136
+ The returned DependencyInfo object will have all dictionaries filled.
137
+ """
138
+ # first perform binding analysis to get inputs and outputs
139
+ info = analyze_bindings(task)
140
+
141
+ # TODO - if the toplevel task needs inputs, that's a groundness error
142
+
143
+ # now perform the dependency analysis
144
+ dependency = DependencyAnalysis(info)
145
+ task.accept(dependency)
146
+ return info
147
+
148
+ #--------------------------------------------------
149
+ # Dependency Analysis
150
+ #--------------------------------------------------
151
+
152
+ # id generator for Clusters
153
+ _global_id = peekable(count(0))
154
+ def next_id():
155
+ return next(_global_id)
156
+
157
+ class Cluster():
158
+ def __init__(self, info: DependencyInfo, task: ir.Task):
159
+ """ Create a cluster starting with only this task. """
160
+ self.id = next_id()
161
+ self.info = info
162
+ # exists and lookups for nullary relations are always required (i.e. everything
163
+ # should depend on them)
164
+ self.required = isinstance(task, ir.Exists) or (isinstance(task, ir.Lookup) and not task.args)
165
+ # this is a binders cluster, which is a candidate to being merged
166
+ self.mergeable = not self.required and isinstance(task, helpers.BINDERS)
167
+ # this is a cluster that will only hold an effect
168
+ self.effectful = isinstance(task, helpers.EFFECTS)
169
+ # this is a cluster that will only hold a composite
170
+ self.composite = isinstance(task, helpers.COMPOSITES)
171
+ # content is either a single task or a set of tasks
172
+ self.content: OrderedSet[ir.Task] = ordered_set(task)
173
+ # combined inputs and outputs for all tasks in the cluster
174
+ self.inputs: OrderedSet[ir.Var] = OrderedSet.from_iterable(info.input_bindings.get(task.id))
175
+ self.outputs: OrderedSet[ir.Var] = OrderedSet.from_iterable(info.output_bindings.get(task.id))
176
+ # eventually we will compute dependencies between clusters
177
+ self.dependencies: OrderedSet[Cluster] = ordered_set()
178
+
179
+ def __str__(self) -> str:
180
+ if isinstance(self.content, ir.Task):
181
+ return str(self.content.id)
182
+ else:
183
+ return ', '.join(str(node.id) for node in self.content)
184
+
185
+ def __eq__(self, other):
186
+ return isinstance(other, Cluster) and other.id == self.id
187
+
188
+ def __hash__(self):
189
+ return hash(self.id)
190
+
191
+ def depends_on(self, other: Cluster):
192
+ """ Assert that this cluster depends on the other cluster. """
193
+ if self in other.dependencies:
194
+ # prevent cycles caused by bugs, like the union hoisting pets in the
195
+ # relationship7 test
196
+ print("Warning: there is a cycle in the dependency graph. This is likely a bug.")
197
+ # k = ','.join(str(x.id) for x in self.content)
198
+ # v = ','.join(str(x.id) for x in other.content)
199
+ # print(f"{k} --> {v}")
200
+ else:
201
+ self.dependencies.add(other)
202
+
203
+ def shares_variable(self, other: Cluster):
204
+ """ Returns True iff this cluster and the other cluster have at least one var in common. """
205
+ return (
206
+ any(i in other.inputs or i in other.outputs for i in self.inputs) or
207
+ any(o in other.inputs or o in other.outputs for o in self.outputs)
208
+ )
209
+
210
+ def try_merge(self, other: Cluster, hoisted_vars: OrderedSet[ir.Var]):
211
+ """
212
+ Verify that this cluster and the other cluster can be merged. If so, merge the
213
+ other cluster into this cluster and return True. Otherwise, return False and the
214
+ clusters are left unmodified.
215
+ """
216
+
217
+ # 1. only mergeable
218
+ if not (self.mergeable and other.mergeable):
219
+ return False
220
+
221
+ # 2. share some variable
222
+ if not self.shares_variable(other):
223
+ return False
224
+
225
+ # 3. all inputs are covered by outputs within the cluster
226
+ if not all(v in self.outputs or v in other.outputs for v in self.inputs):
227
+ return False
228
+ if not all(v in self.outputs or v in other.outputs for v in other.inputs):
229
+ return False
230
+
231
+ # 4. if there are hoisted vars in context, we can only merge clusters that bind the
232
+ # same hoisted vars
233
+ if hoisted_vars:
234
+ for v in hoisted_vars:
235
+ # if self binds v and other does not bind v, they can't be merged
236
+ if v in self.outputs or v in self.inputs:
237
+ if v not in other.outputs or v not in other.inputs:
238
+ return False
239
+ # the other way around
240
+ if v in other.outputs or v in other.inputs:
241
+ if v not in self.outputs or v not in self.inputs:
242
+ return False
243
+
244
+ # ok, can merge
245
+ self.merge(other)
246
+ return True
247
+
248
+ def try_merge_group(self, others: list[Cluster]):
249
+ """
250
+ Verify that this cluster and the other clusters can all be merged together. If so,
251
+ merge the other clusters into this cluster and return True. Otherwise, return False
252
+ and all clusters are left unmodified.
253
+ """
254
+ assert(len(others) > 0)
255
+
256
+ # 1. only mergeable
257
+ if not (self.mergeable and all(o.mergeable for o in others)):
258
+ return False
259
+
260
+ # 2. share some variable
261
+ if not self.shares_variable(others[0]):
262
+ return False
263
+
264
+ # 3. all inputs are covered by outputs within the newly formed cluster
265
+ if len(others) == 1:
266
+ others_outputs = others[0].outputs
267
+ else:
268
+ others_outputs = ordered_set()
269
+ [others_outputs.update(o.outputs) for o in others]
270
+ if not all(v in self.outputs or v in others_outputs for v in self.inputs):
271
+ return False
272
+ for other in others:
273
+ if not all(v in self.outputs or v in others_outputs for v in other.inputs):
274
+ return False
275
+
276
+ # ok, can merge
277
+ self.merge(others)
278
+ return True
279
+
280
+ def merge(self, other: Cluster|Iterable[Cluster]):
281
+ """
282
+ Merge the other cluster(s) into this one. This assumes that the merge makes sense.
283
+ In general, we should use try_merge or try_merge_group instead.
284
+ """
285
+ # merge the other cluster's content, inputs and outputs
286
+ if isinstance(other, Cluster):
287
+ self.content.update(other.content)
288
+ self.inputs.update(other.inputs)
289
+ self.outputs.update(other.outputs)
290
+ # update dependencies, ensuring we remove the other from the self
291
+ self.dependencies.update(other.dependencies)
292
+ self.dependencies.remove(other)
293
+ else:
294
+ for o in other:
295
+ self.content.update(o.content)
296
+ self.inputs.update(o.inputs)
297
+ self.outputs.update(o.outputs)
298
+ self.dependencies.update(o.dependencies)
299
+ self.dependencies.remove(o)
300
+
301
+
302
+ class DependencyAnalysis(visitor.Visitor):
303
+ """
304
+ A visitor to perform dependency analysis in logicals and store the result in a
305
+ DependencyInfo object.
306
+
307
+ The dependency analysis is performed for Logical nodes in 3 steps:
308
+
309
+ 1. form clusters of children that are mutually dependent, because they are binders (like
310
+ lookups and aggregates) that have variables in common.
311
+
312
+ 2. compute dependencies between the clusters based on input and outputs.
313
+
314
+ 3. attempt to merge clusters that could form larger clusters.
315
+
316
+ Consider the following example, where we are computing dependencies for the numbered nodes:
317
+
318
+ Logical
319
+ |1| Edges(edges)
320
+ |2| i(edges, i)
321
+ |3| Logical ⇑[v]
322
+ Logical ⇑[j=None]
323
+ j(edges, j)
324
+ count([edges, j], [i], [v])
325
+ |4| i < 10
326
+ |5| i < v
327
+ |6| Logical ⇑[v_2=None]
328
+ max([i], [], [v, v_2])
329
+ |7| → output[i](v, v_2 as 'v2')
330
+
331
+ In step 1., we merge (1,2,4) because they have `edges` and `i` in common, but nothing
332
+ else. In particular, (5) is not merged as it also depends on v.
333
+
334
+ In step 2. we compute dependencies:
335
+ (1,2,4)
336
+ (3) -> (1,2,4)
337
+ (5) -> (1,2,4), (3)
338
+ (6) -> (1,2,4), (3), (5)
339
+ (7) -> (1,2,4), (3), (5), (6)
340
+
341
+ For this example, step 3. does not change anything.
342
+
343
+ This result can be interpreted as, in order to compute task 6, tasks (1,2,4), (3) and (5)
344
+ must hold. This means that a compiler pass that extracts the logical in task 6 into its
345
+ own top-level logical must bring these dependencies together.
346
+
347
+ To illustrate the need for step 3, consider this example:
348
+
349
+ Logical
350
+ |1| Edge(edge)
351
+ |2| i(edge, i)
352
+ |3| Edge(edge_2)
353
+ |4| j(edge_2, j)
354
+ |5| i = j
355
+ |6| Logical ⇑[res=None]
356
+ .....
357
+ |7| → output[edge, j, i](i, res)
358
+
359
+ The result of step 2 is the following:
360
+ (1,2)
361
+ (3,4)
362
+ (5) -> (1,2), (3,4)
363
+ (6) -> (1,2), (3,4), (5)
364
+ (7) -> (1,2), (3,4), (5), (6)
365
+
366
+ Step 3 observes that task (5) is a bridge between (1,2) and (3,4), so that merging those
367
+ 3 clusters together yields a consistent cluster. So the result is:
368
+
369
+ (1,2,3,4,5)
370
+ (6) -> (1,2,3,4,5)
371
+ (7) -> (1,2,3,4,5), (6)
372
+
373
+ """
374
+ def __init__(self, info: DependencyInfo):
375
+ self.info = info
376
+
377
+
378
+ def enter(self, node: ir.Node, parent: Optional[ir.Node]=None):
379
+ # keep track of parents of all nodes
380
+ if parent and isinstance(parent, ir.Task):
381
+ self.info.parent[node.id] = parent
382
+ return super().enter(node, parent)
383
+
384
+
385
+ def visit_logical(self, node: ir.Logical, parent: Optional[ir.Node]):
386
+ # quick check to see if it's worth it computing clusters at all
387
+ some_child_has_bindings = False
388
+ for child in node.body:
389
+ if child.id in self.info.input_bindings or child.id in self.info.output_bindings:
390
+ some_child_has_bindings = True
391
+ break
392
+
393
+ if some_child_has_bindings:
394
+ # print(ir.node_to_string(node, print_ids=True))
395
+ # compute clusters for the nodes based on inputs/outputs and shared variables
396
+ clusters = self.compute_clusters(node)
397
+ # compute the dependencies between those clusters
398
+ self.compute_dependencies(clusters)
399
+ # attempt to further merge clusters
400
+ self.merge_clusters(clusters)
401
+ # index the clusters by tasks participating in those clusters, and record it
402
+ self.index(clusters)
403
+ # self._print_debug_info(node, clusters)
404
+
405
+ return super().visit_logical(node, parent)
406
+
407
+
408
+ def compute_clusters(self, task: ir.Logical) -> list[Cluster]:
409
+ """
410
+ Cluster the children of the logical, storing together children that are mutually
411
+ dependent.
412
+ """
413
+ # create initial clusters
414
+ clusters:list[Cluster] = [Cluster(self.info, child) for child in task.body]
415
+
416
+ # all hoisted vars of children, used to ensure we don't merge clusters that depend
417
+ # on a variable hoisted by a composite
418
+ hoisted_vars = ordered_set()
419
+ for child in task.body:
420
+ if isinstance(child, helpers.COMPOSITES):
421
+ hoisted_vars.update(helpers.hoisted_vars(child.hoisted))
422
+
423
+ # iterate clustering until nothing changes
424
+ merging = True
425
+ while merging:
426
+ merging = False
427
+ cs = list(clusters)
428
+ while cs:
429
+ # last c1 merged some c2s, so cs was modified, restart
430
+ if merging:
431
+ break
432
+ c1 = cs.pop()
433
+ for c2 in cs:
434
+ if c1 is c2:
435
+ continue
436
+ if c1.try_merge(c2, hoisted_vars):
437
+ clusters.remove(c2)
438
+ merging = True
439
+ return clusters
440
+
441
+
442
+ def compute_dependencies(self, clusters: list[Cluster]):
443
+ """
444
+ Traverse the clusters finding dependencies between them, based on input and output
445
+ variables used by tasks within the clusters.
446
+ """
447
+ def has_dependency(c1: Cluster, c2: Cluster):
448
+ # c2 is a required cluster, everything depends no it
449
+ if c2.required:
450
+ return True
451
+ # if c1 has an effect and c2 is mergeable (basically it contains only binders)
452
+ # then c2 behaves like a filter, so c1 must depend on it, even if it does not
453
+ # have variables in common (this may bring other dependencies).
454
+ if c1.effectful and c2.mergeable:
455
+ return True
456
+ # if c1 has an effect and c2 is a composite without hoisted variables or with a
457
+ # hoisted variable that does not have a default (it is a plain var), then c2
458
+ # behaves like a filter and c1 depends on it.
459
+ if c1.effectful and c2.composite:
460
+ task = c2.content.some()
461
+ assert(isinstance(task, helpers.COMPOSITES))
462
+ if not task.hoisted:
463
+ return True
464
+ for h in task.hoisted:
465
+ if isinstance(h, ir.Var): # no default
466
+ return True
467
+
468
+ # if c1 is a composite and c2 binds its hoisted vars, c1 can't depend on c2
469
+ # (dependency is the other way around)
470
+ if c1.composite and c1.outputs:
471
+ for v in c1.outputs:
472
+ if c2.outputs and v in c2.outputs:
473
+ return False
474
+ if c2.inputs and v in c2.inputs:
475
+ return False
476
+
477
+ # c1 does not depend on c2 if one of its output vars is an input to c2
478
+ # (dependency is the other way around)
479
+ if (c1.outputs and c2.inputs):
480
+ # optimization for any([v in c2.inputs for v in c1_outputs])):
481
+ for v in c1.outputs:
482
+ if v in c2.inputs:
483
+ return False
484
+
485
+ # c1 depends on c2 if one of its input vars is an output of c2
486
+ if (c1.inputs and c2.outputs):
487
+ # optimization for any([v in c2.outputs for v in c1_inputs])):
488
+ for v in c1.inputs:
489
+ if v in c2.outputs:
490
+ return True
491
+
492
+ # c1 is a composite with hoisted variables; it depends on c2 if c2 is a
493
+ # composite that does not have hoisted vars, hence behaving like a filter.
494
+ if c1.composite and c2.composite:
495
+ c1task = c1.content.some()
496
+ assert(isinstance(c1task, helpers.COMPOSITES))
497
+ if c1task.hoisted:
498
+ c2task = c2.content.some()
499
+ assert(isinstance(c2task, helpers.COMPOSITES))
500
+ if not c2task.hoisted:
501
+ return True
502
+ return False
503
+
504
+ cs = list(clusters)
505
+ while cs:
506
+ c1 = cs.pop()
507
+ for c2 in cs:
508
+ if c1 is c2:
509
+ continue
510
+
511
+ if has_dependency(c1, c2):
512
+ c1.depends_on(c2)
513
+ if has_dependency(c2, c1):
514
+ c2.depends_on(c1)
515
+
516
+
517
+ def merge_clusters(self, clusters: list[Cluster]):
518
+ """
519
+ Traverse clusters trying to merge multiple clusters if they together form a larger
520
+ cluster.
521
+ """
522
+ # iterate clustering until nothing changes
523
+ merging = True
524
+ while merging:
525
+ merging = False
526
+ cs = list(clusters)
527
+ while cs:
528
+ if merging:
529
+ break
530
+ c = cs.pop()
531
+ if c.dependencies and c.mergeable:
532
+ deps = list(c.dependencies)
533
+ if c.try_merge_group(deps):
534
+ # remove the deps from clusters
535
+ for d in deps:
536
+ clusters.remove(d)
537
+ # rewire other clusters to the new node
538
+ # this is not very efficient but should not happen often
539
+ for c2 in clusters:
540
+ if c2 is not c:
541
+ for d in deps:
542
+ if d in c2.dependencies:
543
+ c2.dependencies.add(c)
544
+ c2.dependencies.remove(d)
545
+ merging = True
546
+
547
+
548
+ def index(self, clusters: list[Cluster]):
549
+ """
550
+ Index clusters by task, and record in the info
551
+ """
552
+ for dep_node in clusters:
553
+ for n in dep_node.content:
554
+ self.info.dependency_clusters[n.id] = dep_node
555
+
556
+
557
+ def _print_debug_info(self, node, clusters: list[Cluster]):
558
+ # print(ir.node_to_string(node, print_ids=True))
559
+ print("dependencies")
560
+ for dep_node in clusters:
561
+ k = ','.join(str(x.id) for x in dep_node.content)
562
+ print(f"({k}) ->")
563
+ for v in dep_node.dependencies:
564
+ v = ','.join(str(x.id) for x in v.content)
565
+ print(f" ({v})")
566
+ print()
567
+ print("clusters")
568
+ for c in clusters:
569
+ print(f"{c}")
570
+ if c.inputs:
571
+ print(f" inputs: {','.join(str(v.name) for v in c.inputs)}")
572
+ if c.outputs:
573
+ print(f" outputs: {','.join(str(v.name) for v in c.outputs)}")
574
+ print()
575
+
576
+
577
+
578
+ class BindingAnalysis(visitor.Visitor):
579
+ """
580
+ Visitor to perform binding analysis, i.e. figure out for each task in the tree, which
581
+ variables it binds as input ad output.
582
+ """
583
+ def __init__(self):
584
+ self.info = DependencyInfo()
585
+ # a stack of variables grounded by the last logical being visited
586
+ self._grounded: list[OrderedSet[ir.Var]] = []
587
+
588
+
589
+ def input(self, key: ir.Task, val: Optional[ir.Var|Iterable[ir.Var]]):
590
+ """ Assert that this task binds this variable(s) as input. """
591
+ self._register(self.info.input_bindings, key, val)
592
+
593
+
594
+ def output(self, key: ir.Task, val: Optional[ir.Var|Iterable[ir.Var]]):
595
+ """ Assert that this task binds this variable(s) as output. """
596
+ self._register(self.info.output_bindings, key, val)
597
+
598
+
599
+ def _register(self, map, key: ir.Task, val: Optional[ir.Var|Iterable[ir.Var]]):
600
+ """ Register key.id -> val in this map, assuming the map holds ordered sets of vals. """
601
+ if val is None or (isinstance(val, Iterable) and not val):
602
+ return
603
+ if key.id not in map:
604
+ map[key.id] = ordered_set()
605
+ if isinstance(val, Iterable):
606
+ for v in val:
607
+ map[key.id].add(v)
608
+ else:
609
+ map[key.id].add(val)
610
+
611
+
612
+ #
613
+ # Composite tasks
614
+ #
615
+ def visit_logical(self, node: ir.Logical, parent: Optional[ir.Node]):
616
+ # compute variables grounded by children of this logical
617
+ grounds = ordered_set()
618
+ grounded_by_ancestors = None
619
+ if self._grounded:
620
+ # grounded variables inherited from ancestors or siblings
621
+ grounded_by_ancestors = self._grounded[-1]
622
+ grounds.update(grounded_by_ancestors)
623
+
624
+ potentially_grounded = ordered_set()
625
+ for child in node.body:
626
+ # leaf constructs that ground variables
627
+ if isinstance(child, ir.Lookup):
628
+ # special case eq because it can be input or output
629
+ # TODO: this is similar to what's done below in visit_lookup, modularize
630
+ if builtins.is_eq(child.relation):
631
+ x, y = child.args[0], child.args[1]
632
+ # Compute input/output vars of the equality
633
+ if isinstance(x, ir.Var) and not isinstance(y, ir.Var):
634
+ # Variable x is potentially grounded by other expressions at
635
+ # level in the Logical. If it is, then we should mark it as
636
+ # input (which is done later).
637
+ potentially_grounded.add((child, x, x))
638
+ elif not isinstance(x, ir.Var) and isinstance(y, ir.Var):
639
+ potentially_grounded.add((child, y, y))
640
+ elif isinstance(x, ir.Var) and isinstance(y, ir.Var):
641
+ # mark as potentially grounded, if any is grounded in other atoms then we later ground both
642
+ potentially_grounded.add((child, x, y))
643
+ else:
644
+ # grounds only outputs
645
+ for idx, f in enumerate(child.relation.fields):
646
+ arg = child.args[idx]
647
+ if not f.input and isinstance(arg, ir.Var):
648
+ grounds.add(arg)
649
+ elif isinstance(child, ir.Data):
650
+ # grounds all vars
651
+ grounds.update(child.vars)
652
+ elif isinstance(child, ir.Aggregate):
653
+ # grounds output args
654
+ for idx, f in enumerate(child.aggregation.fields):
655
+ arg = child.args[idx]
656
+ if not f.input and isinstance(arg, ir.Var):
657
+ grounds.add(arg)
658
+ elif isinstance(child, ir.Rank):
659
+ # grounds the info
660
+ grounds.add(child.result)
661
+ elif isinstance(child, ir.Construct):
662
+ # grounds the output var
663
+ grounds.add(child.id_var)
664
+
665
+ # add child hoisted vars to grounded so that they can be picked up by the children
666
+ for child in node.body:
667
+ if isinstance(child, helpers.COMPOSITES):
668
+ grounds.update(helpers.hoisted_vars(child.hoisted))
669
+
670
+ # equalities where both sides are already grounded mean that both sides are input
671
+ for child, x, y in potentially_grounded:
672
+ if x in grounds and y in grounds:
673
+ self.input(child, x)
674
+ self.input(child, y)
675
+
676
+ # deal with potentially grounded vars up to a fixpoint
677
+ changed = True
678
+ while changed:
679
+ changed = False
680
+ for child, x, y in potentially_grounded:
681
+ if x in grounds and y not in grounds:
682
+ self.input(child, x)
683
+ self.output(child, y)
684
+ grounds.add(y)
685
+ changed = True
686
+ elif y in grounds and x not in grounds:
687
+ self.input(child, y)
688
+ self.output(child, x)
689
+ grounds.add(x)
690
+ changed = True
691
+
692
+ # now visit the children
693
+ self._grounded.append(grounds)
694
+ super().visit_logical(node, parent)
695
+ self._grounded.pop()
696
+
697
+ hoisted_vars = helpers.hoisted_vars(node.hoisted)
698
+ if grounded_by_ancestors:
699
+ # inputs to this logical: grounded by ancestor while being used by a child,
700
+ # excluding variables hoisted by the logical
701
+ vars = helpers.collect_vars(node)
702
+ self.input(node, (grounded_by_ancestors & vars) - hoisted_vars)
703
+
704
+ # outputs are vars declared as hoisted
705
+ self.output(node, hoisted_vars)
706
+
707
+
708
+ def visit_union(self, node: ir.Union, parent: Optional[ir.Node]):
709
+ # visit children first
710
+ super().visit_union(node, parent)
711
+
712
+ # inputs taken from all children
713
+ for child in node.tasks:
714
+ self.input(node, self.info.task_inputs(child))
715
+ # outputs are vars declared as hoisted
716
+ self.output(node, helpers.hoisted_vars(node.hoisted))
717
+
718
+
719
+ def visit_match(self, node: ir.Match, parent: Optional[ir.Node]):
720
+ # visit children first
721
+ super().visit_match(node, parent)
722
+
723
+ # inputs taken from all children
724
+ for child in node.tasks:
725
+ self.input(node, self.info.task_inputs(child))
726
+ # outputs are vars declared as hoisted
727
+ self.output(node, helpers.hoisted_vars(node.hoisted))
728
+
729
+
730
+ def visit_require(self, node: ir.Require, parent: Optional[ir.Node]):
731
+ # visit children first
732
+ super().visit_require(node, parent)
733
+
734
+ # inputs taken from the domain and all check tasks
735
+ self.input(node, self.info.task_inputs(node.domain))
736
+ for check in node.checks:
737
+ self.input(node, self.info.task_inputs(check.check))
738
+
739
+
740
+ #
741
+ # Logical tasks
742
+ #
743
+ def visit_not(self, node: ir.Not, parent: Optional[ir.Node]):
744
+ # visit children first
745
+ super().visit_not(node, parent)
746
+
747
+ # not gets the inputs from its child
748
+ self.input(node, self.info.task_inputs(node.task))
749
+
750
+
751
+ def visit_exists(self, node: ir.Exists, parent: Optional[ir.Node]):
752
+ # visit children first
753
+ super().visit_exists(node, parent)
754
+
755
+ # exists variables are local, so they are ignored
756
+ self.input(node, self.info.task_inputs(node.task))
757
+
758
+
759
+ #
760
+ # Leaf tasks
761
+ #
762
+ def visit_data(self, node: ir.Data, parent: Optional[ir.Node]):
763
+ # data outputs all its variables
764
+ for v in helpers.vars(node.vars):
765
+ self.output(node, v)
766
+
767
+ return super().visit_data(node, parent)
768
+
769
+
770
+ def visit_update(self, node: ir.Update, parent: Optional[ir.Node]):
771
+ # register variables being used as arguments to the update, it's always considered an input
772
+ for v in helpers.vars(node.args):
773
+ self.input(node, v)
774
+ return super().visit_update(node, parent)
775
+
776
+
777
+ def visit_lookup(self, node: ir.Lookup, parent: Optional[ir.Node]):
778
+ def register(node, field, arg):
779
+ if isinstance(arg, ir.Var):
780
+ if field.input:
781
+ self.input(node, arg)
782
+ else:
783
+ self.output(node, arg)
784
+
785
+ if builtins.is_eq(node.relation):
786
+ # Most cases are covered already at the parent level if the equality is part of
787
+ # a Logical. The remaining cases are when the equality is a child of a
788
+ # non-Logical, or if its variables are not ground elsewhere in the Logical.
789
+ if self.info.task_inputs(node) or self.info.task_outputs(node):
790
+ # already covered
791
+ pass
792
+ else:
793
+ x, y = node.args[0], node.args[1]
794
+ grounds = self._grounded[-1] if self._grounded else ordered_set()
795
+ if isinstance(x, ir.Var):
796
+ if x in grounds:
797
+ self.input(node, x)
798
+ else:
799
+ self.output(node, x)
800
+ if isinstance(y, ir.Var):
801
+ if y in grounds:
802
+ self.input(node, y)
803
+ else:
804
+ self.output(node, y)
805
+ else:
806
+ # register variables depending on the input flag of the relation bound to the lookup
807
+ for idx, f in enumerate(node.relation.fields):
808
+ arg = node.args[idx]
809
+ if isinstance(arg, Iterable):
810
+ # deal with ListType fields that pack arguments in a tuple
811
+ for element in arg:
812
+ register(node, f, element)
813
+ else:
814
+ register(node, f, arg)
815
+ return super().visit_lookup(node, parent)
816
+
817
+
818
+ def visit_output(self, node: ir.Output, parent: Optional[ir.Node]):
819
+ # register variables being output, they always considered an input to the task
820
+ for v in helpers.output_vars(node.aliases):
821
+ self.input(node, v)
822
+ # also register keys as inputs
823
+ self.input(node, node.keys)
824
+ return super().visit_output(node, parent)
825
+
826
+
827
+ def visit_construct(self, node: ir.Construct, parent: Optional[ir.Node]):
828
+ # values are inputs, id_var is an output
829
+ for v in helpers.vars(node.values):
830
+ self.input(node, v)
831
+ self.output(node, node.id_var)
832
+
833
+
834
+ def visit_aggregate(self, node: ir.Aggregate, parent: Optional[ir.Node]):
835
+ # register projection and group as inputs
836
+ for v in node.projection:
837
+ self.input(node, v)
838
+ for v in node.group:
839
+ self.input(node, v)
840
+
841
+ # register variables depending on the input flag of the aggregation relation
842
+ for idx, f in enumerate(node.aggregation.fields):
843
+ arg = node.args[idx]
844
+ if isinstance(arg, ir.Var):
845
+ if f.input:
846
+ self.input(node, arg)
847
+ else:
848
+ self.output(node, arg)
849
+ return super().visit_aggregate(node, parent)
850
+
851
+
852
+ def visit_rank(self, node: ir.Rank, parent: Optional[ir.Node]):
853
+ # register projection and group as inputs
854
+ for v in node.projection:
855
+ self.input(node, v)
856
+ for v in node.group:
857
+ self.input(node, v)
858
+ for v in node.args:
859
+ self.input(node, v)
860
+
861
+ self.output(node, node.result)
862
+ return super().visit_rank(node, parent)