def test_not_enough_aggregations(self, use_num_aggregations):
        weights = num_aggregations = None
        if use_num_aggregations:
            num_aggregations = 2
        else:
            weights = [1, 1]  # 2 aggregations
        budget_accountant = NaiveBudgetAccountant(
            total_epsilon=1,
            total_delta=1e-6,
            num_aggregations=num_aggregations,
            aggregation_weights=weights)

        budget_accountant._compute_budget_for_aggregation(1)
        with self.assertRaises(ValueError):
            # num_aggregations = 2, but only 1 aggregation_scope was created
            budget_accountant.compute_budgets()
    def test_num_aggregations(self, num_aggregations):
        total_epsilon, total_delta = 1, 1e-6
        budget_accountant = NaiveBudgetAccountant(
            total_epsilon=total_epsilon,
            total_delta=total_delta,
            num_aggregations=num_aggregations)
        for _ in range(num_aggregations):
            budget = budget_accountant._compute_budget_for_aggregation(1)
            expected_epsilon = total_epsilon / num_aggregations
            expected_delta = total_delta / num_aggregations
            self.assertAlmostEqual(expected_epsilon, budget.epsilon)
            self.assertAlmostEqual(expected_delta, budget.delta)

        budget_accountant.compute_budgets()
    def test_aggregation_weights(self):

        total_epsilon, total_delta = 1, 1e-6
        weights = [1, 2, 5]
        budget_accountant = NaiveBudgetAccountant(total_epsilon=total_epsilon,
                                                  total_delta=total_delta,
                                                  aggregation_weights=weights)
        for weight in weights:
            budget = budget_accountant._compute_budget_for_aggregation(weight)
            expected_epsilon = total_epsilon * weight / sum(weights)
            expected_delta = total_delta * weight / sum(weights)
            self.assertAlmostEqual(expected_epsilon, budget.epsilon)
            self.assertAlmostEqual(expected_delta, budget.delta)

        budget_accountant.compute_budgets()