{ "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 }