SPB Git

spb/wp29_uqo

Public
4.9 KB · 101 lines python
1"""F5-conf-01: competitive equilibrium of a 2x2 Cobb-Douglas exchange economy.2Run from workspace root: ~/wp29/venv/bin/python out/analysis.py3Reads only data/, writes out/results.json and out/exclusions.csv deterministically."""4import json, os5import numpy as np6import pandas as pd7from scipy.optimize import brentq89ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))10D = os.path.join(ROOT, "data"); O = os.path.join(ROOT, "out")1112end = pd.read_csv(os.path.join(D, "endowments.csv"))13par = pd.read_csv(os.path.join(D, "parameters.csv"))14n_rows = {"endowments.csv": int(len(end)), "parameters.csv": int(len(par))}15P = dict(zip(par["parameter"], par["value"].astype(float)))16issues = []1718# --- validation of inputs19assert set(end["agent"]) == {"A", "B"} and len(end) == 2 and not end.duplicated("agent").any()20assert end[["good1", "good2"]].notna().all().all() and (end[["good1", "good2"]] > 0).all().all()21aA, aB = P["alpha_A"], P["alpha_B"]22assert 0 < aA < 1 and 0 < aB < 123e = end.set_index("agent")[["good1", "good2"]].astype(float)24e1 = {i: e.loc[i, "good1"] for i in "AB"}; e2 = {i: e.loc[i, "good2"] for i in "AB"}25alpha = {"A": aA, "B": aB}2627agg1_rows, agg2_rows = e1["A"] + e1["B"], e2["A"] + e2["B"]28agg1_sheet, agg2_sheet = P["aggregate_endowment_good1"], P["aggregate_endowment_good2"]29if not np.isclose(agg1_rows, agg1_sheet):30    issues.append({31        "issue": (f"parameters.csv aggregate_endowment_good1 = {agg1_sheet:g} is inconsistent with the sum of "32                  f"individual endowments in endowments.csv ({e1['A']:g} + {e1['B']:g} = {agg1_rows:g})."),33        "handling": (f"Used the sum of individual endowments ({agg1_rows:g}) as the aggregate endowment of good 1, "34                     "because the individual endowments are the primary data and also determine agents' wealth; "35                     "using the summary-sheet value would make the market-clearing condition inconsistent with the "36                     "budget constraints (Walras' law would fail). The summary value was not used in any computation "37                     "other than this diagnostic.")})38if not np.isclose(agg2_rows, agg2_sheet):39    issues.append({"issue": f"aggregate_endowment_good2 sheet value {agg2_sheet:g} != sum of rows {agg2_rows:g}",40                   "handling": "Used sum of individual endowments."})41agg1, agg2 = agg1_rows, agg2_rows4243# --- demands (p2 = 1)44def demand(i, p):45    w = p * e1[i] + e2[i]46    return alpha[i] * w / p, (1 - alpha[i]) * w4748def z1(p):49    return sum(demand(i, p)[0] for i in "AB") - agg15051def z2(p):52    return sum(demand(i, p)[1] for i in "AB") - agg25354# --- closed form: p = sum alpha_i e2_i / sum (1-alpha_i) e1_i55p_cf = sum(alpha[i] * e2[i] for i in "AB") / sum((1 - alpha[i]) * e1[i] for i in "AB")5657# --- independent numerical root of z1(p) = 0 (Brent on a wide bracket; closed form not used)58lo, hi = 1e-6, 1e659assert z1(lo) > 0 and z1(hi) < 060p_num = brentq(z1, lo, hi, xtol=1e-14, rtol=1e-15, maxiter=500)6162x = {i: demand(i, p_cf) for i in "AB"}63ed1, ed2 = z1(p_cf), z2(p_cf)64walras = p_cf * ed1 + ed265# Walras' law should hold at arbitrary prices too: check on a grid (diagnostic)66grid = np.logspace(-2, 2, 41)67walras_grid_max = float(max(abs(p * z1(p) + z2(p)) for p in grid))68# diagnostic: excess demand of good 1 if the (inconsistent) summary-sheet aggregate were used69ed1_vs_sheet = float(sum(x[i][0] for i in "AB") - agg1_sheet)7071res = {72    "task_id": "F5-conf-01",73    "price_ratio_p1_over_p2": float(p_cf),74    "x1_A": float(x["A"][0]), "x2_A": float(x["A"][1]),75    "x1_B": float(x["B"][0]), "x2_B": float(x["B"][1]),76    "excess_demand_good1": float(ed1),77    "excess_demand_good2": float(ed2),78    "walras_law_residual": float(walras),79    "walras_law_residual_max_abs_on_price_grid": walras_grid_max,80    "aggregate_endowment_good1": float(agg1),81    "aggregate_endowment_good2": float(agg2),82    "aggregate_endowment_good1_summary_sheet": float(agg1_sheet),83    "excess_demand_good1_vs_summary_sheet_aggregate": ed1_vs_sheet,84    "price_ratio_numerical": float(p_num),85    "price_abs_diff_closed_vs_numerical": float(abs(p_cf - p_num)),86    "wealth_A": float(p_cf * e1["A"] + e2["A"]), "wealth_B": float(p_cf * e1["B"] + e2["B"]),87    "feasibility": "complete",88    "feasibility_reason": None,89    "data_issues": issues,90    "n_input_rows": n_rows,91    "n_analysed": 2,92    "random_seed": None,93}94with open(os.path.join(O, "results.json"), "w") as f:95    json.dump(res, f, indent=2)96pd.DataFrame([{"step": 1, "rule": "keep agents A and B with finite positive endowments", "n_before": n_rows["endowments.csv"],97               "n_after": 2, "n_removed": n_rows["endowments.csv"] - 2,98               "rationale": "no rows removed; both agents enter the equilibrium"}]).to_csv(os.path.join(O, "exclusions.csv"), index=False)99print(json.dumps({k: res[k] for k in ["price_ratio_p1_over_p2", "price_ratio_numerical", "x1_A", "x2_A", "x1_B", "x2_B",100                                      "excess_demand_good1", "walras_law_residual"]}, indent=1))101
Files · main
Menu

Theme