diff --git a/.gitignore b/.gitignore index 2b396a8..7ca1fdc 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ share/python-wheels/ *.egg MANIFEST *.ipynb +*.idea # PyInstaller # Usually these files are written by a python script from a template diff --git a/wavelet.py b/wavelet.py index 5d9d466..3c9db19 100644 --- a/wavelet.py +++ b/wavelet.py @@ -35,19 +35,35 @@ def _allocate_mcw(self, message_length): if self.mcw is None: self.mcw = np.zeros((self.m, message_length + self.mg - self.m)) + def _displace_mcw(self, pad): + self.mcw = np.roll(self.mcw, pad) + + def _get_encoded_model(self): + return np.zeros((self.mcw.shape[1],)) + def mcw_from_coefficients(self, file, message_length): self._set_a_coefficients(file) self._allocate_mcw(message_length) self.mcw[:self.m, :self.mg] = self.A - def displace_mcw(self, pad): - self.mcw = np.roll(self.mcw, self.m * pad) - - def get_encoded_output(self): - return np.zeros((self.mcw.shape[1])) - def encode(self, message): - pass - + encoded = self._get_encoded_model() + mcw = np.copy(self.mcw) + for i in range(0, np.size(message), self.m): + encoded += np.matmul(message[i: i + self.m], mcw) + mcw = np.roll(mcw, self.m) + return encoded + def _get_decoded_model(self): + if self.mcw is None: + raise ValueError("MCW is not known") + return np.zeros((self.mcw.shape[1] - self.mg + self.m,)) + def decode(self, encoded): + decoded = self._get_decoded_model() + mcw = np.copy(self.mcw) + for i in range(np.size(decoded)): + if i and i % self.m == 0: + mcw = np.roll(mcw, self.m) + decoded[i] = np.dot(mcw[i % self.m], encoded) + return decoded diff --git a/wavelet_tests.py b/wavelet_tests.py index 0d4a548..c35a85b 100644 --- a/wavelet_tests.py +++ b/wavelet_tests.py @@ -5,19 +5,23 @@ from wavelet import Wavelet +class OtherTests(unittest.TestCase): + def test_allocate_matrix(self): + self.assertEqual(self.w.A, None) + ans = np.zeros((self.w.m, self.w.mg)) + self.w._allocate_a_matrix() + self.assertTrue(np.array_equal(ans, self.w.A)) + + class WaveletShortTests(unittest.TestCase): def setUp(self): self.w = Wavelet(m=2, g=1) + self.file = 'mcw2_4.txt' + self.message = np.array([-1, 1, -1, 1]) def test_mg(self): self.assertEqual(self.w.mg, 2) - def test_allocate_matrix(self): - self.assertEqual(self.w.A, None) - ans = np.zeros((self.w.m, self.w.mg)) - self.w._allocate_a_matrix() - self.assertTrue(np.array_equal(ans, self.w.A)) - def test_vstack(self): arr1 = np.array([0, 1]) arr2 = np.array([2, 3]) @@ -26,16 +30,14 @@ def test_vstack(self): self.assertTrue(np.array_equal(ret, ans)) def test_get_raw_4_lines(self): - file = 'mcw2_4.txt' - l0, l1 = list(self.w._get_raw_lines(file)) + l0, l1 = list(self.w._get_raw_lines(self.file)) self.assertTrue(np.array_equal(l0, np.array([-1, 10]))) self.assertTrue(np.array_equal(l1, np.array([111, -1.9]))) def test_set_a_coefficients(self): self.w = Wavelet(m=2, g=1) - file = 'mcw2_4.txt' ans = np.array([[-1, 10], [111, -1.9]]) - self.w._set_a_coefficients(file) + self.w._set_a_coefficients(self.file) self.assertTrue(np.array_equal(ans, self.w.A)) def test_allocate_mcw(self): @@ -45,70 +47,110 @@ def test_allocate_mcw(self): self.assertTrue(np.array_equal(self.w.mcw, ans)) def test_mcw_from_coefficients(self): - file = 'mcw2_4.txt' message_length = 4 - self.w.mcw_from_coefficients(file, message_length) + self.w.mcw_from_coefficients(self.file, message_length) mcw_lines, mcw_columns = self.w.mcw.shape self.assertEqual(self.w.m, mcw_lines) self.assertEqual(message_length + self.w.mg - self.w.m, mcw_columns) self.assertTrue(np.array_equal(self.w.mcw[:self.w.m, :self.w.mg], self.w.A)) def test_mcw_displacement(self): - file = 'mcw2_4.txt' message_length = 6 - self.w.mcw_from_coefficients(file, message_length) + self.w.mcw_from_coefficients(self.file, message_length) original_mcw = np.copy(self.w.mcw) # Displace by one m - self.w.displace_mcw(1) + self.w._displace_mcw(1) ans = np.array([ - [0, 0, -1, 10, 0, 0], - [0, 0, 111, -1.9, 0, 0], + [0, -1, 10, 0, 0, 0], + [0, 111, -1.9, 0, 0, 0], ]) self.assertTrue(np.array_equal(ans, self.w.mcw)) - self.w.displace_mcw(-1) + self.w._displace_mcw(-1) self.assertTrue(np.array_equal(original_mcw, self.w.mcw)) def test_get_encoded_model(self): - file = 'mcw2_4.txt' message_length = 4 - self.w.mcw_from_coefficients(file, message_length) - encoded_output = self.w.get_encoded_output() + self.w.mcw_from_coefficients(self.file, message_length) + encoded_output = self.w._get_encoded_model() self.assertTrue(np.array_equal(np.zeros(4, ), encoded_output)) - def test_encode(self): - file = 'mcw2_4.txt' - message = np.array([-1, 1, -1, 1]) - self.w.mcw_from_coefficients(file, np.size(message)) + def test_encoding(self): + self.w.mcw_from_coefficients(self.file, np.size(self.message)) - ans = np.matmul(np.array([[-1, 10, 0, 0], [-111, -1.9, 0, 0], [0, 0, -1, 10], [0, 0, -111, -1.9]]), message) + ans = np.matmul(self.message, np.array([[-1, 10, 0, 0], [111, -1.9, 0, 0], [0, 0, -1, 10], [0, 0, 111, -1.9]])) - # model = self.w.get_encoded_output() - # self.assertEqual(np.size(model), np.size(ans)) - - encoded_output = self.w.encode(message) + encoded_output = self.w.encode(self.message) self.assertTrue(np.array_equal(ans, encoded_output)) + def test_get_decoded_model(self): + self.assertRaises(ValueError, self.w._get_decoded_model) + self.w.mcw_from_coefficients(self.file, np.size(self.message)) + decoded_model = self.w._get_decoded_model() + self.assertEqual(np.size(self.message), np.size(decoded_model)) + + def test_decoding(self): + self.w.mcw_from_coefficients(self.file, np.size(self.message)) + encoded = self.w.encode(self.message) + decoded = self.w.decode(encoded) + decoded[decoded >= 0] = 1 + decoded[decoded < 0] = -1 + self.assertTrue(np.array_equal(self.message, decoded)) + class WaveletLongTests(unittest.TestCase): def setUp(self): self.w = Wavelet(m=2, g=64) + self.file = 'mcw2_128.txt' + self.message = np.array([1, -1, 1, 1, 1, -1]) - @staticmethod - def read_256_coefficients(): - with open('mcw2_128.txt', 'r') as file: + def read_256_coefficients(self): + with open(self.file, 'r') as file: flatten_array = np.asarray([float(l) for l in file.readlines()]) return flatten_array[:128], flatten_array[128:] def test_get_raw_128_lines(self): - file = 'mcw2_128.txt' ans0, ans1 = self.read_256_coefficients() - l0, l1 = list(self.w._get_raw_lines(file)) + l0, l1 = list(self.w._get_raw_lines(self.file)) self.assertTrue(np.array_equal(ans0, l0)) self.assertTrue(np.array_equal(ans1, l1)) self.assertEqual(np.size(l0), self.w.mg) self.assertEqual(np.size(l1), self.w.mg) + def test_encoding(self): + n = np.size(self.message) + mcw_lines = n + mcw_columns = n + self.w.mg - self.w.m + mcw = np.zeros((mcw_lines, mcw_columns)) + f_line, s_line = self.read_256_coefficients() + for i in range(0, mcw_lines, self.w.m): + mcw[i, i: i + self.w.mg] = f_line + mcw[i + 1, i:i + self.w.mg] = s_line + self.assertEqual(mcw.shape[0], 6) + ans = np.matmul(self.message, mcw) + + self.w.mcw_from_coefficients(self.file, np.size(self.message)) + encoded = self.w.encode(self.message) + + self.assertTrue(np.array_equal(ans, encoded)) + + def test_decoding(self): + self.w.mcw_from_coefficients(self.file, np.size(self.message)) + encoded = self.w.encode(self.message) + decoded = self.w.decode(encoded) + decoded[decoded >= 0] = 1 + decoded[decoded < 0] = -1 + self.assertTrue(np.array_equal(self.message, decoded)) + + def test_huge_encoding_and_decoding(self): + message = np.array([np.random.choice([-1, 1]) for _ in range(50000)]) + self.w.mcw_from_coefficients(self.file, np.size(message)) + encoded = self.w.encode(message) + decoded = self.w.decode(encoded) + decoded[decoded >= 0] = 1 + decoded[decoded < 0] = -1 + self.assertTrue(np.array_equal(message, decoded)) + if __name__ == '__main__': unittest.main()