From e18a3e73634bf031f96f92469d47d56e091443bf Mon Sep 17 00:00:00 2001 From: Daniel Rosel Date: Wed, 8 Apr 2026 11:58:20 +0200 Subject: [PATCH] scary --- Makefile | 20 +- paper/defense/manim/requirements.txt | 2 - paper/src/chapters/03-methodology.tex | 2 +- paper/src/chapters/04-results.tex | 10 +- paper/src/chapters/06-conclusion.tex | 4 +- .../legacy/first_sweep_headline_summary.json | 10 - .../legacy/first_sweep_tier_alpha_deltas.csv | 31 -- .../first_sweep_tier_alpha_mode_summary.csv | 61 ---- .../legacy/first_sweep_tier_mode_summary.csv | 11 - .../legacy/first_sweep_top_configs.csv | 26 -- .../legacy/plots/first_sweep_tier_revenue.pdf | Bin 17510 -> 0 bytes .../legacy/plots/ppo_alpha_curves.pdf | Bin 25398 -> 0 bytes .../legacy/plots/ppo_delta_curves.pdf | Bin 21999 -> 0 bytes .../legacy/plots/ppo_tradeoff_scatter.pdf | Bin 26824 -> 0 bytes .../generated/legacy/ppo_alpha_deltas.csv | 7 - .../legacy/ppo_alpha_mode_summary.csv | 13 - .../legacy/ppo_headline_summary.json | 7 - .../legacy/ppo_overall_mode_summary.csv | 3 - .../legacy/ppo_pairwise_win_rates.csv | 25 -- .../{final => }/final_focus_coi_by_alpha.tex | 0 .../final_focus_coi_preservation_grid.tex | 0 .../final_focus_revenue_by_alpha.tex | 0 .../{final => }/final_focus_revenue_delta.tex | 0 .../{final => }/final_focus_risk_deltas.tex | 0 .../legacy/first_sweep_tier_revenue.tex | 1 - .../includes/legacy/ppo_alpha_curves.tex | 1 - .../includes/legacy/ppo_delta_curves.tex | 1 - .../includes/legacy/ppo_tradeoff_scatter.tex | 1 - .../chapters/figures/results/plot_results.py | 313 ------------------ .../figures/results/process_all_results.py | 51 --- .../figures/results/process_final_sweeps.py | 2 +- .../figures/results/process_first_sweep.py | 272 --------------- .../figures/results/process_ppo_benchmark.py | 277 ---------------- .../figures/results/revenue_alpha_classic.py | 63 ---- paper/src/chapters/mdp_agent.pdf | Bin 10932 -> 10932 bytes paper/src/chapters/mdp_human.pdf | Bin 11953 -> 11953 bytes 36 files changed, 28 insertions(+), 1186 deletions(-) delete mode 100644 paper/defense/manim/requirements.txt delete mode 100644 paper/src/chapters/figures/results/generated/legacy/first_sweep_headline_summary.json delete mode 100644 paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_deltas.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_mode_summary.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_mode_summary.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/first_sweep_top_configs.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/plots/first_sweep_tier_revenue.pdf delete mode 100644 paper/src/chapters/figures/results/generated/legacy/plots/ppo_alpha_curves.pdf delete mode 100644 paper/src/chapters/figures/results/generated/legacy/plots/ppo_delta_curves.pdf delete mode 100644 paper/src/chapters/figures/results/generated/legacy/plots/ppo_tradeoff_scatter.pdf delete mode 100644 paper/src/chapters/figures/results/generated/legacy/ppo_alpha_deltas.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/ppo_alpha_mode_summary.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/ppo_headline_summary.json delete mode 100644 paper/src/chapters/figures/results/generated/legacy/ppo_overall_mode_summary.csv delete mode 100644 paper/src/chapters/figures/results/generated/legacy/ppo_pairwise_win_rates.csv rename paper/src/chapters/figures/results/includes/{final => }/final_focus_coi_by_alpha.tex (100%) rename paper/src/chapters/figures/results/includes/{final => }/final_focus_coi_preservation_grid.tex (100%) rename paper/src/chapters/figures/results/includes/{final => }/final_focus_revenue_by_alpha.tex (100%) rename paper/src/chapters/figures/results/includes/{final => }/final_focus_revenue_delta.tex (100%) rename paper/src/chapters/figures/results/includes/{final => }/final_focus_risk_deltas.tex (100%) delete mode 100644 paper/src/chapters/figures/results/includes/legacy/first_sweep_tier_revenue.tex delete mode 100644 paper/src/chapters/figures/results/includes/legacy/ppo_alpha_curves.tex delete mode 100644 paper/src/chapters/figures/results/includes/legacy/ppo_delta_curves.tex delete mode 100644 paper/src/chapters/figures/results/includes/legacy/ppo_tradeoff_scatter.tex delete mode 100644 paper/src/chapters/figures/results/plot_results.py delete mode 100644 paper/src/chapters/figures/results/process_all_results.py delete mode 100644 paper/src/chapters/figures/results/process_first_sweep.py delete mode 100644 paper/src/chapters/figures/results/process_ppo_benchmark.py delete mode 100644 paper/src/chapters/figures/results/revenue_alpha_classic.py diff --git a/Makefile b/Makefile index 9e2d5d2..754751c 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ SWEEP_ENV_LOAD = set -a; [ -f "$(SWEEP_ENV_FILE)" ] && . "$(SWEEP_ENV_FILE)" || .PHONY: help help: - @echo "pdf.build pdf.watch pdf.clean pdf.genpop pdf.genpop.watch pdf.arxiv | test.backend test.e2e test.all | web.dev | install | train | benchmark | benchmark.simple | benchmark.agent | train.agent | train.bootstrap | stats.lines | manim.render manim.render.all" + @echo "pdf.build pdf.watch pdf.clean pdf.genpop pdf.genpop.watch pdf.arxiv | test.backend test.e2e test.all | web.dev | install | train | benchmark | benchmark.simple | benchmark.agent | train.agent | train.bootstrap | stats.lines | manim.defense manim.defense.hq manim.render manim.render.full manim.render.poster manim.render.appendix manim.render.all" @echo "backend.server backend.provider backend.worker | platform.up platform.down platform.logs | docker.train.publish" @echo "data.pull data.push data.whoclicked.publish | study.margin-erosion study.margin-erosion.quick study.margin-erosion.plot" @echo "tpu.ray.bootstrap tpu.ray.deps tpu.ray.verify tpu.ray.teardown" @@ -235,9 +235,25 @@ count-lines: all: @$(NX) run paper:build -.PHONY: manim.render manim.render.all +.PHONY: manim.defense manim.defense.hq manim.render manim.render.full manim.render.poster manim.render.appendix manim.render.all +# Main defense reel (paper/defense/manim/render_defense); uses paper/defense/.venv when present +manim.defense: + @cd paper/defense/manim && ./render_defense full + +manim.defense.hq: + @cd paper/defense/manim && ./render_defense full --quality qh + manim.render: @$(NX) run manim:render +manim.render.full: + @$(NX) run manim:render-full + +manim.render.poster: + @$(NX) run manim:render-poster + +manim.render.appendix: + @$(NX) run manim:render-appendix + manim.render.all: @$(NX) run manim:render-all diff --git a/paper/defense/manim/requirements.txt b/paper/defense/manim/requirements.txt deleted file mode 100644 index 4da4506..0000000 --- a/paper/defense/manim/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -manim>=0.18,<1 -numpy>=1.24 diff --git a/paper/src/chapters/03-methodology.tex b/paper/src/chapters/03-methodology.tex index 4fec8a0..d6144d7 100644 --- a/paper/src/chapters/03-methodology.tex +++ b/paper/src/chapters/03-methodology.tex @@ -304,7 +304,7 @@ $\mathcal{A}_{\text{filter}}$ & \texttt{search}, \texttt{filter\_date}, \texttt{ This partition enables the weight function $\omega$ from Eq.~\ref{eq:qhat} to assign category-specific signal strengths, with $\omega(\mathcal{A}_{\text{cart}}) > \omega(\mathcal{A}_{\text{dwell}}) > \omega(\mathcal{A}_{\text{nav}}) > \omega(\mathcal{A}_{\text{filter}})$ reflecting decreasing commitment. It's important to acknowledge that this creates a very blatant assumption in the weighting, and we motivate the scale of each weight by the per-category observed divergence between each behavioral profile. In the simulator baseline this order is encoded with a compact fixed scale: cart $=4.0$, dwell $=2.0$, nav $=1.0$, filter $=0.5$. Unknown actions are mapped by prefix heuristics to the nearest category. -We back this up by saying that each weight was assigned by observing an initial small dataset and computing KL divergence between each interaction type; the ones with the highest divergence receive a proportionately high weight in our demand estimation. +We back this up by saying that each weight was assigned by observing an initial small dataset and computing KL divergence between each interaction type; the ones with the highest divergence receive a proportionately high weight in our demand estimation. From the order which we observe in divergences, we assign a multiple of 2 increase in weight ascending form the lowest weight of $0.5$ in rare filtering operations. The metadata record $\mu$ varies by action type. For product views, $\mu$ contains the observed price $p_{\text{obs}}$ and product attributes. For dwell events, $\mu$ includes the element text and accumulated hover duration. This heterogeneous structure is captured via a schema-on-read approach in our Kafka ingestion pipeline, where events are validated against type-specific schemas before storage. diff --git a/paper/src/chapters/04-results.tex b/paper/src/chapters/04-results.tex index a9c9ae2..f661bd3 100644 --- a/paper/src/chapters/04-results.tex +++ b/paper/src/chapters/04-results.tex @@ -73,35 +73,35 @@ In our complete training runs we logged $\approx 180$ days of net compute time. \begin{figure}[ht] \centering - \input{chapters/figures/results/includes/final/final_focus_revenue_by_alpha.tex} + \input{chapters/figures/results/includes/final_focus_revenue_by_alpha.tex} \caption{Revenue curves by contamination for the final cohort. The baseline remains above the defended curve in most cells, but the gap narrows in the high-contamination region.} \label{fig:final_focus_revenue_by_alpha} \end{figure} \begin{figure}[ht] \centering - \input{chapters/figures/results/includes/final/final_focus_coi_by_alpha.tex} + \input{chapters/figures/results/includes/final_focus_coi_by_alpha.tex} \caption{COI level curves by contamination for the final cohort. The shaded band marks the per-$\alpha$ gap between defended and baseline policies.} \label{fig:final_focus_coi_by_alpha} \end{figure} \begin{figure}[ht] \centering - \input{chapters/figures/results/includes/final/final_focus_coi_preservation_grid.tex} + \input{chapters/figures/results/includes/final_focus_coi_preservation_grid.tex} \caption{COI preservation by product count at the contamination endpoints ($\alpha=0.0$ and $\alpha=1.0$). Bars report defended-minus-baseline mean COI level, with the zero line separating preservation from erosion.} \label{fig:final_focus_coi_preservation_grid} \end{figure} \begin{figure}[ht] \centering - \input{chapters/figures/results/includes/final/final_focus_revenue_delta.tex} + \input{chapters/figures/results/includes/final_focus_revenue_delta.tex} \caption{Defended-minus-baseline revenue delta over contamination for the final cohort. The strongest high-contamination deviation begins at $\alpha=0.7$, followed by recovery toward near parity by $\alpha=1.0$.} \label{fig:final_focus_revenue_delta} \end{figure} \begin{figure}[ht] \centering - \input{chapters/figures/results/includes/final/final_focus_risk_deltas.tex} + \input{chapters/figures/results/includes/final_focus_risk_deltas.tex} \caption{Defended-minus-baseline leakage and volatility deltas for the final cohort. Leakage remains lower for the defended policy across the full contamination range.} \label{fig:final_focus_risk_deltas} \end{figure} diff --git a/paper/src/chapters/06-conclusion.tex b/paper/src/chapters/06-conclusion.tex index a905bbb..34b01c7 100644 --- a/paper/src/chapters/06-conclusion.tex +++ b/paper/src/chapters/06-conclusion.tex @@ -21,4 +21,6 @@ Now we very explicitly mention what we contribute in this paper: \subsection{Future Works and Next Steps} -During the eights months of research dedicated to this work, a plethora of opportunities and industry gaps was identified, sadly a majority of which could not be addressed directly. +In our effort to tackle this work we initiated a set of constraints which we hope to relax in future iterations and hope that some of these will be addressed in industry. First of these constraints is the weighting of different actions within the demand estimation, which we would ideally find through learned methodology. Next, assumption of perfect alternating turns between the platform and the market calls for a fixed length non-strictly alternating state definition with a history of actions to possibly allow for the development of multi agentic or multi platform simulation. In our simulation we also make assumptions of non-perishable supply of items, which creates the biggest sim-to-real gap in our system. We also would like to further remove intra-session stationary nature of the contamination parameter to further create high-fidelity non-stationarity within a single evaluation window. + +For deployment of this it is advised to collect a higher sample size of human baselines and to complement this with the simulated agentic sessions and to mind the matrix scaling for very large catalog sizes. diff --git a/paper/src/chapters/figures/results/generated/legacy/first_sweep_headline_summary.json b/paper/src/chapters/figures/results/generated/legacy/first_sweep_headline_summary.json deleted file mode 100644 index caf3d15..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/first_sweep_headline_summary.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "runs": 340, - "tiers": 5, - "alphas": 6, - "status": "ok", - "mean_tier_revenue_robust": 190714.62212212436, - "mean_tier_revenue_no_robust": 197371.17216609977, - "mean_tier_revenue_delta": -6656.5500439754105, - "mean_tier_revenue_delta_pct": -3.3726050116242514 -} \ No newline at end of file diff --git a/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_deltas.csv b/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_deltas.csv deleted file mode 100644 index fcddcd6..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_deltas.csv +++ /dev/null @@ -1,31 +0,0 @@ -tier,alpha,runs_robust,runs_no_robust,eval_revenue_mean_delta,eval_revenue_mean_delta_pct,eval_reward_mean_delta,eval_reward_mean_delta_pct,eval_coi_level_mean_delta,eval_coi_level_mean_delta_pct,eval_margin_mean_delta,eval_margin_mean_delta_pct,objective_score_delta,objective_score_delta_pct,train_alpha_adv_delta,train_alpha_adv_delta_pct -dqn,0.0,5.0,2.0,-31308.987414117495,-8.73651226889534,-1909.7427407095092,-0.5742991901121623,-2.8982436567700063,-2.1108702433020436,-0.001972064237093285,-0.2116777198290971,-1909.7427407095092,-0.5742991901121623,, -dqn,0.1,8.0,4.0,-7723.542755668925,-2.2789188721535494,-74239.37371836061,-21.063854618469847,1.7435833801418141,1.2859365583872486,0.0011891962142838164,0.1278074871971924,-74239.37371836061,-21.063854618469847,0.17619791666666657,176.19791666666694 -dqn,0.25,7.0,3.0,-12344.82818986749,-3.7035466052614323,93154.03627578515,36.06691230407512,0.03214544949867104,0.023426184113378143,1.763733457238459e-05,0.001893256490383175,93154.03627578515,36.06691230407512,0.14530952380952394,58.12380952380958 -dqn,0.4,5.0,10.0,-7816.300706216833,-2.4694340725162824,-42362.74668471434,-13.411888482380219,0.6251272343707797,0.4579446603861758,0.0002750615520492605,0.02953644634355915,-42362.74668471434,-13.411888482380219,0.09856666666666747,24.64166666666691 -dqn,0.6,5.0,4.0,-16150.011887742497,-5.347485987139731,-28508.74710866122,-10.151356300001888,-0.63306323164079,-0.46056970247177387,-0.00034537433455417155,-0.0370668515552649,-28508.74710866122,-10.151356300001888,0.1361999999999981,22.699999999999644 -dqn,0.8,7.0,6.0,-18191.8826663699,-6.440527544692988,-55296.94441124235,-20.19273590083627,-0.796733634735034,-0.579832425016392,-0.0006423984775592029,-0.0689476165584585,-55296.94441124235,-20.19273590083627,0.1532857142857158,19.160714285714512 -linear,0.0,9.0,8.0,-14967.67388588126,-4.273413942959129,-20107.23171681742,-6.60039931288617,-0.06127790826209889,-0.04564810574240612,-7.607744079518586e-05,-0.008177885913528719,-20107.23171681742,-6.60039931288617,, -linear,0.1,3.0,5.0,-24531.399901538738,-7.171831328305365,-96669.7835552101,-26.44920711447249,-0.3680976907859872,-0.2733723058172187,-0.0002515287835096469,-0.02702956778346356,-96669.7835552101,-26.44920711447249,, -linear,0.25,6.0,9.0,-14840.859479571285,-4.520682292638562,-26510.179456423968,-8.033117756667396,-0.13734776448131925,-0.10212641096230607,-9.41162442338328e-05,-0.010115001392981545,-26510.179456423968,-8.033117756667396,, -linear,0.4,4.0,11.0,-17196.7642560167,-5.486915251242723,-74520.10209817477,-25.042311510043184,0.12217076984330788,0.09098828726103136,0.00010713887099822461,0.011516865671259795,-74520.10209817477,-25.042311510043184,, -linear,0.6,5.0,3.0,-14284.06615788641,-4.854766876637072,38417.71856593515,14.088596762512362,0.24251461234271687,0.1806530855220358,0.0002606811969937395,0.028024824619509187,38417.71856593515,14.088596762512362,, -linear,0.8,4.0,11.0,-10840.488575784548,-3.933600919557566,15749.581078662042,6.447651726824251,0.028051260535562506,0.020876236575910773,5.361882659971062e-05,0.005763158099097226,15749.581078662042,6.447651726824251,, -qtable,0.0,9.0,8.0,-18644.457288398524,-8.15323701554329,32993.42568058451,20.675688115613053,10.369779227648095,10.682768960780463,0.018566897519637582,2.0803084179092814,32993.42568058451,20.675688115613053,0.11839814814814797, -qtable,0.1,6.0,5.0,-12549.400855549495,-4.616991193742389,-37207.79701261924,-15.336047254435487,0.0884057957559321,0.07703761042583206,-0.01127789819771663,-1.2272540823820444,-37207.79701261924,-15.336047254435487,0.07577777777777787,75.77777777777803 -qtable,0.25,6.0,5.0,-1534.3527429780224,-0.5456640130847226,18433.43663451099,7.304472653867784,-0.5776125938941306,-0.45734160960552755,-0.003316338490628068,-0.3584028328803385,18433.43663451099,7.304472653867784,0.1181458333333334,47.258333333333354 -qtable,0.4,8.0,6.0,-15146.258176090778,-5.274860187729517,-37364.22587794208,-13.005651205148677,0.4611471727478005,0.3629050099230144,0.0071046453227539,0.7751478467862876,-37364.22587794208,-13.005651205148677,0.11010416666666772,27.52604166666698 -qtable,0.6,6.0,6.0,-9577.578548656049,-3.9322693501816666,-19088.152339068736,-9.571307395166029,0.9081750157567683,0.7495917946306662,0.0015520804425310786,0.16838348372043557,-19088.152339068736,-9.571307395166029,0.16983333333333228,28.305555555555333 -qtable,0.8,5.0,2.0,-52751.680936846446,-19.699089872409548,-16508.209313987172,-7.589601869470744,-15.022454081083623,-11.215398490282094,-0.007791824761087751,-0.8384414846099099,-16508.209313987172,-7.589601869470744,0.11120000000000174,13.900000000000245 -static,0.0,5.0,6.0,-4782.871053113384,-5.233544525848519,14411.4689779756,25.538141347978577,1.307060701942973,1.8731997380823568,0.002537468952847566,0.2911381045328444,14411.4689779756,25.538141347978577,, -static,0.1,8.0,5.0,1629.4524528499896,1.880088900553112,-5347.078589385725,-8.14812684380662,0.3600324838305795,0.5019134064795009,-4.6492644957929485e-05,-0.005316014641356001,-5347.078589385725,-8.14812684380662,, -static,0.25,5.0,6.0,-9938.662276761897,-10.398087633377964,-23616.087243780566,-27.701108621456626,-3.0513860773271233,-4.099238223547561,-0.003519771479853273,-0.40113716461596144,-23616.087243780566,-27.701108621456626,, -static,0.4,3.0,4.0,1850.8400595222774,2.1912497828943436,15058.659457798465,23.67199439061036,3.669612467486587,5.430169778169349,0.006763447803564415,0.7804393835882188,15058.659457798465,23.67199439061036,, -static,0.6,6.0,5.0,1038.893948415236,1.2765037688226162,-6062.864079504681,-9.363144945348399,-1.712609061865976,-2.3996341009364213,-0.0042285583442709385,-0.48362088973179423,-6062.864079504681,-9.363144945348399,, -static,0.8,3.0,7.0,2696.6340631967323,3.6826150812750567,149.22406835677975,0.27280281303997084,0.8491716126507072,1.2427748744725668,0.0032786525965587954,0.3777595573932637,149.22406835677975,0.27280281303997084,, -surge,0.0,6.0,6.0,-606.73760243367,-5.066579306500225,-244.17585425326251,-5.525800641331023,0.014874931199557295,0.09186560988877175,0.0019308940532419272,0.4471794260021321,-244.17585425326251,-5.525800641331023,, -surge,0.1,2.0,5.0,169.78743573408792,1.446343107913299,-1012.7706974660168,-20.02053666691211,-0.14459518037699226,-0.864651254901582,-0.0018650458785858248,-0.4260349899970559,-1012.7706974660168,-20.02053666691211,, -surge,0.25,10.0,7.0,-128.20993816584632,-1.1276930411162496,-81.21373487263281,-1.7081453033360994,0.3008506477195141,1.839047728806548,0.0030750148302954305,0.7102446987902812,-81.21373487263281,-1.7081453033360994,, -surge,0.4,6.0,6.0,-473.03722764431404,-4.297928307550563,28.557452243338048,0.6755106104955642,-0.5027452173053764,-3.072002360121898,-0.005581380442163164,-1.288152985482699,28.557452243338048,0.6755106104955642,, -surge,0.6,2.0,5.0,307.79436325796996,3.0356727142643067,2060.57396030564,63.382050333909866,0.2339650444065704,1.438519400758399,0.001302270025389629,0.30077697380833807,2060.57396030564,63.382050333909866,, -surge,0.8,3.0,3.0,423.15386247993047,4.372210191290083,1117.0942083304312,34.86182570616373,0.8971464536957541,5.327339899805159,0.007068630716831503,1.6094191039618562,1117.0942083304312,34.86182570616373,, diff --git a/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_mode_summary.csv b/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_mode_summary.csv deleted file mode 100644 index dba8d81..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_alpha_mode_summary.csv +++ /dev/null @@ -1,61 +0,0 @@ -tier,alpha,mode,runs,eval_revenue_mean_mean,eval_revenue_mean_std,eval_reward_mean_mean,eval_reward_mean_std,eval_coi_level_mean_mean,eval_coi_level_mean_std,eval_margin_mean_mean,eval_margin_mean_std,objective_score_mean,objective_score_std,train_alpha_adv_mean,train_alpha_adv_std -dqn,0.0,no_robust,2,358369.40933039243,3531.782519351935,332534.46523867303,114183.5587841961,137.30089123035202,0.8184776440325546,0.9316352418598786,0.0006839003676302996,332534.46523867303,114183.5587841961,, -dqn,0.0,robust,5,327060.42191627494,24311.17412598574,330624.7224979635,62834.39223547943,134.40264757358202,6.160000643680792,0.9296631776227853,0.004262039730140749,330624.7224979635,62834.39223547943,0.17835000000000004,0.08829347371125472 -dqn,0.1,no_robust,4,338912.58043645386,19584.736810155388,352449.13650924934,34076.74819101191,135.58860029055563,3.4055508991301524,0.9304589585186211,0.0023438665484978773,352449.13650924934,34076.74819101191,0.0999999999999998,0.0 -dqn,0.1,robust,8,331189.03768078494,8060.912085646968,278209.7627908887,57861.69545853692,137.33218367069745,0.43113256118808096,0.931648154732905,0.000296560958972609,278209.7627908887,57861.69545853692,0.2761979166666664,0.09826648189130198 -dqn,0.25,no_robust,3,333324.4996115304,6101.717861804452,258281.15112936878,46772.05216097596,137.2201692904545,0.9866477887862672,0.9315871706751672,0.0006356053229300815,258281.15112936878,46772.05216097596,0.25,0.0 -dqn,0.25,robust,7,320979.6714216629,7345.8761269427705,351435.18740515393,40320.63699261721,137.25231473995316,0.3527287960309152,0.9316048080097395,0.0002575240668471541,351435.18740515393,40320.63699261721,0.39530952380952394,0.073021206240698 -dqn,0.4,no_robust,10,316521.94295076875,3631.1820920182718,315859.66987697606,59129.03566963754,136.50715652926755,0.5085743959240285,0.931261495881483,0.00031280530251053175,315859.66987697606,59129.03566963754,0.3999999999999993,0.0 -dqn,0.4,robust,5,308705.6422445519,10654.571556448245,273496.9231922617,68868.59270778317,137.13228376363833,0.9543108715306617,0.9315365574335323,0.0006302636717132419,273496.9231922617,68868.59270778317,0.49856666666666677,0.05745573175159429 -dqn,0.6,no_robust,4,302011.2988903938,2354.1141598720183,280836.828756133,58683.00124997926,137.4522093492651,0.4692723362517602,0.9317606434396914,0.0003317518021682495,280836.828756133,58683.00124997926,0.600000000000001,0.0 -dqn,0.6,robust,5,285861.2870026513,10386.571631344234,252328.08164747176,59388.56063758225,136.8191461176243,1.0629203361893034,0.9314152691051373,0.0005692783702932289,252328.08164747176,59388.56063758225,0.7361999999999991,0.07108625433623189 -dqn,0.8,no_robust,6,282459.51189759385,2625.018247527438,273845.72691287595,66378.16690732416,137.4075681801531,0.29728950101826707,0.9317196295169007,0.00022799290978965786,273845.72691287595,66378.16690732416,0.7999999999999985,0.0 -dqn,0.8,robust,7,264267.62923122395,6771.288971321149,218548.7825016336,50043.2009443344,136.61083454541807,1.2319662937254596,0.9310772310393415,0.0010118564779437284,218548.7825016336,50043.2009443344,0.9532857142857143,0.04709817507333055 -linear,0.0,no_robust,8,350250.9723061577,3156.286820918861,304636.59490360576,71682.88027353655,134.2397614654424,0.32611787466946035,0.9302824910938235,0.00024020749661685483,304636.59490360576,71682.88027353655,, -linear,0.0,robust,9,335283.29842027643,7707.594869976611,284529.36318678834,55524.58819004573,134.1784835571803,0.4477314164684001,0.9302064136530284,0.00034781034181738526,284529.36318678834,55524.58819004573,, -linear,0.1,no_robust,5,342052.1032713031,2576.546352056584,365492.17954557994,44890.93522299766,134.65068807375954,0.2181027640393531,0.930569018064469,0.00014058935916940913,365492.17954557994,44890.93522299766,, -linear,0.1,robust,3,317520.7033697644,4796.580459456527,268822.39599036984,39256.421140635124,134.28259038297355,0.24570499109363475,0.9303174892809594,0.00018817899183709092,268822.39599036984,39256.421140635124,, -linear,0.25,no_robust,9,328288.0441241802,2178.525494145428,330011.0898339667,38591.36053388808,134.48799697074742,0.2199303973026469,0.9304619997297959,0.00015341642413402035,330011.0898339667,38591.36053388808,, -linear,0.25,robust,6,313447.18464460893,11811.426711620714,303500.9103775427,63358.917144214036,134.3506492062661,0.2947034403278951,0.9303678834855621,0.00021446628431268986,303500.9103775427,63358.917144214036,, -linear,0.4,no_robust,11,313414.0672597746,1982.9537556159262,297576.7714904776,69396.90446617964,134.2708754290745,0.3062093691351849,0.9302780292522507,0.00023067974755288992,297576.7714904776,69396.90446617964,, -linear,0.4,robust,4,296217.3030037579,5109.898340355844,223056.66939230284,38293.73688466607,134.3930461989178,0.12347753686382154,0.9303851681232489,7.324605809708878e-05,223056.66939230284,38293.73688466607,, -linear,0.6,no_robust,3,294227.64307441004,2081.9176570448135,272686.62176604365,66672.50905805513,134.24327165069943,0.30764332256042104,0.9301795837547151,0.00020453921786790446,272686.62176604365,66672.50905805513,, -linear,0.6,robust,5,279943.5769165236,9866.031719660255,311104.3403319788,28363.930707781863,134.48578626304214,0.21280262186464388,0.9304402649517088,0.00020533894868120649,311104.3403319788,28363.930707781863,, -linear,0.8,no_robust,11,275586.89347174135,1618.038877505867,244268.4832547461,56201.44465269986,134.36933631960773,0.2845660213184439,0.9303723007028001,0.00017640716421186918,244268.4832547461,56201.44465269986,, -linear,0.8,robust,4,264746.4048959568,7976.6279174956235,260018.06433340814,57942.49882730146,134.3973875801433,0.31511916357643405,0.9304259195293998,0.00023606570471334208,260018.06433340814,57942.49882730146,, -qtable,0.0,no_robust,8,228675.52179404112,103199.70453252994,159575.94976328663,95848.81008103945,97.07014413321637,33.0637115678536,0.8925069648229078,0.04890522141482132,159575.94976328663,95848.81008103945,0.0,0.0 -qtable,0.0,robust,9,210031.0645056426,84361.3834579348,192569.37544387113,116824.7880426837,107.43992336086447,21.41128645838254,0.9110738623425454,0.019188350719133364,192569.37544387113,116824.7880426837,0.11839814814814797,0.061909456985161225 -qtable,0.1,no_robust,5,271809.0706466638,14898.209045050968,242616.60384397948,49181.45526408063,114.75666919996793,3.461383158930426,0.9189538140159812,0.002294693249439748,242616.60384397948,49181.45526408063,0.0999999999999998,0.0 -qtable,0.1,robust,6,259259.66979111428,102995.29934229614,205408.80683136024,94155.1845420674,114.84507499572386,36.206421837506966,0.9076759158182646,0.048591979839360346,205408.80683136024,94155.1845420674,0.17577777777777767,0.06720562696899951 -qtable,0.25,no_robust,5,281190.01916657295,70274.10208723843,252358.2126733039,129868.46825082717,126.29784427276161,15.368804047323954,0.9253103453385114,0.009044883517550522,252358.2126733039,129868.46825082717,0.25,0.0 -qtable,0.25,robust,6,279655.6664235949,93056.2549557545,270791.6493078149,116021.46257259768,125.72023167886748,26.760714047253796,0.9219940068478834,0.022785695882060884,270791.6493078149,116021.46257259768,0.3681458333333334,0.08845114686619042 -qtable,0.4,no_robust,6,287140.4669895195,32698.16434426399,287292.23388022534,83855.95000252876,127.07104066863859,9.200301166154173,0.9165535777734913,0.01306001923887748,287292.23388022534,83855.95000252876,0.3999999999999993,0.0 -qtable,0.4,robust,8,271994.2088134287,79259.3185780895,249928.00800228326,88265.30801790548,127.53218784138639,23.406428094683015,0.9236582230962452,0.020073747007871224,249928.00800228326,88265.30801790548,0.510104166666667,0.09294655989347765 -qtable,0.6,no_robust,6,243563.64469828535,67006.60707045678,199430.98211127534,79119.52886604435,121.15594411011905,17.91243944823949,0.9217533740470492,0.011558797825966702,199430.98211127534,79119.52886604435,0.600000000000001,0.0 -qtable,0.6,robust,6,233986.0661496293,43155.478617087436,180342.8297722066,48117.79957836251,122.06411912587582,12.160951090203252,0.9233054544895802,0.006840854872863436,180342.8297722066,48117.79957836251,0.7698333333333333,0.09107066853090896 -qtable,0.8,no_robust,2,267787.4017455507,1552.038101264713,217510.87340156303,45358.788584678456,133.9448981157492,0.47346860040111405,0.9293224278749692,0.0002998116010539045,217510.87340156303,45358.788584678456,0.7999999999999985,0.0 -qtable,0.8,robust,5,215035.72080870424,32869.73253165852,201002.66408757586,63247.67956376057,118.92244403466557,8.586916805142152,0.9215306031138815,0.004644709320891907,201002.66408757586,63247.67956376057,0.9112000000000002,0.07381653307732307 -static,0.0,no_robust,6,91388.75248869567,13415.65534300268,56431.15832748852,8525.098185703384,69.77689967440658,3.670744870085874,0.8715688236409825,0.005831496806767582,56431.15832748852,8525.098185703384,, -static,0.0,robust,5,86605.88143558228,7614.909395960895,70842.62730546412,8033.737230392738,71.08396037634955,3.6802889678420283,0.8741062925938301,0.005083911544334936,70842.62730546412,8033.737230392738,, -static,0.1,no_robust,5,86668.90445290186,8037.955688932984,65623.40881389238,19329.448262530004,71.73199185012882,4.199046495412734,0.874577067494122,0.006610505646022198,65623.40881389238,19329.448262530004,, -static,0.1,robust,8,88298.35690575185,9576.838833058617,60276.33022450666,13359.490452744656,72.0920243339594,6.7706096714767865,0.8745305748491641,0.010083585815241344,60276.33022450666,13359.490452744656,, -static,0.25,no_robust,6,95581.63603909909,8345.698435455577,85253.22060752509,13111.526873622026,74.43788116042678,2.1078820386097368,0.8774483618896327,0.0037254791853004897,85253.22060752509,13111.526873622026,, -static,0.25,robust,5,85642.97376233719,9472.880627242153,61637.13336374452,15937.429780623212,71.38649508309966,4.0264905454627264,0.8739285904097794,0.005323853359397925,61637.13336374452,15937.429780623212,, -static,0.4,no_robust,4,84465.04245981346,12101.831388745604,63613.81812329075,7778.361846092061,67.5782271530322,3.9088888968092,0.8666205147756862,0.007149121199217965,63613.81812329075,7778.361846092061,, -static,0.4,robust,3,86315.88251933573,8642.748496122398,78672.47758108922,17823.74997200773,71.24783962051879,2.790416943786253,0.8733839625792507,0.005990544453538607,78672.47758108922,17823.74997200773,, -static,0.6,no_robust,5,81385.88962988024,12343.523894997037,64752.43216774836,23486.779472906223,71.36959177224794,5.100226704959064,0.874353948320141,0.007787250295491337,64752.43216774836,23486.779472906223,, -static,0.6,robust,6,82424.78357829548,9831.886701625144,58689.56808824368,12672.506035553573,69.65698271038197,3.484982360048201,0.8701253899758701,0.005917711231889304,58689.56808824368,12672.506035553573,, -static,0.8,no_robust,7,73226.06364450825,4447.877985963851,54700.340767716196,14406.881298569717,68.32867561883204,3.68262917356943,0.8679204886788817,0.007467501164611224,54700.340767716196,14406.881298569717,, -static,0.8,robust,3,75922.69770770498,5046.089536162847,54849.564836072976,22780.98012221352,69.17784723148274,1.5268167784698885,0.8711991412754405,0.0033278715575433297,54849.564836072976,22780.98012221352,, -surge,0.0,no_robust,6,11975.290738176132,411.4052900076416,4418.832131346071,896.5828048394391,16.192056219479124,0.8040364003224534,0.4317940274006973,0.008271862690929055,4418.832131346071,896.5828048394391,, -surge,0.0,robust,6,11368.553135742462,623.8217438159004,4174.6562770928085,639.9963040241264,16.20693115067868,0.9853827520149101,0.4337249214539392,0.010371668289035135,4174.6562770928085,639.9963040241264,, -surge,0.1,no_robust,5,11739.084232858655,332.778792718381,5058.659087494994,1110.8409258976824,16.722948073839394,0.6578121995950104,0.4377682402562083,0.005683401047550787,5058.659087494994,1110.8409258976824,, -surge,0.1,robust,2,11908.871668592743,81.41250285550258,4045.8883900289775,784.7169500268457,16.5783528934624,0.4088194924856508,0.4359031943776225,0.004531137621699143,4045.8883900289775,784.7169500268457,, -surge,0.25,no_robust,7,11369.223138855004,236.1121240061105,4754.4980344481255,1038.0550037539617,16.359045119223275,0.3945156775653057,0.4329514652531622,0.0038762110261952457,4754.4980344481255,1038.0550037539617,, -surge,0.25,robust,10,11241.013200689158,684.503587066406,4673.284299575493,1187.78635131025,16.65989576694279,1.0515950311117155,0.4360264800834576,0.009701952962125513,4673.284299575493,1187.78635131025,, -surge,0.4,no_robust,6,11006.168409400554,364.6584583108646,4227.535704048808,1414.7964077877168,16.365391636138824,0.9138430058543858,0.4332855262584901,0.008024003783434592,4227.535704048808,1414.7964077877168,, -surge,0.4,robust,6,10533.13118175624,526.0758051960169,4256.093156292146,783.7965507386594,15.862646418833448,0.7732699435426456,0.42770414581632693,0.008967505611725135,4256.093156292146,783.7965507386594,, -surge,0.6,no_robust,5,10139.2472848498,97.448078425168,3251.037082975553,742.2100315641153,16.26429537781848,0.4432465691073604,0.4329686574409998,0.004121820888165019,3251.037082975553,742.2100315641153,, -surge,0.6,robust,2,10447.04164810777,524.0029334247373,5311.611043281193,1808.6200710093085,16.49826042222505,0.6088756908260344,0.43427092746638946,0.007817511630542989,5311.611043281193,1808.6200710093085,, -surge,0.8,no_robust,3,9678.259826640971,272.83530913170915,3204.3479815026553,556.8799617962688,16.840420745981802,0.4589959822922529,0.43920385308157944,0.004953937449529005,3204.3479815026553,556.8799617962688,, -surge,0.8,robust,3,10101.413689120902,526.8318040489241,4321.442189833087,1284.166148011517,17.737567199677557,0.6586775330563983,0.44627248379841095,0.004644261847052545,4321.442189833087,1284.166148011517,, diff --git a/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_mode_summary.csv b/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_mode_summary.csv deleted file mode 100644 index e296749..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/first_sweep_tier_mode_summary.csv +++ /dev/null @@ -1,11 +0,0 @@ -tier,mode,runs,eval_revenue_mean_mean,eval_revenue_mean_std,eval_reward_mean_mean,eval_reward_mean_std,eval_coi_level_mean_mean,eval_coi_level_mean_std,eval_margin_mean_mean,eval_margin_mean_std,objective_score_mean,objective_score_std,train_alpha_adv_mean,train_alpha_adv_std -dqn,no_robust,29,315185.66674813855,23538.781000060844,302576.8036266896,62951.88633145167,136.82560356086017,1.3692652218935986,0.9313739013618878,0.0009314135057224836,302576.8036266896,62951.88633145167,0.45740740740740693,0.2368477698794438 -dqn,robust,37,306875.13950902375,27585.74444520695,283724.7169827867,69843.05611741856,136.68837571992978,2.3797541654948753,0.9312171495138941,0.0016512408492580111,283724.7169827867,69843.05611741856,0.5058198198198196,0.28324483129860284 -linear,no_robust,47,315501.15296155965,27105.014861872147,298149.1730416604,67664.7308344108,134.36884359609928,0.29743647613433244,0.9303607531364,0.0002152647006739543,298149.1730416604,67664.7308344108,, -linear,robust,31,306269.9232239004,26399.875293394463,279872.824370329,54401.104602086416,134.32737693008372,0.31909212993628877,0.9303375215162144,0.00025000448833182963,279872.824370329,54401.104602086416,, -qtable,no_robust,32,259818.72178238883,67188.58622318009,222088.83510765125,94450.12569617687,116.84641954166946,22.42810298937963,0.9140582213134033,0.02778864370791322,222088.83510765125,94450.12569617687,0.29218749999999993,0.2559326319498438 -qtable,robust,40,244470.50673219413,78666.30912808319,216920.53697298188,93983.50987622296,118.94013969887506,23.1428303249914,0.9178608956089163,0.023827311253270544,216920.53697298188,93983.50987622296,0.4396239583333334,0.29521865862482416 -static,no_robust,33,85228.452028227,12041.415672002751,64828.579890468536,17681.280330831738,70.58818912317687,4.204964531595236,0.8721419294578765,0.007107262779462876,64828.579890468536,17681.280330831738,, -static,robust,30,84963.18577955024,8926.291379160475,63243.76603076817,14880.924342692271,70.94358095957392,4.363134562111469,0.8730306888410219,0.006660289247744752,63243.76603076817,14880.924342692271,, -surge,no_robust,32,11121.867310184698,809.9895800277001,4260.038064073964,1160.4282377968032,16.416108827015794,0.641203520341943,0.43413855082681374,0.006214799767130059,4260.038064073964,1160.4282377968032,, -surge,robust,29,10994.355365953365,750.5115890942825,4448.160863178768,1000.7519971246122,16.495943148858906,0.9823026347466668,0.4347587896392907,0.009698591291108968,4448.160863178768,1000.7519971246122,, diff --git a/paper/src/chapters/figures/results/generated/legacy/first_sweep_top_configs.csv b/paper/src/chapters/figures/results/generated/legacy/first_sweep_top_configs.csv deleted file mode 100644 index e51fd74..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/first_sweep_top_configs.csv +++ /dev/null @@ -1,26 +0,0 @@ -Name,tier,alpha,mode,objective/score,eval/revenue_mean,eval/reward_mean,eval/coi_level_mean,lambda_coi,robust_radius,learning_rate,batch_size,n_steps,total_timesteps -eager-sweep-244,dqn,0.0,no_robust,413274.4339549909,355872.06196128257,413274.4339549909,136.722140138007,0.2,0.1,0.0003,256,4096,15000 -efficient-sweep-319,linear,0.0,no_robust,410094.0151741567,353309.5198146561,410094.0151741567,134.55152038805429,0.4,0.1,0.001,128,4096,15000 -swept-sweep-422,linear,0.0,no_robust,403130.32747386186,347611.2815474988,403130.32747386186,133.8559785775022,0.4,0.3,0.0001,512,1024,15000 -decent-sweep-478,linear,0.1,no_robust,400452.36418713134,345284.5750647792,400452.36418713134,134.73082941975588,0.1,0.2,0.001,128,1024,50000 -eternal-sweep-339,linear,0.1,no_robust,399628.4231731644,344154.38525771734,399628.4231731644,134.89479277649667,0.4,0.1,0.0001,256,1024,50000 -ethereal-sweep-21,dqn,0.1,no_robust,398492.807245857,343580.6802427996,398492.807245857,136.67160732585188,0.1,0.2,0.001,512,2048,50000 -dark-sweep-418,linear,0.1,no_robust,394615.3720658343,339749.76272695075,394615.3720658343,134.39233246711,0.2,0.1,0.0003,256,1024,50000 -wandering-sweep-122,dqn,0.0,robust,394061.3617726404,339512.43434806296,394061.3617726404,137.6864755964331,0.1,0.3,0.0001,256,2048,30000 -laced-sweep-132,dqn,0.1,robust,389274.54998495104,335600.5979215904,389274.54998495104,137.36888574027677,0.4,0.2,0.001,256,2048,30000 -rich-sweep-53,qtable,0.0,robust,388601.2626147048,335630.6853337664,388601.2626147048,133.4414069888203,0.2,0.1,0.0001,512,1024,50000 -faithful-sweep-430,qtable,0.25,no_robust,387035.6970938766,333255.5771210341,387035.6970938766,137.4906091183188,0.1,0.2,0.0003,128,1024,15000 -dark-sweep-280,qtable,0.25,no_robust,386318.8845004527,332220.0316564078,386318.8845004527,137.26992450099925,0.4,0.1,0.0001,256,1024,50000 -chocolate-sweep-383,linear,0.25,no_robust,383989.49015403807,331071.7003244704,383989.49015403807,134.60590742050857,0.1,0.2,0.001,512,1024,30000 -dry-sweep-263,dqn,0.0,robust,383372.6880637367,330436.0312615148,383372.6880637367,137.40558130223476,0.1,0.3,0.001,128,1024,50000 -different-sweep-143,qtable,0.0,robust,383278.4198015018,330546.16800945485,383278.4198015018,135.9021538079678,0.1,0.3,0.001,256,2048,30000 -woven-sweep-139,dqn,0.25,robust,382788.1296637251,329427.735752473,382788.1296637251,136.8968339394894,0.1,0.1,0.001,512,1024,15000 -dark-sweep-215,dqn,0.25,robust,382358.2401374872,329330.0097603144,382358.2401374872,137.64528612332785,0.2,0.1,0.0001,512,4096,30000 -charmed-sweep-136,linear,0.25,no_robust,382249.5728044314,329646.2053260979,382249.5728044314,134.46825608007862,0.4,0.1,0.0001,256,2048,15000 -light-sweep-308,linear,0.0,robust,381939.1275250679,329628.9436641051,381939.1275250679,133.6209821974879,0.2,0.2,0.001,128,4096,30000 -treasured-sweep-325,linear,0.25,robust,381322.0104772589,328353.58675398555,381322.0104772589,134.8950293943581,0.1,0.1,0.0001,512,2048,15000 -fine-sweep-202,dqn,0.25,robust,378751.33572275366,326518.9068184018,378751.33572275366,137.2900973301052,0.1,0.2,0.0001,512,2048,30000 -treasured-sweep-380,linear,0.25,no_robust,377898.0979419424,325869.1953595453,377898.0979419424,134.54118723889738,0.4,0.3,0.001,128,1024,50000 -pretty-sweep-49,qtable,0.25,robust,377318.4766808995,325282.0152823859,377318.4766808995,137.19609012644068,0.4,0.1,0.0001,128,4096,50000 -desert-sweep-253,linear,0.25,robust,376808.6335063269,325146.3478714648,376808.6335063269,134.48396340732663,0.2,0.1,0.0003,256,1024,30000 -jolly-sweep-133,qtable,0.4,no_robust,376419.57394710975,323709.24588324485,376419.57394710975,137.8349363778071,0.1,0.3,0.0001,128,2048,50000 diff --git a/paper/src/chapters/figures/results/generated/legacy/plots/first_sweep_tier_revenue.pdf b/paper/src/chapters/figures/results/generated/legacy/plots/first_sweep_tier_revenue.pdf deleted file mode 100644 index a2787265ff4344842a889b0c132a1c1d8850dad5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17510 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 diff --git a/paper/src/chapters/figures/results/generated/legacy/ppo_alpha_deltas.csv b/paper/src/chapters/figures/results/generated/legacy/ppo_alpha_deltas.csv deleted file mode 100644 index 42cf5c9..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/ppo_alpha_deltas.csv +++ /dev/null @@ -1,7 +0,0 @@ -alpha,runs_robust,runs_no_robust,eval_revenue_mean_robust,eval_revenue_mean_no_robust,eval_revenue_mean_delta,eval_revenue_mean_delta_pct,eval_reward_mean_robust,eval_reward_mean_no_robust,eval_reward_mean_delta,eval_reward_mean_delta_pct,eval_coi_level_mean_robust,eval_coi_level_mean_no_robust,eval_coi_level_mean_delta,eval_coi_level_mean_delta_pct,eval_coi_leakage_mean_robust,eval_coi_leakage_mean_no_robust,eval_coi_leakage_mean_delta,eval_coi_leakage_mean_delta_pct,eval_volatility_mean_robust,eval_volatility_mean_no_robust,eval_volatility_mean_delta,eval_volatility_mean_delta_pct,eval_margin_mean_robust,eval_margin_mean_no_robust,eval_margin_mean_delta,eval_margin_mean_delta_pct,train_alpha_adv_robust,train_alpha_adv_no_robust,train_alpha_adv_delta,train_alpha_adv_delta_pct,train_coi_penalty_robust,train_coi_penalty_no_robust,train_coi_penalty_delta,train_coi_penalty_delta_pct,train_ux_penalty_robust,train_ux_penalty_no_robust,train_ux_penalty_delta,train_ux_penalty_delta_pct,train_agent_prob_robust,train_agent_prob_no_robust,train_agent_prob_delta,train_agent_prob_delta_pct -0.0,4.0,4.0,3379.9042994670963,3565.2912010160844,-185.38690154898813,-5.199768857482219,313527.4707462,331300.229069,-17772.758322799986,-5.364547550342456,137.08358925982625,137.28764358955686,-0.2040543297306101,-0.14863269875959326,0.1146626165658294,0.11861133504329742,-0.003948718477468013,-3.3291240470622716,0.06687153537785637,0.06445662162531288,0.0024149137525434905,3.746572022625408,0.9315273502623671,0.9317078361627993,-0.00018048590043218127,-0.019371512552207898,0.18958333333333333,,,,5.553200113221484,,,,61.35134238638615,66.58479574844135,-5.233453362055201,-7.859832418540847,0.12778212146468534,0.11615891320235115,0.011623208262334192,10.00629907933654 -0.1,4.0,4.0,3307.028238366196,3458.002436284769,-150.97419791857283,-4.365936713473732,306772.49146475,321215.477968,-14442.986503249966,-4.4963544704059375,137.1182041122497,136.82757579763506,0.29062831461465066,0.21240478238427865,0.1128546052304944,0.11704917861668755,-0.004194573386193154,-3.5835991638433753,0.0685405649303561,0.06737596899527175,0.0011645959350843477,1.728503430007924,0.9315331673960889,0.9313276818191593,0.00020548557692967595,0.0220637248243606,0.2818749999999999,0.1,0.18187499999999987,181.87499999999986,5.079528726095333,,,,52.44772950699336,53.288869747139515,-0.841140240146153,-1.578453895039319,0.11644381911386253,0.11765277436070229,-0.0012089552468397546,-1.0275620387270383 -0.25,4.0,4.0,3134.3438215278165,3300.5539051855053,-166.21008365768876,-5.035823938416998,290691.4771835,306522.90003785,-15831.422854350007,-5.16484179563586,136.89990884669214,136.71752459667877,0.18238425001337077,0.1334022471160229,0.11113957413522965,0.1139905600539111,-0.0028509859186814507,-2.50107194607439,0.06427159998376095,0.06846858821082077,-0.004196988227059828,-6.12980103246314,0.9314501501825461,0.9313053225630614,0.0001448276194846443,0.015551035302371268,0.44833333333333336,0.25,0.19833333333333336,79.33333333333334,4.7183804755060255,,,,49.04307009982127,55.2030005738411,-6.159930474019831,-11.158687770568074,0.10998505830218755,0.11684259343269415,-0.0068575351305066035,-5.869037077182653 -0.4,4.0,4.0,2983.852437569374,3180.7872854626567,-196.9348478932825,-6.191386918369099,276545.26309355,295433.5405797,-18888.277486150037,-6.393409986248494,136.19210761854086,136.5783021470118,-0.38619452847095204,-0.2827641890402586,0.10875560547061063,0.11189234314151972,-0.0031367376709090927,-2.8033532794480807,0.07452230347799255,0.07104688223410768,0.003475421243884863,4.891729425132195,0.9307282962514367,0.9310542820602117,-0.0003259858087749645,-0.03501254599824534,0.5999999999999999,0.4000000000000001,0.1999999999999998,49.999999999999936,4.174996403604185,,,,47.99794119802058,50.794260008988424,-2.796318810967847,-5.505186630286606,0.10222958892923095,0.11161526349272373,-0.009385674563492777,-8.408952565976458 -0.6,4.0,4.0,2789.0434220430398,2982.2460998252786,-193.20267778223888,-6.4784283830083,258688.11700405,277051.95613675,-18363.8391327,-6.628301560749781,136.86774320500828,136.81931587629953,0.04842732870875466,0.035395096371142916,0.10501047827147733,0.10802266412956946,-0.0030121858580921257,-2.788475809557069,0.06914180963767007,0.06698591531512615,0.0021558943225439137,3.2184292957732996,0.9314130089130337,0.9313849217310588,2.8087181974889575e-05,0.003015636319588161,0.7733333333333334,0.5999999999999999,0.17333333333333356,28.888888888888935,4.178300996512875,,,,39.928062615509425,47.86860429278531,-7.940541677275881,-16.588203885594947,0.11297979438696983,0.1162670925925253,-0.0032872982055554695,-2.827367686122743 -0.8,4.0,4.0,2586.098242115281,2841.1305915063504,-255.03234939106915,-8.97643882169642,239765.24959855,264140.55002745,-24375.300428900024,-9.228155399224729,136.5038826686135,137.28163778418497,-0.7777551155714661,-0.5665397995864124,0.10253056902792507,0.1031498585902154,-0.0006192895622903344,-0.6003784888844036,0.07325665736408164,0.06592454978099352,0.007332107583088124,11.1219683827132,0.9311235469993302,0.9316596013994161,-0.0005360544000858614,-0.05753758124541101,1.0,0.8000000000000002,0.19999999999999984,24.99999999999998,3.5384100686094007,,,,37.14414699970415,37.43809775029793,-0.29395075059377973,-0.7851647606519765,0.09990322635678014,0.10432800196112454,-0.0044247756043444,-4.241215705437541 diff --git a/paper/src/chapters/figures/results/generated/legacy/ppo_alpha_mode_summary.csv b/paper/src/chapters/figures/results/generated/legacy/ppo_alpha_mode_summary.csv deleted file mode 100644 index 52cff7b..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/ppo_alpha_mode_summary.csv +++ /dev/null @@ -1,13 +0,0 @@ -alpha,mode,runs,eval_revenue_mean_mean,eval_revenue_mean_std,eval_reward_mean_mean,eval_reward_mean_std,eval_coi_level_mean_mean,eval_coi_level_mean_std,eval_coi_leakage_mean_mean,eval_coi_leakage_mean_std,eval_volatility_mean_mean,eval_volatility_mean_std,eval_margin_mean_mean,eval_margin_mean_std,train_alpha_adv_mean,train_alpha_adv_std,train_coi_penalty_mean,train_coi_penalty_std,train_ux_penalty_mean,train_ux_penalty_std,train_agent_prob_mean,train_agent_prob_std -0.0,no_robust,4,3565.2912010160844,52.219179508209216,331300.229069,5038.96659004527,137.28764358955686,0.6434240315013728,0.11861133504329742,0.004019332768284657,0.06445662162531288,0.004080405219050139,0.9317078361627993,0.00038018051704976865,,,,,66.58479574844135,32.282270089830455,0.11615891320235115,0.016558627227281013 -0.0,robust,4,3379.9042994670963,54.727408939657735,313527.4707462,5408.058196552377,137.08358925982625,1.047386315387148,0.1146626165658294,0.0025627354157035497,0.06687153537785637,0.008577061675868377,0.9315273502623671,0.0007274203134899985,0.18958333333333333,0.02083333333333336,5.553200113221484,0.45981481828856186,61.35134238638615,30.27964905193963,0.12778212146468534,0.027929667978205217 -0.1,no_robust,4,3458.002436284769,60.75923217871363,321215.477968,6016.373193216596,136.82757579763506,1.1899102161551907,0.11704917861668755,0.0021220259908233973,0.06737596899527175,0.006801136773079149,0.9313276818191593,0.0008352263172197586,0.1,0.0,,,53.288869747139515,18.480340945815023,0.11765277436070229,0.017544197575138736 -0.1,robust,4,3307.028238366196,35.58495715224888,306772.49146475,3488.2690530060245,137.1182041122497,0.8582218376452346,0.1128546052304944,0.0005963155492967403,0.0685405649303561,0.0050673362512629015,0.9315331673960889,0.0005217376436765336,0.2818749999999999,0.03624999999999999,5.079528726095333,0.6109585102054891,52.44772950699336,29.0263361696475,0.11644381911386253,0.021152545180088765 -0.25,no_robust,4,3300.5539051855053,50.460978662647115,306522.90003785,4860.668937531515,136.71752459667877,0.7410676951244369,0.1139905600539111,0.003319948537321803,0.06846858821082077,0.008614994548315848,0.9313053225630614,0.0004919872662680591,0.25,0.0,,,55.2030005738411,26.88247558235345,0.11684259343269415,0.013462146346772591 -0.25,robust,4,3134.3438215278165,64.06834403659167,290691.4771835,6331.196493752059,136.89990884669214,1.3796663751798552,0.11113957413522965,0.0015044942041406348,0.06427159998376095,0.0042331619171274894,0.9314501501825461,0.0008939739741734515,0.44833333333333336,0.0033333333333333518,4.7183804755060255,0.4538389380858333,49.04307009982127,28.20484665432831,0.10998505830218755,0.010731404693185651 -0.4,no_robust,4,3180.7872854626567,71.87564776824694,295433.5405797,7035.374110540269,136.5783021470118,1.7095219574599192,0.11189234314151972,0.0013821115134030936,0.07104688223410768,0.005766138692685495,0.9310542820602117,0.0013989725050689828,0.4000000000000001,0.0,,,50.794260008988424,24.836708377642946,0.11161526349272373,0.005787749200301594 -0.4,robust,4,2983.852437569374,45.51290575912758,276545.26309355,4555.1725323898245,136.19210761854086,1.5546063667946701,0.10875560547061063,0.001118798290958954,0.07452230347799255,0.0040446395928049874,0.9307282962514367,0.0013558080014763189,0.5999999999999999,0.0,4.174996403604185,0.12189448324552496,47.99794119802058,33.51782503281748,0.10222958892923095,0.0031686467591609474 -0.6,no_robust,4,2982.2460998252786,39.93674476199945,277051.95613675,3931.02017169463,136.81931587629953,1.1995405806950865,0.10802266412956946,0.000405835985606262,0.06698591531512615,0.002805894772223563,0.9313849217310588,0.0008100530228792662,0.5999999999999999,0.0,,,47.86860429278531,23.830502772642472,0.1162670925925253,0.028676813474186293 -0.6,robust,4,2789.0434220430398,35.297482315631626,258688.11700405,3420.6735023624556,136.86774320500828,0.7097303238857778,0.10501047827147733,0.0008273121554488608,0.06914180963767007,0.009066158371268139,0.9314130089130337,0.0005024421703994162,0.7733333333333334,0.053333333333333385,4.178300996512875,0.5865970573865015,39.928062615509425,30.25078643153115,0.11297979438696983,0.0274101056520461 -0.8,no_robust,4,2841.1305915063504,21.84043179776092,264140.55002745,2073.353315114627,137.28163778418497,0.6288968799501957,0.1031498585902154,0.0012877581835795701,0.06592454978099352,0.00340700896766341,0.9316596013994161,0.00038430108058413553,0.8000000000000002,0.0,,,37.43809775029793,32.01740090550489,0.10432800196112454,0.018337841526911584 -0.8,robust,4,2586.098242115281,48.05539265296157,239765.24959855,4681.6472175597555,136.5038826686135,1.0611320896043694,0.10253056902792507,0.002587472569909977,0.07325665736408164,0.0015359324114246234,0.9311235469993302,0.0006145440308596868,1.0,0.0,3.5384100686094007,0.391972726035734,37.14414699970415,25.614063825315505,0.09990322635678014,0.010269342031085898 diff --git a/paper/src/chapters/figures/results/generated/legacy/ppo_headline_summary.json b/paper/src/chapters/figures/results/generated/legacy/ppo_headline_summary.json deleted file mode 100644 index 5b106f2..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/ppo_headline_summary.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "status": "ok", - "revenue_delta": -191.29017636530716, - "revenue_delta_pct": -5.938226273545598, - "coi_leakage_delta": -0.002960415145605702, - "coi_leakage_delta_pct": -2.6404147469510946 -} \ No newline at end of file diff --git a/paper/src/chapters/figures/results/generated/legacy/ppo_overall_mode_summary.csv b/paper/src/chapters/figures/results/generated/legacy/ppo_overall_mode_summary.csv deleted file mode 100644 index c45b856..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/ppo_overall_mode_summary.csv +++ /dev/null @@ -1,3 +0,0 @@ -mode,runs,eval_revenue_mean_mean,eval_revenue_mean_std,eval_reward_mean_mean,eval_reward_mean_std,eval_coi_level_mean_mean,eval_coi_level_mean_std,eval_coi_leakage_mean_mean,eval_coi_leakage_mean_std,eval_volatility_mean_mean,eval_volatility_mean_std,eval_margin_mean_mean,eval_margin_mean_std,train_alpha_adv_mean,train_alpha_adv_std,train_coi_penalty_mean,train_coi_penalty_std,train_ux_penalty_mean,train_ux_penalty_std,train_agent_prob_mean,train_agent_prob_std -no_robust,24,3221.335253213441,262.46595166337727,299277.442303125,24382.561944761477,136.9186666318945,1.0038463876967063,0.11211932326253345,0.005805494533542669,0.06737642102693879,0.005402738047823369,0.9314066076226178,0.0007436370959663933,0.43,0.2546411303445653,,,51.86293802024894,25.340287421525442,0.11381077317368686,0.016664235359362907 -robust,24,3030.0450768481337,288.262657026656,280998.34484843333,26820.020161880373,136.77757261848845,1.06224696086916,0.10915890811692774,0.004616462637659704,0.06943407846195294,0.006435789449278624,0.9312959200008004,0.0007858424519830652,0.5488541666666666,0.2860373751485706,4.540469463924883,0.7906156355346259,47.985382134405825,27.407657819442747,0.11155393475895271,0.01943348418653492 diff --git a/paper/src/chapters/figures/results/generated/legacy/ppo_pairwise_win_rates.csv b/paper/src/chapters/figures/results/generated/legacy/ppo_pairwise_win_rates.csv deleted file mode 100644 index 856cc8b..0000000 --- a/paper/src/chapters/figures/results/generated/legacy/ppo_pairwise_win_rates.csv +++ /dev/null @@ -1,25 +0,0 @@ -alpha,metric,direction,wins,ties,total_pairs,win_probability -0.0,eval/revenue_mean,higher,0,0,16,0.0 -0.0,eval/reward_mean,higher,0,0,16,0.0 -0.0,eval/coi_leakage_mean,lower,14,0,16,0.875 -0.0,eval/volatility_mean,lower,8,0,16,0.5 -0.1,eval/revenue_mean,higher,0,0,16,0.0 -0.1,eval/reward_mean,higher,0,0,16,0.0 -0.1,eval/coi_leakage_mean,lower,16,0,16,1.0 -0.1,eval/volatility_mean,lower,8,0,16,0.5 -0.25,eval/revenue_mean,higher,0,0,16,0.0 -0.25,eval/reward_mean,higher,0,0,16,0.0 -0.25,eval/coi_leakage_mean,lower,12,0,16,0.75 -0.25,eval/volatility_mean,lower,11,0,16,0.6875 -0.4,eval/revenue_mean,higher,0,0,16,0.0 -0.4,eval/reward_mean,higher,0,0,16,0.0 -0.4,eval/coi_leakage_mean,lower,16,0,16,1.0 -0.4,eval/volatility_mean,lower,6,0,16,0.375 -0.6,eval/revenue_mean,higher,0,0,16,0.0 -0.6,eval/reward_mean,higher,0,0,16,0.0 -0.6,eval/coi_leakage_mean,lower,16,0,16,1.0 -0.6,eval/volatility_mean,lower,7,0,16,0.4375 -0.8,eval/revenue_mean,higher,0,0,16,0.0 -0.8,eval/reward_mean,higher,0,0,16,0.0 -0.8,eval/coi_leakage_mean,lower,11,0,16,0.6875 -0.8,eval/volatility_mean,lower,0,0,16,0.0 diff --git a/paper/src/chapters/figures/results/includes/final/final_focus_coi_by_alpha.tex b/paper/src/chapters/figures/results/includes/final_focus_coi_by_alpha.tex similarity index 100% rename from paper/src/chapters/figures/results/includes/final/final_focus_coi_by_alpha.tex rename to paper/src/chapters/figures/results/includes/final_focus_coi_by_alpha.tex diff --git a/paper/src/chapters/figures/results/includes/final/final_focus_coi_preservation_grid.tex b/paper/src/chapters/figures/results/includes/final_focus_coi_preservation_grid.tex similarity index 100% rename from paper/src/chapters/figures/results/includes/final/final_focus_coi_preservation_grid.tex rename to paper/src/chapters/figures/results/includes/final_focus_coi_preservation_grid.tex diff --git a/paper/src/chapters/figures/results/includes/final/final_focus_revenue_by_alpha.tex b/paper/src/chapters/figures/results/includes/final_focus_revenue_by_alpha.tex similarity index 100% rename from paper/src/chapters/figures/results/includes/final/final_focus_revenue_by_alpha.tex rename to paper/src/chapters/figures/results/includes/final_focus_revenue_by_alpha.tex diff --git a/paper/src/chapters/figures/results/includes/final/final_focus_revenue_delta.tex b/paper/src/chapters/figures/results/includes/final_focus_revenue_delta.tex similarity index 100% rename from paper/src/chapters/figures/results/includes/final/final_focus_revenue_delta.tex rename to paper/src/chapters/figures/results/includes/final_focus_revenue_delta.tex diff --git a/paper/src/chapters/figures/results/includes/final/final_focus_risk_deltas.tex b/paper/src/chapters/figures/results/includes/final_focus_risk_deltas.tex similarity index 100% rename from paper/src/chapters/figures/results/includes/final/final_focus_risk_deltas.tex rename to paper/src/chapters/figures/results/includes/final_focus_risk_deltas.tex diff --git a/paper/src/chapters/figures/results/includes/legacy/first_sweep_tier_revenue.tex b/paper/src/chapters/figures/results/includes/legacy/first_sweep_tier_revenue.tex deleted file mode 100644 index 52a61b4..0000000 --- a/paper/src/chapters/figures/results/includes/legacy/first_sweep_tier_revenue.tex +++ /dev/null @@ -1 +0,0 @@ -\includegraphics[width=0.99\linewidth]{chapters/figures/results/generated/legacy/plots/first_sweep_tier_revenue.pdf} diff --git a/paper/src/chapters/figures/results/includes/legacy/ppo_alpha_curves.tex b/paper/src/chapters/figures/results/includes/legacy/ppo_alpha_curves.tex deleted file mode 100644 index b4f6618..0000000 --- a/paper/src/chapters/figures/results/includes/legacy/ppo_alpha_curves.tex +++ /dev/null @@ -1 +0,0 @@ -\includegraphics[width=0.98\linewidth]{chapters/figures/results/generated/legacy/plots/ppo_alpha_curves.pdf} diff --git a/paper/src/chapters/figures/results/includes/legacy/ppo_delta_curves.tex b/paper/src/chapters/figures/results/includes/legacy/ppo_delta_curves.tex deleted file mode 100644 index 2b37f92..0000000 --- a/paper/src/chapters/figures/results/includes/legacy/ppo_delta_curves.tex +++ /dev/null @@ -1 +0,0 @@ -\includegraphics[width=0.98\linewidth]{chapters/figures/results/generated/legacy/plots/ppo_delta_curves.pdf} diff --git a/paper/src/chapters/figures/results/includes/legacy/ppo_tradeoff_scatter.tex b/paper/src/chapters/figures/results/includes/legacy/ppo_tradeoff_scatter.tex deleted file mode 100644 index 7b795d1..0000000 --- a/paper/src/chapters/figures/results/includes/legacy/ppo_tradeoff_scatter.tex +++ /dev/null @@ -1 +0,0 @@ -\includegraphics[width=0.88\linewidth]{chapters/figures/results/generated/legacy/plots/ppo_tradeoff_scatter.pdf} diff --git a/paper/src/chapters/figures/results/plot_results.py b/paper/src/chapters/figures/results/plot_results.py deleted file mode 100644 index 0476948..0000000 --- a/paper/src/chapters/figures/results/plot_results.py +++ /dev/null @@ -1,313 +0,0 @@ -from __future__ import annotations - -import argparse -from pathlib import Path - -import matplotlib - -matplotlib.use("Agg") -import matplotlib.pyplot as plt -from matplotlib.ticker import FuncFormatter -import numpy as np -import pandas as pd - -from process_first_sweep import run as run_first_sweep -from process_ppo_benchmark import run as run_ppo_benchmark - - -def _output_dir() -> Path: - return Path(__file__).resolve().parent / "generated" / "legacy" - - -def _plot_dir() -> Path: - return _output_dir() / "plots" - - -def _configure_style() -> None: - plt.rcParams.update( - { - "font.family": "serif", - "font.size": 10, - "axes.titlesize": 10, - "axes.labelsize": 9, - "legend.fontsize": 8, - "xtick.labelsize": 8, - "ytick.labelsize": 8, - "figure.dpi": 220, - "savefig.dpi": 320, - "axes.spines.top": False, - "axes.spines.right": False, - "axes.grid": True, - "grid.alpha": 0.22, - } - ) - - -def _fmt_thousands(value: float, _: int) -> str: - return f"{int(value):,}" - - -def _load_csv(path: Path) -> pd.DataFrame: - if not path.exists(): - raise FileNotFoundError(f"Missing required input: {path}") - return pd.read_csv(path) - - -def _plot_ppo_alpha_curves(alpha_mode: pd.DataFrame, out_dir: Path) -> Path: - fig, axes = plt.subplots(2, 2, figsize=(9.3, 6.4), constrained_layout=True) - robust_color = "#C44E52" - baseline_color = "#4C72B0" - mode_colors = {"robust": robust_color, "no_robust": baseline_color} - mode_labels = {"robust": "Robust", "no_robust": "Non-robust"} - - panels = [ - ("eval_revenue_mean", "Mean Episode Revenue", "Revenue"), - ("eval_reward_mean", "Mean Episode Reward", "Reward"), - ("eval_coi_leakage_mean", "Mean COI Leakage", "COI Leakage"), - ("eval_volatility_mean", "Mean Price Volatility", "Volatility"), - ] - - for ax, (metric_prefix, title, ylabel) in zip(axes.flat, panels): - mean_col = f"{metric_prefix}_mean" - std_col = f"{metric_prefix}_std" - for mode in ("no_robust", "robust"): - sub = alpha_mode[alpha_mode["mode"] == mode].sort_values("alpha") - if sub.empty: - continue - x = sub["alpha"].to_numpy(dtype=float) - y = sub[mean_col].to_numpy(dtype=float) - ax.plot( - x, - y, - marker="o", - linewidth=1.8, - markersize=4, - color=mode_colors[mode], - label=mode_labels[mode], - ) - if std_col in sub.columns: - sigma = sub[std_col].fillna(0.0).to_numpy(dtype=float) - ax.fill_between( - x, - y - sigma, - y + sigma, - color=mode_colors[mode], - alpha=0.14, - linewidth=0, - ) - - ax.set_title(title) - ax.set_xlabel(r"Contamination $\alpha$") - ax.set_ylabel(ylabel) - ax.set_xticks(sorted(alpha_mode["alpha"].unique())) - if metric_prefix in {"eval_revenue_mean", "eval_reward_mean"}: - ax.yaxis.set_major_formatter(FuncFormatter(_fmt_thousands)) - - handles, labels = axes.flat[0].get_legend_handles_labels() - fig.legend(handles, labels, ncol=2, loc="upper center", bbox_to_anchor=(0.5, 1.02)) - - out_path = out_dir / "ppo_alpha_curves.pdf" - fig.savefig(out_path, bbox_inches="tight") - plt.close(fig) - return out_path - - -def _plot_ppo_delta_curves(deltas: pd.DataFrame, out_dir: Path) -> Path: - fig, axes = plt.subplots(2, 1, figsize=(8.6, 6.0), constrained_layout=True) - deltas = deltas.sort_values("alpha") - x = deltas["alpha"].to_numpy(dtype=float) - - top_metrics = [ - ("eval_revenue_mean_delta_pct", "Revenue", "#4C72B0"), - ("eval_reward_mean_delta_pct", "Reward", "#8172B3"), - ] - for col, label, color in top_metrics: - axes[0].plot( - x, - deltas[col].to_numpy(dtype=float), - marker="o", - linewidth=1.8, - markersize=4, - color=color, - label=label, - ) - axes[0].axhline(0.0, color="#444444", linewidth=1.0, linestyle="--") - axes[0].set_title("Robust Minus Non-robust Delta by Contamination") - axes[0].set_ylabel("Delta (%)") - axes[0].set_xlabel(r"Contamination $\alpha$") - axes[0].set_xticks(x) - axes[0].legend(loc="lower left") - - bottom_metrics = [ - ("eval_coi_leakage_mean_delta_pct", "COI Leakage", "#55A868"), - ("eval_volatility_mean_delta_pct", "Volatility", "#DD8452"), - ] - for col, label, color in bottom_metrics: - axes[1].plot( - x, - deltas[col].to_numpy(dtype=float), - marker="o", - linewidth=1.8, - markersize=4, - color=color, - label=label, - ) - axes[1].axhline(0.0, color="#444444", linewidth=1.0, linestyle="--") - axes[1].set_ylabel("Delta (%)") - axes[1].set_xlabel(r"Contamination $\alpha$") - axes[1].set_xticks(x) - axes[1].legend(loc="lower left") - - out_path = out_dir / "ppo_delta_curves.pdf" - fig.savefig(out_path, bbox_inches="tight") - plt.close(fig) - return out_path - - -def _plot_ppo_tradeoff_scatter(deltas: pd.DataFrame, out_dir: Path) -> Path: - fig, ax = plt.subplots(figsize=(6.4, 5.2), constrained_layout=True) - data = deltas.sort_values("alpha") - x = data["eval_coi_leakage_mean_delta_pct"].to_numpy(dtype=float) - y = data["eval_revenue_mean_delta_pct"].to_numpy(dtype=float) - alphas = data["alpha"].to_numpy(dtype=float) - - scatter = ax.scatter( - x, - y, - c=alphas, - cmap="viridis", - s=72, - edgecolor="#222222", - linewidth=0.5, - ) - for x_i, y_i, alpha in zip(x, y, alphas): - ax.annotate( - rf"$\alpha={alpha:.2f}$", - (x_i, y_i), - textcoords="offset points", - xytext=(5, 4), - fontsize=8, - ) - - ax.axhline(0.0, color="#555555", linewidth=1.0, linestyle="--") - ax.axvline(0.0, color="#555555", linewidth=1.0, linestyle="--") - ax.set_xlabel("COI Leakage Delta (%)") - ax.set_ylabel("Revenue Delta (%)") - ax.set_title("PPO Robust Tradeoff Frontier") - cbar = fig.colorbar(scatter, ax=ax) - cbar.set_label(r"Contamination $\alpha$") - - out_path = out_dir / "ppo_tradeoff_scatter.pdf" - fig.savefig(out_path, bbox_inches="tight") - plt.close(fig) - return out_path - - -def _plot_first_sweep_tier_revenue(tier_mode: pd.DataFrame, out_dir: Path) -> Path: - pivot = ( - tier_mode.pivot(index="tier", columns="mode", values="eval_revenue_mean_mean") - .dropna(subset=["robust", "no_robust"], how="any") - .copy() - ) - if pivot.empty: - raise ValueError("First sweep tier summary missing robust/non-robust pairs") - - order = sorted(pivot.index.tolist()) - pivot = pivot.loc[order] - delta_pct = 100.0 * (pivot["robust"] - pivot["no_robust"]) / pivot["no_robust"] - - fig, axes = plt.subplots(1, 2, figsize=(10.2, 4.3), constrained_layout=True) - x = np.arange(len(order)) - width = 0.36 - - axes[0].bar( - x - width / 2, - pivot["no_robust"].to_numpy(dtype=float), - width=width, - label="Non-robust", - color="#4C72B0", - ) - axes[0].bar( - x + width / 2, - pivot["robust"].to_numpy(dtype=float), - width=width, - label="Robust", - color="#C44E52", - ) - axes[0].set_xticks(x) - axes[0].set_xticklabels(order, rotation=20) - axes[0].set_ylabel("Mean Revenue") - axes[0].set_yscale("log") - axes[0].yaxis.set_major_formatter(FuncFormatter(_fmt_thousands)) - axes[0].set_title("First Sweep Tier Revenue (log scale)") - axes[0].legend() - - axes[1].bar(x, delta_pct.to_numpy(dtype=float), color="#55A868", width=0.55) - axes[1].axhline(0.0, color="#444444", linewidth=1.0, linestyle="--") - axes[1].set_xticks(x) - axes[1].set_xticklabels(order, rotation=20) - axes[1].set_ylabel("Revenue Delta (%)") - axes[1].set_title("Robust Minus Non-robust by Tier") - - out_path = out_dir / "first_sweep_tier_revenue.pdf" - fig.savefig(out_path, bbox_inches="tight") - plt.close(fig) - return out_path - - -def build_plots(data_dir: Path, out_dir: Path) -> list[Path]: - alpha_mode = _load_csv(data_dir / "ppo_alpha_mode_summary.csv") - deltas = _load_csv(data_dir / "ppo_alpha_deltas.csv") - tier_mode = _load_csv(data_dir / "first_sweep_tier_mode_summary.csv") - - out_dir.mkdir(parents=True, exist_ok=True) - paths = [ - _plot_ppo_alpha_curves(alpha_mode, out_dir), - _plot_ppo_delta_curves(deltas, out_dir), - _plot_ppo_tradeoff_scatter(deltas, out_dir), - _plot_first_sweep_tier_revenue(tier_mode, out_dir), - ] - return paths - - -def main() -> None: - parser = argparse.ArgumentParser( - description="Create paper-ready plots from result CSVs" - ) - parser.add_argument("--data-dir", type=Path, default=_output_dir()) - parser.add_argument("--plot-dir", type=Path, default=_plot_dir()) - parser.add_argument( - "--refresh-data", - action="store_true", - help="Regenerate processed CSVs before plotting", - ) - args = parser.parse_args() - - _configure_style() - - if bool(args.refresh_data): - run_ppo_benchmark( - input_path=Path(__file__).resolve().parents[5] - / "tpu_orchestration" - / "results" - / "ppo_benchmark.csv", - output_dir=args.data_dir, - include_non_finished=False, - ) - run_first_sweep( - input_path=Path(__file__).resolve().parents[5] - / "tpu_orchestration" - / "results" - / "first_sweep.csv", - output_dir=args.data_dir, - include_non_finished=False, - top_n=25, - ) - - outputs = build_plots(data_dir=args.data_dir, out_dir=args.plot_dir) - for path in outputs: - print(path) - - -if __name__ == "__main__": - main() diff --git a/paper/src/chapters/figures/results/process_all_results.py b/paper/src/chapters/figures/results/process_all_results.py deleted file mode 100644 index 78ca65f..0000000 --- a/paper/src/chapters/figures/results/process_all_results.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import annotations - -import argparse -from pathlib import Path - -from process_first_sweep import run as run_first_sweep -from process_ppo_benchmark import run as run_ppo_benchmark - - -def _default_output_dir() -> Path: - return Path(__file__).resolve().parent / "generated" / "legacy" - - -def main() -> None: - parser = argparse.ArgumentParser( - description="Process all result CSV exports for paper figures" - ) - parser.add_argument("--output-dir", type=Path, default=_default_output_dir()) - parser.add_argument("--include-non-finished", action="store_true") - parser.add_argument("--top-n", type=int, default=25) - args = parser.parse_args() - - written: list[Path] = [] - written.extend( - run_ppo_benchmark( - input_path=Path(__file__).resolve().parents[5] - / "tpu_orchestration" - / "results" - / "ppo_benchmark.csv", - output_dir=args.output_dir, - include_non_finished=bool(args.include_non_finished), - ) - ) - written.extend( - run_first_sweep( - input_path=Path(__file__).resolve().parents[5] - / "tpu_orchestration" - / "results" - / "first_sweep.csv", - output_dir=args.output_dir, - include_non_finished=bool(args.include_non_finished), - top_n=int(args.top_n), - ) - ) - - for path in written: - print(path) - - -if __name__ == "__main__": - main() diff --git a/paper/src/chapters/figures/results/process_final_sweeps.py b/paper/src/chapters/figures/results/process_final_sweeps.py index 3dc5c0a..550eb8a 100644 --- a/paper/src/chapters/figures/results/process_final_sweeps.py +++ b/paper/src/chapters/figures/results/process_final_sweeps.py @@ -639,7 +639,7 @@ def run( ) ) - include_dir = Path(__file__).resolve().parent / "includes" / "final" + include_dir = Path(__file__).resolve().parent / "includes" written.append( _write_include( include_dir / "final_focus_revenue_by_alpha.tex", diff --git a/paper/src/chapters/figures/results/process_first_sweep.py b/paper/src/chapters/figures/results/process_first_sweep.py deleted file mode 100644 index 0e62525..0000000 --- a/paper/src/chapters/figures/results/process_first_sweep.py +++ /dev/null @@ -1,272 +0,0 @@ -from __future__ import annotations - -import argparse -import json -from pathlib import Path -from typing import Iterable - -import numpy as np -import pandas as pd - - -def _project_root() -> Path: - return Path(__file__).resolve().parents[5] - - -def _default_input() -> Path: - return _project_root() / "tpu_orchestration" / "results" / "first_sweep.csv" - - -def _default_output_dir() -> Path: - return Path(__file__).resolve().parent / "generated" / "legacy" - - -def _sanitize(key: str) -> str: - return key.replace("/", "_").replace("-", "_") - - -def _coerce_numeric(frame: pd.DataFrame, columns: Iterable[str]) -> None: - for column in columns: - if column in frame.columns: - frame[column] = pd.to_numeric(frame[column], errors="coerce") - - -def _extract_alpha(frame: pd.DataFrame) -> pd.Series: - if "study/alpha" in frame.columns: - return pd.to_numeric(frame["study/alpha"], errors="coerce") - if "alpha" in frame.columns: - return pd.to_numeric(frame["alpha"], errors="coerce") - return pd.Series(np.nan, index=frame.index, dtype=float) - - -def _extract_mode(frame: pd.DataFrame) -> pd.Series: - if "study/mode" in frame.columns: - return frame["study/mode"].astype(str).str.strip().str.lower() - if "study/no_robust" in frame.columns: - no_robust = pd.to_numeric(frame["study/no_robust"], errors="coerce").fillna(0.0) - return pd.Series( - np.where(no_robust > 0.5, "no_robust", "robust"), - index=frame.index, - dtype="object", - ) - if "no_robust" in frame.columns: - no_robust = ( - frame["no_robust"].astype(str).str.lower().isin({"1", "true", "yes"}) - ) - return pd.Series( - np.where(no_robust, "no_robust", "robust"), - index=frame.index, - dtype="object", - ) - return pd.Series("", index=frame.index, dtype="object") - - -def _extract_tier(frame: pd.DataFrame) -> pd.Series: - for column in ("tiers", "runtime/backend", "algo", "run.backend", "run.algo"): - if column in frame.columns: - tier = frame[column].astype(str).str.strip().str.lower() - if tier.notna().any(): - return tier - return pd.Series("unknown", index=frame.index, dtype="object") - - -def _prepare_frame(frame: pd.DataFrame, include_non_finished: bool) -> pd.DataFrame: - data = frame.copy() - if not include_non_finished and "State" in data.columns: - data = data[data["State"].astype(str).str.lower() == "finished"].copy() - - data["alpha"] = _extract_alpha(data) - data["mode"] = _extract_mode(data) - data["tier"] = _extract_tier(data) - data = data[data["mode"].isin({"robust", "no_robust"})] - data = data[data["alpha"].notna()] - - _coerce_numeric( - data, - [ - "eval/revenue_mean", - "eval/reward_mean", - "eval/coi_level_mean", - "eval/coi_leakage_mean", - "eval/margin_mean", - "eval/volatility_mean", - "objective/score", - "train/alpha_adv", - "lambda_coi", - "robust_radius", - "learning_rate", - "batch_size", - "n_steps", - "total_timesteps", - ], - ) - return data.sort_values(["tier", "alpha", "mode"]).reset_index(drop=True) - - -def _group_summary( - frame: pd.DataFrame, by: list[str], metrics: list[str] -) -> pd.DataFrame: - agg_spec: dict[str, tuple[str, str]] = {"runs": ("mode", "size")} - for metric in metrics: - safe = _sanitize(metric) - agg_spec[f"{safe}_mean"] = (metric, "mean") - agg_spec[f"{safe}_std"] = (metric, "std") - return frame.groupby(by, as_index=False).agg(**agg_spec).sort_values(by) - - -def _tier_alpha_deltas(summary: pd.DataFrame, metrics: list[str]) -> pd.DataFrame: - rows: list[dict[str, float | str]] = [] - for (tier, alpha), group in summary.groupby(["tier", "alpha"], sort=True): - robust = group[group["mode"] == "robust"] - no_robust = group[group["mode"] == "no_robust"] - if robust.empty or no_robust.empty: - continue - - row: dict[str, float | str] = { - "tier": str(tier), - "alpha": float(alpha), - "runs_robust": float(robust["runs"].iloc[0]), - "runs_no_robust": float(no_robust["runs"].iloc[0]), - } - for metric in metrics: - safe = _sanitize(metric) - robust_value = float(robust[f"{safe}_mean"].iloc[0]) - no_robust_value = float(no_robust[f"{safe}_mean"].iloc[0]) - delta = robust_value - no_robust_value - row[f"{safe}_delta"] = delta - row[f"{safe}_delta_pct"] = ( - np.nan if no_robust_value == 0 else 100.0 * delta / no_robust_value - ) - rows.append(row) - - return pd.DataFrame(rows) - - -def _top_runs(frame: pd.DataFrame, n: int) -> pd.DataFrame: - rank_metric = "objective/score" - if rank_metric not in frame.columns or frame[rank_metric].notna().sum() == 0: - rank_metric = "eval/reward_mean" - - keep = [ - "Name", - "tier", - "alpha", - "mode", - rank_metric, - "eval/revenue_mean", - "eval/reward_mean", - "eval/coi_level_mean", - "eval/coi_leakage_mean", - "lambda_coi", - "robust_radius", - "learning_rate", - "batch_size", - "n_steps", - "total_timesteps", - ] - present = [column for column in keep if column in frame.columns] - ranked = frame[present].copy().sort_values(rank_metric, ascending=False) - return ranked.head(max(1, int(n))).reset_index(drop=True) - - -def _headline_json( - frame: pd.DataFrame, tier_mode: pd.DataFrame -) -> dict[str, float | str]: - out: dict[str, float | str] = { - "runs": int(len(frame)), - "tiers": int(frame["tier"].nunique()), - "alphas": int(frame["alpha"].nunique()), - } - - robust_rows = tier_mode[tier_mode["mode"] == "robust"] - no_robust_rows = tier_mode[tier_mode["mode"] == "no_robust"] - if robust_rows.empty or no_robust_rows.empty: - out["status"] = "incomplete_modes" - return out - - robust_mean = robust_rows["eval_revenue_mean_mean"].mean() - no_robust_mean = no_robust_rows["eval_revenue_mean_mean"].mean() - out.update( - { - "status": "ok", - "mean_tier_revenue_robust": float(robust_mean), - "mean_tier_revenue_no_robust": float(no_robust_mean), - "mean_tier_revenue_delta": float(robust_mean - no_robust_mean), - "mean_tier_revenue_delta_pct": float( - 100.0 * (robust_mean - no_robust_mean) / no_robust_mean - ) - if no_robust_mean - else np.nan, - } - ) - return out - - -def run( - input_path: Path, output_dir: Path, include_non_finished: bool, top_n: int -) -> list[Path]: - output_dir.mkdir(parents=True, exist_ok=True) - raw = pd.read_csv(input_path) - frame = _prepare_frame(raw, include_non_finished=include_non_finished) - - metrics = [ - metric - for metric in ( - "eval/revenue_mean", - "eval/reward_mean", - "eval/coi_level_mean", - "eval/coi_leakage_mean", - "eval/margin_mean", - "eval/volatility_mean", - "objective/score", - "train/alpha_adv", - ) - if metric in frame.columns - ] - - tier_mode = _group_summary(frame, ["tier", "mode"], metrics) - tier_alpha_mode = _group_summary(frame, ["tier", "alpha", "mode"], metrics) - deltas = _tier_alpha_deltas(tier_alpha_mode, metrics) - top_configs = _top_runs(frame, n=top_n) - headline = _headline_json(frame, tier_mode) - - outputs = { - "first_sweep_tier_mode_summary.csv": tier_mode, - "first_sweep_tier_alpha_mode_summary.csv": tier_alpha_mode, - "first_sweep_tier_alpha_deltas.csv": deltas, - "first_sweep_top_configs.csv": top_configs, - } - written_paths: list[Path] = [] - for filename, table in outputs.items(): - path = output_dir / filename - table.to_csv(path, index=False) - written_paths.append(path) - - headline_path = output_dir / "first_sweep_headline_summary.json" - headline_path.write_text(json.dumps(headline, indent=2)) - written_paths.append(headline_path) - return written_paths - - -def main() -> None: - parser = argparse.ArgumentParser( - description="Process first sweep CSV for paper tables" - ) - parser.add_argument("--input", type=Path, default=_default_input()) - parser.add_argument("--output-dir", type=Path, default=_default_output_dir()) - parser.add_argument("--include-non-finished", action="store_true") - parser.add_argument("--top-n", type=int, default=25) - args = parser.parse_args() - - written = run( - input_path=args.input, - output_dir=args.output_dir, - include_non_finished=bool(args.include_non_finished), - top_n=int(args.top_n), - ) - for path in written: - print(path) - - -if __name__ == "__main__": - main() diff --git a/paper/src/chapters/figures/results/process_ppo_benchmark.py b/paper/src/chapters/figures/results/process_ppo_benchmark.py deleted file mode 100644 index 85f48b2..0000000 --- a/paper/src/chapters/figures/results/process_ppo_benchmark.py +++ /dev/null @@ -1,277 +0,0 @@ -from __future__ import annotations - -import argparse -import json -from pathlib import Path -from typing import Iterable - -import numpy as np -import pandas as pd - - -def _project_root() -> Path: - return Path(__file__).resolve().parents[5] - - -def _default_input() -> Path: - return _project_root() / "tpu_orchestration" / "results" / "ppo_benchmark.csv" - - -def _default_output_dir() -> Path: - return Path(__file__).resolve().parent / "generated" / "legacy" - - -def _sanitize(key: str) -> str: - return key.replace("/", "_").replace("-", "_") - - -def _coerce_numeric(frame: pd.DataFrame, columns: Iterable[str]) -> None: - for column in columns: - if column in frame.columns: - frame[column] = pd.to_numeric(frame[column], errors="coerce") - - -def _extract_alpha(frame: pd.DataFrame) -> pd.Series: - if "study/alpha" in frame.columns: - return pd.to_numeric(frame["study/alpha"], errors="coerce") - if "alpha" in frame.columns: - return pd.to_numeric(frame["alpha"], errors="coerce") - return pd.Series(np.nan, index=frame.index, dtype=float) - - -def _extract_mode(frame: pd.DataFrame) -> pd.Series: - if "study/mode" in frame.columns: - return frame["study/mode"].astype(str).str.strip().str.lower() - if "study/no_robust" in frame.columns: - no_robust = pd.to_numeric(frame["study/no_robust"], errors="coerce").fillna(0.0) - return pd.Series( - np.where(no_robust > 0.5, "no_robust", "robust"), - index=frame.index, - dtype="object", - ) - if "no_robust" in frame.columns: - no_robust = ( - frame["no_robust"].astype(str).str.lower().isin({"1", "true", "yes"}) - ) - return pd.Series( - np.where(no_robust, "no_robust", "robust"), - index=frame.index, - dtype="object", - ) - return pd.Series("", index=frame.index, dtype="object") - - -def _prepare_frame(frame: pd.DataFrame, include_non_finished: bool) -> pd.DataFrame: - data = frame.copy() - if not include_non_finished and "State" in data.columns: - data = data[data["State"].astype(str).str.lower() == "finished"].copy() - - data["alpha"] = _extract_alpha(data) - data["mode"] = _extract_mode(data) - data = data[data["mode"].isin({"robust", "no_robust"})] - data = data[data["alpha"].notna()] - - numeric_cols = [ - "eval/revenue_mean", - "eval/reward_mean", - "eval/coi_level_mean", - "eval/coi_leakage_mean", - "eval/volatility_mean", - "eval/margin_mean", - "train/alpha_adv", - "train/coi_penalty", - "train/ux_penalty", - "train/agent_prob", - ] - _coerce_numeric(data, numeric_cols) - return data.sort_values(["alpha", "mode"]).reset_index(drop=True) - - -def _summary_by_alpha_mode(frame: pd.DataFrame, metrics: list[str]) -> pd.DataFrame: - agg_spec: dict[str, tuple[str, str]] = {"runs": ("mode", "size")} - for metric in metrics: - safe = _sanitize(metric) - agg_spec[f"{safe}_mean"] = (metric, "mean") - agg_spec[f"{safe}_std"] = (metric, "std") - - return ( - frame.groupby(["alpha", "mode"], as_index=False) - .agg(**agg_spec) - .sort_values(["alpha", "mode"]) - .reset_index(drop=True) - ) - - -def _delta_by_alpha(summary: pd.DataFrame, metrics: list[str]) -> pd.DataFrame: - rows: list[dict[str, float]] = [] - for alpha, alpha_group in summary.groupby("alpha", sort=True): - robust = alpha_group[alpha_group["mode"] == "robust"] - no_robust = alpha_group[alpha_group["mode"] == "no_robust"] - if robust.empty or no_robust.empty: - continue - - row: dict[str, float] = { - "alpha": float(alpha), - "runs_robust": float(robust["runs"].iloc[0]), - "runs_no_robust": float(no_robust["runs"].iloc[0]), - } - for metric in metrics: - safe = _sanitize(metric) - robust_value = float(robust[f"{safe}_mean"].iloc[0]) - no_robust_value = float(no_robust[f"{safe}_mean"].iloc[0]) - delta = robust_value - no_robust_value - row[f"{safe}_robust"] = robust_value - row[f"{safe}_no_robust"] = no_robust_value - row[f"{safe}_delta"] = delta - row[f"{safe}_delta_pct"] = ( - np.nan if no_robust_value == 0 else 100.0 * delta / no_robust_value - ) - rows.append(row) - - return pd.DataFrame(rows) - - -def _pairwise_win_rates(frame: pd.DataFrame) -> pd.DataFrame: - rules = { - "eval/revenue_mean": "higher", - "eval/reward_mean": "higher", - "eval/coi_leakage_mean": "lower", - "eval/volatility_mean": "lower", - } - rows: list[dict[str, float]] = [] - for alpha, alpha_group in frame.groupby("alpha", sort=True): - robust = alpha_group[alpha_group["mode"] == "robust"] - no_robust = alpha_group[alpha_group["mode"] == "no_robust"] - if robust.empty or no_robust.empty: - continue - - for metric, direction in rules.items(): - if metric not in frame.columns: - continue - robust_values = robust[metric].dropna().to_numpy(dtype=float) - no_robust_values = no_robust[metric].dropna().to_numpy(dtype=float) - if robust_values.size == 0 or no_robust_values.size == 0: - continue - - if direction == "higher": - wins = (robust_values[:, None] > no_robust_values[None, :]).sum() - else: - wins = (robust_values[:, None] < no_robust_values[None, :]).sum() - ties = (robust_values[:, None] == no_robust_values[None, :]).sum() - total = robust_values.size * no_robust_values.size - win_prob = (wins + 0.5 * ties) / total - rows.append( - { - "alpha": float(alpha), - "metric": metric, - "direction": direction, - "wins": int(wins), - "ties": int(ties), - "total_pairs": int(total), - "win_probability": float(win_prob), - } - ) - return pd.DataFrame(rows) - - -def _overall_mode_summary(frame: pd.DataFrame, metrics: list[str]) -> pd.DataFrame: - agg_spec: dict[str, tuple[str, str]] = {"runs": ("mode", "size")} - for metric in metrics: - safe = _sanitize(metric) - agg_spec[f"{safe}_mean"] = (metric, "mean") - agg_spec[f"{safe}_std"] = (metric, "std") - return frame.groupby("mode", as_index=False).agg(**agg_spec).sort_values("mode") - - -def _headline_json(overall: pd.DataFrame) -> dict[str, float | str]: - if {"robust", "no_robust"} - set(overall["mode"].tolist()): - return {"status": "incomplete_modes"} - - robust = overall[overall["mode"] == "robust"].iloc[0] - no_robust = overall[overall["mode"] == "no_robust"].iloc[0] - - revenue_delta = float( - robust["eval_revenue_mean_mean"] - no_robust["eval_revenue_mean_mean"] - ) - leakage_delta = float( - robust["eval_coi_leakage_mean_mean"] - no_robust["eval_coi_leakage_mean_mean"] - ) - return { - "status": "ok", - "revenue_delta": revenue_delta, - "revenue_delta_pct": float( - 100.0 * revenue_delta / no_robust["eval_revenue_mean_mean"] - ), - "coi_leakage_delta": leakage_delta, - "coi_leakage_delta_pct": float( - 100.0 * leakage_delta / no_robust["eval_coi_leakage_mean_mean"] - ), - } - - -def run(input_path: Path, output_dir: Path, include_non_finished: bool) -> list[Path]: - output_dir.mkdir(parents=True, exist_ok=True) - raw = pd.read_csv(input_path) - frame = _prepare_frame(raw, include_non_finished=include_non_finished) - - metrics = [ - metric - for metric in ( - "eval/revenue_mean", - "eval/reward_mean", - "eval/coi_level_mean", - "eval/coi_leakage_mean", - "eval/volatility_mean", - "eval/margin_mean", - "train/alpha_adv", - "train/coi_penalty", - "train/ux_penalty", - "train/agent_prob", - ) - if metric in frame.columns - ] - - alpha_mode = _summary_by_alpha_mode(frame, metrics) - deltas = _delta_by_alpha(alpha_mode, metrics) - win_rates = _pairwise_win_rates(frame) - overall = _overall_mode_summary(frame, metrics) - headline = _headline_json(overall) - - outputs = { - "ppo_alpha_mode_summary.csv": alpha_mode, - "ppo_alpha_deltas.csv": deltas, - "ppo_pairwise_win_rates.csv": win_rates, - "ppo_overall_mode_summary.csv": overall, - } - written_paths: list[Path] = [] - for filename, table in outputs.items(): - path = output_dir / filename - table.to_csv(path, index=False) - written_paths.append(path) - - headline_path = output_dir / "ppo_headline_summary.json" - headline_path.write_text(json.dumps(headline, indent=2)) - written_paths.append(headline_path) - return written_paths - - -def main() -> None: - parser = argparse.ArgumentParser( - description="Process PPO benchmark CSV for paper tables" - ) - parser.add_argument("--input", type=Path, default=_default_input()) - parser.add_argument("--output-dir", type=Path, default=_default_output_dir()) - parser.add_argument("--include-non-finished", action="store_true") - args = parser.parse_args() - - written = run( - input_path=args.input, - output_dir=args.output_dir, - include_non_finished=bool(args.include_non_finished), - ) - for path in written: - print(path) - - -if __name__ == "__main__": - main() diff --git a/paper/src/chapters/figures/results/revenue_alpha_classic.py b/paper/src/chapters/figures/results/revenue_alpha_classic.py deleted file mode 100644 index a91f2f6..0000000 --- a/paper/src/chapters/figures/results/revenue_alpha_classic.py +++ /dev/null @@ -1,63 +0,0 @@ -from pathlib import Path - -import numpy as np -import pandas as pd -from scipy import stats - - -root = Path(__file__).resolve().parents[5] -runs = ( - root - / "engine/studies/results/wandb_sweep_bundles/bundle_20260317_122818/runs_finished.csv" -) - -df = pd.read_csv(runs) -df = df[ - (df["sweep_id"].astype(str) == "i88nw811") - & (df["study_mode"].astype(str) == "baseline") - & (pd.to_numeric(df["n_products"], errors="coerce") == 100.0) - & (pd.to_numeric(df["eta_ux"], errors="coerce") == 0.0) -].copy() - -alpha = pd.to_numeric(df["alpha"], errors="coerce") -revenue = pd.to_numeric(df["eval_revenue_mean"], errors="coerce") -mask = alpha.notna() & revenue.notna() -alpha = alpha[mask].to_numpy(dtype=float) -revenue = revenue[mask].to_numpy(dtype=float) - -if len(alpha) < 3 or np.unique(alpha).size < 2: - raise ValueError("Not enough data for regression") - -fit = stats.linregress(alpha, revenue) -n = len(alpha) -dof = n - 2 -t_stat = fit.slope / fit.stderr -p_val = 2.0 * stats.t.sf(abs(t_stat), df=dof) -r2 = fit.rvalue**2 -t_crit = stats.t.ppf(0.975, dof) -slope_ci = (fit.slope - t_crit * fit.stderr, fit.slope + t_crit * fit.stderr) - -x = np.column_stack([np.ones(n), alpha]) -beta = np.linalg.lstsq(x, revenue, rcond=None)[0] -resid = revenue - x @ beta -xtx_inv = np.linalg.pinv(x.T @ x) -meat = (x * resid[:, None]).T @ (x * resid[:, None]) -cov_hc1 = (n / (n - x.shape[1])) * (xtx_inv @ meat @ xtx_inv) -se_hc1 = np.sqrt(np.diag(cov_hc1)) -t_hc1 = beta[1] / se_hc1[1] -p_hc1 = 2.0 * stats.t.sf(abs(t_hc1), df=dof) -slope_ci_hc1 = (beta[1] - t_crit * se_hc1[1], beta[1] + t_crit * se_hc1[1]) - -print("Contamination-Revenue Slope") -print( - "cohort: bundle_20260317_122818, sweep=i88nw811, mode=baseline, n_products=100, eta_ux=0.0" -) -print(f"n={n}") -print(f"model: revenue = {fit.intercept:.2f} {fit.slope:+.2f} * alpha") -print( - f"OLS: t({dof})={t_stat:.2f}, p={p_val:.3e}, R^2={r2:.3f}, slope_95CI=[{slope_ci[0]:.2f}, {slope_ci[1]:.2f}]" -) -print( - f"HC1: t={t_hc1:.2f}, p={p_hc1:.3e}, slope_95CI=[{slope_ci_hc1[0]:.2f}, {slope_ci_hc1[1]:.2f}]" -) -print(f"effect: +0.1 alpha -> {0.1 * fit.slope:.2f} revenue units") diff --git a/paper/src/chapters/mdp_agent.pdf b/paper/src/chapters/mdp_agent.pdf index 24d141ea8f5e3b3d4d986e0cda0860d91e6d895b..17d299e68d5e4207c1cb1833a0049fb74da537c1 100644 GIT binary patch delta 291 zcmV+;0o?wyRkT&GeJFolYlAQp#ozrD=VeS8Xs)&P57LLWP{tTY+qbcY5Q7zlktB}w z+b_}T7p@yfu}<2U0Mc@j0M_ z>RSs6cDq4QYE|_@YJ`F}T7hC(#~H$#wVl}}$v|t(yIUhntaN`JMdLSGa@(l($gM

