def ref_generator(d, ref, io_sums=False): circuit = circuit_model.Circuit() var_inputs = [circuit.var(f'x_{i}', kind='input') for i in range(d)] var_outputs = [circuit.var(f'y_{i}', kind='output') for i in range(d)] ref(circuit=circuit, inputs=var_inputs, outputs=var_outputs) if io_sums: s = circuit.var('s') circuit.p_sum(s, var_inputs) circuit.p_sum(s, var_outputs) return circuit
def test_refresh(d, ref=simple_ref): circuit = circuit_model.Circuit() var_inputs = [circuit.var(f'x_{i}', kind='input') for i in range(d)] var_outputs = [circuit.var(f'y_{i}', kind='output') for i in range(d)] ref(circuit=circuit, inputs=var_inputs, outputs=var_outputs) g = circuit_model.CompGraph(circuit) x = gen_random_input(d) inputs = {f'x_{i}': v for i, v in enumerate(x)} res, _ = g.compute(inputs) y = [ v for var, v in res.items() if circuit.vars[var].name.startswith('y_') ] assert (sum(x) % 2) == (sum(y) % 2)
def pini3(d, mat_gen, tmp_sums, strong_bij=False): c = circuit_model.Circuit() sx, sy, sz, x, y, z = mul_preamble(d, c, strong_bij) if tmp_sums: var_sums = (sx, sy) else: var_sums = None ref_prods = mat_gen(c, x, y, var_sums=var_sums) # randoms & temps in matrix r = [{ j: c.var(f'r_{i}_{j}', kind='random' if j < i else 'intermediate') for j in range(d) if j != i } for i in range(d)] for i in range(d): for j in range(i): c.assign(r[j][i], r[i][j]) s = [{j: c.var(f's_{i}_{j}') for j in range(d) if j != i} for i in range(d)] p = [{ j: [c.var(f'p_{i}_{j}_{k}') for k in range(3)] for j in range(d) if j != i } for i in range(d)] t = [{j: c.var(f't_{i}_{j}') for j in range(d)} for i in range(d)] for i in range(d): c.l_prod(t[i][i], ref_prods[i][i]) for j in range(d): if j != i: xi, yj = ref_prods[i][j] # not(x_i) #nxi = c.var(f'nxi_{i}_{j}') #c.l_sum(nxi, (xi,)) c.l_sum(s[i][j], (yj, r[i][j])) c.l_prod(p[i][j][0], (xi, r[i][j])) c.l_prod(p[i][j][1], (xi, s[i][j])) c.l_sum(p[i][j][2], (p[i][j][0], r[i][j])) c.l_sum(t[i][j], (p[i][j][2], p[i][j][1])) c_var = [[c.var(f'c_{i}_{j}') for j in range(d)] for i in range(d)] for i in range(d): c.assign(c_var[i][0], t[i][0]) for j in range(1, d): c.l_sum(c_var[i][j], (c_var[i][j - 1], t[i][j])) c.assign(z[i], c_var[i][d - 1]) return c
def BBP15(d, strong_bij=False): d2 = d - 1 c = circuit_model.Circuit() _, _, _, x, y, z = mul_preamble(d, c, strong_bij) # product matrix p = [[c.var(f'p_{i}_{j}') for j in range(d)] for i in range(d)] for i, j in it.product(range(d), range(d)): c.l_prod(p[i][j], (x[i], y[j])) # randoms & temps in matrix & compression r = [{ d2 - j: c.var(f'r_{i}_{j}', kind='random') for j in range(0, d2 - i, 2) } for i in range(d)] r2 = {j: c.var(f'r2_{j}', kind='random') for j in range(d2 - 1, 0, -2)} t = [{ j: [c.var(f't_{i}_{j}_{k}') for k in range(5)] for j in range(d2, i + 1, -2) } for i in range(d)] c_var = [{j: c.var(f'c_{i}_{j}') for j in range(d2 + 2, i + 1, -2)} for i in range(d)] for i in range(d): c.assign(c_var[i][d2 + 2], p[i][i]) for j in range(d2, i + 1, -2): c.l_sum(t[i][j][0], (r[i][j], p[i][j])) c.l_sum(t[i][j][1], (t[i][j][0], p[j][i])) c.l_sum(t[i][j][2], (t[i][j][1], r2[j - 1])) c.l_sum(t[i][j][3], (t[i][j][2], p[i][j - 1])) c.l_sum(t[i][j][4], (t[i][j][3], p[j - 1][i])) c.l_sum(c_var[i][j], (c_var[i][j + 2], t[i][j][4])) if (i - d2) % 2 != 0: t[i][i + 1] = [c.var(f't_{i}_{i+1}_0'), c.var(f't_{i}_{i+1}_1')] c_var[i][i + 1] = c.var(f'c_{i}_{i+1}') c.l_sum(t[i][i + 1][0], (r[i][i + 1], p[i][i + 1])) c.l_sum(t[i][i + 1][1], (t[i][i + 1][0], p[i + 1][i])) c.l_sum(c_var[i][i + 1], (c_var[i][i + 3], t[i][i + 1][1])) if i % 2 == 1: c.l_sum(z[i], (c_var[i][i + 1], r2[i])) else: c.assign(z[i], c_var[i][i + 1]) else: for j in range(i - 1, -1, -1): c_var[i][j + 2] = c.var(f'c_{i}_{j+2}') c.l_sum(c_var[i][j + 2], (c_var[i][j + 3], r[j][i])) c.assign(z[i], c_var[i][2]) return c
def pinic(d, mat_gen, tmp_sums, strong_bij=False): c = circuit_model.Circuit() x, y, z, shx, shy, shz = mul_preamble(d, c, strong_bij=False, x_kind='intermediate', x_name='x2') shx2 = [c.var(f'x_{i}', kind='input') for i in range(d)] if strong_bij: for sx, sy in zip(shx2, shy): c.bij(sx, sy) x2 = c.var('x', kind='property') c.bij(x2, x) refs_gen.bat_ref(c, shx2, shx) if tmp_sums: c.p_sum(x, shx2) bat_mul_inner(d, mat_gen, tmp_sums, c, x, y, z, shx, shy, shz) return c
def pini1(d, strong_bij=False): c = circuit_model.Circuit() sx, sy, sz, x, y, z = mul_preamble(d, c, strong_bij) # randoms & temps in matrix r = [{ j: c.var(f'r_{i}_{j}', kind='random' if j < i else 'intermediate') for j in range(d) if j != i } for i in range(d)] for i in range(d): for j in range(i): c.assign(r[j][i], r[i][j]) s = [{j: c.var(f's_{i}_{j}') for j in range(d) if j != i} for i in range(d)] p = [{ j: [c.var(f'p_{i}_{j}_{k}') for k in range(2)] for j in range(d) if j != i } for i in range(d)] t = [{j: c.var(f't_{i}_{j}') for j in range(d)} for i in range(d)] for i in range(d): c.l_prod(t[i][i], (x[i], y[i])) # not(x_i) nxi = c.var(f'nxi_{i}') c.l_sum(nxi, (x[i], )) for j in range(d): if j != i: xi, yj = x[i], y[j] c.l_sum(s[i][j], (yj, r[i][j])) c.l_prod(p[i][j][0], (nxi, r[i][j])) c.l_prod(p[i][j][1], (xi, s[i][j])) c.l_sum(t[i][j], (p[i][j][0], p[i][j][1])) c_var = [[c.var(f'c_{i}_{j}') for j in range(d)] for i in range(d)] for i in range(d): c.assign(c_var[i][0], t[i][0]) for j in range(1, d): c.l_sum(c_var[i][j], (c_var[i][j - 1], t[i][j])) c.assign(z[i], c_var[i][d - 1]) return c
def bat_mul(d, mat_gen, tmp_sums, strong_bij=False): c = circuit_model.Circuit() sx, sy, sz, x, y, z = mul_preamble(d, c, strong_bij) bat_mul_inner(d, mat_gen, tmp_sums, c, sx, sy, sz, x, y, z) return c
def pini2(d, mat_gen, tmp_sums, strong_bij=False): d2 = d - 1 c = circuit_model.Circuit() sx, sy, sz, x, y, z = mul_preamble(d, c, strong_bij) if tmp_sums: var_sums = (sx, sy) else: var_sums = None ref_prods = mat_gen(c, x, y, var_sums=var_sums) # product matrix s1 = [c.var(f's1_{i}', kind='random') for i in range(d)] s = [{j: c.var(f's_{i}_{j}') for j in range(i + 1, d)} for i in range(d)] u = [{ j: [c.var(f's_{i}_{j}_{k}') for k in range(2)] for j in range(i + 1, d) } for i in range(d)] p = [{ j: [c.var(f's_{i}_{j}_{k}') for k in range(4)] for j in range(i + 1, d) } for i in range(d)] for i in range(d): for j in range(i + 1, d): c.l_sum(s[i][j], (s1[i], s1[j])) xi, yj = ref_prods[i][j] xj, yi = ref_prods[j][i] c.l_sum(u[i][j][0], (yj, s[i][j])) c.l_sum(u[i][j][1], (xj, s[i][j])) c.l_prod(p[i][j][0], (xi, s[i][j])) c.l_prod(p[i][j][1], (xi, u[i][j][0])) c.l_prod(p[i][j][2], (yi, s[i][j])) c.l_prod(p[i][j][3], (yi, u[i][j][1])) # randoms & temps in matrix & compression r = [{ d2 - j: c.var(f'r_{i}_{j}', kind='random') for j in range(0, d2 - i, 2) } for i in range(d)] r2 = {j: c.var(f'r2_{j}', kind='random') for j in range(d2 - 1, 0, -2)} t = [{ j: [c.var(f't_{i}_{j}_{k}') for k in range(9)] for j in range(d2, i + 1, -2) } for i in range(d)] c_var = [{j: c.var(f'c_{i}_{j}') for j in range(d2 + 2, i + 1, -2)} for i in range(d)] for i in range(d): pi = c.var(f'p_{i}_{i}') c.l_prod(pi, ref_prods[i][i]) c.assign(c_var[i][d2 + 2], pi) for j in range(d2, i + 1, -2): c.l_sum(t[i][j][0], (r[i][j], p[i][j][0])) c.l_sum(t[i][j][1], (t[i][j][0], p[i][j][1])) c.l_sum(t[i][j][2], (t[i][j][1], p[i][j][2])) c.l_sum(t[i][j][3], (t[i][j][2], p[i][j][3])) c.l_sum(t[i][j][4], (t[i][j][3], r2[j - 1])) c.l_sum(t[i][j][5], (t[i][j][4], p[i][j - 1][0])) c.l_sum(t[i][j][6], (t[i][j][5], p[i][j - 1][1])) c.l_sum(t[i][j][7], (t[i][j][6], p[i][j - 1][2])) c.l_sum(t[i][j][8], (t[i][j][7], p[i][j - 1][3])) c.l_sum(c_var[i][j], (c_var[i][j + 2], t[i][j][8])) if (i - d2) % 2 != 0: t[i][i + 1] = [c.var(f't_{i}_{i+1}_{k}') for k in range(4)] c_var[i][i + 1] = c.var(f'c_{i}_{i+1}') c.l_sum(t[i][i + 1][0], (r[i][i + 1], p[i][i + 1][0])) c.l_sum(t[i][i + 1][1], (t[i][i + 1][0], p[i][i + 1][1])) c.l_sum(t[i][i + 1][2], (t[i][i + 1][1], p[i][i + 1][2])) c.l_sum(t[i][i + 1][3], (t[i][i + 1][2], p[i][i + 1][3])) c.l_sum(c_var[i][i + 1], (c_var[i][i + 3], t[i][i + 1][3])) if i % 2 == 1: c.l_sum(z[i], (c_var[i][i + 1], r2[i])) else: c.assign(z[i], c_var[i][i + 1]) else: for j in range(i - 1, -1, -1): c_var[i][j + 2] = c.var(f'c_{i}_{j+2}') c.l_sum(c_var[i][j + 2], (c_var[i][j + 3], r[j][i])) c.assign(z[i], c_var[i][2]) return c
def test_refresh(d, ref=simple_ref): circuit = circuit_model.Circuit() var_inputs = [circuit.var(f'x_{i}', kind='input') for i in range(d)] var_outputs = [circuit.var(f'y_{i}', kind='output') for i in range(d)] ref(circuit=circuit, inputs=var_inputs, outputs=var_outputs) g = circuit_model.CompGraph(circuit) x = gen_random_input(d) inputs = {f'x_{i}': v for i, v in enumerate(x)} res, _ = g.compute(inputs) y = [ v for var, v in res.items() if circuit.vars[var].name.startswith('y_') ] assert (sum(x) % 2) == (sum(y) % 2) if __name__ == '__main__': import sys try: d = int(sys.argv[1]) except IndexError: d = 3 for ref_name, ref_f in refs.items(): #for ref_name, ref_f in (): print(f'---- {ref_name}, d={d} ----') circuit = circuit_model.Circuit() var_inputs = [circuit.var(f'x_{i}', kind='input') for i in range(d)] ref_f(circuit, var_inputs, out_name='y') print(circuit) for _ in range(100): test_refresh(d, ref_f)