Skip to content
Snippets Groups Projects
Commit 12d27738 authored by Oscar Gustafsson's avatar Oscar Gustafsson :bicyclist:
Browse files

Add more WDF adaptors

parent ba14ff12
No related branches found
No related tags found
1 merge request!428Draft: Add more WDF adaptors
......@@ -12,3 +12,4 @@ from b_asic.signal import *
from b_asic.signal_flow_graph import *
from b_asic.simulation import *
from b_asic.special_operations import *
from b_asic.wdf_operations import *
......@@ -912,73 +912,6 @@ class MAD(AbstractOperation):
p._index = i
class SymmetricTwoportAdaptor(AbstractOperation):
r"""
Wave digital filter symmetric twoport-adaptor operation.
.. math::
\begin{eqnarray}
y_0 & = & x_1 + \text{value}\times\left(x_1 - x_0\right)\\
y_1 & = & x_0 + \text{value}\times\left(x_1 - x_0\right)
\end{eqnarray}
"""
is_linear = True
is_swappable = True
def __init__(
self,
value: Num = 0,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
):
"""Construct a SymmetricTwoportAdaptor operation."""
super().__init__(
input_count=2,
output_count=2,
name=Name(name),
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
self.value = value
@classmethod
def type_name(cls) -> TypeName:
return TypeName("sym2p")
def evaluate(self, a, b):
tmp = self.value * (b - a)
return b + tmp, a + tmp
@property
def value(self) -> Num:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Num) -> None:
"""Set the constant value of this operation."""
if -1 <= value <= 1:
self.set_param("value", value)
else:
raise ValueError('value must be between -1 and 1 (inclusive)')
def swap_io(self) -> None:
# Swap inputs and outputs and change sign of coefficient
self._input_ports.reverse()
for i, p in enumerate(self._input_ports):
p._index = i
self._output_ports.reverse()
for i, p in enumerate(self._output_ports):
p._index = i
self.set_param("value", -self.value)
class Reciprocal(AbstractOperation):
r"""
Reciprocal operation.
......
......@@ -668,13 +668,12 @@ class AbstractOperation(Operation, AbstractGraphComponent):
f" {self.input_count}, got {len(input_values)})"
)
values = self.evaluate(
*(
self.quantize_inputs(input_values, bits_override)
if quantize
else input_values
)
input_values = (
self.quantize_inputs(input_values, bits_override)
if quantize
else input_values
)
values = self.evaluate(*input_values)
if isinstance(values, collections.abc.Sequence):
if len(values) != self.output_count:
raise RuntimeError(
......
......@@ -7,15 +7,11 @@ from typing import Dict, Optional, Sequence, Union
import numpy as np
from b_asic.core_operations import (
Addition,
ConstantMultiplication,
Name,
SymmetricTwoportAdaptor,
)
from b_asic.core_operations import Addition, ConstantMultiplication, Name
from b_asic.signal import Signal
from b_asic.signal_flow_graph import SFG
from b_asic.special_operations import Delay, Input, Output
from b_asic.wdf_operations import SymmetricTwoportAdaptor
def wdf_allpass(
......
"""
B-ASIC Core Operations Module.
Contains wave digital filter adaptors.
"""
from typing import Dict, Iterable, Optional, Tuple
from b_asic.graph_component import Name, TypeName
from b_asic.operation import AbstractOperation
from b_asic.port import SignalSourceProvider
from b_asic.types import Num
class SymmetricTwoportAdaptor(AbstractOperation):
r"""
Wave digital filter symmetric twoport-adaptor operation.
.. math::
\begin{eqnarray}
y_0 & = & x_1 + \text{value}\times\left(x_1 - x_0\right)\\
y_1 & = & x_0 + \text{value}\times\left(x_1 - x_0\right)
\end{eqnarray}
"""
is_linear = True
is_swappable = True
def __init__(
self,
value: Num = 0,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
):
"""Construct a SymmetricTwoportAdaptor operation."""
super().__init__(
input_count=2,
output_count=2,
name=Name(name),
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
self.value = value
@classmethod
def type_name(cls) -> TypeName:
return TypeName("sym2p")
def evaluate(self, a, b):
tmp = self.value * (b - a)
return b + tmp, a + tmp
@property
def value(self) -> Num:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Num) -> None:
"""Set the constant value of this operation."""
if -1 <= value <= 1:
self.set_param("value", value)
else:
raise ValueError('value must be between -1 and 1 (inclusive)')
def swap_io(self) -> None:
# Swap inputs and outputs and change sign of coefficient
self._input_ports.reverse()
for i, p in enumerate(self._input_ports):
p._index = i
self._output_ports.reverse()
for i, p in enumerate(self._output_ports):
p._index = i
self.set_param("value", -self.value)
class SeriesTwoportAdaptor(AbstractOperation):
r"""
Wave digital filter series twoport-adaptor operation.
.. math::
\begin{eqnarray}
y_0 & = & x_0 - \text{value}\times\left(x_0 + x_1\right)\\
y_1 & = & x_1 - (2-\text{value})\times\left(x_0 + x_1\right)\\
& = & -2x_0 - x_1 + \text{value}\times\left(x_0 + x_1\right)
\end{eqnarray}
Port 1 is the dependent port.
"""
is_linear = True
is_swappable = True
def __init__(
self,
value: Num = 0,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
):
"""Construct a SeriesTwoportAdaptor operation."""
super().__init__(
input_count=2,
output_count=2,
name=Name(name),
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
self.value = value
@classmethod
def type_name(cls) -> TypeName:
return TypeName("ser2p")
def evaluate(self, a, b):
s = a + b
val = self.value
t = val * a
y0 = a - t
y1 = -(s + y0)
return y0, y1
@property
def value(self) -> Num:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Num) -> None:
"""Set the constant value of this operation."""
if 0 <= value <= 2:
self.set_param("value", value)
else:
raise ValueError('value must be between 0 and 2 (inclusive)')
def swap_io(self) -> None:
# Swap inputs and outputs and, hence, which port is dependent
self._input_ports.reverse()
for i, p in enumerate(self._input_ports):
p._index = i
self._output_ports.reverse()
for i, p in enumerate(self._output_ports):
p._index = i
self.set_param("value", 2 - self.value)
class ParallelTwoportAdaptor(AbstractOperation):
r"""
Wave digital filter parallel twoport-adaptor operation.
.. math::
\begin{eqnarray}
y_0 & = & - x_0 + \text{value}\times x_0 + (2 - \text{value}) \times x_1\\
& = & 2x_1 - x_0 + \text{value}\times \left(x_0 - x_1\right)
y_1 & = & - x_1 + \text{value}\times x_0 + (2 - \text{value}) \times x_1\\
& = & x_1 + \text{value}\times\left(x_0 - x_1\right)
\end{eqnarray}
Port 1 is the dependent port.
"""
is_linear = True
is_swappable = True
def __init__(
self,
value: Num = 0,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
):
"""Construct a ParallelTwoportAdaptor operation."""
super().__init__(
input_count=2,
output_count=2,
name=Name(name),
input_sources=[src0, src1],
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
self.value = value
@classmethod
def type_name(cls) -> TypeName:
return TypeName("par2p")
def evaluate(self, a, b):
s = b - a
val = self.value
t = val * s
y1 = b - t
y0 = y1 + s
return y0, y1
@property
def value(self) -> Num:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Num) -> None:
"""Set the constant value of this operation."""
if 0 <= value <= 2:
self.set_param("value", value)
else:
raise ValueError('value must be between 0 and 2 (inclusive)')
def swap_io(self) -> None:
# Swap inputs and outputs and, hence, which port is dependent
self._input_ports.reverse()
for i, p in enumerate(self._input_ports):
p._index = i
self._output_ports.reverse()
for i, p in enumerate(self._output_ports):
p._index = i
self.set_param("value", 2 - self.value)
class SeriesThreeportAdaptor(AbstractOperation):
r"""
Wave digital filter series threeport-adaptor operation.
.. math::
\begin{eqnarray}
y_0 & = & x_0 - \text{value}_0\times\left(x_0 + x_1 + x_2\right)\\
y_1 & = & x_1 - \text{value}_1\times\left(x_0 + x_1 + x_2\right)\\
y_2 & = & x_2 - \left(2 - \text{value}_0 - \text{value}_1\right)\times\left(x_0
+ x_1 + x_2\right)
\end{eqnarray}
Port 2 is the dependent port.
"""
is_linear = True
is_swappable = True
def __init__(
self,
value: Tuple[Num, Num] = (0, 0),
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
src2: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
):
"""Construct a SeriesThreeportAdaptor operation."""
super().__init__(
input_count=3,
output_count=3,
name=Name(name),
input_sources=[src0, src1, src2],
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
self.value = value
@classmethod
def type_name(cls) -> TypeName:
return TypeName("ser3p")
def evaluate(self, a, b, c):
s = a + b + c
val0, val1 = self.value
y0 = a - val0 * s
y1 = b - val1 * s
y2 = -(y0 + y1 + s)
return y0, y1, y2
@property
def value(self) -> Tuple[Num, Num]:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Tuple[Num, Num]) -> None:
"""Set the constant value of this operation."""
if not all(0 <= v <= 2 for v in value):
raise ValueError('each value must be between 0 and 2 (inclusive)')
if 0 <= sum(value) <= 2:
self.set_param("value", value)
else:
raise ValueError('sum of values must be between 0 and 2 (inclusive)')
class ReflectionFreeSeriesThreeportAdaptor(AbstractOperation):
r"""
Wave digital filter reflection free series threeport-adaptor operation.
.. math::
\begin{eqnarray}
y_0 & = & x_0 - \text{value}\times\left(x_0 + x_1 + x_2\right)\\
y_1 & = & -x_0 - x_2\\
y_2 & = & x_2 - \left(1 - \text{value}\right)\times\left(x_0
+ x_1 + x_2\right) \\
& = & -x_0 - x_1 + \text{value}\times\left(x_0
+ x_1 + x_2\right)
\end{eqnarray}
Port 1 is the reflection-free port and port 2 is the dependent port.
"""
is_linear = True
is_swappable = True
def __init__(
self,
value: Num = 0,
src0: Optional[SignalSourceProvider] = None,
src1: Optional[SignalSourceProvider] = None,
src2: Optional[SignalSourceProvider] = None,
name: Name = Name(""),
latency: Optional[int] = None,
latency_offsets: Optional[Dict[str, int]] = None,
execution_time: Optional[int] = None,
):
"""Construct a ReflectionFreeSeriesThreeportAdaptor operation."""
super().__init__(
input_count=3,
output_count=3,
name=Name(name),
input_sources=[src0, src1, src2],
latency=latency,
latency_offsets=latency_offsets,
execution_time=execution_time,
)
self.value = value
@classmethod
def type_name(cls) -> TypeName:
return TypeName("rfs3p")
def evaluate(self, a, b, c):
s = a + c
y1 = -s
y0 = a - self.value * (b + s)
y2 = -(y0 + b)
return y0, y1, y2
@property
def value(self) -> Num:
"""Get the constant value of this operation."""
return self.param("value")
@value.setter
def value(self, value: Num) -> None:
"""Set the constant value of this operation."""
if 0 <= value <= 1:
self.set_param("value", value)
else:
raise ValueError('value must be between 0 and 1 (inclusive)')
def inputs_required_for_output(self, output_index: int) -> Iterable[int]:
"""
Get the input indices of all inputs in this operation whose values are
required in order to evaluate the output at the given output index.
"""
return {0: (0, 1, 2), 1: (0, 2), 2: (0, 1, 2)}
*************************
``b_asic.wdf_operations``
*************************
.. inheritance-diagram:: b_asic.wdf_operations
:parts: 1
:top-classes: b_asic.graph_component.GraphComponent, b_asic.port.SignalSourceProvider
.. automodule:: b_asic.wdf_operations
:members:
:undoc-members:
:show-inheritance:
......@@ -7,10 +7,10 @@ LWDF first-order allpass section
This has different latency offsets for the different inputs/outputs.
"""
from b_asic.core_operations import SymmetricTwoportAdaptor
from b_asic.schedule import Schedule
from b_asic.signal_flow_graph import SFG
from b_asic.special_operations import Delay, Input, Output
from b_asic.wdf_operations import SymmetricTwoportAdaptor
in0 = Input()
......
......@@ -8,12 +8,13 @@ Small bireciprocal lattice wave digital filter.
import numpy as np
from mplsignal.freq_plots import freqz_fir
from b_asic.core_operations import Addition, SymmetricTwoportAdaptor
from b_asic.core_operations import Addition
from b_asic.schedule import Schedule
from b_asic.signal_flow_graph import SFG
from b_asic.signal_generator import Impulse
from b_asic.simulation import Simulation
from b_asic.special_operations import Delay, Input, Output
from b_asic.wdf_operations import SymmetricTwoportAdaptor
in0 = Input("x")
D0 = Delay(in0)
......
......@@ -22,7 +22,6 @@ from b_asic import (
Sink,
SquareRoot,
Subtraction,
SymmetricTwoportAdaptor,
)
......@@ -349,39 +348,6 @@ class TestButterfly:
assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == -1 + 3j
class TestSymmetricTwoportAdaptor:
"""Tests for SymmetricTwoportAdaptor class."""
def test_symmetrictwoportadaptor_positive(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2, 3]) == 3.5
assert test_operation.evaluate_output(1, [2, 3]) == 2.5
assert test_operation.value == 0.5
def test_symmetrictwoportadaptor_negative(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [-2, -3]) == -3.5
assert test_operation.evaluate_output(1, [-2, -3]) == -2.5
def test_symmetrictwoportadaptor_complex(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2 + 1j, 3 - 2j]) == 3.5 - 3.5j
assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == 2.5 - 0.5j
def test_symmetrictwoportadaptor_swap_io(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.value == 0.5
test_operation.swap_io()
assert test_operation.value == -0.5
def test_symmetrictwoportadaptor_error(self):
with pytest.raises(ValueError, match="value must be between -1 and 1"):
_ = SymmetricTwoportAdaptor(-2)
test_operation = SymmetricTwoportAdaptor(0)
with pytest.raises(ValueError, match="value must be between -1 and 1"):
test_operation.value = 2
class TestReciprocal:
"""Tests for Absolute class."""
......
......@@ -18,7 +18,6 @@ from b_asic.core_operations import (
Multiplication,
SquareRoot,
Subtraction,
SymmetricTwoportAdaptor,
)
from b_asic.operation import ResultKey
from b_asic.save_load_structure import python_to_sfg, sfg_to_python
......@@ -26,6 +25,7 @@ from b_asic.sfg_generators import wdf_allpass
from b_asic.signal_flow_graph import SFG, GraphID
from b_asic.simulation import Simulation
from b_asic.special_operations import Delay
from b_asic.wdf_operations import SymmetricTwoportAdaptor
class TestInit:
......
import numpy as np
import pytest
from b_asic.core_operations import (
Addition,
ConstantMultiplication,
SymmetricTwoportAdaptor,
)
from b_asic.core_operations import Addition, ConstantMultiplication
from b_asic.sfg_generators import (
direct_form_fir,
transposed_direct_form_fir,
......@@ -14,6 +10,7 @@ from b_asic.sfg_generators import (
from b_asic.signal_generator import Impulse
from b_asic.simulation import Simulation
from b_asic.special_operations import Delay
from b_asic.wdf_operations import SymmetricTwoportAdaptor
def test_wdf_allpass():
......
"""B-ASIC test suite for the core operations."""
import pytest
from b_asic.wdf_operations import (
ParallelTwoportAdaptor,
ReflectionFreeSeriesThreeportAdaptor,
SeriesThreeportAdaptor,
SeriesTwoportAdaptor,
SymmetricTwoportAdaptor,
)
class TestSymmetricTwoportAdaptor:
"""Tests for SymmetricTwoportAdaptor class."""
def test_symmetrictwoportadaptor_positive(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2, 3]) == 3.5
assert test_operation.evaluate_output(1, [2, 3]) == 2.5
assert test_operation.value == 0.5
def test_symmetrictwoportadaptor_negative(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [-2, -3]) == -3.5
assert test_operation.evaluate_output(1, [-2, -3]) == -2.5
def test_symmetrictwoportadaptor_complex(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2 + 1j, 3 - 2j]) == 3.5 - 3.5j
assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == 2.5 - 0.5j
def test_symmetrictwoportadaptor_swap_io(self):
test_operation = SymmetricTwoportAdaptor(0.5)
assert test_operation.value == 0.5
test_operation.swap_io()
assert test_operation.value == -0.5
def test_symmetrictwoportadaptor_error(self):
with pytest.raises(ValueError, match="value must be between -1 and 1"):
_ = SymmetricTwoportAdaptor(-2)
test_operation = SymmetricTwoportAdaptor(0)
with pytest.raises(ValueError, match="value must be between -1 and 1"):
test_operation.value = 2
class TestSeriesTwoportAdaptor:
"""Tests for SeriesTwoportAdaptor class."""
def test_seriestwoportadaptor_positive(self):
test_operation = SeriesTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2, 3]) == 1.0
assert test_operation.evaluate_output(1, [2, 3]) == -6.0
assert test_operation.value == 0.5
def test_seriestwoportadaptor_negative(self):
test_operation = SeriesTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [-2, -3]) == -1.0
assert test_operation.evaluate_output(1, [-2, -3]) == 6.0
def test_seriestwoportadaptor_complex(self):
test_operation = SeriesTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2 + 1j, 3 - 2j]) == 1 + 0.5j
assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == -6 + 0.5j
def test_seriestwoportadaptor_swap_io(self):
test_operation = SeriesTwoportAdaptor(0.5)
assert test_operation.value == 0.5
test_operation.swap_io()
assert test_operation.value == 1.5
def test_seriestwoportadaptor_error(self):
with pytest.raises(ValueError, match="value must be between 0 and 2"):
_ = SeriesTwoportAdaptor(-1)
test_operation = SeriesTwoportAdaptor(0)
with pytest.raises(ValueError, match="value must be between 0 and 2"):
test_operation.value = 3
class TestParallelTwoportAdaptor:
"""Tests for ParallelTwoportAdaptor class."""
def test_seriestwoportadaptor_positive(self):
test_operation = ParallelTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2, 3]) == 3.5
assert test_operation.evaluate_output(1, [2, 3]) == 2.5
assert test_operation.value == 0.5
def test_seriestwoportadaptor_negative(self):
test_operation = ParallelTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [-2, -3]) == -3.5
assert test_operation.evaluate_output(1, [-2, -3]) == -2.5
def test_seriestwoportadaptor_complex(self):
test_operation = ParallelTwoportAdaptor(0.5)
assert test_operation.evaluate_output(0, [2 + 1j, 3 - 2j]) == 3.5 - 3.5j
assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == 2.5 - 0.5j
def test_seriestwoportadaptor_swap_io(self):
test_operation = ParallelTwoportAdaptor(0.5)
assert test_operation.value == 0.5
test_operation.swap_io()
assert test_operation.value == 1.5
def test_seriestwoportadaptor_error(self):
with pytest.raises(ValueError, match="value must be between 0 and 2"):
_ = ParallelTwoportAdaptor(-1)
test_operation = ParallelTwoportAdaptor(0)
with pytest.raises(ValueError, match="value must be between 0 and 2"):
test_operation.value = 3
class TestSeriesThreeportAdaptor:
"""Tests for SeriesThreeportAdaptor class."""
def test_seriesthreeportadaptor_positive(self):
test_operation = SeriesThreeportAdaptor((0.5, 1.25))
assert test_operation.evaluate_output(0, [2, 3, 4]) == -2.5
assert test_operation.evaluate_output(1, [2, 3, 4]) == -8.25
assert test_operation.evaluate_output(2, [2, 3, 4]) == 1.75
assert test_operation.value == (0.5, 1.25)
def test_seriesthreeportadaptor_negative(self):
test_operation = SeriesThreeportAdaptor((0.5, 1.25))
assert test_operation.evaluate_output(0, [-2, -3, -4]) == 2.5
assert test_operation.evaluate_output(1, [-2, -3, -4]) == 8.25
assert test_operation.evaluate_output(2, [-2, -3, -4]) == -1.75
def test_seriesthreeportadaptor_complex(self):
test_operation = SeriesThreeportAdaptor((0.5, 1.25))
assert test_operation.evaluate_output(0, [2 + 1j, 3 - 2j, 4 + 3j]) == -2.5 + 0j
assert (
test_operation.evaluate_output(1, [2 + 1j, 3 - 2j, 4 + 3j]) == -8.25 - 4.5j
)
assert (
test_operation.evaluate_output(2, [2 + 1j, 3 - 2j, 4 + 3j]) == 1.75 + 2.5j
)
def test_seriesthreeportadaptor_error(self):
with pytest.raises(ValueError, match="each value must be between 0 and 2"):
_ = SeriesThreeportAdaptor((-1, 3))
with pytest.raises(ValueError, match="sum of values must be between 0 and 2"):
_ = SeriesThreeportAdaptor((1.5, 1.5))
test_operation = SeriesThreeportAdaptor((0, 0.5))
with pytest.raises(ValueError, match="each value must be between 0 and 2"):
test_operation.value = (-0.5, 1)
with pytest.raises(ValueError, match="sum of values must be between 0 and 2"):
test_operation.value = (0.5, 2)
class TestReflectionFreeSeriesThreeportAdaptor:
"""Tests for ReflectionFreeSeriesThreeportAdaptor class."""
def test_reflectionfreeseriesthreeportadaptor_positive(self):
test_operation = ReflectionFreeSeriesThreeportAdaptor(0.25)
assert test_operation.evaluate_output(0, [2, 3, 4]) == -0.25
assert test_operation.evaluate_output(1, [2, 3, 4]) == -6
assert test_operation.evaluate_output(2, [2, 3, 4]) == -2.75
assert test_operation.value == 0.25
def test_reflectionfreeseriesthreeportadaptor_negative(self):
test_operation = ReflectionFreeSeriesThreeportAdaptor(0.25)
assert test_operation.evaluate_output(0, [-2, -3, -4]) == 0.25
assert test_operation.evaluate_output(1, [-2, -3, -4]) == 6
assert test_operation.evaluate_output(2, [-2, -3, -4]) == 2.75
def test_reflectionfreeseriesthreeportadaptor_complex(self):
test_operation = ReflectionFreeSeriesThreeportAdaptor(0.25)
assert (
test_operation.evaluate_output(0, [2 + 1j, 3 - 2j, 4 + 3j]) == -0.25 + 0.5j
)
assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j, 4 + 3j]) == -6 - 4j
assert (
test_operation.evaluate_output(2, [2 + 1j, 3 - 2j, 4 + 3j]) == -2.75 + 1.5j
)
def test_reflectionfreeseriesthreeportadaptor_error(self):
with pytest.raises(ValueError, match="value must be between 0 and 1"):
_ = ReflectionFreeSeriesThreeportAdaptor(-1)
test_operation = ReflectionFreeSeriesThreeportAdaptor(0.5)
with pytest.raises(ValueError, match="value must be between 0 and 1"):
test_operation.value = 4
def test_reflectionfree_equals_normal(self):
test_operation1 = SeriesThreeportAdaptor((0.25, 1))
test_operation2 = ReflectionFreeSeriesThreeportAdaptor(0.25)
for port in range(3):
assert test_operation1.evaluate_output(
port, [2, 3, 4]
) == test_operation2.evaluate_output(port, [2, 3, 4])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment