computation-graph 53__tar.gz → 56__tar.gz
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.
- {computation-graph-53 → computation_graph-56}/PKG-INFO +1 -1
- {computation-graph-53 → computation_graph-56}/computation_graph/base_types.py +5 -3
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/__init__.py +31 -33
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/duplication.py +2 -1
- {computation-graph-53 → computation_graph-56}/computation_graph/graph.py +25 -22
- {computation-graph-53 → computation_graph-56}/computation_graph/graph_test.py +54 -5
- {computation-graph-53 → computation_graph-56}/computation_graph/legacy.py +3 -0
- computation_graph-56/computation_graph/run.py +609 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/signature.py +7 -10
- {computation-graph-53 → computation_graph-56}/computation_graph.egg-info/PKG-INFO +1 -1
- {computation-graph-53 → computation_graph-56}/computation_graph.egg-info/top_level.txt +1 -0
- {computation-graph-53 → computation_graph-56}/setup.py +1 -1
- computation-graph-53/computation_graph/run.py +0 -398
- {computation-graph-53 → computation_graph-56}/LICENSE.md +0 -0
- {computation-graph-53 → computation_graph-56}/README.md +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/__init__.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/composers_test.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/condition.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/condition_test.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/debug.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/lift.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/logic.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/memory.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/composers/memory_test.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/graph_runners.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/trace/__init__.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/trace/ascii.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/trace/graphviz.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/trace/graphviz_test.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/trace/mermaid.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph/trace/trace_utils.py +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph.egg-info/SOURCES.txt +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph.egg-info/dependency_links.txt +0 -0
- {computation-graph-53 → computation_graph-56}/computation_graph.egg-info/requires.txt +0 -0
- {computation-graph-53 → computation_graph-56}/pyproject.toml +0 -0
- {computation-graph-53 → computation_graph-56}/setup.cfg +0 -0
|
@@ -96,11 +96,13 @@ class ComputationNode:
|
|
|
96
96
|
func: Callable
|
|
97
97
|
signature: NodeSignature
|
|
98
98
|
is_terminal: bool
|
|
99
|
+
computed_hash: int = dataclasses.field(init=False)
|
|
100
|
+
|
|
101
|
+
def __post_init__(self):
|
|
102
|
+
object.__setattr__(self, "computed_hash", hash(self.func))
|
|
99
103
|
|
|
100
104
|
def __hash__(self):
|
|
101
|
-
|
|
102
|
-
return hash(self.name)
|
|
103
|
-
return hash(self.func)
|
|
105
|
+
return self.computed_hash
|
|
104
106
|
|
|
105
107
|
def __repr__(self):
|
|
106
108
|
return self.name
|
|
@@ -48,14 +48,14 @@ def make_and(
|
|
|
48
48
|
|
|
49
49
|
merge_node = graph.make_computation_node(args_to_tuple)
|
|
50
50
|
|
|
51
|
-
return gamla.pipe(
|
|
51
|
+
return gamla.sync.pipe(
|
|
52
52
|
funcs,
|
|
53
|
-
gamla.map(_callable_or_graph_type_to_node_or_graph_type),
|
|
53
|
+
gamla.sync.map(_callable_or_graph_type_to_node_or_graph_type),
|
|
54
54
|
tuple,
|
|
55
|
-
gamla.juxtcat(
|
|
56
|
-
gamla.map(_get_edges_from_node_or_graph),
|
|
57
|
-
gamla.compose_left(
|
|
58
|
-
gamla.map(_infer_sink),
|
|
55
|
+
gamla.sync.juxtcat(
|
|
56
|
+
gamla.sync.map(_get_edges_from_node_or_graph),
|
|
57
|
+
gamla.sync.compose_left(
|
|
58
|
+
gamla.sync.map(_infer_sink),
|
|
59
59
|
tuple,
|
|
60
60
|
lambda nodes: (
|
|
61
61
|
(
|
|
@@ -72,7 +72,7 @@ def make_and(
|
|
|
72
72
|
),
|
|
73
73
|
),
|
|
74
74
|
),
|
|
75
|
-
gamla.star(base_types.merge_graphs),
|
|
75
|
+
gamla.sync.star(base_types.merge_graphs),
|
|
76
76
|
)
|
|
77
77
|
|
|
78
78
|
|
|
@@ -92,13 +92,13 @@ def make_or(
|
|
|
92
92
|
|
|
93
93
|
filter_node = graph.make_computation_node(filter_computation_errors)
|
|
94
94
|
|
|
95
|
-
return gamla.pipe(
|
|
95
|
+
return gamla.sync.pipe(
|
|
96
96
|
funcs,
|
|
97
|
-
gamla.map(make_optional(default_value=_ComputationError())),
|
|
97
|
+
gamla.sync.map(make_optional(default_value=_ComputationError())),
|
|
98
98
|
tuple,
|
|
99
|
-
gamla.
|
|
100
|
-
gamla.compose_left(
|
|
101
|
-
gamla.map(_infer_sink),
|
|
99
|
+
gamla.sync.pair_right(
|
|
100
|
+
gamla.sync.compose_left(
|
|
101
|
+
gamla.sync.map(_infer_sink),
|
|
102
102
|
tuple,
|
|
103
103
|
lambda sinks: (
|
|
104
104
|
(
|
|
@@ -116,7 +116,7 @@ def make_or(
|
|
|
116
116
|
)
|
|
117
117
|
),
|
|
118
118
|
gamla.concat,
|
|
119
|
-
gamla.star(base_types.merge_graphs),
|
|
119
|
+
gamla.sync.star(base_types.merge_graphs),
|
|
120
120
|
)
|
|
121
121
|
|
|
122
122
|
|
|
@@ -126,18 +126,16 @@ _destinations = gamla.compose(set, gamla.map(base_types.edge_destination))
|
|
|
126
126
|
def _infer_sink(graph_or_node: base_types.NodeOrGraph) -> base_types.ComputationNode:
|
|
127
127
|
if isinstance(graph_or_node, base_types.ComputationNode):
|
|
128
128
|
return graph_or_node
|
|
129
|
-
graph_without_future_edges =
|
|
129
|
+
graph_without_future_edges = graph.remove_future_edges(graph_or_node)
|
|
130
130
|
if graph_without_future_edges:
|
|
131
131
|
try:
|
|
132
|
-
return
|
|
133
|
-
graph_without_future_edges, graph.sink_excluding_terminals
|
|
134
|
-
)
|
|
132
|
+
return graph.sink_excluding_terminals(graph_without_future_edges)
|
|
135
133
|
except AssertionError:
|
|
136
134
|
# If we reached here we can try again without sources of future edges.
|
|
137
|
-
sources_of_future_edges = gamla.pipe(
|
|
135
|
+
sources_of_future_edges = gamla.sync.pipe(
|
|
138
136
|
graph_or_node,
|
|
139
|
-
gamla.filter(base_types.edge_is_future),
|
|
140
|
-
gamla.map(base_types.edge_source),
|
|
137
|
+
gamla.sync.filter(base_types.edge_is_future),
|
|
138
|
+
gamla.sync.map(base_types.edge_source),
|
|
141
139
|
frozenset,
|
|
142
140
|
)
|
|
143
141
|
result = (
|
|
@@ -234,30 +232,30 @@ def _infer_composition_edges(
|
|
|
234
232
|
graph.get_incoming_edges_for_node(destination)
|
|
235
233
|
)
|
|
236
234
|
return base_types.merge_graphs(
|
|
237
|
-
gamla.pipe(
|
|
235
|
+
gamla.sync.pipe(
|
|
238
236
|
destination,
|
|
239
|
-
gamla.mapcat(graph.get_edge_nodes),
|
|
237
|
+
gamla.sync.mapcat(graph.get_edge_nodes),
|
|
240
238
|
gamla.unique,
|
|
241
|
-
gamla.filter(
|
|
242
|
-
gamla.compose_left(
|
|
239
|
+
gamla.sync.filter(
|
|
240
|
+
gamla.sync.compose_left(
|
|
243
241
|
unbound_signature,
|
|
244
242
|
lambda sig: key in sig.kwargs
|
|
245
243
|
or (key is None and signature.is_unary(sig)),
|
|
246
244
|
)
|
|
247
245
|
),
|
|
248
246
|
# Do not add edges to nodes from source that are already present in destination (cycle).
|
|
249
|
-
gamla.filter(
|
|
247
|
+
gamla.sync.filter(
|
|
250
248
|
lambda node: isinstance(source, base_types.ComputationNode)
|
|
251
249
|
or node not in graph.get_all_nodes(source)
|
|
252
250
|
),
|
|
253
|
-
gamla.map(
|
|
251
|
+
gamla.sync.map(
|
|
254
252
|
lambda destination: try_connect(
|
|
255
253
|
destination=destination,
|
|
256
254
|
unbound_destination_signature=unbound_signature(destination),
|
|
257
255
|
)
|
|
258
256
|
),
|
|
259
257
|
tuple,
|
|
260
|
-
gamla.check(
|
|
258
|
+
gamla.sync.check(
|
|
261
259
|
gamla.identity,
|
|
262
260
|
AssertionError(
|
|
263
261
|
f"Cannot compose, destination signature does not contain key '{key}'"
|
|
@@ -278,13 +276,13 @@ def _make_compose_inner(
|
|
|
278
276
|
assert (
|
|
279
277
|
len(funcs) > 1
|
|
280
278
|
), f"Only {len(funcs)} function passed to compose, need at least 2, funcs={funcs}"
|
|
281
|
-
return gamla.pipe(
|
|
279
|
+
return gamla.sync.pipe(
|
|
282
280
|
funcs,
|
|
283
281
|
reversed,
|
|
284
|
-
gamla.map(_callable_or_graph_type_to_node_or_graph_type),
|
|
282
|
+
gamla.sync.map(_callable_or_graph_type_to_node_or_graph_type),
|
|
285
283
|
gamla.sliding_window(2),
|
|
286
|
-
gamla.map(gamla.star(_infer_composition_edges(priority, key, is_future))),
|
|
287
|
-
gamla.star(base_types.merge_graphs),
|
|
284
|
+
gamla.sync.map(gamla.star(_infer_composition_edges(priority, key, is_future))),
|
|
285
|
+
gamla.sync.star(base_types.merge_graphs),
|
|
288
286
|
)
|
|
289
287
|
|
|
290
288
|
|
|
@@ -389,8 +387,8 @@ def compose_dict(
|
|
|
389
387
|
return gamla.pipe(
|
|
390
388
|
d,
|
|
391
389
|
dict.items,
|
|
392
|
-
gamla.map(gamla.star(lambda key, fn: make_compose(f, fn, key=key))),
|
|
393
|
-
gamla.star(base_types.merge_graphs),
|
|
390
|
+
gamla.sync.map(gamla.star(lambda key, fn: make_compose(f, fn, key=key))),
|
|
391
|
+
gamla.sync.star(base_types.merge_graphs),
|
|
394
392
|
) or compose_left_unary(f, lambda x: x)
|
|
395
393
|
|
|
396
394
|
|
|
@@ -44,6 +44,7 @@ _duplicate_node = gamla.compose_left(
|
|
|
44
44
|
graph.make_computation_node,
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
+
duplicate_node = _duplicate_node
|
|
47
48
|
|
|
48
49
|
_node_to_duplicated_node = gamla.compose_left(
|
|
49
50
|
gamla.remove(base_types.node_is_terminal),
|
|
@@ -104,4 +105,4 @@ def safe_replace_sources(
|
|
|
104
105
|
g = graph.replace_source(source, get_node_replacement(source), g)
|
|
105
106
|
return g
|
|
106
107
|
|
|
107
|
-
return
|
|
108
|
+
return base_types.merge_graphs(*(update_edge(e) for e in cg))
|
|
@@ -6,16 +6,16 @@ from gamla.optimized import sync as opt_gamla
|
|
|
6
6
|
|
|
7
7
|
from computation_graph import base_types, signature
|
|
8
8
|
|
|
9
|
-
get_edge_nodes =
|
|
9
|
+
get_edge_nodes = opt_gamla.ternary(
|
|
10
10
|
base_types.edge_args,
|
|
11
11
|
lambda edge: edge.args + (edge.destination,),
|
|
12
12
|
lambda edge: (edge.source, edge.destination),
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
-
get_all_nodes =
|
|
15
|
+
get_all_nodes = opt_gamla.compose_left(opt_gamla.mapcat(get_edge_nodes), frozenset)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
edges_to_node_id_map =
|
|
18
|
+
edges_to_node_id_map = opt_gamla.compose_left(
|
|
19
19
|
gamla.mapcat(get_edge_nodes), gamla.unique, enumerate, gamla.map(reversed), dict
|
|
20
20
|
)
|
|
21
21
|
|
|
@@ -41,13 +41,13 @@ def make_computation_node(
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def get_leaves(edges: base_types.GraphType) -> FrozenSet[base_types.ComputationNode]:
|
|
44
|
-
return
|
|
44
|
+
return opt_gamla.pipe(
|
|
45
45
|
edges,
|
|
46
46
|
get_all_nodes,
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
opt_gamla.remove(
|
|
48
|
+
opt_gamla.pipe(
|
|
49
49
|
edges,
|
|
50
|
-
|
|
50
|
+
opt_gamla.mapcat(lambda edge: (edge.source, *edge.args)),
|
|
51
51
|
frozenset,
|
|
52
52
|
gamla.contains,
|
|
53
53
|
)
|
|
@@ -56,27 +56,29 @@ def get_leaves(edges: base_types.GraphType) -> FrozenSet[base_types.ComputationN
|
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
sink_excluding_terminals =
|
|
59
|
+
sink_excluding_terminals = opt_gamla.compose_left(
|
|
60
60
|
get_leaves,
|
|
61
|
-
|
|
61
|
+
opt_gamla.remove(base_types.node_is_terminal),
|
|
62
62
|
tuple,
|
|
63
63
|
gamla.assert_that(gamla.len_equals(1)),
|
|
64
64
|
gamla.head,
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
get_incoming_edges_for_node =
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
get_incoming_edges_for_node = opt_gamla.compose_left(
|
|
68
|
+
opt_gamla.groupby(base_types.edge_destination),
|
|
69
|
+
opt_gamla.valmap(frozenset),
|
|
70
70
|
gamla.dict_to_getter_with_default(frozenset()),
|
|
71
71
|
)
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
get_terminals =
|
|
75
|
-
get_all_nodes,
|
|
74
|
+
get_terminals = opt_gamla.compose_left(
|
|
75
|
+
get_all_nodes, opt_gamla.filter(base_types.node_is_terminal), tuple
|
|
76
76
|
)
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
remove_future_edges =
|
|
79
|
+
remove_future_edges = opt_gamla.compose(
|
|
80
|
+
tuple, opt_gamla.remove(base_types.edge_is_future)
|
|
81
|
+
)
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
def make_source():
|
|
@@ -98,7 +100,7 @@ def make_terminal(name: str, func: Callable) -> base_types.ComputationNode:
|
|
|
98
100
|
)
|
|
99
101
|
|
|
100
102
|
|
|
101
|
-
_keep_not_in_bound_kwargs =
|
|
103
|
+
_keep_not_in_bound_kwargs = opt_gamla.compose_left(
|
|
102
104
|
opt_gamla.map(base_types.edge_key),
|
|
103
105
|
gamla.filter(gamla.identity),
|
|
104
106
|
frozenset,
|
|
@@ -151,16 +153,16 @@ def _replace_source_in_edges(
|
|
|
151
153
|
traverse_forward: Callable[
|
|
152
154
|
[base_types.GraphType],
|
|
153
155
|
Callable[[base_types.CallableOrNode], Tuple[base_types.ComputationNode, ...]],
|
|
154
|
-
] =
|
|
156
|
+
] = opt_gamla.compose_left(
|
|
155
157
|
gamla.mapcat(
|
|
156
|
-
|
|
158
|
+
opt_gamla.compose_left(
|
|
157
159
|
gamla.juxt(base_types.edge_sources, base_types.edge_destination),
|
|
158
160
|
gamla.explode(0),
|
|
159
161
|
)
|
|
160
162
|
),
|
|
161
163
|
gamla.groupby_many_reduce(
|
|
162
|
-
|
|
163
|
-
lambda destinations, e:
|
|
164
|
+
opt_gamla.compose_left(gamla.head, gamla.wrap_tuple),
|
|
165
|
+
lambda destinations, e: {*(destinations if destinations else ()), e[1]},
|
|
164
166
|
),
|
|
165
167
|
gamla.dict_to_getter_with_default(()),
|
|
166
168
|
gamla.before(make_computation_node),
|
|
@@ -212,7 +214,8 @@ def transform_edges(
|
|
|
212
214
|
edge_mapper: Callable[[base_types.ComputationEdge], base_types.ComputationEdge],
|
|
213
215
|
):
|
|
214
216
|
return _operate_on_subgraph(
|
|
215
|
-
_split_by_condition(query),
|
|
217
|
+
_split_by_condition(query),
|
|
218
|
+
opt_gamla.compose_left(gamla.map(edge_mapper), tuple),
|
|
216
219
|
)
|
|
217
220
|
|
|
218
221
|
|
|
@@ -283,7 +286,7 @@ def _operate_on_subgraph(selector, transformation):
|
|
|
283
286
|
|
|
284
287
|
|
|
285
288
|
def _split_by_condition(condition):
|
|
286
|
-
return
|
|
289
|
+
return opt_gamla.compose_left(
|
|
287
290
|
gamla.bifurcate(gamla.filter(condition), gamla.remove(condition)),
|
|
288
291
|
gamla.map(tuple),
|
|
289
292
|
tuple,
|
|
@@ -63,6 +63,55 @@ def test_simple():
|
|
|
63
63
|
)
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
async def test_async_run_as_soon_as_possible(capsys):
|
|
67
|
+
# This test is to make sure that the async node runs as soon as possible.
|
|
68
|
+
# nodes in different topological layers should run concurrently if not dependent on each other.
|
|
69
|
+
async def concurrent1(x):
|
|
70
|
+
print("start concurrent1") # noqa
|
|
71
|
+
await asyncio.sleep(0.1)
|
|
72
|
+
print("end concurrent1") # noqa
|
|
73
|
+
return "concurrent1"
|
|
74
|
+
|
|
75
|
+
async def concurrent2(x):
|
|
76
|
+
print("start concurrent2") # noqa
|
|
77
|
+
await asyncio.sleep(0.1)
|
|
78
|
+
print("end concurrent2") # noqa
|
|
79
|
+
return "concurrent2"
|
|
80
|
+
|
|
81
|
+
def sink(x, y):
|
|
82
|
+
return f"x={x}, y={y}"
|
|
83
|
+
|
|
84
|
+
g = base_types.merge_graphs(
|
|
85
|
+
composers.compose_unary(concurrent1, lambda: "x"),
|
|
86
|
+
composers.compose_unary(concurrent2, lambda y: y, lambda: "y"),
|
|
87
|
+
composers.compose_left(concurrent1, sink, key="x"),
|
|
88
|
+
composers.compose_left(concurrent2, sink, key="y"),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
await graph_runners.nullary(g, sink)
|
|
92
|
+
|
|
93
|
+
# Capture the output
|
|
94
|
+
captured = capsys.readouterr()
|
|
95
|
+
|
|
96
|
+
# Assertions
|
|
97
|
+
assert "start concurrent1" in captured.out
|
|
98
|
+
assert "start concurrent2" in captured.out
|
|
99
|
+
assert "end concurrent1" in captured.out
|
|
100
|
+
assert "end concurrent2" in captured.out
|
|
101
|
+
assert captured.out.index("start concurrent1") < captured.out.index(
|
|
102
|
+
"end concurrent1"
|
|
103
|
+
)
|
|
104
|
+
assert captured.out.index("start concurrent2") < captured.out.index(
|
|
105
|
+
"end concurrent2"
|
|
106
|
+
)
|
|
107
|
+
assert captured.out.index("start concurrent1") < captured.out.index(
|
|
108
|
+
"end concurrent2"
|
|
109
|
+
)
|
|
110
|
+
assert captured.out.index("start concurrent2") < captured.out.index(
|
|
111
|
+
"end concurrent1"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
66
115
|
async def test_simple_async():
|
|
67
116
|
assert (
|
|
68
117
|
await graph_runners.unary(
|
|
@@ -376,7 +425,7 @@ def test_or_with_sink_that_raises():
|
|
|
376
425
|
|
|
377
426
|
|
|
378
427
|
def test_unambiguous_composition_using_terminal():
|
|
379
|
-
terminal = graph.make_terminal("1", lambda x: x)
|
|
428
|
+
terminal = graph.make_terminal("1", lambda x: x[0])
|
|
380
429
|
|
|
381
430
|
def source():
|
|
382
431
|
return 1
|
|
@@ -403,8 +452,8 @@ def test_unambiguous_composition_using_terminal():
|
|
|
403
452
|
|
|
404
453
|
|
|
405
454
|
def test_two_terminals():
|
|
406
|
-
terminal1 = graph.make_terminal("1",
|
|
407
|
-
terminal2 = graph.make_terminal("2",
|
|
455
|
+
terminal1 = graph.make_terminal("1", lambda x: x)
|
|
456
|
+
terminal2 = graph.make_terminal("2", lambda x: x)
|
|
408
457
|
result = graph_runners.unary_bare(
|
|
409
458
|
base_types.merge_graphs(
|
|
410
459
|
composers.compose_unary(terminal1, composers.make_compose(_node2, _node1)),
|
|
@@ -418,8 +467,8 @@ def test_two_terminals():
|
|
|
418
467
|
|
|
419
468
|
def test_two_paths_succeed():
|
|
420
469
|
source = graph.make_source()
|
|
421
|
-
terminal1 = graph.make_terminal("1",
|
|
422
|
-
terminal2 = graph.make_terminal("2",
|
|
470
|
+
terminal1 = graph.make_terminal("1", lambda x: x)
|
|
471
|
+
terminal2 = graph.make_terminal("2", lambda x: x)
|
|
423
472
|
result = graph_runners.variadic_bare(
|
|
424
473
|
base_types.merge_graphs(
|
|
425
474
|
composers.make_first(
|