Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/bindings/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ pybind_extension(
"@google_dp//algorithms:order-statistics",
"@google_dp//proto:util-lib"
],
)
)
134 changes: 41 additions & 93 deletions src/bindings/PyDP/algorithms/bounded_functions.cpp
Original file line number Diff line number Diff line change
@@ -1,111 +1,59 @@
// Provides bindings for Bounded Functions

#include "../../c/c_api.h"

#include "../pydp_lib/casting.hpp" // our caster helper library
#include "../pydp_lib/helper_class.hpp" // Dummy helper class

#include "pybind11/complex.h"
#include "pybind11/functional.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

using namespace std;
#include "algorithms/algorithm.h"
#include "algorithms/bounded-mean.h"
#include "algorithms/bounded-standard-deviation.h"
#include "algorithms/bounded-sum.h"
#include "algorithms/bounded-variance.h"

namespace py = pybind11;
#include "../pydp_lib/algorithm_builder.hpp"
#include "../pydp_lib/casting.hpp" // our caster helper library

class BoundedMeanDummy : public Dummy {
public:
using Dummy::Dummy;
double Result(py::list l) override {
return Result_BoundedMean(obj, l);
}
};

class BoundedSumDummy : public Dummy {
public:
using Dummy::Dummy;
double Result(py::list l) override {
return Result_BoundedSum(obj, l);
}
};

class BoundedStandardDeviationDummy : public Dummy {
public:
using Dummy::Dummy;
double Result(py::list l) override {
return Result_BoundedStandardDeviation(obj, l);
}
};
using namespace std;

class BoundedVarianceDummy : public Dummy {
public:
using Dummy::Dummy;
double Result(py::list l) override {
return Result_BoundedVariance(obj, l);
}
};
namespace py = pybind11;
namespace dp = differential_privacy;

