in fbpcs/emp_games/lift/calculator/OutputMetrics.hpp [696:778]
void OutputMetrics<MY_ROLE>::calculateValue(
const OutputMetrics::GroupType& groupType,
const std::vector<std::vector<emp::Integer>>& purchaseValueArrays,
const std::vector<std::vector<emp::Bit>>& eventArrays,
const std::vector<emp::Bit>& reachedArray) {
XLOG(INFO) << "Calculate " << getGroupTypeStr(groupType) << " value";
std::vector<std::vector<emp::Integer>> valueArrays =
private_measurement::functional::zip_apply(
[](std::vector<emp::Bit> testEvents,
std::vector<emp::Integer> purchaseValues)
-> std::vector<emp::Integer> {
std::vector<emp::Integer> vec;
if (testEvents.size() != purchaseValues.size()) {
XLOG(FATAL) << "Numbers of test event bits and/or purchase "
"values are inconsistent.";
}
for (size_t i = 0; i < testEvents.size(); ++i) {
const emp::Integer zero = emp::Integer{
static_cast<int>(purchaseValues.at(i).size()),
0,
emp::PUBLIC};
vec.emplace_back(
emp::If(testEvents.at(i), purchaseValues.at(i), zero));
}
return vec;
},
eventArrays.begin(),
eventArrays.end(),
purchaseValueArrays.begin());
std::vector<std::vector<emp::Integer>> reachedValue;
if (groupType == GroupType::TEST) {
reachedValue = private_measurement::functional::zip_apply(
[](std::vector<emp::Integer> validValues,
emp::Bit reached) -> std::vector<emp::Integer> {
std::vector<emp::Integer> vec;
for (const auto& validValue : validValues) {
const emp::Integer zero = emp::Integer{
static_cast<int>(validValue.size()), 0, emp::PUBLIC};
vec.emplace_back(emp::If(reached, validValue, zero));
}
return vec;
},
valueArrays.begin(),
valueArrays.end(),
reachedArray.begin());
metrics_.testValue = sum(valueArrays);
metrics_.reachedValue = sum(reachedValue);
} else {
metrics_.controlValue = sum(valueArrays);
}
// And compute for breakdowns + cohorts
// TODO: These could be abstracted into a common function
for (size_t i = 0; i < numPublisherBreakdowns_; ++i) {
auto groupInts = private_measurement::secret_sharing::multiplyBitmask(
valueArrays, publisherBitmasks_.at(i));
if (groupType == GroupType::TEST) {
publisherBreakdowns_[i].testValue = sum(groupInts);
auto reachedGroupInts =
private_measurement::secret_sharing::multiplyBitmask(
reachedValue, publisherBitmasks_.at(i));
publisherBreakdowns_[i].reachedValue = sum(reachedGroupInts);
} else {
publisherBreakdowns_[i].controlValue = sum(groupInts);
}
}
for (size_t i = 0; i < numPartnerCohorts_; ++i) {
auto groupInts = private_measurement::secret_sharing::multiplyBitmask(
valueArrays, partnerBitmasks_.at(i));
if (groupType == GroupType::TEST) {
cohortMetrics_[i].testValue = sum(groupInts);
auto reachedGroupInts =
private_measurement::secret_sharing::multiplyBitmask(
reachedValue, partnerBitmasks_.at(i));
cohortMetrics_[i].reachedValue = sum(reachedGroupInts);
} else {
cohortMetrics_[i].controlValue = sum(groupInts);
}
}
}