def linear(f, n): if n <= 10: # пробегаемся по всем наборам аргументов функции, начиная с тройки for x in range(3, 2**n): term = integer_to_term(x, n) ones = term.count(1) # набор только с одной единицей не интересует, # так как соответствующее слагаемое полинома # Жегалкина будет состоять из одной переменной if ones == 1: continue coef = 0 # коэффициент при соотвестующем слагаемом полинома Жегалкина for i in range(1, ones + 1): # находим все возможные сочетания индексов единиц по i combs = combinations(compress(range(0, n), term), i) for comb in combs: # формируем сравнимый с рассматриваемым x # набор аргументов, в котором единицы, # стоящие на индексах из текущего сочетания, заменяются нулями comp_set = [ 0 if ind in comb else bit for ind, bit in enumerate(term) ] coef ^= int(calc(f, term_to_integer(comp_set), n) == True) coef ^= int(calc(f, x, n) == True) # если в полиноме Жегалкина присутствует слагаемое # с более чем одним множителем, функция является нелинейной if coef == 1: return False return True else: a_0 = int(calc(f, 0, n) == True) attempts = 5 * n for i in range(0, attempts): random_number = random.getrandbits(n) tmp = random_number f_x = int(calc(f, random_number, n) == True) random_number = random.getrandbits(n) f_y = int(calc(f, random_number, n) == True) f_x_y = int(calc(f, tmp ^ random_number, n) == True) if a_0 ^ f_x ^ f_y != f_x_y: return False return True
def check_list_0(fs, m, n): combs = combinations( fs, m) # все возможные сочетания из наборов аргументов функции по m for el in combs: dis = 0 for p in el: dis |= p # если в дизъюнкции m сочетаний наборов аргументов функции # не нашлось ни одного нуля, то m не является порядком класса I if 0 not in integer_to_term(dis, n): return False return True
def check_list_1(fs, m, n): combs = combinations( fs, m) # все возможные сочетания из наборов аргументов функции по m t = 2**n - 1 for el in combs: con = t for p in el: con &= p # если в конъюнкции m сочетаний наборов аргументов функции # не нашлось ни одной единицы, то m не является порядком класса I if 1 not in integer_to_term(con, n): return False return True
def test_integer_to_term(): assert integer_to_term(777) == [1, 1, 0, 0, 0, 0, 1, 0, 0, 1] assert integer_to_term(123, 3) == [1, 1, 1, 1, 0, 1, 1] assert integer_to_term(456, 16) == [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0]
def calc(f, args, n): return f(*[true if x == 1 else false for x in integer_to_term(args, n)])