relationalai 0.12.4__py3-none-any.whl → 0.12.7__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 (116) hide show
  1. relationalai/__init__.py +4 -0
  2. relationalai/clients/snowflake.py +34 -13
  3. relationalai/early_access/lqp/constructors/__init__.py +2 -2
  4. relationalai/early_access/metamodel/rewrite/__init__.py +2 -2
  5. relationalai/{semantics/reasoners/graph → experimental}/paths/README.md +2 -2
  6. relationalai/experimental/paths/__init__.py +14 -309
  7. relationalai/{semantics/reasoners/graph → experimental}/paths/examples/basic_example.py +2 -2
  8. relationalai/{semantics/reasoners/graph → experimental}/paths/examples/paths_benchmark.py +2 -2
  9. relationalai/{semantics/reasoners/graph → experimental}/paths/examples/paths_example.py +2 -2
  10. relationalai/{semantics/reasoners/graph → experimental}/paths/examples/pattern_to_automaton.py +1 -1
  11. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/one_sided_ball_repetition.py +1 -1
  12. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/single.py +3 -3
  13. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/two_sided_balls_repetition.py +1 -1
  14. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/two_sided_balls_upto.py +2 -2
  15. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/usp-old.py +3 -3
  16. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/usp-tuple.py +3 -3
  17. relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/usp.py +3 -3
  18. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_max_length.py +2 -2
  19. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_multiple.py +2 -2
  20. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_single.py +2 -2
  21. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_walks_multiple.py +2 -2
  22. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_walks_single.py +2 -2
  23. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_repetition_multiple.py +2 -2
  24. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_repetition_single.py +2 -2
  25. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_upto_multiple.py +2 -2
  26. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_upto_single.py +2 -2
  27. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_paths.py +2 -2
  28. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_walks.py +2 -2
  29. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_walks_undirected.py +2 -2
  30. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_repetition_multiple.py +2 -2
  31. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_repetition_single.py +2 -2
  32. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_upto_multiple.py +2 -2
  33. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_upto_single.py +2 -2
  34. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_usp_nsp_multiple.py +2 -2
  35. relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_usp_nsp_single.py +2 -2
  36. relationalai/semantics/__init__.py +4 -0
  37. relationalai/semantics/internal/annotations.py +1 -0
  38. relationalai/semantics/internal/internal.py +3 -4
  39. relationalai/semantics/internal/snowflake.py +14 -1
  40. relationalai/semantics/lqp/builtins.py +1 -0
  41. relationalai/semantics/lqp/constructors.py +0 -5
  42. relationalai/semantics/lqp/executor.py +34 -10
  43. relationalai/semantics/lqp/intrinsics.py +2 -2
  44. relationalai/semantics/lqp/model2lqp.py +105 -9
  45. relationalai/semantics/lqp/passes.py +27 -8
  46. relationalai/semantics/lqp/primitives.py +18 -15
  47. relationalai/semantics/lqp/rewrite/__init__.py +2 -2
  48. relationalai/semantics/lqp/rewrite/{fd_constraints.py → function_annotations.py} +4 -4
  49. relationalai/semantics/lqp/utils.py +17 -13
  50. relationalai/semantics/metamodel/builtins.py +50 -1
  51. relationalai/semantics/metamodel/typer/typer.py +3 -0
  52. relationalai/semantics/reasoners/__init__.py +4 -0
  53. relationalai/semantics/reasoners/experimental/__init__.py +7 -0
  54. relationalai/semantics/reasoners/graph/core.py +1154 -122
  55. relationalai/semantics/rel/builtins.py +3 -1
  56. relationalai/semantics/rel/compiler.py +2 -2
  57. relationalai/semantics/rel/executor.py +30 -8
  58. relationalai/semantics/rel/rel_utils.py +5 -0
  59. relationalai/semantics/snowflake/__init__.py +2 -2
  60. relationalai/semantics/sql/compiler.py +6 -0
  61. relationalai/semantics/sql/executor/snowflake.py +6 -2
  62. relationalai/semantics/tests/test_snapshot_abstract.py +5 -4
  63. {relationalai-0.12.4.dist-info → relationalai-0.12.7.dist-info}/METADATA +2 -2
  64. {relationalai-0.12.4.dist-info → relationalai-0.12.7.dist-info}/RECORD +99 -115
  65. {relationalai-0.12.4.dist-info → relationalai-0.12.7.dist-info}/WHEEL +1 -1
  66. relationalai/early_access/paths/__init__.py +0 -22
  67. relationalai/early_access/paths/api/__init__.py +0 -12
  68. relationalai/early_access/paths/benchmarks/__init__.py +0 -13
  69. relationalai/early_access/paths/graph/__init__.py +0 -12
  70. relationalai/early_access/paths/path_algorithms/find_paths/__init__.py +0 -12
  71. relationalai/early_access/paths/path_algorithms/one_sided_ball_repetition/__init__.py +0 -12
  72. relationalai/early_access/paths/path_algorithms/one_sided_ball_upto/__init__.py +0 -12
  73. relationalai/early_access/paths/path_algorithms/single/__init__.py +0 -12
  74. relationalai/early_access/paths/path_algorithms/two_sided_balls_repetition/__init__.py +0 -12
  75. relationalai/early_access/paths/path_algorithms/two_sided_balls_upto/__init__.py +0 -12
  76. relationalai/early_access/paths/path_algorithms/usp/__init__.py +0 -12
  77. relationalai/early_access/paths/rpq/__init__.py +0 -13
  78. relationalai/early_access/paths/utilities/iterators/__init__.py +0 -12
  79. relationalai/experimental/paths/pathfinder.rel +0 -2560
  80. relationalai/semantics/reasoners/graph/paths/__init__.py +0 -16
  81. relationalai/semantics/reasoners/graph/paths/path_algorithms/__init__.py +0 -3
  82. relationalai/semantics/reasoners/graph/paths/utilities/__init__.py +0 -3
  83. /relationalai/{semantics/reasoners/graph → experimental}/paths/api.py +0 -0
  84. /relationalai/{semantics/reasoners/graph → experimental}/paths/benchmarks/__init__.py +0 -0
  85. /relationalai/{semantics/reasoners/graph → experimental}/paths/benchmarks/grid_graph.py +0 -0
  86. /relationalai/{semantics/reasoners/graph → experimental}/paths/code_organization.md +0 -0
  87. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/Movies.ipynb +0 -0
  88. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/minimal_engine_warmup.py +0 -0
  89. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movie_example.py +0 -0
  90. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/actedin.csv +0 -0
  91. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/directed.csv +0 -0
  92. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/follows.csv +0 -0
  93. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/movies.csv +0 -0
  94. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/person.csv +0 -0
  95. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/produced.csv +0 -0
  96. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/ratings.csv +0 -0
  97. /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/wrote.csv +0 -0
  98. /relationalai/{semantics/reasoners/graph → experimental}/paths/find_paths_via_automaton.py +0 -0
  99. /relationalai/{semantics/reasoners/graph → experimental}/paths/graph.py +0 -0
  100. /relationalai/{early_access → experimental}/paths/path_algorithms/__init__.py +0 -0
  101. /relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/find_paths.py +0 -0
  102. /relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/one_sided_ball_upto.py +0 -0
  103. /relationalai/{semantics/reasoners/graph → experimental}/paths/product_graph.py +0 -0
  104. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/__init__.py +0 -0
  105. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/automaton.py +0 -0
  106. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/diagnostics.py +0 -0
  107. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/filter.py +0 -0
  108. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/glushkov.py +0 -0
  109. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/rpq.py +0 -0
  110. /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/transition.py +0 -0
  111. /relationalai/{early_access → experimental}/paths/utilities/__init__.py +0 -0
  112. /relationalai/{semantics/reasoners/graph → experimental}/paths/utilities/iterators.py +0 -0
  113. /relationalai/{semantics/reasoners/graph → experimental}/paths/utilities/prefix_sum.py +0 -0
  114. /relationalai/{semantics/reasoners/graph → experimental}/paths/utilities/utilities.py +0 -0
  115. {relationalai-0.12.4.dist-info → relationalai-0.12.7.dist-info}/entry_points.txt +0 -0
  116. {relationalai-0.12.4.dist-info → relationalai-0.12.7.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,8 @@
1
1
  from relationalai.semantics.metamodel.types import digits_to_bits
2
2
  from relationalai.semantics.lqp import ir as lqp
3
3
  from relationalai.semantics.lqp.types import is_numeric
4
- from relationalai.semantics.lqp.utils import UniqueNames, lqp_hash
5
- from relationalai.semantics.lqp.constructors import mk_primitive, mk_specialized_value, mk_type, mk_value, mk_var
4
+ from relationalai.semantics.lqp.utils import TranslationCtx, gen_unique_var, lqp_hash
5
+ from relationalai.semantics.lqp.constructors import mk_primitive, mk_specialized_value, mk_type, mk_value
6
6
 
7
7
  rel_to_lqp = {
8
8
  "=": "rel_primitive_eq",
@@ -96,6 +96,9 @@ rel_to_lqp = {
96
96
  "split": "rel_primitive_string_split",
97
97
  "split_part": "rel_primitive_string_split",
98
98
  "regex_match": "rel_primitive_regex_match",
99
+ "infomap": "rel_primitive_infomap",
100
+ "louvain": "rel_primitive_louvain",
101
+ "label_propagation": "rel_primitive_async_label_propagation",
99
102
  }
100
103
 
101
104
  primitive_type_reorderings = {
@@ -202,15 +205,15 @@ def is_monotype(name: str) -> bool:
202
205
 
203
206
  # We take the name and type of the variable that we're summing over, so that we can generate
204
207
  # recognizable names for the variables in the reduce operation and preserve the type.
205
- def lqp_avg_op(names: UniqueNames, op_name: str, sum_name: str, sum_type: lqp.Type) -> lqp.Abstraction:
208
+ def lqp_avg_op(ctx: TranslationCtx, op_name: str, sum_name: str, sum_type: lqp.Type) -> lqp.Abstraction:
206
209
  count_type = mk_type(lqp.TypeName.INT)
207
210
  vars = [
208
- (mk_var(names.get_name(sum_name)), sum_type),
209
- (mk_var(names.get_name("counter")), count_type),
210
- (mk_var(names.get_name(sum_name)), sum_type),
211
- (mk_var(names.get_name("one")), count_type),
212
- (mk_var(names.get_name("sum")), sum_type),
213
- (mk_var(names.get_name("count")), count_type),
211
+ (gen_unique_var(ctx, sum_name), sum_type),
212
+ (gen_unique_var(ctx, "counter"), count_type),
213
+ (gen_unique_var(ctx, sum_name), sum_type),
214
+ (gen_unique_var(ctx, "one"), count_type),
215
+ (gen_unique_var(ctx, "sum"), sum_type),
216
+ (gen_unique_var(ctx, "count"), count_type),
214
217
  ]
215
218
 
216
219
  x1 = vars[0][0]
@@ -230,10 +233,10 @@ def lqp_avg_op(names: UniqueNames, op_name: str, sum_name: str, sum_type: lqp.Ty
230
233
  return lqp.Abstraction(vars=vars, value=body, meta=None)
231
234
 
232
235
  # Default handler for aggregation operations in LQP.
233
- def lqp_agg_op(names: UniqueNames, op_name: str, aggr_arg_name: str, aggr_arg_type: lqp.Type) -> lqp.Abstraction:
234
- x = mk_var(names.get_name(f"x_{aggr_arg_name}"))
235
- y = mk_var(names.get_name(f"y_{aggr_arg_name}"))
236
- z = mk_var(names.get_name(f"z_{aggr_arg_name}"))
236
+ def lqp_agg_op(ctx: TranslationCtx, op_name: str, aggr_arg_name: str, aggr_arg_type: lqp.Type) -> lqp.Abstraction:
237
+ x = gen_unique_var(ctx, f"x_{aggr_arg_name}")
238
+ y = gen_unique_var(ctx, f"y_{aggr_arg_name}")
239
+ z = gen_unique_var(ctx, f"z_{aggr_arg_name}")
237
240
  ts = [(x, aggr_arg_type), (y, aggr_arg_type), (z, aggr_arg_type)]
238
241
 
239
242
  name = agg_to_lqp.get(op_name, op_name)
@@ -241,9 +244,9 @@ def lqp_agg_op(names: UniqueNames, op_name: str, aggr_arg_name: str, aggr_arg_ty
241
244
 
242
245
  return lqp.Abstraction(vars=ts, value=body, meta=None)
243
246
 
244
- def lqp_operator(names: UniqueNames, op_name: str, aggr_arg_name: str, aggr_arg_type: lqp.Type) -> lqp.Abstraction:
247
+ def lqp_operator(ctx: TranslationCtx, op_name: str, aggr_arg_name: str, aggr_arg_type: lqp.Type) -> lqp.Abstraction:
245
248
  # TODO: Can we just pass through unknown operations?
246
249
  if op_name not in agg_to_lqp:
247
250
  raise NotImplementedError(f"Unsupported aggregation: {op_name}")
248
251
 
249
- return lqp_agg_op(names, op_name, aggr_arg_name, aggr_arg_type)
252
+ return lqp_agg_op(ctx, op_name, aggr_arg_name, aggr_arg_type)
@@ -1,7 +1,7 @@
1
1
  from .cdc import CDC
2
2
  from .extract_common import ExtractCommon
3
3
  from .extract_keys import ExtractKeys
4
- from .fd_constraints import FDConstraints
4
+ from .function_annotations import FunctionAnnotations
5
5
  from .quantify_vars import QuantifyVars
6
6
  from .splinter import Splinter
7
7
 
@@ -9,7 +9,7 @@ __all__ = [
9
9
  "CDC",
10
10
  "ExtractCommon",
11
11
  "ExtractKeys",
12
- "FDConstraints",
12
+ "FunctionAnnotations",
13
13
  "QuantifyVars",
14
14
  "Splinter",
15
15
  ]
@@ -5,7 +5,7 @@ from relationalai.semantics.metamodel import ir, compiler as c, visitor as v, bu
5
5
  from relationalai.semantics.metamodel.util import OrderedSet, ordered_set
6
6
 
7
7
 
8
- class FDConstraints(c.Pass):
8
+ class FunctionAnnotations(c.Pass):
9
9
  """
10
10
  Pass marks all appropriate relations with `function` annotation.
11
11
  Criteria:
@@ -17,7 +17,7 @@ class FDConstraints(c.Pass):
17
17
  collect_fd = CollectFunctionalRelationsVisitor()
18
18
  new_model = collect_fd.walk(model)
19
19
  # mark relations collected by previous visitor with `@function` annotation
20
- return FDConstraintsVisitor(collect_fd.functional_relations).walk(new_model)
20
+ return FunctionalAnnotationsVisitor(collect_fd.functional_relations).walk(new_model)
21
21
 
22
22
 
23
23
  @dataclass
@@ -57,9 +57,9 @@ class CollectFunctionalRelationsVisitor(v.Rewriter):
57
57
 
58
58
 
59
59
  @dataclass
60
- class FDConstraintsVisitor(v.Rewriter):
60
+ class FunctionalAnnotationsVisitor(v.Rewriter):
61
61
  """
62
- This visitor marks functional_relations with `functional` annotation.
62
+ This visitor marks functional_relations with `function` annotation.
63
63
  """
64
64
 
65
65
  def __init__(self, functional_relations: OrderedSet):
@@ -1,5 +1,6 @@
1
1
  from relationalai.semantics.lqp import ir as lqp
2
2
  from relationalai.semantics.metamodel import ir
3
+ from relationalai.semantics.metamodel.helpers import sanitize
3
4
  from relationalai.semantics.metamodel.util import FrozenOrderedSet
4
5
 
5
6
  from hashlib import sha256
@@ -13,21 +14,24 @@ class UniqueNames:
13
14
  self.id_to_name = dict[int,str]()
14
15
 
15
16
  def get_name(self, name: str) -> str:
16
- if name in self.seen:
17
- self.seen[name] += 1
18
- id = self.seen[name]
19
- # If the original name has a suffix we can get collisions with generated names,
20
- # so test the new name.
21
- while f"{name}_{id}" in self.seen:
22
- id += 1
23
- self.seen[name] = id
24
- new_name = f"{name}_{id}"
25
- self.seen[new_name] = 1
26
- return new_name
27
- else:
17
+ # Names will eventually be sanitized, which could cause collisions, so we
18
+ # do the sanitization here.
19
+ name = '_' if name == '_' else sanitize(name)
20
+ if name not in self.seen:
28
21
  self.seen[name] = 1
29
22
  return f"{name}"
30
23
 
24
+ self.seen[name] += 1
25
+ id = self.seen[name]
26
+ # If the original name has a suffix we can get collisions with generated names,
27
+ # so test the new name.
28
+ while f"{name}_{id}" in self.seen:
29
+ id += 1
30
+ self.seen[name] = id
31
+ new_name = f"{name}_{id}"
32
+ self.seen[new_name] = 1
33
+ return new_name
34
+
31
35
  # Get a unique name for the given id. If the id is already in the map, return the
32
36
  # existing name. Otherwise, generate a new name using the suggested_name and
33
37
  # store it in the map.
@@ -55,7 +59,7 @@ def gen_rel_id(ctx: TranslationCtx, orig_name: str, suffix: str = "") -> lqp.Rel
55
59
  ctx.rel_id_to_orig_name[relation_id] = orig_name
56
60
  return relation_id
57
61
 
58
- def gen_unique_var(ctx: TranslationCtx, name_hint: str):
62
+ def gen_unique_var(ctx: TranslationCtx, name_hint: str) -> lqp.Var:
59
63
  """
60
64
  Generate a new variable with a unique name based on the provided hint.
61
65
  """
@@ -507,6 +507,13 @@ track = f.relation("track", [
507
507
  ])
508
508
  track_annotation = f.annotation(track, [])
509
509
 
510
+ # Enables config used by raicode/src/Recursion. Supported for Relationships and queries.
511
+ recursion_config = f.relation("recursion_config", [
512
+ f.input_field("config_key", types.Symbol),
513
+ f.input_field("config_value", types.Int64)
514
+ ])
515
+ recursion_config_annotation = f.annotation(recursion_config, [])
516
+
510
517
  # All ir nodes marked by this annotation will be removed from the final metamodel before compilation.
511
518
  # Specifically it happens in `Flatten` pass when rewrites for `require` happen
512
519
  discharged = f.relation("discharged", [])
@@ -648,6 +655,48 @@ rel_primitive_solverlib_ho_appl = aggregation("rel_primitive_solverlib_ho_appl",
648
655
  implies = f.relation("implies", [f.input_field("a", types.Bool), f.input_field("b", types.Bool)])
649
656
  all_different = aggregation("all_different", [f.input_field("over", types.Any)])
650
657
 
658
+ # graph primitive algorithm helpers
659
+ infomap = aggregation("infomap", [
660
+ f.input_field("weights", types.AnyList),
661
+ f.input_field("node_count", types.Any),
662
+ f.input_field("edge_count", types.Any),
663
+ f.input_field("teleportation_rate", types.Float),
664
+ f.input_field("visit_rate_tolerance", types.Float),
665
+ f.input_field("level_tolerance", types.Float),
666
+ f.input_field("sweep_tolerance", types.Float),
667
+ f.input_field("max_levels", types.Int64),
668
+ f.input_field("max_sweeps", types.Int64),
669
+ f.input_field("randomization_seed", types.Int64),
670
+ f.field("termination_info", types.String),
671
+ f.field("node_index", types.Int64),
672
+ f.field("community", types.Int64)
673
+ ])
674
+
675
+ louvain = aggregation("louvain", [
676
+ f.input_field("weights", types.AnyList),
677
+ f.input_field("node_count", types.Any),
678
+ f.input_field("edge_count", types.Any),
679
+ f.input_field("level_tolerance", types.Float),
680
+ f.input_field("sweep_tolerance", types.Float),
681
+ f.input_field("max_levels", types.Int64),
682
+ f.input_field("max_sweeps", types.Int64),
683
+ f.input_field("randomization_seed", types.Int64),
684
+ f.field("termination_info", types.String),
685
+ f.field("node_index", types.Int64),
686
+ f.field("community", types.Int64)
687
+ ])
688
+
689
+ label_propagation = aggregation("label_propagation", [
690
+ f.input_field("weights", types.AnyList),
691
+ f.input_field("node_count", types.Any),
692
+ f.input_field("edge_count", types.Any),
693
+ f.input_field("max_sweeps", types.Int64),
694
+ f.input_field("randomization_seed", types.Int64),
695
+ f.field("termination_info", types.String),
696
+ f.field("node_index", types.Int64),
697
+ f.field("community", types.Int64)
698
+ ])
699
+
651
700
  #
652
701
  # Public access to built-in relations
653
702
  #
@@ -683,7 +732,7 @@ def _compute_builtin_overloads() -> list[ir.Relation]:
683
732
  return overloads
684
733
 
685
734
  # manually maintain the list of relations that are actually annotations
686
- builtin_annotations = [external, export, concept_population, from_cdc, from_cast, track]
735
+ builtin_annotations = [external, export, concept_population, from_cdc, from_cast, track, recursion_config]
687
736
  builtin_annotations_by_name = dict((r.name, r) for r in builtin_annotations)
688
737
 
689
738
  builtin_relations = _compute_builtin_relations()
@@ -137,6 +137,9 @@ def to_type(value: ir.Value|ir.Field) -> ir.Type:
137
137
  if isinstance(value, tuple):
138
138
  return types.AnyList
139
139
 
140
+ if isinstance(value, ir.Relation):
141
+ return types.AnyList
142
+
140
143
  raise TypeError(f"Cannot determine IR type for value: {value} of type {type(value).__name__}")
141
144
 
142
145
  def type_matches(actual:ir.Type, expected:ir.Type, allow_expected_parents=False) -> bool:
@@ -1,3 +1,7 @@
1
+ """
2
+ The RelationalAI Semantics Reasoners Module.
3
+ """
4
+
1
5
  # Mark this package's docstrings for inclusion
2
6
  # in automatically generated web documentation,
3
7
  # by default as early access.
@@ -0,0 +1,7 @@
1
+ """
2
+ Experimental reasoners and algorithms.
3
+
4
+ This namespace contains experimental features that may change in future versions.
5
+ """
6
+
7
+ __all__ = []