TropicZ/tropicZ.ipynb

632 lines
26 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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