1"""F5-conf-01: Walrasian equilibrium of a 2x2 Cobb-Douglas exchange economy.2Run from workspace root: ~/wp29/venv/bin/python out/analysis.py3No randomness is used (random_seed = null).4"""5import json, os6import numpy as np7import pandas as pd8from scipy.optimize import brentq910ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))11D = os.path.join(ROOT, "data"); O = os.path.join(ROOT, "out")1213endw = pd.read_csv(os.path.join(D, "endowments.csv"))14pars = pd.read_csv(os.path.join(D, "parameters.csv"))15n_rows = {"endowments.csv": int(len(endw)), "parameters.csv": int(len(pars))}16P = dict(zip(pars["parameter"], pars["value"].astype(float)))17issues = []1819# --- audit / validation ---20assert sorted(endw["agent"]) == ["A", "B"] and not endw["agent"].duplicated().any()21assert not endw.isna().any().any() and not pars["value"].isna().any()22assert (endw[["good1", "good2"]] > 0).all().all(), "endowments must be strictly positive"23alpha = {"A": P["alpha_A"], "B": P["alpha_B"]}24assert all(0 < a < 1 for a in alpha.values())25e1 = dict(zip(endw["agent"], endw["good1"].astype(float)))26e2 = dict(zip(endw["agent"], endw["good2"].astype(float)))27agents = ["A", "B"]28E1 = sum(e1.values()); E2 = sum(e2.values())29for E, key in [(E1, "aggregate_endowment_good1"), (E2, "aggregate_endowment_good2")]:30 if not np.isclose(E, P[key]):31 issues.append({32 "issue": f"parameters.csv {key}={P[key]:g} disagrees with the sum of individual "33 f"endowments in endowments.csv ({E:g}).",34 "handling": f"Used the sum of individual endowments ({E:g}) because endowments.csv is the "35 "primary data and market clearing must be consistent with the agents' budget "36 "constraints (using the summary value would make the good-1 clearing condition "37 "inconsistent with the budget constraints, so Walras' law would fail). Summary value not used in any computation except a reported sensitivity."})3839# --- model ---40def demand(i, p):41 w = p * e1[i] + e2[i]42 return alpha[i] * w / p, (1 - alpha[i]) * w4344def z(p):45 x1 = sum(demand(i, p)[0] for i in agents); x2 = sum(demand(i, p)[1] for i in agents)46 return x1 - E1, x2 - E24748# baseline / independent check: bracketing root of z1(p) (closed form not used)49lo, hi = 1e-6, 1.050while z(hi)[0] > 0:51 hi *= 252p_num = brentq(lambda q: z(q)[0], lo, hi, xtol=1e-14, rtol=1e-15, maxiter=500)5354# closed form: p = sum alpha_i e2_i / sum (1-alpha_i) e1_i55p = sum(alpha[i] * e2[i] for i in agents) / sum((1 - alpha[i]) * e1[i] for i in agents)5657z1, z2 = z(p)58alloc = {f"x{g}_{i}": float(demand(i, p)[g - 1]) for i in agents for g in (1, 2)}5960res = {61 "task_id": "F5-conf-01",62 "price_ratio_p1_over_p2": float(p),63 **{k: alloc[k] for k in ["x1_A", "x2_A", "x1_B", "x2_B"]},64 "excess_demand_good1": float(z1),65 "excess_demand_good2": float(z2),66 "walras_law_residual": float(p * z1 + z2),67 "aggregate_endowment_good1": float(E1),68 "aggregate_endowment_good2": float(E2),69 "price_ratio_numerical": float(p_num),70 "abs_diff_closed_vs_numerical": float(abs(p - p_num)),71 "excess_demand_good1_at_numerical_price": float(z(p_num)[0]),72 "wealth_A": float(p * e1["A"] + e2["A"]),73 "wealth_B": float(p * e1["B"] + e2["B"]),74 "summary_sheet_aggregate_endowment_good1": float(P["aggregate_endowment_good1"]),75 "sensitivity_excess_demand_good1_vs_summary_E1": float(sum(alloc[f"x1_{i}"] for i in agents) - P["aggregate_endowment_good1"]),76 "feasibility": "complete",77 "feasibility_reason": None,78 "data_issues": issues,79 "n_input_rows": n_rows,80 "n_analysed": len(agents),81 "random_seed": None,82}83with open(os.path.join(O, "results.json"), "w") as f:84 json.dump(res, f, indent=2)85print(json.dumps({k: res[k] for k in ["price_ratio_p1_over_p2", "price_ratio_numerical",86 "excess_demand_good1", "walras_law_residual"]}, indent=2))87