Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Exact finite audit of Theorem 4 (the matching EMD lower bound). | |
| The source construction has two truths. They differ only by moving mass | |
| epsilon from day 4 to day 2, while a midpoint prediction is equally close to | |
| both. A deterministic ski-rental policy is a threshold K (or infinity). | |
| Enumerating every threshold proves the two incompatible threshold regions; | |
| the final mixture inequality is Yao's argument for randomized policies. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| from fractions import Fraction | |
| from pathlib import Path | |
| INF = None | |
| def distribution_pair(b: int) -> tuple[dict[int, Fraction], dict[int, Fraction], dict[int, Fraction], Fraction]: | |
| delta = Fraction(1, 8 * b) | |
| epsilon = Fraction(1, 2 * b) + delta | |
| p1 = { | |
| 1: Fraction(1, 2), | |
| 2: Fraction(1, 4), | |
| 4: epsilon, | |
| b + 3: Fraction(1, 4) - epsilon, | |
| } | |
| p2 = { | |
| 1: Fraction(1, 2), | |
| 2: Fraction(1, 4) + epsilon, | |
| b + 3: Fraction(1, 4) - epsilon, | |
| } | |
| midpoint = { | |
| 1: Fraction(1, 2), | |
| 2: Fraction(1, 4) + epsilon / 2, | |
| 4: epsilon / 2, | |
| b + 3: Fraction(1, 4) - epsilon, | |
| } | |
| return p1, p2, midpoint, epsilon | |
| def policy_cost(distribution: dict[int, Fraction], threshold: int | None, b: int) -> Fraction: | |
| if threshold is INF: | |
| return sum(Fraction(day) * mass for day, mass in distribution.items()) | |
| return sum( | |
| (Fraction(day) if day <= threshold else Fraction(threshold + b)) * mass | |
| for day, mass in distribution.items() | |
| ) | |
| def emd(first: dict[int, Fraction], second: dict[int, Fraction]) -> Fraction: | |
| cumulative = Fraction(0) | |
| distance = Fraction(0) | |
| points = sorted(set(first) | set(second)) | |
| for left, right in zip(points, points[1:]): | |
| cumulative += first.get(left, 0) - second.get(left, 0) | |
| distance += abs(cumulative) * (right - left) | |
| return distance | |
| def audit_one(b: int) -> dict: | |
| p1, p2, midpoint, epsilon = distribution_pair(b) | |
| candidates: list[int | None] = list(range(0, b + 4)) + [INF] | |
| costs1 = {k: policy_cost(p1, k, b) for k in candidates} | |
| costs2 = {k: policy_cost(p2, k, b) for k in candidates} | |
| opt1 = min(costs1.values()) | |
| opt2 = min(costs2.values()) | |
| opt1_thresholds = [k for k, value in costs1.items() if value == opt1] | |
| opt2_thresholds = [k for k, value in costs2.items() if value == opt2] | |
| # Buying after the last support point ties rent-forever; the source's | |
| # canonical choice is A_infinity and it is present in the optimum set. | |
| assert INF in opt1_thresholds, opt1_thresholds | |
| assert opt2_thresholds == [2], opt2_thresholds | |
| low = [costs1[k] - opt1 for k in range(4)] | |
| high = [costs2[k] - opt2 for k in candidates if k is INF or k >= 4] | |
| min_low = min(low) | |
| min_high = min(high) | |
| randomized_worst_case = min(min_low, min_high) / 2 | |
| midpoint_emd_1 = emd(midpoint, p1) | |
| midpoint_emd_2 = emd(midpoint, p2) | |
| assert midpoint_emd_1 == epsilon == midpoint_emd_2 | |
| # For q=P(threshold <= 3), p1 loss >= q*min_low and p2 loss >= | |
| # (1-q)*min_high. Their maximum is at least half the smaller constant. | |
| assert randomized_worst_case > 0 | |
| return { | |
| "b": b, | |
| "delta": str(Fraction(1, 8 * b)), | |
| "epsilon": str(epsilon), | |
| "support_max": b + 3, | |
| "prediction_emd_to_p1": str(midpoint_emd_1), | |
| "prediction_emd_to_p2": str(midpoint_emd_2), | |
| "p1_optimal_threshold": "infinity", | |
| "p2_optimal_threshold": 2, | |
| "low_thresholds_0_to_3_loss": [str(value) for value in low], | |
| "min_loss_p1_for_K_le_3": str(min_low), | |
| "min_loss_p2_for_K_ge_4_or_infinity": str(min_high), | |
| "randomized_worst_case_lower_bound": str(randomized_worst_case), | |
| "randomized_bound_over_b_times_emd": float(randomized_worst_case / (b * epsilon)), | |
| "enumerated_deterministic_policies": len(candidates), | |
| } | |
| def main() -> None: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--output", type=Path, required=True) | |
| args = parser.parse_args() | |
| # These are finite support instances, with a nontrivial range of b. | |
| rows = [audit_one(b) for b in (16, 32, 64, 128, 256, 1024, 4096, 16384, 65536, 262144)] | |
| result = { | |
| "theorem": "Theorem 4", | |
| "arithmetic": "exact Fraction", | |
| "rows": rows, | |
| "all_midpoint_emd_equal_epsilon": all( | |
| r["prediction_emd_to_p1"] == r["prediction_emd_to_p2"] == r["epsilon"] for r in rows | |
| ), | |
| "all_optima_match_source": all( | |
| r["p1_optimal_threshold"] == "infinity" and r["p2_optimal_threshold"] == 2 for r in rows | |
| ), | |
| "all_randomized_lower_bounds_positive": all( | |
| Fraction(r["randomized_worst_case_lower_bound"]) > 0 for r in rows | |
| ), | |
| } | |
| args.output.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8") | |
| print(json.dumps(result, indent=2)) | |
| if __name__ == "__main__": | |
| main() | |