relationalai 0.13.0__py3-none-any.whl → 0.13.0.dev0__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 (836) 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/semantics/__init__.py +146 -22
  16. relationalai/semantics/backends/lqp/annotations.py +11 -0
  17. relationalai/semantics/backends/sql/sql_compiler.py +327 -0
  18. relationalai/semantics/frontend/base.py +1707 -0
  19. relationalai/semantics/frontend/core.py +179 -0
  20. relationalai/semantics/frontend/front_compiler.py +1313 -0
  21. relationalai/semantics/frontend/pprint.py +408 -0
  22. relationalai/semantics/metamodel/__init__.py +6 -40
  23. relationalai/semantics/metamodel/builtins.py +205 -771
  24. relationalai/semantics/metamodel/metamodel.py +437 -0
  25. relationalai/semantics/metamodel/metamodel_analyzer.py +519 -0
  26. relationalai/semantics/metamodel/pprint.py +412 -0
  27. relationalai/semantics/metamodel/rewriter.py +266 -0
  28. relationalai/semantics/metamodel/typer.py +1378 -0
  29. relationalai/semantics/std/__init__.py +60 -40
  30. relationalai/semantics/std/aggregates.py +149 -0
  31. relationalai/semantics/std/common.py +44 -0
  32. relationalai/semantics/std/constraints.py +37 -43
  33. relationalai/semantics/std/datetime.py +246 -135
  34. relationalai/semantics/std/decimals.py +45 -52
  35. relationalai/semantics/std/floats.py +13 -5
  36. relationalai/semantics/std/integers.py +26 -11
  37. relationalai/semantics/std/math.py +183 -112
  38. relationalai/semantics/std/numbers.py +86 -0
  39. relationalai/semantics/std/re.py +80 -62
  40. relationalai/semantics/std/strings.py +117 -60
  41. relationalai/shims/executor.py +147 -0
  42. relationalai/shims/helpers.py +126 -0
  43. relationalai/shims/hoister.py +221 -0
  44. relationalai/shims/mm2v0.py +1290 -0
  45. relationalai/tools/cli/__init__.py +6 -0
  46. relationalai/tools/cli/cli.py +90 -0
  47. relationalai/tools/cli/components/__init__.py +5 -0
  48. relationalai/tools/cli/components/progress_reader.py +1524 -0
  49. relationalai/tools/cli/components/utils.py +58 -0
  50. relationalai/tools/cli/config_template.py +45 -0
  51. relationalai/tools/cli/dev.py +19 -0
  52. relationalai/tools/debugger.py +289 -183
  53. relationalai/tools/typer_debugger.py +93 -0
  54. relationalai/util/dataclasses.py +43 -0
  55. relationalai/util/docutils.py +40 -0
  56. relationalai/util/error.py +199 -0
  57. relationalai/util/format.py +48 -106
  58. relationalai/util/naming.py +145 -0
  59. relationalai/util/python.py +35 -0
  60. relationalai/util/runtime.py +156 -0
  61. relationalai/util/schema.py +197 -0
  62. relationalai/util/source.py +185 -0
  63. relationalai/util/structures.py +163 -0
  64. relationalai/util/tracing.py +261 -0
  65. relationalai-0.13.0.dev0.dist-info/METADATA +46 -0
  66. relationalai-0.13.0.dev0.dist-info/RECORD +488 -0
  67. relationalai-0.13.0.dev0.dist-info/WHEEL +5 -0
  68. relationalai-0.13.0.dev0.dist-info/entry_points.txt +3 -0
  69. relationalai-0.13.0.dev0.dist-info/top_level.txt +2 -0
  70. v0/relationalai/__init__.py +216 -0
  71. v0/relationalai/clients/__init__.py +5 -0
  72. v0/relationalai/clients/azure.py +477 -0
  73. v0/relationalai/clients/client.py +912 -0
  74. v0/relationalai/clients/config.py +673 -0
  75. v0/relationalai/clients/direct_access_client.py +118 -0
  76. v0/relationalai/clients/hash_util.py +31 -0
  77. v0/relationalai/clients/local.py +571 -0
  78. v0/relationalai/clients/profile_polling.py +73 -0
  79. v0/relationalai/clients/result_helpers.py +420 -0
  80. v0/relationalai/clients/snowflake.py +3869 -0
  81. v0/relationalai/clients/types.py +113 -0
  82. v0/relationalai/clients/use_index_poller.py +980 -0
  83. v0/relationalai/clients/util.py +356 -0
  84. v0/relationalai/debugging.py +389 -0
  85. v0/relationalai/dsl.py +1749 -0
  86. v0/relationalai/early_access/builder/__init__.py +30 -0
  87. v0/relationalai/early_access/builder/builder/__init__.py +35 -0
  88. v0/relationalai/early_access/builder/snowflake/__init__.py +12 -0
  89. v0/relationalai/early_access/builder/std/__init__.py +25 -0
  90. v0/relationalai/early_access/builder/std/decimals/__init__.py +12 -0
  91. v0/relationalai/early_access/builder/std/integers/__init__.py +12 -0
  92. v0/relationalai/early_access/builder/std/math/__init__.py +12 -0
  93. v0/relationalai/early_access/builder/std/strings/__init__.py +14 -0
  94. v0/relationalai/early_access/devtools/__init__.py +12 -0
  95. v0/relationalai/early_access/devtools/benchmark_lqp/__init__.py +12 -0
  96. v0/relationalai/early_access/devtools/extract_lqp/__init__.py +12 -0
  97. v0/relationalai/early_access/dsl/adapters/orm/adapter_qb.py +427 -0
  98. v0/relationalai/early_access/dsl/adapters/orm/parser.py +636 -0
  99. v0/relationalai/early_access/dsl/adapters/owl/adapter.py +176 -0
  100. v0/relationalai/early_access/dsl/adapters/owl/parser.py +160 -0
  101. v0/relationalai/early_access/dsl/bindings/common.py +402 -0
  102. v0/relationalai/early_access/dsl/bindings/csv.py +170 -0
  103. v0/relationalai/early_access/dsl/bindings/legacy/binding_models.py +143 -0
  104. v0/relationalai/early_access/dsl/bindings/snowflake.py +64 -0
  105. v0/relationalai/early_access/dsl/codegen/binder.py +411 -0
  106. v0/relationalai/early_access/dsl/codegen/common.py +79 -0
  107. v0/relationalai/early_access/dsl/codegen/helpers.py +23 -0
  108. v0/relationalai/early_access/dsl/codegen/relations.py +700 -0
  109. v0/relationalai/early_access/dsl/codegen/weaver.py +417 -0
  110. v0/relationalai/early_access/dsl/core/builders/__init__.py +47 -0
  111. v0/relationalai/early_access/dsl/core/builders/logic.py +19 -0
  112. v0/relationalai/early_access/dsl/core/builders/scalar_constraint.py +11 -0
  113. v0/relationalai/early_access/dsl/core/constraints/predicate/atomic.py +455 -0
  114. v0/relationalai/early_access/dsl/core/constraints/predicate/universal.py +73 -0
  115. v0/relationalai/early_access/dsl/core/constraints/scalar.py +310 -0
  116. v0/relationalai/early_access/dsl/core/context.py +13 -0
  117. v0/relationalai/early_access/dsl/core/cset.py +132 -0
  118. v0/relationalai/early_access/dsl/core/exprs/__init__.py +116 -0
  119. v0/relationalai/early_access/dsl/core/exprs/relational.py +18 -0
  120. v0/relationalai/early_access/dsl/core/exprs/scalar.py +412 -0
  121. v0/relationalai/early_access/dsl/core/instances.py +44 -0
  122. v0/relationalai/early_access/dsl/core/logic/__init__.py +193 -0
  123. v0/relationalai/early_access/dsl/core/logic/aggregation.py +98 -0
  124. v0/relationalai/early_access/dsl/core/logic/exists.py +223 -0
  125. v0/relationalai/early_access/dsl/core/logic/helper.py +163 -0
  126. v0/relationalai/early_access/dsl/core/namespaces.py +32 -0
  127. v0/relationalai/early_access/dsl/core/relations.py +276 -0
  128. v0/relationalai/early_access/dsl/core/rules.py +112 -0
  129. v0/relationalai/early_access/dsl/core/std/__init__.py +45 -0
  130. v0/relationalai/early_access/dsl/core/temporal/recall.py +6 -0
  131. v0/relationalai/early_access/dsl/core/types/__init__.py +270 -0
  132. v0/relationalai/early_access/dsl/core/types/concepts.py +128 -0
  133. v0/relationalai/early_access/dsl/core/types/constrained/__init__.py +267 -0
  134. v0/relationalai/early_access/dsl/core/types/constrained/nominal.py +143 -0
  135. v0/relationalai/early_access/dsl/core/types/constrained/subtype.py +124 -0
  136. v0/relationalai/early_access/dsl/core/types/standard.py +92 -0
  137. v0/relationalai/early_access/dsl/core/types/unconstrained.py +50 -0
  138. v0/relationalai/early_access/dsl/core/types/variables.py +203 -0
  139. v0/relationalai/early_access/dsl/ir/compiler.py +318 -0
  140. v0/relationalai/early_access/dsl/ir/executor.py +260 -0
  141. v0/relationalai/early_access/dsl/ontologies/constraints.py +88 -0
  142. v0/relationalai/early_access/dsl/ontologies/export.py +30 -0
  143. v0/relationalai/early_access/dsl/ontologies/models.py +453 -0
  144. v0/relationalai/early_access/dsl/ontologies/python_printer.py +303 -0
  145. v0/relationalai/early_access/dsl/ontologies/readings.py +60 -0
  146. v0/relationalai/early_access/dsl/ontologies/relationships.py +322 -0
  147. v0/relationalai/early_access/dsl/ontologies/roles.py +87 -0
  148. v0/relationalai/early_access/dsl/ontologies/subtyping.py +55 -0
  149. v0/relationalai/early_access/dsl/orm/constraints.py +438 -0
  150. v0/relationalai/early_access/dsl/orm/measures/dimensions.py +200 -0
  151. v0/relationalai/early_access/dsl/orm/measures/initializer.py +16 -0
  152. v0/relationalai/early_access/dsl/orm/measures/measure_rules.py +275 -0
  153. v0/relationalai/early_access/dsl/orm/measures/measures.py +299 -0
  154. v0/relationalai/early_access/dsl/orm/measures/role_exprs.py +268 -0
  155. v0/relationalai/early_access/dsl/orm/models.py +256 -0
  156. v0/relationalai/early_access/dsl/orm/object_oriented_printer.py +344 -0
  157. v0/relationalai/early_access/dsl/orm/printer.py +469 -0
  158. v0/relationalai/early_access/dsl/orm/reasoners.py +480 -0
  159. v0/relationalai/early_access/dsl/orm/relations.py +19 -0
  160. v0/relationalai/early_access/dsl/orm/relationships.py +251 -0
  161. v0/relationalai/early_access/dsl/orm/types.py +42 -0
  162. v0/relationalai/early_access/dsl/orm/utils.py +79 -0
  163. v0/relationalai/early_access/dsl/orm/verb.py +204 -0
  164. v0/relationalai/early_access/dsl/physical_metadata/tables.py +133 -0
  165. v0/relationalai/early_access/dsl/relations.py +170 -0
  166. v0/relationalai/early_access/dsl/rulesets.py +69 -0
  167. v0/relationalai/early_access/dsl/schemas/__init__.py +450 -0
  168. v0/relationalai/early_access/dsl/schemas/builder.py +48 -0
  169. v0/relationalai/early_access/dsl/schemas/comp_names.py +51 -0
  170. v0/relationalai/early_access/dsl/schemas/components.py +203 -0
  171. v0/relationalai/early_access/dsl/schemas/contexts.py +156 -0
  172. v0/relationalai/early_access/dsl/schemas/exprs.py +89 -0
  173. v0/relationalai/early_access/dsl/schemas/fragments.py +464 -0
  174. v0/relationalai/early_access/dsl/serialization.py +79 -0
  175. v0/relationalai/early_access/dsl/serialize/exporter.py +163 -0
  176. v0/relationalai/early_access/dsl/snow/api.py +104 -0
  177. v0/relationalai/early_access/dsl/snow/common.py +76 -0
  178. v0/relationalai/early_access/dsl/state_mgmt/__init__.py +129 -0
  179. v0/relationalai/early_access/dsl/state_mgmt/state_charts.py +125 -0
  180. v0/relationalai/early_access/dsl/state_mgmt/transitions.py +130 -0
  181. v0/relationalai/early_access/dsl/types/__init__.py +40 -0
  182. v0/relationalai/early_access/dsl/types/concepts.py +12 -0
  183. v0/relationalai/early_access/dsl/types/entities.py +135 -0
  184. v0/relationalai/early_access/dsl/types/values.py +17 -0
  185. v0/relationalai/early_access/dsl/utils.py +102 -0
  186. v0/relationalai/early_access/graphs/__init__.py +13 -0
  187. v0/relationalai/early_access/lqp/__init__.py +12 -0
  188. v0/relationalai/early_access/lqp/compiler/__init__.py +12 -0
  189. v0/relationalai/early_access/lqp/constructors/__init__.py +18 -0
  190. v0/relationalai/early_access/lqp/executor/__init__.py +12 -0
  191. v0/relationalai/early_access/lqp/ir/__init__.py +12 -0
  192. v0/relationalai/early_access/lqp/passes/__init__.py +12 -0
  193. v0/relationalai/early_access/lqp/pragmas/__init__.py +12 -0
  194. v0/relationalai/early_access/lqp/primitives/__init__.py +12 -0
  195. v0/relationalai/early_access/lqp/types/__init__.py +12 -0
  196. v0/relationalai/early_access/lqp/utils/__init__.py +12 -0
  197. v0/relationalai/early_access/lqp/validators/__init__.py +12 -0
  198. v0/relationalai/early_access/metamodel/__init__.py +58 -0
  199. v0/relationalai/early_access/metamodel/builtins/__init__.py +12 -0
  200. v0/relationalai/early_access/metamodel/compiler/__init__.py +12 -0
  201. v0/relationalai/early_access/metamodel/dependency/__init__.py +12 -0
  202. v0/relationalai/early_access/metamodel/factory/__init__.py +17 -0
  203. v0/relationalai/early_access/metamodel/helpers/__init__.py +12 -0
  204. v0/relationalai/early_access/metamodel/ir/__init__.py +14 -0
  205. v0/relationalai/early_access/metamodel/rewrite/__init__.py +7 -0
  206. v0/relationalai/early_access/metamodel/typer/__init__.py +3 -0
  207. v0/relationalai/early_access/metamodel/typer/typer/__init__.py +12 -0
  208. v0/relationalai/early_access/metamodel/types/__init__.py +15 -0
  209. v0/relationalai/early_access/metamodel/util/__init__.py +15 -0
  210. v0/relationalai/early_access/metamodel/visitor/__init__.py +12 -0
  211. v0/relationalai/early_access/rel/__init__.py +12 -0
  212. v0/relationalai/early_access/rel/executor/__init__.py +12 -0
  213. v0/relationalai/early_access/rel/rel_utils/__init__.py +12 -0
  214. v0/relationalai/early_access/rel/rewrite/__init__.py +7 -0
  215. v0/relationalai/early_access/solvers/__init__.py +19 -0
  216. v0/relationalai/early_access/sql/__init__.py +11 -0
  217. v0/relationalai/early_access/sql/executor/__init__.py +3 -0
  218. v0/relationalai/early_access/sql/rewrite/__init__.py +3 -0
  219. v0/relationalai/early_access/tests/logging/__init__.py +12 -0
  220. v0/relationalai/early_access/tests/test_snapshot_base/__init__.py +12 -0
  221. v0/relationalai/early_access/tests/utils/__init__.py +12 -0
  222. v0/relationalai/environments/__init__.py +35 -0
  223. v0/relationalai/environments/base.py +381 -0
  224. v0/relationalai/environments/colab.py +14 -0
  225. v0/relationalai/environments/generic.py +71 -0
  226. v0/relationalai/environments/ipython.py +68 -0
  227. v0/relationalai/environments/jupyter.py +9 -0
  228. v0/relationalai/environments/snowbook.py +169 -0
  229. v0/relationalai/errors.py +2455 -0
  230. v0/relationalai/experimental/SF.py +38 -0
  231. v0/relationalai/experimental/inspect.py +47 -0
  232. v0/relationalai/experimental/pathfinder/__init__.py +158 -0
  233. v0/relationalai/experimental/pathfinder/api.py +160 -0
  234. v0/relationalai/experimental/pathfinder/automaton.py +584 -0
  235. v0/relationalai/experimental/pathfinder/bridge.py +226 -0
  236. v0/relationalai/experimental/pathfinder/compiler.py +416 -0
  237. v0/relationalai/experimental/pathfinder/datalog.py +214 -0
  238. v0/relationalai/experimental/pathfinder/diagnostics.py +56 -0
  239. v0/relationalai/experimental/pathfinder/filter.py +236 -0
  240. v0/relationalai/experimental/pathfinder/glushkov.py +439 -0
  241. v0/relationalai/experimental/pathfinder/options.py +265 -0
  242. v0/relationalai/experimental/pathfinder/rpq.py +344 -0
  243. v0/relationalai/experimental/pathfinder/transition.py +200 -0
  244. v0/relationalai/experimental/pathfinder/utils.py +26 -0
  245. v0/relationalai/experimental/paths/api.py +143 -0
  246. v0/relationalai/experimental/paths/benchmarks/grid_graph.py +37 -0
  247. v0/relationalai/experimental/paths/examples/basic_example.py +40 -0
  248. v0/relationalai/experimental/paths/examples/minimal_engine_warmup.py +3 -0
  249. v0/relationalai/experimental/paths/examples/movie_example.py +77 -0
  250. v0/relationalai/experimental/paths/examples/paths_benchmark.py +115 -0
  251. v0/relationalai/experimental/paths/examples/paths_example.py +116 -0
  252. v0/relationalai/experimental/paths/examples/pattern_to_automaton.py +28 -0
  253. v0/relationalai/experimental/paths/find_paths_via_automaton.py +85 -0
  254. v0/relationalai/experimental/paths/graph.py +185 -0
  255. v0/relationalai/experimental/paths/path_algorithms/find_paths.py +280 -0
  256. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +26 -0
  257. v0/relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +111 -0
  258. v0/relationalai/experimental/paths/path_algorithms/single.py +59 -0
  259. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +39 -0
  260. v0/relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +103 -0
  261. v0/relationalai/experimental/paths/path_algorithms/usp-old.py +130 -0
  262. v0/relationalai/experimental/paths/path_algorithms/usp-tuple.py +183 -0
  263. v0/relationalai/experimental/paths/path_algorithms/usp.py +150 -0
  264. v0/relationalai/experimental/paths/product_graph.py +93 -0
  265. v0/relationalai/experimental/paths/rpq/automaton.py +584 -0
  266. v0/relationalai/experimental/paths/rpq/diagnostics.py +56 -0
  267. v0/relationalai/experimental/paths/rpq/rpq.py +378 -0
  268. v0/relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +90 -0
  269. v0/relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +119 -0
  270. v0/relationalai/experimental/paths/tests/tests_limit_sp_single.py +104 -0
  271. v0/relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +113 -0
  272. v0/relationalai/experimental/paths/tests/tests_limit_walks_single.py +149 -0
  273. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +70 -0
  274. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +64 -0
  275. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +115 -0
  276. v0/relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +75 -0
  277. v0/relationalai/experimental/paths/tests/tests_single_paths.py +152 -0
  278. v0/relationalai/experimental/paths/tests/tests_single_walks.py +208 -0
  279. v0/relationalai/experimental/paths/tests/tests_single_walks_undirected.py +297 -0
  280. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +107 -0
  281. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +76 -0
  282. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +76 -0
  283. v0/relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +110 -0
  284. v0/relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +229 -0
  285. v0/relationalai/experimental/paths/tests/tests_usp_nsp_single.py +108 -0
  286. v0/relationalai/experimental/paths/tree_agg.py +168 -0
  287. v0/relationalai/experimental/paths/utilities/iterators.py +27 -0
  288. v0/relationalai/experimental/paths/utilities/prefix_sum.py +91 -0
  289. v0/relationalai/experimental/solvers.py +1087 -0
  290. v0/relationalai/loaders/__init__.py +0 -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 +324 -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 +469 -0
  306. v0/relationalai/semantics/lqp/intrinsics.py +24 -0
  307. v0/relationalai/semantics/lqp/model2lqp.py +839 -0
  308. v0/relationalai/semantics/lqp/passes.py +680 -0
  309. v0/relationalai/semantics/lqp/primitives.py +252 -0
  310. v0/relationalai/semantics/lqp/result_helpers.py +202 -0
  311. v0/relationalai/semantics/lqp/rewrite/annotate_constraints.py +57 -0
  312. v0/relationalai/semantics/lqp/rewrite/cdc.py +216 -0
  313. v0/relationalai/semantics/lqp/rewrite/extract_common.py +338 -0
  314. v0/relationalai/semantics/lqp/rewrite/extract_keys.py +449 -0
  315. v0/relationalai/semantics/lqp/rewrite/function_annotations.py +114 -0
  316. v0/relationalai/semantics/lqp/rewrite/functional_dependencies.py +314 -0
  317. v0/relationalai/semantics/lqp/rewrite/quantify_vars.py +296 -0
  318. v0/relationalai/semantics/lqp/rewrite/splinter.py +76 -0
  319. v0/relationalai/semantics/lqp/types.py +101 -0
  320. v0/relationalai/semantics/lqp/utils.py +160 -0
  321. v0/relationalai/semantics/lqp/validators.py +57 -0
  322. v0/relationalai/semantics/metamodel/__init__.py +40 -0
  323. v0/relationalai/semantics/metamodel/builtins.py +774 -0
  324. v0/relationalai/semantics/metamodel/compiler.py +133 -0
  325. v0/relationalai/semantics/metamodel/dependency.py +862 -0
  326. v0/relationalai/semantics/metamodel/executor.py +61 -0
  327. v0/relationalai/semantics/metamodel/factory.py +287 -0
  328. v0/relationalai/semantics/metamodel/helpers.py +361 -0
  329. v0/relationalai/semantics/metamodel/rewrite/discharge_constraints.py +39 -0
  330. v0/relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +210 -0
  331. v0/relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +78 -0
  332. v0/relationalai/semantics/metamodel/rewrite/flatten.py +549 -0
  333. v0/relationalai/semantics/metamodel/rewrite/format_outputs.py +165 -0
  334. v0/relationalai/semantics/metamodel/typer/checker.py +353 -0
  335. v0/relationalai/semantics/metamodel/typer/typer.py +1395 -0
  336. v0/relationalai/semantics/metamodel/util.py +505 -0
  337. v0/relationalai/semantics/reasoners/__init__.py +10 -0
  338. v0/relationalai/semantics/reasoners/graph/__init__.py +37 -0
  339. v0/relationalai/semantics/reasoners/graph/core.py +9020 -0
  340. v0/relationalai/semantics/reasoners/optimization/__init__.py +68 -0
  341. v0/relationalai/semantics/reasoners/optimization/common.py +88 -0
  342. v0/relationalai/semantics/reasoners/optimization/solvers_dev.py +568 -0
  343. v0/relationalai/semantics/reasoners/optimization/solvers_pb.py +1163 -0
  344. v0/relationalai/semantics/rel/builtins.py +40 -0
  345. v0/relationalai/semantics/rel/compiler.py +989 -0
  346. v0/relationalai/semantics/rel/executor.py +359 -0
  347. v0/relationalai/semantics/rel/rel.py +482 -0
  348. v0/relationalai/semantics/rel/rel_utils.py +276 -0
  349. v0/relationalai/semantics/snowflake/__init__.py +3 -0
  350. v0/relationalai/semantics/sql/compiler.py +2503 -0
  351. v0/relationalai/semantics/sql/executor/duck_db.py +52 -0
  352. v0/relationalai/semantics/sql/executor/result_helpers.py +64 -0
  353. v0/relationalai/semantics/sql/executor/snowflake.py +145 -0
  354. v0/relationalai/semantics/sql/rewrite/denormalize.py +222 -0
  355. v0/relationalai/semantics/sql/rewrite/double_negation.py +49 -0
  356. v0/relationalai/semantics/sql/rewrite/recursive_union.py +127 -0
  357. v0/relationalai/semantics/sql/rewrite/sort_output_query.py +246 -0
  358. v0/relationalai/semantics/sql/sql.py +504 -0
  359. v0/relationalai/semantics/std/__init__.py +54 -0
  360. v0/relationalai/semantics/std/constraints.py +43 -0
  361. v0/relationalai/semantics/std/datetime.py +363 -0
  362. v0/relationalai/semantics/std/decimals.py +62 -0
  363. v0/relationalai/semantics/std/floats.py +7 -0
  364. v0/relationalai/semantics/std/integers.py +22 -0
  365. v0/relationalai/semantics/std/math.py +141 -0
  366. v0/relationalai/semantics/std/pragmas.py +11 -0
  367. v0/relationalai/semantics/std/re.py +83 -0
  368. v0/relationalai/semantics/std/std.py +14 -0
  369. v0/relationalai/semantics/std/strings.py +63 -0
  370. v0/relationalai/semantics/tests/__init__.py +0 -0
  371. v0/relationalai/semantics/tests/test_snapshot_abstract.py +143 -0
  372. v0/relationalai/semantics/tests/test_snapshot_base.py +9 -0
  373. v0/relationalai/semantics/tests/utils.py +46 -0
  374. v0/relationalai/std/__init__.py +70 -0
  375. v0/relationalai/tools/__init__.py +0 -0
  376. v0/relationalai/tools/cli.py +1940 -0
  377. v0/relationalai/tools/cli_controls.py +1826 -0
  378. v0/relationalai/tools/cli_helpers.py +390 -0
  379. v0/relationalai/tools/debugger.py +183 -0
  380. v0/relationalai/tools/debugger_client.py +109 -0
  381. v0/relationalai/tools/debugger_server.py +302 -0
  382. v0/relationalai/tools/dev.py +685 -0
  383. v0/relationalai/tools/qb_debugger.py +425 -0
  384. v0/relationalai/util/clean_up_databases.py +95 -0
  385. v0/relationalai/util/format.py +123 -0
  386. v0/relationalai/util/list_databases.py +9 -0
  387. v0/relationalai/util/otel_configuration.py +25 -0
  388. v0/relationalai/util/otel_handler.py +484 -0
  389. v0/relationalai/util/snowflake_handler.py +88 -0
  390. v0/relationalai/util/span_format_test.py +43 -0
  391. v0/relationalai/util/span_tracker.py +207 -0
  392. v0/relationalai/util/spans_file_handler.py +72 -0
  393. v0/relationalai/util/tracing_handler.py +34 -0
  394. frontend/debugger/dist/.gitignore +0 -2
  395. frontend/debugger/dist/assets/favicon-Dy0ZgA6N.png +0 -0
  396. frontend/debugger/dist/assets/index-Cssla-O7.js +0 -208
  397. frontend/debugger/dist/assets/index-DlHsYx1V.css +0 -9
  398. frontend/debugger/dist/index.html +0 -17
  399. relationalai/clients/__init__.py +0 -18
  400. relationalai/clients/client.py +0 -912
  401. relationalai/clients/config.py +0 -673
  402. relationalai/clients/direct_access_client.py +0 -118
  403. relationalai/clients/hash_util.py +0 -31
  404. relationalai/clients/local.py +0 -571
  405. relationalai/clients/profile_polling.py +0 -73
  406. relationalai/clients/resources/__init__.py +0 -8
  407. relationalai/clients/resources/azure/azure.py +0 -477
  408. relationalai/clients/resources/snowflake/__init__.py +0 -20
  409. relationalai/clients/resources/snowflake/cli_resources.py +0 -87
  410. relationalai/clients/resources/snowflake/direct_access_resources.py +0 -711
  411. relationalai/clients/resources/snowflake/engine_state_handlers.py +0 -309
  412. relationalai/clients/resources/snowflake/error_handlers.py +0 -199
  413. relationalai/clients/resources/snowflake/export_procedure.py.jinja +0 -249
  414. relationalai/clients/resources/snowflake/resources_factory.py +0 -99
  415. relationalai/clients/resources/snowflake/snowflake.py +0 -3083
  416. relationalai/clients/resources/snowflake/use_index_poller.py +0 -1011
  417. relationalai/clients/resources/snowflake/use_index_resources.py +0 -188
  418. relationalai/clients/resources/snowflake/util.py +0 -387
  419. relationalai/clients/result_helpers.py +0 -420
  420. relationalai/clients/types.py +0 -113
  421. relationalai/clients/util.py +0 -356
  422. relationalai/debugging.py +0 -389
  423. relationalai/dsl.py +0 -1749
  424. relationalai/early_access/builder/__init__.py +0 -30
  425. relationalai/early_access/builder/builder/__init__.py +0 -35
  426. relationalai/early_access/builder/snowflake/__init__.py +0 -12
  427. relationalai/early_access/builder/std/__init__.py +0 -25
  428. relationalai/early_access/builder/std/decimals/__init__.py +0 -12
  429. relationalai/early_access/builder/std/integers/__init__.py +0 -12
  430. relationalai/early_access/builder/std/math/__init__.py +0 -12
  431. relationalai/early_access/builder/std/strings/__init__.py +0 -14
  432. relationalai/early_access/devtools/__init__.py +0 -12
  433. relationalai/early_access/devtools/benchmark_lqp/__init__.py +0 -12
  434. relationalai/early_access/devtools/extract_lqp/__init__.py +0 -12
  435. relationalai/early_access/dsl/adapters/orm/adapter_qb.py +0 -427
  436. relationalai/early_access/dsl/adapters/orm/parser.py +0 -636
  437. relationalai/early_access/dsl/adapters/owl/adapter.py +0 -176
  438. relationalai/early_access/dsl/adapters/owl/parser.py +0 -160
  439. relationalai/early_access/dsl/bindings/common.py +0 -402
  440. relationalai/early_access/dsl/bindings/csv.py +0 -170
  441. relationalai/early_access/dsl/bindings/legacy/binding_models.py +0 -143
  442. relationalai/early_access/dsl/bindings/snowflake.py +0 -64
  443. relationalai/early_access/dsl/codegen/binder.py +0 -411
  444. relationalai/early_access/dsl/codegen/common.py +0 -79
  445. relationalai/early_access/dsl/codegen/helpers.py +0 -23
  446. relationalai/early_access/dsl/codegen/relations.py +0 -700
  447. relationalai/early_access/dsl/codegen/weaver.py +0 -417
  448. relationalai/early_access/dsl/core/builders/__init__.py +0 -47
  449. relationalai/early_access/dsl/core/builders/logic.py +0 -19
  450. relationalai/early_access/dsl/core/builders/scalar_constraint.py +0 -11
  451. relationalai/early_access/dsl/core/constraints/predicate/atomic.py +0 -455
  452. relationalai/early_access/dsl/core/constraints/predicate/universal.py +0 -73
  453. relationalai/early_access/dsl/core/constraints/scalar.py +0 -310
  454. relationalai/early_access/dsl/core/context.py +0 -13
  455. relationalai/early_access/dsl/core/cset.py +0 -132
  456. relationalai/early_access/dsl/core/exprs/__init__.py +0 -116
  457. relationalai/early_access/dsl/core/exprs/relational.py +0 -18
  458. relationalai/early_access/dsl/core/exprs/scalar.py +0 -412
  459. relationalai/early_access/dsl/core/instances.py +0 -44
  460. relationalai/early_access/dsl/core/logic/__init__.py +0 -193
  461. relationalai/early_access/dsl/core/logic/aggregation.py +0 -98
  462. relationalai/early_access/dsl/core/logic/exists.py +0 -223
  463. relationalai/early_access/dsl/core/logic/helper.py +0 -163
  464. relationalai/early_access/dsl/core/namespaces.py +0 -32
  465. relationalai/early_access/dsl/core/relations.py +0 -276
  466. relationalai/early_access/dsl/core/rules.py +0 -112
  467. relationalai/early_access/dsl/core/std/__init__.py +0 -45
  468. relationalai/early_access/dsl/core/temporal/recall.py +0 -6
  469. relationalai/early_access/dsl/core/types/__init__.py +0 -270
  470. relationalai/early_access/dsl/core/types/concepts.py +0 -128
  471. relationalai/early_access/dsl/core/types/constrained/__init__.py +0 -267
  472. relationalai/early_access/dsl/core/types/constrained/nominal.py +0 -143
  473. relationalai/early_access/dsl/core/types/constrained/subtype.py +0 -124
  474. relationalai/early_access/dsl/core/types/standard.py +0 -92
  475. relationalai/early_access/dsl/core/types/unconstrained.py +0 -50
  476. relationalai/early_access/dsl/core/types/variables.py +0 -203
  477. relationalai/early_access/dsl/ir/compiler.py +0 -318
  478. relationalai/early_access/dsl/ir/executor.py +0 -260
  479. relationalai/early_access/dsl/ontologies/constraints.py +0 -88
  480. relationalai/early_access/dsl/ontologies/export.py +0 -30
  481. relationalai/early_access/dsl/ontologies/models.py +0 -453
  482. relationalai/early_access/dsl/ontologies/python_printer.py +0 -303
  483. relationalai/early_access/dsl/ontologies/readings.py +0 -60
  484. relationalai/early_access/dsl/ontologies/relationships.py +0 -322
  485. relationalai/early_access/dsl/ontologies/roles.py +0 -87
  486. relationalai/early_access/dsl/ontologies/subtyping.py +0 -55
  487. relationalai/early_access/dsl/orm/constraints.py +0 -438
  488. relationalai/early_access/dsl/orm/measures/dimensions.py +0 -200
  489. relationalai/early_access/dsl/orm/measures/initializer.py +0 -16
  490. relationalai/early_access/dsl/orm/measures/measure_rules.py +0 -275
  491. relationalai/early_access/dsl/orm/measures/measures.py +0 -299
  492. relationalai/early_access/dsl/orm/measures/role_exprs.py +0 -268
  493. relationalai/early_access/dsl/orm/models.py +0 -256
  494. relationalai/early_access/dsl/orm/object_oriented_printer.py +0 -344
  495. relationalai/early_access/dsl/orm/printer.py +0 -469
  496. relationalai/early_access/dsl/orm/reasoners.py +0 -480
  497. relationalai/early_access/dsl/orm/relations.py +0 -19
  498. relationalai/early_access/dsl/orm/relationships.py +0 -251
  499. relationalai/early_access/dsl/orm/types.py +0 -42
  500. relationalai/early_access/dsl/orm/utils.py +0 -79
  501. relationalai/early_access/dsl/orm/verb.py +0 -204
  502. relationalai/early_access/dsl/physical_metadata/tables.py +0 -133
  503. relationalai/early_access/dsl/relations.py +0 -170
  504. relationalai/early_access/dsl/rulesets.py +0 -69
  505. relationalai/early_access/dsl/schemas/__init__.py +0 -450
  506. relationalai/early_access/dsl/schemas/builder.py +0 -48
  507. relationalai/early_access/dsl/schemas/comp_names.py +0 -51
  508. relationalai/early_access/dsl/schemas/components.py +0 -203
  509. relationalai/early_access/dsl/schemas/contexts.py +0 -156
  510. relationalai/early_access/dsl/schemas/exprs.py +0 -89
  511. relationalai/early_access/dsl/schemas/fragments.py +0 -464
  512. relationalai/early_access/dsl/serialization.py +0 -79
  513. relationalai/early_access/dsl/serialize/exporter.py +0 -163
  514. relationalai/early_access/dsl/snow/api.py +0 -105
  515. relationalai/early_access/dsl/snow/common.py +0 -76
  516. relationalai/early_access/dsl/state_mgmt/__init__.py +0 -129
  517. relationalai/early_access/dsl/state_mgmt/state_charts.py +0 -125
  518. relationalai/early_access/dsl/state_mgmt/transitions.py +0 -130
  519. relationalai/early_access/dsl/types/__init__.py +0 -40
  520. relationalai/early_access/dsl/types/concepts.py +0 -12
  521. relationalai/early_access/dsl/types/entities.py +0 -135
  522. relationalai/early_access/dsl/types/values.py +0 -17
  523. relationalai/early_access/dsl/utils.py +0 -102
  524. relationalai/early_access/graphs/__init__.py +0 -13
  525. relationalai/early_access/lqp/__init__.py +0 -12
  526. relationalai/early_access/lqp/compiler/__init__.py +0 -12
  527. relationalai/early_access/lqp/constructors/__init__.py +0 -18
  528. relationalai/early_access/lqp/executor/__init__.py +0 -12
  529. relationalai/early_access/lqp/ir/__init__.py +0 -12
  530. relationalai/early_access/lqp/passes/__init__.py +0 -12
  531. relationalai/early_access/lqp/pragmas/__init__.py +0 -12
  532. relationalai/early_access/lqp/primitives/__init__.py +0 -12
  533. relationalai/early_access/lqp/types/__init__.py +0 -12
  534. relationalai/early_access/lqp/utils/__init__.py +0 -12
  535. relationalai/early_access/lqp/validators/__init__.py +0 -12
  536. relationalai/early_access/metamodel/__init__.py +0 -58
  537. relationalai/early_access/metamodel/builtins/__init__.py +0 -12
  538. relationalai/early_access/metamodel/compiler/__init__.py +0 -12
  539. relationalai/early_access/metamodel/dependency/__init__.py +0 -12
  540. relationalai/early_access/metamodel/factory/__init__.py +0 -17
  541. relationalai/early_access/metamodel/helpers/__init__.py +0 -12
  542. relationalai/early_access/metamodel/ir/__init__.py +0 -14
  543. relationalai/early_access/metamodel/rewrite/__init__.py +0 -7
  544. relationalai/early_access/metamodel/typer/__init__.py +0 -3
  545. relationalai/early_access/metamodel/typer/typer/__init__.py +0 -12
  546. relationalai/early_access/metamodel/types/__init__.py +0 -15
  547. relationalai/early_access/metamodel/util/__init__.py +0 -15
  548. relationalai/early_access/metamodel/visitor/__init__.py +0 -12
  549. relationalai/early_access/rel/__init__.py +0 -12
  550. relationalai/early_access/rel/executor/__init__.py +0 -12
  551. relationalai/early_access/rel/rel_utils/__init__.py +0 -12
  552. relationalai/early_access/rel/rewrite/__init__.py +0 -7
  553. relationalai/early_access/solvers/__init__.py +0 -19
  554. relationalai/early_access/sql/__init__.py +0 -11
  555. relationalai/early_access/sql/executor/__init__.py +0 -3
  556. relationalai/early_access/sql/rewrite/__init__.py +0 -3
  557. relationalai/early_access/tests/logging/__init__.py +0 -12
  558. relationalai/early_access/tests/test_snapshot_base/__init__.py +0 -12
  559. relationalai/early_access/tests/utils/__init__.py +0 -12
  560. relationalai/environments/__init__.py +0 -35
  561. relationalai/environments/base.py +0 -381
  562. relationalai/environments/colab.py +0 -14
  563. relationalai/environments/generic.py +0 -71
  564. relationalai/environments/ipython.py +0 -68
  565. relationalai/environments/jupyter.py +0 -9
  566. relationalai/environments/snowbook.py +0 -169
  567. relationalai/errors.py +0 -2478
  568. relationalai/experimental/SF.py +0 -38
  569. relationalai/experimental/inspect.py +0 -47
  570. relationalai/experimental/pathfinder/__init__.py +0 -158
  571. relationalai/experimental/pathfinder/api.py +0 -160
  572. relationalai/experimental/pathfinder/automaton.py +0 -584
  573. relationalai/experimental/pathfinder/bridge.py +0 -226
  574. relationalai/experimental/pathfinder/compiler.py +0 -416
  575. relationalai/experimental/pathfinder/datalog.py +0 -214
  576. relationalai/experimental/pathfinder/diagnostics.py +0 -56
  577. relationalai/experimental/pathfinder/filter.py +0 -236
  578. relationalai/experimental/pathfinder/glushkov.py +0 -439
  579. relationalai/experimental/pathfinder/options.py +0 -265
  580. relationalai/experimental/pathfinder/pathfinder-v0.7.0.rel +0 -1951
  581. relationalai/experimental/pathfinder/rpq.py +0 -344
  582. relationalai/experimental/pathfinder/transition.py +0 -200
  583. relationalai/experimental/pathfinder/utils.py +0 -26
  584. relationalai/experimental/paths/README.md +0 -107
  585. relationalai/experimental/paths/api.py +0 -143
  586. relationalai/experimental/paths/benchmarks/grid_graph.py +0 -37
  587. relationalai/experimental/paths/code_organization.md +0 -2
  588. relationalai/experimental/paths/examples/Movies.ipynb +0 -16328
  589. relationalai/experimental/paths/examples/basic_example.py +0 -40
  590. relationalai/experimental/paths/examples/minimal_engine_warmup.py +0 -3
  591. relationalai/experimental/paths/examples/movie_example.py +0 -77
  592. relationalai/experimental/paths/examples/movies_data/actedin.csv +0 -193
  593. relationalai/experimental/paths/examples/movies_data/directed.csv +0 -45
  594. relationalai/experimental/paths/examples/movies_data/follows.csv +0 -7
  595. relationalai/experimental/paths/examples/movies_data/movies.csv +0 -39
  596. relationalai/experimental/paths/examples/movies_data/person.csv +0 -134
  597. relationalai/experimental/paths/examples/movies_data/produced.csv +0 -16
  598. relationalai/experimental/paths/examples/movies_data/ratings.csv +0 -10
  599. relationalai/experimental/paths/examples/movies_data/wrote.csv +0 -11
  600. relationalai/experimental/paths/examples/paths_benchmark.py +0 -115
  601. relationalai/experimental/paths/examples/paths_example.py +0 -116
  602. relationalai/experimental/paths/examples/pattern_to_automaton.py +0 -28
  603. relationalai/experimental/paths/find_paths_via_automaton.py +0 -85
  604. relationalai/experimental/paths/graph.py +0 -185
  605. relationalai/experimental/paths/path_algorithms/find_paths.py +0 -280
  606. relationalai/experimental/paths/path_algorithms/one_sided_ball_repetition.py +0 -26
  607. relationalai/experimental/paths/path_algorithms/one_sided_ball_upto.py +0 -111
  608. relationalai/experimental/paths/path_algorithms/single.py +0 -59
  609. relationalai/experimental/paths/path_algorithms/two_sided_balls_repetition.py +0 -39
  610. relationalai/experimental/paths/path_algorithms/two_sided_balls_upto.py +0 -103
  611. relationalai/experimental/paths/path_algorithms/usp-old.py +0 -130
  612. relationalai/experimental/paths/path_algorithms/usp-tuple.py +0 -183
  613. relationalai/experimental/paths/path_algorithms/usp.py +0 -150
  614. relationalai/experimental/paths/product_graph.py +0 -93
  615. relationalai/experimental/paths/rpq/automaton.py +0 -584
  616. relationalai/experimental/paths/rpq/diagnostics.py +0 -56
  617. relationalai/experimental/paths/rpq/rpq.py +0 -378
  618. relationalai/experimental/paths/tests/tests_limit_sp_max_length.py +0 -90
  619. relationalai/experimental/paths/tests/tests_limit_sp_multiple.py +0 -119
  620. relationalai/experimental/paths/tests/tests_limit_sp_single.py +0 -104
  621. relationalai/experimental/paths/tests/tests_limit_walks_multiple.py +0 -113
  622. relationalai/experimental/paths/tests/tests_limit_walks_single.py +0 -149
  623. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_multiple.py +0 -70
  624. relationalai/experimental/paths/tests/tests_one_sided_ball_repetition_single.py +0 -64
  625. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_multiple.py +0 -115
  626. relationalai/experimental/paths/tests/tests_one_sided_ball_upto_single.py +0 -75
  627. relationalai/experimental/paths/tests/tests_single_paths.py +0 -152
  628. relationalai/experimental/paths/tests/tests_single_walks.py +0 -208
  629. relationalai/experimental/paths/tests/tests_single_walks_undirected.py +0 -297
  630. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_multiple.py +0 -107
  631. relationalai/experimental/paths/tests/tests_two_sided_balls_repetition_single.py +0 -76
  632. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_multiple.py +0 -76
  633. relationalai/experimental/paths/tests/tests_two_sided_balls_upto_single.py +0 -110
  634. relationalai/experimental/paths/tests/tests_usp_nsp_multiple.py +0 -229
  635. relationalai/experimental/paths/tests/tests_usp_nsp_single.py +0 -108
  636. relationalai/experimental/paths/tree_agg.py +0 -168
  637. relationalai/experimental/paths/utilities/iterators.py +0 -27
  638. relationalai/experimental/paths/utilities/prefix_sum.py +0 -91
  639. relationalai/experimental/solvers.py +0 -1087
  640. relationalai/loaders/csv.py +0 -195
  641. relationalai/loaders/loader.py +0 -177
  642. relationalai/loaders/types.py +0 -23
  643. relationalai/rel_emitter.py +0 -373
  644. relationalai/rel_utils.py +0 -185
  645. relationalai/semantics/designs/query_builder/identify_by.md +0 -106
  646. relationalai/semantics/devtools/benchmark_lqp.py +0 -535
  647. relationalai/semantics/devtools/compilation_manager.py +0 -294
  648. relationalai/semantics/devtools/extract_lqp.py +0 -110
  649. relationalai/semantics/internal/internal.py +0 -3785
  650. relationalai/semantics/internal/snowflake.py +0 -325
  651. relationalai/semantics/lqp/README.md +0 -34
  652. relationalai/semantics/lqp/builtins.py +0 -16
  653. relationalai/semantics/lqp/compiler.py +0 -22
  654. relationalai/semantics/lqp/constructors.py +0 -68
  655. relationalai/semantics/lqp/executor.py +0 -469
  656. relationalai/semantics/lqp/intrinsics.py +0 -24
  657. relationalai/semantics/lqp/model2lqp.py +0 -877
  658. relationalai/semantics/lqp/passes.py +0 -680
  659. relationalai/semantics/lqp/primitives.py +0 -252
  660. relationalai/semantics/lqp/result_helpers.py +0 -202
  661. relationalai/semantics/lqp/rewrite/annotate_constraints.py +0 -57
  662. relationalai/semantics/lqp/rewrite/cdc.py +0 -216
  663. relationalai/semantics/lqp/rewrite/extract_common.py +0 -338
  664. relationalai/semantics/lqp/rewrite/extract_keys.py +0 -506
  665. relationalai/semantics/lqp/rewrite/function_annotations.py +0 -114
  666. relationalai/semantics/lqp/rewrite/functional_dependencies.py +0 -314
  667. relationalai/semantics/lqp/rewrite/quantify_vars.py +0 -296
  668. relationalai/semantics/lqp/rewrite/splinter.py +0 -76
  669. relationalai/semantics/lqp/types.py +0 -101
  670. relationalai/semantics/lqp/utils.py +0 -160
  671. relationalai/semantics/lqp/validators.py +0 -57
  672. relationalai/semantics/metamodel/compiler.py +0 -133
  673. relationalai/semantics/metamodel/dependency.py +0 -862
  674. relationalai/semantics/metamodel/executor.py +0 -61
  675. relationalai/semantics/metamodel/factory.py +0 -287
  676. relationalai/semantics/metamodel/helpers.py +0 -361
  677. relationalai/semantics/metamodel/rewrite/discharge_constraints.py +0 -39
  678. relationalai/semantics/metamodel/rewrite/dnf_union_splitter.py +0 -210
  679. relationalai/semantics/metamodel/rewrite/extract_nested_logicals.py +0 -78
  680. relationalai/semantics/metamodel/rewrite/flatten.py +0 -554
  681. relationalai/semantics/metamodel/rewrite/format_outputs.py +0 -165
  682. relationalai/semantics/metamodel/typer/checker.py +0 -353
  683. relationalai/semantics/metamodel/typer/typer.py +0 -1395
  684. relationalai/semantics/metamodel/util.py +0 -506
  685. relationalai/semantics/reasoners/__init__.py +0 -10
  686. relationalai/semantics/reasoners/graph/README.md +0 -620
  687. relationalai/semantics/reasoners/graph/__init__.py +0 -37
  688. relationalai/semantics/reasoners/graph/core.py +0 -9019
  689. relationalai/semantics/reasoners/graph/design/beyond_demand_transform.md +0 -797
  690. relationalai/semantics/reasoners/graph/tests/README.md +0 -21
  691. relationalai/semantics/reasoners/optimization/__init__.py +0 -68
  692. relationalai/semantics/reasoners/optimization/common.py +0 -88
  693. relationalai/semantics/reasoners/optimization/solvers_dev.py +0 -568
  694. relationalai/semantics/reasoners/optimization/solvers_pb.py +0 -1163
  695. relationalai/semantics/rel/builtins.py +0 -40
  696. relationalai/semantics/rel/compiler.py +0 -989
  697. relationalai/semantics/rel/executor.py +0 -362
  698. relationalai/semantics/rel/rel.py +0 -482
  699. relationalai/semantics/rel/rel_utils.py +0 -276
  700. relationalai/semantics/snowflake/__init__.py +0 -3
  701. relationalai/semantics/sql/compiler.py +0 -2503
  702. relationalai/semantics/sql/executor/duck_db.py +0 -52
  703. relationalai/semantics/sql/executor/result_helpers.py +0 -64
  704. relationalai/semantics/sql/executor/snowflake.py +0 -149
  705. relationalai/semantics/sql/rewrite/denormalize.py +0 -222
  706. relationalai/semantics/sql/rewrite/double_negation.py +0 -49
  707. relationalai/semantics/sql/rewrite/recursive_union.py +0 -127
  708. relationalai/semantics/sql/rewrite/sort_output_query.py +0 -246
  709. relationalai/semantics/sql/sql.py +0 -504
  710. relationalai/semantics/std/pragmas.py +0 -11
  711. relationalai/semantics/std/std.py +0 -14
  712. relationalai/semantics/tests/test_snapshot_abstract.py +0 -143
  713. relationalai/semantics/tests/test_snapshot_base.py +0 -9
  714. relationalai/semantics/tests/utils.py +0 -46
  715. relationalai/std/__init__.py +0 -70
  716. relationalai/tools/cli.py +0 -1936
  717. relationalai/tools/cli_controls.py +0 -1826
  718. relationalai/tools/cli_helpers.py +0 -398
  719. relationalai/tools/debugger_client.py +0 -109
  720. relationalai/tools/debugger_server.py +0 -302
  721. relationalai/tools/dev.py +0 -685
  722. relationalai/tools/notes +0 -7
  723. relationalai/tools/qb_debugger.py +0 -425
  724. relationalai/util/clean_up_databases.py +0 -95
  725. relationalai/util/list_databases.py +0 -9
  726. relationalai/util/otel_configuration.py +0 -26
  727. relationalai/util/otel_handler.py +0 -484
  728. relationalai/util/snowflake_handler.py +0 -88
  729. relationalai/util/span_format_test.py +0 -43
  730. relationalai/util/span_tracker.py +0 -207
  731. relationalai/util/spans_file_handler.py +0 -72
  732. relationalai/util/tracing_handler.py +0 -34
  733. relationalai-0.13.0.dist-info/METADATA +0 -74
  734. relationalai-0.13.0.dist-info/RECORD +0 -458
  735. relationalai-0.13.0.dist-info/WHEEL +0 -4
  736. relationalai-0.13.0.dist-info/entry_points.txt +0 -3
  737. relationalai-0.13.0.dist-info/licenses/LICENSE +0 -202
  738. relationalai_test_util/__init__.py +0 -4
  739. relationalai_test_util/fixtures.py +0 -229
  740. relationalai_test_util/snapshot.py +0 -252
  741. relationalai_test_util/traceback.py +0 -118
  742. /relationalai/{analysis → semantics/frontend}/__init__.py +0 -0
  743. /relationalai/{auth/__init__.py → semantics/metamodel/metamodel_compiler.py} +0 -0
  744. /relationalai/{early_access → shims}/__init__.py +0 -0
  745. {relationalai/early_access/dsl/adapters → v0/relationalai/analysis}/__init__.py +0 -0
  746. {relationalai → v0/relationalai}/analysis/mechanistic.py +0 -0
  747. {relationalai → v0/relationalai}/analysis/whynot.py +0 -0
  748. {relationalai/early_access/dsl/adapters/orm → v0/relationalai/auth}/__init__.py +0 -0
  749. {relationalai → v0/relationalai}/auth/jwt_generator.py +0 -0
  750. {relationalai → v0/relationalai}/auth/oauth_callback_server.py +0 -0
  751. {relationalai → v0/relationalai}/auth/token_handler.py +0 -0
  752. {relationalai → v0/relationalai}/auth/util.py +0 -0
  753. {relationalai/clients/resources/snowflake → v0/relationalai/clients}/cache_store.py +0 -0
  754. {relationalai → v0/relationalai}/compiler.py +0 -0
  755. {relationalai → v0/relationalai}/dependencies.py +0 -0
  756. {relationalai → v0/relationalai}/docutils.py +0 -0
  757. {relationalai/early_access/dsl/adapters/owl → v0/relationalai/early_access}/__init__.py +0 -0
  758. {relationalai → v0/relationalai}/early_access/dsl/__init__.py +0 -0
  759. {relationalai/early_access/dsl/bindings → v0/relationalai/early_access/dsl/adapters}/__init__.py +0 -0
  760. {relationalai/early_access/dsl/bindings/legacy → v0/relationalai/early_access/dsl/adapters/orm}/__init__.py +0 -0
  761. {relationalai → v0/relationalai}/early_access/dsl/adapters/orm/model.py +0 -0
  762. {relationalai/early_access/dsl/codegen → v0/relationalai/early_access/dsl/adapters/owl}/__init__.py +0 -0
  763. {relationalai → v0/relationalai}/early_access/dsl/adapters/owl/model.py +0 -0
  764. {relationalai/early_access/dsl/core/temporal → v0/relationalai/early_access/dsl/bindings}/__init__.py +0 -0
  765. {relationalai/early_access/dsl/ir → v0/relationalai/early_access/dsl/bindings/legacy}/__init__.py +0 -0
  766. {relationalai/early_access/dsl/ontologies → v0/relationalai/early_access/dsl/codegen}/__init__.py +0 -0
  767. {relationalai → v0/relationalai}/early_access/dsl/constants.py +0 -0
  768. {relationalai → v0/relationalai}/early_access/dsl/core/__init__.py +0 -0
  769. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/__init__.py +0 -0
  770. {relationalai → v0/relationalai}/early_access/dsl/core/constraints/predicate/__init__.py +0 -0
  771. {relationalai → v0/relationalai}/early_access/dsl/core/stack.py +0 -0
  772. {relationalai/early_access/dsl/orm → v0/relationalai/early_access/dsl/core/temporal}/__init__.py +0 -0
  773. {relationalai → v0/relationalai}/early_access/dsl/core/utils.py +0 -0
  774. {relationalai/early_access/dsl/orm/measures → v0/relationalai/early_access/dsl/ir}/__init__.py +0 -0
  775. {relationalai/early_access/dsl/physical_metadata → v0/relationalai/early_access/dsl/ontologies}/__init__.py +0 -0
  776. {relationalai → v0/relationalai}/early_access/dsl/ontologies/raw_source.py +0 -0
  777. {relationalai/early_access/dsl/serialize → v0/relationalai/early_access/dsl/orm}/__init__.py +0 -0
  778. {relationalai/early_access/dsl/snow → v0/relationalai/early_access/dsl/orm/measures}/__init__.py +0 -0
  779. {relationalai → v0/relationalai}/early_access/dsl/orm/reasoner_errors.py +0 -0
  780. {relationalai/loaders → v0/relationalai/early_access/dsl/physical_metadata}/__init__.py +0 -0
  781. {relationalai/semantics/tests → v0/relationalai/early_access/dsl/serialize}/__init__.py +0 -0
  782. {relationalai → v0/relationalai}/early_access/dsl/serialize/binding_model.py +0 -0
  783. {relationalai → v0/relationalai}/early_access/dsl/serialize/model.py +0 -0
  784. {relationalai/tools → v0/relationalai/early_access/dsl/snow}/__init__.py +0 -0
  785. {relationalai → v0/relationalai}/early_access/tests/__init__.py +0 -0
  786. {relationalai → v0/relationalai}/environments/ci.py +0 -0
  787. {relationalai → v0/relationalai}/environments/hex.py +0 -0
  788. {relationalai → v0/relationalai}/environments/terminal.py +0 -0
  789. {relationalai → v0/relationalai}/experimental/__init__.py +0 -0
  790. {relationalai → v0/relationalai}/experimental/graphs.py +0 -0
  791. {relationalai → v0/relationalai}/experimental/paths/__init__.py +0 -0
  792. {relationalai → v0/relationalai}/experimental/paths/benchmarks/__init__.py +0 -0
  793. {relationalai → v0/relationalai}/experimental/paths/path_algorithms/__init__.py +0 -0
  794. {relationalai → v0/relationalai}/experimental/paths/rpq/__init__.py +0 -0
  795. {relationalai → v0/relationalai}/experimental/paths/rpq/filter.py +0 -0
  796. {relationalai → v0/relationalai}/experimental/paths/rpq/glushkov.py +0 -0
  797. {relationalai → v0/relationalai}/experimental/paths/rpq/transition.py +0 -0
  798. {relationalai → v0/relationalai}/experimental/paths/utilities/__init__.py +0 -0
  799. {relationalai → v0/relationalai}/experimental/paths/utilities/utilities.py +0 -0
  800. {relationalai → v0/relationalai}/metagen.py +0 -0
  801. {relationalai → v0/relationalai}/metamodel.py +0 -0
  802. {relationalai → v0/relationalai}/rel.py +0 -0
  803. {relationalai → v0/relationalai}/semantics/devtools/__init__.py +0 -0
  804. {relationalai → v0/relationalai}/semantics/internal/__init__.py +0 -0
  805. {relationalai → v0/relationalai}/semantics/internal/annotations.py +0 -0
  806. {relationalai → v0/relationalai}/semantics/lqp/__init__.py +0 -0
  807. {relationalai → v0/relationalai}/semantics/lqp/ir.py +0 -0
  808. {relationalai → v0/relationalai}/semantics/lqp/pragmas.py +0 -0
  809. {relationalai → v0/relationalai}/semantics/lqp/rewrite/__init__.py +0 -0
  810. {relationalai → v0/relationalai}/semantics/metamodel/dataflow.py +0 -0
  811. {relationalai → v0/relationalai}/semantics/metamodel/ir.py +0 -0
  812. {relationalai → v0/relationalai}/semantics/metamodel/rewrite/__init__.py +0 -0
  813. {relationalai → v0/relationalai}/semantics/metamodel/typer/__init__.py +0 -0
  814. {relationalai → v0/relationalai}/semantics/metamodel/types.py +0 -0
  815. {relationalai → v0/relationalai}/semantics/metamodel/visitor.py +0 -0
  816. {relationalai → v0/relationalai}/semantics/reasoners/experimental/__init__.py +0 -0
  817. {relationalai → v0/relationalai}/semantics/rel/__init__.py +0 -0
  818. {relationalai → v0/relationalai}/semantics/sql/__init__.py +0 -0
  819. {relationalai → v0/relationalai}/semantics/sql/executor/__init__.py +0 -0
  820. {relationalai → v0/relationalai}/semantics/sql/rewrite/__init__.py +0 -0
  821. {relationalai → v0/relationalai}/semantics/tests/logging.py +0 -0
  822. {relationalai → v0/relationalai}/std/aggregates.py +0 -0
  823. {relationalai → v0/relationalai}/std/dates.py +0 -0
  824. {relationalai → v0/relationalai}/std/graphs.py +0 -0
  825. {relationalai → v0/relationalai}/std/inspect.py +0 -0
  826. {relationalai → v0/relationalai}/std/math.py +0 -0
  827. {relationalai → v0/relationalai}/std/re.py +0 -0
  828. {relationalai → v0/relationalai}/std/strings.py +0 -0
  829. {relationalai → v0/relationalai}/tools/cleanup_snapshots.py +0 -0
  830. {relationalai → v0/relationalai}/tools/constants.py +0 -0
  831. {relationalai → v0/relationalai}/tools/query_utils.py +0 -0
  832. {relationalai → v0/relationalai}/tools/snapshot_viewer.py +0 -0
  833. {relationalai → v0/relationalai}/util/__init__.py +0 -0
  834. {relationalai → v0/relationalai}/util/constants.py +0 -0
  835. {relationalai → v0/relationalai}/util/graph.py +0 -0
  836. {relationalai → v0/relationalai}/util/timeout.py +0 -0