void declareBoundedMean(py::module& m) {
py::class_<BoundedMeanDummy> bld(m, "BoundedMean");
template <typename T, class Algorithm>
void declareBoundedAlgorithm(py::module& m) {
using builder = typename dp::python::AlgorithmBuilder<T, Algorithm>;
py::class_<Algorithm> bld(m, builder().get_algorithm_name().c_str());
bld.attr("__module__") = "pydp";
bld.def(py::init<double, int, int>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
bld.def(py::init<double>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
bld.def("result", &BoundedMeanDummy::Result);
bld.def_property("l0_sensitivity", &BoundedMeanDummy::get_l0_sensitivity,
&BoundedMeanDummy::set_l0_sensitivity);
bld.def_property("linf_sensitivity", &BoundedMeanDummy::get_linf_sensitivity,
&BoundedMeanDummy::set_linf_sensitivity);
bld.def(py::init([](double epsilon, T lower_bound, T upper_bound, int l0_sensitivity,
int linf_sensitivity) {
py::print("Building with bounds");
return builder().BuildWithBounds(epsilon, lower_bound, upper_bound,
l0_sensitivity, linf_sensitivity);
}),
py::arg("epsilon"), py::arg("lower_bound"), py::arg("upper_bound"),
py::arg("l0_sensitivity") = 1, py::arg("linf_sensitivity") = 1);
bld.def(py::init([](double epsilon, int l0_sensitivity, int linf_sensitivity) {
py::print("Building without bounds");
return builder().BuildWithoutBounds(epsilon, l0_sensitivity,
linf_sensitivity);
}),
py::arg("epsilon"), py::arg("l0_sensitivity") = 1,
py::arg("linf_sensitivity") = 1);
bld.def("result", [](Algorithm& obj, std::vector<T>& v) {
return dp::GetValue<T>(obj.Result(v.begin(), v.end()).ValueOrDie());
});
}

void declareBoundedSum(py::module& m) {
py::class_<BoundedSumDummy> cls(m, "BoundedSum");
cls.attr("__module__") = "pydp";
cls.def(py::init<double, int, int>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
cls.def(py::init<double>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
cls.def("result", &BoundedSumDummy::Result);
cls.def_property("l0_sensitivity", &BoundedSumDummy::get_l0_sensitivity,
&BoundedSumDummy::set_l0_sensitivity);
cls.def_property("linf_sensitivity", &BoundedSumDummy::get_linf_sensitivity,
&BoundedSumDummy::set_linf_sensitivity);
}
void init_algorithms_bounded_functions(py::module& m) {
declareBoundedAlgorithm<int, dp::BoundedMean<int>>(m);
declareBoundedAlgorithm<double, dp::BoundedMean<double>>(m);

void declareBoundedStandardDeviation(py::module& m) {
py::class_<BoundedStandardDeviationDummy> cls(m, "BoundedStandardDeviation");
cls.attr("__module__") = "pydp";
cls.def(py::init<double, int, int>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
cls.def(py::init<double>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
cls.def("result", &BoundedStandardDeviationDummy::Result);
cls.def_property("l0_sensitivity", &BoundedStandardDeviationDummy::get_l0_sensitivity,
&BoundedStandardDeviationDummy::set_l0_sensitivity);
cls.def_property("linf_sensitivity",
&BoundedStandardDeviationDummy::get_linf_sensitivity,
&BoundedSumDummy::set_linf_sensitivity);
}
declareBoundedAlgorithm<int, dp::BoundedSum<int>>(m);
declareBoundedAlgorithm<double, dp::BoundedSum<double>>(m);

void declareBoundedVariance(py::module& m) {
py::class_<BoundedVarianceDummy> cls(m, "BoundedVariance");
cls.attr("__module__") = "pydp";
cls.def(py::init<double, int, int>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
cls.def(py::init<double>(), py::return_value_policy::reference,
py::call_guard<pybind11::gil_scoped_release>());
cls.def("result", &BoundedVarianceDummy::Result);
cls.def_property("l0_sensitivity", &BoundedVarianceDummy::get_l0_sensitivity,
&BoundedVarianceDummy::set_l0_sensitivity);
cls.def_property("linf_sensitivity", &BoundedVarianceDummy::get_linf_sensitivity,
&BoundedVarianceDummy::set_linf_sensitivity);
}
declareBoundedAlgorithm<int, dp::BoundedStandardDeviation<int>>(m);
declareBoundedAlgorithm<double, dp::BoundedStandardDeviation<double>>(m);

void init_algorithms_bounded_functions(py::module& m) {
declareBoundedMean(m);
declareBoundedSum(m);
declareBoundedStandardDeviation(m);
declareBoundedVariance(m);
declareBoundedAlgorithm<int, dp::BoundedVariance<int>>(m);
declareBoundedAlgorithm<double, dp::BoundedVariance<double>>(m);
}
61 changes: 61 additions & 0 deletions src/bindings/PyDP/pydp_lib/algorithm_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
#define PYDP_LIB_ALGORITHM_H_

#include "algorithms/algorithm.h"
#include "algorithms/bounded-mean.h"
#include "algorithms/bounded-standard-deviation.h"
#include "algorithms/bounded-sum.h"
#include "algorithms/bounded-variance.h"
#include "algorithms/numerical-mechanisms.h"

namespace dp = differential_privacy;

namespace differential_privacy {
namespace python {

Expand All @@ -17,6 +23,61 @@ class AlgorithmBuilder {
.Build()
.ValueOrDie();
}

std::unique_ptr<Algorithm> BuildWithBounds(double epsilon, T lower_bound,
T upper_bound, int l0_sensitivity = 1,
int linf_sensitivity = 1) {
return typename Algorithm::Builder()
.SetLaplaceMechanism(absl::make_unique<LaplaceMechanism::Builder>())
.SetEpsilon(epsilon)
.SetLower(lower_bound)
.SetUpper(upper_bound)
.SetMaxPartitionsContributed(l0_sensitivity)
.SetMaxContributionsPerPartition(linf_sensitivity)
.Build()
.ValueOrDie();
}

std::unique_ptr<Algorithm> BuildWithoutBounds(double epsilon, int l0_sensitivity = 1,
int linf_sensitivity = 1) {
return typename Algorithm::Builder()
.SetLaplaceMechanism(absl::make_unique<LaplaceMechanism::Builder>())
.SetEpsilon(epsilon)
.SetMaxPartitionsContributed(l0_sensitivity)
.SetMaxContributionsPerPartition(linf_sensitivity)
.Build()
.ValueOrDie();
}

std::string get_algorithm_name() {
// Set the suffix string
std::string suffix = "";
// TODO: Change to mapping function
if (typeid(T) == typeid(int)) {
suffix = "Int";
} else if (typeid(T) == typeid(double)) {
suffix = "Double";
} else {
throw std::runtime_error("Binding error - Only int and double types supported");
}

// Set the algorithm name string
std::string name = "";
// TODO: Change to mapping function
if (typeid(Algorithm) == typeid(dp::BoundedMean<T>)) {
name = "BoundedMean";
} else if (typeid(Algorithm) == typeid(dp::BoundedSum<T>)) {
name = "BoundedSum";
} else if (typeid(Algorithm) == typeid(dp::BoundedStandardDeviation<T>)) {
name = "BoundedStandardDeviation";
} else if (typeid(Algorithm) == typeid(dp::BoundedVariance<T>)) {
name = "BoundedVariance";
} else {
throw std::runtime_error(std::string("Binding error - Unsupported algorithm: ") +
std::string(typeid(Algorithm).name()));
}
return (name + suffix);
}
};

} // namespace python
Expand Down