def test_sample_without_replacement():
    array = np.ones(100)
    node_single = DataNode()
    node_single.set_private_data(name="array", data=array)
    sample_size = 50

    def u(x, r):
        output = np.zeros(len(r))
        for i in range(len(r)):
            output[i] = r[i] * sum(np.greater_equal(x, r[i]))
        return output

    r = np.arange(0, 3.5, 0.001)
    delta_u = r.max()
    epsilon = 5
    exponential_mechanism = ExponentialMechanism(u,
                                                 r,
                                                 delta_u,
                                                 epsilon,
                                                 size=sample_size)

    access_modes = [LaplaceMechanism(1, 1)]
    access_modes.append(GaussianMechanism(1, (0.5, 0.5)))
    access_modes.append(RandomizedResponseBinary(0.5, 0.5, 1))
    access_modes.append(RandomizedResponseCoins())
    access_modes.append(exponential_mechanism)

    for a in access_modes:
        sampling_method = SampleWithoutReplacement(a, sample_size, array.shape)
        node_single.configure_data_access("array", sampling_method)
        result = node_single.query("array")
        assert result.shape[0] == sample_size
def test_epsilon_delta_reduction():
    epsilon = 1
    n = (100, )
    m = 50
    access_mode = LaplaceMechanism(1, epsilon)
    sampling_method = SampleWithoutReplacement(access_mode, m, n)
    proportion = m / n[0]
    assert sampling_method.epsilon_delta == (log(1 + proportion *
                                                 (exp(epsilon) - 1)), 0)

    nd = (20, 5)
    m = 10
    access_mode = LaplaceMechanism(1, epsilon)
    sampling_method = SampleWithoutReplacement(access_mode, m, nd)
    proportion = (m * nd[1]) / (nd[0] * nd[1])
    assert sampling_method.epsilon_delta == (log(1 + proportion *
                                                 (exp(epsilon) - 1)), 0)
def test_sample_error():
    array = np.ones(100)
    node_single = DataNode()
    node_single.set_private_data(name="array", data=array)
    sample_size = 101

    with pytest.raises(ValueError):
        access_mode = SampleWithoutReplacement(LaplaceMechanism(1, 1),
                                               sample_size, array.shape)
Example #4
0
def test_laplace_scalar_mechanism():
    scalar = 175

    node = DataNode()
    node.set_private_data("scalar", scalar)
    node.configure_data_access("scalar", LaplaceMechanism(1, 1))

    result = node.query("scalar")

    assert scalar != result
    assert np.abs(scalar - result) < 100
def test_sample_without_replacement_multidimensional():
    array = np.ones((100, 2))
    sample_size = 50
    node_single = DataNode()
    node_single.set_private_data(name="array", data=array)
    epsilon = 1
    access_mode = LaplaceMechanism(1, epsilon)
    sampling_method = SampleWithoutReplacement(access_mode, sample_size,
                                               array.shape)
    node_single.configure_data_access("array", sampling_method)
    result = node_single.query("array")

    assert result.shape[0] == sample_size
Example #6
0
def test_laplace_dictionary_mechanism():
    dictionary = {
        0: np.array([[2, 4, 5], [2, 3, 5]]),
        1: np.array([[1, 3, 1], [1, 4, 6]])
    }

    node = DataNode()
    node.set_private_data("dictionary", dictionary)
    node.configure_data_access("dictionary", LaplaceMechanism(1, 1))

    result = node.query("dictionary")

    assert dictionary.keys() == result.keys()
    assert np.mean(dictionary[0]) - np.mean(result[0]) < 5
Example #7
0
def test_laplace_dictionary_mechanism_wrong_shapes():
    dictionary = {0: np.array([2, 3, 5]), 1: np.array([[1, 3, 1], [1, 4, 6]])}

    sensitivity = {
        0: np.array([[1, 1, 2], [2, 1, 1]]),
        1: np.array([3, 1, 11, 1, 2])
    }

    node = DataNode()
    node.set_private_data("dictionary", dictionary)
    dp_access_mechanism = LaplaceMechanism(sensitivity, 1)
    node.configure_data_access("dictionary", dp_access_mechanism)

    with pytest.raises(ValueError):
        node.query("dictionary")
Example #8
0
def test_laplace_mechanism():
    data_size = 1000
    array = NormalDistribution(175, 7).sample(data_size)
    federated_array = shfl.private.federated_operation.federate_array(
        array, data_size)

    federated_array.configure_data_access(LaplaceMechanism(1, 1))
    result = federated_array.query()

    differences = 0
    for i in range(data_size):
        if result[i] != array[i]:
            differences = differences + 1

    assert differences == data_size
    assert np.mean(array) - np.mean(result) < 5
