TropicZ/tropicZ.py

430 lines
15 KiB
Python
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.

# -*- 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)