relationalai 0.13.0.dev0__py3-none-any.whl → 0.13.1__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 (837) hide show
  1. frontend/debugger/dist/.gitignore +2 -0
  2. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  3. frontend/debugger/dist/assets/index-Cssla-O7.js +208 -0
  4. frontend/debugger/dist/assets/index-DlHsYx1V.css +9 -0
  5. frontend/debugger/dist/index.html +17 -0
  6. relationalai/__init__.py +256 -1
  7. relationalai/clients/__init__.py +18 -0
  8. relationalai/clients/client.py +912 -0
  9. relationalai/clients/config.py +673 -0
  10. relationalai/clients/direct_access_client.py +118 -0
  11. relationalai/clients/exec_txn_poller.py +91 -0
  12. relationalai/clients/hash_util.py +31 -0
  13. relationalai/clients/local.py +571 -0
  14. relationalai/clients/profile_polling.py +73 -0
  15. relationalai/clients/resources/__init__.py +8 -0
  16. relationalai/clients/resources/azure/azure.py +477 -0
  17. relationalai/clients/resources/snowflake/__init__.py +20 -0
  18. relationalai/clients/resources/snowflake/cli_resources.py +87 -0
  19. relationalai/clients/resources/snowflake/direct_access_resources.py +694 -0
  20. relationalai/clients/resources/snowflake/engine_state_handlers.py +309 -0
  21. relationalai/clients/resources/snowflake/error_handlers.py +199 -0
  22. relationalai/clients/resources/snowflake/export_procedure.py.jinja +249 -0
  23. relationalai/clients/resources/snowflake/resources_factory.py +99 -0
  24. relationalai/clients/resources/snowflake/snowflake.py +3190 -0
  25. relationalai/clients/resources/snowflake/use_index_poller.py +1019 -0
  26. relationalai/clients/resources/snowflake/use_index_resources.py +188 -0
  27. relationalai/clients/resources/snowflake/util.py +387 -0
  28. relationalai/clients/result_helpers.py +420 -0
  29. relationalai/clients/types.py +113 -0
  30. relationalai/clients/util.py +356 -0
  31. relationalai/debugging.py +389 -0
  32. relationalai/dsl.py +1749 -0
  33. relationalai/early_access/builder/__init__.py +30 -0
  34. relationalai/early_access/builder/builder/__init__.py +35 -0
  35. relationalai/early_access/builder/snowflake/__init__.py +12 -0
  36. relationalai/early_access/builder/std/__init__.py +25 -0
  37. relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  38. relationalai/early_access/builder/std/integers/__init__.py +12 -0
  39. relationalai/early_access/builder/std/math/__init__.py +12 -0
  40. relationalai/early_access/builder/std/strings/__init__.py +14 -0
  41. relationalai/early_access/devtools/__init__.py +12 -0
  42. relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  43. relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  44. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  45. relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  46. relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  47. relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  48. relationalai/early_access/dsl/bindings/common.py +402 -0
  49. relationalai/early_access/dsl/bindings/csv.py +170 -0
  50. relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  51. relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  52. relationalai/early_access/dsl/codegen/binder.py +411 -0
  53. relationalai/early_access/dsl/codegen/common.py +79 -0
  54. relationalai/early_access/dsl/codegen/helpers.py +23 -0
  55. relationalai/early_access/dsl/codegen/relations.py +700 -0
  56. relationalai/early_access/dsl/codegen/weaver.py +417 -0
  57. relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  58. relationalai/early_access/dsl/core/builders/logic.py +19 -0
  59. relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  60. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  61. relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  62. relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  63. relationalai/early_access/dsl/core/context.py +13 -0
  64. relationalai/early_access/dsl/core/cset.py +132 -0
  65. relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  66. relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  67. relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  68. relationalai/early_access/dsl/core/instances.py +44 -0
  69. relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  70. relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  71. relationalai/early_access/dsl/core/logic/exists.py +223 -0
  72. relationalai/early_access/dsl/core/logic/helper.py +163 -0
  73. relationalai/early_access/dsl/core/namespaces.py +32 -0
  74. relationalai/early_access/dsl/core/relations.py +276 -0
  75. relationalai/early_access/dsl/core/rules.py +112 -0
  76. relationalai/early_access/dsl/core/std/__init__.py +45 -0
  77. relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  78. relationalai/early_access/dsl/core/types/__init__.py +270 -0
  79. relationalai/early_access/dsl/core/types/concepts.py +128 -0
  80. relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  81. relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  82. relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  83. relationalai/early_access/dsl/core/types/standard.py +92 -0
  84. relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  85. relationalai/early_access/dsl/core/types/variables.py +203 -0
  86. relationalai/early_access/dsl/ir/compiler.py +318 -0
  87. relationalai/early_access/dsl/ir/executor.py +260 -0
  88. relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  89. relationalai/early_access/dsl/ontologies/export.py +30 -0
  90. relationalai/early_access/dsl/ontologies/models.py +453 -0
  91. relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  92. relationalai/early_access/dsl/ontologies/readings.py +60 -0
  93. relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  94. relationalai/early_access/dsl/ontologies/roles.py +87 -0
  95. relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  96. relationalai/early_access/dsl/orm/constraints.py +438 -0
  97. relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  98. relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  99. relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  100. relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  101. relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  102. relationalai/early_access/dsl/orm/models.py +256 -0
  103. relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  104. relationalai/early_access/dsl/orm/printer.py +469 -0
  105. relationalai/early_access/dsl/orm/reasoners.py +480 -0
  106. relationalai/early_access/dsl/orm/relations.py +19 -0
  107. relationalai/early_access/dsl/orm/relationships.py +251 -0
  108. relationalai/early_access/dsl/orm/types.py +42 -0
  109. relationalai/early_access/dsl/orm/utils.py +79 -0
  110. relationalai/early_access/dsl/orm/verb.py +204 -0
  111. relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  112. relationalai/early_access/dsl/relations.py +170 -0
  113. relationalai/early_access/dsl/rulesets.py +69 -0
  114. relationalai/early_access/dsl/schemas/__init__.py +450 -0
  115. relationalai/early_access/dsl/schemas/builder.py +48 -0
  116. relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  117. relationalai/early_access/dsl/schemas/components.py +203 -0
  118. relationalai/early_access/dsl/schemas/contexts.py +156 -0
  119. relationalai/early_access/dsl/schemas/exprs.py +89 -0
  120. relationalai/early_access/dsl/schemas/fragments.py +464 -0
  121. relationalai/early_access/dsl/serialization.py +79 -0
  122. relationalai/early_access/dsl/serialize/exporter.py +163 -0
  123. relationalai/early_access/dsl/snow/api.py +105 -0
  124. relationalai/early_access/dsl/snow/common.py +76 -0
  125. relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  126. relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  127. relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  128. relationalai/early_access/dsl/types/__init__.py +40 -0
  129. relationalai/early_access/dsl/types/concepts.py +12 -0
  130. relationalai/early_access/dsl/types/entities.py +135 -0
  131. relationalai/early_access/dsl/types/values.py +17 -0
  132. relationalai/early_access/dsl/utils.py +102 -0
  133. relationalai/early_access/graphs/__init__.py +13 -0
  134. relationalai/early_access/lqp/__init__.py +12 -0
  135. relationalai/early_access/lqp/compiler/__init__.py +12 -0
  136. relationalai/early_access/lqp/constructors/__init__.py +18 -0
  137. relationalai/early_access/lqp/executor/__init__.py +12 -0
  138. relationalai/early_access/lqp/ir/__init__.py +12 -0
  139. relationalai/early_access/lqp/passes/__init__.py +12 -0
  140. relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  141. relationalai/early_access/lqp/primitives/__init__.py +12 -0
  142. relationalai/early_access/lqp/types/__init__.py +12 -0
  143. relationalai/early_access/lqp/utils/__init__.py +12 -0
  144. relationalai/early_access/lqp/validators/__init__.py +12 -0
  145. relationalai/early_access/metamodel/__init__.py +58 -0
  146. relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  147. relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  148. relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  149. relationalai/early_access/metamodel/factory/__init__.py +17 -0
  150. relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  151. relationalai/early_access/metamodel/ir/__init__.py +14 -0
  152. relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  153. relationalai/early_access/metamodel/typer/__init__.py +3 -0
  154. relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  155. relationalai/early_access/metamodel/types/__init__.py +15 -0
  156. relationalai/early_access/metamodel/util/__init__.py +15 -0
  157. relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  158. relationalai/early_access/rel/__init__.py +12 -0
  159. relationalai/early_access/rel/executor/__init__.py +12 -0
  160. relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  161. relationalai/early_access/rel/rewrite/__init__.py +7 -0
  162. relationalai/early_access/solvers/__init__.py +19 -0
  163. relationalai/early_access/sql/__init__.py +11 -0
  164. relationalai/early_access/sql/executor/__init__.py +3 -0
  165. relationalai/early_access/sql/rewrite/__init__.py +3 -0
  166. relationalai/early_access/tests/logging/__init__.py +12 -0
  167. relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  168. relationalai/early_access/tests/utils/__init__.py +12 -0
  169. relationalai/environments/__init__.py +35 -0
  170. relationalai/environments/base.py +381 -0
  171. relationalai/environments/colab.py +14 -0
  172. relationalai/environments/generic.py +71 -0
  173. relationalai/environments/ipython.py +68 -0
  174. relationalai/environments/jupyter.py +9 -0
  175. relationalai/environments/snowbook.py +169 -0
  176. relationalai/errors.py +2496 -0
  177. relationalai/experimental/SF.py +38 -0
  178. relationalai/experimental/inspect.py +47 -0
  179. relationalai/experimental/pathfinder/__init__.py +158 -0
  180. relationalai/experimental/pathfinder/api.py +160 -0
  181. relationalai/experimental/pathfinder/automaton.py +584 -0
  182. relationalai/experimental/pathfinder/bridge.py +226 -0
  183. relationalai/experimental/pathfinder/compiler.py +416 -0
  184. relationalai/experimental/pathfinder/datalog.py +214 -0
  185. relationalai/experimental/pathfinder/diagnostics.py +56 -0
  186. relationalai/experimental/pathfinder/filter.py +236 -0
  187. relationalai/experimental/pathfinder/glushkov.py +439 -0
  188. relationalai/experimental/pathfinder/options.py +265 -0
  189. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +1951 -0
  190. relationalai/experimental/pathfinder/rpq.py +344 -0
  191. relationalai/experimental/pathfinder/transition.py +200 -0
  192. relationalai/experimental/pathfinder/utils.py +26 -0
  193. relationalai/experimental/paths/README.md +107 -0
  194. relationalai/experimental/paths/api.py +143 -0
  195. relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  196. relationalai/experimental/paths/code_organization.md +2 -0
  197. relationalai/experimental/paths/examples/Movies.ipynb +16328 -0
  198. relationalai/experimental/paths/examples/basic_example.py +40 -0
  199. relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  200. relationalai/experimental/paths/examples/movie_example.py +77 -0
  201. relationalai/experimental/paths/examples/movies_data/actedin.csv +193 -0
  202. relationalai/experimental/paths/examples/movies_data/directed.csv +45 -0
  203. relationalai/experimental/paths/examples/movies_data/follows.csv +7 -0
  204. relationalai/experimental/paths/examples/movies_data/movies.csv +39 -0
  205. relationalai/experimental/paths/examples/movies_data/person.csv +134 -0
  206. relationalai/experimental/paths/examples/movies_data/produced.csv +16 -0
  207. relationalai/experimental/paths/examples/movies_data/ratings.csv +10 -0
  208. relationalai/experimental/paths/examples/movies_data/wrote.csv +11 -0
  209. relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  210. relationalai/experimental/paths/examples/paths_example.py +116 -0
  211. relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  212. relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  213. relationalai/experimental/paths/graph.py +185 -0
  214. relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  215. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  216. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  217. relationalai/experimental/paths/path_algorithms/single.py +59 -0
  218. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  219. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  220. relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  221. relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  222. relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  223. relationalai/experimental/paths/product_graph.py +93 -0
  224. relationalai/experimental/paths/rpq/automaton.py +584 -0
  225. relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  226. relationalai/experimental/paths/rpq/rpq.py +378 -0
  227. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  228. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  229. relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  230. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  231. relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  232. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  233. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  234. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  235. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  236. relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  237. relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  238. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  239. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  240. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  241. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  242. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  243. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  244. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  245. relationalai/experimental/paths/tree_agg.py +168 -0
  246. relationalai/experimental/paths/utilities/iterators.py +27 -0
  247. relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  248. relationalai/experimental/solvers.py +1087 -0
  249. relationalai/loaders/csv.py +195 -0
  250. relationalai/loaders/loader.py +177 -0
  251. relationalai/loaders/types.py +23 -0
  252. relationalai/rel_emitter.py +373 -0
  253. relationalai/rel_utils.py +185 -0
  254. relationalai/semantics/__init__.py +22 -146
  255. relationalai/semantics/designs/query_builder/identify_by.md +106 -0
  256. relationalai/semantics/devtools/benchmark_lqp.py +535 -0
  257. relationalai/semantics/devtools/compilation_manager.py +294 -0
  258. relationalai/semantics/devtools/extract_lqp.py +110 -0
  259. relationalai/semantics/internal/internal.py +3785 -0
  260. relationalai/semantics/internal/snowflake.py +325 -0
  261. relationalai/semantics/lqp/README.md +34 -0
  262. relationalai/semantics/lqp/builtins.py +16 -0
  263. relationalai/semantics/lqp/compiler.py +22 -0
  264. relationalai/semantics/lqp/constructors.py +68 -0
  265. relationalai/semantics/lqp/executor.py +469 -0
  266. relationalai/semantics/lqp/intrinsics.py +24 -0
  267. relationalai/semantics/lqp/model2lqp.py +877 -0
  268. relationalai/semantics/lqp/passes.py +680 -0
  269. relationalai/semantics/lqp/primitives.py +252 -0
  270. relationalai/semantics/lqp/result_helpers.py +202 -0
  271. relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  272. relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  273. relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  274. relationalai/semantics/lqp/rewrite/extract_keys.py +512 -0
  275. relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  276. relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  277. relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  278. relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  279. relationalai/semantics/lqp/types.py +101 -0
  280. relationalai/semantics/lqp/utils.py +160 -0
  281. relationalai/semantics/lqp/validators.py +57 -0
  282. relationalai/semantics/metamodel/__init__.py +40 -6
  283. relationalai/semantics/metamodel/builtins.py +771 -205
  284. relationalai/semantics/metamodel/compiler.py +133 -0
  285. relationalai/semantics/metamodel/dependency.py +862 -0
  286. relationalai/semantics/metamodel/executor.py +61 -0
  287. relationalai/semantics/metamodel/factory.py +287 -0
  288. relationalai/semantics/metamodel/helpers.py +361 -0
  289. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  290. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  291. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  292. relationalai/semantics/metamodel/rewrite/flatten.py +554 -0
  293. relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  294. relationalai/semantics/metamodel/typer/checker.py +353 -0
  295. relationalai/semantics/metamodel/typer/typer.py +1395 -0
  296. relationalai/semantics/metamodel/util.py +506 -0
  297. relationalai/semantics/reasoners/__init__.py +10 -0
  298. relationalai/semantics/reasoners/graph/README.md +620 -0
  299. relationalai/semantics/reasoners/graph/__init__.py +37 -0
  300. relationalai/semantics/reasoners/graph/core.py +9019 -0
  301. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +797 -0
  302. relationalai/semantics/reasoners/graph/tests/README.md +21 -0
  303. relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  304. relationalai/semantics/reasoners/optimization/common.py +88 -0
  305. relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  306. relationalai/semantics/reasoners/optimization/solvers_pb.py +1414 -0
  307. relationalai/semantics/rel/builtins.py +40 -0
  308. relationalai/semantics/rel/compiler.py +989 -0
  309. relationalai/semantics/rel/executor.py +362 -0
  310. relationalai/semantics/rel/rel.py +482 -0
  311. relationalai/semantics/rel/rel_utils.py +276 -0
  312. relationalai/semantics/snowflake/__init__.py +3 -0
  313. relationalai/semantics/sql/compiler.py +2503 -0
  314. relationalai/semantics/sql/executor/duck_db.py +52 -0
  315. relationalai/semantics/sql/executor/result_helpers.py +64 -0
  316. relationalai/semantics/sql/executor/snowflake.py +149 -0
  317. relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  318. relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  319. relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  320. relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  321. relationalai/semantics/sql/sql.py +504 -0
  322. relationalai/semantics/std/__init__.py +40 -60
  323. relationalai/semantics/std/constraints.py +43 -37
  324. relationalai/semantics/std/datetime.py +135 -246
  325. relationalai/semantics/std/decimals.py +52 -45
  326. relationalai/semantics/std/floats.py +5 -13
  327. relationalai/semantics/std/integers.py +11 -26
  328. relationalai/semantics/std/math.py +112 -183
  329. relationalai/semantics/std/pragmas.py +11 -0
  330. relationalai/semantics/std/re.py +62 -80
  331. relationalai/semantics/std/std.py +14 -0
  332. relationalai/semantics/std/strings.py +60 -117
  333. relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  334. relationalai/semantics/tests/test_snapshot_base.py +9 -0
  335. relationalai/semantics/tests/utils.py +46 -0
  336. relationalai/std/__init__.py +70 -0
  337. relationalai/tools/cli.py +1936 -0
  338. relationalai/tools/cli_controls.py +1826 -0
  339. relationalai/tools/cli_helpers.py +398 -0
  340. relationalai/tools/debugger.py +183 -289
  341. relationalai/tools/debugger_client.py +109 -0
  342. relationalai/tools/debugger_server.py +302 -0
  343. relationalai/tools/dev.py +685 -0
  344. relationalai/tools/notes +7 -0
  345. relationalai/tools/qb_debugger.py +425 -0
  346. relationalai/util/clean_up_databases.py +95 -0
  347. relationalai/util/format.py +106 -48
  348. relationalai/util/list_databases.py +9 -0
  349. relationalai/util/otel_configuration.py +26 -0
  350. relationalai/util/otel_handler.py +484 -0
  351. relationalai/util/snowflake_handler.py +88 -0
  352. relationalai/util/span_format_test.py +43 -0
  353. relationalai/util/span_tracker.py +207 -0
  354. relationalai/util/spans_file_handler.py +72 -0
  355. relationalai/util/tracing_handler.py +34 -0
  356. relationalai-0.13.1.dist-info/METADATA +74 -0
  357. relationalai-0.13.1.dist-info/RECORD +459 -0
  358. relationalai-0.13.1.dist-info/WHEEL +4 -0
  359. relationalai-0.13.1.dist-info/entry_points.txt +3 -0
  360. relationalai-0.13.1.dist-info/licenses/LICENSE +202 -0
  361. relationalai_test_util/__init__.py +4 -0
  362. relationalai_test_util/fixtures.py +233 -0
  363. relationalai_test_util/snapshot.py +252 -0
  364. relationalai_test_util/traceback.py +118 -0
  365. relationalai/config/__init__.py +0 -56
  366. relationalai/config/config.py +0 -289
  367. relationalai/config/config_fields.py +0 -86
  368. relationalai/config/connections/__init__.py +0 -46
  369. relationalai/config/connections/base.py +0 -23
  370. relationalai/config/connections/duckdb.py +0 -29
  371. relationalai/config/connections/snowflake.py +0 -243
  372. relationalai/config/external/__init__.py +0 -17
  373. relationalai/config/external/dbt_converter.py +0 -101
  374. relationalai/config/external/dbt_models.py +0 -93
  375. relationalai/config/external/snowflake_converter.py +0 -41
  376. relationalai/config/external/snowflake_models.py +0 -85
  377. relationalai/config/external/utils.py +0 -19
  378. relationalai/semantics/backends/lqp/annotations.py +0 -11
  379. relationalai/semantics/backends/sql/sql_compiler.py +0 -327
  380. relationalai/semantics/frontend/base.py +0 -1707
  381. relationalai/semantics/frontend/core.py +0 -179
  382. relationalai/semantics/frontend/front_compiler.py +0 -1313
  383. relationalai/semantics/frontend/pprint.py +0 -408
  384. relationalai/semantics/metamodel/metamodel.py +0 -437
  385. relationalai/semantics/metamodel/metamodel_analyzer.py +0 -519
  386. relationalai/semantics/metamodel/metamodel_compiler.py +0 -0
  387. relationalai/semantics/metamodel/pprint.py +0 -412
  388. relationalai/semantics/metamodel/rewriter.py +0 -266
  389. relationalai/semantics/metamodel/typer.py +0 -1378
  390. relationalai/semantics/std/aggregates.py +0 -149
  391. relationalai/semantics/std/common.py +0 -44
  392. relationalai/semantics/std/numbers.py +0 -86
  393. relationalai/shims/executor.py +0 -147
  394. relationalai/shims/helpers.py +0 -126
  395. relationalai/shims/hoister.py +0 -221
  396. relationalai/shims/mm2v0.py +0 -1290
  397. relationalai/tools/cli/__init__.py +0 -6
  398. relationalai/tools/cli/cli.py +0 -90
  399. relationalai/tools/cli/components/__init__.py +0 -5
  400. relationalai/tools/cli/components/progress_reader.py +0 -1524
  401. relationalai/tools/cli/components/utils.py +0 -58
  402. relationalai/tools/cli/config_template.py +0 -45
  403. relationalai/tools/cli/dev.py +0 -19
  404. relationalai/tools/typer_debugger.py +0 -93
  405. relationalai/util/dataclasses.py +0 -43
  406. relationalai/util/docutils.py +0 -40
  407. relationalai/util/error.py +0 -199
  408. relationalai/util/naming.py +0 -145
  409. relationalai/util/python.py +0 -35
  410. relationalai/util/runtime.py +0 -156
  411. relationalai/util/schema.py +0 -197
  412. relationalai/util/source.py +0 -185
  413. relationalai/util/structures.py +0 -163
  414. relationalai/util/tracing.py +0 -261
  415. relationalai-0.13.0.dev0.dist-info/METADATA +0 -46
  416. relationalai-0.13.0.dev0.dist-info/RECORD +0 -488
  417. relationalai-0.13.0.dev0.dist-info/WHEEL +0 -5
  418. relationalai-0.13.0.dev0.dist-info/entry_points.txt +0 -3
  419. relationalai-0.13.0.dev0.dist-info/top_level.txt +0 -2
  420. v0/relationalai/__init__.py +0 -216
  421. v0/relationalai/clients/__init__.py +0 -5
  422. v0/relationalai/clients/azure.py +0 -477
  423. v0/relationalai/clients/client.py +0 -912
  424. v0/relationalai/clients/config.py +0 -673
  425. v0/relationalai/clients/direct_access_client.py +0 -118
  426. v0/relationalai/clients/hash_util.py +0 -31
  427. v0/relationalai/clients/local.py +0 -571
  428. v0/relationalai/clients/profile_polling.py +0 -73
  429. v0/relationalai/clients/result_helpers.py +0 -420
  430. v0/relationalai/clients/snowflake.py +0 -3869
  431. v0/relationalai/clients/types.py +0 -113
  432. v0/relationalai/clients/use_index_poller.py +0 -980
  433. v0/relationalai/clients/util.py +0 -356
  434. v0/relationalai/debugging.py +0 -389
  435. v0/relationalai/dsl.py +0 -1749
  436. v0/relationalai/early_access/builder/__init__.py +0 -30
  437. v0/relationalai/early_access/builder/builder/__init__.py +0 -35
  438. v0/relationalai/early_access/builder/snowflake/__init__.py +0 -12
  439. v0/relationalai/early_access/builder/std/__init__.py +0 -25
  440. v0/relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  441. v0/relationalai/early_access/builder/std/integers/__init__.py +0 -12
  442. v0/relationalai/early_access/builder/std/math/__init__.py +0 -12
  443. v0/relationalai/early_access/builder/std/strings/__init__.py +0 -14
  444. v0/relationalai/early_access/devtools/__init__.py +0 -12
  445. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  446. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  447. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  448. v0/relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  449. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  450. v0/relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  451. v0/relationalai/early_access/dsl/bindings/common.py +0 -402
  452. v0/relationalai/early_access/dsl/bindings/csv.py +0 -170
  453. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  454. v0/relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  455. v0/relationalai/early_access/dsl/codegen/binder.py +0 -411
  456. v0/relationalai/early_access/dsl/codegen/common.py +0 -79
  457. v0/relationalai/early_access/dsl/codegen/helpers.py +0 -23
  458. v0/relationalai/early_access/dsl/codegen/relations.py +0 -700
  459. v0/relationalai/early_access/dsl/codegen/weaver.py +0 -417
  460. v0/relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  461. v0/relationalai/early_access/dsl/core/builders/logic.py +0 -19
  462. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  463. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  464. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  465. v0/relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  466. v0/relationalai/early_access/dsl/core/context.py +0 -13
  467. v0/relationalai/early_access/dsl/core/cset.py +0 -132
  468. v0/relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  469. v0/relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  470. v0/relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  471. v0/relationalai/early_access/dsl/core/instances.py +0 -44
  472. v0/relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  473. v0/relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  474. v0/relationalai/early_access/dsl/core/logic/exists.py +0 -223
  475. v0/relationalai/early_access/dsl/core/logic/helper.py +0 -163
  476. v0/relationalai/early_access/dsl/core/namespaces.py +0 -32
  477. v0/relationalai/early_access/dsl/core/relations.py +0 -276
  478. v0/relationalai/early_access/dsl/core/rules.py +0 -112
  479. v0/relationalai/early_access/dsl/core/std/__init__.py +0 -45
  480. v0/relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  481. v0/relationalai/early_access/dsl/core/types/__init__.py +0 -270
  482. v0/relationalai/early_access/dsl/core/types/concepts.py +0 -128
  483. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  484. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  485. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  486. v0/relationalai/early_access/dsl/core/types/standard.py +0 -92
  487. v0/relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  488. v0/relationalai/early_access/dsl/core/types/variables.py +0 -203
  489. v0/relationalai/early_access/dsl/ir/compiler.py +0 -318
  490. v0/relationalai/early_access/dsl/ir/executor.py +0 -260
  491. v0/relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  492. v0/relationalai/early_access/dsl/ontologies/export.py +0 -30
  493. v0/relationalai/early_access/dsl/ontologies/models.py +0 -453
  494. v0/relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  495. v0/relationalai/early_access/dsl/ontologies/readings.py +0 -60
  496. v0/relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  497. v0/relationalai/early_access/dsl/ontologies/roles.py +0 -87
  498. v0/relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  499. v0/relationalai/early_access/dsl/orm/constraints.py +0 -438
  500. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  501. v0/relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  502. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  503. v0/relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  504. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  505. v0/relationalai/early_access/dsl/orm/models.py +0 -256
  506. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  507. v0/relationalai/early_access/dsl/orm/printer.py +0 -469
  508. v0/relationalai/early_access/dsl/orm/reasoners.py +0 -480
  509. v0/relationalai/early_access/dsl/orm/relations.py +0 -19
  510. v0/relationalai/early_access/dsl/orm/relationships.py +0 -251
  511. v0/relationalai/early_access/dsl/orm/types.py +0 -42
  512. v0/relationalai/early_access/dsl/orm/utils.py +0 -79
  513. v0/relationalai/early_access/dsl/orm/verb.py +0 -204
  514. v0/relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  515. v0/relationalai/early_access/dsl/relations.py +0 -170
  516. v0/relationalai/early_access/dsl/rulesets.py +0 -69
  517. v0/relationalai/early_access/dsl/schemas/__init__.py +0 -450
  518. v0/relationalai/early_access/dsl/schemas/builder.py +0 -48
  519. v0/relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  520. v0/relationalai/early_access/dsl/schemas/components.py +0 -203
  521. v0/relationalai/early_access/dsl/schemas/contexts.py +0 -156
  522. v0/relationalai/early_access/dsl/schemas/exprs.py +0 -89
  523. v0/relationalai/early_access/dsl/schemas/fragments.py +0 -464
  524. v0/relationalai/early_access/dsl/serialization.py +0 -79
  525. v0/relationalai/early_access/dsl/serialize/exporter.py +0 -163
  526. v0/relationalai/early_access/dsl/snow/api.py +0 -104
  527. v0/relationalai/early_access/dsl/snow/common.py +0 -76
  528. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  529. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  530. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  531. v0/relationalai/early_access/dsl/types/__init__.py +0 -40
  532. v0/relationalai/early_access/dsl/types/concepts.py +0 -12
  533. v0/relationalai/early_access/dsl/types/entities.py +0 -135
  534. v0/relationalai/early_access/dsl/types/values.py +0 -17
  535. v0/relationalai/early_access/dsl/utils.py +0 -102
  536. v0/relationalai/early_access/graphs/__init__.py +0 -13
  537. v0/relationalai/early_access/lqp/__init__.py +0 -12
  538. v0/relationalai/early_access/lqp/compiler/__init__.py +0 -12
  539. v0/relationalai/early_access/lqp/constructors/__init__.py +0 -18
  540. v0/relationalai/early_access/lqp/executor/__init__.py +0 -12
  541. v0/relationalai/early_access/lqp/ir/__init__.py +0 -12
  542. v0/relationalai/early_access/lqp/passes/__init__.py +0 -12
  543. v0/relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  544. v0/relationalai/early_access/lqp/primitives/__init__.py +0 -12
  545. v0/relationalai/early_access/lqp/types/__init__.py +0 -12
  546. v0/relationalai/early_access/lqp/utils/__init__.py +0 -12
  547. v0/relationalai/early_access/lqp/validators/__init__.py +0 -12
  548. v0/relationalai/early_access/metamodel/__init__.py +0 -58
  549. v0/relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  550. v0/relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  551. v0/relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  552. v0/relationalai/early_access/metamodel/factory/__init__.py +0 -17
  553. v0/relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  554. v0/relationalai/early_access/metamodel/ir/__init__.py +0 -14
  555. v0/relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  556. v0/relationalai/early_access/metamodel/typer/__init__.py +0 -3
  557. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  558. v0/relationalai/early_access/metamodel/types/__init__.py +0 -15
  559. v0/relationalai/early_access/metamodel/util/__init__.py +0 -15
  560. v0/relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  561. v0/relationalai/early_access/rel/__init__.py +0 -12
  562. v0/relationalai/early_access/rel/executor/__init__.py +0 -12
  563. v0/relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  564. v0/relationalai/early_access/rel/rewrite/__init__.py +0 -7
  565. v0/relationalai/early_access/solvers/__init__.py +0 -19
  566. v0/relationalai/early_access/sql/__init__.py +0 -11
  567. v0/relationalai/early_access/sql/executor/__init__.py +0 -3
  568. v0/relationalai/early_access/sql/rewrite/__init__.py +0 -3
  569. v0/relationalai/early_access/tests/logging/__init__.py +0 -12
  570. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  571. v0/relationalai/early_access/tests/utils/__init__.py +0 -12
  572. v0/relationalai/environments/__init__.py +0 -35
  573. v0/relationalai/environments/base.py +0 -381
  574. v0/relationalai/environments/colab.py +0 -14
  575. v0/relationalai/environments/generic.py +0 -71
  576. v0/relationalai/environments/ipython.py +0 -68
  577. v0/relationalai/environments/jupyter.py +0 -9
  578. v0/relationalai/environments/snowbook.py +0 -169
  579. v0/relationalai/errors.py +0 -2455
  580. v0/relationalai/experimental/SF.py +0 -38
  581. v0/relationalai/experimental/inspect.py +0 -47
  582. v0/relationalai/experimental/pathfinder/__init__.py +0 -158
  583. v0/relationalai/experimental/pathfinder/api.py +0 -160
  584. v0/relationalai/experimental/pathfinder/automaton.py +0 -584
  585. v0/relationalai/experimental/pathfinder/bridge.py +0 -226
  586. v0/relationalai/experimental/pathfinder/compiler.py +0 -416
  587. v0/relationalai/experimental/pathfinder/datalog.py +0 -214
  588. v0/relationalai/experimental/pathfinder/diagnostics.py +0 -56
  589. v0/relationalai/experimental/pathfinder/filter.py +0 -236
  590. v0/relationalai/experimental/pathfinder/glushkov.py +0 -439
  591. v0/relationalai/experimental/pathfinder/options.py +0 -265
  592. v0/relationalai/experimental/pathfinder/rpq.py +0 -344
  593. v0/relationalai/experimental/pathfinder/transition.py +0 -200
  594. v0/relationalai/experimental/pathfinder/utils.py +0 -26
  595. v0/relationalai/experimental/paths/api.py +0 -143
  596. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  597. v0/relationalai/experimental/paths/examples/basic_example.py +0 -40
  598. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  599. v0/relationalai/experimental/paths/examples/movie_example.py +0 -77
  600. v0/relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  601. v0/relationalai/experimental/paths/examples/paths_example.py +0 -116
  602. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  603. v0/relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  604. v0/relationalai/experimental/paths/graph.py +0 -185
  605. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  606. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  607. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  608. v0/relationalai/experimental/paths/path_algorithms/single.py +0 -59
  609. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  610. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  611. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  612. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  613. v0/relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  614. v0/relationalai/experimental/paths/product_graph.py +0 -93
  615. v0/relationalai/experimental/paths/rpq/automaton.py +0 -584
  616. v0/relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  617. v0/relationalai/experimental/paths/rpq/rpq.py +0 -378
  618. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  619. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  620. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  621. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  622. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  623. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  624. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  625. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  626. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  627. v0/relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  628. v0/relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  629. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  630. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  631. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  632. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  633. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  634. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  635. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  636. v0/relationalai/experimental/paths/tree_agg.py +0 -168
  637. v0/relationalai/experimental/paths/utilities/iterators.py +0 -27
  638. v0/relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  639. v0/relationalai/experimental/solvers.py +0 -1087
  640. v0/relationalai/loaders/csv.py +0 -195
  641. v0/relationalai/loaders/loader.py +0 -177
  642. v0/relationalai/loaders/types.py +0 -23
  643. v0/relationalai/rel_emitter.py +0 -373
  644. v0/relationalai/rel_utils.py +0 -185
  645. v0/relationalai/semantics/__init__.py +0 -29
  646. v0/relationalai/semantics/devtools/benchmark_lqp.py +0 -536
  647. v0/relationalai/semantics/devtools/compilation_manager.py +0 -294
  648. v0/relationalai/semantics/devtools/extract_lqp.py +0 -110
  649. v0/relationalai/semantics/internal/internal.py +0 -3785
  650. v0/relationalai/semantics/internal/snowflake.py +0 -324
  651. v0/relationalai/semantics/lqp/builtins.py +0 -16
  652. v0/relationalai/semantics/lqp/compiler.py +0 -22
  653. v0/relationalai/semantics/lqp/constructors.py +0 -68
  654. v0/relationalai/semantics/lqp/executor.py +0 -469
  655. v0/relationalai/semantics/lqp/intrinsics.py +0 -24
  656. v0/relationalai/semantics/lqp/model2lqp.py +0 -839
  657. v0/relationalai/semantics/lqp/passes.py +0 -680
  658. v0/relationalai/semantics/lqp/primitives.py +0 -252
  659. v0/relationalai/semantics/lqp/result_helpers.py +0 -202
  660. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  661. v0/relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  662. v0/relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  663. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +0 -449
  664. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  665. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  666. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  667. v0/relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  668. v0/relationalai/semantics/lqp/types.py +0 -101
  669. v0/relationalai/semantics/lqp/utils.py +0 -160
  670. v0/relationalai/semantics/lqp/validators.py +0 -57
  671. v0/relationalai/semantics/metamodel/__init__.py +0 -40
  672. v0/relationalai/semantics/metamodel/builtins.py +0 -774
  673. v0/relationalai/semantics/metamodel/compiler.py +0 -133
  674. v0/relationalai/semantics/metamodel/dependency.py +0 -862
  675. v0/relationalai/semantics/metamodel/executor.py +0 -61
  676. v0/relationalai/semantics/metamodel/factory.py +0 -287
  677. v0/relationalai/semantics/metamodel/helpers.py +0 -361
  678. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  679. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  680. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  681. v0/relationalai/semantics/metamodel/rewrite/flatten.py +0 -549
  682. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  683. v0/relationalai/semantics/metamodel/typer/checker.py +0 -353
  684. v0/relationalai/semantics/metamodel/typer/typer.py +0 -1395
  685. v0/relationalai/semantics/metamodel/util.py +0 -505
  686. v0/relationalai/semantics/reasoners/__init__.py +0 -10
  687. v0/relationalai/semantics/reasoners/graph/__init__.py +0 -37
  688. v0/relationalai/semantics/reasoners/graph/core.py +0 -9020
  689. v0/relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  690. v0/relationalai/semantics/reasoners/optimization/common.py +0 -88
  691. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  692. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  693. v0/relationalai/semantics/rel/builtins.py +0 -40
  694. v0/relationalai/semantics/rel/compiler.py +0 -989
  695. v0/relationalai/semantics/rel/executor.py +0 -359
  696. v0/relationalai/semantics/rel/rel.py +0 -482
  697. v0/relationalai/semantics/rel/rel_utils.py +0 -276
  698. v0/relationalai/semantics/snowflake/__init__.py +0 -3
  699. v0/relationalai/semantics/sql/compiler.py +0 -2503
  700. v0/relationalai/semantics/sql/executor/duck_db.py +0 -52
  701. v0/relationalai/semantics/sql/executor/result_helpers.py +0 -64
  702. v0/relationalai/semantics/sql/executor/snowflake.py +0 -145
  703. v0/relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  704. v0/relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  705. v0/relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  706. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  707. v0/relationalai/semantics/sql/sql.py +0 -504
  708. v0/relationalai/semantics/std/__init__.py +0 -54
  709. v0/relationalai/semantics/std/constraints.py +0 -43
  710. v0/relationalai/semantics/std/datetime.py +0 -363
  711. v0/relationalai/semantics/std/decimals.py +0 -62
  712. v0/relationalai/semantics/std/floats.py +0 -7
  713. v0/relationalai/semantics/std/integers.py +0 -22
  714. v0/relationalai/semantics/std/math.py +0 -141
  715. v0/relationalai/semantics/std/pragmas.py +0 -11
  716. v0/relationalai/semantics/std/re.py +0 -83
  717. v0/relationalai/semantics/std/std.py +0 -14
  718. v0/relationalai/semantics/std/strings.py +0 -63
  719. v0/relationalai/semantics/tests/__init__.py +0 -0
  720. v0/relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  721. v0/relationalai/semantics/tests/test_snapshot_base.py +0 -9
  722. v0/relationalai/semantics/tests/utils.py +0 -46
  723. v0/relationalai/std/__init__.py +0 -70
  724. v0/relationalai/tools/__init__.py +0 -0
  725. v0/relationalai/tools/cli.py +0 -1940
  726. v0/relationalai/tools/cli_controls.py +0 -1826
  727. v0/relationalai/tools/cli_helpers.py +0 -390
  728. v0/relationalai/tools/debugger.py +0 -183
  729. v0/relationalai/tools/debugger_client.py +0 -109
  730. v0/relationalai/tools/debugger_server.py +0 -302
  731. v0/relationalai/tools/dev.py +0 -685
  732. v0/relationalai/tools/qb_debugger.py +0 -425
  733. v0/relationalai/util/clean_up_databases.py +0 -95
  734. v0/relationalai/util/format.py +0 -123
  735. v0/relationalai/util/list_databases.py +0 -9
  736. v0/relationalai/util/otel_configuration.py +0 -25
  737. v0/relationalai/util/otel_handler.py +0 -484
  738. v0/relationalai/util/snowflake_handler.py +0 -88
  739. v0/relationalai/util/span_format_test.py +0 -43
  740. v0/relationalai/util/span_tracker.py +0 -207
  741. v0/relationalai/util/spans_file_handler.py +0 -72
  742. v0/relationalai/util/tracing_handler.py +0 -34
  743. /relationalai/{semantics/frontend → analysis}/__init__.py +0 -0
  744. {v0/relationalai → relationalai}/analysis/mechanistic.py +0 -0
  745. {v0/relationalai → relationalai}/analysis/whynot.py +0 -0
  746. /relationalai/{shims → auth}/__init__.py +0 -0
  747. {v0/relationalai → relationalai}/auth/jwt_generator.py +0 -0
  748. {v0/relationalai → relationalai}/auth/oauth_callback_server.py +0 -0
  749. {v0/relationalai → relationalai}/auth/token_handler.py +0 -0
  750. {v0/relationalai → relationalai}/auth/util.py +0 -0
  751. {v0/relationalai/clients → relationalai/clients/resources/snowflake}/cache_store.py +0 -0
  752. {v0/relationalai → relationalai}/compiler.py +0 -0
  753. {v0/relationalai → relationalai}/dependencies.py +0 -0
  754. {v0/relationalai → relationalai}/docutils.py +0 -0
  755. {v0/relationalai/analysis → relationalai/early_access}/__init__.py +0 -0
  756. {v0/relationalai → relationalai}/early_access/dsl/__init__.py +0 -0
  757. {v0/relationalai/auth → relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  758. {v0/relationalai/early_access → relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  759. {v0/relationalai → relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  760. {v0/relationalai/early_access/dsl/adapters → relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  761. {v0/relationalai → relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  762. {v0/relationalai/early_access/dsl/adapters/orm → relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  763. {v0/relationalai/early_access/dsl/adapters/owl → relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  764. {v0/relationalai/early_access/dsl/bindings → relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  765. {v0/relationalai → relationalai}/early_access/dsl/constants.py +0 -0
  766. {v0/relationalai → relationalai}/early_access/dsl/core/__init__.py +0 -0
  767. {v0/relationalai → relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  768. {v0/relationalai → relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  769. {v0/relationalai → relationalai}/early_access/dsl/core/stack.py +0 -0
  770. {v0/relationalai/early_access/dsl/bindings/legacy → relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  771. {v0/relationalai → relationalai}/early_access/dsl/core/utils.py +0 -0
  772. {v0/relationalai/early_access/dsl/codegen → relationalai/early_access/dsl/ir}/__init__.py +0 -0
  773. {v0/relationalai/early_access/dsl/core/temporal → relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  774. {v0/relationalai → relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  775. {v0/relationalai/early_access/dsl/ir → relationalai/early_access/dsl/orm}/__init__.py +0 -0
  776. {v0/relationalai/early_access/dsl/ontologies → relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  777. {v0/relationalai → relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  778. {v0/relationalai/early_access/dsl/orm → relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  779. {v0/relationalai/early_access/dsl/orm/measures → relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  780. {v0/relationalai → relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  781. {v0/relationalai → relationalai}/early_access/dsl/serialize/model.py +0 -0
  782. {v0/relationalai/early_access/dsl/physical_metadata → relationalai/early_access/dsl/snow}/__init__.py +0 -0
  783. {v0/relationalai → relationalai}/early_access/tests/__init__.py +0 -0
  784. {v0/relationalai → relationalai}/environments/ci.py +0 -0
  785. {v0/relationalai → relationalai}/environments/hex.py +0 -0
  786. {v0/relationalai → relationalai}/environments/terminal.py +0 -0
  787. {v0/relationalai → relationalai}/experimental/__init__.py +0 -0
  788. {v0/relationalai → relationalai}/experimental/graphs.py +0 -0
  789. {v0/relationalai → relationalai}/experimental/paths/__init__.py +0 -0
  790. {v0/relationalai → relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  791. {v0/relationalai → relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  792. {v0/relationalai → relationalai}/experimental/paths/rpq/__init__.py +0 -0
  793. {v0/relationalai → relationalai}/experimental/paths/rpq/filter.py +0 -0
  794. {v0/relationalai → relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  795. {v0/relationalai → relationalai}/experimental/paths/rpq/transition.py +0 -0
  796. {v0/relationalai → relationalai}/experimental/paths/utilities/__init__.py +0 -0
  797. {v0/relationalai → relationalai}/experimental/paths/utilities/utilities.py +0 -0
  798. {v0/relationalai/early_access/dsl/serialize → relationalai/loaders}/__init__.py +0 -0
  799. {v0/relationalai → relationalai}/metagen.py +0 -0
  800. {v0/relationalai → relationalai}/metamodel.py +0 -0
  801. {v0/relationalai → relationalai}/rel.py +0 -0
  802. {v0/relationalai → relationalai}/semantics/devtools/__init__.py +0 -0
  803. {v0/relationalai → relationalai}/semantics/internal/__init__.py +0 -0
  804. {v0/relationalai → relationalai}/semantics/internal/annotations.py +0 -0
  805. {v0/relationalai → relationalai}/semantics/lqp/__init__.py +0 -0
  806. {v0/relationalai → relationalai}/semantics/lqp/ir.py +0 -0
  807. {v0/relationalai → relationalai}/semantics/lqp/pragmas.py +0 -0
  808. {v0/relationalai → relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  809. {v0/relationalai → relationalai}/semantics/metamodel/dataflow.py +0 -0
  810. {v0/relationalai → relationalai}/semantics/metamodel/ir.py +0 -0
  811. {v0/relationalai → relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  812. {v0/relationalai → relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  813. {v0/relationalai → relationalai}/semantics/metamodel/types.py +0 -0
  814. {v0/relationalai → relationalai}/semantics/metamodel/visitor.py +0 -0
  815. {v0/relationalai → relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  816. {v0/relationalai → relationalai}/semantics/rel/__init__.py +0 -0
  817. {v0/relationalai → relationalai}/semantics/sql/__init__.py +0 -0
  818. {v0/relationalai → relationalai}/semantics/sql/executor/__init__.py +0 -0
  819. {v0/relationalai → relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  820. {v0/relationalai/early_access/dsl/snow → relationalai/semantics/tests}/__init__.py +0 -0
  821. {v0/relationalai → relationalai}/semantics/tests/logging.py +0 -0
  822. {v0/relationalai → relationalai}/std/aggregates.py +0 -0
  823. {v0/relationalai → relationalai}/std/dates.py +0 -0
  824. {v0/relationalai → relationalai}/std/graphs.py +0 -0
  825. {v0/relationalai → relationalai}/std/inspect.py +0 -0
  826. {v0/relationalai → relationalai}/std/math.py +0 -0
  827. {v0/relationalai → relationalai}/std/re.py +0 -0
  828. {v0/relationalai → relationalai}/std/strings.py +0 -0
  829. {v0/relationalai/loaders → relationalai/tools}/__init__.py +0 -0
  830. {v0/relationalai → relationalai}/tools/cleanup_snapshots.py +0 -0
  831. {v0/relationalai → relationalai}/tools/constants.py +0 -0
  832. {v0/relationalai → relationalai}/tools/query_utils.py +0 -0
  833. {v0/relationalai → relationalai}/tools/snapshot_viewer.py +0 -0
  834. {v0/relationalai → relationalai}/util/__init__.py +0 -0
  835. {v0/relationalai → relationalai}/util/constants.py +0 -0
  836. {v0/relationalai → relationalai}/util/graph.py +0 -0
  837. {v0/relationalai → relationalai}/util/timeout.py +0 -0
@@ -1,1087 +0,0 @@
1
- from __future__ import annotations
2
- import time
3
- from typing import Any, List, Optional
4
- from dataclasses import dataclass
5
- import textwrap
6
- from .. import dsl, std
7
- from ..std import rel
8
- from ..metamodel import Builtins
9
- from ..tools.cli_controls import Spinner
10
- from ..tools.constants import DEFAULT_QUERY_TIMEOUT_MINS
11
- from .. import debugging
12
- from .. errors import ResponseStatusException
13
- import uuid
14
- import v0.relationalai
15
- import json
16
- from ..clients.util import poll_with_specified_overhead
17
- from ..clients.snowflake import Resources as SnowflakeResources
18
- from ..clients.snowflake import DirectAccessClient, DirectAccessResources
19
- from ..util.timeout import calc_remaining_timeout_minutes
20
-
21
- rel_sv = rel._tagged(Builtins.SingleValued)
22
-
23
- APP_NAME = v0.relationalai.clients.snowflake.APP_NAME
24
-
25
- ENGINE_TYPE_SOLVER = "SOLVER"
26
- # TODO (dba) The ERP still uses `worker` instead of `engine`. Change
27
- # this once we fix this in the ERP.
28
- WORKER_ERRORS = ["worker is suspended", "create/resume", "worker not found", "no workers found", "worker was deleted"]
29
- ENGINE_ERRORS = ["engine is suspended", "create/resume", "engine not found", "no engines found", "engine was deleted"]
30
- ENGINE_NOT_READY_MSGS = ["worker is in pending", "worker is provisioning", "worker is not ready to accept jobs"]
31
-
32
- # --------------------------------------------------
33
- # SolverModel object.
34
- # --------------------------------------------------
35
-
36
- class SolverModel:
37
- def __init__(self, graph:dsl.Graph):
38
- self.graph = graph
39
- self.id = dsl.next_id()
40
- self.scope = f"solvermodel{self.id}_"
41
- scope = self.scope
42
- self.Variable = dsl.Type(graph, "variables", scope=scope)
43
- self.MinObjective = dsl.Type(graph, "min_objectives", scope=scope)
44
- self.MaxObjective = dsl.Type(graph, "max_objectives", scope=scope)
45
- self.Constraint = dsl.Type(graph, "constraints", scope=scope)
46
- self.Solution = dsl.Type(graph, "solutions", scope=scope)
47
- self.components = [
48
- (self.MinObjective, "minimization objectives"),
49
- (self.MaxObjective, "maximization objectives"),
50
- (self.Constraint, "constraints"),
51
- ]
52
- self.solve_index = 0
53
- self.is_solved = False
54
-
55
- # Install model helpers.
56
- self.graph.install_raw(textwrap.dedent(f"""
57
- @inline
58
- def _solverlib_ho_appl(op, {{R}}, s): rel_primitive_solverlib_ho_appl(R, op, s)
59
-
60
- @inline
61
- def _solver_unwrap({{R}}, h, x...): exists((v) | R(v, x...) and pyrel_unwrap(v, h))
62
-
63
- declare {scope}variable_name
64
- declare {scope}component_name
65
- declare {scope}serialized
66
- declare {scope}primal_start
67
-
68
- def {scope}component_string(h, s):
69
- rel_primitive_solverlib_print_expr(
70
- {scope}serialized[h], _solver_unwrap[{scope}variable_name], s
71
- )
72
-
73
- declare {scope}solve_output
74
- """))
75
- return None
76
-
77
- # Add an entity to the variable set, (optionally) set a string name from the
78
- # arguments and add domain constraints on the variable.
79
- def variable(
80
- self,
81
- var, # variable entity
82
- name_args:List|None=None, # list of strings to concatenate into a string name
83
- type:str|None=None, # variable type: "integer" or "zero_one"
84
- lower:int|float|None=None, # lower bound
85
- upper:int|float|None=None, # upper bound
86
- fixed:int|float|None=None, # fixed value
87
- start:int|float|None=None, # (primal) start value
88
- ):
89
- if type not in {"integer", "zero_one", None}:
90
- raise Exception(f"Invalid domain type: {type}.")
91
- var.set(self.Variable)
92
-
93
- # Set variable name.
94
- if name_args:
95
- var.set(**{f"{self.scope}variable_name": make_string(name_args)})
96
-
97
- # Add domain constraints.
98
- cons = []
99
- if fixed is not None:
100
- cons.append(eq(var, fixed))
101
- if type == "zero_one":
102
- cons.append(zero_one(var))
103
- if lower is not None and upper is not None:
104
- if type == "integer":
105
- cons.append(integer_interval(var, lower, upper))
106
- else:
107
- cons.append(interval(var, lower, upper))
108
- else:
109
- if type == "integer":
110
- cons.append(integer(var))
111
- if lower is not None:
112
- cons.append(gte(var, lower))
113
- if upper is not None:
114
- cons.append(lte(var, upper))
115
- if len(cons) == 1:
116
- self.constraint(cons[0])
117
- elif len(cons) > 1:
118
- self.constraint(and_(*cons))
119
-
120
- # Set primal start.
121
- if start is not None:
122
- var.set(**{f"{self.scope}primal_start": start})
123
- return var
124
-
125
- # Get variable string name.
126
- def variable_name(self, var):
127
- return std.alias(getattr(var, f"{self.scope}variable_name"), "name")
128
-
129
- # Add a constraint, minimization objective, or maximization objective.
130
- def constraint(self, expr, name_args:List|None=None):
131
- return self._add_component(self.Constraint, expr, name_args)
132
-
133
- def min_objective(self, expr, name_args:List|None=None):
134
- return self._add_component(self.MinObjective, expr, name_args)
135
-
136
- def max_objective(self, expr, name_args:List|None=None):
137
- return self._add_component(self.MaxObjective, expr, name_args)
138
-
139
- def _add_component(self, typ, expr, name_args:List|None):
140
- comp = typ.add(serialized=_wrap_expr(expr))
141
- if name_args:
142
- comp.set(component_name=make_string(name_args))
143
- return comp
144
-
145
- # Get component string name.
146
- def component_name(self, comp):
147
- return std.alias(comp.component_name, "name")
148
-
149
- # Get serialized component string in human-readable format.
150
- def component_string(self, comp):
151
- return std.alias(comp.component_string, "string")
152
-
153
- # Summarize the model by printing the number of variables and components.
154
- # Use outside a rule/query.
155
- def summarize(self):
156
- with self.graph.query() as select:
157
- vars = select(std.aggregates.count(self.Variable()))
158
- s = f"Model has: {vars.results.iat[0, 0]} variables"
159
- for (c_type, c_name) in self.components:
160
- with self.graph.query() as select:
161
- exprs = select(std.aggregates.count(c_type()))
162
- if not exprs.results.empty:
163
- s += f", {exprs.results.iat[0, 0]} {c_name}"
164
- print(s)
165
- return None
166
-
167
- # Print the model in human-readable format. Use outside a rule/query.
168
- def print(self):
169
- with self.graph.query() as select:
170
- vars = select(rel.last(getattr(rel, f"{self.scope}variable_name")))
171
- print("variables:")
172
- print(vars.results.to_string(index=False, header=False))
173
- for (c_type, c_name) in self.components:
174
- with self.graph.query() as select:
175
- exprs = select(self.component_string(c_type()))
176
- if not exprs.results.empty:
177
- print(c_name + ":")
178
- print(exprs.results.to_string(index=False, header=False))
179
- return None
180
-
181
- # Solve the model given a solver and solver options. Use outside a rule/query.
182
- def solve(self, solver: Solver, log_to_console=True, **kwargs):
183
- self.is_solved = False
184
- self.solve_index += 1
185
- self.solve_output = dsl.RelationNS([f"{self.scope}solve_output"], f"i_{self.solve_index}")
186
-
187
- options = kwargs
188
- options["version"] = 1
189
-
190
- # Validate options.
191
- for k, v in options.items():
192
- if not isinstance(k, str):
193
- raise Exception(f"Invalid parameter key. Expected string, got {type(k)} for {k}.")
194
- if not isinstance(v, (int, float, str, bool)):
195
- raise Exception(
196
- f"Invalid parameter value. Expected string, integer, float, or boolean, got {type(v)} for {k}."
197
- )
198
-
199
- # Run the solve query and insert the solve_output result.
200
- scope = self.scope
201
- variable_name_string = f"{scope}variable_name" if "print_format" in options else "{}"
202
- component_name_string = f"{scope}component_name" if "print_format" in options else "{}"
203
-
204
- input_id = uuid.uuid4()
205
- model_uri = f"snowflake://APP_STATE.RAI_INTERNAL_STAGE/job-inputs/solver/{input_id}/model.binpb"
206
- sf_input_uri = f"snowflake://job-inputs/solver/{input_id}/model.binpb"
207
-
208
- payload: dict[str, Any] = {"solver": solver.solver_name.lower()}
209
- payload["options"] = options
210
- payload["model_uri"] = sf_input_uri
211
-
212
- rai_config = self.graph._config
213
- query_timeout_mins = kwargs.get("query_timeout_mins", None)
214
- if query_timeout_mins is None and (timeout_value := rai_config.get("query_timeout_mins", DEFAULT_QUERY_TIMEOUT_MINS)) is not None:
215
- query_timeout_mins = int(timeout_value)
216
- config_file_path = getattr(rai_config, 'file_path', None)
217
- start_time = time.monotonic()
218
- remaining_timeout_minutes = query_timeout_mins
219
- response = self.graph.exec_raw(
220
- textwrap.dedent(f"""
221
- @inline
222
- def {scope}specialized_components(t, h, s):
223
- exists((v) | {{
224
- (:min_objective, {scope}min_objectives);
225
- (:max_objective, {scope}max_objectives);
226
- (:constraint, {scope}constraints);
227
- }}(t, v) and pyrel_unwrap(v, h) and {scope}serialized(v, s)
228
- )
229
-
230
- @no_diagnostics(:EXPERIMENTAL)
231
- def {scope}model_string {{
232
- rel_primitive_solverlib_model_string[{{
233
- (:variable, _solver_unwrap[{scope}variables]);
234
- {scope}specialized_components;
235
- (:variable_name, _solver_unwrap[{variable_name_string}]);
236
- (:expression_name, _solver_unwrap[{component_name_string}]);
237
- (:primal_start, _solver_unwrap[{scope}primal_start]);
238
- }}]
239
- }}
240
-
241
- ic model_not_empty("Solver model is empty.") requires not empty({scope}model_string)
242
-
243
- def config[:envelope, :content_type]: "application/octet-stream"
244
- def config[:envelope, :payload, :data]: {scope}model_string
245
- def config[:envelope, :payload, :path]: "{model_uri}"
246
- def export {{ config }}
247
- """),
248
- query_timeout_mins=remaining_timeout_minutes,
249
- )
250
- txn = response.transaction or {}
251
- # The above `exec_raw` will throw an error if the transaction
252
- # gets aborted. But in the case it gets cancelled, by the user
253
- # or the system, it won't throw. In that case we also did not
254
- # upload the input model.
255
- if txn["state"] == "":
256
- txn = solver.provider.resources.get_transaction(txn["id"]) or {}
257
- if txn["state"] != "COMPLETED":
258
- raise Exception(f"Transaction that materializes the solver inputs did not complete! ID: `{txn['id']}` State `{txn['state']}`")
259
-
260
- # 2. Execute job and wait for completion.
261
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
262
- start_time, query_timeout_mins, config_file_path=config_file_path
263
- )
264
- job_id = solver._exec_job(payload, log_to_console=log_to_console, query_timeout_mins=remaining_timeout_minutes)
265
-
266
- # 3. Extract result.
267
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
268
- start_time, query_timeout_mins, config_file_path=config_file_path
269
- )
270
- res = self.graph.exec_raw(
271
- textwrap.dedent(f"""
272
- ic result_not_empty("Solver result is empty.") requires not empty(result)
273
-
274
- def result {{load_binary["snowflake://APP_STATE.RAI_INTERNAL_STAGE/job-results/{job_id}/result.binpb"] }}
275
- def delete[:{scope}solve_output, :"i_{self.solve_index}"]: {scope}solve_output[:"i_{self.solve_index}"]
276
-
277
- @no_diagnostics(:EXPERIMENTAL)
278
- def insert[:{scope}solve_output, :"i_{self.solve_index}"]:
279
- rel_primitive_solverlib_extract[result]
280
-
281
- def output[:solver_error]: {scope}solve_output[:"i_{self.solve_index}", :error]
282
- """),
283
- readonly=False,
284
- query_timeout_mins=remaining_timeout_minutes,
285
- )
286
- errors = []
287
- for result in res.results:
288
- if result["relationId"] == "/:output/:solver_error/String":
289
- errors.extend(result["table"]["v1"])
290
-
291
- # 4. Map results to solution.
292
- with self.graph.rule(dynamic=True):
293
- sol = self.Solution.add(index = self.solve_index)
294
- for name in {"error", "termination_status", "solve_time_sec", "objective_value", "solver_version", "printed_model"}:
295
- val = dsl.create_var()
296
- getattr(self.solve_output, name)(val)
297
- sol.set(**{name:val})
298
-
299
- self.is_solved = True
300
-
301
- if len(errors) > 0:
302
- raise Exception("\n".join(errors))
303
-
304
- return None
305
-
306
- # Get scalar result information after solving.
307
- def __getattr__(self, name:str):
308
- if not self.is_solved:
309
- raise Exception("Model has not been solved yet.")
310
- if name in {"error", "termination_status", "solve_time_sec", "objective_value", "solver_version", "printed_model"}:
311
- return getattr(self.Solution(index = self.solve_index), name)
312
- else:
313
- return None
314
-
315
- # Get variable point values after solving. If `index` is specified, get the value
316
- # of the variable in the return the `index`-th solution.
317
- def value(self, var, index:int|None=None):
318
- if not self.is_solved:
319
- raise Exception("Model has not been solved yet.")
320
- val = dsl.create_var()
321
- unwrap_var = rel_sv.pyrel_unwrap(var)
322
- if index:
323
- self.solve_output.points(unwrap_var, index, val)
324
- else:
325
- self.solve_output.point(unwrap_var, val)
326
- std.alias(val, "value")
327
- return val
328
-
329
- # --------------------------------------------------
330
- # Operator definitions
331
- # --------------------------------------------------
332
-
333
- # Builtin binary operators
334
-
335
- def plus(left, right):
336
- return _make_fo_expr(10, left, right)
337
-
338
- def minus(left, right):
339
- return _make_fo_expr(11, left, right)
340
-
341
- def mult(left, right):
342
- return _make_fo_expr(12, left, right)
343
-
344
- def div(left, right):
345
- return _make_fo_expr(13, left, right)
346
-
347
- def pow(left, right):
348
- return _make_fo_expr(14, left, right)
349
-
350
- def eq(left, right):
351
- return _make_fo_expr(30, left, right)
352
-
353
- def neq(left, right):
354
- return _make_fo_expr(31, left, right)
355
-
356
- def lte(left, right):
357
- return _make_fo_expr(32, left, right)
358
-
359
- def gte(left, right):
360
- return _make_fo_expr(33, left, right)
361
-
362
- def lt(left, right):
363
- return _make_fo_expr(34, left, right)
364
-
365
- def gt(left, right):
366
- return _make_fo_expr(35, left, right)
367
-
368
- # First order operators
369
-
370
- def abs(arg):
371
- return _make_fo_expr(20, arg)
372
-
373
- def exp(arg):
374
- return _make_fo_expr(21, arg)
375
-
376
- def log(arg):
377
- return _make_fo_expr(22, arg)
378
-
379
- def integer(arg):
380
- return _make_fo_expr(41, arg)
381
-
382
- def zero_one(arg):
383
- return _make_fo_expr(42, arg)
384
-
385
- def interval(arg, low, high):
386
- return _make_fo_expr(51, low, high, arg)
387
-
388
- def integer_interval(arg, low, high):
389
- return _make_fo_expr(50, low, high, 1, arg)
390
-
391
- def if_then_else(cond, left, right):
392
- return _make_fo_expr(60, cond, left, right)
393
-
394
- def not_(arg):
395
- return _make_fo_expr(61, arg)
396
-
397
- def implies(left, right):
398
- return _make_fo_expr(62, left, right)
399
-
400
- def iff(left, right):
401
- return _make_fo_expr(63, left, right)
402
-
403
- def xor(left, right):
404
- return _make_fo_expr(64, left, right)
405
-
406
- def and_(*args):
407
- return _make_fo_expr(70, *args)
408
-
409
- def or_(*args):
410
- return _make_fo_expr(71, *args)
411
-
412
- # Aggregate operators
413
-
414
- def sum(*args, per=[]) -> Any:
415
- return _make_ho_expr(80, args, per)
416
-
417
- def product(*args, per=[]) -> Any:
418
- return _make_ho_expr(81, args, per)
419
-
420
- def min(*args, per=[]) -> Any:
421
- return _make_ho_expr(82, args, per)
422
-
423
- def max(*args, per=[]) -> Any:
424
- return _make_ho_expr(83, args, per)
425
-
426
- def count(*args, per=[]) -> Any:
427
- return _make_ho_expr(84, args, per)
428
-
429
- def all_different(*args, per=[]) -> Any:
430
- return _make_ho_expr(90, args, per)
431
-
432
- # --------------------------------------------------
433
- # Symbolic expression helpers
434
- # --------------------------------------------------
435
-
436
- def _make_fo_expr(*args):
437
- expr = rel_sv.rel_primitive_solverlib_fo_appl(*args)
438
- expr.__class__ = SolverExpression
439
- return expr
440
-
441
- # TODO(coey) test:
442
- # dsl.tag(rel_sv.rel_primitive_solverlib_fo_appl, Builtins.Expensive)
443
-
444
- def _make_ho_expr(op, args, per):
445
- return SolverExpression(dsl.get_graph(), _ho_appl_def, [args, per, [op]])
446
-
447
- _ho_appl_def = dsl.build.aggregate_def("_solverlib_ho_appl")
448
-
449
- class SolverExpression(dsl.Expression):
450
- def __init__(self, graph, op, args):
451
- super().__init__(graph, op, args)
452
-
453
- def _wrap_expr(e):
454
- # If expression is not known to produce a serialized expression string,
455
- # wrap it with the identity operation just in case
456
- return e if isinstance(e, SolverExpression) else _make_fo_expr(0, e)
457
-
458
- # Symbolic expression context, in which some builtin infix operators are redefined
459
- # TODO(coey) handle comparison chains (e.g. 0 < x < y <= 1) or throw error
460
- class Operators(dsl.Context):
461
- def _supports_binary_op(self, op):
462
- return op in _builtin_binary_map
463
-
464
- def _make_binary_op(self, op, left, right):
465
- return _make_fo_expr(_builtin_binary_map[op], left, right)
466
-
467
- def operators():
468
- return Operators(dsl.get_graph())
469
-
470
- # Maps for Builtins operator to SolverLib operator ID
471
- _builtin_binary_map = {
472
- Builtins.plus: 10,
473
- Builtins.minus: 11,
474
- Builtins.mult: 12,
475
- Builtins.div: 13,
476
- Builtins.pow: 14,
477
- Builtins.approx_eq: 30,
478
- Builtins.neq: 31,
479
- Builtins.lte: 32,
480
- Builtins.gte: 33,
481
- Builtins.lt: 34,
482
- Builtins.gt: 35,
483
- }
484
-
485
- # Concatenate arguments into a string separated by underscores
486
- def make_string(args:List):
487
- string = args[0]
488
- for arg in args[1:]:
489
- string = rel_sv.concat(rel_sv.concat(string, "_"), arg)
490
- return string
491
-
492
-
493
- # --------------------------------------------------
494
- # Solver
495
- # --------------------------------------------------
496
-
497
-
498
- @dataclass
499
- class PollingState:
500
- job_id: str
501
- continuation_token: str
502
- is_done: bool
503
- log_to_console: bool
504
-
505
-
506
- class Solver:
507
- def __init__(
508
- self,
509
- solver_name: str,
510
- engine_name: str | None = None,
511
- engine_size: str | None = None,
512
- auto_suspend_mins: int | None = None,
513
- resources: SnowflakeResources | None = None,
514
- ):
515
- self.provider = Provider(resources=resources)
516
- self.solver_name = solver_name.lower()
517
-
518
- self.rai_config = self.provider.resources.config
519
- settings: dict[str, Any] = {}
520
- if "experimental" in self.rai_config:
521
- exp_config = self.rai_config.get("experimental", {})
522
- if isinstance(exp_config, dict):
523
- if "solvers" in exp_config:
524
- settings = exp_config["solvers"].copy()
525
-
526
- # Engine configuration fields are not necessary for the solver
527
- # settings so we `pop` them from the settings object. Default
528
- # size and auto_suspend_mins are set in the `Provider` methods.
529
- engine_name = engine_name or settings.pop("engine", None)
530
- if not engine_name:
531
- engine_name = self.provider.resources.get_user_based_engine_name()
532
- self.engine_name = engine_name
533
-
534
- self.engine_size = engine_size or settings.pop("engine_size", None)
535
- self.engine_auto_suspend_mins = auto_suspend_mins or settings.pop("auto_suspend_mins", None)
536
-
537
- # The settings are used when creating a solver engine, they
538
- # may configure each individual solver.
539
- self.engine_settings = settings
540
-
541
- # Optimistically set the engine object to a `READY` engine to
542
- # avoid checking the engine status on each execution.
543
- self.engine:Optional[dict[str,Any]] = {"name": engine_name, "state": "READY"}
544
-
545
- return None
546
-
547
- # --------------------------------------------------
548
- # Helper
549
- # --------------------------------------------------
550
- def _auto_create_solver_async(self):
551
- name = self.engine_name
552
- auto_suspend_mins = self.engine_auto_suspend_mins
553
- size = self.engine_size
554
- settings = self.engine_settings
555
- with Spinner(
556
- "Checking solver status",
557
- leading_newline=True,
558
- ) as spinner:
559
- engine = None
560
- engines = [e for e in self.provider.list_solvers() if e["name"] == name]
561
- assert len(engines) == 1 or len(engines) == 0
562
- if len(engines) != 0:
563
- engine = engines[0]
564
-
565
- if engine:
566
- # TODO (dba) Logic engines support altering the
567
- # auto_suspend_mins setting. Currently, we don't have
568
- # this capability for solver engines, so users need to
569
- # recreate or use another engine. For both the size
570
- # and Gurobi configuration the user anyways has to
571
- # create a new one as this configuration must happen
572
- # when the engine is created.
573
- settings_cannot_be_altered_msg = "The configuration of a solver engine happens when the engine is created and _cannot_ be changed. You either need to specify a new engine name or delete the current engine.\n\nSee `solvers.Provider().delete_solver()`."
574
- # Make sure that the solver requested is enabled
575
- # on the engine.
576
- if self.solver_name not in engine["solvers"]:
577
- raise Exception(
578
- f"Solver `{self.solver_name}` is not enabled on `{name}`.\n\n" + settings_cannot_be_altered_msg
579
- )
580
-
581
- # Make sure size and auto_suspend_mins settings match
582
- # what the user requests.
583
- if size is not None and size != engine["size"]:
584
- raise Exception(
585
- f"Engine `{name}` has size setting of `{engine['size']}` but size is requested to be `{size}`.\n\n" + settings_cannot_be_altered_msg
586
- )
587
-
588
- if auto_suspend_mins is not None and auto_suspend_mins != engine["auto_suspend_mins"]:
589
- raise Exception(
590
- f"Engine `{name}` has auto_suspend_mins setting of `{engine['auto_suspend_mins']}` but auto_suspend_mins is requested to be `{auto_suspend_mins}`.\n\n" + settings_cannot_be_altered_msg
591
- )
592
-
593
- if engine["state"] == "PENDING":
594
- spinner.update_messages(
595
- {
596
- "finished_message": f"Solver {name} is starting",
597
- }
598
- )
599
- pass
600
- elif engine["state"] == "SUSPENDED":
601
- spinner.update_messages(
602
- {
603
- "finished_message": f"Resuming solver {name}",
604
- }
605
- )
606
- self.provider.resume_solver_async(name)
607
- elif engine["state"] == "READY":
608
- spinner.update_messages(
609
- {
610
- "finished_message": f"Solver {name} is ready",
611
- }
612
- )
613
- pass
614
- else:
615
- spinner.update_messages(
616
- {
617
- "message": f"Restarting solver {name}",
618
- }
619
- )
620
- self.provider.delete_solver(name)
621
- engine = None
622
- if not engine:
623
- # Validate Gurobi config.
624
- if self.solver_name == "gurobi":
625
- is_gurobi_configured = False
626
- gurobi_config = settings.get("gurobi", {})
627
- if all(
628
- k in gurobi_config
629
- for k in ["license_secret_name", "external_access_integration"]
630
- ):
631
- is_gurobi_configured = True
632
- if not is_gurobi_configured:
633
- raise Exception(
634
- "Gurobi is not properly configured. You need to provide both `license_secret_name` and `external_access_integration` in its configuration, see https://docs.relational.ai/build/reasoners/prescriptive/solver-backends/gurobi/#usage"
635
- )
636
- self.provider.create_solver_async(name, settings=settings, size=size, auto_suspend_mins=auto_suspend_mins)
637
- engine = self.provider.get_solver(name)
638
- spinner.update_messages(
639
- {
640
- "finished_message": f"Starting solver {name}...",
641
- }
642
- )
643
-
644
- self.engine = engine
645
-
646
- def _exec_job(self, payload, log_to_console=True, query_timeout_mins: Optional[int]=None):
647
- if self.engine is None:
648
- raise Exception("Engine not initialized.")
649
-
650
- with debugging.span("job") as job_span:
651
- # Retry logic. If creating a job fails with an engine
652
- # related error we will create/resume/... the engine and
653
- # retry.
654
- try:
655
- job_id = self.provider.create_job_async(self.engine["name"], payload, query_timeout_mins=query_timeout_mins)
656
- except Exception as e:
657
- err_message = str(e).lower()
658
- if isinstance(e, ResponseStatusException):
659
- err_message = e.response.json().get("message", "")
660
- if any(kw in err_message.lower() for kw in ENGINE_ERRORS + WORKER_ERRORS + ENGINE_NOT_READY_MSGS):
661
- self._auto_create_solver_async()
662
- # Wait until the engine is ready.
663
- poll_with_specified_overhead(lambda: self._is_solver_ready(), 0.1)
664
- job_id = self.provider.create_job_async(self.engine["name"], payload, query_timeout_mins=query_timeout_mins)
665
- else:
666
- raise e
667
-
668
- job_span["job_id"] = job_id
669
- debugging.event("job_created", job_span, job_id=job_id, engine_name=self.engine["name"], job_type=ENGINE_TYPE_SOLVER)
670
- if not isinstance(job_id, str):
671
- job_id = ""
672
- polling_state = PollingState(job_id, "", False, log_to_console)
673
-
674
- try:
675
- with debugging.span("wait", job_id=job_id):
676
- poll_with_specified_overhead(
677
- lambda: self._check_job_status(polling_state), 0.1
678
- )
679
- except KeyboardInterrupt as e:
680
- print(f"Canceling job {job_id}")
681
- self.provider.cancel_job(job_id)
682
- raise e
683
-
684
- return job_id
685
-
686
- def _is_solver_ready(self):
687
- if self.engine is None:
688
- raise Exception("Engine not initialized.")
689
-
690
- result = self.provider.get_solver(self.engine["name"])
691
-
692
- if result is None:
693
- raise Exception("No engine available.")
694
-
695
- self.engine = result
696
- state = result["state"]
697
- if state != "READY" and state != "PENDING":
698
- # Might have suspended or otherwise gone. Recreate.
699
- self._auto_create_solver_async()
700
- return state == "READY"
701
-
702
- def _check_job_status(self, state):
703
- response = self.provider.get_job(state.job_id)
704
- assert response, f"No results from get_job('{state.job_id}')"
705
-
706
- status: str = response["state"]
707
-
708
- self._print_solver_logs(state)
709
-
710
- return status == "COMPLETED" or status == "FAILED" or status == "CANCELED"
711
-
712
- def _print_solver_logs(self, state: PollingState):
713
- if state.is_done:
714
- return
715
-
716
- resp = self.provider.get_job_events(state.job_id, state.continuation_token)
717
-
718
- # Print solver logs to stdout.
719
- for event in resp["events"]:
720
- if event["type"] == "LogMessage":
721
- if state.log_to_console:
722
- print(event["event"]["message"])
723
- else:
724
- continue
725
-
726
- state.continuation_token = resp["continuation_token"]
727
- if state.continuation_token == "":
728
- state.is_done = True
729
-
730
-
731
- # --------------------------------------------------
732
- # Provider
733
- # --------------------------------------------------
734
- #
735
- # TODO (dba) We use an experimental and unified engine API for
736
- # solvers. Once it is no longer experimental we can remove the
737
- # provider here and use the normal PyRel provider.
738
-
739
-
740
- class Provider:
741
- def __init__(self, resources=None):
742
- if not resources:
743
- resources = v0.relationalai.Resources()
744
- if not isinstance(resources, v0.relationalai.clients.snowflake.Resources):
745
- raise Exception("Solvers are only supported on SPCS.")
746
-
747
- self.resources = resources
748
- self.direct_access_client: Optional[DirectAccessClient] = None
749
-
750
- if isinstance(self.resources, DirectAccessResources):
751
- self.direct_access_client = self.resources.direct_access_client
752
-
753
- def create_solver(
754
- self,
755
- name: str,
756
- size: str | None = None,
757
- settings: dict | None = None,
758
- auto_suspend_mins: int | None = None,
759
- ):
760
- if size is None:
761
- size = "HIGHMEM_X64_S"
762
- if settings is None:
763
- settings = {}
764
- engine_config: dict[str, Any] = {"settings": settings}
765
- if auto_suspend_mins is not None:
766
- engine_config["auto_suspend_mins"] = auto_suspend_mins
767
- self.resources._exec_sql(
768
- f"CALL {APP_NAME}.experimental.create_engine('{ENGINE_TYPE_SOLVER}', '{name}', '{size}', {engine_config});", None
769
- )
770
-
771
- def create_solver_async(
772
- self,
773
- name: str,
774
- size: str | None = None,
775
- settings: dict | None = None,
776
- auto_suspend_mins: int | None = None,
777
- ):
778
- if size is None:
779
- size = "HIGHMEM_X64_S"
780
-
781
- if self.direct_access_client is not None:
782
- payload:dict[str, Any] = {
783
- "name": name,
784
- "settings": settings,
785
- }
786
- if auto_suspend_mins is not None:
787
- payload["auto_suspend_mins"] = auto_suspend_mins
788
- if size is not None:
789
- payload["size"] = size
790
- response = self.direct_access_client.request(
791
- "create_engine",
792
- payload=payload,
793
- path_params={"engine_type": "solver"},
794
- )
795
- if response.status_code != 200:
796
- raise ResponseStatusException(
797
- f"Failed to create engine {name} with size {size}.", response
798
- )
799
- else:
800
- engine_config: dict[str, Any] = {}
801
- if settings is not None:
802
- engine_config["settings"] = settings
803
- if auto_suspend_mins is not None:
804
- engine_config["auto_suspend_mins"] = auto_suspend_mins
805
- self.resources._exec_sql(
806
- f"CALL {APP_NAME}.experimental.create_engine_async('{ENGINE_TYPE_SOLVER}', '{name}', '{size}', {engine_config});",
807
- None
808
- )
809
-
810
- def delete_solver(self, name: str):
811
- if self.direct_access_client is not None:
812
- response = self.direct_access_client.request(
813
- "delete_engine", path_params = {"engine_type": ENGINE_TYPE_SOLVER, "engine_name": name}
814
- )
815
- if response.status_code != 200:
816
- raise ResponseStatusException("Failed to delete engine.", response)
817
- return None
818
- else:
819
- self.resources._exec_sql(
820
- f"CALL {APP_NAME}.experimental.delete_engine('{ENGINE_TYPE_SOLVER}', '{name}');",
821
- None
822
- )
823
-
824
- def resume_solver_async(self, name: str):
825
- if self.direct_access_client is not None:
826
- response = self.direct_access_client.request(
827
- "resume_engine", path_params = {"engine_type": ENGINE_TYPE_SOLVER, "engine_name": name}
828
- )
829
- if response.status_code != 200:
830
- raise ResponseStatusException("Failed to resume engine.", response)
831
- return None
832
- else:
833
- self.resources._exec_sql(
834
- f"CALL {APP_NAME}.experimental.resume_engine_async('{ENGINE_TYPE_SOLVER}', '{name}');",
835
- None
836
- )
837
- return None
838
-
839
- def get_solver(self, name: str):
840
- if self.direct_access_client is not None:
841
- response = self.direct_access_client.request(
842
- "get_engine", path_params = {"engine_type": ENGINE_TYPE_SOLVER, "engine_name": name}
843
- )
844
- if response.status_code != 200:
845
- raise ResponseStatusException("Failed to get engine.", response)
846
- solver = response.json()
847
- if not solver :
848
- return None
849
- solver_state = {
850
- "name": solver["name"],
851
- "id": solver["id"],
852
- "size": solver["size"],
853
- "state": solver["status"], # callers are expecting 'state'
854
- "created_by": solver["created_by"],
855
- "created_on": solver["created_on"],
856
- "updated_on": solver["updated_on"],
857
- "version": solver["version"],
858
- "auto_suspend": solver["auto_suspend_mins"],
859
- "suspends_at": solver["suspends_at"],
860
- "solvers": []
861
- if solver["settings"] == ""
862
- else [
863
- k
864
- for (k,v) in json.loads(solver["settings"]).items()
865
- if isinstance(v, dict) and v.get("enabled", False)
866
- ],
867
- }
868
- return solver_state
869
- else:
870
- results = self.resources._exec_sql(
871
- f"CALL {APP_NAME}.experimental.get_engine('{ENGINE_TYPE_SOLVER}', '{name}');",
872
- None
873
- )
874
- return solver_list_to_dicts(results)[0]
875
-
876
- def list_solvers(self, state: str | None = None):
877
- if self.direct_access_client is not None:
878
- response = self.direct_access_client.request(
879
- "list_engines"
880
- )
881
- if response.status_code != 200:
882
- raise ResponseStatusException("Failed to list engines.", response)
883
- response_content = response.json()
884
- if not response_content:
885
- return []
886
- engines = [
887
- {
888
- "name": engine["name"],
889
- "id": engine["id"],
890
- "size": engine["size"],
891
- "state": engine["status"], # callers are expecting 'state'
892
- "created_by": engine["created_by"],
893
- "created_on": engine["created_on"],
894
- "updated_on": engine["updated_on"],
895
- "auto_suspend_mins": engine["auto_suspend_mins"],
896
- "solvers": []
897
- if engine["settings"] == ""
898
- else [
899
- k
900
- for (k, v) in json.loads(engine["settings"]).items()
901
- if isinstance(v, dict) and v.get("enabled", False)
902
- ],
903
- }
904
- for engine in response_content.get("engines", [])
905
- if (state is None or engine.get("status") == state) and (engine.get("type") == ENGINE_TYPE_SOLVER)
906
- ]
907
- return sorted(engines, key=lambda x: x["name"])
908
- else:
909
- where_clause = f"WHERE TYPE='{ENGINE_TYPE_SOLVER}'"
910
- where_clause = (
911
- f"{where_clause} AND STATUS = '{state.upper()}'" if state else where_clause
912
- )
913
- statement = f"SELECT NAME,ID,SIZE,STATUS,CREATED_BY,CREATED_ON,UPDATED_ON,AUTO_SUSPEND_MINS,SETTINGS FROM {APP_NAME}.experimental.engines {where_clause};"
914
- results = self.resources._exec_sql(statement, None)
915
- return solver_list_to_dicts(results)
916
-
917
- # --------------------------------------------------
918
- # Job API
919
- # --------------------------------------------------
920
-
921
- def create_job_async(self, engine_name, payload, query_timeout_mins: Optional[int]=None):
922
- payload_json = json.dumps(payload)
923
-
924
- if query_timeout_mins is None and (timeout_value := self.resources.config.get("query_timeout_mins", DEFAULT_QUERY_TIMEOUT_MINS)) is not None:
925
- query_timeout_mins = int(timeout_value)
926
-
927
- if self.direct_access_client is not None:
928
- job = {
929
- "job_type":ENGINE_TYPE_SOLVER,
930
- "worker_name": engine_name,
931
- "timeout_mins": query_timeout_mins,
932
- "payload": payload_json,
933
- }
934
- response = self.direct_access_client.request(
935
- "create_job",
936
- payload=job,
937
- )
938
- if response.status_code != 200:
939
- raise ResponseStatusException("Failed to create job.", response)
940
- response_content = response.json()
941
- return response_content["id"]
942
- else:
943
- if query_timeout_mins is not None:
944
- sql_string = textwrap.dedent(f"""
945
- CALL {APP_NAME}.experimental.exec_job_async('{ENGINE_TYPE_SOLVER}', '{engine_name}', '{payload_json}', null, {query_timeout_mins})
946
- """)
947
- else:
948
- sql_string = textwrap.dedent(f"""
949
- CALL {APP_NAME}.experimental.exec_job_async('{ENGINE_TYPE_SOLVER}', '{engine_name}', '{payload_json}')
950
- """)
951
- res = self.resources._exec_sql(sql_string, None)
952
- return res[0]["ID"]
953
-
954
- def list_jobs(self, state=None, limit=None):
955
- if self.direct_access_client is not None:
956
- response = self.direct_access_client.request(
957
- "list_jobs"
958
- )
959
- if response.status_code != 200:
960
- raise ResponseStatusException("Failed to list jobs.", response)
961
- response_content = response.json()
962
- if not response_content:
963
- return []
964
- jobs = [
965
- {
966
- "id": job["id"],
967
- "state": job["state"],
968
- "created_by": job["created_by"],
969
- "created_on": job["created_on"],
970
- "finished_at": job.get("finished_at", None),
971
- "duration": job["duration"] if "duration" in job else 0,
972
- "solver": json.loads(job["payload"]).get("solver", ""),
973
- "engine": job.get("engine_name", job["worker_name"]),
974
- }
975
- for job in response_content.get("jobs", [])
976
- if state is None or job.get("state") == state
977
- ]
978
- return sorted(jobs, key=lambda x: x["created_on"], reverse=True)
979
- else:
980
- state_clause = f"AND STATE = '{state.upper()}'" if state else ""
981
- limit_clause = f"LIMIT {limit}" if limit else ""
982
- results = self.resources._exec_sql(
983
- f"SELECT ID,STATE,CREATED_BY,CREATED_ON,FINISHED_AT,DURATION,PAYLOAD,ENGINE_NAME FROM {APP_NAME}.experimental.jobs where type='{ENGINE_TYPE_SOLVER}' {state_clause} ORDER BY created_on DESC {limit_clause};",
984
- None
985
- )
986
- return job_list_to_dicts(results)
987
-
988
- def get_job(self, id: str):
989
- if self.direct_access_client is not None:
990
- response = self.direct_access_client.request(
991
- "get_job", path_params = {"job_type": ENGINE_TYPE_SOLVER, "job_id": id}
992
- )
993
- if response.status_code != 200:
994
- raise ResponseStatusException("Failed to get job.", response)
995
- response_content = response.json()
996
- return response_content["job"]
997
- else:
998
- results = self.resources._exec_sql(
999
- f"CALL {APP_NAME}.experimental.get_job('{ENGINE_TYPE_SOLVER}', '{id}');",
1000
- None
1001
- )
1002
- return job_list_to_dicts(results)[0]
1003
-
1004
- def get_job_events(self, job_id: str, continuation_token: str = ""):
1005
- if self.direct_access_client is not None:
1006
- response = self.direct_access_client.request(
1007
- "get_job_events",
1008
- path_params = {"job_type": ENGINE_TYPE_SOLVER, "job_id": job_id, "stream_name": "progress"},
1009
- query_params={"continuation_token": continuation_token},
1010
- )
1011
- if response.status_code != 200:
1012
- raise ResponseStatusException("Failed to get job events.", response)
1013
- response_content = response.json()
1014
- if not response_content:
1015
- return {
1016
- "events": [],
1017
- "continuation_token": None
1018
- }
1019
- return response_content
1020
- else:
1021
- results = self.resources._exec_sql(
1022
- f"SELECT {APP_NAME}.experimental.get_job_events('{ENGINE_TYPE_SOLVER}', '{job_id}', '{continuation_token}');",
1023
- None
1024
- )
1025
- if not results:
1026
- return {"events": [], "continuation_token": None}
1027
- row = results[0][0]
1028
- if not isinstance(row, str):
1029
- row = ""
1030
- return json.loads(row)
1031
-
1032
- def cancel_job(self, id: str):
1033
- if self.direct_access_client is not None:
1034
- response = self.direct_access_client.request(
1035
- "cancel_job", path_params = {"job_type": ENGINE_TYPE_SOLVER, "job_id": id}
1036
- )
1037
- if response.status_code != 200:
1038
- raise ResponseStatusException("Failed to cancel job.", response)
1039
- return None
1040
- else:
1041
- self.resources._exec_sql(
1042
- f"CALL {APP_NAME}.experimental.cancel_job('{ENGINE_TYPE_SOLVER}', '{id}');",
1043
- None
1044
- )
1045
- return None
1046
-
1047
-
1048
- def solver_list_to_dicts(results):
1049
- if not results:
1050
- return []
1051
- return [
1052
- {
1053
- "name": row["NAME"],
1054
- "id": row["ID"],
1055
- "size": row["SIZE"],
1056
- "state": row["STATUS"], # callers are expecting 'state'
1057
- "created_by": row["CREATED_BY"],
1058
- "created_on": row["CREATED_ON"],
1059
- "updated_on": row["UPDATED_ON"],
1060
- "auto_suspend_mins": row["AUTO_SUSPEND_MINS"],
1061
- "solvers": []
1062
- if row["SETTINGS"] == ""
1063
- else [
1064
- k
1065
- for (k, v) in json.loads(row["SETTINGS"]).items()
1066
- if isinstance(v, dict) and v.get("enabled", False)
1067
- ],
1068
- }
1069
- for row in results
1070
- ]
1071
-
1072
- def job_list_to_dicts(results):
1073
- if not results:
1074
- return []
1075
- return [
1076
- {
1077
- "id": row["ID"],
1078
- "state": row["STATE"],
1079
- "created_by": row["CREATED_BY"],
1080
- "created_on": row["CREATED_ON"],
1081
- "finished_at": row["FINISHED_AT"],
1082
- "duration": row["DURATION"] if "DURATION" in row else 0,
1083
- "solver": json.loads(row["PAYLOAD"])["solver"],
1084
- "engine": row["ENGINE_NAME"],
1085
- }
1086
- for row in results
1087
- ]