Skip to content
Snippets Groups Projects

Add matrix inversion sfg generator

Merged Simon Bjurek requested to merge add-matrix-inversion-sfg-generator into master
2 unresolved threads
1 file
+ 120
0
Compare changes
  • Side-by-side
  • Inline
+ 120
0
@@ -3,9 +3,11 @@ import pytest
@@ -3,9 +3,11 @@ import pytest
from scipy import signal
from scipy import signal
from b_asic.core_operations import (
from b_asic.core_operations import (
 
MADS,
Addition,
Addition,
Butterfly,
Butterfly,
ConstantMultiplication,
ConstantMultiplication,
 
Reciprocal,
SymmetricTwoportAdaptor,
SymmetricTwoportAdaptor,
)
)
from b_asic.sfg_generators import (
from b_asic.sfg_generators import (
@@ -644,6 +646,12 @@ class TestLdltMatrixInverse:
@@ -644,6 +646,12 @@ class TestLdltMatrixInverse:
def test_1x1(self):
def test_1x1(self):
sfg = ldlt_matrix_inverse(N=1, is_complex=False)
sfg = ldlt_matrix_inverse(N=1, is_complex=False)
 
assert len(sfg.inputs) == 1
 
assert len(sfg.outputs) == 1
 
 
assert len(sfg.find_by_type_name(MADS.type_name())) == 0
 
assert len(sfg.find_by_type_name(Reciprocal.type_name())) == 1
 
A_input = [Constant(5)]
A_input = [Constant(5)]
sim = Simulation(sfg, A_input)
sim = Simulation(sfg, A_input)
@@ -655,6 +663,12 @@ class TestLdltMatrixInverse:
@@ -655,6 +663,12 @@ class TestLdltMatrixInverse:
def test_2x2_simple_spd(self):
def test_2x2_simple_spd(self):
sfg = ldlt_matrix_inverse(N=2, is_complex=False)
sfg = ldlt_matrix_inverse(N=2, is_complex=False)
 
assert len(sfg.inputs) == 3
 
assert len(sfg.outputs) == 3
 
 
assert len(sfg.find_by_type_name(MADS.type_name())) == 4
 
assert len(sfg.find_by_type_name(Reciprocal.type_name())) == 2
 
A = np.array([[1, 2], [2, 1]])
A = np.array([[1, 2], [2, 1]])
A_input = [Constant(1), Constant(2), Constant(1)]
A_input = [Constant(1), Constant(2), Constant(1)]
@@ -671,6 +685,12 @@ class TestLdltMatrixInverse:
@@ -671,6 +685,12 @@ class TestLdltMatrixInverse:
def test_3x3_simple_spd(self):
def test_3x3_simple_spd(self):
sfg = ldlt_matrix_inverse(N=3, is_complex=False)
sfg = ldlt_matrix_inverse(N=3, is_complex=False)
 
assert len(sfg.inputs) == 6
 
assert len(sfg.outputs) == 6
 
 
assert len(sfg.find_by_type_name(MADS.type_name())) == 15
 
assert len(sfg.find_by_type_name(Reciprocal.type_name())) == 3
 
A = np.array([[2, -1, 0], [-1, 3, -1], [0, -1, 2]])
A = np.array([[2, -1, 0], [-1, 3, -1], [0, -1, 2]])
A_input = [
A_input = [
Constant(2),
Constant(2),
@@ -693,3 +713,103 @@ class TestLdltMatrixInverse:
@@ -693,3 +713,103 @@ class TestLdltMatrixInverse:
assert np.isclose(res["3"], A_inv[1, 1])
assert np.isclose(res["3"], A_inv[1, 1])
assert np.isclose(res["4"], A_inv[1, 2])
assert np.isclose(res["4"], A_inv[1, 2])
assert np.isclose(res["5"], A_inv[2, 2])
assert np.isclose(res["5"], A_inv[2, 2])
 
 
def test_5x5_random_spd(self):
 
N = 5
 
 
sfg = ldlt_matrix_inverse(N=N, is_complex=False)
 
 
assert len(sfg.inputs) == 15
 
assert len(sfg.outputs) == 15
 
 
assert len(sfg.find_by_type_name(MADS.type_name())) == 70
 
assert len(sfg.find_by_type_name(Reciprocal.type_name())) == N
 
 
A = self._generate_random_spd_matrix(N)
 
 
upper_tridiag = A[np.triu_indices_from(A)]
 
 
A_input = [Constant(num) for num in upper_tridiag]
 
A_inv = np.linalg.inv(A)
 
 
sim = Simulation(sfg, A_input)
 
sim.run_for(1)
 
res = sim.results
 
 
row_indices, col_indices = np.triu_indices(N)
 
expected_values = A_inv[row_indices, col_indices]
 
actual_values = [res[str(i)] for i in range(len(expected_values))]
 
 
for i in range(len(expected_values)):
 
assert np.isclose(actual_values[i], expected_values[i])
 
 
def test_30x30_random_spd(self):
 
N = 30
 
 
sfg = ldlt_matrix_inverse(N=N, is_complex=False)
 
 
A = self._generate_random_spd_matrix(N)
 
 
assert len(sfg.inputs) == len(A[np.triu_indices_from(A)])
 
assert len(sfg.outputs) == len(A[np.triu_indices_from(A)])
 
 
assert len(sfg.find_by_type_name(Reciprocal.type_name())) == N
 
 
upper_tridiag = A[np.triu_indices_from(A)]
 
 
A_input = [Constant(num) for num in upper_tridiag]
 
A_inv = np.linalg.inv(A)
 
 
sim = Simulation(sfg, A_input)
 
sim.run_for(1)
 
res = sim.results
 
 
row_indices, col_indices = np.triu_indices(N)
 
expected_values = A_inv[row_indices, col_indices]
 
actual_values = [res[str(i)] for i in range(len(expected_values))]
 
 
for i in range(len(expected_values)):
 
assert np.isclose(actual_values[i], expected_values[i])
 
 
# def test_2x2_random_complex_spd(self):
 
# N = 2
 
 
# sfg = ldlt_matrix_inverse(N=N, is_complex=True)
 
 
# # A = self._generate_random_complex_spd_matrix(N)
 
# A = np.array([[2, 1+1j],[1-1j, 3]])
 
 
# assert len(sfg.inputs) == len(A[np.triu_indices_from(A)])
 
# assert len(sfg.outputs) == len(A[np.triu_indices_from(A)])
 
 
# assert len(sfg.find_by_type_name(Reciprocal.type_name())) == N
 
 
# upper_tridiag = A[np.triu_indices_from(A)]
 
 
# A_input = [Constant(num) for num in upper_tridiag]
 
# A_inv = np.linalg.inv(A)
 
 
# sim = Simulation(sfg, A_input)
 
# sim.run_for(1)
 
# res = sim.results
 
 
# row_indices, col_indices = np.triu_indices(N)
 
# expected_values = A_inv[row_indices, col_indices]
 
# actual_values = [res[str(i)] for i in range(len(expected_values))]
 
 
# for i in range(len(expected_values)):
 
# assert np.isclose(actual_values[i], expected_values[i])
 
 
def _generate_random_spd_matrix(self, N: int) -> np.ndarray:
 
A = np.random.rand(N, N)
 
A = (A + A.T) / 2 # ensure symmetric
 
min_eig = np.min(np.linalg.eigvals(A))
 
A += (np.abs(min_eig) + 0.1) * np.eye(N) # ensure positive definiteness
 
return A
 
 
def _generate_random_complex_spd_matrix(self, N: int) -> np.ndarray:
 
A = np.random.randn(N, N) + 1j * np.random.randn(N, N)
 
A = (A + A.conj().T) / 2 # ensure symmetric
 
min_eig = np.min(np.linalg.eigvals(A))
 
A += (np.abs(min_eig) + 0.1) * np.eye(N) # ensure positive definiteness
 
return A
Loading