relationalai 0.12.4__py3-none-any.whl → 0.12.6__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.
- relationalai/__init__.py +4 -0
- relationalai/clients/snowflake.py +23 -11
- relationalai/{semantics/reasoners/graph → experimental}/paths/README.md +2 -2
- relationalai/experimental/paths/__init__.py +14 -309
- relationalai/{semantics/reasoners/graph → experimental}/paths/examples/basic_example.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/examples/paths_benchmark.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/examples/paths_example.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/examples/pattern_to_automaton.py +1 -1
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/one_sided_ball_repetition.py +1 -1
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/single.py +3 -3
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/two_sided_balls_repetition.py +1 -1
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/two_sided_balls_upto.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/usp-old.py +3 -3
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/usp-tuple.py +3 -3
- relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/usp.py +3 -3
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_max_length.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_single.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_walks_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_walks_single.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_repetition_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_repetition_single.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_upto_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_one_sided_ball_upto_single.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_paths.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_walks.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_walks_undirected.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_repetition_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_repetition_single.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_upto_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_two_sided_balls_upto_single.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_usp_nsp_multiple.py +2 -2
- relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_usp_nsp_single.py +2 -2
- relationalai/semantics/__init__.py +4 -0
- relationalai/semantics/internal/annotations.py +1 -0
- relationalai/semantics/internal/internal.py +2 -0
- relationalai/semantics/lqp/builtins.py +1 -0
- relationalai/semantics/lqp/model2lqp.py +96 -3
- relationalai/semantics/lqp/primitives.py +3 -0
- relationalai/semantics/metamodel/builtins.py +50 -1
- relationalai/semantics/metamodel/typer/typer.py +3 -0
- relationalai/semantics/reasoners/__init__.py +4 -0
- relationalai/semantics/reasoners/experimental/__init__.py +7 -0
- relationalai/semantics/reasoners/graph/core.py +1154 -122
- relationalai/semantics/rel/builtins.py +3 -1
- relationalai/semantics/rel/rel_utils.py +5 -0
- relationalai/semantics/sql/compiler.py +6 -0
- {relationalai-0.12.4.dist-info → relationalai-0.12.6.dist-info}/METADATA +1 -1
- {relationalai-0.12.4.dist-info → relationalai-0.12.6.dist-info}/RECORD +84 -100
- {relationalai-0.12.4.dist-info → relationalai-0.12.6.dist-info}/WHEEL +1 -1
- relationalai/early_access/paths/__init__.py +0 -22
- relationalai/early_access/paths/api/__init__.py +0 -12
- relationalai/early_access/paths/benchmarks/__init__.py +0 -13
- relationalai/early_access/paths/graph/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/find_paths/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/one_sided_ball_repetition/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/one_sided_ball_upto/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/single/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/two_sided_balls_repetition/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/two_sided_balls_upto/__init__.py +0 -12
- relationalai/early_access/paths/path_algorithms/usp/__init__.py +0 -12
- relationalai/early_access/paths/rpq/__init__.py +0 -13
- relationalai/early_access/paths/utilities/iterators/__init__.py +0 -12
- relationalai/experimental/paths/pathfinder.rel +0 -2560
- relationalai/semantics/reasoners/graph/paths/__init__.py +0 -16
- relationalai/semantics/reasoners/graph/paths/path_algorithms/__init__.py +0 -3
- relationalai/semantics/reasoners/graph/paths/utilities/__init__.py +0 -3
- /relationalai/{semantics/reasoners/graph → experimental}/paths/api.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/benchmarks/__init__.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/benchmarks/grid_graph.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/code_organization.md +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/Movies.ipynb +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/minimal_engine_warmup.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movie_example.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/actedin.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/directed.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/follows.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/movies.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/person.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/produced.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/ratings.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/examples/movies_data/wrote.csv +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/find_paths_via_automaton.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/graph.py +0 -0
- /relationalai/{early_access → experimental}/paths/path_algorithms/__init__.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/find_paths.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/path_algorithms/one_sided_ball_upto.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/product_graph.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/__init__.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/automaton.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/diagnostics.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/filter.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/glushkov.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/rpq.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/rpq/transition.py +0 -0
- /relationalai/{early_access → experimental}/paths/utilities/__init__.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/utilities/iterators.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/utilities/prefix_sum.py +0 -0
- /relationalai/{semantics/reasoners/graph → experimental}/paths/utilities/utilities.py +0 -0
- {relationalai-0.12.4.dist-info → relationalai-0.12.6.dist-info}/entry_points.txt +0 -0
- {relationalai-0.12.4.dist-info → relationalai-0.12.6.dist-info}/licenses/LICENSE +0 -0
relationalai/__init__.py
CHANGED
|
@@ -834,19 +834,25 @@ Otherwise, remove it from your '{profile}' configuration profile.
|
|
|
834
834
|
program_span_id: str | None = None,
|
|
835
835
|
headers: Dict | None = None,
|
|
836
836
|
):
|
|
837
|
-
"""Only call
|
|
837
|
+
"""Only call poll() if there are sources to process and cache is not valid."""
|
|
838
838
|
sources_list = list(sources)
|
|
839
839
|
self.database = model
|
|
840
840
|
if sources_list:
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
841
|
+
poller = UseIndexPoller(
|
|
842
|
+
self,
|
|
843
|
+
app_name,
|
|
844
|
+
sources_list,
|
|
845
|
+
model,
|
|
846
|
+
engine_name,
|
|
847
|
+
engine_size,
|
|
848
|
+
self.language,
|
|
849
|
+
program_span_id,
|
|
850
|
+
headers,
|
|
851
|
+
self.generation
|
|
849
852
|
)
|
|
853
|
+
# If cache is valid (data freshness has not expired), skip polling
|
|
854
|
+
if not poller.cache.is_valid():
|
|
855
|
+
return poller.poll()
|
|
850
856
|
|
|
851
857
|
#--------------------------------------------------
|
|
852
858
|
# Models
|
|
@@ -3450,19 +3456,25 @@ class DirectAccessResources(Resources):
|
|
|
3450
3456
|
program_span_id: str | None = None,
|
|
3451
3457
|
headers: Dict | None = None,
|
|
3452
3458
|
):
|
|
3453
|
-
"""Only call
|
|
3459
|
+
"""Only call poll() if there are sources to process and cache is not valid."""
|
|
3454
3460
|
sources_list = list(sources)
|
|
3455
3461
|
self.database = model
|
|
3456
3462
|
if sources_list:
|
|
3457
|
-
|
|
3463
|
+
poller = DirectUseIndexPoller(
|
|
3464
|
+
self,
|
|
3458
3465
|
app_name=app_name,
|
|
3459
3466
|
sources=sources_list,
|
|
3460
3467
|
model=model,
|
|
3461
3468
|
engine_name=engine_name,
|
|
3462
3469
|
engine_size=engine_size,
|
|
3470
|
+
language=self.language,
|
|
3463
3471
|
program_span_id=program_span_id,
|
|
3464
3472
|
headers=headers,
|
|
3473
|
+
generation=self.generation,
|
|
3465
3474
|
)
|
|
3475
|
+
# If cache is valid (data freshness has not expired), skip polling
|
|
3476
|
+
if not poller.cache.is_valid():
|
|
3477
|
+
return poller.poll()
|
|
3466
3478
|
|
|
3467
3479
|
def _check_exec_async_status(self, txn_id: str, headers: Dict[str, str] | None = None) -> bool:
|
|
3468
3480
|
"""Check whether the given transaction has completed."""
|
|
@@ -12,8 +12,8 @@ The following is a minimal working example:
|
|
|
12
12
|
from relationalai.semantics import Model, Integer, select, String, where, define
|
|
13
13
|
from relationalai.semantics.std import strings
|
|
14
14
|
|
|
15
|
-
from relationalai.
|
|
16
|
-
from relationalai.
|
|
15
|
+
from relationalai.experimental.paths.graph import Graph
|
|
16
|
+
from relationalai.experimental.paths.api import node, edge, path, star, match
|
|
17
17
|
|
|
18
18
|
model = Model("my_paths")
|
|
19
19
|
|
|
@@ -1,309 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
self.max = 1
|
|
16
|
-
|
|
17
|
-
def __getitem__(self, key):
|
|
18
|
-
if isinstance(key, slice):
|
|
19
|
-
self.min = key.start
|
|
20
|
-
self.max = key.stop
|
|
21
|
-
else:
|
|
22
|
-
raise ValueError("VarLength only supports slicing")
|
|
23
|
-
return self
|
|
24
|
-
|
|
25
|
-
class PathSelection(Enum):
|
|
26
|
-
ALL = "all" # return all paths between source and target
|
|
27
|
-
SINGLE = "single" # return a single path between source and target
|
|
28
|
-
LIMIT = "limit" # return a specified number paths between source and target, as given by parameter k.
|
|
29
|
-
RANDOM = "random" # return a single randomly-chosen path between source and target, seeded with parameter seed.
|
|
30
|
-
UNIFORM_RANDOM = "uniform_random" # return a single uniform randomly-chosen path between source and target, seeded with parameter seed.
|
|
31
|
-
|
|
32
|
-
class PathGroup(Enum):
|
|
33
|
-
ANY = "any"
|
|
34
|
-
FOREACH = "for_each"
|
|
35
|
-
|
|
36
|
-
class Strategy(Enum):
|
|
37
|
-
FROM_SOURCE = "from_source"
|
|
38
|
-
TWO_SIDED = "two_sided"
|
|
39
|
-
|
|
40
|
-
class PathQuery:
|
|
41
|
-
|
|
42
|
-
def __init__(
|
|
43
|
-
self,
|
|
44
|
-
model: Graph,
|
|
45
|
-
segments: List[Union[Instance,VarLength]],
|
|
46
|
-
backwards_edge: str,
|
|
47
|
-
group: PathGroup = PathGroup.FOREACH,
|
|
48
|
-
selection: PathSelection = PathSelection.ALL,
|
|
49
|
-
strategy: Strategy = Strategy.FROM_SOURCE,
|
|
50
|
-
):
|
|
51
|
-
# create types and instance
|
|
52
|
-
self._path_id = next_id()
|
|
53
|
-
self._conn_relation_name = f"conn_{self._path_id}"
|
|
54
|
-
self._model = model
|
|
55
|
-
|
|
56
|
-
# create types
|
|
57
|
-
self._Path = dsl.Type(model, f"Path{self._path_id}", omit_intrinsic_type_in_hash=True)
|
|
58
|
-
self._PathNode = dsl.Type(model, f"PathNode{self._path_id}", omit_intrinsic_type_in_hash=True)
|
|
59
|
-
self._PathEdge = dsl.Type(model, f"PathEdge{self._path_id}", omit_intrinsic_type_in_hash=True)
|
|
60
|
-
|
|
61
|
-
# declare multivalued attributes
|
|
62
|
-
self._Path.nodes.has_many()
|
|
63
|
-
self._Path.edges.has_many()
|
|
64
|
-
|
|
65
|
-
# mark these types and their attributes as @no_inline
|
|
66
|
-
self._add_noinline(self._Path, [])
|
|
67
|
-
self._add_noinline(self._PathNode, ["path", "index", "node_id"])
|
|
68
|
-
self._add_noinline(self._PathEdge, ["path", "index", "label"])
|
|
69
|
-
|
|
70
|
-
# create instance
|
|
71
|
-
self._instance = self._Path()
|
|
72
|
-
self._match_called = False
|
|
73
|
-
|
|
74
|
-
# store path query attributes
|
|
75
|
-
self._segments = segments
|
|
76
|
-
self._backwards_edge = backwards_edge
|
|
77
|
-
self._group = group
|
|
78
|
-
self._selection = selection
|
|
79
|
-
self._strategy = strategy
|
|
80
|
-
|
|
81
|
-
def _add_noinline(self, typ, props):
|
|
82
|
-
typ._type.parents.append(Builtins.NoInlineAnnotation)
|
|
83
|
-
for prop in props:
|
|
84
|
-
getattr(typ, prop)._prop.parents.append(Builtins.NoInlineAnnotation)
|
|
85
|
-
|
|
86
|
-
def _match(self):
|
|
87
|
-
# avoid emitting the Rel multiple times, which throws off Pathfinder
|
|
88
|
-
if not self._match_called:
|
|
89
|
-
self._match_called = True
|
|
90
|
-
|
|
91
|
-
begin_var, end_var = self._match_inner()
|
|
92
|
-
|
|
93
|
-
self._begin_var = begin_var
|
|
94
|
-
self._end_var = end_var
|
|
95
|
-
|
|
96
|
-
return self._conn_relation_name
|
|
97
|
-
|
|
98
|
-
def _match_inner(self):
|
|
99
|
-
begin_var = None
|
|
100
|
-
cur_end = None
|
|
101
|
-
|
|
102
|
-
for idx, segment in enumerate(self._segments):
|
|
103
|
-
if isinstance(segment, VarLength):
|
|
104
|
-
var_length_rel_name = self._var_length(idx, segment)
|
|
105
|
-
seg_begin, seg_end = create_vars(2)
|
|
106
|
-
getattr(rel, var_length_rel_name)(seg_begin, seg_end)
|
|
107
|
-
|
|
108
|
-
if begin_var is None:
|
|
109
|
-
begin_var = seg_begin
|
|
110
|
-
cur_end = seg_end
|
|
111
|
-
else:
|
|
112
|
-
getattr(seg_begin, self._backwards_edge) == cur_end
|
|
113
|
-
cur_end = seg_end
|
|
114
|
-
else:
|
|
115
|
-
next_var = segment
|
|
116
|
-
if begin_var is None:
|
|
117
|
-
begin_var = next_var
|
|
118
|
-
cur_end = begin_var
|
|
119
|
-
else:
|
|
120
|
-
getattr(next_var, self._backwards_edge) == cur_end
|
|
121
|
-
cur_end = next_var
|
|
122
|
-
|
|
123
|
-
conn_relation = getattr(rel, self._conn_relation_name)
|
|
124
|
-
conn_relation._rel.parents.append(Builtins.NoInlineAnnotation)
|
|
125
|
-
conn_relation.add(begin_var, cur_end)
|
|
126
|
-
|
|
127
|
-
return begin_var, cur_end
|
|
128
|
-
|
|
129
|
-
def _var_length(self, segment_idx: int, segment: VarLength):
|
|
130
|
-
# relations for each length
|
|
131
|
-
prefix = f"conn_{self._path_id}_segment_{segment_idx}"
|
|
132
|
-
|
|
133
|
-
lines = []
|
|
134
|
-
|
|
135
|
-
for length in range(1, segment.max+1):
|
|
136
|
-
length_rel_name = f"{prefix}_length_{length}"
|
|
137
|
-
|
|
138
|
-
if length == 1:
|
|
139
|
-
lines.extend([
|
|
140
|
-
f"def {length_rel_name}(a, a1):",
|
|
141
|
-
f" {segment.type._type.name}(a) and",
|
|
142
|
-
" a = a1"
|
|
143
|
-
])
|
|
144
|
-
# would just project `(a, a)`, but that gives a
|
|
145
|
-
# bunch of Rel warnings`
|
|
146
|
-
|
|
147
|
-
else:
|
|
148
|
-
prev_length_relation_name = f"{prefix}_length_{length-1}"
|
|
149
|
-
lines.extend([
|
|
150
|
-
f"def {length_rel_name}(a, c):",
|
|
151
|
-
" exists((b) |",
|
|
152
|
-
f" {prev_length_relation_name}(a, b) and",
|
|
153
|
-
f" {segment.type._type.name}(c) and",
|
|
154
|
-
f" {self._backwards_edge}(c, b)",
|
|
155
|
-
" )"
|
|
156
|
-
])
|
|
157
|
-
|
|
158
|
-
# union them all together in overall segment relation
|
|
159
|
-
lines.extend([
|
|
160
|
-
f"def {prefix}(start, finish):",
|
|
161
|
-
" " + " or\n ".join([
|
|
162
|
-
f"{prefix}_length_{length}(start, finish)"
|
|
163
|
-
for length in range(1, segment.max+1)
|
|
164
|
-
]),
|
|
165
|
-
])
|
|
166
|
-
|
|
167
|
-
self._model.install_raw(
|
|
168
|
-
'\n'.join(lines),
|
|
169
|
-
name=f"path_{self._path_id}_segment_{segment_idx}",
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
return prefix
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class PathInstance(Instance):
|
|
176
|
-
|
|
177
|
-
def __init__(
|
|
178
|
-
self,
|
|
179
|
-
path_query: PathQuery,
|
|
180
|
-
):
|
|
181
|
-
self._path_query = path_query
|
|
182
|
-
|
|
183
|
-
self._already_called = False
|
|
184
|
-
super().__init__(
|
|
185
|
-
self._path_query._model,
|
|
186
|
-
ActionType.Get, [self._path_query._instance],
|
|
187
|
-
named={},
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
# implements producer API
|
|
191
|
-
def _to_var(self):
|
|
192
|
-
self._invoke_pathfinder()
|
|
193
|
-
return super()._to_var()
|
|
194
|
-
|
|
195
|
-
def _invoke_pathfinder(self):
|
|
196
|
-
if self._already_called:
|
|
197
|
-
return
|
|
198
|
-
self._already_called = True
|
|
199
|
-
|
|
200
|
-
# ensure that the pathfinder Rel library is installed
|
|
201
|
-
_install_pathfinder(self._path_query._model)
|
|
202
|
-
|
|
203
|
-
source_rel = f"source_{self._path_query._path_id}"
|
|
204
|
-
target_rel = f"target_{self._path_query._path_id}"
|
|
205
|
-
getattr(rel, source_rel).add(self._path_query._begin_var)
|
|
206
|
-
getattr(rel, target_rel).add(self._path_query._end_var)
|
|
207
|
-
|
|
208
|
-
shortest_paths_rel = f"shortest_paths_{self._path_query._path_id}"
|
|
209
|
-
path_edge_rel = f"path_edge_{self._path_query._path_id}"
|
|
210
|
-
path_node_rel = f"path_node_{self._path_query._path_id}"
|
|
211
|
-
|
|
212
|
-
invocation = f"""
|
|
213
|
-
@no_inline
|
|
214
|
-
def {shortest_paths_rel} {{
|
|
215
|
-
::pathfinder::shortest_paths[
|
|
216
|
-
:{self._path_query._group.value},
|
|
217
|
-
:{self._path_query._selection.value},
|
|
218
|
-
:{self._path_query._strategy.value},
|
|
219
|
-
{self._path_query._conn_relation_name},
|
|
220
|
-
{source_rel},
|
|
221
|
-
{target_rel}
|
|
222
|
-
]
|
|
223
|
-
}}
|
|
224
|
-
|
|
225
|
-
@no_inline
|
|
226
|
-
def {path_node_rel}(path, index, id):
|
|
227
|
-
{shortest_paths_rel}(path, :node, index, id)
|
|
228
|
-
|
|
229
|
-
@no_inline
|
|
230
|
-
def {path_edge_rel}(path, index, label):
|
|
231
|
-
{shortest_paths_rel}(path, :edge_label, index, label)
|
|
232
|
-
"""
|
|
233
|
-
|
|
234
|
-
self._path_query._model.install_raw(invocation)
|
|
235
|
-
|
|
236
|
-
# select out nodes
|
|
237
|
-
with self._path_query._model.rule():
|
|
238
|
-
path_id, index, node_label = create_vars(3)
|
|
239
|
-
getattr(rel, path_node_rel)(path_id, index, node_label)
|
|
240
|
-
path = self._path_query._Path.add(id=path_id)
|
|
241
|
-
# TODO: avoid perf hit of going in both directions (path<->node)
|
|
242
|
-
node = self._path_query._PathNode.add(path=path, index=index, value=node_label)
|
|
243
|
-
path.nodes.add(node)
|
|
244
|
-
|
|
245
|
-
# select out edges
|
|
246
|
-
with self._path_query._model.rule():
|
|
247
|
-
path_id, index, label = create_vars(3)
|
|
248
|
-
getattr(rel, path_edge_rel)(path_id, index, label)
|
|
249
|
-
path = self._path_query._Path.add(id=path_id)
|
|
250
|
-
# TODO: avoid perf hit of going in both directions (path<->edge)
|
|
251
|
-
edge = self._path_query._PathEdge.add(path=path, index=index, label=label)
|
|
252
|
-
path.edges.add(edge)
|
|
253
|
-
|
|
254
|
-
# TODO: automatically infer this from the path query itself
|
|
255
|
-
def enable_on(edge: Property, filter_attrs: List[Tuple[Type, Set[str]]]): # noqa: F821
|
|
256
|
-
edge._prop.parents.append(Builtins.PQEdgeAnnotation)
|
|
257
|
-
edge._prop.parents.append(Builtins.NoInlineAnnotation)
|
|
258
|
-
for type, attrs in filter_attrs:
|
|
259
|
-
type._type.parents.append(Builtins.PQFilterAnnotation)
|
|
260
|
-
type._type.parents.append(Builtins.NoInlineAnnotation)
|
|
261
|
-
for attr_name in attrs:
|
|
262
|
-
prop = getattr(type, attr_name)
|
|
263
|
-
prop._prop.parents.append(Builtins.PQFilterAnnotation)
|
|
264
|
-
prop._prop.parents.append(Builtins.NoInlineAnnotation)
|
|
265
|
-
|
|
266
|
-
# main entry point
|
|
267
|
-
def path(
|
|
268
|
-
segments: List[Union[Instance,VarLength]],
|
|
269
|
-
backwards_edge: str,
|
|
270
|
-
group: PathGroup = PathGroup.FOREACH,
|
|
271
|
-
selection: PathSelection = PathSelection.ALL,
|
|
272
|
-
strategy: Strategy = Strategy.FROM_SOURCE,
|
|
273
|
-
):
|
|
274
|
-
"""
|
|
275
|
-
Find a path consisting of the provided segments, linked by
|
|
276
|
-
the provided `backwards_edge` property.
|
|
277
|
-
"""
|
|
278
|
-
|
|
279
|
-
model = get_graph()
|
|
280
|
-
|
|
281
|
-
query = PathQuery(model, segments, backwards_edge, group, selection, strategy)
|
|
282
|
-
|
|
283
|
-
# declare filter relations
|
|
284
|
-
conn_relation_name = query._match()
|
|
285
|
-
|
|
286
|
-
# invoke filter
|
|
287
|
-
a, b = create_vars(2)
|
|
288
|
-
getattr(rel, conn_relation_name)(a, b)
|
|
289
|
-
|
|
290
|
-
# return a special Producer representing the path itself, which
|
|
291
|
-
# lazily invokes Pathfinder
|
|
292
|
-
return PathInstance(query)
|
|
293
|
-
|
|
294
|
-
def _get_pathfinder_source():
|
|
295
|
-
# check if the current dir is in a zip file
|
|
296
|
-
current_dir = os.path.dirname(__file__)
|
|
297
|
-
pathfinder_path = os.path.join(current_dir, "pathfinder.rel")
|
|
298
|
-
if os.path.exists(pathfinder_path):
|
|
299
|
-
return open(pathfinder_path).read()
|
|
300
|
-
# if we're in a zip file, read it within that
|
|
301
|
-
zip_split = current_dir.split(".zip")
|
|
302
|
-
zip_path = zip_split[0] + ".zip"
|
|
303
|
-
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
|
304
|
-
with zip_ref.open('relationalai/experimental/paths/pathfinder.rel') as file:
|
|
305
|
-
return file.read().decode("utf-8")
|
|
306
|
-
|
|
307
|
-
def _install_pathfinder(model: Graph):
|
|
308
|
-
source = _get_pathfinder_source()
|
|
309
|
-
model.install_raw(source, name="pathfinder", overwrite=True)
|
|
1
|
+
## pathfinder module
|
|
2
|
+
|
|
3
|
+
from .api import node, edge, path, optional, plus, star, union, match
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
'node',
|
|
7
|
+
'edge',
|
|
8
|
+
'path',
|
|
9
|
+
'optional',
|
|
10
|
+
'plus',
|
|
11
|
+
'star',
|
|
12
|
+
'union',
|
|
13
|
+
'match',
|
|
14
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, select, String, define
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.api import path, star, match
|
|
4
4
|
|
|
5
5
|
# Create an automaton that matches paths with pattern: A(A*)B:
|
|
6
6
|
pattern = path("A", star("A"), "B")
|
|
@@ -4,8 +4,8 @@ Example usage of automaton-based pathfinding.
|
|
|
4
4
|
|
|
5
5
|
import time
|
|
6
6
|
from relationalai.semantics import Model, Integer, select, String, define
|
|
7
|
-
from relationalai.
|
|
8
|
-
from relationalai.
|
|
7
|
+
from relationalai.experimental.paths.graph import Graph
|
|
8
|
+
from relationalai.experimental.paths.api import node, path, match
|
|
9
9
|
|
|
10
10
|
import argparse
|
|
11
11
|
|
|
@@ -4,8 +4,8 @@ Example usage of automaton-based pathfinding.
|
|
|
4
4
|
|
|
5
5
|
import time
|
|
6
6
|
from relationalai.semantics import Model, Integer, select, String, define
|
|
7
|
-
from relationalai.
|
|
8
|
-
from relationalai.
|
|
7
|
+
from relationalai.experimental.paths.graph import Graph
|
|
8
|
+
from relationalai.experimental.paths.api import node, path, match
|
|
9
9
|
|
|
10
10
|
import argparse
|
|
11
11
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Integer, define
|
|
3
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def ball_with_repetition(g:Graph, Source, max_length):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Integer, where, define, select, min
|
|
3
|
-
from relationalai.
|
|
4
|
-
from relationalai.
|
|
5
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_repetition import ball_with_repetition
|
|
5
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_upto import ball_upto
|
|
6
6
|
|
|
7
7
|
# find a (deterministic) path from src to dst inside the given ball
|
|
8
8
|
# where dst is at distance radius from src
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Integer, define
|
|
3
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def two_balls_repetition(g:Graph, Source, Target, max_length):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Integer, define, not_, count
|
|
3
|
-
from relationalai.
|
|
4
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
|
+
from relationalai.experimental.paths.utilities.iterators import setup_iteration
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def two_balls_upto(g:Graph, Source, Target, max_length=None):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Integer, define, max, sum, not_
|
|
3
|
-
from relationalai.
|
|
4
|
-
from relationalai.
|
|
5
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_upto import ball_upto
|
|
5
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_repetition import ball_with_repetition
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def compute_usp(g: Graph, Source, Target, max_length = None):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Model, Integer, define, max, sum, select, not_
|
|
3
|
-
from relationalai.
|
|
4
|
-
from relationalai.
|
|
5
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_upto import ball_upto
|
|
5
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_repetition import ball_with_repetition
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def compute_usp(g: Graph, Source, Target, max_length = None):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# For builder components.
|
|
2
2
|
from relationalai.semantics import Integer, define, sum, not_
|
|
3
|
-
from relationalai.
|
|
4
|
-
from relationalai.
|
|
5
|
-
from relationalai.
|
|
3
|
+
from relationalai.experimental.paths.graph import Graph
|
|
4
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_upto import ball_upto
|
|
5
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_repetition import ball_with_repetition
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def compute_usp(g: Graph, Source, Target, max_length=None):
|
relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_max_length.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select, count
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.find_paths import find_shortest_paths
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph
|
relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_multiple.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select, count
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.find_paths import find_shortest_paths
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph
|
relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_sp_single.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select, count
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.find_paths import find_shortest_paths
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph
|
relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_walks_multiple.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select, count
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.find_paths import find_walks
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph
|
relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_limit_walks_single.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select, count
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.find_paths import find_walks
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_repetition import ball_with_repetition
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# Test with grid graph
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_repetition import ball_with_repetition
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# Test with grid graph
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_upto import ball_upto
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph and multiple source and target nodes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.one_sided_ball_upto import ball_upto
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
# First test with grid graph
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.single import single_shortest_path
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
model = Model("test_single_paths", dry_run=False)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.single import single_walk
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
model = Model("test_single_paths", dry_run=False)
|
relationalai/{semantics/reasoners/graph → experimental}/paths/tests/tests_single_walks_undirected.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from relationalai.semantics import Model, Integer, define, select
|
|
2
|
-
from relationalai.
|
|
3
|
-
from relationalai.
|
|
2
|
+
from relationalai.experimental.paths.graph import Graph
|
|
3
|
+
from relationalai.experimental.paths.path_algorithms.single import single_walk
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
model = Model("test_single_paths", dry_run=False)
|