123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- #
- # Copyright 2019 The FATE Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #
- #
- # Copyright 2019 The FATE Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #
- import random
- import unittest
- import uuid
- from concurrent.futures import ProcessPoolExecutor, as_completed
- import numpy as np
- from federatedml.secureprotol.spdz import SPDZ
- from federatedml.secureprotol.spdz.tensor.fixedpoint_numpy import FixedPointTensor
- from federatedml.transfer_variable.transfer_class.secret_share_transfer_variable import SecretShareTransferVariable
- NUM_HOSTS = 1
- EPS = 0.001
- def session_init(job_id, idx):
- from fate_arch import session
- role = "guest" if idx < 1 else "host"
- party_id = 9999 + idx if idx < 1 else 10000 + (idx - 1)
- role_parties = {
- "host": [
- 10000 + i for i in range(NUM_HOSTS)
- ],
- "guest": [
- 9999 + i for i in range(1)
- ]
- }
- sess = session.init(job_id)
- sess.init_federation(job_id, dict(local=dict(role=role, party_id=party_id), role=role_parties))
- return sess.parties.local_party(), sess.parties.all_parties()
- def submit(func, *args, **kwargs):
- with ProcessPoolExecutor() as pool:
- num = NUM_HOSTS + 1
- result = [None] * num
- futures = {}
- for _idx in range(num):
- kv = kwargs.copy()
- kv["idx"] = _idx
- futures[pool.submit(func, *args, **kv)] = _idx
- for future in as_completed(futures):
- result[futures[future]] = future.result()
- return result
- def create_and_get(job_id, idx, data):
- _, all_parties = session_init(job_id, idx)
- with SPDZ():
- if idx == 0:
- x = FixedPointTensor.from_source("x", data)
- else:
- x = FixedPointTensor.from_source("x", all_parties[0])
- return x.get()
- def add_and_sub(job_id, idx, data_list):
- _, all_parties = session_init(job_id, idx)
- with SPDZ():
- if idx == 0:
- x = FixedPointTensor.from_source("x", data_list[0])
- y = FixedPointTensor.from_source("y", all_parties[1])
- else:
- x = FixedPointTensor.from_source("x", all_parties[0])
- y = FixedPointTensor.from_source("y", data_list[1])
- a = (x + y).get()
- b = (x - y).get()
- return a, b
- def add_and_sub_plaintext(job_id, idx, data_list):
- _, all_parties = session_init(job_id, idx)
- with SPDZ():
- if idx == 0:
- x = FixedPointTensor.from_source("x", data_list[0])
- else:
- x = FixedPointTensor.from_source("x", all_parties[0])
- y = data_list[1]
- a = (x + y).get()
- a1 = (y + x).get()
- b = (x - y).get()
- b1 = (y - x).get()
- return a, a1, b, b1
- def mul_plaintext(job_id, idx, data_list):
- _, all_parties = session_init(job_id, idx)
- with SPDZ():
- if idx == 0:
- x = FixedPointTensor.from_source("x", data_list[0])
- else:
- x = FixedPointTensor.from_source("x", all_parties[0])
- y = data_list[1]
- return (x * y).get(), (y * x).get()
- def mat_mul(job_id, idx, data_list):
- _, all_parties = session_init(job_id, idx)
- with SPDZ():
- if idx == 0:
- x = FixedPointTensor.from_source("x", data_list[0])
- y = FixedPointTensor.from_source("y", all_parties[1])
- else:
- x = FixedPointTensor.from_source("x", all_parties[0])
- y = FixedPointTensor.from_source("y", data_list[1])
- return (x @ y).get()
- def einsum(job_id, idx, einsum_expr, data_list):
- _, all_parties = session_init(job_id, idx)
- with SPDZ():
- if idx == 0:
- x = FixedPointTensor.from_source("x", data_list[0])
- y = FixedPointTensor.from_source("y", all_parties[1])
- else:
- x = FixedPointTensor.from_source("x", all_parties[0])
- y = FixedPointTensor.from_source("y", data_list[1])
- return x.einsum(y, einsum_expr).get()
- class TestSyncBase(unittest.TestCase):
- def setUp(self) -> None:
- self.transfer_variable = SecretShareTransferVariable()
- self.job_id = str(uuid.uuid1())
- self.transfer_variable.set_flowid(self.job_id)
- def test_create_and_get(self):
- data = np.random.rand(10, 15)
- rec = submit(create_and_get, self.job_id, data=data)
- for x in rec:
- self.assertAlmostEqual(np.linalg.norm(x - data), 0, delta=EPS)
- def test_add_and_sub(self):
- x = np.random.rand(10, 15)
- y = np.random.rand(10, 15)
- data_list = [x, y]
- rec = submit(add_and_sub, self.job_id, data_list=data_list)
- for a, b in rec:
- self.assertAlmostEqual(np.linalg.norm((x + y) - a), 0, delta=2 * EPS)
- self.assertAlmostEqual(np.linalg.norm((x - y) - b), 0, delta=2 * EPS)
- def test_add_and_sub_plaintext(self):
- # x = np.random.rand(10, 15)
- # y = np.random.rand(10, 15)
- x = np.array([1, 2, 3, 4])
- y = np.array([5, 6, 7, 8])
- data_list = [x, y]
- rec = submit(add_and_sub_plaintext, self.job_id, data_list=data_list)
- for a, a1, b, b1 in rec:
- self.assertAlmostEqual(np.linalg.norm((x + y) - a), 0, delta=2 * EPS)
- self.assertAlmostEqual(np.linalg.norm((x + y) - a1), 0, delta=2 * EPS)
- self.assertAlmostEquals(np.linalg.norm((x - y) - b), 0, delta=2 * EPS)
- self.assertAlmostEquals(np.linalg.norm((y - x) - b1), 0, delta=2 * EPS)
- def test_mul_plaintext(self):
- x = np.random.rand(10, 15)
- y = random.randint(1, 10000)
- data_list = [x, y]
- rec = submit(mul_plaintext, self.job_id, data_list=data_list)
- for a, b in rec:
- self.assertAlmostEqual(np.linalg.norm((x * y) - a), 0, delta=y * EPS)
- self.assertAlmostEqual(np.linalg.norm((x * y) - b), 0, delta=y * EPS)
- def test_matmul(self):
- j_dim = 15
- x = np.random.rand(10, j_dim)
- y = np.random.rand(j_dim, 20)
- data_list = [x, y]
- rec = submit(mat_mul, self.job_id, data_list=data_list)
- for a in rec:
- self.assertAlmostEqual(np.linalg.norm((x @ y) - a), 0, delta=j_dim * EPS)
- def test_einsum(self):
- j_dim = 5
- k_dim = 4
- x = np.random.rand(10, j_dim, k_dim)
- y = np.random.rand(k_dim, j_dim, 20)
- einsum_expr = "ijk,kjl->il"
- data_list = [x, y]
- rec = submit(einsum, self.job_id, einsum_expr=einsum_expr, data_list=data_list)
- for a in rec:
- self.assertAlmostEqual(np.linalg.norm(np.einsum(einsum_expr, x, y) - a), 0, delta=j_dim * k_dim * EPS)
|