1"""F5-conf-01: Walrasian equilibrium of a 2x2 Cobb-Douglas exchange economy.2Run from workspace root: ~/wp29/venv/bin/python out/analysis.py3Reads data/ only; deterministic (no randomness)."""4import json, os5import pandas as pd6from scipy.optimize import brentq78end = pd.read_csv("data/endowments.csv")9par = pd.read_csv("data/parameters.csv")10P = dict(zip(par["parameter"], par["value"].astype(float)))1112issues = []13# --- validation / exclusions ---14assert end["agent"].is_unique and set(end["agent"]) == {"A", "B"}15valid = end[(end.good1 > 0) & (end.good2 > 0)]16agents = list(valid["agent"])17alpha = {i: P[f"alpha_{i}"] for i in agents}18assert all(0 < a < 1 for a in alpha.values())19e1 = dict(zip(valid.agent, valid.good1.astype(float)))20e2 = dict(zip(valid.agent, valid.good2.astype(float)))2122E1 = sum(e1.values()); E2 = sum(e2.values())23rec1 = P["aggregate_endowment_good1"]; rec2 = P["aggregate_endowment_good2"]24if abs(rec1 - E1) > 1e-12:25 issues.append({"issue": f"parameters.csv aggregate_endowment_good1={rec1} differs from sum of individual endowments in endowments.csv ({E1}).",26 "handling": f"Used {E1} (sum of primary individual endowments) in market clearing; the recorded {rec1} is inconsistent with agents' resources and was not used. Price implied by {rec1} reported as diagnostic only."})27if abs(rec2 - E2) > 1e-12:28 issues.append({"issue": f"parameters.csv aggregate_endowment_good2={rec2} differs from sum of individual endowments ({E2}).",29 "handling": f"Used {E2}."})3031def demand(p, i):32 m = p * e1[i] + e2[i]33 return alpha[i] * m / p, (1 - alpha[i]) * m3435def z(p, E1_=None):36 E1_ = E1 if E1_ is None else E1_37 z1 = sum(demand(p, i)[0] for i in agents) - E1_38 z2 = sum(demand(p, i)[1] for i in agents) - E239 return z1, z24041# --- closed form: sum_i alpha_i (p e1_i + e2_i) = p E1 => p = sum alpha_i e2_i / sum (1-alpha_i) e1_i42p_cf = sum(alpha[i] * e2[i] for i in agents) / sum((1 - alpha[i]) * e1[i] for i in agents)43alloc = {i: demand(p_cf, i) for i in agents}44z1, z2 = z(p_cf)4546# --- independent numerical root of z1(p) (does not use closed form) ---47p_num = brentq(lambda p: z(p)[0], 1e-8, 1e8, xtol=1e-15, rtol=1e-15, maxiter=500)4849# diagnostic: root if the (inconsistent) recorded aggregate were used50p_diag = brentq(lambda p: z(p, rec1)[0], 1e-8, 1e8, xtol=1e-15, rtol=1e-15, maxiter=500)5152res = {53 "task_id": "F5-conf-01",54 "price_ratio_p1_over_p2": p_cf,55 "x1_A": alloc["A"][0], "x2_A": alloc["A"][1],56 "x1_B": alloc["B"][0], "x2_B": alloc["B"][1],57 "excess_demand_good1": z1,58 "excess_demand_good2": z2,59 "walras_law_residual": p_cf * z1 + z2,60 "aggregate_endowment_good1": E1,61 "aggregate_endowment_good2": E2,62 "price_ratio_numerical": p_num,63 "abs_diff_closed_form_vs_numerical": abs(p_cf - p_num),64 "diagnostic_price_if_recorded_aggregate_used": p_diag,65 "feasibility": "complete",66 "feasibility_reason": None,67 "data_issues": issues,68 "n_input_rows": {"endowments.csv": int(len(end)), "parameters.csv": int(len(par))},69 "n_analysed": len(agents),70 "random_seed": None,71}72os.makedirs("out", exist_ok=True)73with open("out/results.json", "w") as f:74 json.dump(res, f, indent=2)75print(json.dumps(res, indent=2))76