Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
2b01e52
Disable distributions code
alejandrosame Aug 5, 2020
6ef9cda
First proof of concept for internal aux class
alejandrosame Aug 5, 2020
958d57f
Update Count test
alejandrosame Aug 6, 2020
3449973
Merge pull request #222 from alejandrosame/refactoring
chinmayshah99 Aug 6, 2020
6885fb3
Refactor bounded functions
alejandrosame Aug 6, 2020
84380ae
Merge pull request #223 from alejandrosame/refactoring
chinmayshah99 Aug 6, 2020
e08c9ca
Added a more compact name type lookup. We might need to validate the …
BenjaminDev Aug 7, 2020
a926b60
Merge pull request #225 from BenjaminDev/count-refactor
chinmayshah99 Aug 7, 2020
acd5f45
added more epsilon property amd budget
chinmayshah99 Aug 7, 2020
3126da7
Merge pull request #228 from chinmayshah99/refactor-capi
chinmayshah99 Aug 7, 2020
05eeccf
added error handing in intialization
chinmayshah99 Aug 8, 2020
62073bf
Merge pull request #229 from chinmayshah99/refactor-capi
chinmayshah99 Aug 8, 2020
bcceec7
Refactor builders error check
alejandrosame Aug 8, 2020
e6069b0
Bind more functions
alejandrosame Aug 8, 2020
b9c881c
Unifiy helper build function
alejandrosame Aug 8, 2020
eea4927
Merge pull request #230 from alejandrosame/refactoring
chinmayshah99 Aug 8, 2020
ad24725
Allow setting delta param
alejandrosame Aug 9, 2020
2bc904f
added error checking in partial result
chinmayshah99 Aug 9, 2020
cf181bb
Merge pull request #231 from chinmayshah99/refactor-capi
chinmayshah99 Aug 9, 2020
d4aa0a7
Generalise algorithm declaration
alejandrosame Aug 9, 2020
1dc6589
Fix merge conflict
alejandrosame Aug 9, 2020
cda7909
Fix delta arg position
alejandrosame Aug 9, 2020
edfddd8
Fix Count result call
alejandrosame Aug 9, 2020
2d8c86a
Define algorithms submodule
alejandrosame Aug 10, 2020
c729da6
Start defining new Python API
alejandrosame Aug 10, 2020
016d7c5
Merge pull request #232 from alejandrosame/refactoring
chinmayshah99 Aug 11, 2020
d0f8ce3
Rename pydp.so to _pydp.so
alejandrosame Aug 12, 2020
537032f
Update Python API
alejandrosame Aug 12, 2020
655d351
Merge pull request #237 from alejandrosame/refactoring
chinmayshah99 Aug 12, 2020
fe7a202
removed delta as it can't be used for laplacian
chinmayshah99 Aug 12, 2020
5127715
Add bounded algorithms
alejandrosame Aug 12, 2020
1c641d9
added bounded functions in python code
chinmayshah99 Aug 12, 2020
863926e
Merge pull request #239 from chinmayshah99/refactor-capi
chinmayshah99 Aug 12, 2020
727c041
Restructure algorithm classes
alejandrosame Aug 13, 2020
2757fff
Resolve merge conflict
alejandrosame Aug 13, 2020
8d5db91
Fix typo
alejandrosame Aug 13, 2020
58b4d50
Delete consume_privacy_budget method from public interface
alejandrosame Aug 13, 2020
b03ee55
Make method wrapping explicit
alejandrosame Aug 13, 2020
bf4147a
Fix init and type errors
alejandrosame Aug 13, 2020
557412e
Fix packaging error
alejandrosame Aug 13, 2020
4d9eb23
Update tests and fix partial_result call
alejandrosame Aug 13, 2020
7d53895
Update bounded algorithm tests
alejandrosame Aug 13, 2020
cccc23a
Merge pull request #240 from alejandrosame/refactoring
chinmayshah99 Aug 13, 2020
1646460
change return datatype to double
chinmayshah99 Aug 13, 2020
a19b0a5
added l0&linf sensitivity
chinmayshah99 Aug 13, 2020
876947d
Merge pull request #241 from chinmayshah99/refactor-capi
chinmayshah99 Aug 13, 2020
b9820b1
Fix sensitivity values init and make getters readonly arguments
alejandrosame Aug 14, 2020
c3c8f7d
Merge pull request #243 from alejandrosame/refactoring
chinmayshah99 Aug 14, 2020
0ff3ca8
Order statistics refactor (#244)
BenjaminDev Aug 14, 2020
d71a94f
Fix compilation with new DP hash
alejandrosame Aug 14, 2020
db3314e
Avoid using string formating
alejandrosame Aug 14, 2020
fc83c4c
Avoid using formatted string
alejandrosame Aug 14, 2020
18990b0
Merge pull request #245 from alejandrosame/refactoring
alejandrosame Aug 14, 2020
e461e53
Tidy up public interface (#246)
alejandrosame Aug 14, 2020
17e834e
added comments for each module
chinmayshah99 Aug 15, 2020
d4c897d
added mypy bindings
chinmayshah99 Aug 15, 2020
9a147e0
removing redundant classes
chinmayshah99 Aug 15, 2020
45436cd
changed upperbound to a more reaslistic values
chinmayshah99 Aug 15, 2020
5bd1ca3
styling python files
chinmayshah99 Aug 15, 2020
e101993
Merge pull request #248 from chinmayshah99/refactor-capi
chinmayshah99 Aug 16, 2020
91a8dd7
added mypy for noise interval
chinmayshah99 Aug 16, 2020
a882261
Merge pull request #250 from OpenMined/chinmayshah99-patch-1
chinmayshah99 Aug 16, 2020
04831f1
fixed typos in comments
chinmayshah99 Aug 16, 2020
f459f0a
style fix
chinmayshah99 Aug 16, 2020
72c9270
Fix typos
alejandrosame Aug 17, 2020
227f5b2
Merge pull request #255 from alejandrosame/test-capi
alejandrosame Aug 17, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/pypipublish_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
cd third_party/differential-privacy
git checkout 0b0a5c2315d84a6a7b1ff34591e33ec11680891e
cd -
rm -rf third_party/differential-privacy/java
rm -rf third_party/differential-privacy/java
rm -rf third_party/differential-privacy/examples/java
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
Expand Down Expand Up @@ -55,8 +55,8 @@ jobs:
- name: Build pydp lib
run: |
bazel build src/python:bindings_test --verbose_failures
rm -f pydp.so
cp -f ./bazel-bin/src/bindings/pydp.so ./pydp
rm -f _pydp.so
cp -f ./bazel-bin/src/bindings/_pydp.so ./pydp

- name: Build wheel
run: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/pypipublish_osx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
cd third_party/differential-privacy
git checkout 0b0a5c2315d84a6a7b1ff34591e33ec11680891es
cd -
rm -rf third_party/differential-privacy/java
rm -rf third_party/differential-privacy/java
rm -rf third_party/differential-privacy/examples/java
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
Expand All @@ -36,8 +36,8 @@ jobs:
- name: Build pydp lib
run: |
bazel build src/python:bindings_test --verbose_failures
rm -f pydp.so
cp -f ./bazel-bin/src/bindings/pydp.so ./pydp
rm -f _pydp.so
cp -f ./bazel-bin/src/bindings/_pydp.so ./pydp


- name: Build wheel
Expand All @@ -49,4 +49,4 @@ jobs:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.TOKEN }}
run: |
twine upload --skip-existing dist/*.whl
twine upload --skip-existing dist/*.whl
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pydp.so
_pydp.so
# bazel files
bazel-bin
bazel-out
Expand Down
4 changes: 2 additions & 2 deletions build_PyDP.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

pipenv install --dev --skip-lock
bazel build src/python:bindings_test --verbose_failures
find ./ -name pydp.so -print0 | xargs -0 -I {} rm {}
cp -f ./bazel-bin/src/bindings/pydp.so ./pydp
find ./ -name _pydp.so -print0 | xargs -0 -I {} rm {}
cp -f ./bazel-bin/src/bindings/_pydp.so ./pydp
3 changes: 2 additions & 1 deletion prereqs_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ fi
# Downloading the Google DP library
git submodule update --init --recursive


# checkout out to particular commit
cd third_party/differential-privacy && git checkout 0b0a5c2315d84a6a7b1ff34591e33ec11680891e && \
cd third_party/differential-privacy && git checkout 1b1dc6639173c0a13613189ec21851604a4c7335 && \
cd -
# renaming workspace.bazel to workspace
mv third_party/differential-privacy/cc/WORKSPACE.bazel third_party/differential-privacy/cc/WORKSPACE
Expand Down
3 changes: 2 additions & 1 deletion pydp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .pydp import *
from pydp import algorithms, distributions, util


__version__ = "0.1.4"
3 changes: 3 additions & 0 deletions pydp/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import laplacian

__all__ = ["laplacian"]
166 changes: 166 additions & 0 deletions pydp/algorithms/_algorithm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
from .._pydp import _algorithms

from typing import Union, List


class MetaAlgorithm:
def __init__(self, **kwargs):
dtype = kwargs.pop("dtype")

# Delete bound params if they are not set to avoid conflicts with builder
if "lower_bound" in kwargs and kwargs["lower_bound"] is None:
kwargs.pop("lower_bound")
if "upper_bound" in kwargs and kwargs["upper_bound"] is None:
kwargs.pop("upper_bound")

binded_class = self.__class__.__name__ + self.__map_dtype_str(dtype)
class_ = getattr(_algorithms, binded_class)

self.dtype = dtype
self.__algorithm = class_(**kwargs)
self._l0_sensitivity = kwargs.get("l0_sensitivity", "Not set")
self._linf_sensitivity = kwargs.get("linf_sensitivity", "Not set")

@staticmethod
def __map_dtype_str(dtype: str):
if dtype == "int":
return "Int"
elif dtype == "float":
return "Double"
else:
raise RuntimeError("dtype: {} is not supported".format(dtype))

@property
def epsilon(self) -> float:
"""
Returns the epsilon set at initialization.
"""
return self.__algorithm.epsilon

@property
def l0_sensitivity(self) -> float:
"""
Returns the l0_sensitivity set at initialization.
"""
return self._l0_sensitivity

@property
def linf_sensitivity(self) -> float:
"""
Returns the linf_sensitivity set at initialization.
"""
return self._linf_sensitivity

def privacy_budget_left(self) -> float:
"""
Returns the remaining privacy budget.
"""
return self.__algorithm.privacy_budget_left()

def memory_used(self) -> float:
"""
Returns the memory currently used by the algorithm in bytes.
"""
return self.__algorithm.memory_used()

def add_entries(self, data: List[Union[int, float]]) -> None:
"""
Adds multiple inputs to the algorithm.
"""
return self.__algorithm.add_entries(data)

def add_entry(self, value: Union[int, float]) -> None:
"""
Adds one input to the algorithm.
"""
return self.__algorithm.add_entry(value)

def quick_result(self, data: List[Union[int, float]]) -> Union[int, float]:
"""
Runs the algorithm on the input using the epsilon parameter provided in the constructor and returns output.

Consumes 100% of the privacy budget.
"""
return self.__algorithm.result(data)

def result(
self,
privacy_budget: Union[float, None] = None,
noise_interval_level: Union[float, None] = None,
) -> Union[int, float]:
"""
Gets the algorithm result.

The default call consumes the remaining privacy budget.

When `privacy_budget` (defined on [0,1]) is set, it consumes only the `privacy_budget` amount of budget.

`noise_interval_level` provides the confidence level of the noise confidence interval, which may be included in the algorithm output.
"""

if privacy_budget is None:
return self.__algorithm.partial_result()
elif noise_interval_level is None:
return self.__algorithm.partial_result(privacy_budget)
else:
return self.__algorithm.partial_result(privacy_budget, noise_interval_level)

def reset(self) -> None:
"""
Resets the algorithm to a state in which it has received no input. After Reset is called, the algorithm should only consider input added after the last Reset call when providing output.
"""
return self.__algorithm.reset()

# TODO: Wrap Summary class before exposing serialize and merge methods.
#
# def serialize(self):
# """
# Serializes summary data of current entries into Summary proto. This allows results from distributed aggregation to be recorded and later merged.
#
# Returns empty summary for algorithms for which serialize is unimplemented.
# """
# return self.__algorithm.serialize()
#
# def merge(self, summary):
# """
# Merges serialized summary data into this algorithm. The summary proto must represent data from the same algorithm type with identical parameters. The data field must contain the algorithm summary type of the corresponding algorithm used. The summary proto cannot be empty.
# """
# return self.__algorithm.merge(summary)

def noise_confidence_interval(
self, confidence_level: float, privacy_budget: float
) -> float:
"""
Returns the confidence_level confidence interval of noise added within the algorithm with specified privacy budget, using epsilon and other relevant, algorithm-specific parameters (e.g. bounds) provided by the constructor.

This metric may be used to gauge the error rate introduced by the noise.

If the returned value is <x,y>, then the noise added has a confidence_level chance of being in the domain [x,y].

By default, NoiseConfidenceInterval() returns an error. Algorithms for which a confidence interval can feasibly be calculated override this and output the relevant value.

Conservatively, we do not release the error rate for algorithms whose confidence intervals rely on input size.
"""
return self.__algorithm.noise_confidence_interval(
confidence_level, privacy_budget
)


class BoundedAlgorithm(MetaAlgorithm):
def __init__(
self,
epsilon: float = 1.0,
lower_bound: Union[int, float, None] = None,
upper_bound: Union[int, float, None] = None,
l0_sensitivity: int = 1,
linf_sensitivity: int = 1,
dtype: str = "int",
):
super().__init__(
epsilon=epsilon,
lower_bound=lower_bound,
upper_bound=upper_bound,
l0_sensitivity=l0_sensitivity,
linf_sensitivity=linf_sensitivity,
dtype=dtype,
)
23 changes: 23 additions & 0 deletions pydp/algorithms/laplacian/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from ._bounded_algorithms import (
BoundedMean,
BoundedSum,
BoundedStandardDeviation,
BoundedVariance,
Max,
Min,
Median,
)
from ._count import Count
from ._percentile import Percentile

__all__ = [
"BoundedMean",
"BoundedStandardDeviation",
"BoundedSum",
"BoundedVariance",
"Count",
"Max",
"Min",
"Median",
"Percentile",
]
64 changes: 64 additions & 0 deletions pydp/algorithms/laplacian/_bounded_algorithms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from .._algorithm import BoundedAlgorithm


class BoundedMean(BoundedAlgorithm):
"""
Bounded Mean Explanation
TODO
"""

pass


class BoundedSum(BoundedAlgorithm):
"""
Bounded Sum Explanation
TODO
"""

pass


class BoundedStandardDeviation(BoundedAlgorithm):
"""
Bounded Standard Deviation Explanation
TODO
"""

pass


class BoundedVariance(BoundedAlgorithm):
"""
Bounded Variance Explanation
TODO
"""

pass


class Max(BoundedAlgorithm):
"""
Max Explanation
TODO
"""

pass


class Min(BoundedAlgorithm):
"""
Min Explanation
TODO
"""

pass


class Median(BoundedAlgorithm):
"""
Median Explanation
TODO
"""

pass
11 changes: 11 additions & 0 deletions pydp/algorithms/laplacian/_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .._algorithm import MetaAlgorithm


class Count(MetaAlgorithm):
"""
Count Explanation
TODO
"""

def __init__(self, epsilon: float = 1.0, dtype: str = "int"):
super().__init__(epsilon=epsilon, dtype=dtype)
27 changes: 27 additions & 0 deletions pydp/algorithms/laplacian/_percentile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from .._algorithm import MetaAlgorithm
from typing import Union


class Percentile(MetaAlgorithm):
def __init__(
self,
epsilon: float = 1.0,
percentile: float = 0.0,
lower_bound: Union[int, float, None] = None,
upper_bound: Union[int, float, None] = None,
dtype: str = "int",
):
super().__init__(
epsilon=epsilon,
percentile=percentile,
lower_bound=lower_bound,
upper_bound=upper_bound,
dtype=dtype,
)

@property
def percentile(self) -> float:
"""
percentile Gets the value that was set in the constructor.
"""
return self._MetaAlgorithm__algorithm.percentile
1 change: 1 addition & 0 deletions pydp/distributions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .._pydp._distributions import *
1 change: 1 addition & 0 deletions pydp/util/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .._pydp._util import *
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def read(fname):
include_package_data=True,
keywords="pydp",
name="python-dp",
package_data={"pydp": ["pydp.so"],},
package_data={"pydp": ["_pydp.so"],},
packages=find_packages(exclude=["tests"]), # need to check this
setup_requires=setup_requirements,
test_suite="tests",
Expand Down
Loading