Example #9
0
def test_laplace_mechanism_list_of_arrays():
    n_nodes = 15
    data = [[np.random.rand(3, 2), np.random.rand(2, 3)]
            for node in range(n_nodes)]

    federated_list = shfl.private.federated_operation.FederatedData()
    for node in range(n_nodes):
        federated_list.add_data_node(data[node])

    federated_list.configure_data_access(
        LaplaceMechanism(sensitivity=0.01, epsilon=1))
    result = federated_list.query()
    for i_node in range(n_nodes):
        for i_list in range(len(data[i_node])):
            assert (data[i_node][i_list] != result[i_node][i_list]).all()
            assert np.abs(
                np.mean(data[i_node][i_list]) -
                np.mean(result[i_node][i_list])) < 1
Example #10
0
def test_laplace_epsilon_delta():
    laplace_mechanism = LaplaceMechanism(sensitivity=0.1, epsilon=1)

    assert laplace_mechanism.epsilon_delta is not None
Example #11
0
def test_sensitivity_wrong_input():

    epsilon_delta = (0.1, 1)

    # Negative sensitivity:
    scalar = 175
    sensitivity = -0.1
    node = DataNode()
    node.set_private_data("scalar", scalar)
    with pytest.raises(ValueError):
        node.configure_data_access(
            "scalar",
            GaussianMechanism(sensitivity=sensitivity,
                              epsilon_delta=epsilon_delta))

    # Scalar query result, Too many sensitivity values provided:
    scalar = 175
    sensitivity = [0.1, 0.5]
    node = DataNode()
    node.set_private_data("scalar", scalar)
    node.configure_data_access(
        "scalar",
        GaussianMechanism(sensitivity=sensitivity,
                          epsilon_delta=epsilon_delta))
    with pytest.raises(ValueError):
        result = node.query("scalar")

    # Both query result and sensitivity are 1D-arrays, but non-broadcastable:
    data_array = [10, 10, 10, 10]
    sensitivity = [0.1, 10, 100, 1000, 1000]
    node = DataNode()
    node.set_private_data("data_array", data_array)
    node.configure_data_access(
        "data_array",
        GaussianMechanism(sensitivity=sensitivity,
                          epsilon_delta=epsilon_delta))
    with pytest.raises(ValueError):
        result = node.query("data_array")

    # ND-array query result and 1D-array sensitivity, but non-broadcastable:
    data_ndarray = [[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]]
    sensitivity = [0.1, 10, 100]
    node = DataNode()
    node.set_private_data("data_ndarray", data_ndarray)
    node.configure_data_access(
        "data_ndarray",
        GaussianMechanism(sensitivity=sensitivity,
                          epsilon_delta=epsilon_delta))
    with pytest.raises(ValueError):
        result = node.query("data_ndarray")

    # Both query result and sensitivity are ND-arrays, but non-broadcastable (they should have the same shape
    # in this case):
    data_ndarray = [[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]]
    sensitivity = [[0.1, 10, 100, 1000, 10000], [0.1, 10, 100, 1000, 10000],
                   [0.1, 10, 100, 1000, 10000]]
    node = DataNode()
    node.set_private_data("data_ndarray", data_ndarray)
    node.configure_data_access(
        "data_ndarray",
        GaussianMechanism(sensitivity=sensitivity,
                          epsilon_delta=epsilon_delta))
    with pytest.raises(ValueError):
        result = node.query("data_ndarray")

    # Query result is a list of arrays: sensitivity must be either a scalar, or a list of the same length as query
    data_list = [
        np.random.rand(30, 20),
        np.random.rand(20, 30),
        np.random.rand(50, 40)
    ]
    sensitivity = np.array([1, 1])  # Array instead of scalar
    node = DataNode()
    node.set_private_data("data_list", data_list)
    node.configure_data_access(
        "data_list", LaplaceMechanism(sensitivity=sensitivity, epsilon=1))
    with pytest.raises(ValueError):
        result = node.query("data_list")

    sensitivity = [1, 1]  # List of wrong length
    node = DataNode()
    node.set_private_data("data_list", data_ndarray)
    node.configure_data_access(
        "data_list", LaplaceMechanism(sensitivity=sensitivity, epsilon=1))
    with pytest.raises(IndexError):
        result = node.query("data_list")

    # Query result is wrong data structure: so far, tuples are not allowed
    data_tuple = (1, 2, 3, 4, 5)
    sensitivity = 2
    node = DataNode()
    node.set_private_data("data_tuple", data_tuple)
    node.configure_data_access(
        "data_tuple", LaplaceMechanism(sensitivity=sensitivity, epsilon=1))
    with pytest.raises(NotImplementedError):
        result = node.query("data_tuple")