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
57 changes: 34 additions & 23 deletions src/bindings/PyDP/algorithms/bounded_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "algorithms/bounded-standard-deviation.h"
#include "algorithms/bounded-sum.h"
#include "algorithms/bounded-variance.h"
#include "base/statusor.h"

#include "../pydp_lib/algorithm_builder.hpp"
#include "../pydp_lib/casting.hpp" // our caster helper library
Expand All @@ -28,47 +27,59 @@ void declareBoundedAlgorithm(py::module& m) {
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);
return builder().Build(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);
return builder().Build(epsilon, nullopt, nullopt, l0_sensitivity,
linf_sensitivity);
}),
py::arg("epsilon"), py::arg("l0_sensitivity") = 1,
py::arg("linf_sensitivity") = 1);

// TODO: can't get it work
// bld.def_property_readonly("l0_sensitivity", [](Algorithm& obj){
// return obj.GetMaxPartitionsContributed();
// });
// bld.def_property_readonly("linf_sensitivity", [](Algorithm& obj){
// return obj.SetMaxContributionsPerPartition();
// });
bld.def_property_readonly("epsilon", [](Algorithm& obj) { return obj.GetEpsilon(); });

bld.def("privacy_budget_left",
[](Algorithm& obj) { return obj.RemainingPrivacyBudget(); });

// TODO
// bld.def("add_entries", [](Algorithm& obj, std::vector<T>& v) {
// return obj.AddEntries(v.begin(), v.end()).ValueOrDie();
// });
bld.def("add_entries", [](Algorithm& obj, std::vector<T>& v) {
obj.AddEntries(v.begin(), v.end());
});

bld.def("partial_result", [](Algorithm& obj) {
auto result = obj.PartialResult();

if (!result.ok()) {
throw std::runtime_error(result.status().error_message());
}

return dp::GetValue<double>(result.ValueOrDie());
});

// bld.def("partial_result", [](Algorithm& obj) {
// return dp::GetValue<double>(obj.PartialResult().ValueOrDie());
// })
// bld.def("partial_result", [](Algorithm& obj, double privacy_budget) {
// return dp::GetValue<double>(obj.PartialResult(privacy_budget).ValueOrDie());
// })
bld.def("partial_result", [](Algorithm& obj, double privacy_budget) {
auto result = obj.PartialResult(privacy_budget);

if (!result.ok()) {
throw std::runtime_error(result.status().error_message());
}

return dp::GetValue<double>(result.ValueOrDie());
});

bld.def_property_readonly("epsilon", [](Algorithm& obj) { return obj.GetEpsilon(); });

bld.def("result", [](Algorithm& obj, std::vector<T>& v) {
return dp::GetValue<double>(obj.Result(v.begin(), v.end()).ValueOrDie());
auto result = obj.Result(v.begin(), v.end());

if (!result.ok()) {
throw std::runtime_error(result.status().error_message());
}

return dp::GetValue<T>(result.ValueOrDie());
});
}

Expand Down
10 changes: 9 additions & 1 deletion src/bindings/PyDP/algorithms/count.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,17 @@ void declareCount(py::module& m, string const& suffix) {
//.def("serialize", &dp::Count<T>::Serialize)
//.def("merge", &dp::Count<T>::Merge)
.def("memory_used", &dp::Count<T>::MemoryUsed)
.def_property_readonly("epsilon",
[](dp::Count<T>& obj) { return obj.GetEpsilon(); })
.def("result",
[](dp::Count<T>& obj, std::vector<T>& v) {
return dp::GetValue<T>(obj.Result(v.begin(), v.end()).ValueOrDie());
auto result = obj.Result(v.begin(), v.end());

if (!result.ok()) {
throw std::runtime_error(result.status().error_message());
}

return dp::GetValue<T>(result.ValueOrDie());
})
.def("partial_result",
[](dp::Count<T>& obj) {
Expand Down
67 changes: 28 additions & 39 deletions src/bindings/PyDP/pydp_lib/algorithm_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,53 +14,42 @@ namespace dp = differential_privacy;
namespace differential_privacy {
namespace python {

template <typename T, class Algorithm>
constexpr bool is_bounded_algorithm() {
return std::is_same<Algorithm, dp::BoundedMean<T>>::value ||
std::is_same<Algorithm, dp::BoundedSum<T>>::value ||
std::is_same<Algorithm, dp::BoundedStandardDeviation<T>>::value ||
std::is_same<Algorithm, dp::BoundedVariance<T>>::value;
}

template <typename T, class Algorithm>
class AlgorithmBuilder {
public:
std::unique_ptr<Algorithm> Build(double epsilon) {
base::StatusOr<std::unique_ptr<Algorithm>> obj;
obj = typename Algorithm::Builder().SetEpsilon(epsilon).Build().ValueOrDie();
if (obj.ok()){
return std::move(obj.ValueOrDie());
}
else{
throw std::runtime_error(obj.status().error_message());
}
}
std::unique_ptr<Algorithm> Build(double epsilon,
std::optional<T> lower_bound = std::nullopt,
std::optional<T> upper_bound = std::nullopt,
std::optional<int> l0_sensitivity = std::nullopt,
std::optional<int> linf_sensitivity = std::nullopt) {
auto builder = typename Algorithm::Builder();

std::unique_ptr<Algorithm> BuildWithBounds(double epsilon, T lower_bound,
T upper_bound, int l0_sensitivity = 1,
int linf_sensitivity = 1) {
base::StatusOr<std::unique_ptr<Algorithm>> obj;
obj = typename Algorithm::Builder()
.SetEpsilon(epsilon)
.SetLower(lower_bound)
.SetUpper(upper_bound)
.SetMaxPartitionsContributed(l0_sensitivity)
.SetMaxContributionsPerPartition(linf_sensitivity)
.Build();
if (obj.ok()){
return std::move(obj.ValueOrDie());
}
else{
throw std::runtime_error(obj.status().error_message());
}
}
builder.SetEpsilon(epsilon);

std::unique_ptr<Algorithm> BuildWithoutBounds(double epsilon, int l0_sensitivity = 1,
int linf_sensitivity = 1) {
base::StatusOr<std::unique_ptr<Algorithm>> obj;
obj = typename Algorithm::Builder()
.SetEpsilon(epsilon)
.SetMaxPartitionsContributed(l0_sensitivity)
.SetMaxContributionsPerPartition(linf_sensitivity)
.Build();
if (obj.ok()){
return std::move(obj.ValueOrDie());
if (l0_sensitivity.has_value())
builder.SetMaxPartitionsContributed(l0_sensitivity.value());
if (linf_sensitivity.has_value())
builder.SetMaxContributionsPerPartition(linf_sensitivity.value());

if constexpr (is_bounded_algorithm<T, Algorithm>()) {
if (lower_bound.has_value()) builder.SetLower(lower_bound.value());
if (upper_bound.has_value()) builder.SetUpper(upper_bound.value());
}
else{

base::StatusOr<std::unique_ptr<Algorithm>> obj = builder.Build();
if (!obj.ok()) {
throw std::runtime_error(obj.status().error_message());
}

return std::move(obj.ValueOrDie());
}

std::map<std::type_index, std::string> type_to_name = {{typeid(double), "Double"},
Expand Down