blob: fd6a1bb3c10e453ccf5ade89bd80f8765cb230be [file] [log] [blame]
//
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "animals_and_carrots.h"
#include <algorithm>
#include <fstream>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/logging.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "algorithms/bounded-mean.h"
#include "algorithms/bounded-sum.h"
#include "algorithms/count.h"
#include "algorithms/quantiles.h"
#include "proto/data.pb.h"
#include "base/status_macros.h"
namespace differential_privacy {
namespace example {
CarrotReporter::CarrotReporter(std::string data_filename, double epsilon)
: total_epsilon_(epsilon), remaining_epsilon_(epsilon) {
std::ifstream file(data_filename);
CHECK(file.is_open()) << "could not open file " << data_filename;
std::string line;
while (getline(file, line)) {
std::vector<std::string> animal_and_count = absl::StrSplit(line, ',');
CHECK_EQ(animal_and_count.size(), 2);
int count;
CHECK(absl::SimpleAtoi(animal_and_count[1], &count));
carrots_per_animal_[animal_and_count[0]] = count;
}
}
int CarrotReporter::Sum() {
int sum = 0;
for (const auto& pair : carrots_per_animal_) {
sum += pair.second;
}
return sum;
}
double CarrotReporter::Mean() {
return static_cast<double>(Sum()) / carrots_per_animal_.size();
}
int CarrotReporter::CountAbove(int limit) {
int count = 0;
for (const auto& pair : carrots_per_animal_) {
if (pair.second > limit) {
++count;
}
}
return count;
}
int CarrotReporter::Max() {
int max = 0;
for (const auto& pair : carrots_per_animal_) {
max = std::max(pair.second, max);
}
return max;
}
double CarrotReporter::RemainingEpsilon() { return remaining_epsilon_; }
absl::StatusOr<Output> CarrotReporter::PrivateSum(double epsilon) {
if (remaining_epsilon_ < epsilon) {
return absl::InvalidArgumentError("Not enough privacy budget.");
}
remaining_epsilon_ -= epsilon;
ASSIGN_OR_RETURN(std::unique_ptr<BoundedSum<int>> sum_algorithm,
BoundedSum<int>::Builder()
.SetEpsilon(epsilon)
.SetLower(0)
.SetUpper(150)
.Build());
for (const auto& pair : carrots_per_animal_) {
sum_algorithm->AddEntry(pair.second);
}
return sum_algorithm->PartialResult();
}
absl::StatusOr<Output> CarrotReporter::PrivateMean(double epsilon) {
if (remaining_epsilon_ < epsilon) {
return absl::InvalidArgumentError("Not enough privacy budget.");
}
remaining_epsilon_ -= epsilon;
ASSIGN_OR_RETURN(std::unique_ptr<BoundedMean<int>> mean_algorithm,
BoundedMean<int>::Builder().SetEpsilon(epsilon).Build());
for (const auto& pair : carrots_per_animal_) {
mean_algorithm->AddEntry(pair.second);
}
return mean_algorithm->PartialResult();
}
absl::StatusOr<Output> CarrotReporter::PrivateCountAbove(double epsilon,
int limit) {
if (remaining_epsilon_ < epsilon) {
return absl::InvalidArgumentError("Not enough privacy budget.");
}
remaining_epsilon_ -= epsilon;
ASSIGN_OR_RETURN(std::unique_ptr<Count<std::string>> count_algorithm,
Count<std::string>::Builder().SetEpsilon(epsilon).Build());
for (const auto& pair : carrots_per_animal_) {
if (pair.second > limit) {
count_algorithm->AddEntry(pair.first);
}
}
return count_algorithm->PartialResult();
}
absl::StatusOr<Output> CarrotReporter::PrivateMax(double epsilon) {
if (remaining_epsilon_ < epsilon) {
return absl::InvalidArgumentError("Not enough privacy budget.");
}
remaining_epsilon_ -= epsilon;
ASSIGN_OR_RETURN(std::unique_ptr<Quantiles<int>> max_algorithm,
Quantiles<int>::Builder()
.SetEpsilon(epsilon)
.SetLower(0)
.SetUpper(150)
.SetQuantiles({1})
.Build());
for (const auto& pair : carrots_per_animal_) {
max_algorithm->AddEntry(pair.second);
}
return max_algorithm->PartialResult();
}
} // namespace example
} // namespace differential_privacy