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,1407 +0,0 @@
1
- """Solver model implementation supporting protobuf and CSV formats.
2
-
3
- This module provides the SolverModelPB class for defining optimization and
4
- constraint programming problems that are serialized and solved by external
5
- solver engines. Supports both protobuf (default) and CSV (future) exchange formats.
6
-
7
- Note: This protobuf-based implementation will be deprecated in favor of the
8
- development version (solvers_dev.py) in future releases.
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import textwrap
14
- import time
15
- import uuid
16
- from typing import Any, Optional
17
- from concurrent.futures import ThreadPoolExecutor
18
-
19
- from relationalai.experimental.solvers import Solver
20
- from relationalai.semantics.internal import internal as b
21
- from relationalai.semantics import std
22
- from relationalai.semantics.rel.executor import RelExecutor
23
- from relationalai.tools.constants import DEFAULT_QUERY_TIMEOUT_MINS
24
- from relationalai.util.timeout import calc_remaining_timeout_minutes
25
-
26
- from .common import make_name
27
-
28
- # =============================================================================
29
- # Solver ProtoBuf Format Constants and Helpers
30
- # =============================================================================
31
-
32
- # Variable type codes for the solver protobuf format
33
- # cont: continuous (real-valued), int: integer, bin: binary (0/1)
34
- _VARIABLE_TYPE_CODES: dict[str, int] = {
35
- "cont": 40,
36
- "int": 41,
37
- "bin": 42,
38
- }
39
-
40
- # First-order operators: arithmetic and mathematical functions
41
- _FIRST_ORDER_OPERATOR_CODES: dict[str, int] = {
42
- "+": 10,
43
- "-": 11,
44
- "*": 12,
45
- "/": 13,
46
- "^": 14,
47
- "abs": 20,
48
- "exp": 21,
49
- "log": 22,
50
- "range": 50,
51
- }
52
-
53
- # First-order comparison operators: relational constraints
54
- _FIRST_ORDER_COMPARISON_CODES: dict[str, int] = {
55
- "=": 30,
56
- "!=": 31,
57
- "<=": 32,
58
- ">=": 33,
59
- "<": 34,
60
- ">": 35,
61
- "implies": 62,
62
- }
63
-
64
- # Higher-order operators: aggregation and global constraints
65
- _HIGHER_ORDER_OPERATOR_CODES: dict[str, int] = {
66
- "sum": 80,
67
- "min": 82,
68
- "max": 83,
69
- "count": 84,
70
- "all_different": 90,
71
- }
72
-
73
- # Mapping from bound type keywords to comparison operators
74
- _BOUND_TO_COMPARISON_OPERATOR: dict[str, str] = {
75
- "lower": ">=",
76
- "upper": "<=",
77
- "fixed": "=",
78
- }
79
-
80
-
81
- def _make_first_order_application_with_result(
82
- operator_code: int, *args: Any
83
- ) -> b.Expression:
84
- """Create a first-order application with a result variable."""
85
- return _make_first_order_application(operator_code, *args, b.String.ref("res"))
86
-
87
-
88
- def _make_first_order_application(operator_code: int, *args: Any) -> b.Expression:
89
- """Create a first-order application expression."""
90
- if not (2 <= len(args) <= 4):
91
- raise ValueError(
92
- f"First-order application requires 2-4 arguments, but got {len(args)}."
93
- )
94
- result_ref = args[-1]
95
- if not isinstance(result_ref, b.Ref):
96
- raise TypeError(
97
- f"Last argument must be a Ref, got {type(result_ref).__name__}."
98
- )
99
- if result_ref._thing != b.String:
100
- result_ref = b.String.ref("res")
101
- application_builtin = b.Relationship.builtins["rel_primitive_solverlib_fo_appl"]
102
- # Wrap operands in TupleArg for the vararg solverlib_fo_appl primitive:
103
- # fo_appl(op, (operands...), result)
104
- return b.Expression(
105
- application_builtin, operator_code, b.TupleArg(args[:-1]), result_ref
106
- )
107
-
108
-
109
- # =============================================================================
110
- # Main Solver Model Class
111
- # =============================================================================
112
-
113
-
114
- class SolverModelPB:
115
- """Solver model interface using protobuf format for optimization problems."""
116
-
117
- def __init__(self, model: b.Model, num_type: str) -> None:
118
- """Initialize solver model.
119
-
120
- Args:
121
- model: The RelationalAI model.
122
- num_type: Variable type - 'cont' or 'int'.
123
- """
124
- if num_type not in ["cont", "int"]:
125
- raise ValueError(
126
- f"Invalid numerical type '{num_type}'. Must be 'cont' or 'int'."
127
- )
128
- self._model = model
129
- self._num_type = num_type
130
- self._id = next(b._global_id)
131
- self._model_id = str(uuid.uuid4()).upper().replace('-', '_')
132
- self._load_point_counter = 0
133
-
134
- # Maps relationships to their corresponding variable concepts
135
- self._variable_relationships: dict[b.Relationship, b.Concept] = {}
136
- prefix_uppercase = f"SolverModel_{self._id}_"
137
- prefix_lowercase = prefix_uppercase.lower()
138
-
139
- # Create core concepts for model components
140
- self.Variable = Variable = model.Concept(prefix_uppercase + "Variable")
141
- self.MinObjective = model.Concept(prefix_uppercase + "MinObjective")
142
- self.MaxObjective = model.Concept(prefix_uppercase + "MaxObjective")
143
- self.Constraint = model.Concept(prefix_uppercase + "Constraint")
144
- self._model_info = {
145
- "num_variables": Variable,
146
- "num_min_objectives": self.MinObjective,
147
- "num_max_objectives": self.MaxObjective,
148
- "num_constraints": self.Constraint,
149
- }
150
- # Add printed_expr property to objectives and constraints for human-readable output
151
- for concept in [self.MinObjective, self.MaxObjective, self.Constraint]:
152
- concept.printed_expr = model.Property(
153
- f"{{{concept._name}}} has {{printed_expr:str}}"
154
- )
155
-
156
- # Create relationships for result extraction
157
- result_type = "int" if num_type == "int" else "float"
158
- self.result_info = model.Relationship(
159
- "{key:str} has {value:str}", short_name=(prefix_lowercase + "result_info")
160
- )
161
- # TODO(coey) PyRel is not able to handle "Variable._name" instead of "var" below due
162
- # to some internal naming bug; this leads to a "Unresolved Type" warning that we
163
- # will have to live with for now
164
- self.point = model.Property(
165
- f"{{var}} has {{value:{result_type}}}",
166
- short_name=(prefix_lowercase + "point"),
167
- )
168
- # TODO (dba) Remove in favor of Loopy when possible.
169
-
170
- # This is a helper relation that allows us to model
171
- # `.load_point()` behavior. Results are loaded from SF views
172
- # and we cannot swap which solution `.point` currently points
173
- # to. So we keep a trace of updates. Each time a user calls
174
- # `.load_point()` we derive a new tuple into this relation and
175
- # use `max` to select the latest update.
176
- self._point_updates = model.Property(
177
- "at {update:int} we load {point:int}"
178
- )
179
- self.points = model.Property(
180
- f"point {{i:int}} for {{var}} has {{value:{result_type}}}",
181
- short_name=(prefix_lowercase + "points"),
182
- )
183
-
184
- # Install raw rel to work around lack of support for rel_primitive_solverlib_print_expr
185
- install_rel = f"""
186
- declare {self.MinObjective._name}
187
- declare {self.MaxObjective._name}
188
- declare {self.Constraint._name}
189
-
190
- declare {prefix_lowercase}variable_name
191
- declare {prefix_lowercase}minobjective_name
192
- declare {prefix_lowercase}maxobjective_name
193
- declare {prefix_lowercase}constraint_name
194
- declare {prefix_lowercase}minobjective_serialized
195
- declare {prefix_lowercase}maxobjective_serialized
196
- declare {prefix_lowercase}constraint_serialized
197
-
198
- def {prefix_lowercase}minobjective_printed_expr(h, s):
199
- rel_primitive_solverlib_print_expr({prefix_lowercase}minobjective_serialized[h], {prefix_lowercase}variable_name, s)
200
-
201
- def {prefix_lowercase}maxobjective_printed_expr(h, s):
202
- rel_primitive_solverlib_print_expr({prefix_lowercase}maxobjective_serialized[h], {prefix_lowercase}variable_name, s)
203
-
204
- def {prefix_lowercase}constraint_printed_expr(h, s):
205
- rel_primitive_solverlib_print_expr({prefix_lowercase}constraint_serialized[h], {prefix_lowercase}variable_name, s)
206
- """
207
- b.define(b.RawSource("rel", textwrap.dedent(install_rel)))
208
-
209
- # -------------------------------------------------------------------------
210
- # Variable Handling
211
- # -------------------------------------------------------------------------
212
-
213
- def solve_for(
214
- self,
215
- expr,
216
- where: Optional[list[Any]] = None,
217
- populate: bool = True,
218
- **kwargs: Any,
219
- ) -> b.Concept:
220
- """Define decision variables.
221
-
222
- Args:
223
- expr: Relationship or expression defining variables.
224
- where: Optional grounding conditions.
225
- populate: Whether to populate relationship with solver results.
226
- **kwargs: Optional properties (name, type, lower, upper, fixed).
227
-
228
- Returns:
229
- Variable concept.
230
- """
231
- if where is None:
232
- where = []
233
- if isinstance(expr, b.Fragment):
234
- # TODO(coey): Remove in future
235
- raise ValueError(
236
- "The select fragment argument to `solve_for` is deprecated. "
237
- "Instead, use the `where = [conditions...]` kwarg to specify optional grounding conditions."
238
- )
239
- elif isinstance(expr, b.Expression):
240
- relationship = expr._op
241
- if not isinstance(relationship, b.Relationship):
242
- raise TypeError(
243
- f"Expression operator must be a Relationship, got {type(relationship).__name__}."
244
- )
245
- params = expr._params
246
- elif isinstance(expr, b.Relationship):
247
- relationship = expr
248
- params = [
249
- b.field_to_type(self._model, field) for field in relationship._fields
250
- ]
251
- else:
252
- raise TypeError(
253
- f"Invalid expression type for solve_for: {type(expr).__name__}. "
254
- f"Expected Relationship or Expression."
255
- )
256
-
257
- if len(params) != len(relationship._fields):
258
- raise ValueError(
259
- f"Parameter count mismatch: Got {len(params)} params "
260
- f"but relationship has {len(relationship._fields)} fields."
261
- )
262
- if relationship in self._variable_relationships:
263
- raise ValueError(
264
- f"Variables are already defined for relationship {relationship}."
265
- )
266
-
267
- # Create a specialized Variable concept for this relationship
268
- # Each decision variable gets its own concept subtype
269
- Var = self._model.Concept(
270
- f"{self.Variable._name}_{str(relationship).replace('.', '_')}",
271
- extends=[self.Variable],
272
- )
273
- self._variable_relationships[relationship] = Var
274
-
275
- # Build field dict from relationship parameters (excluding the value field)
276
- fields = {}
277
- for i in range(len(params) - 1):
278
- if i == 0 and relationship._parent is not None:
279
- concept = relationship._parent
280
- if not isinstance(concept, b.Concept):
281
- raise TypeError(
282
- f"Relationship parent must be a Concept, got {type(concept).__name__}."
283
- )
284
- else:
285
- concept = params[i]
286
- field_name = relationship._field_names[i]
287
- # Prevent "Implicit Subtype Relationship" warnings by explicitly registering
288
- # the relationship on the parent Variable concept before using it on subtypes
289
- self.Variable._relationships[field_name] = self.Variable._get_relationship(
290
- field_name
291
- )
292
- fields[field_name] = concept
293
- var = Var.new(**fields)
294
- b.define(var).where(*where)
295
-
296
- # Handle optional variable properties
297
- for key, value in kwargs.items():
298
- if key == "name":
299
- definition = self.Variable.name(var, make_name(value))
300
- elif key == "type":
301
- if not isinstance(value, str):
302
- raise TypeError(
303
- f"Variable 'type' must be a string, but got {type(value).__name__}."
304
- )
305
- if value not in _VARIABLE_TYPE_CODES:
306
- valid_types = ", ".join(_VARIABLE_TYPE_CODES.keys())
307
- raise ValueError(
308
- f"Invalid variable type '{value}'. Valid types are: {valid_types}."
309
- )
310
- serialized_expr = _make_first_order_application_with_result(
311
- _VARIABLE_TYPE_CODES[value], var
312
- )
313
- definition = self.Constraint.new(serialized=serialized_expr)
314
- elif key in ("lower", "upper", "fixed"):
315
- if not isinstance(value, (b.Producer, float, int)):
316
- raise TypeError(
317
- f"Variable '{key}' must be a number, but got {type(value).__name__}."
318
- )
319
- # Map bound types to comparison operators
320
- operator = _BOUND_TO_COMPARISON_OPERATOR[key]
321
- serialized_expr = _make_first_order_application_with_result(
322
- _FIRST_ORDER_COMPARISON_CODES[operator], var, value
323
- )
324
- definition = self.Constraint.new(serialized=serialized_expr)
325
- else:
326
- raise ValueError(f"Invalid keyword argument '{key}' for solve_for.")
327
- b.define(definition).where(*where)
328
-
329
- if populate:
330
- # Automatically populate the variable relationship with solver results
331
- # This defines the original relationship to pull values from self.point after solving
332
- value_ref = (b.Integer if self._num_type == "int" else b.Float).ref()
333
- b.define(
334
- relationship(
335
- *[getattr(Var, field_name) for field_name in fields], value_ref
336
- )
337
- ).where(self.point(Var, value_ref))
338
-
339
- return Var
340
-
341
- # -------------------------------------------------------------------------
342
- # Objective Functions
343
- # -------------------------------------------------------------------------
344
-
345
- def minimize(
346
- self,
347
- expr: b.Producer | float | int | b.Fragment,
348
- name: Optional[str | list[str]] = None,
349
- ) -> None:
350
- """Add minimization objective.
351
-
352
- Args:
353
- expr: Expression to minimize.
354
- name: Optional objective name.
355
- """
356
- return self._add_objective(self.MinObjective, expr, name)
357
-
358
- def maximize(
359
- self,
360
- expr: b.Producer | float | int | b.Fragment,
361
- name: Optional[str | list[str]] = None,
362
- ) -> None:
363
- """Add maximization objective.
364
-
365
- Args:
366
- expr: Expression to maximize.
367
- name: Optional objective name.
368
- """
369
- return self._add_objective(self.MaxObjective, expr, name)
370
-
371
- def _add_objective(
372
- self,
373
- objective_concept: b.Concept,
374
- expr: b.Producer | float | int | b.Fragment,
375
- name: Optional[str | list[str]],
376
- ) -> None:
377
- context = SymbolifyContext(self)
378
- symbolic_expr = context.rewrite(expr)
379
- if not isinstance(symbolic_expr, Symbolic):
380
- # Expr is not symbolic (a constant) - wrap it as a trivial expression
381
- symbolic_expr = _make_first_order_application_with_result(0, expr)
382
- else:
383
- # Unwrap the symbolic expression
384
- unwrapped_expr = symbolic_expr.expr
385
- # Check if it's a bare variable (needs wrapping for protobuf)
386
- is_bare_variable = isinstance(unwrapped_expr, b.ConceptMember)
387
- is_fragment_with_variable = (
388
- isinstance(unwrapped_expr, b.Fragment)
389
- and unwrapped_expr._select
390
- and isinstance(unwrapped_expr._select[0], b.ConceptMember)
391
- )
392
- if is_bare_variable or is_fragment_with_variable:
393
- # The protobuf format requires all objectives to be expressions, not bare variables
394
- symbolic_expr = _make_first_order_application_with_result(
395
- 0, unwrapped_expr
396
- )
397
- else:
398
- symbolic_expr = unwrapped_expr
399
-
400
- if isinstance(symbolic_expr, Symbolic):
401
- raise ValueError(
402
- "Internal error. Expression is still Symbolic after unwrapping."
403
- )
404
-
405
- objective = objective_concept.new(serialized=symbolic_expr)
406
- definitions = [objective]
407
- if name is not None:
408
- definitions.append(objective.name(make_name(name)))
409
- b.define(*definitions)
410
-
411
- def satisfy(
412
- self,
413
- expr: b.Fragment,
414
- check: bool = False,
415
- name: Optional[str | list[str]] = None,
416
- ) -> None:
417
- """Add constraints.
418
-
419
- Args:
420
- expr: Fragment with require clause.
421
- check: Whether to keep require in model validation.
422
- name: Optional constraint name.
423
- """
424
- if not isinstance(expr, b.Fragment):
425
- raise TypeError(
426
- f"The satisfy method expects a Fragment, but got {type(expr).__name__}."
427
- )
428
- if not expr._require:
429
- raise ValueError("Fragment for satisfy must have a require clause.")
430
- if expr._select or expr._define:
431
- raise ValueError(
432
- "Fragment for satisfy must not have select or define clauses."
433
- )
434
- if not check:
435
- # Remove the `require` from the model roots so it is not checked as an integrity constraint
436
- b._remove_roots([expr])
437
- context = SymbolifyContext(self)
438
-
439
- symbolic_where_clauses = context.rewrite_where(*expr._where)
440
- definitions = []
441
- for requirement in expr._require:
442
- symbolic_requirement = context.rewrite(requirement)
443
- if not isinstance(symbolic_requirement, Symbolic):
444
- raise ValueError(
445
- f"Cannot symbolify requirement {requirement} in satisfy. "
446
- f"The requirement must contain solver variables or expressions."
447
- )
448
- constraint = self.Constraint.new(serialized=symbolic_requirement.expr)
449
- definitions.append(constraint)
450
- if name is not None:
451
- definitions.append(constraint.name(make_name(name)))
452
- b.define(*definitions).where(*symbolic_where_clauses)
453
-
454
- # -------------------------------------------------------------------------
455
- # Model Inspection and Display
456
- # -------------------------------------------------------------------------
457
-
458
- @staticmethod
459
- def _print_dataframe(df: Any) -> None:
460
- """Print dataframe with consistent formatting for long strings."""
461
- for row in df.itertuples(index=False):
462
- print(" ".join(str(val) for val in row))
463
- print()
464
-
465
- def summarize(self) -> None:
466
- """Print counts of variables, objectives, and constraints in the model."""
467
- counts_df = b.select(
468
- *[(b.count(item) | 0) for (_, item) in self._model_info.items()]
469
- ).to_df()
470
- if counts_df.shape != (1, 4):
471
- raise ValueError("Unexpected counts dataframe shape.")
472
- num_vars, num_min_objs, num_max_objs, num_constraints = counts_df.iloc[0]
473
- print(
474
- f"Solver model has {num_vars} variables, {num_min_objs} minimization objectives, {num_max_objs} maximization objectives, and {num_constraints} constraints."
475
- )
476
-
477
- def print(self, with_names: bool = False) -> None:
478
- """Print model components.
479
-
480
- Args:
481
- with_names: Whether to print expression string names (if available).
482
- """
483
- # Print variables
484
- var_df = b.select(self.Variable.name | "_").where(self.Variable).to_df()
485
- if var_df.empty:
486
- print("No variables defined.")
487
- return
488
- print("Solver model:")
489
- print()
490
- print(f"Variables ({var_df.shape[0]}):")
491
- self._print_dataframe(var_df)
492
-
493
- # Print components
494
- components = [
495
- (self.MinObjective, "Min objectives"),
496
- (self.MaxObjective, "Max objectives"),
497
- (self.Constraint, "Constraints"),
498
- ]
499
- printed_expr_ref = b.String.ref()
500
- for component_concept, component_label in components:
501
- selection = (
502
- [component_concept.name | "", printed_expr_ref]
503
- if with_names
504
- else [printed_expr_ref]
505
- )
506
- component_df = (
507
- b.select(*selection)
508
- .where(component_concept.printed_expr(printed_expr_ref))
509
- .to_df()
510
- )
511
- if not component_df.empty:
512
- print(f"{component_label} ({component_df.shape[0]}):")
513
- self._print_dataframe(component_df)
514
-
515
- # -------------------------------------------------------------------------
516
- # Solving and Result Handling
517
- # -------------------------------------------------------------------------
518
-
519
- def _export_model_to_csv(
520
- self,
521
- model_id: str,
522
- executor: RelExecutor,
523
- prefix_lowercase: str,
524
- query_timeout_mins: Optional[int] = None
525
- ) -> None:
526
- """Export model to CSV files in Snowflake stage.
527
-
528
- Args:
529
- model_id: Unique model identifier for stage paths.
530
- executor: RelExecutor instance.
531
- prefix_lowercase: Prefix for relation names.
532
- query_timeout_mins: Query timeout in minutes.
533
- """
534
- stage_base_no_txn = f"snowflake://APP_STATE.RAI_INTERNAL_STAGE/SOLVERS/job_{model_id}"
535
-
536
- # Export all model relations using Rel-native export_csv in a single transaction
537
- # Transformations (uuid_string, encode_base64) are done inline in the export query
538
- export_rel = textwrap.dedent(f"""
539
- // Get transaction ID for folder naming - solver service validates ownership
540
- // Use uuid_string to get proper UUID format, then replace hyphens with underscores
541
- def txn_id_str {{string_replace[uuid_string[current_transaction_id], "-", "_"]}}
542
-
543
- // Define base path with txn_id in folder name: model_{{txn_id}}/
544
- def base_path {{"{stage_base_no_txn}/model"}}
545
-
546
- // Export variable_hash.csv - single column: HASH (UUID string)
547
- // Transformation: convert Variable UInt128 to UUID string inline
548
- def variable_hash_data(:HASH, v, h):
549
- {self.Variable._name}(v) and uuid_string(v, h)
550
-
551
- def export[:variable_hash]: {{export_csv[{{
552
- (:path, base_path ++ "/variable_hash_" ++ txn_id_str ++ ".csv");
553
- (:data, variable_hash_data);
554
- (:compression, "gzip")
555
- }}]}}
556
-
557
- // Export variable_name.csv - columns: HASH (UUID string), VALUE (name string)
558
- // Transformation: convert Variable UInt128 to UUID string inline
559
- def variable_name_data(:HASH, v, h):
560
- {prefix_lowercase}variable_name(v, _) and uuid_string(v, h)
561
- def variable_name_data(:VALUE, v, name):
562
- {prefix_lowercase}variable_name(v, name)
563
-
564
- def export[:variable_name]: {{export_csv[{{
565
- (:path, base_path ++ "/variable_name_" ++ txn_id_str ++ ".csv");
566
- (:data, variable_name_data);
567
- (:compression, "gzip")
568
- }}]}}
569
-
570
- // Export constraint.csv - single column: VALUE (base64 encoded constraint)
571
- // Transformation: encode_base64 done inline
572
- def constraint_data(:VALUE, c, e):
573
- exists((s) |
574
- {self.Constraint._name}(c) and
575
- {prefix_lowercase}constraint_serialized(c, s) and
576
- encode_base64(s, e))
577
-
578
- def export[:constraint]: {{export_csv[{{
579
- (:path, base_path ++ "/constraint_" ++ txn_id_str ++ ".csv");
580
- (:data, constraint_data);
581
- (:compression, "gzip")
582
- }}]}}
583
-
584
- // Export min_objective.csv - columns: HASH (UUID string), VALUE (base64 encoded)
585
- // Transformations: uuid_string and encode_base64 done inline
586
- def min_objective_data(:HASH, obj, h):
587
- {self.MinObjective._name}(obj) and uuid_string(obj, h)
588
- def min_objective_data(:VALUE, obj, e):
589
- exists((s) |
590
- {self.MinObjective._name}(obj) and
591
- {prefix_lowercase}minobjective_serialized(obj, s) and
592
- encode_base64(s, e))
593
-
594
- def export[:min_objective]: {{export_csv[{{
595
- (:path, base_path ++ "/min_objective_" ++ txn_id_str ++ ".csv");
596
- (:data, min_objective_data);
597
- (:compression, "gzip")
598
- }}]}}
599
-
600
- // Export max_objective.csv - columns: HASH (UUID string), VALUE (base64 encoded)
601
- // Transformations: uuid_string and encode_base64 done inline
602
- def max_objective_data(:HASH, obj, h):
603
- {self.MaxObjective._name}(obj) and uuid_string(obj, h)
604
- def max_objective_data(:VALUE, obj, e):
605
- exists((s) |
606
- {self.MaxObjective._name}(obj) and
607
- {prefix_lowercase}maxobjective_serialized(obj, s) and
608
- encode_base64(s, e))
609
-
610
- def export[:max_objective]: {{export_csv[{{
611
- (:path, base_path ++ "/max_objective_" ++ txn_id_str ++ ".csv");
612
- (:data, max_objective_data);
613
- (:compression, "gzip")
614
- }}]}}
615
- """)
616
-
617
- executor.execute_raw(export_rel, query_timeout_mins=query_timeout_mins)
618
-
619
- def _import_solver_results_from_views(self) -> None:
620
- from relationalai.semantics.internal.snowflake import Table
621
-
622
- resources = self._model._to_executor().resources
623
- app_name = resources.get_app_name()
624
- logic_engine_name = resources.get_default_engine_name()
625
- model_id = self._model_id
626
-
627
- query = f"select {resources.get_app_name()}.api.get_index_db_name(?)"
628
-
629
- # To prevent sql injection, pass the variable as a separate argument to the executor
630
- index_db_name = resources._exec(query, [self._model.name])[0][0]
631
-
632
- # Result tables.
633
- ancillary_tbl = Table(f"{resources.get_app_name()}.RESULTS.SOLVERS_{model_id}_ANCILLARY")
634
- obj_vals_tbl = Table(f"{resources.get_app_name()}.RESULTS.SOLVERS_{model_id}_OBJECTIVE_VALUES")
635
- points_tbl = Table(f"{resources.get_app_name()}.RESULTS.SOLVERS_{model_id}_POINTS")
636
-
637
- # Skip cdc as we already make sure the tables are loaded.
638
- ancillary_tbl._skip_cdc = True
639
- obj_vals_tbl._skip_cdc = True
640
- points_tbl._skip_cdc = True
641
-
642
- # Load all tables into the GI database in parallel.
643
- load_statements = []
644
- for tbl in [ancillary_tbl, obj_vals_tbl, points_tbl]:
645
- rel_name = tbl._fqn.replace(".", "_").lower()
646
- load_statements.append(f"call {app_name}.api.load_data('{index_db_name}', '{logic_engine_name}', '{rel_name}', '{tbl._fqn}', '')")
647
-
648
- with ThreadPoolExecutor(max_workers=3) as executor:
649
- futures = [executor.submit(resources._exec, stmt) for stmt in load_statements]
650
- for future in futures:
651
- future.result()
652
-
653
- NumericType = b.Integer if self._num_type == "int" else b.Float
654
-
655
- # Metadata.
656
- key, val = b.String.ref(), b.String.ref()
657
- b.where(ancillary_tbl.name == key, ancillary_tbl.value == val).define(
658
- self.result_info(key, val)
659
- )
660
-
661
- b.where(obj_vals_tbl.sol_index == 1, std.strings.string(obj_vals_tbl.value) == val).define(
662
- self.result_info("objective_value", val)
663
- )
664
-
665
- # Points.
666
- val_ref = NumericType.ref()
667
- b.where(
668
- points_tbl.sol_index == b.Integer,
669
- points_tbl.var_hash == b.String,
670
- points_tbl.value == val_ref,
671
- ).define(self.points(b.Integer, std.parse_uuid(b.String), val_ref))
672
-
673
- # Default to loading solution `1`.
674
- b.define(self._point_updates(self._load_point_counter, 1))
675
-
676
- # Derive into `point` the latest user selection from
677
- # `_point_updates`.
678
- point_index = b.Integer.ref()
679
- b.where(self._point_updates(b.Integer, point_index), b.Integer == b.max(b.Integer),
680
- self.points(point_index, b.Hash, val_ref))\
681
- .define(self.point(b.Hash, val_ref))
682
-
683
- def _export_model_to_protobuf(
684
- self,
685
- model_uri: str,
686
- executor: RelExecutor,
687
- prefix_lowercase: str,
688
- query_timeout_mins: Optional[int] = None
689
- ) -> None:
690
- """Export model to protobuf format in Snowflake stage.
691
-
692
- Args:
693
- model_uri: Snowflake URI for the protobuf file.
694
- executor: RelExecutor instance.
695
- prefix_lowercase: Prefix for relation names.
696
- query_timeout_mins: Query timeout in minutes.
697
- """
698
- export_rel = f"""
699
- // Collect all model components into a relation for serialization
700
- def model_relation {{
701
- (:variable, {self.Variable._name});
702
- (:variable_name, {prefix_lowercase}variable_name);
703
- (:min_objective, {prefix_lowercase}minobjective_serialized);
704
- (:max_objective, {prefix_lowercase}maxobjective_serialized);
705
- (:constraint, {prefix_lowercase}constraint_serialized);
706
- }}
707
-
708
- @no_diagnostics(:EXPERIMENTAL)
709
- def model_string {{ rel_primitive_solverlib_model_string[model_relation] }}
710
-
711
- ic model_not_empty("Solver model is empty.") requires not empty(model_string)
712
-
713
- def config[:envelope, :content_type]: "application/octet-stream"
714
- def config[:envelope, :payload, :data]: model_string
715
- def config[:envelope, :payload, :path]: "{model_uri}"
716
- def export {{ config }}
717
- """
718
- executor.execute_raw(
719
- textwrap.dedent(export_rel),
720
- query_timeout_mins=query_timeout_mins
721
- )
722
-
723
- def _import_solver_results_from_protobuf(
724
- self,
725
- job_id: str,
726
- executor: RelExecutor,
727
- query_timeout_mins: Optional[int] = None
728
- ) -> None:
729
- """Import solver results from protobuf format.
730
-
731
- Args:
732
- job_id: Job identifier for result location.
733
- executor: RelExecutor instance.
734
- query_timeout_mins: Query timeout in minutes.
735
- """
736
- extract_rel = f"""
737
- def raw_result {{
738
- load_binary["snowflake://APP_STATE.RAI_INTERNAL_STAGE/job-results/{job_id}/result.binpb"]
739
- }}
740
-
741
- ic result_not_empty("Solver result is empty.") requires not empty(raw_result)
742
-
743
- @no_diagnostics(:EXPERIMENTAL)
744
- def extracted {{ rel_primitive_solverlib_extract[raw_result] }}
745
-
746
- def delete[:{self.result_info._name}]: {self.result_info._name}
747
- def delete[:{self.point._name}]: {self.point._name}
748
- def delete[:{self.points._name}]: {self.points._name}
749
-
750
- def insert(:{self.result_info._name}, key, value):
751
- exists((original_key) | string(extracted[original_key], value) and ::std::mirror::lower(original_key, key))
752
- """
753
-
754
- if self._num_type == "int":
755
- insert_points_relation = f"""
756
- def insert(:{self.point._name}, variable, value):
757
- exists((float_value) | extracted(:point, variable, float_value) and
758
- ::std::mirror::convert(std::mirror::typeof[Int128], float_value, value)
759
- )
760
- def insert(:{self.points._name}, point_index, variable, value):
761
- exists((float_index, float_value) | extracted(:points, variable, float_index, float_value) and
762
- ::std::mirror::convert(std::mirror::typeof[Int128], float_index, point_index) and
763
- ::std::mirror::convert(std::mirror::typeof[Int128], float_value, value)
764
- )
765
- """
766
- else:
767
- insert_points_relation = f"""
768
- def insert(:{self.point._name}, variable, value): extracted(:point, variable, value)
769
- def insert(:{self.points._name}, point_index, variable, value):
770
- exists((float_index) | extracted(:points, variable, float_index, value) and
771
- ::std::mirror::convert(std::mirror::typeof[Int128], float_index, point_index)
772
- )
773
- """
774
-
775
- executor.execute_raw(
776
- textwrap.dedent(extract_rel) + textwrap.dedent(insert_points_relation),
777
- query_timeout_mins=query_timeout_mins
778
- )
779
-
780
- def solve(
781
- self, solver: Solver, log_to_console: bool = False, **kwargs: Any
782
- ) -> None:
783
- """Solve the model.
784
-
785
- Args:
786
- solver: Solver instance.
787
- log_to_console: Whether to show solver output.
788
- **kwargs: Solver options and parameters.
789
- """
790
-
791
- self._solver = solver
792
-
793
- use_csv_store = solver.engine_settings.get("store", {})\
794
- .get("csv", {})\
795
- .get("enabled", True)
796
-
797
- print(f"Using {'csv' if use_csv_store else 'protobuf'} store...")
798
-
799
- options = {**kwargs, "version": 1}
800
-
801
- # Validate solver options
802
- for option_key, option_value in options.items():
803
- if not isinstance(option_key, str):
804
- raise TypeError(
805
- f"Solver option keys must be strings, but got {type(option_key).__name__} for key {option_key!r}."
806
- )
807
- if not isinstance(option_value, (int, float, str, bool)):
808
- raise TypeError(
809
- f"Solver option values must be int, float, str, or bool, "
810
- f"but got {type(option_value).__name__} for option {option_key!r}."
811
- )
812
-
813
- executor = self._model._to_executor()
814
- if not isinstance(executor, RelExecutor):
815
- raise ValueError(f"Expected RelExecutor, got {type(executor).__name__}.")
816
- prefix_lowercase = f"solvermodel_{self._id}_"
817
-
818
- # Initialize timeout from config
819
- query_timeout_mins = kwargs.get("query_timeout_mins", None)
820
- config = self._model._config
821
- if (
822
- query_timeout_mins is None
823
- and (
824
- timeout_value := config.get(
825
- "query_timeout_mins", DEFAULT_QUERY_TIMEOUT_MINS
826
- )
827
- )
828
- is not None
829
- ):
830
- query_timeout_mins = int(timeout_value)
831
- config_file_path = getattr(config, "file_path", None)
832
- start_time = time.monotonic()
833
-
834
- # Force evaluation of Variable concept before export
835
- b.select(b.count(self.Variable)).to_df()
836
-
837
- # Prepare payload for solver service
838
- payload: dict[str, Any] = {"solver": solver.solver_name.lower(), "options": options}
839
-
840
- if use_csv_store:
841
- payload["model_uri"] = f"snowflake://SOLVERS/job_{self._model_id}/model"
842
-
843
- print("Exporting model to CSV...")
844
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
845
- start_time, query_timeout_mins, config_file_path=config_file_path
846
- )
847
- self._export_model_to_csv(self._model_id, executor, prefix_lowercase, remaining_timeout_minutes)
848
- print("Model CSV export completed")
849
-
850
- print("Execute solver job")
851
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
852
- start_time, query_timeout_mins, config_file_path=config_file_path
853
- )
854
- solver._exec_job(payload, log_to_console=log_to_console, query_timeout_mins=remaining_timeout_minutes)
855
-
856
- print("Loading and extracting solver results...")
857
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
858
- start_time, query_timeout_mins, config_file_path=config_file_path
859
- )
860
- self._import_solver_results_from_views()
861
-
862
- else: # protobuf format
863
- # Protobuf format: model and results are exchanged via binary protobuf
864
- input_id = uuid.uuid4()
865
- model_uri = f"snowflake://APP_STATE.RAI_INTERNAL_STAGE/job-inputs/solver/{input_id}/model.binpb"
866
- sf_input_uri = f"snowflake://job-inputs/solver/{input_id}/model.binpb"
867
- payload["model_uri"] = sf_input_uri
868
-
869
- print("Export model...")
870
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
871
- start_time, query_timeout_mins, config_file_path=config_file_path
872
- )
873
- self._export_model_to_protobuf(model_uri, executor, prefix_lowercase, remaining_timeout_minutes)
874
-
875
- print("Execute solver job...")
876
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
877
- start_time, query_timeout_mins, config_file_path=config_file_path
878
- )
879
- job_id = solver._exec_job(payload, log_to_console=log_to_console, query_timeout_mins=remaining_timeout_minutes)
880
-
881
- print("Extract result...")
882
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
883
- start_time, query_timeout_mins, config_file_path=config_file_path
884
- )
885
- self._import_solver_results_from_protobuf(job_id, executor, remaining_timeout_minutes)
886
-
887
- print("Finished solve")
888
- print()
889
- return None
890
-
891
- def load_point(self, point_index: int) -> None:
892
- """Load a solution point.
893
-
894
- Args:
895
- point_index: Solution point index (0-based).
896
- """
897
- if not isinstance(point_index, int):
898
- raise TypeError(
899
- f"Point index must be an integer, but got {type(point_index).__name__}."
900
- )
901
- if point_index < 0:
902
- raise ValueError(
903
- f"Point index must be non-negative, but got {point_index}."
904
- )
905
- executor = self._model._to_executor()
906
- if not isinstance(executor, RelExecutor):
907
- raise ValueError(
908
- f"Expected RelExecutor, but got {type(executor).__name__}."
909
- )
910
-
911
- use_csv_store = True
912
- if self._solver is not None:
913
- use_csv_store = self._solver.engine_settings.get("store", {})\
914
- .get("csv", {})\
915
- .get("enabled", True)
916
-
917
- if use_csv_store:
918
- self._load_point_counter += 1
919
- b.define(self._point_updates(self._load_point_counter, point_index))
920
- else:
921
- load_point_relation = f"""
922
- def delete[:{self.point._name}]: {self.point._name}
923
- def insert(:{self.point._name}, variable, value): {self.points._name}(int128[{point_index}], variable, value)
924
- """
925
- executor.execute_raw(textwrap.dedent(load_point_relation))
926
-
927
- def summarize_result(self) -> Any:
928
- """Print solver result summary.
929
-
930
- Returns:
931
- DataFrame with result information.
932
- """
933
- info_keys_to_retrieve = [
934
- "error",
935
- "termination_status",
936
- "solve_time_sec",
937
- "objective_value",
938
- "solver_version",
939
- "result_count",
940
- ]
941
- key, value_ref = b.String.ref(), b.String.ref()
942
- result_df = (
943
- b.select(key, value_ref)
944
- .where(self.result_info(key, value_ref), key.in_(info_keys_to_retrieve))
945
- .to_df()
946
- )
947
- if result_df.empty:
948
- raise ValueError(
949
- "No result information is available. Has the model been solved?"
950
- )
951
- print("Solver result:")
952
- print(result_df.to_string(index=False, header=False))
953
- print()
954
- return result_df
955
-
956
- def variable_values(self, multiple: bool = False) -> b.Fragment:
957
- """Retrieve variable values.
958
-
959
- Args:
960
- multiple: Whether to return all solution points.
961
-
962
- Returns:
963
- Fragment for selecting values.
964
- """
965
- variable_ref = self.Variable.ref()
966
- value_ref = (b.Integer if self._num_type == "int" else b.Float).ref()
967
- if multiple:
968
- point_index = b.Integer.ref()
969
- return b.select(point_index, variable_ref.name, value_ref).where(
970
- self.points(point_index, variable_ref, value_ref)
971
- )
972
- return b.select(variable_ref.name, value_ref).where(
973
- self.point(variable_ref, value_ref)
974
- )
975
-
976
- # Valid result info keys that can be accessed as attributes
977
- _RESULT_INFO_KEYS = frozenset(
978
- [
979
- "error",
980
- "termination_status",
981
- "solver_version",
982
- "printed_model",
983
- "solve_time_sec",
984
- "objective_value",
985
- "result_count",
986
- ]
987
- )
988
-
989
- def __getattr__(self, name: str) -> Any:
990
- """Get result attribute (e.g., num_variables, termination_status, objective_value).
991
-
992
- Args:
993
- name: Attribute name.
994
-
995
- Returns:
996
- Attribute value or None.
997
- """
998
- # Try to get dataframe from model info or result info
999
- if name in self._model_info:
1000
- result_df = b.select(b.count(self._model_info[name]) | 0).to_df()
1001
- elif name in self._RESULT_INFO_KEYS:
1002
- value_ref = b.String.ref()
1003
- result_df = (
1004
- b.select(value_ref).where(self.result_info(name, value_ref)).to_df()
1005
- )
1006
- else:
1007
- return None
1008
-
1009
- # Extract and convert scalar value
1010
- if result_df.shape != (1, 1):
1011
- raise ValueError(
1012
- f"Expected exactly one value for attribute '{name}', "
1013
- f"but got dataframe with shape {result_df.shape}."
1014
- )
1015
-
1016
- result_value = result_df.iloc[0, 0]
1017
- if not isinstance(result_value, str):
1018
- return result_value
1019
-
1020
- # Convert string results to appropriate types
1021
- if name == "solve_time_sec":
1022
- return float(result_value)
1023
- if name == "objective_value":
1024
- return int(result_value) if self._num_type == "int" else float(result_value)
1025
- if name == "result_count":
1026
- return int(result_value)
1027
- return result_value
1028
-
1029
-
1030
- # =============================================================================
1031
- # Symbolic Expression Classes
1032
- # =============================================================================
1033
-
1034
-
1035
- class Symbolic:
1036
- """Wrapper for symbolified solver expressions."""
1037
-
1038
- def __init__(self, expr: Any) -> None:
1039
- if isinstance(expr, Symbolic):
1040
- raise TypeError("Cannot wrap a Symbolic expression in another Symbolic.")
1041
- self.expr = expr
1042
-
1043
-
1044
- class SymbolifyContext:
1045
- """Context for rewriting expressions into solver-compatible symbolic form."""
1046
-
1047
- def __init__(self, solver_model: SolverModelPB) -> None:
1048
- self.model = solver_model._model
1049
- self.solver_model = solver_model
1050
- # Maps original variables (or refs) to symbolic variables bound in where clauses
1051
- self.variable_map: dict[Any, Any] = {}
1052
-
1053
- # -------------------------------------------------------------------------
1054
- # Public Rewriting Methods
1055
- # -------------------------------------------------------------------------
1056
-
1057
- def rewrite_where(self, *exprs: Any) -> list[Any]:
1058
- """Rewrite where clause expressions.
1059
-
1060
- Args:
1061
- *exprs: Where clause expressions.
1062
-
1063
- Returns:
1064
- Rewritten expressions.
1065
- """
1066
- rewritten_expressions: list[Any] = []
1067
- # Two-pass strategy: first handle variable relationships to populate variable_map,
1068
- # then rewrite other expressions that may reference those variables
1069
- # First pass: identify and handle variable relationship expressions
1070
- for expression in exprs:
1071
- if (
1072
- isinstance(expression, b.Expression)
1073
- and isinstance(expression._op, b.Relationship)
1074
- and expression._op in self.solver_model._variable_relationships
1075
- ):
1076
- rewritten_expressions.append(
1077
- self._handle_variable_relationship(expression)
1078
- )
1079
- else:
1080
- rewritten_expressions.append(None)
1081
- # Second pass: rewrite remaining non-variable expressions
1082
- for i, expr in enumerate(exprs):
1083
- if rewritten_expressions[i] is None:
1084
- rewritten_expressions[i] = (
1085
- expr
1086
- if expr in self.variable_map
1087
- else self._rewrite_nonsymbolic(expr)
1088
- )
1089
- return rewritten_expressions
1090
-
1091
- def rewrite(self, expr: Any) -> Optional[Symbolic | Any]:
1092
- """Rewrite expressions to symbolify solver variables."""
1093
- if expr is None:
1094
- return None
1095
-
1096
- elif isinstance(expr, (int, float, str)):
1097
- return None
1098
-
1099
- elif isinstance(expr, b.ConceptFilter):
1100
- concept = expr._op
1101
- assert isinstance(concept, b.Concept)
1102
- (ident, kwargs) = expr._params
1103
- assert ident is None
1104
- assert isinstance(kwargs, dict)
1105
- new_kwargs = {}
1106
- values_were_rewritten = False
1107
- for key, value in kwargs.items():
1108
- rewritten_value = self.rewrite(value)
1109
- if isinstance(rewritten_value, Symbolic):
1110
- raise ValueError(
1111
- f"Cannot symbolify ConceptFilter argument {key} with symbolic value."
1112
- )
1113
- if rewritten_value is not None:
1114
- values_were_rewritten = True
1115
- new_kwargs[key] = rewritten_value
1116
- else:
1117
- new_kwargs[key] = value
1118
- if values_were_rewritten:
1119
- return b.ConceptFilter(concept, ident, new_kwargs)
1120
- return None
1121
-
1122
- elif isinstance(expr, (b.DataColumn, b.TypeRef, b.Concept)):
1123
- return None
1124
-
1125
- elif isinstance(expr, b.Alias):
1126
- return self.rewrite(expr._thing)
1127
-
1128
- elif isinstance(expr, b.Ref):
1129
- if expr in self.variable_map:
1130
- return Symbolic(self.variable_map[expr])
1131
- thing = self.rewrite(expr._thing)
1132
- if thing is not None:
1133
- raise ValueError(
1134
- f"Internal error. Ref._thing rewrite unexpectedly returned {thing}."
1135
- )
1136
- return None
1137
-
1138
- elif isinstance(expr, b.Relationship):
1139
- if expr in self.variable_map:
1140
- return Symbolic(self.variable_map[expr])
1141
- variable_result = self._get_variable_ref(expr, expr._parent)
1142
- if variable_result is not None:
1143
- self.variable_map[expr] = variable_result
1144
- return Symbolic(variable_result)
1145
- return None
1146
-
1147
- elif isinstance(expr, b.RelationshipRef):
1148
- if expr in self.variable_map:
1149
- return Symbolic(self.variable_map[expr])
1150
- relationship = expr._relationship
1151
- if isinstance(relationship, b.Relationship):
1152
- variable_result = self._get_variable_ref(relationship, expr._parent)
1153
- if variable_result is not None:
1154
- self.variable_map[expr] = variable_result
1155
- return Symbolic(variable_result)
1156
- rewritten_parent = self.rewrite(expr._parent)
1157
- if isinstance(rewritten_parent, Symbolic):
1158
- raise ValueError(
1159
- "Internal error. RelationshipRef parent rewrite returned Symbolic."
1160
- )
1161
- if rewritten_parent is not None:
1162
- return b.RelationshipRef(rewritten_parent, relationship)
1163
- return None
1164
-
1165
- elif isinstance(expr, b.RelationshipFieldRef):
1166
- relationship = expr._relationship
1167
- if not isinstance(relationship, b.Relationship):
1168
- # TODO(coey): Handle relationship:RelationshipReading
1169
- return None
1170
-
1171
- # Rewrite the relationship reference
1172
- relationship_expression = (
1173
- relationship
1174
- if expr._parent is None
1175
- else b.RelationshipRef(expr._parent, relationship)
1176
- )
1177
- variable_result = self.rewrite(relationship_expression)
1178
- if variable_result is None:
1179
- return None
1180
-
1181
- # Handle symbolic result - return as-is if it's the last field
1182
- if isinstance(variable_result, Symbolic):
1183
- if expr._field_ix == len(relationship._fields) - 1:
1184
- return variable_result
1185
- variable_result = variable_result.expr
1186
-
1187
- return getattr(variable_result, relationship._field_names[expr._field_ix])
1188
-
1189
- elif isinstance(expr, b.Expression):
1190
- operator = self.rewrite(expr._op)
1191
- if isinstance(operator, Symbolic):
1192
- raise ValueError(
1193
- "Internal error: Expression operator rewrite returned Symbolic."
1194
- )
1195
- params_were_rewritten = False
1196
- has_symbolic_params = False
1197
- params = []
1198
- for param in expr._params:
1199
- rewritten_param = self.rewrite(param)
1200
- if isinstance(rewritten_param, Symbolic):
1201
- has_symbolic_params = True
1202
- params_were_rewritten = True
1203
- params.append(rewritten_param.expr)
1204
- elif rewritten_param is not None:
1205
- params_were_rewritten = True
1206
- params.append(rewritten_param)
1207
- else:
1208
- params.append(param)
1209
- if operator is not None:
1210
- if has_symbolic_params:
1211
- raise NotImplementedError(
1212
- f"Solver rewrites cannot handle expression {expr} "
1213
- f"with both a symbolic operator and symbolic parameters."
1214
- )
1215
- return b.Expression(operator, *params)
1216
- if not has_symbolic_params:
1217
- return b.Expression(expr._op, *params)
1218
- if not params_were_rewritten:
1219
- return None
1220
-
1221
- # Some arguments involve solver variables, so rewrite into solver protobuf format
1222
- # This converts operations like x + y into fo_appl(ADD_OP, (x, y), res)
1223
- if not has_symbolic_params:
1224
- raise ValueError(
1225
- "Internal error. Expected symbolic parameters but none were found."
1226
- )
1227
- if not isinstance(expr._op, b.Relationship):
1228
- raise NotImplementedError(
1229
- f"Solver rewrites cannot handle expression {expr} "
1230
- f"with operator type {type(expr._op).__name__}."
1231
- )
1232
- operator_name = expr._op._name
1233
- if not isinstance(operator_name, str):
1234
- raise ValueError(
1235
- f"Internal error. Operator name is {type(operator_name).__name__}, expected str."
1236
- )
1237
- if operator_name in _FIRST_ORDER_OPERATOR_CODES:
1238
- return Symbolic(
1239
- _make_first_order_application(
1240
- _FIRST_ORDER_OPERATOR_CODES[operator_name], *params
1241
- )
1242
- )
1243
- elif operator_name in _FIRST_ORDER_COMPARISON_CODES:
1244
- return Symbolic(
1245
- _make_first_order_application_with_result(
1246
- _FIRST_ORDER_COMPARISON_CODES[operator_name], *params
1247
- )
1248
- )
1249
- else:
1250
- raise NotImplementedError(
1251
- f"Solver rewrites cannot handle operator '{operator_name}'."
1252
- )
1253
-
1254
- elif isinstance(expr, b.Aggregate):
1255
- # Only the last argument can be symbolic
1256
- preceding_args = [self._rewrite_nonsymbolic(arg) for arg in expr._args[:-1]]
1257
- group = [self._rewrite_nonsymbolic(arg) for arg in expr._group]
1258
- # TODO(coey): Should this be done with a subcontext (for variable_map)?
1259
- where = self.rewrite_where(*expr._where._where)
1260
- rewritten = (
1261
- preceding_args != expr._args[:-1]
1262
- or group != expr._group
1263
- or where != expr._where
1264
- )
1265
- symbolic_arg = self.rewrite(expr._args[-1])
1266
- if symbolic_arg is None and not rewritten:
1267
- return None
1268
- if not isinstance(symbolic_arg, Symbolic):
1269
- if symbolic_arg is None:
1270
- symbolic_arg = expr._args[-1]
1271
- aggregate_expr = b.Aggregate(expr._op, *preceding_args, symbolic_arg)
1272
- return aggregate_expr.per(*group).where(*where)
1273
-
1274
- # The last argument is symbolic - convert to higher-order application
1275
- # Example: sum(x for x in variables) becomes ho_appl(..., x, SUM_OP)
1276
- operator_name = expr._op._name
1277
- if not isinstance(operator_name, str):
1278
- raise ValueError(
1279
- f"Internal error. Aggregate operator name is {type(operator_name).__name__}, expected str."
1280
- )
1281
- if operator_name not in _HIGHER_ORDER_OPERATOR_CODES:
1282
- raise NotImplementedError(
1283
- f"Solver rewrites cannot handle aggregate operator '{operator_name}'. "
1284
- f"Supported operators: {', '.join(_HIGHER_ORDER_OPERATOR_CODES.keys())}"
1285
- )
1286
- higher_order_application_builtin = b.Relationship.builtins[
1287
- "rel_primitive_solverlib_ho_appl"
1288
- ]
1289
- aggregate_expr = b.Aggregate(
1290
- higher_order_application_builtin,
1291
- *preceding_args,
1292
- symbolic_arg.expr,
1293
- _HIGHER_ORDER_OPERATOR_CODES[operator_name],
1294
- )
1295
- return Symbolic(aggregate_expr.per(*group).where(*where))
1296
-
1297
- elif isinstance(expr, b.Union):
1298
- # Return union of the symbolified expressions, if any are symbolic
1299
- args_were_rewritten = False
1300
- has_symbolic_args = False
1301
- args = []
1302
- for union_arg in expr._args:
1303
- rewritten_arg = self.rewrite(union_arg)
1304
- if isinstance(rewritten_arg, Symbolic):
1305
- has_symbolic_args = True
1306
- args.append(rewritten_arg.expr)
1307
- elif rewritten_arg is not None:
1308
- args_were_rewritten = True
1309
- args.append(rewritten_arg)
1310
- else:
1311
- args.append(union_arg)
1312
- if has_symbolic_args:
1313
- return Symbolic(b.union(*args))
1314
- elif args_were_rewritten:
1315
- return b.union(*args)
1316
- return None
1317
-
1318
- elif isinstance(expr, b.Fragment):
1319
- # Only support selects with one item
1320
- if expr._define or expr._require:
1321
- raise ValueError(
1322
- "Solver rewrites do not support fragments with define or require clauses."
1323
- )
1324
- if len(expr._select) != 1:
1325
- raise ValueError(
1326
- f"Solver rewrites require fragments with exactly one select item, "
1327
- f"but got {len(expr._select)}."
1328
- )
1329
- # TODO(coey): Should this be done with a subcontext (for variable_map)?
1330
- where = self.rewrite_where(*expr._where)
1331
- symbolic_select = self.rewrite(expr._select[0])
1332
- if isinstance(symbolic_select, Symbolic):
1333
- return Symbolic(b.select(symbolic_select.expr).where(*where))
1334
- elif symbolic_select is not None:
1335
- return b.select(symbolic_select).where(*where)
1336
- return None
1337
-
1338
- raise NotImplementedError(
1339
- f"Solver rewrites cannot handle {expr} of type {type(expr).__name__}."
1340
- )
1341
-
1342
- # -------------------------------------------------------------------------
1343
- # Private Helper Methods
1344
- # -------------------------------------------------------------------------
1345
-
1346
- def _handle_variable_relationship(self, expr: b.Expression) -> Any:
1347
- """Create symbolic reference for variable relationship expression."""
1348
- relationship = expr._op
1349
- if not isinstance(relationship, b.Relationship):
1350
- raise TypeError(
1351
- f"Expected Relationship in variable expression, but got {type(relationship).__name__}."
1352
- )
1353
- params = expr._params
1354
- if len(params) != len(relationship._fields):
1355
- raise ValueError(
1356
- f"Parameter count mismatch: Got {len(params)} params "
1357
- f"but relationship has {len(relationship._fields)} fields."
1358
- )
1359
- last_param = params[-1]
1360
- if isinstance(last_param, b.Alias):
1361
- last_param = last_param._thing
1362
- if not isinstance(last_param, (b.Concept, b.Ref)):
1363
- raise TypeError(
1364
- f"Last parameter must be a Concept or Ref, but got {type(last_param).__name__}."
1365
- )
1366
- # Extract and rewrite field parameters to build the symbolic variable reference
1367
- # This maps the relationship fields to their grounding values
1368
- fields = {}
1369
- for i in range(len(params) - 1):
1370
- rewritten_param = self.rewrite(params[i])
1371
- assert not isinstance(rewritten_param, Symbolic)
1372
- fields[relationship._field_names[i]] = (
1373
- rewritten_param if rewritten_param is not None else params[i]
1374
- )
1375
- # Create new ref corresponding to the decision variable
1376
- variable_ref = self.solver_model._variable_relationships[relationship].ref()
1377
- self.variable_map[last_param] = variable_ref
1378
- # Return new condition to ground the variable
1379
- return b.where(
1380
- *[
1381
- getattr(variable_ref, field_name) == field_value
1382
- for field_name, field_value in fields.items()
1383
- ]
1384
- )
1385
-
1386
- def _rewrite_nonsymbolic(self, expr: Any) -> Any:
1387
- """Rewrite expression ensuring non-symbolic result."""
1388
- new_expr = self.rewrite(expr)
1389
- if isinstance(new_expr, Symbolic):
1390
- raise ValueError(
1391
- f"Internal error. Non-symbolic rewrite unexpectedly returned Symbolic for {expr}."
1392
- )
1393
- return expr if new_expr is None else new_expr
1394
-
1395
- def _get_variable_ref(
1396
- self, relationship: b.Relationship, parent_producer: b.Producer | None
1397
- ) -> Optional[Any]:
1398
- """Get variable reference for relationship, or None if not a solver variable."""
1399
- # Check if this relationship corresponds to a decision variable
1400
- VariableConcept = self.solver_model._variable_relationships.get(relationship)
1401
- if VariableConcept is None:
1402
- return None
1403
-
1404
- properties = {}
1405
- if parent_producer is not None:
1406
- properties[relationship._field_names[0]] = parent_producer
1407
- return VariableConcept(VariableConcept.ref(), **properties)