def test_misc(self): secint = mpc.SecInt() secfxp = mpc.SecFxp() secfld = mpc.SecFld() for secnum in (secint, secfxp, secfld): self.assertEqual(type(mpc.run(mpc.output(secnum(0), raw=True))), secnum.field) self.assertEqual(mpc.run(mpc.output(mpc._reshare([secnum(0)]))), [0]) self.assertEqual(mpc.run(mpc.output(mpc.all(secnum(1) for _ in range(5)))), True) self.assertEqual(mpc.run(mpc.output(mpc.all([secnum(1), secnum(1), secnum(0)]))), False) self.assertEqual(mpc.run(mpc.output(mpc.any(secnum(0) for _ in range(5)))), False) self.assertEqual(mpc.run(mpc.output(mpc.any([secnum(0), secnum(1), secnum(1)]))), True) self.assertEqual(mpc.run(mpc.output(mpc.sum([secnum(1)], start=1))), 2) self.assertEqual(mpc.run(mpc.output(mpc.prod([secnum(1)], start=1))), 1) self.assertEqual(mpc.run(mpc.output(mpc.sum([secnum(1)], start=secnum(1)))), 2) self.assertEqual(mpc.run(mpc.output(mpc.min(secint(i) for i in range(-1, 2, 1)))), -1) self.assertEqual(mpc.run(mpc.output(mpc.argmin(secint(i) for i in range(-1, 2, 1))[0])), 0) self.assertEqual(mpc.run(mpc.output(mpc.max(secfxp(i) for i in range(-1, 2, 1)))), 1) self.assertEqual(mpc.run(mpc.output(mpc.argmax(secfxp(i) for i in range(-1, 2, 1))[0])), 2) self.assertEqual(mpc.run(mpc.output(list(mpc.min_max(map(secfxp, range(5)))))), [0, 4]) x = (secint(i) for i in range(-3, 3)) s = [0, -1, 1, -2, 2, -3] self.assertEqual(mpc.run(mpc.output(mpc.sorted(x, key=lambda a: a*(2*a+1)))), s) x = (secfxp(i) for i in range(5)) self.assertEqual(mpc.run(mpc.output(mpc.sorted(x, reverse=True))), [4, 3, 2, 1, 0]) self.assertEqual(mpc.run(mpc.output(mpc.sum(map(secint, range(5))))), 10) self.assertEqual(mpc.run(mpc.output(mpc.sum([secfxp(2.75)], start=3.125))), 5.875) self.assertEqual(int(mpc.run(mpc.output(mpc.prod(map(secfxp, range(1, 5)))))), 24) self.assertEqual(int(mpc.run(mpc.output(mpc.prod([secfxp(1.414214)]*4)))), 4)
def maxpool(x): logging.info('- - - - - - - - maxpool - - - - - - -') # maxpooling 2 * 2 squares in images of size m * n with stride 2 k, r, m, n = dim(x) Y = [[[[mpc.max(y[i][j], y[i][j+1], y[i+1][j], y[i+1][j+1]) for j in range(0, n, 2)] for i in range(0, m, 2)] for y in z] for z in x] return np.array(Y)
def test_misc(self): secint = mpc.SecInt() secfxp = mpc.SecFxp() secfld = mpc.SecFld() for secnum in (secint, secfxp, secfld): self.assertEqual(mpc.run(mpc.output(mpc._reshare([secnum(0)]))), [0]) self.assertEqual( mpc.run(mpc.output(mpc.all(secnum(1) for _ in range(5)))), True) self.assertEqual( mpc.run(mpc.output(mpc.all([secnum(1), secnum(1), secnum(0)]))), False) self.assertEqual( mpc.run(mpc.output(mpc.any(secnum(0) for _ in range(5)))), False) self.assertEqual( mpc.run(mpc.output(mpc.any([secnum(0), secnum(1), secnum(1)]))), True) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=1))), 2) self.assertEqual( mpc.run(mpc.output(mpc.prod([secnum(1)], start=1))), 1) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=secnum(1)))), 2) self.assertEqual( mpc.run(mpc.output(mpc.min(secint(i) for i in range(-1, 2, 1)))), -1) self.assertEqual( mpc.run(mpc.output(mpc.max(secfxp(i) for i in range(-1, 2, 1)))), 1) self.assertEqual( mpc.run(mpc.output(list(mpc.min_max(map(secfxp, range(5)))))), [0, 4]) self.assertEqual(mpc.run(mpc.output(mpc.sum(map(secint, range(5))))), 10) self.assertEqual( mpc.run(mpc.output(mpc.sum([secfxp(2.72)], start=3.14))), 5.86) self.assertEqual( int(mpc.run(mpc.output(mpc.prod(map(secfxp, range(1, 5)))))), 24) self.assertEqual( int(mpc.run(mpc.output(mpc.prod([secfxp(1.414214)] * 4)))), 4)
def test_misc(self): secint = mpc.SecInt() secfxp = mpc.SecFxp() secfld = mpc.SecFld() for secnum in (secint, secfxp, secfld): self.assertEqual(type(mpc.run(mpc.output(secnum(0), raw=True))), secnum.field) self.assertEqual(mpc.run(mpc.output(mpc._reshare([secnum(0)]))), [0]) self.assertEqual( mpc.run(mpc.output(mpc.all(secnum(1) for _ in range(5)))), True) self.assertEqual( mpc.run(mpc.output(mpc.all([secnum(1), secnum(1), secnum(0)]))), False) self.assertEqual( mpc.run(mpc.output(mpc.any(secnum(0) for _ in range(5)))), False) self.assertEqual( mpc.run(mpc.output(mpc.any([secnum(0), secnum(1), secnum(1)]))), True) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=1))), 2) self.assertEqual( mpc.run(mpc.output(mpc.prod([secnum(1)], start=1))), 1) self.assertEqual( mpc.run(mpc.output(mpc.sum([secnum(1)], start=secnum(1)))), 2) self.assertEqual( mpc.run(mpc.output(mpc.find([secnum(1)], 0, e=-1))), -1) self.assertEqual(mpc.run(mpc.output(mpc.find([secnum(1)], 1))), 0) self.assertEqual( mpc.run(mpc.output(mpc.find([secnum(1)], 1, f=lambda i: i))), 0) self.assertEqual( mpc.run(mpc.output(mpc.min(secint(i) for i in range(-1, 2, 1)))), -1) self.assertEqual( mpc.run( mpc.output(mpc.argmin(secint(i) for i in range(-1, 2, 1))[0])), 0) self.assertEqual( mpc.run(mpc.output(mpc.max(secfxp(i) for i in range(-1, 2, 1)))), 1) self.assertEqual( mpc.run( mpc.output(mpc.argmax(secfxp(i) for i in range(-1, 2, 1))[0])), 2) self.assertEqual( mpc.run(mpc.output(list(mpc.min_max(map(secfxp, range(5)))))), [0, 4]) x = (secint(i) for i in range(-3, 3)) s = [0, -1, 1, -2, 2, -3] self.assertEqual( mpc.run(mpc.output(mpc.sorted(x, key=lambda a: a * (2 * a + 1)))), s) x = (secfxp(i) for i in range(5)) self.assertEqual(mpc.run(mpc.output(mpc.sorted(x, reverse=True))), [4, 3, 2, 1, 0]) self.assertEqual(mpc.run(mpc.output(mpc.sum(map(secint, range(5))))), 10) self.assertEqual( mpc.run(mpc.output(mpc.sum([secfxp(2.75)], start=3.125))), 5.875) self.assertEqual( int(mpc.run(mpc.output(mpc.prod(map(secfxp, range(1, 5)))))), 24) self.assertEqual( int(mpc.run(mpc.output(mpc.prod([secfxp(1.414214)] * 4)))), 4) self.assertEqual(mpc.find([], 0), 0) self.assertEqual(mpc.find([], 0, e=None), (1, 0)) self.assertEqual( mpc.run(mpc.output(list(mpc.find([secfld(1)], 1, e=None)))), [0, 0]) self.assertEqual( mpc.run(mpc.output(mpc.find([secfld(2)], 2, bits=False))), 0) x = [secint(i) for i in range(5)] f = lambda i: [i**2, 3**i] self.assertEqual(mpc.run(mpc.output(mpc.find(x, 2, bits=False, f=f))), [4, 9]) cs_f = lambda b, i: [b * (2 * i + 1) + i**2, (b * 2 + 1) * 3**i] self.assertEqual( mpc.run(mpc.output(mpc.find(x, 2, bits=False, cs_f=cs_f))), [4, 9])
def test_secfxp(self): secfxp = mpc.SecFxp() self.assertEqual( mpc.run(mpc.output(mpc.input(secfxp(7.75), senders=0))), 7.75) c = mpc.to_bits(secfxp(0), 0) # mpc.output() only works for nonempty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(secfxp(0)))) self.assertEqual(c, [0.0] * 32) c = mpc.run(mpc.output(mpc.to_bits(secfxp(1)))) self.assertEqual(c, [0.0] * 16 + [1.0] + [0.0] * 15) c = mpc.run(mpc.output(mpc.to_bits(secfxp(0.5)))) self.assertEqual(c, [0.0] * 15 + [1.0] + [0.0] * 16) c = mpc.run(mpc.output(mpc.to_bits(secfxp(8113)))) self.assertEqual(c, [0.0] * 16 + [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(2**15 - 1)))) self.assertEqual(c, [0] * 16 + [1] * 15 + [0]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(-1)))) self.assertEqual(c, [0] * 16 + [1] * 16) c = mpc.run(mpc.output(mpc.to_bits(secfxp(-2**15)))) self.assertEqual(c, [0] * 31 + [1]) for f in [8, 16, 32, 64]: secfxp = mpc.SecFxp(2 * f) c = mpc.run(mpc.output(secfxp(1) + secfxp(1))) self.assertEqual(c, 2) c = mpc.run(mpc.output(secfxp(2**-f) + secfxp(1))) if f != 64: # NB: 1 + 2**-64 == 1 in Python self.assertEqual(c, 1 + 2**-f) self.assertEqual(mpc.run(mpc.output(secfxp(0.5) * secfxp(2.0))), 1) self.assertEqual(mpc.run(mpc.output(secfxp(2.0) * secfxp(0.5))), 1) c = mpc.run( mpc.output( secfxp(2**(f // 2 - 1) - 0.5) * secfxp(-2**(f // 2) + 0.5))) self.assertEqual(c, -2**(f - 1) + 1.5 * 2**(f // 2 - 1) - 0.25) s = [10.75, -3.375, 0.125, -0.125] self.assertEqual(mpc.run(mpc.output(list(map(secfxp, s)))), s) s = [10.5, -3.25, 0.125, -0.125] a, b, c, d = list(map(secfxp, s)) t = [v * v for v in s] self.assertEqual(mpc.run(mpc.output([a * a, b * b, c * c, d * d])), t) x = [a, b, c, d] self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x))), t) self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x[:]))), t) t = sum(t) self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x))), t) self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x[:]))), t) self.assertEqual( mpc.run(mpc.output(mpc.matrix_prod([x], [x], True)[0])), [t]) u = mpc.unit_vector(secfxp(3), 4) self.assertEqual( mpc.run(mpc.output(mpc.matrix_prod([x], [u], True)[0])), [s[3]]) self.assertEqual( mpc.run(mpc.output(mpc.matrix_prod([u], [x], True)[0])), [s[3]]) self.assertEqual( mpc.run(mpc.output(mpc.gauss([[a]], b, [a], [b])[0])), [0]) t = [_ for a, b, c, d in [s] for _ in [a + b, a * b, a - b]] self.assertEqual(mpc.run(mpc.output([a + b, a * b, a - b])), t) t = [ _ for a, b, c, d in [s] for _ in [(a + b)**2, (a + b)**2 + 3 * c] ] self.assertEqual( mpc.run(mpc.output([(a + b)**2, (a + b)**2 + 3 * c])), t) t = [_ for a, b, c, d in [s] for _ in [a < b, b < c, c < d]] self.assertEqual(mpc.run(mpc.output([a < b, b < c, c < d])), t) t = s[0] < s[1] and s[1] < s[2] self.assertEqual(mpc.run(mpc.output((a < b) & (b < c))), t) t = s[0] < s[1] or s[1] < s[2] self.assertEqual(mpc.run(mpc.output((a < b) | (b < c))), t) t = (int(s[0] < s[1]) ^ int(s[1] < s[2])) self.assertEqual(mpc.run(mpc.output((a < b) ^ (b < c))), t) t = (int(not s[0] < s[1]) ^ int(s[1] < s[2])) self.assertEqual(mpc.run(mpc.output(~(a < b) ^ b < c)), t) t = [s[0] > 1, 10 * s[1] < 5, 10 * s[0] == 5] self.assertEqual( mpc.run(mpc.output([a > 1, 10 * b < 5, 10 * a == 5])), t) s[3] = -0.120 d = secfxp(s[3]) t = s[3] / 0.25 self.assertAlmostEqual(mpc.run(mpc.output(d / 0.25)), t, delta=2**(1 - f)) t = round(s[3] / s[2] + s[0]) self.assertEqual(round(mpc.run(mpc.output(d / c + a))), t) t = ((s[0] + s[1])**2 + 3 * s[2]) / s[2] self.assertAlmostEqual(mpc.run(mpc.output( ((a + b)**2 + 3 * c) / c)), t, delta=2**(8 - f)) t = 1 / s[3] self.assertAlmostEqual(mpc.run(mpc.output(1 / d)), t, delta=2**(6 - f)) t = s[2] / s[3] self.assertAlmostEqual(mpc.run(mpc.output(c / d)), t, delta=2**(3 - f)) t = -s[3] / s[2] self.assertAlmostEqual(mpc.run(mpc.output(-d / c)), t, delta=2**(3 - f)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(+a))), s[0] > 0) self.assertEqual(mpc.run(mpc.output(mpc.sgn(-a))), -(s[0] > 0)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(secfxp(0)))), 0) self.assertEqual(mpc.run(mpc.output(abs(secfxp(-1.5)))), 1.5) self.assertEqual(mpc.run(mpc.output(mpc.min(a, b, c, d))), min(s)) self.assertEqual(mpc.run(mpc.output(mpc.min(a, 0))), min(s[0], 0)) self.assertEqual(mpc.run(mpc.output(mpc.min(0, b))), min(0, s[1])) self.assertEqual(mpc.run(mpc.output(mpc.max(a, b, c, d))), max(s)) self.assertEqual(mpc.run(mpc.output(mpc.max(a, 0))), max(s[0], 0)) self.assertEqual(mpc.run(mpc.output(mpc.max(0, b))), max(0, s[1])) self.assertEqual( mpc.run(mpc.output(list(mpc.min_max(a, b, c, d)))), [min(s), max(s)]) self.assertEqual(mpc.run(mpc.output(mpc.argmin([a, b, c, d])[0])), 1) self.assertEqual( mpc.run(mpc.output(mpc.argmin([a, b], key=operator.neg)[1])), max(s)) self.assertEqual(mpc.run(mpc.output(mpc.argmax([a, b, c, d])[0])), 0) self.assertEqual( mpc.run(mpc.output(mpc.argmax([a, b], key=operator.neg)[1])), min(s)) self.assertEqual(mpc.run(mpc.output(secfxp(5) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secfxp(1) % 2**(1 - f))), 0) self.assertEqual(mpc.run(mpc.output(secfxp(2**-f) % 2**(1 - f))), 2**-f) self.assertEqual( mpc.run(mpc.output(secfxp(2 * 2**-f) % 2**(1 - f))), 0) self.assertEqual(mpc.run(mpc.output(secfxp(1) // 2**(1 - f))), 2**(f - 1)) self.assertEqual(mpc.run(mpc.output(secfxp(27.0) % 7.0)), 6.0) self.assertEqual(mpc.run(mpc.output(secfxp(-27.0) // 7.0)), -4.0) self.assertEqual( mpc.run(mpc.output(list(divmod(secfxp(27.0), 6.0)))), [4.0, 3.0]) self.assertEqual(mpc.run(mpc.output(secfxp(21.5) % 7.5)), 6.5) self.assertEqual(mpc.run(mpc.output(secfxp(-21.5) // 7.5)), -3.0) self.assertEqual( mpc.run(mpc.output(list(divmod(secfxp(21.5), 0.5)))), [43.0, 0.0])
my_sec_noise = secfxp(None) # Secret-share the votes from this party with every other party all_sec_votes = mpc.input(my_sec_votes, senders=list(range(1, M))) # Aggregate the secure votes from all parties total_sec_votes = vector_add_all(all_sec_votes) # Secret-share the noise part from this party with every other party all_sec_noises = mpc.input(my_sec_noise, senders=list(range(1, M))) # Aggregate the secure noises from all parties total_sec_noise = scalar_add_all(all_sec_noises) # Find the secure maximum in the aggregated array of votes sec_max = mpc.max(total_sec_votes) # Add the aggregated noise to this max value noisy_sec_max = sec_max + total_sec_noise # Reveal (=recombine the shares) of this noisy maximum noisy_max = float(mpc.run(mpc.output(noisy_sec_max))) # If it is lower than a threshold, the teachers are not confident enough # Then don't label this sample, and skip to the next one if noisy_max < THRESHOLD: if IS_SERVER: print(f'[*] Sample {sample_id}: NULL') LABELS[sample_id] = -1 elapsed = time.time() - last_time
async def main(): parser = argparse.ArgumentParser() parser.add_argument( '-i', '--dataset', type=int, metavar='I', help=('dataset 0=btrial(default) 1=waltons 2=aml 3=lung 4=dd' ' 5=stanford_heart_transplants 6=kidney_transplant')) parser.add_argument('-s', '--stride', type=int, metavar='S', help='interval length for aggregated events') parser.add_argument('-a', '--accuracy', type=int, metavar='A', help='number of fractional bits') parser.add_argument('--collapse', action='store_true', default=False, help='days->weeks->month->years') parser.add_argument('--print-tables', action='store_true', default=False, help='print survival tables') parser.add_argument('--plot-curves', action='store_true', default=False, help='plot survival curves') parser.set_defaults(dataset=0) args = parser.parse_args() settings = [('btrial.csv', 12, 28, 'months', 'time', 'death', 'im', ('-ve immunohistochemical response', '+ve immunohistochemical response'), (1, 2)), ('waltons', 10, 32, 'days', 'T', 'E', 'group', ('miR-137', 'control'), ('miR-137', 'control')), ('aml.csv', 16, 32, 'weeks', 'time', 'cens', 'group', ('Maintained', 'Not maintained'), (1, 2)), ('lung', 73, 32, 'days', 'time', 'status', 'sex', ('Male', 'Female'), (1, 2)), ('dd', 3, 48, 'years', 'duration', 'observed', 'democracy', ('Democracy', 'Non-democracy'), ('Democracy', 'Non-democracy')), ('stanford_heart_transplants', 90, 32, 'days', 'time', 'event', 'transplant', ('no transplant', 'transplant'), (0, 1)), ('kidney_transplant', 180, 40, 'days', 'time', 'death', 'sex', ('male', 'female'), (1, 0))] (name, stride, accuracy, unit_of_time, times, events, groups, (label1, label2), (value1, value2)) = settings[args.dataset] if name.endswith('.csv'): df = pd.read_csv(os.path.join('data', 'surv', name)) name = name[:-4] else: df = eval('lifelines.datasets.load_' + name)() if name == 'lung': df['status'] = df['status'] - 1 # 1-2 -> 0-1 = censored-death elif name == 'stanford_heart_transplants': df = df[(df['transplant'] == 1) | ~df['id'].isin(set(df[df['transplant'] == 1]['id']))] df['time'] = round(df['stop'] - df['start'] + 0.5) elif name == 'kidney_transplant': df['sex'] = df['black_male'] + df['white_male'] if args.stride: stride = args.stride if args.collapse: if unit_of_time == 'days': unit_of_time = 'weeks' df[times] = (df[times] + 6) // 7 # convert days to weeks stride //= 7 elif unit_of_time == 'weeks': unit_of_time = 'months' df[times] = (df[times] + 3) // 4 # convert weeks to months stride //= 4 elif unit_of_time == 'months': unit_of_time = 'years' df[times] = (df[times] + 11) // 12 # convert months to years stride //= 12 if args.accuracy: accuracy = args.accuracy secfxp = mpc.SecFxp(2 * accuracy) print(f'Using secure fixed-point numbers: {secfxp.__name__}') maxT_clear = int(df[times].max()) m = len(mpc.parties) print(f'Dataset: {name}, with {m}-party split,' f' time 1 to {maxT_clear} (stride {stride}) {unit_of_time}') logging.info('Logrank test on all events in the clear.') T, E = df[times], df[events] ix = df[groups] == value1 results = lifelines.statistics.logrank_test(T[ix], T[~ix], E[ix], E[~ix]) print(f'Chi2={results.test_statistic:.6f}, p={results.p_value:.6f}' ' for all events in the clear') await mpc.start() df = df[mpc.pid::m] # simple partition of dataset between m parties my_maxT = int(df[times].max()) maxT = int(await mpc.output(mpc.max(mpc.input(secfxp(my_maxT))))) assert maxT == maxT_clear logging.info('Logrank test on own events in the clear.') T, E = df[times], df[events] ix = df[groups] == value1 T1, T2, E1, E2 = T[ix], T[~ix], E[ix], E[~ix] results = lifelines.statistics.logrank_test(T1, T2, E1, E2) print(f'Chi2={results.test_statistic:.6f}, p={results.p_value:.6f}' ' for own events in the clear') if args.print_tables or args.plot_curves: plt.figure(1) title = f'Party {mpc.pid}: {name} Survival - individual events' kmf1, kmf2 = fit_plot(T1, T2, E1, E2, title, unit_of_time, label1, label2) if args.print_tables: print(kmf1.event_table) print(kmf2.event_table) # expand to timeline 1..maxT and add all input data homomorphically per group d1, n1 = events_to_table(maxT, T1, E1) d2, n2 = events_to_table(maxT, T2, E2) d1, n1, d2, n2 = (reduce(mpc.vector_add, mpc.input(list(map(secfxp, _)))) for _ in (d1, n1, d2, n2)) agg_d1, agg_n1 = aggregate(d1, n1, stride) agg_d2, agg_n2 = aggregate(d2, n2, stride) agg_d1, agg_n1, agg_d2, agg_n2 = [ list(map(int, await mpc.output(_))) for _ in (agg_d1, agg_n1, agg_d2, agg_n2) ] T1, E1 = events_from_table(agg_d1, agg_n1) T2, E2 = events_from_table(agg_d2, agg_n2) logging.info('Logrank test on aggregated events in the clear.') results = lifelines.statistics.logrank_test(T1, T2, E1, E2) print(f'Chi2={results.test_statistic:.6f}, p={results.p_value:.6f}' ' for aggregated events in the clear') if args.print_tables or args.plot_curves: plt.figure(2) title = f'Party {mpc.pid}: {name} Survival - aggregated by {stride} {unit_of_time}' kmf1, kmf2 = fit_plot([t * stride for t in T1], [t * stride for t in T2], E1, E2, title, unit_of_time, label1, label2) if args.print_tables: print(kmf1.event_table) print(kmf2.event_table) if args.plot_curves: plt.show() logging.info('Optimized secure logrank test on all individual events.') results = await agg_logrank_test(secfxp, d1, d2, n1, n2, agg_d1, agg_d2, stride) print(f'Chi2={results.test_statistic:.6f}, p={results.p_value:.6f}' ' for all events secure, exploiting aggregates') logging.info(f'Secure logrank test for all {maxT} time moments.') results = await logrank_test(secfxp, d1, d2, n1, n2) print(f'Chi2={results.test_statistic:.6f}, p={results.p_value:.6f}' f' for all {maxT} time moments secure') await mpc.shutdown()
def test_secfxp(self): secfxp = mpc.SecFxp() c = mpc.to_bits(secfxp(0), 0) # mpc.output() only works for non-empty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(secfxp(0)))) self.assertEqual(c, [0.0] * 32) c = mpc.run(mpc.output(mpc.to_bits(secfxp(1)))) self.assertEqual(c, [0.0] * 16 + [1.0] + [0.0] * 15) c = mpc.run(mpc.output(mpc.to_bits(secfxp(8113)))) self.assertEqual(c, [0.0] * 16 + [ float(b) for b in [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0] ]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(2**15 - 1)))) self.assertEqual(c, [float(b) for b in [0] * 16 + [1] * 15 + [0]]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(-1)))) self.assertEqual(c, [float(b) for b in [0] * 16 + [1] * 16]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(-2**15)))) self.assertEqual(c, [float(b) for b in [0] * 31 + [1]]) for f in [8, 16, 32, 64]: secfxp = mpc.SecFxp(2 * f) d = mpc.run(mpc.output(secfxp(1) + secfxp(1))) self.assertEqual(d.frac_length, f) self.assertEqual(d, 2) d = mpc.run(mpc.output(secfxp(2**-f) + secfxp(1))) f == 64 or self.assertEqual( d, 1 + 2**-f) # NB: 1 + 2**-64 == 1 in Python d = mpc.run(mpc.output(secfxp(0.5) * secfxp(2.0))) self.assertEqual(d, 1) d = mpc.run(mpc.output(secfxp(2.0) * secfxp(0.5))) self.assertEqual(d, 1) s = [10.7, -3.4, 0.1, -0.11] self.assertEqual(mpc.run(mpc.output(list(map(secfxp, s)))), s) s = [10.5, -3.25, 0.125, -0.125] x, y, z, w = list(map(secfxp, s)) s2 = [v * v for v in s] self.assertEqual(mpc.run(mpc.output([x * x, y * y, z * z, w * w])), s2) self.assertEqual( mpc.run(mpc.output(mpc.schur_prod([x, y, z, w], [x, y, z, w]))), s2) s2 = [_ for x, y, z, w in [s] for _ in [x + y, x * y, x - y]] self.assertEqual(mpc.run(mpc.output([x + y, x * y, x - y])), s2) s2 = [ _ for x, y, z, w in [s] for _ in [(x + y)**2, (x + y)**2 + 3 * z] ] self.assertEqual( mpc.run(mpc.output([(x + y)**2, (x + y)**2 + 3 * z])), s2) s2 = [int(_) for x, y, z, w in [s] for _ in [x < y, y < z, z < w]] self.assertEqual(mpc.run(mpc.output([x < y, y < z, z < w])), s2) s2 = int(s[0] < s[1] and s[1] < s[2]) self.assertEqual(mpc.run(mpc.output((x < y) & (y < z))), s2) s2 = int(s[0] < s[1] or s[1] < s[2]) self.assertEqual(mpc.run(mpc.output((x < y) | (y < z))), s2) s2 = (int(s[0] < s[1]) ^ int(s[1] < s[2])) self.assertEqual(mpc.run(mpc.output((x < y) ^ (y < z))), s2) s2 = (int(not s[0] < s[1]) ^ int(s[1] < s[2])) self.assertEqual(mpc.run(mpc.output(~(x < y) ^ y < z)), s2) s2 = [int(s[0] < 1), int(10 * s[1] < 5), int(10 * s[0] == 5)] self.assertEqual( mpc.run(mpc.output([x < 1, 10 * y < 5, 10 * x == 5])), s2) s[3] = -0.120 w = secfxp(s[3]) for _ in range(3): s2 = s[3] / s[2] + s[0] self.assertAlmostEqual(mpc.run(mpc.output(w / z + x)).signed(), s2, delta=1) ss2 = round(s2 * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(w / z + x)), ss2, delta=1) s2 = ((s[0] + s[1])**2 + 3 * s[2]) / s[2] self.assertAlmostEqual(mpc.run( mpc.output(((x + y)**2 + 3 * z) / z)).signed(), s2, delta=2) s2 = 1 / s[3] self.assertAlmostEqual((mpc.run(mpc.output(1 / w))).signed(), s2, delta=1) s2 = s[2] / s[3] self.assertAlmostEqual(mpc.run(mpc.output(z / w)).signed(), s2, delta=1) s2 = -s[3] / s[2] ss2 = round(s2 * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(-w / z)), ss2, delta=1) s2 = s[2] / s[3] ss2 = round(s2 * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(w / z)), ss2, delta=1) self.assertEqual(mpc.run(mpc.output(mpc.sgn(x))), int(s[0] > 0)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(-x))), -int(s[0] > 0)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(secfxp(0)))), 0) self.assertEqual(mpc.run(mpc.output(mpc.min(x, y, w, z))), min(s)) self.assertEqual(mpc.run(mpc.output(mpc.min(x, 0))), min(s[0], 0)) self.assertEqual(mpc.run(mpc.output(mpc.min(0, y))), min(0, s[1])) self.assertEqual(mpc.run(mpc.output(mpc.max(x, y, w, z))), max(s)) self.assertEqual(mpc.run(mpc.output(mpc.max(x, 0))), max(s[0], 0)) self.assertEqual(mpc.run(mpc.output(mpc.max(0, y))), max(0, s[1])) self.assertEqual(mpc.run(mpc.output(secfxp(5) % 2)), 1 * (2**f)) self.assertEqual(mpc.run(mpc.output(secfxp(1) % 2**(1 - f))), 0 * (2**f)) self.assertEqual( mpc.run(mpc.output(secfxp(1 / 2**f) % 2**(1 - f))), 1) self.assertEqual( mpc.run(mpc.output(secfxp(2 / 2**f) % 2**(1 - f))), 0) self.assertEqual(mpc.run(mpc.output(secfxp(1) // 2**(1 - f))), 2**(f - 1)) self.assertEqual(mpc.run(mpc.output(secfxp(27.0) % 7.0)), 6.0) self.assertEqual(mpc.run(mpc.output(secfxp(-27.0) // 7.0)), -4.0) self.assertEqual( mpc.run(mpc.output(list(divmod(secfxp(27.0), 6.0)))), [4.0, 3.0]) self.assertEqual(mpc.run(mpc.output(secfxp(21.5) % 7.5)), 6.5) self.assertEqual(mpc.run(mpc.output(secfxp(-21.5) // 7.5)), -3.0) self.assertEqual( mpc.run(mpc.output(list(divmod(secfxp(21.5), 0.5)))), [43.0, 0.0])
def test_secfxp(self): secfxp = mpc.SecFxp() c = mpc.to_bits(secfxp(0), 0) # mpc.output() only works for nonempty lists self.assertEqual(c, []) c = mpc.run(mpc.output(mpc.to_bits(secfxp(0)))) self.assertEqual(c, [0.0] * 32) c = mpc.run(mpc.output(mpc.to_bits(secfxp(1)))) self.assertEqual(c, [0.0] * 16 + [1.0] + [0.0] * 15) c = mpc.run(mpc.output(mpc.to_bits(secfxp(0.5)))) self.assertEqual(c, [0.0] * 15 + [1.0] + [0.0] * 16) c = mpc.run(mpc.output(mpc.to_bits(secfxp(8113)))) self.assertEqual(c, [0.0] * 16 + [ float(b) for b in [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0] ]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(2**15 - 1)))) self.assertEqual(c, [float(b) for b in [0] * 16 + [1] * 15 + [0]]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(-1)))) self.assertEqual(c, [float(b) for b in [0] * 16 + [1] * 16]) c = mpc.run(mpc.output(mpc.to_bits(secfxp(-2**15)))) self.assertEqual(c, [float(b) for b in [0] * 31 + [1]]) for f in [8, 16, 32, 64]: secfxp = mpc.SecFxp(2 * f) c = mpc.run(mpc.output(secfxp(1) + secfxp(1))) self.assertEqual(c.frac_length, f) self.assertEqual(c, 2) c = mpc.run(mpc.output(secfxp(2**-f) + secfxp(1))) if f != 64: # NB: 1 + 2**-64 == 1 in Python self.assertEqual(c, 1 + 2**-f) self.assertEqual(mpc.run(mpc.output(secfxp(0.5) * secfxp(2.0))), 1) self.assertEqual(mpc.run(mpc.output(secfxp(2.0) * secfxp(0.5))), 1) s = [10.7, -3.4, 0.1, -0.11] self.assertEqual(mpc.run(mpc.output(list(map(secfxp, s)))), s) s = [10.5, -3.25, 0.125, -0.125] a, b, c, d = list(map(secfxp, s)) t = [v * v for v in s] self.assertEqual(mpc.run(mpc.output([a * a, b * b, c * c, d * d])), t) x = [a, b, c, d] self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x))), t) self.assertEqual(mpc.run(mpc.output(mpc.schur_prod(x, x[:]))), t) t = sum(t) self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x))), t) self.assertEqual(mpc.run(mpc.output(mpc.in_prod(x, x[:]))), t) self.assertEqual( mpc.run(mpc.output(mpc.matrix_prod([x], [x], True)[0])), [t]) t = [_ for a, b, c, d in [s] for _ in [a + b, a * b, a - b]] self.assertEqual(mpc.run(mpc.output([a + b, a * b, a - b])), t) t = [ _ for a, b, c, d in [s] for _ in [(a + b)**2, (a + b)**2 + 3 * c] ] self.assertEqual( mpc.run(mpc.output([(a + b)**2, (a + b)**2 + 3 * c])), t) t = [int(_) for a, b, c, d in [s] for _ in [a < b, b < c, c < d]] self.assertEqual(mpc.run(mpc.output([a < b, b < c, c < d])), t) t = int(s[0] < s[1] and s[1] < s[2]) self.assertEqual(mpc.run(mpc.output((a < b) & (b < c))), t) t = int(s[0] < s[1] or s[1] < s[2]) self.assertEqual(mpc.run(mpc.output((a < b) | (b < c))), t) t = (int(s[0] < s[1]) ^ int(s[1] < s[2])) self.assertEqual(mpc.run(mpc.output((a < b) ^ (b < c))), t) t = (int(not s[0] < s[1]) ^ int(s[1] < s[2])) self.assertEqual(mpc.run(mpc.output(~(a < b) ^ b < c)), t) t = [int(s[0] > 1), int(10 * s[1] < 5), int(10 * s[0] == 5)] self.assertEqual( mpc.run(mpc.output([a > 1, 10 * b < 5, 10 * a == 5])), t) s[3] = -0.120 d = secfxp(s[3]) t = s[3] / 0.25 self.assertAlmostEqual(mpc.run(mpc.output(d / 0.25)).signed(), t, delta=1) t = s[3] / s[2] + s[0] self.assertAlmostEqual(mpc.run(mpc.output(d / c + a)).signed(), t, delta=1) t = round(t * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(d / c + a)), t, delta=1) t = ((s[0] + s[1])**2 + 3 * s[2]) / s[2] self.assertAlmostEqual(mpc.run(mpc.output( ((a + b)**2 + 3 * c) / c)).signed(), t, delta=2) t = 1 / s[3] self.assertAlmostEqual((mpc.run(mpc.output(1 / d))).signed(), t, delta=1) t = s[2] / s[3] self.assertAlmostEqual(mpc.run(mpc.output(c / d)).signed(), t, delta=1) t = -s[3] / s[2] t = round(t * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(-d / c)), t, delta=1) t = s[2] / s[3] t = round(t * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(d / c)), t, delta=1) self.assertEqual(mpc.run(mpc.output(mpc.sgn(+a))), int(s[0] > 0)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(-a))), -int(s[0] > 0)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(secfxp(0)))), 0) self.assertEqual(mpc.run(mpc.output(abs(secfxp(-1.5)))), 1.5) self.assertEqual(mpc.run(mpc.output(mpc.min(a, b, c, d))), min(s)) self.assertEqual(mpc.run(mpc.output(mpc.min(a, 0))), min(s[0], 0)) self.assertEqual(mpc.run(mpc.output(mpc.min(0, b))), min(0, s[1])) self.assertEqual(mpc.run(mpc.output(mpc.max(a, b, c, d))), max(s)) self.assertEqual(mpc.run(mpc.output(mpc.max(a, 0))), max(s[0], 0)) self.assertEqual(mpc.run(mpc.output(mpc.max(0, b))), max(0, s[1])) self.assertEqual( mpc.run(mpc.output(list(mpc.min_max(a, b, c, d)))), [min(s), max(s)]) self.assertEqual(mpc.run(mpc.output(secfxp(5) % 2)), 1) self.assertEqual(mpc.run(mpc.output(secfxp(1) % 2**(1 - f))), 0) self.assertEqual(mpc.run(mpc.output(secfxp(2**-f) % 2**(1 - f))), 2**-f) self.assertEqual( mpc.run(mpc.output(secfxp(2 * 2**-f) % 2**(1 - f))), 0) self.assertEqual(mpc.run(mpc.output(secfxp(1) // 2**(1 - f))), 2**(f - 1)) self.assertEqual(mpc.run(mpc.output(secfxp(27.0) % 7.0)), 6.0) self.assertEqual(mpc.run(mpc.output(secfxp(-27.0) // 7.0)), -4.0) self.assertEqual( mpc.run(mpc.output(list(divmod(secfxp(27.0), 6.0)))), [4.0, 3.0]) self.assertEqual(mpc.run(mpc.output(secfxp(21.5) % 7.5)), 6.5) self.assertEqual(mpc.run(mpc.output(secfxp(-21.5) // 7.5)), -3.0) self.assertEqual( mpc.run(mpc.output(list(divmod(secfxp(21.5), 0.5)))), [43.0, 0.0])
def test_secfxp(self): secfxp = mpc.SecFxp() f = 16 d = mpc.run(mpc.output(secfxp(1) + secfxp(1))) self.assertEqual(d.frac_length, f) self.assertEqual(d, 2 * 2**f) d = mpc.run(mpc.output(secfxp(2**-f) + secfxp(1))) self.assertEqual(d, 1 + 2**f) s = [10.7, -3.4, 0.1, -0.11] ss = [round(v * (1 << f)) for v in s] self.assertEqual(mpc.run(mpc.output(list(map(secfxp, s)))), ss) s = [10.5, -3.25, 0.125, -0.125] x, y, z, w = list(map(secfxp, s)) s2 = [v * v for v in s] ss2 = [round(v * (1 << f)) for v in s2] self.assertEqual(mpc.run(mpc.output([x * x, y * y, z * z, w * w])), ss2) s2 = [s[0] + s[1], s[0] * s[1], s[0] - s[1]] ss2 = [round(v * (1 << f)) for v in s2] self.assertEqual(mpc.run(mpc.output([x + y, x * y, x - y])), ss2) s2 = [(s[0] + s[1])**2, (s[0] + s[1])**2 + 3 * s[2]] ss2 = [round(v * (1 << f)) for v in s2] self.assertEqual(mpc.run(mpc.output([(x + y)**2, (x + y)**2 + 3 * z])), ss2) ss2 = [int(s[i] < s[i + 1]) * (1 << f) for i in range(len(s) - 1)] self.assertEqual(mpc.run(mpc.output([x < y, y < z, z < w])), ss2) ss2 = int(s[0] < s[1] and s[1] < s[2]) * (1 << f) self.assertEqual(mpc.run(mpc.output((x < y) & (y < z))), ss2) ss2 = int(s[0] < s[1] or s[1] < s[2]) * (1 << f) self.assertEqual(mpc.run(mpc.output((x < y) | (y < z))), ss2) ss2 = (int(s[0] < s[1]) ^ int(s[1] < s[2])) * (1 << f) self.assertEqual(mpc.run(mpc.output((x < y) ^ (y < z))), ss2) ss2 = (int(not s[0] < s[1]) ^ int(s[1] < s[2])) * (1 << f) self.assertEqual(mpc.run(mpc.output(~(x < y) ^ y < z)), ss2) s2 = [s[0] < 1, 10 * s[1] < 5, 10 * s[0] == 5] ss2 = [round(v * (1 << f)) for v in s2] self.assertEqual(mpc.run(mpc.output([x < 1, 10 * y < 5, 10 * x == 5])), ss2) s[3] = -0.120 w = secfxp(s[3]) for _ in range(3): s2 = s[3] / s[2] + s[0] self.assertAlmostEqual(mpc.run(mpc.output(w / z + x)).signed(), s2, delta=1) ss2 = round(s2 * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(w / z + x)), ss2, delta=1) s2 = ((s[0] + s[1])**2 + 3 * s[2]) / s[2] self.assertAlmostEqual(mpc.run(mpc.output( ((x + y)**2 + 3 * z) / z)).signed(), s2, delta=2) s2 = 1 / s[3] self.assertAlmostEqual((mpc.run(mpc.output(1 / w))).signed(), s2, delta=1) s2 = s[2] / s[3] self.assertAlmostEqual(mpc.run(mpc.output(z / w)).signed(), s2, delta=1) s2 = -s[3] / s[2] ss2 = round(s2 * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(-w / z)), ss2, delta=1) s2 = s[2] / s[3] ss2 = round(s2 * (1 << f)) self.assertAlmostEqual(mpc.run(mpc.output(w / z)), ss2, delta=1) a = mpc._norm(w) self.assertEqual(mpc.run(mpc.output(mpc.sgn(x))), int(s[0] > 0) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(-x))), -int(s[0] > 0) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.sgn(secfxp(0)))), 0) ss2 = round(min(s) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.min(x, y, w, z))), ss2) ss2 = round(min(s[0], 0) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.min(x, 0))), ss2) ss2 = round(min(0, s[1]) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.min(0, y))), ss2) ss2 = round(max(s) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.max(x, y, w, z))), ss2) ss2 = round(max(s[0], 0) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.max(x, 0))), ss2) ss2 = round(max(0, s[1]) * (1 << f)) self.assertEqual(mpc.run(mpc.output(mpc.max(0, y))), ss2) self.assertEqual(mpc.run(mpc.output(mpc.lsb(secfxp(1)))), 0 * (2**f)) self.assertEqual(mpc.run(mpc.output(mpc.lsb(secfxp(1 / 2**f)))), 1 * (2**f)) self.assertEqual(mpc.run(mpc.output(mpc.lsb(secfxp(2 / 2**f)))), 0 * (2**f))
print('\n' + "=" * 50) mpc.run(mpc.start()) #### START THE MPC ROUNDS OF COMPUTATION #### print("=" * 50, '\n') ############################################################################### all_sec_vi = mpc.input(sec_vi) cmd = 'std' if cmd == 'min': sec_minimum = mpc.min(all_sec_vi) minimum = mpc.run(mpc.output(sec_minimum)) print(minimum) elif cmd == 'max': sec_maximum = mpc.max(all_sec_vi) maximum = mpc.run(mpc.output(sec_maximum)) print(maximum) elif cmd == 'mean': sec_sum = mpc.sum(all_sec_vi) sec_mean = mpc.div(sec_sum, nb_parties) mean = mpc.run(mpc.output(sec_mean)) print(mean) elif cmd == 'std': sec_sum = mpc.sum(all_sec_vi) sec_mean = mpc.div(sec_sum, nb_parties) sec_stddev = mpc.pow(mpc.sub(all_sec_vi[0], sec_mean), 2) for v in all_sec_vi[1:]: sec_stddev = mpc.add(sec_stddev, mpc.pow(mpc.sub(v, sec_mean), 2))