Загрузить файлы в «/»
This commit is contained in:
parent
20460f30aa
commit
9c0b165a6b
429
tropicZ.py
Normal file
429
tropicZ.py
Normal file
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user