teS;p2x%N3&+mOe8UO(uV_@Z_w$zT{f^96s3q-euMBz4~!+nS1Fv+kkS~%&}YR z1P0lxIBC^)C<;ILd2|`*gf5P1-kQ$4iTi|KVRbL3>EO1G^1Bi8eA;{HQhR=uM)g`q pgT?H5aYA9o@WvM1;a|Z6xBN@hkACh3k9uzD7yFHGNwbkDBLNWClc)dy delta 291 zcmV+;0o?wyRkT&GeJFoXYr-%Th2Q%t&dZoGu({FJD#Zsa$QXlCeH(iSG1S6nN|KKG z@0V2DG4gaj?#VfaOJEVDNLa){2}QKVa-Bwbj`)1*6yj3U%0>XbMWkrw+VQR`*6K pi{<2b@83a~8A*Vw&v z0)u2#oU|GTl%*g1JiAPEK^I3g@6F)d#BISZuzHlsRJpCA{O*K2pAH_n)SjQEQKJ^p pV7q!=oKV;~ym1zH_*byvmVc@C-p}3OUe7K40{?|?PP30KA^{6VkLv&c delta 291 zcmV+;0o?wvU9nxTdn|v!YQr!PMDO~Fxs*B-Y)OtCH<%ofKq#dUlHN)WLKcpoSVodd z^Y@jU*rn*Sj~&en%RmV$QBcCc3P#up`Kly!jqLr}D`ZE}Dn|fhuex#g00+ehpCj6t zq4Qv5vl$gfYnnkSi$n@-4Oq&mbcy8Reec#;HqzFL{-UKzjctDyi`zF=39n7J7hWOR zuQ}x<&3VOGQSs#yWsj6DCX>HdcnH=}e-u{595LAl-c+N-*8GIHG(7%XR^Vl^nqzl9 z2ppEP;$Y3tqpsr+=bOt&Cv*