Skip to content

Commit

Permalink
Remove stack-specific operations
Browse files Browse the repository at this point in the history
  • Loading branch information
bwohlberg committed Dec 8, 2023
1 parent 457b289 commit 7afe23b
Show file tree
Hide file tree
Showing 4 changed files with 2 additions and 98 deletions.
20 changes: 1 addition & 19 deletions scico/linop/_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@

from __future__ import annotations

import operator
from functools import partial
from typing import Optional, Sequence, Union

import scico.numpy as snp
from scico.numpy import Array, BlockArray
from scico.operator._stack import DiagonalStack as DStack
from scico.operator._stack import VerticalStack as VStack

from ._linop import LinearOperator, _wrap_add_sub
from ._linop import LinearOperator


class VerticalStack(VStack, LinearOperator):
Expand Down Expand Up @@ -70,22 +68,6 @@ def __init__(
def _adj(self, y: Union[Array, BlockArray]) -> Array: # type: ignore
return sum([op.adj(y_block) for y_block, op in zip(y, self.ops)]) # type: ignore

@partial(_wrap_add_sub, op=operator.add)
def __add__(self, other):
# add another VerticalStack of the same shape
return VerticalStack(
[op1 + op2 for op1, op2 in zip(self.ops, other.ops)],
collapse_output=self.collapse_output,
)

@partial(_wrap_add_sub, op=operator.sub)
def __sub__(self, other):
# subtract another VerticalStack of the same shape
return VerticalStack(
[op1 - op2 for op1, op2 in zip(self.ops, other.ops)],
collapse_output=self.collapse_output,
)


class DiagonalStack(DStack, LinearOperator):
r"""A diagonal stack of linear operators.
Expand Down
50 changes: 1 addition & 49 deletions scico/operator/_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from scico.numpy.util import is_nested
from scico.typing import BlockShape, Shape

from ._operator import Operator, _wrap_mul_div_scalar
from ._operator import Operator


def collapse_shapes(
Expand Down Expand Up @@ -144,54 +144,6 @@ def _eval(self, x: Array) -> Union[Array, BlockArray]:
return snp.stack([op(x) for op in self.ops])
return BlockArray([op(x) for op in self.ops])

def scale_ops(self, scalars: Array):
"""Scale component operators.
Return a copy of `self` with each operator scaled by the
corresponding entry in `scalars`.
Args:
scalars: List or array of scalars to use.
"""
if len(scalars) != len(self.ops):
raise ValueError("Expected scalars to be the same length as self.ops.")

return self.__class__(
[a * op for a, op in zip(scalars, self.ops)], collapse_output=self.collapse_output
)

def __add__(self, other):
# add another VerticalStack of the same shape
return self.__class__(
[op1 + op2 for op1, op2 in zip(self.ops, other.ops)],
collapse_output=self.collapse_output,
)

def __sub__(self, other):
# subtract another VerticalStack of the same shape
return self.__class__(
[op1 - op2 for op1, op2 in zip(self.ops, other.ops)],
collapse_output=self.collapse_output,
)

@_wrap_mul_div_scalar
def __mul__(self, scalar):
return self.__class__(
[scalar * op for op in self.ops], collapse_output=self.collapse_output
)

@_wrap_mul_div_scalar
def __rmul__(self, scalar):
return self.__class__(
[scalar * op for op in self.ops], collapse_output=self.collapse_output
)

@_wrap_mul_div_scalar
def __truediv__(self, scalar):
return self.__class__(
[op / scalar for op in self.ops], collapse_output=self.collapse_output
)


class DiagonalStack(Operator):
r"""A diagonal stack of operators.
Expand Down
15 changes: 0 additions & 15 deletions scico/test/linop/test_linop_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,6 @@ def test_algebra(self, collapse_output, jit):
np.testing.assert_allclose((S @ x)[0], (H @ x + G @ x)[0])
np.testing.assert_allclose((S @ x)[1], (H @ x + G @ x)[1])

# result of adding two conformable stacks should be a stack
assert isinstance(S, VerticalStack)
assert isinstance(H - G, VerticalStack)

# scalar multiplication
assert isinstance(1.0 * H, VerticalStack)

# op scaling
scalars = [2.0, 3.0]
y1 = S @ x
S2 = S.scale_ops(scalars)
y2 = S2 @ x

np.testing.assert_allclose(scalars[0] * y1[0], y2[0])


class TestBlockDiagonalLinearOperator:
def test_construct(self):
Expand Down
15 changes: 0 additions & 15 deletions scico/test/operator/test_op_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,21 +86,6 @@ def test_algebra(self, collapse_output, jit):
np.testing.assert_allclose((S(x))[0], (H(x) + G(x))[0])
np.testing.assert_allclose((S(x))[1], (H(x) + G(x))[1])

# result of adding two conformable stacks should be a stack
assert isinstance(S, VerticalStack)
assert isinstance(H - G, VerticalStack)

# scalar multiplication
assert isinstance(1.0 * H, VerticalStack)

# op scaling
scalars = [2.0, 3.0]
y1 = S(x)
S2 = S.scale_ops(scalars)
y2 = S2(x)

np.testing.assert_allclose(scalars[0] * y1[0], y2[0])


class TestBlockDiagonalOperator:
def test_construct(self):
Expand Down

0 comments on commit 7afe23b

Please sign in to comment.