Files
MP-SPDZ/Programs/Source/test_permute.mpc
2024-12-11 15:42:04 +01:00

124 lines
4.0 KiB
Plaintext

def test_case(permutation_sizes, timer_base: int | None = None):
if timer_base is not None:
start_timer(timer_base + 0)
arrays = []
permutations = []
for size in permutation_sizes:
arrays.append(Array.create_from([sint(i) for i in range(size)]))
permutations.append(sint.get_secure_shuffle(size))
if timer_base is not None:
stop_timer(timer_base + 0)
start_timer(timer_base + 1)
for arr, p in zip(arrays, permutations):
arr.secure_permute(p)
if timer_base is not None:
stop_timer(timer_base + 1)
start_timer(timer_base + 2)
for i, arr in enumerate(arrays):
revealed = arr.reveal()
print_ln("%s", revealed)
n_matched = cint(0)
@for_range(len(arr))
def count_matches(i: cint) -> None:
n_matched.update(n_matched + (revealed[i] == i))
@if_(n_matched == len(arr))
def didnt_permute():
print_ln("Permutation potentially didn't work (permutation might have been identity by chance).")
crash()
if timer_base is not None:
stop_timer(timer_base + 2)
start_timer(timer_base + 3)
for arr, p in zip(arrays, permutations):
arr.secure_permute(p, reverse=True)
if timer_base is not None:
stop_timer(timer_base + 3)
start_timer(timer_base + 4)
for i, arr in enumerate(arrays):
revealed = arr.reveal()
print_ln("%s", revealed)
@for_range(len(arr))
def test_is_original(i: cint) -> None:
@if_(revealed[i] != i)
def fail():
print_ln("Failed to invert permutation!")
crash()
if timer_base is not None:
stop_timer(timer_base + 4)
def test_parallel_permutation_equals_sequential_permutation(sizes: list[int], timer_base: int) -> None:
start_timer(timer_base)
permutations = []
for permutation_size in sizes:
permutations.append(sint.get_secure_shuffle(permutation_size))
stop_timer(timer_base)
start_timer(timer_base + 1)
arrs_to_permute_sequentially = []
arrs_to_permute_parallely = []
for permutation_size in sizes:
arrs_to_permute_sequentially.append(Array.create_from([sint(i) for i in range(permutation_size)]))
arrs_to_permute_parallely.append(Array.create_from([sint(i) for i in range(permutation_size)]))
stop_timer(timer_base + 1)
start_timer(timer_base + 2)
for arr, perm in zip(arrs_to_permute_sequentially, permutations):
arr.secure_permute(perm)
break_point()
stop_timer(timer_base + 2)
start_timer(timer_base + 3)
for arr, perm in zip(arrs_to_permute_parallely, permutations):
arr.secure_permute(perm)
stop_timer(timer_base + 3)
start_timer(timer_base + 4)
arrs_to_permute_sequentially = [arr.reveal() for arr in arrs_to_permute_sequentially]
arrs_to_permute_parallely = [arr.reveal() for arr in arrs_to_permute_parallely]
stop_timer(timer_base + 4)
for (arr_seq, arr_par) in zip(arrs_to_permute_sequentially, arrs_to_permute_parallely):
print_ln("Sequential: %s", arr_seq)
print_ln("Parallel: %s", arr_par)
@for_range(len(arr_seq))
def test_equals(i: cint) -> None:
@if_(arr_seq[i] != arr_par[i])
def fail():
print_ln("Sequentially permuted arrays to not match the parallely permuted arrays.")
crash()
def test_allocator():
arr1 = sint.Array(5)
arr2 = sint.Array(10)
arr3 = sint.Array(20)
p1 = sint.get_secure_shuffle(5)
p2 = sint.get_secure_shuffle(10)
p3 = sint.get_secure_shuffle(20)
# Look at the bytecode, arr1 and arr3 should be shuffled in parallel, arr2 afterward.
arr1.secure_permute(p1)
arr2[0] = arr1[0]
arr2.secure_permute(p2)
arr3.secure_permute(p3)
# test_allocator()
test_case([5,10], 10)
test_case([5, 10, 15, 20], 20)
test_case([4,8,16], 30)
test_case([5], 40)
test_parallel_permutation_equals_sequential_permutation([5,10],50)