1
- #include " mechanism.h"
1
+ #include < pybind11/pybind11.h>
2
+ #include " pybind11/complex.h"
3
+ #include " pybind11/functional.h"
4
+ #include " pybind11/stl.h"
5
+
6
+ #include " algorithms/distributions.h"
7
+ #include " algorithms/numerical-mechanisms.h"
8
+
9
+ #include " ../pydp_lib/algorithm_builder.hpp"
10
+ #include " ../pydp_lib/casting.hpp"
11
+
12
+ using namespace std ;
13
+
14
+ namespace py = pybind11;
15
+ namespace dp = differential_privacy;
16
+
17
+ class ConfidenceIntervalBinder {
18
+ public:
19
+ static void DeclareIn (py::module& m) {
20
+ py::class_<dp::ConfidenceInterval> confidence_interval (m, " ConfidenceInterval" );
21
+ confidence_interval.attr (" __module__" ) = " pydp" ;
22
+ confidence_interval
23
+ .def_property (" lower_bound" , &dp::ConfidenceInterval::lower_bound,
24
+ &dp::ConfidenceInterval::set_lower_bound)
25
+ .def_property (" upper_bound" , &dp::ConfidenceInterval::upper_bound,
26
+ &dp::ConfidenceInterval::set_upper_bound)
27
+ .def_property (" confidence_level" , &dp::ConfidenceInterval::confidence_level,
28
+ &dp::ConfidenceInterval::set_confidence_level);
29
+ }
30
+ };
31
+
32
+ template <typename T>
33
+ py::class_<dp::NumericalMechanism>& DefPyAddNoise (
34
+ py::class_<dp::NumericalMechanism>& pyclass) {
35
+ using FunctorType = T (dp::NumericalMechanism::*)(T);
36
+ return pyclass.def (" add_noise" ,
37
+ static_cast <FunctorType>(&dp::NumericalMechanism::AddNoise),
38
+ py::arg (" result" ));
39
+ }
40
+
41
+ template <typename T, typename U>
42
+ py::class_<dp::NumericalMechanism>& DefPyAddNoise (
43
+ py::class_<dp::NumericalMechanism>& pyclass) {
44
+ using FunctorType = T (dp::NumericalMechanism::*)(T, U);
45
+ return pyclass.def (" add_noise" ,
46
+ static_cast <FunctorType>(&dp::NumericalMechanism::AddNoise),
47
+ py::arg (" result" ), py::arg (" privacy_budget" ));
48
+ }
49
+
50
+ template <typename T, typename U>
51
+ std::unique_ptr<T> downcast_unique_ptr (std::unique_ptr<U> u_ptr) {
52
+ static_assert (std::is_base_of<U, T>::value, " Illegal downcast." );
53
+ T* ptr = dynamic_cast <T*>(u_ptr.release ());
54
+ return std::unique_ptr<T>(ptr);
55
+ }
56
+
57
+ class NumericalMechanismBinder {
58
+ public:
59
+ static void DeclareIn (py::module& m) {
60
+ py::class_<dp::NumericalMechanism> numerical_mech (m, " NumericalMechanism" ,
61
+ R"pbdoc(
62
+ Base class for all (Ɛ, 𝛿)-differenially private additive noise numerical mechanisms.
63
+ )pbdoc" );
64
+ numerical_mech.attr (" __module__" ) = " pydp" ;
65
+ DefPyAddNoise<int , double >(numerical_mech);
66
+ DefPyAddNoise<int64_t , double >(numerical_mech);
67
+ DefPyAddNoise<double , double >(numerical_mech);
68
+ DefPyAddNoise<int >(numerical_mech);
69
+ DefPyAddNoise<int64_t >(numerical_mech);
70
+ DefPyAddNoise<double >(numerical_mech);
71
+ numerical_mech
72
+ .def (" noised_value_above_threshold" ,
73
+ &dp::NumericalMechanism::NoisedValueAboveThreshold,
74
+ R"pbdoc(
75
+ Quickly determines if `result` with added noise is above certain `threshold`.
76
+ )pbdoc" )
77
+ .def (" memory_used" , &dp::NumericalMechanism::MemoryUsed)
78
+ .def (
79
+ " noise_confidence_interval" ,
80
+ [](dp::NumericalMechanism& self, double cl, double pb,
81
+ double nr) -> dp::ConfidenceInterval {
82
+ auto result = self.NoiseConfidenceInterval (cl, pb, nr);
83
+ return result.ValueOrDie ();
84
+ },
85
+ py::arg (" confidence_level" ), py::arg (" privacy_budget" ),
86
+ py::arg (" noised_result" ),
87
+ R"pbdoc(
88
+ Returns the confidence interval of the specified confidence level of the
89
+ noise that AddNoise() would add with the specified privacy budget.
90
+ If the returned value is <x,y>, then the noise added has a confidence_level
91
+ chance of being in the domain [x,y]
92
+ )pbdoc" )
93
+ .def_property_readonly (" epsilon" , &dp::NumericalMechanism::GetEpsilon,
94
+ " The Ɛ of the numerical mechanism" );
95
+ }
96
+ };
97
+
98
+ class LaplaceMechanismBinder {
99
+ public:
100
+ static std::unique_ptr<dp::LaplaceMechanism> build (double epsilon,
101
+ double l1_sensitivity) {
102
+ dp::LaplaceMechanism::Builder builder;
103
+ builder.SetEpsilon (epsilon);
104
+ builder.SetSensitivity (l1_sensitivity);
105
+ builder.SetL1Sensitivity (l1_sensitivity);
106
+ return downcast_unique_ptr<dp::LaplaceMechanism, dp::NumericalMechanism>(
107
+ builder.Build ().value ());
108
+ }
109
+
110
+ static std::unique_ptr<dp::NumericalMechanismBuilder> clone () {
111
+ dp::LaplaceMechanism::Builder cloner;
112
+ return std::move (cloner.Clone ());
113
+ }
114
+
115
+ static void DeclareIn (py::module& m) {
116
+ py::class_<dp::LaplaceMechanism, dp::NumericalMechanism> lap_mech (
117
+ m, " LaplaceMechanism" );
118
+ lap_mech.attr (" __module__" ) = " pydp" ;
119
+ lap_mech
120
+ .def (py::init ([](double epsilon, double sensitivity) {
121
+ return build (epsilon, sensitivity);
122
+ }),
123
+ py::arg (" epsilon" ), py::arg (" sensitivity" ) = 1.0 )
124
+ .def (" get_uniform_double" , &dp::LaplaceMechanism::GetUniformDouble)
125
+ // .def("deserialize", &dp::LaplaceMechanism::Deserialize)
126
+ // .def("serialize", &dp::LaplaceMechanism::Serialize)
127
+ .def_property_readonly (" sensitivity" , &dp::LaplaceMechanism::GetSensitivity,
128
+ " The L1 sensitivity of the query." )
129
+ .def_property_readonly (" diversity" , &dp::LaplaceMechanism::GetDiversity,
130
+ " The diversity of the Laplace mechanism." );
131
+ }
132
+ };
133
+
134
+ class GaussianMechanismBinder {
135
+ public:
136
+ static std::unique_ptr<dp::GaussianMechanism> build (double epsilon, double delta,
137
+ double l2_sensitivity) {
138
+ dp::GaussianMechanism::Builder builder;
139
+ builder.SetEpsilon (epsilon);
140
+ builder.SetDelta (delta);
141
+ builder.SetL2Sensitivity (l2_sensitivity);
142
+ return downcast_unique_ptr<dp::GaussianMechanism, dp::NumericalMechanism>(
143
+ builder.Build ().value ());
144
+ };
145
+
146
+ static std::unique_ptr<dp::NumericalMechanismBuilder> clone () {
147
+ dp::GaussianMechanism::Builder cloner;
148
+ return std::move (cloner.Clone ());
149
+ };
150
+
151
+ static void DeclareIn (py::module& m) {
152
+ py::class_<dp::GaussianMechanism, dp::NumericalMechanism> gaus_mech (
153
+ m, " GaussianMechanism" );
154
+ gaus_mech.attr (" __module__" ) = " pydp" ;
155
+ gaus_mech
156
+ .def (py::init ([](double epsilon, double delta, double l2_sensitivity) {
157
+ return build (epsilon, delta, l2_sensitivity);
158
+ }))
159
+ // .def("deserialize", &dp::GaussianMechanism::Deserialize)
160
+ // .def("serialize", &dp::GaussianMechanism::Serialize)
161
+ .def_property_readonly (" delta" , &dp::GaussianMechanism::GetDelta,
162
+ " The 𝛿 of the Gaussian mechanism." )
163
+ .def_property_readonly (
164
+ " std" ,
165
+ [](const dp::GaussianMechanism& self) {
166
+ return dp::GaussianMechanism::CalculateStddev (
167
+ self.GetEpsilon (), self.GetDelta (), self.GetL2Sensitivity ());
168
+ },
169
+ R"pbdoc(
170
+ The standard deviation parameter of the
171
+ Gaussian mechanism underlying distribution.
172
+ )pbdoc" )
173
+ .def_property_readonly (" l2_sensitivity" ,
174
+ &dp::GaussianMechanism::GetL2Sensitivity,
175
+ " The L2 sensitivity of the query." );
176
+ }
177
+ };
178
+
179
+ void init_mechanisms_mechanism (py::module& m) {
180
+ ConfidenceIntervalBinder::DeclareIn (m);
181
+ NumericalMechanismBinder::DeclareIn (m);
182
+ LaplaceMechanismBinder::DeclareIn (m);
183
+ GaussianMechanismBinder::DeclareIn (m);
184
+ }
0 commit comments