diff --git a/tropicZ.py b/tropicZ.py new file mode 100644 index 0000000..2132820 --- /dev/null +++ b/tropicZ.py @@ -0,0 +1,429 @@ +# -*- coding: utf-8 -*- +"""tropic.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/14lR3A29PgCuP9jUS9quiNFYPcYhZvxLi +""" + +class TropicZ(object): + def __init__(self, infty = 1000, add_op = 'max'): + self.__infty = infty + self._posinf = infty + self._neginf = -infty + + self.add_op = max + if add_op == 'min': + self.add_op = min + + @property + def neginf(self): + return TropicZ.TropicElement(self, self._neginf) + + @property + def posinf(self): + return TropicZ.TropicElement(self, self._posinf) + + def elem(self, val = 0): + ''' + Формирует тропический элемента из целого числа val + ''' + return TropicZ.TropicElement(self, val) + + class TropicElement(object): + def __init__(self, outer_instance, val = 0): + self.__outer_instance = outer_instance + self._val = self.bound(val) + + def bound(self, val = 0): + neginf = self.__outer_instance._neginf + posinf = self.__outer_instance._posinf + return min(max(int(val), neginf), posinf) + + def __repr__(self): + return str(self) + def __str__(self): + return str(self._val) + def __iter__(self): + return self.entries.__iter__() + + def add(self, val): + ''' + Тропическое сложение текущего элемента с значением val + ''' + if isinstance(val, TropicZ.TropicElement): + result = val._val + else: + result = int(val) + + op = self.__outer_instance.add_op + result = op(self._val, result) + return TropicZ.TropicElement(self.__outer_instance, result) + + def __add__(self, val): + return self.add(val) + + def __iadd__(self, val): + self._val = self.add(val)._val + return self + + def __neg__(self): + result = self.bound(-self._val) + return TropicZ.TropicElement(self.__outer_instance, result) + + def mult(self, val): + ''' + Тропическое умножение текущего элемента на val + ''' + if isinstance(val, TropicZ.TropicElement): + result = val._val + else: + result = int(val) + result = self._val + result + return TropicZ.TropicElement(self.__outer_instance, result) + + def __mul__(self, val): + return self.mult(val) + + def __imul__(self, val): + self._val = self.mult(val)._val + return self + + def div(self, val): + ''' + Тропическое деление текущего элемента на val + ''' + if isinstance(val, TropicZ.TropicElement): + result = val._val + else: + result = int(val) + result = self._val - result + return TropicZ.TropicElement(self.__outer_instance, result) + + def __truediv__(self, val): + return self.div(val) + + def __floordiv__(self, val): + return self.div(val) + +TZ = TropicZ(1000, 'max') +TZmin = TropicZ(1000, 'min') +TZmax = TropicZ(1000, 'max') + +a = TZ.elem(5) +b = TZ.elem(6) +stroka = TropicZ.TropicElement.__repr__(a) +print(stroka) +print(int(stroka)+5) +print(-a) +print(a * b) +print(a + b) +L = [TZ.elem(i) for i in range(7)] +print(L) +print(sum(L, TZ.neginf)) +print(a * TZ.neginf) + +import math + +class TropicalMatrix: + def __init__(self, entries): + self.entries = entries + + def __str__(self): + return str(self.entries) + + def get_entry(self, i, j): + return self.entries[i][j] + + def dual(self, dual): + n = 2 + new_matrix = [[0, 0], [0, 0]] + for i in range(n): + for j in range(n): + new_matrix[i][j] = dual.elem(self[i][j]) + return TropicalMatrix(new_matrix) + + def add_tropical_matrix(self, matrix, dual): + n = 2 + new_matrix = [[0, 0], [0, 0]] + self = TropicalMatrix.dual(self, dual) + matrix = TropicalMatrix.dual(matrix, dual) + for i in range(n): + for j in range(n): + new_matrix[i][j] = self.get_entry(i, j) + matrix.get_entry(i, j) + return TropicalMatrix(new_matrix) + + def mult_scalar(self, scalar, dual): + n = 2 + new_matrix = [[0, 0], [0, 0]] + self = TropicalMatrix.dual(self, dual) + for i in range(n): + for j in range(n): + new_matrix[i][j] = self.get_entry(i, j) * scalar + return TropicalMatrix(new_matrix) + + def mult_tropical_matrix(self, matrix, dual): + n = 2 + new_matrix = [[0, 0], [0, 0]] + self = TropicalMatrix.dual(self, dual) + matrix = TropicalMatrix.dual(matrix, dual) + for i in range(n): + for j in range(n): + sum_list = [] + for k in range(n): + sum_list.append(self.get_entry(i, k) * matrix.get_entry(k, j)) + new_matrix[i][j] = sum_list[0] + sum_list[1] + return TropicalMatrix(new_matrix) + + def get_dimension(self): + return len(self.entries) + + def __iter__(self): # метод для превращения тропической матрицы в список + return self.entries.__iter__() + +if __name__ == "__main__": + M = [[-1000, 10], [5, 3]] + N = [[3, 6], [15, 1000]] + A = [[5, -1000], [-1000, 5]] + B = [[2, -1000], [-1000, 2]] + + p = TropicalMatrix.add_tropical_matrix(M, A, TZmax) + t = TropicalMatrix.mult_tropical_matrix(N, N, TZmin) + q = TropicalMatrix.add_tropical_matrix(M, B, TZmax) + r = TropicalMatrix.mult_scalar(N, 3, TZmin) + + print('p(x) =', p) + print('t(x) =', t) + print('q(x) =', q) + print('r(x) =', r) + +import math +import random +import numpy as np + +class TropicalMatrix_without_dual: + def __init__(self, entries): + self.entries = entries + + def __str__(self): + return str(self.entries) + + def add_tropical_matrix_without_dual(self, matrix): + n = 2 + new_matrix = [[0, 0], [0, 0]] + for i in range(n): + for j in range(n): + new_matrix[i][j] = self.get_entry(i, j) + matrix.get_entry(i, j) + return TropicalMatrix_without_dual(new_matrix) + + def mult_tropical_matrix_without_dual(self, matrix): + n = 2 + new_matrix = [[0, 0], [0, 0]] + for i in range(n): + for j in range(n): + sum_list = [] + for k in range(n): + sum_list.append(self.get_entry(i, k) * matrix.get_entry(k, j)) + new_matrix[i][j] = sum_list[0] + sum_list[1] + return TropicalMatrix(new_matrix) + + def get_entry(self, i, j): + return self.entries[i][j] + + def __iter__(self): # метод для превращения тропической матрицы в список + return self.entries.__iter__() + +if __name__ == "__main__": + M = TropicalMatrix.dual([[-1000, 10], [5, 3]], TZmax) + N = TropicalMatrix.dual([[3, 6], [15, 1000]], TZmin) + l = TropicalMatrix_without_dual.add_tropical_matrix_without_dual(M, N) + m = TropicalMatrix_without_dual.mult_tropical_matrix_without_dual(M, N) + print(m) + +def convert(matrix): + s = list(matrix) + for i in range(2): + for j in range(2): + s[i][j] = int(TropicZ.TropicElement.__repr__(s[i][j])) + return s + +def generate_random_matrix(n, min_elem, max_elem): + new_matrix = [[0, 0], [0, 0]] + for i in range(n): + for j in range(n): + new_matrix[i][j] = random.randint(min_elem, max_elem) + return new_matrix + +def generate_random_tropical_poly(max_degree, min_coefficient, max_coefficient): + """ + Генерирует случайный (не константу) тропический многочлен с точностью до заданной степени. + """ + coefficients = [] + for d in range(0, random.randint(1, max_degree) + 1): + coefficients.append(random.randint(min_coefficient, max_coefficient)) + return coefficients + +def MatrixMul(a, n): + if (n <= 1): + return a + else: + return TropicalMatrix_without_dual.mult_tropical_matrix_without_dual(MatrixMul(a, n-1), a) + +def evaluate_polynomial(tropical_matrix, coefficient_list, dual): + """ + Вычисляет многочлен (списком), заданный тропической матрицей. + """ + identity_matrix_Zmax = [[0, -1000], [-1000, 0]] + identity_matrix_Zmin = [[0, 1000], [1000, 0]] + null_matrix_Zmax = [[-1000, -1000], [-1000, -1000]] + null_matrix_Zmin = [[1000, 1000], [1000, 1000]] + sum_list = [] + + # свободный член + if coefficient_list[0] != 0: + if dual == TZmin: + sum_list.append(TropicalMatrix.mult_scalar(identity_matrix_Zmin, coefficient_list[0], dual)) + else: + sum_list.append(TropicalMatrix.mult_scalar(identity_matrix_Zmax, coefficient_list[0], dual)) + if coefficient_list[0] == 0: + if dual == TZmin: + sum_list.append(TropicalMatrix.dual(null_matrix_Zmin, dual)) + else: + sum_list.append(TropicalMatrix.dual(null_matrix_Zmax, dual)) + + # для многочлена первой степени + if (coefficient_list[1] != 0) and (coefficient_list[1] != 1): + sum_list.append(TropicalMatrix.mult_scalar(tropical_matrix, coefficient_list[1], dual)) + if coefficient_list[1] == 1: + sum_list.append(TropicalMatrix.dual(tropical_matrix, dual)) + if coefficient_list[1] == 0: + if dual == TZmin: + sum_list.append(TropicalMatrix.dual(null_matrix_Zmin, dual)) + else: + sum_list.append(TropicalMatrix.dual(null_matrix_Zmax, dual)) + + # для многочлена второй степени и выше + + for i in range(2, len(coefficient_list)): + sum_list.append(TropicalMatrix.dual(tropical_matrix, dual)) + sum_list[i] = MatrixMul(sum_list[i], i) + if (coefficient_list[i] != 1) and (coefficient_list[i] != 0): + sum_list[i] = TropicalMatrix.mult_scalar(convert(sum_list[i]), coefficient_list[i], dual) + if coefficient_list[i] == 0: + if dual == TZmin: + sum_list.append(TropicalMatrix.dual(null_matrix_Zmin, dual)) + else: + sum_list.append(TropicalMatrix.dual(null_matrix_Zmax, dual)) + + new_matrix = sum_list[0] # складываем все матрицы в sum_list + for matrix in sum_list: + new_matrix = TropicalMatrix_without_dual.add_tropical_matrix_without_dual(new_matrix, matrix) + return TropicalMatrix(new_matrix) + +def get_polynomial_representation(coefficient_list): + term_list = [str(coefficient_list[0])] + for i in range(1, len(coefficient_list)): + term_list.append(str(coefficient_list[i]) + "x^" + str(i)) + return " + ".join(term_list) + +def generate_key(public_term, public_matrix_a, public_matrix_b): + left_term = TropicalMatrix.mult_tropical_matrix(public_matrix_a, public_term, TZmax) + right_term = TropicalMatrix.mult_tropical_matrix(convert(left_term), public_matrix_b, TZmin) + return right_term + +if __name__ == "__main__": + p_x = [5, 1] + t_x = [0, 0, 1] + q_x = [2, 1] + r_x = [0, 3] + + X = [[1, 2], [6, 10]] + M = [[-1000, 10], [5, 3]] + N = [[3, 6], [15, 1000]] + p_M = convert(evaluate_polynomial(M, p_x, TZmax)) + t_N = convert(evaluate_polynomial(N, t_x, TZmin)) + q_M = convert(evaluate_polynomial(M, q_x, TZmax)) + r_N = convert(evaluate_polynomial(N, r_x, TZmin)) + + print('p(x) =', p_M) + print('t(x) =', t_N) + print('q(x) =', q_M) + print('r(x) =', r_N) + + Alica = TropicalMatrix.mult_tropical_matrix(p_M, X, TZmax) + alice_public_key = TropicalMatrix.mult_tropical_matrix(convert(Alica), t_N, TZmin) + print('Открытый ключ Алисы: ', alice_public_key) + + Bob = TropicalMatrix.mult_tropical_matrix(q_M, X, TZmax) + bob_public_key = TropicalMatrix.mult_tropical_matrix(convert(Bob), r_N, TZmin) + print('Открытый ключ Боба: ', bob_public_key) + + print('Секретный ключ Алисы: ', generate_key(convert(bob_public_key), p_M, t_N)) + print('Секретный ключ Боба: ', generate_key(convert(alice_public_key), q_M, r_N)) + +import random + +def pprint_matrix(matrix): + print('\n'.join([' '.join([str(cell) for cell in row]) for row in matrix.entries])) + +if __name__ == "__main__": + matrix_size = 2 + min_matrix_term = -15 + max_matrix_term = 15 + min_polynomial_coefficient = -10 + max_polynomial_coefficient = 10 + max_polynomial_degree = 5 + + print('Генерация многочленов') + + print("Секретные многочлены Алисы: ") + p_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient) + t_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient) + print('p(x) =', get_polynomial_representation(p_x)) + print('t(x) =', get_polynomial_representation(t_x)) + + print('Секретные многочлены Боба: ') + q_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient) + r_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient) + print('q(x) =', get_polynomial_representation(q_x)) + print('r(x) =', get_polynomial_representation(r_x)) + + print('Открытая матрица Алисы: ') + #M = generate_random_matrix(matrix_size, min_matrix_term, max_matrix_term) + M = [[68, 1000],[-1000, 11]] + print('M = ', M) + + print('Открытая матрица Боба: ') + #N = generate_random_matrix(matrix_size, min_matrix_term, max_matrix_term) + N = [[15, 122],[78, 12]] + print('N = ', N) + + X_matrix = generate_random_matrix(matrix_size, min_matrix_term, max_matrix_term) + print('Матрица X: ', X_matrix) + + print('Алиса отправляет Бобу следующую матрицу') + p_M = convert(evaluate_polynomial(M, p_x, TZmax)) + t_N = convert(evaluate_polynomial(N, t_x, TZmin)) + Alica = TropicalMatrix.mult_tropical_matrix(p_M, X, TZmax) + alice_public_key = TropicalMatrix.mult_tropical_matrix(convert(Alica), t_N, TZmin) + print('Открытый ключ Алисы: ') + pprint_matrix(alice_public_key) + + print('Боб отправляет Алисе следующую матрицу') + q_M = convert(evaluate_polynomial(M, q_x, TZmax)) + r_N = convert(evaluate_polynomial(N, r_x, TZmin)) + Bob = TropicalMatrix.mult_tropical_matrix(q_M, X, TZmax) + bob_public_key = TropicalMatrix.mult_tropical_matrix(convert(Bob), r_N, TZmin) + print('Открытый ключ Боба: ') + pprint_matrix(bob_public_key) + + print('Алиса и Боб вычисляют секретные ключи') + print('Секретный ключ Алисы: ') + alice_key = generate_key(convert(bob_public_key), p_M, t_N) + pprint_matrix(alice_key) + + print('Секретный ключ Боба: ') + bob_key = generate_key(convert(alice_public_key), q_M, r_N) + pprint_matrix(bob_key) +