@@ -1,1163 +0,0 @@
1
- """Solver model implementation using protobuf format.
2
-
3
- This module provides the SolverModelPB class for defining optimization and
4
- constraint programming problems that are serialized to protobuf format and
5
- solved by external solver engines.
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
-
18
- from relationalai.experimental.solvers import Solver
19
- from relationalai.semantics.internal import internal as b
20
- from relationalai.semantics.rel.executor import RelExecutor
21
- from relationalai.tools.constants import DEFAULT_QUERY_TIMEOUT_MINS
22
- from relationalai.util.timeout import calc_remaining_timeout_minutes
23
-
24
- from .common import make_name
25
-
26
-
27
- # =============================================================================
28
- # Solver ProtoBuf Format Constants and Helpers
29
- # =============================================================================
30
-
31
- # Variable type codes for the solver protobuf format
32
- # cont: continuous (real-valued), int: integer, bin: binary (0/1)
33
- _VARIABLE_TYPE_CODES: dict[str, int] = {
34
- "cont": 40,
35
- "int": 41,
36
- "bin": 42,
37
- }
38
-
39
- # First-order operators: arithmetic and mathematical functions
40
- _FIRST_ORDER_OPERATOR_CODES: dict[str, int] = {
41
- "+": 10,
42
- "-": 11,
43
- "*": 12,
44
- "/": 13,
45
- "^": 14,
46
- "abs": 20,
47
- "exp": 21,
48
- "log": 22,
49
- "range": 50,
50
- }
51
-
52
- # First-order comparison operators: relational constraints
53
- _FIRST_ORDER_COMPARISON_CODES: dict[str, int] = {
54
- "=": 30,
55
- "!=": 31,
56
- "<=": 32,
57
- ">=": 33,
58
- "<": 34,
59
- ">": 35,
60
- "implies": 62,
61
- }
62
-
63
- # Higher-order operators: aggregation and global constraints
64
- _HIGHER_ORDER_OPERATOR_CODES: dict[str, int] = {
65
- "sum": 80,
66
- "min": 82,
67
- "max": 83,
68
- "count": 84,
69
- "all_different": 90,
70
- }
71
-
72
- # Mapping from bound type keywords to comparison operators
73
- _BOUND_TO_COMPARISON_OPERATOR: dict[str, str] = {
74
- "lower": ">=",
75
- "upper": "<=",
76
- "fixed": "=",
77
- }
78
-
79
-
80
- def _make_first_order_application_with_result(
81
- operator_code: int, *args: Any
82
- ) -> b.Expression:
83
- """Create a first-order application with a result variable."""
84
- return _make_first_order_application(operator_code, *args, b.String.ref("res"))
85
-
86
-
87
- def _make_first_order_application(operator_code: int, *args: Any) -> b.Expression:
88
- """Create a first-order application expression."""
89
- if not (2 <= len(args) <= 4):
90
- raise ValueError(
91
- f"First-order application requires 2-4 arguments, but got {len(args)}."
92
- )
93
- result_ref = args[-1]
94
- if not isinstance(result_ref, b.Ref):
95
- raise TypeError(
96
- f"Last argument must be a Ref, got {type(result_ref).__name__}."
97
- )
98
- if result_ref._thing != b.String:
99
- result_ref = b.String.ref("res")
100
- application_builtin = b.Relationship.builtins["rel_primitive_solverlib_fo_appl"]
101
- # Wrap operands in TupleArg for the vararg solverlib_fo_appl primitive:
102
- # fo_appl(op, (operands...), result)
103
- return b.Expression(
104
- application_builtin, operator_code, b.TupleArg(args[:-1]), result_ref
105
- )
106
-
107
-
108
- # =============================================================================
109
- # Main Solver Model Class
110
- # =============================================================================
111
-
112
-
113
- class SolverModelPB:
114
- """Solver model interface using protobuf format for optimization problems."""
115
-
116
- def __init__(self, model: b.Model, num_type: str) -> None:
117
- """Initialize solver model.
118
-
119
- Args:
120
- model: The RelationalAI model.
121
- num_type: Variable type - 'cont' or 'int'.
122
- """
123
- if num_type not in ["cont", "int"]:
124
- raise ValueError(
125
- f"Invalid numerical type '{num_type}'. Must be 'cont' or 'int'."
126
- )
127
- self._model = model
128
- self._num_type = num_type
129
- self._id = next(b._global_id)
130
- # Maps relationships to their corresponding variable concepts
131
- self._variable_relationships: dict[b.Relationship, b.Concept] = {}
132
- prefix_uppercase = f"SolverModel_{self._id}_"
133
- prefix_lowercase = prefix_uppercase.lower()
134
-
135
- # Create core concepts for model components
136
- self.Variable = Variable = model.Concept(prefix_uppercase + "Variable")
137
- self.MinObjective = model.Concept(prefix_uppercase + "MinObjective")
138
- self.MaxObjective = model.Concept(prefix_uppercase + "MaxObjective")
139
- self.Constraint = model.Concept(prefix_uppercase + "Constraint")
140
- self._model_info = {
141
- "num_variables": Variable,
142
- "num_min_objectives": self.MinObjective,
143
- "num_max_objectives": self.MaxObjective,
144
- "num_constraints": self.Constraint,
145
- }
146
- # Add printed_expr property to objectives and constraints for human-readable output
147
- for concept in [self.MinObjective, self.MaxObjective, self.Constraint]:
148
- concept.printed_expr = model.Property(
149
- f"{{{concept._name}}} has {{printed_expr:str}}"
150
- )
151
-
152
- # Create relationships for result extraction
153
- result_type = "int" if num_type == "int" else "float"
154
- self.result_info = model.Relationship(
155
- "{key:str} has {value:str}", short_name=(prefix_lowercase + "result_info")
156
- )
157
- # TODO(coey) PyRel is not able to handle "Variable._name" instead of "var" below due
158
- # to some internal naming bug; this leads to a "Unresolved Type" warning that we
159
- # will have to live with for now
160
- self.point = model.Property(
161
- f"{{var}} has {{value:{result_type}}}",
162
- short_name=(prefix_lowercase + "point"),
163
- )
164
- self.points = model.Property(
165
- f"point {{i:int}} for {{var}} has {{value:{result_type}}}",
166
- short_name=(prefix_lowercase + "points"),
167
- )
168
-
169
- # Install raw rel to work around lack of support for rel_primitive_solverlib_print_expr
170
- install_rel = f"""
171
- declare {self.MinObjective._name}
172
- declare {self.MaxObjective._name}
173
- declare {self.Constraint._name}
174
-
175
- declare {prefix_lowercase}variable_name
176
- declare {prefix_lowercase}minobjective_name
177
- declare {prefix_lowercase}maxobjective_name
178
- declare {prefix_lowercase}constraint_name
179
- declare {prefix_lowercase}minobjective_serialized
180
- declare {prefix_lowercase}maxobjective_serialized
181
- declare {prefix_lowercase}constraint_serialized
182
-
183
- def {prefix_lowercase}minobjective_printed_expr(h, s):
184
- rel_primitive_solverlib_print_expr({prefix_lowercase}minobjective_serialized[h], {prefix_lowercase}variable_name, s)
185
-
186
- def {prefix_lowercase}maxobjective_printed_expr(h, s):
187
- rel_primitive_solverlib_print_expr({prefix_lowercase}maxobjective_serialized[h], {prefix_lowercase}variable_name, s)
188
-
189
- def {prefix_lowercase}constraint_printed_expr(h, s):
190
- rel_primitive_solverlib_print_expr({prefix_lowercase}constraint_serialized[h], {prefix_lowercase}variable_name, s)
191
- """
192
- b.define(b.RawSource("rel", textwrap.dedent(install_rel)))
193
-
194
- # -------------------------------------------------------------------------
195
- # Variable Handling
196
- # -------------------------------------------------------------------------
197
-
198
- def solve_for(
199
- self,
200
- expr,
201
- where: Optional[list[Any]] = None,
202
- populate: bool = True,
203
- **kwargs: Any,
204
- ) -> b.Concept:
205
- """Define decision variables.
206
-
207
- Args:
208
- expr: Relationship or expression defining variables.
209
- where: Optional grounding conditions.
210
- populate: Whether to populate relationship with solver results.
211
- **kwargs: Optional properties (name, type, lower, upper, fixed).
212
-
213
- Returns:
214
- Variable concept.
215
- """
216
- if where is None:
217
- where = []
218
- if isinstance(expr, b.Fragment):
219
- # TODO(coey): Remove in future
220
- raise ValueError(
221
- "The select fragment argument to `solve_for` is deprecated. "
222
- "Instead, use the `where = [conditions...]` kwarg to specify optional grounding conditions."
223
- )
224
- elif isinstance(expr, b.Expression):
225
- relationship = expr._op
226
- if not isinstance(relationship, b.Relationship):
227
- raise TypeError(
228
- f"Expression operator must be a Relationship, got {type(relationship).__name__}."
229
- )
230
- params = expr._params
231
- elif isinstance(expr, b.Relationship):
232
- relationship = expr
233
- params = [
234
- b.field_to_type(self._model, field) for field in relationship._fields
235
- ]
236
- else:
237
- raise TypeError(
238
- f"Invalid expression type for solve_for: {type(expr).__name__}. "
239
- f"Expected Relationship or Expression."
240
- )
241
-
242
- if len(params) != len(relationship._fields):
243
- raise ValueError(
244
- f"Parameter count mismatch: Got {len(params)} params "
245
- f"but relationship has {len(relationship._fields)} fields."
246
- )
247
- if relationship in self._variable_relationships:
248
- raise ValueError(
249
- f"Variables are already defined for relationship {relationship}."
250
- )
251
-
252
- # Create a specialized Variable concept for this relationship
253
- # Each decision variable gets its own concept subtype
254
- Var = self._model.Concept(
255
- f"{self.Variable._name}_{str(relationship).replace('.', '_')}",
256
- extends=[self.Variable],
257
- )
258
- self._variable_relationships[relationship] = Var
259
-
260
- # Build field dict from relationship parameters (excluding the value field)
261
- fields = {}
262
- for i in range(len(params) - 1):
263
- if i == 0 and relationship._parent is not None:
264
- concept = relationship._parent
265
- if not isinstance(concept, b.Concept):
266
- raise TypeError(
267
- f"Relationship parent must be a Concept, got {type(concept).__name__}."
268
- )
269
- else:
270
- concept = params[i]
271
- field_name = relationship._field_names[i]
272
- # Prevent "Implicit Subtype Relationship" warnings by explicitly registering
273
- # the relationship on the parent Variable concept before using it on subtypes
274
- self.Variable._relationships[field_name] = self.Variable._get_relationship(
275
- field_name
276
- )
277
- fields[field_name] = concept
278
- var = Var.new(**fields)
279
- b.define(var).where(*where)
280
-
281
- # Handle optional variable properties
282
- for key, value in kwargs.items():
283
- if key == "name":
284
- definition = self.Variable.name(var, make_name(value))
285
- elif key == "type":
286
- if not isinstance(value, str):
287
- raise TypeError(
288
- f"Variable 'type' must be a string, but got {type(value).__name__}."
289
- )
290
- if value not in _VARIABLE_TYPE_CODES:
291
- valid_types = ", ".join(_VARIABLE_TYPE_CODES.keys())
292
- raise ValueError(
293
- f"Invalid variable type '{value}'. Valid types are: {valid_types}."
294
- )
295
- serialized_expr = _make_first_order_application_with_result(
296
- _VARIABLE_TYPE_CODES[value], var
297
- )
298
- definition = self.Constraint.new(serialized=serialized_expr)
299
- elif key in ("lower", "upper", "fixed"):
300
- if not isinstance(value, (b.Producer, float, int)):
301
- raise TypeError(
302
- f"Variable '{key}' must be a number, but got {type(value).__name__}."
303
- )
304
- # Map bound types to comparison operators
305
- operator = _BOUND_TO_COMPARISON_OPERATOR[key]
306
- serialized_expr = _make_first_order_application_with_result(
307
- _FIRST_ORDER_COMPARISON_CODES[operator], var, value
308
- )
309
- definition = self.Constraint.new(serialized=serialized_expr)
310
- else:
311
- raise ValueError(f"Invalid keyword argument '{key}' for solve_for.")
312
- b.define(definition).where(*where)
313
-
314
- if populate:
315
- # Automatically populate the variable relationship with solver results
316
- # This defines the original relationship to pull values from self.point after solving
317
- value_ref = (b.Integer if self._num_type == "int" else b.Float).ref()
318
- b.define(
319
- relationship(
320
- *[getattr(Var, field_name) for field_name in fields], value_ref
321
- )
322
- ).where(self.point(Var, value_ref))
323
-
324
- return Var
325
-
326
- # -------------------------------------------------------------------------
327
- # Objective Functions
328
- # -------------------------------------------------------------------------
329
-
330
- def minimize(
331
- self,
332
- expr: b.Producer | float | int | b.Fragment,
333
- name: Optional[str | list[str]] = None,
334
- ) -> None:
335
- """Add minimization objective.
336
-
337
- Args:
338
- expr: Expression to minimize.
339
- name: Optional objective name.
340
- """
341
- return self._add_objective(self.MinObjective, expr, name)
342
-
343
- def maximize(
344
- self,
345
- expr: b.Producer | float | int | b.Fragment,
346
- name: Optional[str | list[str]] = None,
347
- ) -> None:
348
- """Add maximization objective.
349
-
350
- Args:
351
- expr: Expression to maximize.
352
- name: Optional objective name.
353
- """
354
- return self._add_objective(self.MaxObjective, expr, name)
355
-
356
- def _add_objective(
357
- self,
358
- objective_concept: b.Concept,
359
- expr: b.Producer | float | int | b.Fragment,
360
- name: Optional[str | list[str]],
361
- ) -> None:
362
- context = SymbolifyContext(self)
363
- symbolic_expr = context.rewrite(expr)
364
- if not isinstance(symbolic_expr, Symbolic):
365
- # Expr is not symbolic (a constant) - wrap it as a trivial expression
366
- symbolic_expr = _make_first_order_application_with_result(0, expr)
367
- else:
368
- # Unwrap the symbolic expression
369
- unwrapped_expr = symbolic_expr.expr
370
- # Check if it's a bare variable (needs wrapping for protobuf)
371
- is_bare_variable = isinstance(unwrapped_expr, b.ConceptMember)
372
- is_fragment_with_variable = (
373
- isinstance(unwrapped_expr, b.Fragment)
374
- and unwrapped_expr._select
375
- and isinstance(unwrapped_expr._select[0], b.ConceptMember)
376
- )
377
- if is_bare_variable or is_fragment_with_variable:
378
- # The protobuf format requires all objectives to be expressions, not bare variables
379
- symbolic_expr = _make_first_order_application_with_result(
380
- 0, unwrapped_expr
381
- )
382
- else:
383
- symbolic_expr = unwrapped_expr
384
-
385
- if isinstance(symbolic_expr, Symbolic):
386
- raise ValueError(
387
- "Internal error. Expression is still Symbolic after unwrapping."
388
- )
389
-
390
- objective = objective_concept.new(serialized=symbolic_expr)
391
- definitions = [objective]
392
- if name is not None:
393
- definitions.append(objective.name(make_name(name)))
394
- b.define(*definitions)
395
-
396
- def satisfy(
397
- self,
398
- expr: b.Fragment,
399
- check: bool = False,
400
- name: Optional[str | list[str]] = None,
401
- ) -> None:
402
- """Add constraints.
403
-
404
- Args:
405
- expr: Fragment with require clause.
406
- check: Whether to keep require in model validation.
407
- name: Optional constraint name.
408
- """
409
- if not isinstance(expr, b.Fragment):
410
- raise TypeError(
411
- f"The satisfy method expects a Fragment, but got {type(expr).__name__}."
412
- )
413
- if not expr._require:
414
- raise ValueError("Fragment for satisfy must have a require clause.")
415
- if expr._select or expr._define:
416
- raise ValueError(
417
- "Fragment for satisfy must not have select or define clauses."
418
- )
419
- if not check:
420
- # Remove the `require` from the model roots so it is not checked as an integrity constraint
421
- b._remove_roots([expr])
422
- context = SymbolifyContext(self)
423
-
424
- symbolic_where_clauses = context.rewrite_where(*expr._where)
425
- definitions = []
426
- for requirement in expr._require:
427
- symbolic_requirement = context.rewrite(requirement)
428
- if not isinstance(symbolic_requirement, Symbolic):
429
- raise ValueError(
430
- f"Cannot symbolify requirement {requirement} in satisfy. "
431
- f"The requirement must contain solver variables or expressions."
432
- )
433
- constraint = self.Constraint.new(serialized=symbolic_requirement.expr)
434
- definitions.append(constraint)
435
- if name is not None:
436
- definitions.append(constraint.name(make_name(name)))
437
- b.define(*definitions).where(*symbolic_where_clauses)
438
-
439
- # -------------------------------------------------------------------------
440
- # Model Inspection and Display
441
- # -------------------------------------------------------------------------
442
-
443
- @staticmethod
444
- def _print_dataframe(df: Any) -> None:
445
- """Print dataframe with consistent formatting for long strings."""
446
- for row in df.itertuples(index=False):
447
- print(" ".join(str(val) for val in row))
448
- print()
449
-
450
- def summarize(self) -> None:
451
- """Print counts of variables, objectives, and constraints in the model."""
452
- counts_df = b.select(
453
- *[(b.count(item) | 0) for (_, item) in self._model_info.items()]
454
- ).to_df()
455
- if counts_df.shape != (1, 4):
456
- raise ValueError("Unexpected counts dataframe shape.")
457
- num_vars, num_min_objs, num_max_objs, num_constraints = counts_df.iloc[0]
458
- print(
459
- f"Solver model has {num_vars} variables, {num_min_objs} minimization objectives, {num_max_objs} maximization objectives, and {num_constraints} constraints."
460
- )
461
-
462
- def print(self, with_names: bool = False) -> None:
463
- """Print model components.
464
-
465
- Args:
466
- with_names: Whether to print expression string names (if available).
467
- """
468
- # Print variables
469
- var_df = b.select(self.Variable.name | "_").where(self.Variable).to_df()
470
- if var_df.empty:
471
- print("No variables defined.")
472
- return
473
- print("Solver model:")
474
- print()
475
- print(f"Variables ({var_df.shape[0]}):")
476
- self._print_dataframe(var_df)
477
-
478
- # Print components
479
- components = [
480
- (self.MinObjective, "Min objectives"),
481
- (self.MaxObjective, "Max objectives"),
482
- (self.Constraint, "Constraints"),
483
- ]
484
- printed_expr_ref = b.String.ref()
485
- for component_concept, component_label in components:
486
- selection = (
487
- [component_concept.name | "", printed_expr_ref]
488
- if with_names
489
- else [printed_expr_ref]
490
- )
491
- component_df = (
492
- b.select(*selection)
493
- .where(component_concept.printed_expr(printed_expr_ref))
494
- .to_df()
495
- )
496
- if not component_df.empty:
497
- print(f"{component_label} ({component_df.shape[0]}):")
498
- self._print_dataframe(component_df)
499
-
500
- # -------------------------------------------------------------------------
501
- # Solving and Result Handling
502
- # -------------------------------------------------------------------------
503
-
504
- def solve(
505
- self, solver: Solver, log_to_console: bool = False, **kwargs: Any
506
- ) -> None:
507
- """Solve the model.
508
-
509
- Args:
510
- solver: Solver instance.
511
- log_to_console: Whether to show solver output.
512
- **kwargs: Solver options and parameters.
513
- """
514
- options = {**kwargs, "version": 1}
515
-
516
- # Validate solver options
517
- for option_key, option_value in options.items():
518
- if not isinstance(option_key, str):
519
- raise TypeError(
520
- f"Solver option keys must be strings, but got {type(option_key).__name__} for key {option_key!r}."
521
- )
522
- if not isinstance(option_value, (int, float, str, bool)):
523
- raise TypeError(
524
- f"Solver option values must be int, float, str, or bool, "
525
- f"but got {type(option_value).__name__} for option {option_key!r}."
526
- )
527
-
528
- # Three-phase solve process:
529
- # 1. Export model to Snowflake as protobuf
530
- # 2. Execute solver job (external solver reads from Snowflake)
531
- # 3. Extract and load results back into the model
532
- input_id = uuid.uuid4()
533
- model_uri = f"snowflake://APP_STATE.RAI_INTERNAL_STAGE/job-inputs/solver/{input_id}/model.binpb"
534
- sf_input_uri = f"snowflake://job-inputs/solver/{input_id}/model.binpb"
535
- payload: dict[str, Any] = {"solver": solver.solver_name.lower()}
536
- payload["options"] = options
537
- payload["model_uri"] = sf_input_uri
538
-
539
- executor = self._model._to_executor()
540
- if not isinstance(executor, RelExecutor):
541
- raise ValueError(f"Expected RelExecutor, got {type(executor).__name__}.")
542
- prefix_lowercase = f"solvermodel_{self._id}_"
543
-
544
- query_timeout_mins = kwargs.get("query_timeout_mins", None)
545
- config = self._model._config
546
- if (
547
- query_timeout_mins is None
548
- and (
549
- timeout_value := config.get(
550
- "query_timeout_mins", DEFAULT_QUERY_TIMEOUT_MINS
551
- )
552
- )
553
- is not None
554
- ):
555
- query_timeout_mins = int(timeout_value)
556
- config_file_path = getattr(config, "file_path", None)
557
- start_time = time.monotonic()
558
- remaining_timeout_minutes = query_timeout_mins
559
-
560
- # Step 1: Materialize the model and store it in Snowflake
561
- print("export model")
562
- # TODO(coey): Weird hack to avoid uninitialized properties error
563
- # This forces evaluation of the Variable concept before export
564
- b.select(b.count(self.Variable)).to_df()
565
- export_model_relation = f"""
566
- // TODO maybe only want to pass names if printing - like in old setup
567
- // Collect all model components into a relation for serialization
568
- def model_relation {{
569
- (:variable, {self.Variable._name});
570
- (:variable_name, {prefix_lowercase}variable_name);
571
- (:min_objective, {prefix_lowercase}minobjective_serialized);
572
- (:max_objective, {prefix_lowercase}maxobjective_serialized);
573
- (:constraint, {prefix_lowercase}constraint_serialized);
574
- }}
575
-
576
- @no_diagnostics(:EXPERIMENTAL)
577
- def model_string {{ rel_primitive_solverlib_model_string[model_relation] }}
578
-
579
- ic model_not_empty("Solver model is empty.") requires not empty(model_string)
580
-
581
- def config[:envelope, :content_type]: "application/octet-stream"
582
- def config[:envelope, :payload, :data]: model_string
583
- def config[:envelope, :payload, :path]: "{model_uri}"
584
- def export {{ config }}
585
- """
586
- executor.execute_raw(
587
- textwrap.dedent(export_model_relation),
588
- query_timeout_mins=remaining_timeout_minutes,
589
- )
590
-
591
- # Step 2: Execute solver job and wait for completion
592
- print("execute solver job")
593
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
594
- start_time,
595
- query_timeout_mins,
596
- config_file_path=config_file_path,
597
- )
598
- job_id = solver._exec_job(
599
- payload,
600
- log_to_console=log_to_console,
601
- query_timeout_mins=remaining_timeout_minutes,
602
- )
603
-
604
- # Step 3: Extract and insert solver results into the model
605
- print("extract result")
606
- remaining_timeout_minutes = calc_remaining_timeout_minutes(
607
- start_time,
608
- query_timeout_mins,
609
- config_file_path=config_file_path,
610
- )
611
- extract_results_relation = f"""
612
- def raw_result {{
613
- load_binary["snowflake://APP_STATE.RAI_INTERNAL_STAGE/job-results/{job_id}/result.binpb"]
614
- }}
615
-
616
- ic result_not_empty("Solver result is empty.") requires not empty(raw_result)
617
-
618
- @no_diagnostics(:EXPERIMENTAL)
619
- def extracted {{ rel_primitive_solverlib_extract[raw_result] }}
620
-
621
- def delete[:{self.result_info._name}]: {self.result_info._name}
622
- def delete[:{self.point._name}]: {self.point._name}
623
- def delete[:{self.points._name}]: {self.points._name}
624
-
625
- def insert(:{self.result_info._name}, key, value):
626
- exists((original_key) | string(extracted[original_key], value) and ::std::mirror::lower(original_key, key))
627
- """
628
- if self._num_type == "int":
629
- insert_points_relation = f"""
630
- def insert(:{self.point._name}, variable, value):
631
- exists((float_value) | extracted(:point, variable, float_value) and
632
- ::std::mirror::convert(std::mirror::typeof[Int128], float_value, value)
633
- )
634
- def insert(:{self.points._name}, point_index, variable, value):
635
- exists((float_index, float_value) | extracted(:points, variable, float_index, float_value) and
636
- ::std::mirror::convert(std::mirror::typeof[Int128], float_index, point_index) and
637
- ::std::mirror::convert(std::mirror::typeof[Int128], float_value, value)
638
- )
639
- """
640
- else:
641
- insert_points_relation = f"""
642
- def insert(:{self.point._name}, variable, value): extracted(:point, variable, value)
643
- def insert(:{self.points._name}, point_index, variable, value):
644
- exists((float_index) | extracted(:points, variable, float_index, value) and
645
- ::std::mirror::convert(std::mirror::typeof[Int128], float_index, point_index)
646
- )
647
- """
648
- executor.execute_raw(
649
- textwrap.dedent(extract_results_relation)
650
- + textwrap.dedent(insert_points_relation),
651
- readonly=False,
652
- query_timeout_mins=remaining_timeout_minutes,
653
- )
654
-
655
- print("finished solve")
656
- print()
657
-
658
- def load_point(self, point_index: int) -> None:
659
- """Load a solution point.
660
-
661
- Args:
662
- point_index: Solution point index (0-based).
663
- """
664
- if not isinstance(point_index, int):
665
- raise TypeError(
666
- f"Point index must be an integer, but got {type(point_index).__name__}."
667
- )
668
- if point_index < 0:
669
- raise ValueError(
670
- f"Point index must be non-negative, but got {point_index}."
671
- )
672
- executor = self._model._to_executor()
673
- if not isinstance(executor, RelExecutor):
674
- raise ValueError(
675
- f"Expected RelExecutor, but got {type(executor).__name__}."
676
- )
677
- load_point_relation = f"""
678
- def delete[:{self.point._name}]: {self.point._name}
679
- def insert(:{self.point._name}, variable, value): {self.points._name}(int128[{point_index}], variable, value)
680
- """
681
- executor.execute_raw(textwrap.dedent(load_point_relation), readonly=False)
682
-
683
- def summarize_result(self) -> Any:
684
- """Print solver result summary.
685
-
686
- Returns:
687
- DataFrame with result information.
688
- """
689
- info_keys_to_retrieve = [
690
- "error",
691
- "termination_status",
692
- "solve_time_sec",
693
- "objective_value",
694
- "solver_version",
695
- "result_count",
696
- ]
697
- key, value_ref = b.String.ref(), b.String.ref()
698
- result_df = (
699
- b.select(key, value_ref)
700
- .where(self.result_info(key, value_ref), key.in_(info_keys_to_retrieve))
701
- .to_df()
702
- )
703
- if result_df.empty:
704
- raise ValueError(
705
- "No result information is available. Has the model been solved?"
706
- )
707
- print("Solver result:")
708
- print(result_df.to_string(index=False, header=False))
709
- print()
710
- return result_df
711
-
712
- def variable_values(self, multiple: bool = False) -> b.Fragment:
713
- """Retrieve variable values.
714
-
715
- Args:
716
- multiple: Whether to return all solution points.
717
-
718
- Returns:
719
- Fragment for selecting values.
720
- """
721
- variable_ref = self.Variable.ref()
722
- value_ref = (b.Integer if self._num_type == "int" else b.Float).ref()
723
- if multiple:
724
- point_index = b.Integer.ref()
725
- return b.select(point_index, variable_ref.name, value_ref).where(
726
- self.points(point_index, variable_ref, value_ref)
727
- )
728
- return b.select(variable_ref.name, value_ref).where(
729
- self.point(variable_ref, value_ref)
730
- )
731
-
732
- # Valid result info keys that can be accessed as attributes
733
- _RESULT_INFO_KEYS = frozenset(
734
- [
735
- "error",
736
- "termination_status",
737
- "solver_version",
738
- "printed_model",
739
- "solve_time_sec",
740
- "objective_value",
741
- "result_count",
742
- ]
743
- )
744
-
745
- def __getattr__(self, name: str) -> Any:
746
- """Get result attribute (e.g., num_variables, termination_status, objective_value).
747
-
748
- Args:
749
- name: Attribute name.
750
-
751
- Returns:
752
- Attribute value or None.
753
- """
754
- # Try to get dataframe from model info or result info
755
- if name in self._model_info:
756
- result_df = b.select(b.count(self._model_info[name]) | 0).to_df()
757
- elif name in self._RESULT_INFO_KEYS:
758
- value_ref = b.String.ref()
759
- result_df = (
760
- b.select(value_ref).where(self.result_info(name, value_ref)).to_df()
761
- )
762
- else:
763
- return None
764
-
765
- # Extract and convert scalar value
766
- if result_df.shape != (1, 1):
767
- raise ValueError(
768
- f"Expected exactly one value for attribute '{name}', "
769
- f"but got dataframe with shape {result_df.shape}."
770
- )
771
-
772
- result_value = result_df.iloc[0, 0]
773
- if not isinstance(result_value, str):
774
- return result_value
775
-
776
- # Convert string results to appropriate types
777
- if name == "solve_time_sec":
778
- return float(result_value)
779
- if name == "objective_value":
780
- return int(result_value) if self._num_type == "int" else float(result_value)
781
- if name == "result_count":
782
- return int(result_value)
783
- return result_value
784
-
785
-
786
- # =============================================================================
787
- # Symbolic Expression Classes
788
- # =============================================================================
789
-
790
-
791
- class Symbolic:
792
- """Wrapper for symbolified solver expressions."""
793
-
794
- def __init__(self, expr: Any) -> None:
795
- if isinstance(expr, Symbolic):
796
- raise TypeError("Cannot wrap a Symbolic expression in another Symbolic.")
797
- self.expr = expr
798
-
799
-
800
- class SymbolifyContext:
801
- """Context for rewriting expressions into solver-compatible symbolic form."""
802
-
803
- def __init__(self, solver_model: SolverModelPB) -> None:
804
- self.model = solver_model._model
805
- self.solver_model = solver_model
806
- # Maps original variables (or refs) to symbolic variables bound in where clauses
807
- self.variable_map: dict[Any, Any] = {}
808
-
809
- # -------------------------------------------------------------------------
810
- # Public Rewriting Methods
811
- # -------------------------------------------------------------------------
812
-
813
- def rewrite_where(self, *exprs: Any) -> list[Any]:
814
- """Rewrite where clause expressions.
815
-
816
- Args:
817
- *exprs: Where clause expressions.
818
-
819
- Returns:
820
- Rewritten expressions.
821
- """
822
- rewritten_expressions: list[Any] = []
823
- # Two-pass strategy: first handle variable relationships to populate variable_map,
824
- # then rewrite other expressions that may reference those variables
825
- # First pass: identify and handle variable relationship expressions
826
- for expression in exprs:
827
- if (
828
- isinstance(expression, b.Expression)
829
- and isinstance(expression._op, b.Relationship)
830
- and expression._op in self.solver_model._variable_relationships
831
- ):
832
- rewritten_expressions.append(
833
- self._handle_variable_relationship(expression)
834
- )
835
- else:
836
- rewritten_expressions.append(None)
837
- # Second pass: rewrite remaining non-variable expressions
838
- for i, expr in enumerate(exprs):
839
- if rewritten_expressions[i] is None:
840
- rewritten_expressions[i] = (
841
- expr
842
- if expr in self.variable_map
843
- else self._rewrite_nonsymbolic(expr)
844
- )
845
- return rewritten_expressions
846
-
847
- def rewrite(self, expr: Any) -> Optional[Symbolic | Any]:
848
- """Rewrite expressions to symbolify solver variables."""
849
- if expr is None:
850
- return None
851
-
852
- elif isinstance(expr, (int, float, str)):
853
- return None
854
-
855
- elif isinstance(expr, b.ConceptFilter):
856
- concept = expr._op
857
- assert isinstance(concept, b.Concept)
858
- (ident, kwargs) = expr._params
859
- assert ident is None
860
- assert isinstance(kwargs, dict)
861
- new_kwargs = {}
862
- values_were_rewritten = False
863
- for key, value in kwargs.items():
864
- rewritten_value = self.rewrite(value)
865
- if isinstance(rewritten_value, Symbolic):
866
- raise ValueError(
867
- f"Cannot symbolify ConceptFilter argument {key} with symbolic value."
868
- )
869
- if rewritten_value is not None:
870
- values_were_rewritten = True
871
- new_kwargs[key] = rewritten_value
872
- else:
873
- new_kwargs[key] = value
874
- if values_were_rewritten:
875
- return b.ConceptFilter(concept, ident, new_kwargs)
876
- return None
877
-
878
- elif isinstance(expr, (b.DataColumn, b.TypeRef, b.Concept)):
879
- return None
880
-
881
- elif isinstance(expr, b.Alias):
882
- return self.rewrite(expr._thing)
883
-
884
- elif isinstance(expr, b.Ref):
885
- if expr in self.variable_map:
886
- return Symbolic(self.variable_map[expr])
887
- thing = self.rewrite(expr._thing)
888
- if thing is not None:
889
- raise ValueError(
890
- f"Internal error. Ref._thing rewrite unexpectedly returned {thing}."
891
- )
892
- return None
893
-
894
- elif isinstance(expr, b.Relationship):
895
- if expr in self.variable_map:
896
- return Symbolic(self.variable_map[expr])
897
- variable_result = self._get_variable_ref(expr, expr._parent)
898
- if variable_result is not None:
899
- self.variable_map[expr] = variable_result
900
- return Symbolic(variable_result)
901
- return None
902
-
903
- elif isinstance(expr, b.RelationshipRef):
904
- if expr in self.variable_map:
905
- return Symbolic(self.variable_map[expr])
906
- relationship = expr._relationship
907
- if isinstance(relationship, b.Relationship):
908
- variable_result = self._get_variable_ref(relationship, expr._parent)
909
- if variable_result is not None:
910
- self.variable_map[expr] = variable_result
911
- return Symbolic(variable_result)
912
- rewritten_parent = self.rewrite(expr._parent)
913
- if isinstance(rewritten_parent, Symbolic):
914
- raise ValueError(
915
- "Internal error. RelationshipRef parent rewrite returned Symbolic."
916
- )
917
- if rewritten_parent is not None:
918
- return b.RelationshipRef(rewritten_parent, relationship)
919
- return None
920
-
921
- elif isinstance(expr, b.RelationshipFieldRef):
922
- relationship = expr._relationship
923
- if not isinstance(relationship, b.Relationship):
924
- # TODO(coey): Handle relationship:RelationshipReading
925
- return None
926
-
927
- # Rewrite the relationship reference
928
- relationship_expression = (
929
- relationship
930
- if expr._parent is None
931
- else b.RelationshipRef(expr._parent, relationship)
932
- )
933
- variable_result = self.rewrite(relationship_expression)
934
- if variable_result is None:
935
- return None
936
-
937
- # Handle symbolic result - return as-is if it's the last field
938
- if isinstance(variable_result, Symbolic):
939
- if expr._field_ix == len(relationship._fields) - 1:
940
- return variable_result
941
- variable_result = variable_result.expr
942
-
943
- return getattr(variable_result, relationship._field_names[expr._field_ix])
944
-
945
- elif isinstance(expr, b.Expression):
946
- operator = self.rewrite(expr._op)
947
- if isinstance(operator, Symbolic):
948
- raise ValueError(
949
- "Internal error: Expression operator rewrite returned Symbolic."
950
- )
951
- params_were_rewritten = False
952
- has_symbolic_params = False
953
- params = []
954
- for param in expr._params:
955
- rewritten_param = self.rewrite(param)
956
- if isinstance(rewritten_param, Symbolic):
957
- has_symbolic_params = True
958
- params_were_rewritten = True
959
- params.append(rewritten_param.expr)
960
- elif rewritten_param is not None:
961
- params_were_rewritten = True
962
- params.append(rewritten_param)
963
- else:
964
- params.append(param)
965
- if operator is not None:
966
- if has_symbolic_params:
967
- raise NotImplementedError(
968
- f"Solver rewrites cannot handle expression {expr} "
969
- f"with both a symbolic operator and symbolic parameters."
970
- )
971
- return b.Expression(operator, *params)
972
- if not has_symbolic_params:
973
- return b.Expression(expr._op, *params)
974
- if not params_were_rewritten:
975
- return None
976
-
977
- # Some arguments involve solver variables, so rewrite into solver protobuf format
978
- # This converts operations like x + y into fo_appl(ADD_OP, (x, y), res)
979
- if not has_symbolic_params:
980
- raise ValueError(
981
- "Internal error. Expected symbolic parameters but none were found."
982
- )
983
- if not isinstance(expr._op, b.Relationship):
984
- raise NotImplementedError(
985
- f"Solver rewrites cannot handle expression {expr} "
986
- f"with operator type {type(expr._op).__name__}."
987
- )
988
- operator_name = expr._op._name
989
- if not isinstance(operator_name, str):
990
- raise ValueError(
991
- f"Internal error. Operator name is {type(operator_name).__name__}, expected str."
992
- )
993
- if operator_name in _FIRST_ORDER_OPERATOR_CODES:
994
- return Symbolic(
995
- _make_first_order_application(
996
- _FIRST_ORDER_OPERATOR_CODES[operator_name], *params
997
- )
998
- )
999
- elif operator_name in _FIRST_ORDER_COMPARISON_CODES:
1000
- return Symbolic(
1001
- _make_first_order_application_with_result(
1002
- _FIRST_ORDER_COMPARISON_CODES[operator_name], *params
1003
- )
1004
- )
1005
- else:
1006
- raise NotImplementedError(
1007
- f"Solver rewrites cannot handle operator '{operator_name}'."
1008
- )
1009
-
1010
- elif isinstance(expr, b.Aggregate):
1011
- # Only the last argument can be symbolic
1012
- preceding_args = [self._rewrite_nonsymbolic(arg) for arg in expr._args[:-1]]
1013
- group = [self._rewrite_nonsymbolic(arg) for arg in expr._group]
1014
- # TODO(coey): Should this be done with a subcontext (for variable_map)?
1015
- where = self.rewrite_where(*expr._where._where)
1016
- rewritten = (
1017
- preceding_args != expr._args[:-1]
1018
- or group != expr._group
1019
- or where != expr._where
1020
- )
1021
- symbolic_arg = self.rewrite(expr._args[-1])
1022
- if symbolic_arg is None and not rewritten:
1023
- return None
1024
- if not isinstance(symbolic_arg, Symbolic):
1025
- if symbolic_arg is None:
1026
- symbolic_arg = expr._args[-1]
1027
- aggregate_expr = b.Aggregate(expr._op, *preceding_args, symbolic_arg)
1028
- return aggregate_expr.per(*group).where(*where)
1029
-
1030
- # The last argument is symbolic - convert to higher-order application
1031
- # Example: sum(x for x in variables) becomes ho_appl(..., x, SUM_OP)
1032
- operator_name = expr._op._name
1033
- if not isinstance(operator_name, str):
1034
- raise ValueError(
1035
- f"Internal error. Aggregate operator name is {type(operator_name).__name__}, expected str."
1036
- )
1037
- if operator_name not in _HIGHER_ORDER_OPERATOR_CODES:
1038
- raise NotImplementedError(
1039
- f"Solver rewrites cannot handle aggregate operator '{operator_name}'. "
1040
- f"Supported operators: {', '.join(_HIGHER_ORDER_OPERATOR_CODES.keys())}"
1041
- )
1042
- higher_order_application_builtin = b.Relationship.builtins[
1043
- "rel_primitive_solverlib_ho_appl"
1044
- ]
1045
- aggregate_expr = b.Aggregate(
1046
- higher_order_application_builtin,
1047
- *preceding_args,
1048
- symbolic_arg.expr,
1049
- _HIGHER_ORDER_OPERATOR_CODES[operator_name],
1050
- )
1051
- return Symbolic(aggregate_expr.per(*group).where(*where))
1052
-
1053
- elif isinstance(expr, b.Union):
1054
- # Return union of the symbolified expressions, if any are symbolic
1055
- args_were_rewritten = False
1056
- has_symbolic_args = False
1057
- args = []
1058
- for union_arg in expr._args:
1059
- rewritten_arg = self.rewrite(union_arg)
1060
- if isinstance(rewritten_arg, Symbolic):
1061
- has_symbolic_args = True
1062
- args.append(rewritten_arg.expr)
1063
- elif rewritten_arg is not None:
1064
- args_were_rewritten = True
1065
- args.append(rewritten_arg)
1066
- else:
1067
- args.append(union_arg)
1068
- if has_symbolic_args:
1069
- return Symbolic(b.union(*args))
1070
- elif args_were_rewritten:
1071
- return b.union(*args)
1072
- return None
1073
-
1074
- elif isinstance(expr, b.Fragment):
1075
- # Only support selects with one item
1076
- if expr._define or expr._require:
1077
- raise ValueError(
1078
- "Solver rewrites do not support fragments with define or require clauses."
1079
- )
1080
- if len(expr._select) != 1:
1081
- raise ValueError(
1082
- f"Solver rewrites require fragments with exactly one select item, "
1083
- f"but got {len(expr._select)}."
1084
- )
1085
- # TODO(coey): Should this be done with a subcontext (for variable_map)?
1086
- where = self.rewrite_where(*expr._where)
1087
- symbolic_select = self.rewrite(expr._select[0])
1088
- if isinstance(symbolic_select, Symbolic):
1089
- return Symbolic(b.select(symbolic_select.expr).where(*where))
1090
- elif symbolic_select is not None:
1091
- return b.select(symbolic_select).where(*where)
1092
- return None
1093
-
1094
- raise NotImplementedError(
1095
- f"Solver rewrites cannot handle {expr} of type {type(expr).__name__}."
1096
- )
1097
-
1098
- # -------------------------------------------------------------------------
1099
- # Private Helper Methods
1100
- # -------------------------------------------------------------------------
1101
-
1102
- def _handle_variable_relationship(self, expr: b.Expression) -> Any:
1103
- """Create symbolic reference for variable relationship expression."""
1104
- relationship = expr._op
1105
- if not isinstance(relationship, b.Relationship):
1106
- raise TypeError(
1107
- f"Expected Relationship in variable expression, but got {type(relationship).__name__}."
1108
- )
1109
- params = expr._params
1110
- if len(params) != len(relationship._fields):
1111
- raise ValueError(
1112
- f"Parameter count mismatch: Got {len(params)} params "
1113
- f"but relationship has {len(relationship._fields)} fields."
1114
- )
1115
- last_param = params[-1]
1116
- if isinstance(last_param, b.Alias):
1117
- last_param = last_param._thing
1118
- if not isinstance(last_param, (b.Concept, b.Ref)):
1119
- raise TypeError(
1120
- f"Last parameter must be a Concept or Ref, but got {type(last_param).__name__}."
1121
- )
1122
- # Extract and rewrite field parameters to build the symbolic variable reference
1123
- # This maps the relationship fields to their grounding values
1124
- fields = {}
1125
- for i in range(len(params) - 1):
1126
- rewritten_param = self.rewrite(params[i])
1127
- assert not isinstance(rewritten_param, Symbolic)
1128
- fields[relationship._field_names[i]] = (
1129
- rewritten_param if rewritten_param is not None else params[i]
1130
- )
1131
- # Create new ref corresponding to the decision variable
1132
- variable_ref = self.solver_model._variable_relationships[relationship].ref()
1133
- self.variable_map[last_param] = variable_ref
1134
- # Return new condition to ground the variable
1135
- return b.where(
1136
- *[
1137
- getattr(variable_ref, field_name) == field_value
1138
- for field_name, field_value in fields.items()
1139
- ]
1140
- )
1141
-
1142
- def _rewrite_nonsymbolic(self, expr: Any) -> Any:
1143
- """Rewrite expression ensuring non-symbolic result."""
1144
- new_expr = self.rewrite(expr)
1145
- if isinstance(new_expr, Symbolic):
1146
- raise ValueError(
1147
- f"Internal error. Non-symbolic rewrite unexpectedly returned Symbolic for {expr}."
1148
- )
1149
- return expr if new_expr is None else new_expr
1150
-
1151
- def _get_variable_ref(
1152
- self, relationship: b.Relationship, parent_producer: b.Producer | None
1153
- ) -> Optional[Any]:
1154
- """Get variable reference for relationship, or None if not a solver variable."""
1155
- # Check if this relationship corresponds to a decision variable
1156
- VariableConcept = self.solver_model._variable_relationships.get(relationship)
1157
- if VariableConcept is None:
1158
- return None
1159
-
1160
- properties = {}
1161
- if parent_producer is not None:
1162
- properties[relationship._field_names[0]] = parent_producer
1163
- return VariableConcept(VariableConcept.ref(), **properties)