diff --git a/tropicZ.ipynb b/tropicZ.ipynb new file mode 100644 index 0000000..9618e4c --- /dev/null +++ b/tropicZ.ipynb @@ -0,0 +1,632 @@ +{ + "cells": [ + { + "cell_type": "code", + "source": [ + "class TropicZ(object):\n", + " def __init__(self, infty = 1000, add_op = 'max'):\n", + " self.__infty = infty\n", + " self._posinf = infty\n", + " self._neginf = -infty\n", + "\n", + " self.add_op = max\n", + " if add_op == 'min':\n", + " self.add_op = min\n", + "\n", + " @property\n", + " def neginf(self):\n", + " return TropicZ.TropicElement(self, self._neginf)\n", + "\n", + " @property\n", + " def posinf(self):\n", + " return TropicZ.TropicElement(self, self._posinf)\n", + "\n", + " def elem(self, val = 0):\n", + " '''\n", + " Формирует тропический элемента из целого числа val\n", + " '''\n", + " return TropicZ.TropicElement(self, val)\n", + "\n", + " class TropicElement(object):\n", + " def __init__(self, outer_instance, val = 0):\n", + " self.__outer_instance = outer_instance\n", + " self._val = self.bound(val)\n", + "\n", + " def bound(self, val = 0):\n", + " neginf = self.__outer_instance._neginf\n", + " posinf = self.__outer_instance._posinf\n", + " return min(max(int(val), neginf), posinf)\n", + "\n", + " def __repr__(self):\n", + " return str(self)\n", + " def __str__(self):\n", + " return str(self._val)\n", + " def __iter__(self):\n", + " return self.entries.__iter__()\n", + "\n", + " def add(self, val):\n", + " '''\n", + " Тропическое сложение текущего элемента с значением val\n", + " '''\n", + " if isinstance(val, TropicZ.TropicElement):\n", + " result = val._val\n", + " else:\n", + " result = int(val)\n", + "\n", + " op = self.__outer_instance.add_op\n", + " result = op(self._val, result)\n", + " return TropicZ.TropicElement(self.__outer_instance, result)\n", + "\n", + " def __add__(self, val):\n", + " return self.add(val)\n", + "\n", + " def __iadd__(self, val):\n", + " self._val = self.add(val)._val\n", + " return self\n", + "\n", + " def __neg__(self):\n", + " result = self.bound(-self._val)\n", + " return TropicZ.TropicElement(self.__outer_instance, result)\n", + "\n", + " def mult(self, val):\n", + " '''\n", + " Тропическое умножение текущего элемента на val\n", + " '''\n", + " if isinstance(val, TropicZ.TropicElement):\n", + " result = val._val\n", + " else:\n", + " result = int(val)\n", + " result = self._val + result\n", + " return TropicZ.TropicElement(self.__outer_instance, result)\n", + "\n", + " def __mul__(self, val):\n", + " return self.mult(val)\n", + "\n", + " def __imul__(self, val):\n", + " self._val = self.mult(val)._val\n", + " return self\n", + "\n", + " def div(self, val):\n", + " '''\n", + " Тропическое деление текущего элемента на val\n", + " '''\n", + " if isinstance(val, TropicZ.TropicElement):\n", + " result = val._val\n", + " else:\n", + " result = int(val)\n", + " result = self._val - result\n", + " return TropicZ.TropicElement(self.__outer_instance, result)\n", + "\n", + " def __truediv__(self, val):\n", + " return self.div(val)\n", + "\n", + " def __floordiv__(self, val):\n", + " return self.div(val)" + ], + "metadata": { + "id": "SRpscGXghDbV" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "xRDb1Z0NhCap" + }, + "outputs": [], + "source": [ + "TZ = TropicZ(1000, 'max')\n", + "TZmin = TropicZ(1000, 'min')\n", + "TZmax = TropicZ(1000, 'max')" + ] + }, + { + "cell_type": "code", + "source": [ + "a = TZ.elem(5)\n", + "b = TZ.elem(6)\n", + "stroka = TropicZ.TropicElement.__repr__(a)\n", + "print(stroka)\n", + "print(int(stroka)+5)\n", + "print(-a)\n", + "print(a * b)\n", + "print(a + b)\n", + "L = [TZ.elem(i) for i in range(7)]\n", + "print(L)\n", + "print(sum(L, TZ.neginf))\n", + "print(a * TZ.neginf)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "4lgRHM3BPbzR", + "outputId": "a1d40437-5c55-47c9-b167-d894d1be9967" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "5\n", + "10\n", + "-5\n", + "11\n", + "6\n", + "[0, 1, 2, 3, 4, 5, 6]\n", + "6\n", + "-995\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import math\n", + "\n", + "class TropicalMatrix:\n", + " def __init__(self, entries):\n", + " self.entries = entries\n", + "\n", + " def __str__(self):\n", + " return str(self.entries)\n", + "\n", + " def get_entry(self, i, j):\n", + " return self.entries[i][j]\n", + "\n", + " def dual(self, dual):\n", + " n = 2\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " for i in range(n):\n", + " for j in range(n):\n", + " new_matrix[i][j] = dual.elem(self[i][j])\n", + " return TropicalMatrix(new_matrix)\n", + "\n", + " def add_tropical_matrix(self, matrix, dual):\n", + " n = 2\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " self = TropicalMatrix.dual(self, dual)\n", + " matrix = TropicalMatrix.dual(matrix, dual)\n", + " for i in range(n):\n", + " for j in range(n):\n", + " new_matrix[i][j] = self.get_entry(i, j) + matrix.get_entry(i, j)\n", + " return TropicalMatrix(new_matrix)\n", + "\n", + " def mult_scalar(self, scalar, dual):\n", + " n = 2\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " self = TropicalMatrix.dual(self, dual)\n", + " for i in range(n):\n", + " for j in range(n):\n", + " new_matrix[i][j] = self.get_entry(i, j) * scalar\n", + " return TropicalMatrix(new_matrix)\n", + "\n", + " def mult_tropical_matrix(self, matrix, dual):\n", + " n = 2\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " self = TropicalMatrix.dual(self, dual)\n", + " matrix = TropicalMatrix.dual(matrix, dual)\n", + " for i in range(n):\n", + " for j in range(n):\n", + " sum_list = []\n", + " for k in range(n):\n", + " sum_list.append(self.get_entry(i, k) * matrix.get_entry(k, j))\n", + " new_matrix[i][j] = sum_list[0] + sum_list[1]\n", + " return TropicalMatrix(new_matrix)\n", + "\n", + " def get_dimension(self):\n", + " return len(self.entries)\n", + "\n", + " def __iter__(self): # метод для превращения тропической матрицы в список\n", + " return self.entries.__iter__()\n", + "\n", + "if __name__ == \"__main__\":\n", + " M = [[-1000, 10], [5, 3]]\n", + " N = [[3, 6], [15, 1000]]\n", + " A = [[5, -1000], [-1000, 5]]\n", + " B = [[2, -1000], [-1000, 2]]\n", + "\n", + " p = TropicalMatrix.add_tropical_matrix(M, A, TZmax)\n", + " t = TropicalMatrix.mult_tropical_matrix(N, N, TZmin)\n", + " q = TropicalMatrix.add_tropical_matrix(M, B, TZmax)\n", + " r = TropicalMatrix.mult_scalar(N, 3, TZmin)\n", + "\n", + " print('p(x) =', p)\n", + " print('t(x) =', t)\n", + " print('q(x) =', q)\n", + " print('r(x) =', r)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "jsQa8vr6NTcr", + "outputId": "88a5c0bf-19c6-47c1-b4bc-1ab8411f287c" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "p(x) = [[5, 10], [5, 5]]\n", + "t(x) = [[6, 9], [18, 21]]\n", + "q(x) = [[2, 10], [5, 3]]\n", + "r(x) = [[6, 9], [18, 1000]]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import math\n", + "import random\n", + "import numpy as np" + ], + "metadata": { + "id": "2_UE8hylV8BD" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "class TropicalMatrix_without_dual:\n", + " def __init__(self, entries):\n", + " self.entries = entries\n", + "\n", + " def __str__(self):\n", + " return str(self.entries)\n", + "\n", + " def add_tropical_matrix_without_dual(self, matrix):\n", + " n = 2\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " for i in range(n):\n", + " for j in range(n):\n", + " new_matrix[i][j] = self.get_entry(i, j) + matrix.get_entry(i, j)\n", + " return TropicalMatrix_without_dual(new_matrix)\n", + "\n", + " def mult_tropical_matrix_without_dual(self, matrix):\n", + " n = 2\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " for i in range(n):\n", + " for j in range(n):\n", + " sum_list = []\n", + " for k in range(n):\n", + " sum_list.append(self.get_entry(i, k) * matrix.get_entry(k, j))\n", + " new_matrix[i][j] = sum_list[0] + sum_list[1]\n", + " return TropicalMatrix(new_matrix)\n", + "\n", + " def get_entry(self, i, j):\n", + " return self.entries[i][j]\n", + "\n", + " def __iter__(self): # метод для превращения тропической матрицы в список\n", + " return self.entries.__iter__()\n", + "\n", + "if __name__ == \"__main__\":\n", + " M = TropicalMatrix.dual([[-1000, 10], [5, 3]], TZmax)\n", + " N = TropicalMatrix.dual([[3, 6], [15, 1000]], TZmin)\n", + " l = TropicalMatrix_without_dual.add_tropical_matrix_without_dual(M, N)\n", + " m = TropicalMatrix_without_dual.mult_tropical_matrix_without_dual(M, N)\n", + " print(m)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DufYsl2a9lrz", + "outputId": "2de93bd5-4f48-4fdd-d530-f7c5e07f19f2" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[25, 1000], [18, 1000]]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "def convert(matrix):\n", + " s = list(matrix)\n", + " for i in range(2):\n", + " for j in range(2):\n", + " s[i][j] = int(TropicZ.TropicElement.__repr__(s[i][j]))\n", + " return s\n", + "\n", + "def generate_random_matrix(n, min_elem, max_elem):\n", + " new_matrix = [[0, 0], [0, 0]]\n", + " for i in range(n):\n", + " for j in range(n):\n", + " new_matrix[i][j] = random.randint(min_elem, max_elem)\n", + " return new_matrix\n", + "\n", + "def generate_random_tropical_poly(max_degree, min_coefficient, max_coefficient):\n", + " \"\"\"\n", + " Генерирует случайный (не константу) тропический многочлен с точностью до заданной степени.\n", + " \"\"\"\n", + " coefficients = []\n", + " for d in range(0, random.randint(1, max_degree) + 1):\n", + " coefficients.append(random.randint(min_coefficient, max_coefficient))\n", + " return coefficients\n", + "\n", + "def MatrixMul(a, n):\n", + " if (n <= 1):\n", + " return a\n", + " else:\n", + " return TropicalMatrix_without_dual.mult_tropical_matrix_without_dual(MatrixMul(a, n-1), a)\n", + "\n", + "def evaluate_polynomial(tropical_matrix, coefficient_list, dual):\n", + " \"\"\"\n", + " Вычисляет многочлен (списком), заданный тропической матрицей.\n", + " \"\"\"\n", + " identity_matrix_Zmax = [[0, -1000], [-1000, 0]]\n", + " identity_matrix_Zmin = [[0, 1000], [1000, 0]]\n", + " null_matrix_Zmax = [[-1000, -1000], [-1000, -1000]]\n", + " null_matrix_Zmin = [[1000, 1000], [1000, 1000]]\n", + " sum_list = []\n", + "\n", + " # свободный член\n", + " if coefficient_list[0] != 0:\n", + " if dual == TZmin:\n", + " sum_list.append(TropicalMatrix.mult_scalar(identity_matrix_Zmin, coefficient_list[0], dual))\n", + " else:\n", + " sum_list.append(TropicalMatrix.mult_scalar(identity_matrix_Zmax, coefficient_list[0], dual))\n", + " if coefficient_list[0] == 0:\n", + " if dual == TZmin:\n", + " sum_list.append(TropicalMatrix.dual(null_matrix_Zmin, dual))\n", + " else:\n", + " sum_list.append(TropicalMatrix.dual(null_matrix_Zmax, dual))\n", + "\n", + " # для многочлена первой степени\n", + " if (coefficient_list[1] != 0) and (coefficient_list[1] != 1):\n", + " sum_list.append(TropicalMatrix.mult_scalar(tropical_matrix, coefficient_list[1], dual))\n", + " if coefficient_list[1] == 1:\n", + " sum_list.append(TropicalMatrix.dual(tropical_matrix, dual))\n", + " if coefficient_list[1] == 0:\n", + " if dual == TZmin:\n", + " sum_list.append(TropicalMatrix.dual(null_matrix_Zmin, dual))\n", + " else:\n", + " sum_list.append(TropicalMatrix.dual(null_matrix_Zmax, dual))\n", + "\n", + " # для многочлена второй степени и выше\n", + "\n", + " for i in range(2, len(coefficient_list)):\n", + " sum_list.append(TropicalMatrix.dual(tropical_matrix, dual))\n", + " sum_list[i] = MatrixMul(sum_list[i], i)\n", + " if (coefficient_list[i] != 1) and (coefficient_list[i] != 0):\n", + " sum_list[i] = TropicalMatrix.mult_scalar(convert(sum_list[i]), coefficient_list[i], dual)\n", + " if coefficient_list[i] == 0:\n", + " if dual == TZmin:\n", + " sum_list.append(TropicalMatrix.dual(null_matrix_Zmin, dual))\n", + " else:\n", + " sum_list.append(TropicalMatrix.dual(null_matrix_Zmax, dual))\n", + "\n", + " new_matrix = sum_list[0] # складываем все матрицы в sum_list\n", + " for matrix in sum_list:\n", + " new_matrix = TropicalMatrix_without_dual.add_tropical_matrix_without_dual(new_matrix, matrix)\n", + " return TropicalMatrix(new_matrix)\n", + "\n", + "def get_polynomial_representation(coefficient_list):\n", + " term_list = [str(coefficient_list[0])]\n", + " for i in range(1, len(coefficient_list)):\n", + " term_list.append(str(coefficient_list[i]) + \"x^\" + str(i))\n", + " return \" + \".join(term_list)\n", + "\n", + "def generate_key(public_term, public_matrix_a, public_matrix_b):\n", + " left_term = TropicalMatrix.mult_tropical_matrix(public_matrix_a, public_term, TZmax)\n", + " right_term = TropicalMatrix.mult_tropical_matrix(convert(left_term), public_matrix_b, TZmin)\n", + " return right_term\n", + "\n", + "if __name__ == \"__main__\":\n", + " p_x = [5, 1]\n", + " t_x = [0, 0, 1]\n", + " q_x = [2, 1]\n", + " r_x = [0, 3]\n", + "\n", + " X = [[1, 2], [6, 10]]\n", + " M = [[-1000, 10], [5, 3]]\n", + " N = [[3, 6], [15, 1000]]\n", + " p_M = convert(evaluate_polynomial(M, p_x, TZmax))\n", + " t_N = convert(evaluate_polynomial(N, t_x, TZmin))\n", + " q_M = convert(evaluate_polynomial(M, q_x, TZmax))\n", + " r_N = convert(evaluate_polynomial(N, r_x, TZmin))\n", + "\n", + " print('p(x) =', p_M)\n", + " print('t(x) =', t_N)\n", + " print('q(x) =', q_M)\n", + " print('r(x) =', r_N)\n", + "\n", + " Alica = TropicalMatrix.mult_tropical_matrix(p_M, X, TZmax)\n", + " alice_public_key = TropicalMatrix.mult_tropical_matrix(convert(Alica), t_N, TZmin)\n", + " print('Открытый ключ Алисы: ', alice_public_key)\n", + "\n", + " Bob = TropicalMatrix.mult_tropical_matrix(q_M, X, TZmax)\n", + " bob_public_key = TropicalMatrix.mult_tropical_matrix(convert(Bob), r_N, TZmin)\n", + " print('Открытый ключ Боба: ', bob_public_key)\n", + "\n", + " print('Секретный ключ Алисы: ', generate_key(convert(bob_public_key), p_M, t_N))\n", + " print('Секретный ключ Боба: ', generate_key(convert(alice_public_key), q_M, r_N))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "m-6cYpv2V3T1", + "outputId": "1082faa4-b53b-447e-ff8d-9388dbd0da88" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "p(x) = [[5, 10], [5, 5]]\n", + "t(x) = [[6, 9], [18, 21]]\n", + "q(x) = [[2, 10], [5, 3]]\n", + "r(x) = [[6, 9], [18, 1000]]\n", + "Открытый ключ Алисы: [[22, 25], [17, 20]]\n", + "Открытый ключ Боба: [[22, 25], [15, 18]]\n", + "Секретный ключ Алисы: [[33, 36], [33, 36]]\n", + "Секретный ключ Боба: [[33, 36], [33, 36]]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import random\n", + "\n", + "def pprint_matrix(matrix):\n", + " print('\\n'.join([' '.join([str(cell) for cell in row]) for row in matrix.entries]))\n", + "\n", + "if __name__ == \"__main__\":\n", + " matrix_size = 2\n", + " min_matrix_term = -15\n", + " max_matrix_term = 15\n", + " min_polynomial_coefficient = -10\n", + " max_polynomial_coefficient = 10\n", + " max_polynomial_degree = 5\n", + "\n", + " print('Генерация многочленов')\n", + "\n", + " print(\"Секретные многочлены Алисы: \")\n", + " p_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient)\n", + " t_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient)\n", + " print('p(x) =', get_polynomial_representation(p_x))\n", + " print('t(x) =', get_polynomial_representation(t_x))\n", + "\n", + " print('Секретные многочлены Боба: ')\n", + " q_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient)\n", + " r_x = generate_random_tropical_poly(max_polynomial_degree, min_polynomial_coefficient, max_polynomial_coefficient)\n", + " print('q(x) =', get_polynomial_representation(q_x))\n", + " print('r(x) =', get_polynomial_representation(r_x))\n", + "\n", + " print('Открытая матрица Алисы: ')\n", + " #M = generate_random_matrix(matrix_size, min_matrix_term, max_matrix_term)\n", + " M = [[68, 1000],[-1000, 11]]\n", + " print('M = ', M)\n", + "\n", + " print('Открытая матрица Боба: ')\n", + " #N = generate_random_matrix(matrix_size, min_matrix_term, max_matrix_term)\n", + " N = [[15, 122],[78, 12]]\n", + " print('N = ', N)\n", + "\n", + " X_matrix = generate_random_matrix(matrix_size, min_matrix_term, max_matrix_term)\n", + " print('Матрица X: ', X_matrix)\n", + "\n", + " print('Алиса отправляет Бобу следующую матрицу')\n", + " p_M = convert(evaluate_polynomial(M, p_x, TZmax))\n", + " t_N = convert(evaluate_polynomial(N, t_x, TZmin))\n", + " Alica = TropicalMatrix.mult_tropical_matrix(p_M, X, TZmax)\n", + " alice_public_key = TropicalMatrix.mult_tropical_matrix(convert(Alica), t_N, TZmin)\n", + " print('Открытый ключ Алисы: ')\n", + " pprint_matrix(alice_public_key)\n", + "\n", + " print('Боб отправляет Алисе следующую матрицу')\n", + " q_M = convert(evaluate_polynomial(M, q_x, TZmax))\n", + " r_N = convert(evaluate_polynomial(N, r_x, TZmin))\n", + " Bob = TropicalMatrix.mult_tropical_matrix(q_M, X, TZmax)\n", + " bob_public_key = TropicalMatrix.mult_tropical_matrix(convert(Bob), r_N, TZmin)\n", + " print('Открытый ключ Боба: ')\n", + " pprint_matrix(bob_public_key)\n", + "\n", + " print('Алиса и Боб вычисляют секретные ключи')\n", + " print('Секретный ключ Алисы: ')\n", + " alice_key = generate_key(convert(bob_public_key), p_M, t_N)\n", + " pprint_matrix(alice_key)\n", + "\n", + " print('Секретный ключ Боба: ')\n", + " bob_key = generate_key(convert(alice_public_key), q_M, r_N)\n", + " pprint_matrix(bob_key)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "lJW_ff1sek6r", + "outputId": "acfe9f61-eafc-49a3-8e9a-42a3a2b0808c" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Генерация многочленов\n", + "Секретные многочлены Алисы: \n", + "p(x) = 9 + -4x^1 + 9x^2 + 7x^3\n", + "t(x) = 10 + -8x^1 + -5x^2 + -7x^3\n", + "Секретные многочлены Боба: \n", + "q(x) = 2 + 9x^1 + -4x^2 + 8x^3\n", + "r(x) = 5 + 6x^1 + 8x^2 + 3x^3\n", + "Открытая матрица Алисы: \n", + "M = [[68, 1000], [-1000, 11]]\n", + "Открытая матрица Боба: \n", + "N = [[15, 122], [78, 12]]\n", + "Матрица X: [[14, 5], [14, 1]]\n", + "Алиса отправляет Бобу следующую матрицу\n", + "Открытый ключ Алисы: \n", + "1000 1000\n", + "88 89\n", + "Боб отправляет Алисе следующую матрицу\n", + "Открытый ключ Боба: \n", + "1000 1000\n", + "87 91\n", + "Алиса и Боб вычисляют секретные ключи\n", + "Секретный ключ Алисы: \n", + "1000 1000\n", + "169 170\n", + "Секретный ключ Боба: \n", + "1000 1000\n", + "169 170\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "vZge8KIiMEql" + }, + "execution_count": null, + "outputs": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ml", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + }, + "colab": { + "provenance": [] + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file