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

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