Skip to content

Commit 8593a74

Browse files
committed
Move einsum to the top of the file einsum.py
1 parent 81dd29e commit 8593a74

1 file changed

Lines changed: 66 additions & 66 deletions

File tree

  • src/torchjd/sparse/_aten_function_overrides

src/torchjd/sparse/_aten_function_overrides/einsum.py

Lines changed: 66 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,72 +11,6 @@
1111
)
1212

1313

14-
def prepare_for_elementwise_op(
15-
t1: Tensor | int | float, t2: Tensor | int | float
16-
) -> tuple[StructuredSparseTensor, StructuredSparseTensor]:
17-
"""
18-
Prepares two SSTs of the same shape from two args, one of those being a SST, and the other being
19-
a SST, Tensor, int or float.
20-
"""
21-
22-
assert isinstance(t1, StructuredSparseTensor) or isinstance(t2, StructuredSparseTensor)
23-
24-
if isinstance(t1, int) or isinstance(t1, float):
25-
t1_ = tensor(t1, device=t2.device)
26-
else:
27-
t1_ = t1
28-
29-
if isinstance(t2, int) or isinstance(t2, float):
30-
t2_ = tensor(t2, device=t1.device)
31-
else:
32-
t2_ = t2
33-
34-
t1_, t2_ = aten.broadcast_tensors.default([t1_, t2_])
35-
t1_ = to_structured_sparse_tensor(t1_)
36-
t2_ = to_structured_sparse_tensor(t2_)
37-
38-
return t1_, t2_
39-
40-
41-
@impl(aten.mul.Tensor)
42-
def mul_Tensor(t1: Tensor | int | float, t2: Tensor | int | float) -> Tensor:
43-
# Element-wise multiplication with broadcasting
44-
t1_, t2_ = prepare_for_elementwise_op(t1, t2)
45-
all_dims = list(range(t1_.ndim))
46-
return einsum((t1_, all_dims), (t2_, all_dims), output=all_dims)
47-
48-
49-
@impl(aten.div.Tensor)
50-
def div_Tensor(t1: Tensor | int | float, t2: Tensor | int | float) -> Tensor:
51-
t1_, t2_ = prepare_for_elementwise_op(t1, t2)
52-
t2_ = StructuredSparseTensor(1.0 / t2_.physical, t2_.v_to_ps)
53-
all_dims = list(range(t1_.ndim))
54-
return einsum((t1_, all_dims), (t2_, all_dims), output=all_dims)
55-
56-
57-
@impl(aten.mul.Scalar)
58-
def mul_Scalar(t: StructuredSparseTensor, scalar) -> StructuredSparseTensor:
59-
# TODO: maybe it could be that scalar is a scalar SST and t is a normal tensor. Need to check
60-
# that
61-
62-
assert isinstance(t, StructuredSparseTensor)
63-
new_physical = aten.mul.Scalar(t.physical, scalar)
64-
return StructuredSparseTensor(new_physical, t.v_to_ps)
65-
66-
67-
@impl(aten.add.Tensor)
68-
def add_Tensor(
69-
t1: Tensor | int | float, t2: Tensor | int | float, alpha: Tensor | float = 1.0
70-
) -> StructuredSparseTensor:
71-
t1_, t2_ = prepare_for_elementwise_op(t1, t2)
72-
73-
if t1_.v_to_ps == t2_.v_to_ps:
74-
new_physical = t1_.physical + t2_.physical * alpha
75-
return StructuredSparseTensor(new_physical, t1_.v_to_ps)
76-
else:
77-
raise NotImplementedError()
78-
79-
8014
def einsum(*args: tuple[StructuredSparseTensor, list[int]], output: list[int]) -> Tensor:
8115

8216
# First part of the algorithm, determine how to cluster physical indices as well as the common
@@ -193,6 +127,72 @@ def unique_int(pair: tuple[int, int]) -> int:
193127
return to_most_efficient_tensor(physical, v_to_ps)
194128

195129

130+
def prepare_for_elementwise_op(
131+
t1: Tensor | int | float, t2: Tensor | int | float
132+
) -> tuple[StructuredSparseTensor, StructuredSparseTensor]:
133+
"""
134+
Prepares two SSTs of the same shape from two args, one of those being a SST, and the other being
135+
a SST, Tensor, int or float.
136+
"""
137+
138+
assert isinstance(t1, StructuredSparseTensor) or isinstance(t2, StructuredSparseTensor)
139+
140+
if isinstance(t1, int) or isinstance(t1, float):
141+
t1_ = tensor(t1, device=t2.device)
142+
else:
143+
t1_ = t1
144+
145+
if isinstance(t2, int) or isinstance(t2, float):
146+
t2_ = tensor(t2, device=t1.device)
147+
else:
148+
t2_ = t2
149+
150+
t1_, t2_ = aten.broadcast_tensors.default([t1_, t2_])
151+
t1_ = to_structured_sparse_tensor(t1_)
152+
t2_ = to_structured_sparse_tensor(t2_)
153+
154+
return t1_, t2_
155+
156+
157+
@impl(aten.mul.Tensor)
158+
def mul_Tensor(t1: Tensor | int | float, t2: Tensor | int | float) -> Tensor:
159+
# Element-wise multiplication with broadcasting
160+
t1_, t2_ = prepare_for_elementwise_op(t1, t2)
161+
all_dims = list(range(t1_.ndim))
162+
return einsum((t1_, all_dims), (t2_, all_dims), output=all_dims)
163+
164+
165+
@impl(aten.div.Tensor)
166+
def div_Tensor(t1: Tensor | int | float, t2: Tensor | int | float) -> Tensor:
167+
t1_, t2_ = prepare_for_elementwise_op(t1, t2)
168+
t2_ = StructuredSparseTensor(1.0 / t2_.physical, t2_.v_to_ps)
169+
all_dims = list(range(t1_.ndim))
170+
return einsum((t1_, all_dims), (t2_, all_dims), output=all_dims)
171+
172+
173+
@impl(aten.mul.Scalar)
174+
def mul_Scalar(t: StructuredSparseTensor, scalar) -> StructuredSparseTensor:
175+
# TODO: maybe it could be that scalar is a scalar SST and t is a normal tensor. Need to check
176+
# that
177+
178+
assert isinstance(t, StructuredSparseTensor)
179+
new_physical = aten.mul.Scalar(t.physical, scalar)
180+
return StructuredSparseTensor(new_physical, t.v_to_ps)
181+
182+
183+
@impl(aten.add.Tensor)
184+
def add_Tensor(
185+
t1: Tensor | int | float, t2: Tensor | int | float, alpha: Tensor | float = 1.0
186+
) -> StructuredSparseTensor:
187+
t1_, t2_ = prepare_for_elementwise_op(t1, t2)
188+
189+
if t1_.v_to_ps == t2_.v_to_ps:
190+
new_physical = t1_.physical + t2_.physical * alpha
191+
return StructuredSparseTensor(new_physical, t1_.v_to_ps)
192+
else:
193+
raise NotImplementedError()
194+
195+
196196
@impl(aten.bmm.default)
197197
def bmm_default(mat1: Tensor, mat2: Tensor) -> Tensor:
198198
assert isinstance(mat1, StructuredSparseTensor) or isinstance(mat2, StructuredSparseTensor)

0 commit comments

Comments
 (0)