Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 31d580e0fe |
@@ -0,0 +1,4 @@
|
|||||||
|
regime,n_runs,contracts_total_mean,contracts_settled_mean,contracts_defaulted_mean,fees_total_mean,interest_total_mean,dividends_total_mean,token_supply_final_mean,gini_balance_mean,gini_wealth_mean,neg_balance_agents_mean,winner_hhi_mean,blocks_produced_mean,errors_mean
|
||||||
|
baseline,12,21.416666666666668,1.5833333333333333,3.6666666666666665,6889.916666666667,25.25,6694.0,5130.25,0.11320579599393549,0.12255043551137738,2.75,0.15893405292171156,30.5,19.583333333333332
|
||||||
|
coordination_push,12,29.5,0.16666666666666666,5.25,6994.083333333333,30.916666666666668,6799.0,5221.0,0.13216124014965233,0.13957263418464463,3.25,0.16634766732050965,23.416666666666668,27.666666666666668
|
||||||
|
high_compute_cost,12,13.666666666666666,1.1666666666666667,2.25,41151.166666666664,2725.5833333333335,40049.0,6429.666666666667,0.4698958246131037,0.4682073883181179,3.5833333333333335,0.17685328716682144,32.5,53.25
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"regime": "baseline",
|
||||||
|
"n_runs": 12,
|
||||||
|
"contracts_total_mean": 21.416666666666668,
|
||||||
|
"contracts_settled_mean": 1.5833333333333333,
|
||||||
|
"contracts_defaulted_mean": 3.6666666666666665,
|
||||||
|
"fees_total_mean": 6889.916666666667,
|
||||||
|
"interest_total_mean": 25.25,
|
||||||
|
"dividends_total_mean": 6694.0,
|
||||||
|
"token_supply_final_mean": 5130.25,
|
||||||
|
"gini_balance_mean": 0.11320579599393549,
|
||||||
|
"gini_wealth_mean": 0.12255043551137738,
|
||||||
|
"neg_balance_agents_mean": 2.75,
|
||||||
|
"winner_hhi_mean": 0.15893405292171156,
|
||||||
|
"blocks_produced_mean": 30.5,
|
||||||
|
"errors_mean": 19.583333333333332
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regime": "coordination_push",
|
||||||
|
"n_runs": 12,
|
||||||
|
"contracts_total_mean": 29.5,
|
||||||
|
"contracts_settled_mean": 0.16666666666666666,
|
||||||
|
"contracts_defaulted_mean": 5.25,
|
||||||
|
"fees_total_mean": 6994.083333333333,
|
||||||
|
"interest_total_mean": 30.916666666666668,
|
||||||
|
"dividends_total_mean": 6799.0,
|
||||||
|
"token_supply_final_mean": 5221.0,
|
||||||
|
"gini_balance_mean": 0.13216124014965233,
|
||||||
|
"gini_wealth_mean": 0.13957263418464463,
|
||||||
|
"neg_balance_agents_mean": 3.25,
|
||||||
|
"winner_hhi_mean": 0.16634766732050965,
|
||||||
|
"blocks_produced_mean": 23.416666666666668,
|
||||||
|
"errors_mean": 27.666666666666668
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regime": "high_compute_cost",
|
||||||
|
"n_runs": 12,
|
||||||
|
"contracts_total_mean": 13.666666666666666,
|
||||||
|
"contracts_settled_mean": 1.1666666666666667,
|
||||||
|
"contracts_defaulted_mean": 2.25,
|
||||||
|
"fees_total_mean": 41151.166666666664,
|
||||||
|
"interest_total_mean": 2725.5833333333335,
|
||||||
|
"dividends_total_mean": 40049.0,
|
||||||
|
"token_supply_final_mean": 6429.666666666667,
|
||||||
|
"gini_balance_mean": 0.4698958246131037,
|
||||||
|
"gini_wealth_mean": 0.4682073883181179,
|
||||||
|
"neg_balance_agents_mean": 3.5833333333333335,
|
||||||
|
"winner_hhi_mean": 0.17685328716682144,
|
||||||
|
"blocks_produced_mean": 32.5,
|
||||||
|
"errors_mean": 53.25
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
run_id,seed,regime,contracts_total,contracts_settled_total,contracts_defaulted_total,inference_fees_total,interest_total,dividends_total,token_supply_final,gini_balance,gini_wealth,negative_balance_agents,winner_hhi,blocks_produced,total_errors
|
||||||
|
baseline_101,101,baseline,25,3,5,6537,0,6344,5688,0.10367867093179228,0.10805514570269281,2,0.140625,32,7
|
||||||
|
baseline_102,102,baseline,21,2,5,6575,41,6336,5395,0.12518686599038964,0.13149684505725645,2,0.21284185493460167,29,17
|
||||||
|
baseline_103,103,baseline,26,1,4,6756,19,6604,5715,0.10513532726028108,0.11377504029472707,2,0.1581450653983353,29,15
|
||||||
|
baseline_104,104,baseline,21,0,3,7565,38,7352,4983,0.14965912014407,0.13289925177524653,3,0.1484375,32,24
|
||||||
|
baseline_105,105,baseline,22,2,2,6370,39,6248,4839,0.1148494778938014,0.14399083449301786,3,0.16326530612244897,28,30
|
||||||
|
baseline_106,106,baseline,25,2,4,6789,2,6648,5482,0.10252117013086992,0.10911460757843772,2,0.1527777777777778,36,5
|
||||||
|
baseline_107,107,baseline,20,0,2,6949,6,6836,4630,0.10530611152734659,0.11835918565196324,4,0.13142857142857142,35,10
|
||||||
|
baseline_108,108,baseline,22,5,5,6736,4,6564,4679,0.08859236426562833,0.10960999081193479,2,0.15051020408163265,28,12
|
||||||
|
baseline_109,109,baseline,23,4,6,6971,32,6708,4840,0.131812438193605,0.13027831094049902,4,0.15976331360946747,26,39
|
||||||
|
baseline_110,110,baseline,19,0,4,6932,52,6648,5412,0.12527187211135882,0.128596114328414,3,0.17146776406035663,27,39
|
||||||
|
baseline_111,111,baseline,18,0,1,7160,55,6960,5015,0.12123074401835465,0.13524268379728754,3,0.17377731529656607,31,22
|
||||||
|
baseline_112,112,baseline,15,0,3,7339,15,7080,4885,0.08522538945972813,0.10918721570505152,3,0.14416896235078056,33,15
|
||||||
|
coordination_push_101,101,coordination_push,29,0,6,6351,14,6160,5546,0.1274476439790575,0.11523020514248583,1,0.168,25,20
|
||||||
|
coordination_push_102,102,coordination_push,32,0,6,6586,11,6336,5603,0.1358069518979863,0.12982571865018744,2,0.1652794292508918,29,16
|
||||||
|
coordination_push_103,103,coordination_push,26,0,4,6641,32,6480,4314,0.13521196144218983,0.12699369892684853,4,0.14951989026063098,27,22
|
||||||
|
coordination_push_104,104,coordination_push,30,1,0,7931,17,7720,5314,0.12537674080232808,0.14814206624753679,4,0.16,30,19
|
||||||
|
coordination_push_105,105,coordination_push,32,0,9,6869,81,6744,5212,0.15909207686774218,0.15521874410710912,3,0.16666666666666666,18,23
|
||||||
|
coordination_push_106,106,coordination_push,32,0,7,6981,57,6852,5624,0.14058216520974498,0.1512555493895671,4,0.15646258503401358,21,45
|
||||||
|
coordination_push_107,107,coordination_push,26,0,4,6556,25,6436,5260,0.13967720970537267,0.15706726246472247,4,0.18112244897959182,28,29
|
||||||
|
coordination_push_108,108,coordination_push,32,0,4,7024,6,6848,5566,0.1090025906735752,0.14071918761012703,4,0.165,20,18
|
||||||
|
coordination_push_109,109,coordination_push,29,1,9,6780,21,6512,4965,0.11734141589088543,0.13086692105890774,3,0.1648,25,41
|
||||||
|
coordination_push_110,110,coordination_push,31,0,3,6862,18,6588,5289,0.11928036605657244,0.11289280849264882,3,0.16,20,25
|
||||||
|
coordination_push_111,111,coordination_push,25,0,5,7805,58,7636,4901,0.1322481243301179,0.1545201186546099,4,0.20500000000000002,20,47
|
||||||
|
coordination_push_112,112,coordination_push,30,0,6,7543,31,7276,5058,0.14486763494025556,0.15213932947098496,3,0.15432098765432098,18,27
|
||||||
|
high_compute_cost_101,101,high_compute_cost,11,0,1,41924,2698,40796,6773,0.4227513119055428,0.41859879954616996,4,0.18626430801248697,31,46
|
||||||
|
high_compute_cost_102,102,high_compute_cost,15,1,6,40494,2956,39300,2978,0.5485028304697586,0.5258750052838483,4,0.17355371900826447,33,63
|
||||||
|
high_compute_cost_103,103,high_compute_cost,10,1,1,40647,2784,39724,7303,0.41454709908024934,0.42170703872772797,3,0.1753902662993572,33,51
|
||||||
|
high_compute_cost_104,104,high_compute_cost,16,1,2,42460,2516,41320,6172,0.5149586456448694,0.5189896196393393,4,0.189453125,32,60
|
||||||
|
high_compute_cost_105,105,high_compute_cost,16,1,1,40145,2840,39272,5899,0.46256225313412336,0.46151061333724375,4,0.16129032258064516,31,52
|
||||||
|
high_compute_cost_106,106,high_compute_cost,15,3,4,40613,3533,39712,6206,0.5568047990578537,0.519489781180039,4,0.15816326530612243,28,67
|
||||||
|
high_compute_cost_107,107,high_compute_cost,12,2,1,40731,2634,39868,8594,0.42507908825438023,0.43840259740259735,3,0.248046875,32,49
|
||||||
|
high_compute_cost_108,108,high_compute_cost,13,0,2,41493,2623,40492,7646,0.47062565812565804,0.4797243946458114,3,0.1697530864197531,36,46
|
||||||
|
high_compute_cost_109,109,high_compute_cost,15,1,5,37479,1953,36116,6775,0.38451149162164633,0.4106027603222946,3,0.16049382716049382,36,45
|
||||||
|
high_compute_cost_110,110,high_compute_cost,13,3,1,39742,1960,38368,8442,0.45729572898557524,0.4670887939920483,3,0.1712962962962963,36,36
|
||||||
|
high_compute_cost_111,111,high_compute_cost,17,0,2,44067,3304,42940,5552,0.5041796108567691,0.49005196406552765,4,0.1607142857142857,28,60
|
||||||
|
high_compute_cost_112,112,high_compute_cost,11,1,1,44019,2906,42680,4816,0.476931378220818,0.46644729167476773,4,0.16782006920415227,34,64
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,581 @@
|
|||||||
|
import csv
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import sqlite3
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import urllib.error
|
||||||
|
import urllib.request
|
||||||
|
from collections import Counter, defaultdict
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
ENGINE_DIR = ROOT / "sim-engine"
|
||||||
|
ENGINE_BIN = ENGINE_DIR / "target" / "release" / "sim-engine"
|
||||||
|
RESULTS_DIR = ROOT / "research" / "results"
|
||||||
|
RUNS_DIR = RESULTS_DIR / "runs"
|
||||||
|
|
||||||
|
|
||||||
|
def http_json(method: str, url: str, payload=None, timeout=20):
|
||||||
|
data = None
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
if payload is not None:
|
||||||
|
data = json.dumps(payload).encode("utf-8")
|
||||||
|
req = urllib.request.Request(url=url, data=data, headers=headers, method=method)
|
||||||
|
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||||
|
return json.loads(resp.read().decode("utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for_engine(base_url: str, timeout_s: float = 15.0):
|
||||||
|
start = time.time()
|
||||||
|
while time.time() - start < timeout_s:
|
||||||
|
try:
|
||||||
|
http_json("GET", f"{base_url}/config", timeout=2)
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
time.sleep(0.2)
|
||||||
|
raise RuntimeError("engine did not become ready")
|
||||||
|
|
||||||
|
|
||||||
|
def gini(values):
|
||||||
|
xs = sorted(values)
|
||||||
|
n = len(xs)
|
||||||
|
if n == 0:
|
||||||
|
return 0.0
|
||||||
|
total = sum(xs)
|
||||||
|
if total == 0:
|
||||||
|
return 0.0
|
||||||
|
weighted = 0
|
||||||
|
for i, x in enumerate(xs, start=1):
|
||||||
|
weighted += i * x
|
||||||
|
return (2 * weighted) / (n * total) - (n + 1) / n
|
||||||
|
|
||||||
|
|
||||||
|
def choose_action(
|
||||||
|
rng,
|
||||||
|
turn,
|
||||||
|
max_turns,
|
||||||
|
agent_id,
|
||||||
|
state_by_agent,
|
||||||
|
pending_sign,
|
||||||
|
pending_arb_rulings,
|
||||||
|
due_confirmations,
|
||||||
|
regime,
|
||||||
|
):
|
||||||
|
me = state_by_agent[agent_id]
|
||||||
|
balance = me["balance"]
|
||||||
|
|
||||||
|
for c in pending_arb_rulings:
|
||||||
|
if c["arbitrator"] == agent_id and c["status"] == "disputed":
|
||||||
|
ruling_for = c["proposer"] if rng.random() < 0.55 else c["counterparty"]
|
||||||
|
return {
|
||||||
|
"action": "arbitrator_ruling",
|
||||||
|
"contract_id": c["contract_id"],
|
||||||
|
"ruling_for": ruling_for,
|
||||||
|
}, None
|
||||||
|
|
||||||
|
for c in pending_sign:
|
||||||
|
if c["counterparty"] == agent_id and c["status"] == "proposed":
|
||||||
|
if rng.random() < regime["sign_prob"]:
|
||||||
|
return {
|
||||||
|
"action": "sign_contract",
|
||||||
|
"contract_id": c["contract_id"],
|
||||||
|
"role": "counterparty",
|
||||||
|
}, None
|
||||||
|
if c["arbitrator"] == agent_id and c["status"] in {"proposed", "countersigned"}:
|
||||||
|
if rng.random() < regime["arb_sign_prob"]:
|
||||||
|
return {
|
||||||
|
"action": "sign_contract",
|
||||||
|
"contract_id": c["contract_id"],
|
||||||
|
"role": "arbitrator",
|
||||||
|
}, None
|
||||||
|
|
||||||
|
for c in due_confirmations:
|
||||||
|
if c["status"] != "active":
|
||||||
|
continue
|
||||||
|
if c["proposer"] == agent_id or c["counterparty"] == agent_id:
|
||||||
|
if rng.random() < regime["confirm_prob"]:
|
||||||
|
return {"action": "confirm_delivery", "contract_id": c["contract_id"]}, None
|
||||||
|
if rng.random() < regime["dispute_prob"]:
|
||||||
|
return {"action": "dispute_delivery", "contract_id": c["contract_id"]}, None
|
||||||
|
|
||||||
|
if turn == 1:
|
||||||
|
core_id = f"core_{rng.randrange(regime['num_cores'])}"
|
||||||
|
bid = max(1, int(abs(rng.gauss(regime["core_bid_mean"], regime["core_bid_std"]))))
|
||||||
|
bid = min(bid, max(1, int(balance * 0.35)))
|
||||||
|
return {"action": "bid_core", "core_id": core_id, "amount": bid}, None
|
||||||
|
|
||||||
|
if balance < 0:
|
||||||
|
if rng.random() < 0.6:
|
||||||
|
return {"action": "job"}, "taking job to cover debt"
|
||||||
|
return {"action": "mine"}, None
|
||||||
|
|
||||||
|
if balance < regime["low_balance_threshold"] and rng.random() < 0.35:
|
||||||
|
return {"action": "job"}, None
|
||||||
|
|
||||||
|
r = rng.random()
|
||||||
|
if r < regime["mine_prob"]:
|
||||||
|
return {"action": "mine"}, None
|
||||||
|
|
||||||
|
r -= regime["mine_prob"]
|
||||||
|
if r < regime["stake_prob"] and balance > 20:
|
||||||
|
amount = min(int(balance * rng.uniform(0.05, 0.25)), max(5, int(balance) - 1))
|
||||||
|
return {"action": "stake", "amount": max(1, amount)}, None
|
||||||
|
|
||||||
|
r -= regime["stake_prob"]
|
||||||
|
if r < regime["burn_prob"] and balance > 20:
|
||||||
|
amount = min(int(balance * rng.uniform(0.03, 0.2)), max(3, int(balance) - 1))
|
||||||
|
return {"action": "burn", "amount": max(1, amount)}, None
|
||||||
|
|
||||||
|
r -= regime["burn_prob"]
|
||||||
|
if r < regime["transfer_prob"] and balance > 15:
|
||||||
|
others = [a for a in state_by_agent if a != agent_id]
|
||||||
|
to = rng.choice(others)
|
||||||
|
amount = max(1, min(int(balance * rng.uniform(0.01, 0.08)), 30))
|
||||||
|
return {"action": "transfer", "to": to, "amount": amount, "fee": 1}, "small transfer"
|
||||||
|
|
||||||
|
r -= regime["transfer_prob"]
|
||||||
|
if r < regime["propose_prob"] and turn < max_turns - 2 and balance > 80:
|
||||||
|
others = [a for a in state_by_agent if a != agent_id]
|
||||||
|
counterparty = rng.choice(others)
|
||||||
|
arb = rng.choice([a for a in others if a != counterparty])
|
||||||
|
delivery = min(max_turns - 1, turn + rng.randint(2, 6))
|
||||||
|
price = rng.randint(15, 80)
|
||||||
|
p_lock = rng.randint(10, 40)
|
||||||
|
cp_lock = rng.randint(10, 40)
|
||||||
|
a_lock = rng.randint(5, 20)
|
||||||
|
contract_type = rng.choice(["service", "information_sale", "forward", "loan"])
|
||||||
|
return {
|
||||||
|
"action": "propose_contract",
|
||||||
|
"contract": {
|
||||||
|
"counterparty": counterparty,
|
||||||
|
"arbitrator": arb,
|
||||||
|
"contract_type": contract_type,
|
||||||
|
"terms": {
|
||||||
|
"description": f"auto-generated {contract_type} at turn {turn}",
|
||||||
|
"price": price,
|
||||||
|
"delivery_turn": delivery,
|
||||||
|
"condition": None,
|
||||||
|
"pool_members": None,
|
||||||
|
},
|
||||||
|
"collateral": {
|
||||||
|
"proposer_locked": p_lock,
|
||||||
|
"counterparty_locked": cp_lock,
|
||||||
|
"arbitrator_locked": a_lock,
|
||||||
|
},
|
||||||
|
"settlement_type": "attested",
|
||||||
|
"penalty": rng.randint(5, 20),
|
||||||
|
"arbitrator_fee": rng.randint(2, 8),
|
||||||
|
"payload": None,
|
||||||
|
},
|
||||||
|
}, "contract proposal"
|
||||||
|
|
||||||
|
if balance > 100 and rng.random() < regime["study_prob"]:
|
||||||
|
return {"action": "study"}, None
|
||||||
|
|
||||||
|
return {"action": "mine"}, None
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_contracts(db_path: Path):
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
rows = conn.execute("SELECT contract_id, status, data FROM contracts").fetchall()
|
||||||
|
conn.close()
|
||||||
|
contracts = []
|
||||||
|
for row in rows:
|
||||||
|
data = json.loads(row["data"])
|
||||||
|
data["status"] = row["status"]
|
||||||
|
contracts.append(data)
|
||||||
|
return contracts
|
||||||
|
|
||||||
|
|
||||||
|
def assign_core_shares(db_path: Path, bids, num_cores):
|
||||||
|
conn = sqlite3.connect(db_path)
|
||||||
|
by_core = defaultdict(list)
|
||||||
|
for bid in bids:
|
||||||
|
by_core[bid["core_id"]].append((bid["agent_id"], int(bid["amount"])))
|
||||||
|
|
||||||
|
winners = {}
|
||||||
|
for i in range(num_cores):
|
||||||
|
core = f"core_{i}"
|
||||||
|
entries = by_core.get(core, [])
|
||||||
|
if entries:
|
||||||
|
winners[core] = max(entries, key=lambda x: x[1])[0]
|
||||||
|
|
||||||
|
if len(winners) < num_cores:
|
||||||
|
seen = set(winners.values())
|
||||||
|
all_agents = sorted({b["agent_id"] for b in bids})
|
||||||
|
fill = [a for a in all_agents if a not in seen] + all_agents
|
||||||
|
idx = 0
|
||||||
|
for i in range(num_cores):
|
||||||
|
core = f"core_{i}"
|
||||||
|
if core in winners:
|
||||||
|
continue
|
||||||
|
winners[core] = fill[idx % len(fill)]
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
conn.execute("DELETE FROM core_shares")
|
||||||
|
for core_id, owner in winners.items():
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO core_shares(core_id, owner, proportion) VALUES (?, ?, ?)",
|
||||||
|
(core_id, owner, 1.0),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return winners
|
||||||
|
|
||||||
|
|
||||||
|
def run_single(seed, regime_name, regime, turns=40, n_agents=8, port=3100):
|
||||||
|
rng = random.Random(seed)
|
||||||
|
agent_ids = [f"agent_{i}" for i in range(n_agents)]
|
||||||
|
db_path = RUNS_DIR / f"run_{regime_name}_{seed}.db"
|
||||||
|
if db_path.exists():
|
||||||
|
db_path.unlink()
|
||||||
|
|
||||||
|
env = os.environ.copy()
|
||||||
|
env["DB_PATH"] = str(db_path)
|
||||||
|
env["PORT"] = str(port)
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
[str(ENGINE_BIN)],
|
||||||
|
cwd=str(ENGINE_DIR),
|
||||||
|
env=env,
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
|
||||||
|
base_url = f"http://127.0.0.1:{port}"
|
||||||
|
try:
|
||||||
|
wait_for_engine(base_url)
|
||||||
|
cfg = {
|
||||||
|
"num_agents": n_agents,
|
||||||
|
"num_cores": regime["num_cores"],
|
||||||
|
"genesis_tokens_per_agent": regime["genesis_tokens_per_agent"],
|
||||||
|
"commons_threshold_per_turn": regime["commons_threshold_per_turn"],
|
||||||
|
"base_inference_rate": regime["base_inference_rate"],
|
||||||
|
"thinking_layer_discount": 0.1,
|
||||||
|
"mine_base_weight": regime["mine_base_weight"],
|
||||||
|
"stake_weight_per_token": regime["stake_weight_per_token"],
|
||||||
|
"burn_weight_per_token": regime["burn_weight_per_token"],
|
||||||
|
"burn_decay_rate": 0.02,
|
||||||
|
"burn_maturity_turns": 3,
|
||||||
|
"unstake_delay_turns": 5,
|
||||||
|
"interest_rate_per_turn": regime["interest_rate_per_turn"],
|
||||||
|
"signing_bonus": 50,
|
||||||
|
"block_threshold": regime["block_threshold"],
|
||||||
|
"attested_confirmation_window": 3,
|
||||||
|
"slash_both_on_timeout": True,
|
||||||
|
}
|
||||||
|
http_json("POST", f"{base_url}/init", {"config": cfg, "agent_ids": agent_ids})
|
||||||
|
|
||||||
|
turn_rows = []
|
||||||
|
action_counts = Counter()
|
||||||
|
winner_counts = Counter()
|
||||||
|
total_errors = 0
|
||||||
|
core_bids = []
|
||||||
|
|
||||||
|
for turn in range(1, turns + 1):
|
||||||
|
state = http_json("GET", f"{base_url}/state")
|
||||||
|
state_by_agent = {a["agent_id"]: a for a in state.get("agents", [])}
|
||||||
|
|
||||||
|
contracts = fetch_contracts(db_path)
|
||||||
|
pending_sign = [
|
||||||
|
c for c in contracts if c["status"] in {"proposed", "countersigned"}
|
||||||
|
]
|
||||||
|
due_confirm = [
|
||||||
|
c
|
||||||
|
for c in contracts
|
||||||
|
if c["status"] == "active" and int(c["terms"]["delivery_turn"]) <= turn
|
||||||
|
]
|
||||||
|
pending_rulings = [c for c in contracts if c["status"] == "disputed"]
|
||||||
|
|
||||||
|
inputs = []
|
||||||
|
for agent_id in agent_ids:
|
||||||
|
action, speech = choose_action(
|
||||||
|
rng,
|
||||||
|
turn,
|
||||||
|
turns,
|
||||||
|
agent_id,
|
||||||
|
state_by_agent,
|
||||||
|
pending_sign,
|
||||||
|
pending_rulings,
|
||||||
|
due_confirm,
|
||||||
|
regime,
|
||||||
|
)
|
||||||
|
action_counts[action["action"]] += 1
|
||||||
|
if action["action"] == "bid_core":
|
||||||
|
core_bids.append(
|
||||||
|
{
|
||||||
|
"turn": turn,
|
||||||
|
"agent_id": agent_id,
|
||||||
|
"core_id": action["core_id"],
|
||||||
|
"amount": action["amount"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
inputs.append(
|
||||||
|
{
|
||||||
|
"agent_id": agent_id,
|
||||||
|
"thinking": "",
|
||||||
|
"action": action,
|
||||||
|
"speech": speech,
|
||||||
|
"thinking_units": rng.randint(10, 100),
|
||||||
|
"output_units": rng.randint(20, 180),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
out = http_json("POST", f"{base_url}/turn", {"inputs": inputs})
|
||||||
|
if not out.get("ok", False):
|
||||||
|
raise RuntimeError(out.get("error", "unknown turn error"))
|
||||||
|
data = out.get("data", {})
|
||||||
|
|
||||||
|
if turn == 1:
|
||||||
|
assign_core_shares(db_path, core_bids, regime["num_cores"])
|
||||||
|
|
||||||
|
winner = data.get("block_winner")
|
||||||
|
if winner:
|
||||||
|
winner_counts[winner] += 1
|
||||||
|
errs = data.get("errors", [])
|
||||||
|
total_errors += len(errs)
|
||||||
|
turn_rows.append(
|
||||||
|
{
|
||||||
|
"turn": turn,
|
||||||
|
"block_winner": winner or "",
|
||||||
|
"inference_fees": int(data.get("inference_fees_collected", 0)),
|
||||||
|
"contracts_settled": len(data.get("contracts_settled", [])),
|
||||||
|
"contracts_defaulted": len(data.get("contracts_defaulted", [])),
|
||||||
|
"errors": len(errs),
|
||||||
|
"dividends_total": int(sum(data.get("dividends_paid", {}).values())),
|
||||||
|
"interest_total": int(sum(data.get("interest_charged", {}).values())),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
final_state = http_json("GET", f"{base_url}/state")
|
||||||
|
agents = final_state.get("agents", [])
|
||||||
|
balances = [int(a.get("balance", 0)) for a in agents]
|
||||||
|
staked = [int(a.get("staked", 0)) for a in agents]
|
||||||
|
wealth = [b + s for b, s in zip(balances, staked)]
|
||||||
|
contracts = fetch_contracts(db_path)
|
||||||
|
status_counts = Counter(c["status"] for c in contracts)
|
||||||
|
|
||||||
|
total_fees = sum(r["inference_fees"] for r in turn_rows)
|
||||||
|
total_interest = sum(r["interest_total"] for r in turn_rows)
|
||||||
|
total_dividends = sum(r["dividends_total"] for r in turn_rows)
|
||||||
|
total_settled = sum(r["contracts_settled"] for r in turn_rows)
|
||||||
|
total_defaulted = sum(r["contracts_defaulted"] for r in turn_rows)
|
||||||
|
|
||||||
|
hhi = 0.0
|
||||||
|
if winner_counts:
|
||||||
|
total_wins = sum(winner_counts.values())
|
||||||
|
hhi = sum((count / total_wins) ** 2 for count in winner_counts.values())
|
||||||
|
|
||||||
|
run_summary = {
|
||||||
|
"run_id": f"{regime_name}_{seed}",
|
||||||
|
"seed": seed,
|
||||||
|
"regime": regime_name,
|
||||||
|
"turns": turns,
|
||||||
|
"agents": n_agents,
|
||||||
|
"contracts_total": len(contracts),
|
||||||
|
"contracts_settled_total": total_settled,
|
||||||
|
"contracts_defaulted_total": total_defaulted,
|
||||||
|
"contracts_final_status": dict(status_counts),
|
||||||
|
"inference_fees_total": total_fees,
|
||||||
|
"interest_total": total_interest,
|
||||||
|
"dividends_total": total_dividends,
|
||||||
|
"token_supply_final": int(final_state.get("token_supply", 0)),
|
||||||
|
"mean_balance": sum(balances) / len(balances),
|
||||||
|
"median_balance": sorted(balances)[len(balances) // 2],
|
||||||
|
"mean_wealth": sum(wealth) / len(wealth),
|
||||||
|
"gini_balance": gini([max(0, b + 2000) for b in balances]),
|
||||||
|
"gini_wealth": gini([max(0, w + 2000) for w in wealth]),
|
||||||
|
"negative_balance_agents": sum(1 for b in balances if b < 0),
|
||||||
|
"winner_hhi": hhi,
|
||||||
|
"blocks_produced": sum(1 for r in turn_rows if r["block_winner"]),
|
||||||
|
"action_counts": dict(action_counts),
|
||||||
|
"winner_counts": dict(winner_counts),
|
||||||
|
"total_errors": total_errors,
|
||||||
|
"balances_final": {a["agent_id"]: int(a.get("balance", 0)) for a in agents},
|
||||||
|
"staked_final": {a["agent_id"]: int(a.get("staked", 0)) for a in agents},
|
||||||
|
"turn_rows": turn_rows,
|
||||||
|
}
|
||||||
|
return run_summary
|
||||||
|
finally:
|
||||||
|
proc.terminate()
|
||||||
|
try:
|
||||||
|
proc.wait(timeout=3)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
proc.kill()
|
||||||
|
|
||||||
|
|
||||||
|
def summarize_by_regime(runs):
|
||||||
|
grouped = defaultdict(list)
|
||||||
|
for r in runs:
|
||||||
|
grouped[r["regime"]].append(r)
|
||||||
|
|
||||||
|
rows = []
|
||||||
|
for regime, rs in grouped.items():
|
||||||
|
n = len(rs)
|
||||||
|
def mean(key):
|
||||||
|
return sum(x[key] for x in rs) / n
|
||||||
|
|
||||||
|
rows.append(
|
||||||
|
{
|
||||||
|
"regime": regime,
|
||||||
|
"n_runs": n,
|
||||||
|
"contracts_total_mean": mean("contracts_total"),
|
||||||
|
"contracts_settled_mean": mean("contracts_settled_total"),
|
||||||
|
"contracts_defaulted_mean": mean("contracts_defaulted_total"),
|
||||||
|
"fees_total_mean": mean("inference_fees_total"),
|
||||||
|
"interest_total_mean": mean("interest_total"),
|
||||||
|
"dividends_total_mean": mean("dividends_total"),
|
||||||
|
"token_supply_final_mean": mean("token_supply_final"),
|
||||||
|
"gini_balance_mean": mean("gini_balance"),
|
||||||
|
"gini_wealth_mean": mean("gini_wealth"),
|
||||||
|
"neg_balance_agents_mean": mean("negative_balance_agents"),
|
||||||
|
"winner_hhi_mean": mean("winner_hhi"),
|
||||||
|
"blocks_produced_mean": mean("blocks_produced"),
|
||||||
|
"errors_mean": mean("total_errors"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return sorted(rows, key=lambda x: x["regime"])
|
||||||
|
|
||||||
|
|
||||||
|
def write_outputs(runs, regime_rows):
|
||||||
|
RESULTS_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
RUNS_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
with open(RESULTS_DIR / "run_summaries.json", "w", encoding="utf-8") as f:
|
||||||
|
json.dump(runs, f, indent=2)
|
||||||
|
|
||||||
|
with open(RESULTS_DIR / "regime_summary.json", "w", encoding="utf-8") as f:
|
||||||
|
json.dump(regime_rows, f, indent=2)
|
||||||
|
|
||||||
|
with open(RESULTS_DIR / "run_summaries.csv", "w", newline="", encoding="utf-8") as f:
|
||||||
|
fields = [
|
||||||
|
"run_id",
|
||||||
|
"seed",
|
||||||
|
"regime",
|
||||||
|
"contracts_total",
|
||||||
|
"contracts_settled_total",
|
||||||
|
"contracts_defaulted_total",
|
||||||
|
"inference_fees_total",
|
||||||
|
"interest_total",
|
||||||
|
"dividends_total",
|
||||||
|
"token_supply_final",
|
||||||
|
"gini_balance",
|
||||||
|
"gini_wealth",
|
||||||
|
"negative_balance_agents",
|
||||||
|
"winner_hhi",
|
||||||
|
"blocks_produced",
|
||||||
|
"total_errors",
|
||||||
|
]
|
||||||
|
w = csv.DictWriter(f, fieldnames=fields)
|
||||||
|
w.writeheader()
|
||||||
|
for r in runs:
|
||||||
|
w.writerow({k: r[k] for k in fields})
|
||||||
|
|
||||||
|
with open(RESULTS_DIR / "regime_summary.csv", "w", newline="", encoding="utf-8") as f:
|
||||||
|
fields = list(regime_rows[0].keys()) if regime_rows else []
|
||||||
|
w = csv.DictWriter(f, fieldnames=fields)
|
||||||
|
w.writeheader()
|
||||||
|
for row in regime_rows:
|
||||||
|
w.writerow(row)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
RUNS_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
if not ENGINE_BIN.exists():
|
||||||
|
raise RuntimeError(f"engine binary not found at {ENGINE_BIN}")
|
||||||
|
|
||||||
|
regimes = {
|
||||||
|
"baseline": {
|
||||||
|
"num_cores": 4,
|
||||||
|
"genesis_tokens_per_agent": 1000,
|
||||||
|
"commons_threshold_per_turn": 100,
|
||||||
|
"base_inference_rate": 1,
|
||||||
|
"mine_base_weight": 10.0,
|
||||||
|
"stake_weight_per_token": 0.01,
|
||||||
|
"burn_weight_per_token": 0.05,
|
||||||
|
"block_threshold": 20.0,
|
||||||
|
"interest_rate_per_turn": 0.01,
|
||||||
|
"core_bid_mean": 120,
|
||||||
|
"core_bid_std": 55,
|
||||||
|
"low_balance_threshold": 120,
|
||||||
|
"mine_prob": 0.46,
|
||||||
|
"stake_prob": 0.14,
|
||||||
|
"burn_prob": 0.10,
|
||||||
|
"transfer_prob": 0.10,
|
||||||
|
"propose_prob": 0.12,
|
||||||
|
"study_prob": 0.08,
|
||||||
|
"sign_prob": 0.62,
|
||||||
|
"arb_sign_prob": 0.58,
|
||||||
|
"confirm_prob": 0.66,
|
||||||
|
"dispute_prob": 0.08,
|
||||||
|
},
|
||||||
|
"coordination_push": {
|
||||||
|
"num_cores": 4,
|
||||||
|
"genesis_tokens_per_agent": 1000,
|
||||||
|
"commons_threshold_per_turn": 100,
|
||||||
|
"base_inference_rate": 1,
|
||||||
|
"mine_base_weight": 10.0,
|
||||||
|
"stake_weight_per_token": 0.01,
|
||||||
|
"burn_weight_per_token": 0.05,
|
||||||
|
"block_threshold": 20.0,
|
||||||
|
"interest_rate_per_turn": 0.01,
|
||||||
|
"core_bid_mean": 150,
|
||||||
|
"core_bid_std": 60,
|
||||||
|
"low_balance_threshold": 100,
|
||||||
|
"mine_prob": 0.36,
|
||||||
|
"stake_prob": 0.15,
|
||||||
|
"burn_prob": 0.08,
|
||||||
|
"transfer_prob": 0.10,
|
||||||
|
"propose_prob": 0.22,
|
||||||
|
"study_prob": 0.09,
|
||||||
|
"sign_prob": 0.80,
|
||||||
|
"arb_sign_prob": 0.75,
|
||||||
|
"confirm_prob": 0.84,
|
||||||
|
"dispute_prob": 0.04,
|
||||||
|
},
|
||||||
|
"high_compute_cost": {
|
||||||
|
"num_cores": 4,
|
||||||
|
"genesis_tokens_per_agent": 1000,
|
||||||
|
"commons_threshold_per_turn": 60,
|
||||||
|
"base_inference_rate": 3,
|
||||||
|
"mine_base_weight": 10.0,
|
||||||
|
"stake_weight_per_token": 0.01,
|
||||||
|
"burn_weight_per_token": 0.05,
|
||||||
|
"block_threshold": 20.0,
|
||||||
|
"interest_rate_per_turn": 0.02,
|
||||||
|
"core_bid_mean": 100,
|
||||||
|
"core_bid_std": 45,
|
||||||
|
"low_balance_threshold": 220,
|
||||||
|
"mine_prob": 0.42,
|
||||||
|
"stake_prob": 0.12,
|
||||||
|
"burn_prob": 0.08,
|
||||||
|
"transfer_prob": 0.08,
|
||||||
|
"propose_prob": 0.10,
|
||||||
|
"study_prob": 0.05,
|
||||||
|
"sign_prob": 0.50,
|
||||||
|
"arb_sign_prob": 0.48,
|
||||||
|
"confirm_prob": 0.52,
|
||||||
|
"dispute_prob": 0.14,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runs = []
|
||||||
|
seeds = list(range(101, 113))
|
||||||
|
port = 3100
|
||||||
|
for regime_name, regime in regimes.items():
|
||||||
|
for seed in seeds:
|
||||||
|
run = run_single(seed=seed, regime_name=regime_name, regime=regime, turns=40, n_agents=8, port=port)
|
||||||
|
runs.append(run)
|
||||||
|
port += 1
|
||||||
|
|
||||||
|
regime_rows = summarize_by_regime(runs)
|
||||||
|
write_outputs(runs, regime_rows)
|
||||||
|
print(json.dumps({"runs": len(runs), "regimes": len(regime_rows)}, indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,333 @@
|
|||||||
|
# Compute-Rationed Firms: Evidence From a Blockchain-Mediated Multi-Agent Economy
|
||||||
|
|
||||||
|
## Abstract
|
||||||
|
|
||||||
|
This paper reports results from 36 simulation runs (3 regimes x 12 seeds) in the `sim-economy` environment, a system where autonomous agents operate firms inside a blockchain-mediated token economy with explicit inference billing, contract collateral, and validator lotteries. We focus on two questions: (1) how compute pricing changes organizational outcomes and (2) which institutional frictions prevent AI-run firms from scaling cooperation. Using only measured outputs from executed runs, we find that high compute cost produces a sharp inequality jump (mean wealth Gini 0.468 vs 0.123 baseline), heavy debt service (mean interest 2725.6 vs 25.3), and more operational errors (53.3 vs 19.6 per run). A coordination-focused regime increases contract volume (29.5 vs 21.4 baseline) but collapses completion quality (settlement rate 0.56%). Across all regimes, approximately 97% of inference fees are captured and redistributed by core owners, making compute infrastructure ownership the dominant rent-extraction channel. We discuss implications for AI-native corporate design: compute rights become quasi-equity, contract throughput is not contract reliability, and governance must prioritize dispute/fulfillment quality over deal count.
|
||||||
|
|
||||||
|
## 1. Background and Motivation
|
||||||
|
|
||||||
|
AI-run companies will need internal market mechanisms for allocating scarce compute, pricing commitments, and enforcing agreements among specialized agents. The `sim-economy` project provides a minimal institutional laboratory for this problem: agents can mine/stake/burn for block production rights, negotiate collateralized contracts, and pay token-denominated inference costs that are redistributed to core-share owners [1].
|
||||||
|
|
||||||
|
From an organizational economics perspective, this setup lets us test a concrete claim: when coordination and production are both mediated by costly compute, ownership of compute infrastructure may dominate classic managerial levers (role assignment, task decomposition, contract templates). If true, AI firms may resemble platform monopolies or utility cartels unless compute governance is explicitly redesigned.
|
||||||
|
|
||||||
|
This study is not a benchmark for model intelligence. Instead, it is a systems paper on institutional dynamics under endogenous compute cost.
|
||||||
|
|
||||||
|
## 2. Environment and Mechanisms
|
||||||
|
|
||||||
|
### 2.1 Engine Architecture
|
||||||
|
|
||||||
|
The simulation engine is Rust/Axum with SQLite persistence (`sim-engine`), and an orchestrator submits turn-level actions (`sim-orchestrator`) [1]. The state transition sequence in each turn follows `process_turn` in `sim-engine/src/engine.rs`: action processing, inference billing, dividend payout, block attempt, contract settlement, then persistence [2].
|
||||||
|
|
||||||
|
### 2.2 Economic Primitives
|
||||||
|
|
||||||
|
- **Inference billing**: agents pay token fees for compute above a commons threshold, with study-based discounting [2].
|
||||||
|
- **Core ownership dividends**: collected inference fees are distributed to core-share owners each turn [2][3].
|
||||||
|
- **Validation competition**: mine/stake/burn contributions determine block lottery odds with threshold gating [4].
|
||||||
|
- **Contracting**: 3-party contracts (proposer, counterparty, arbitrator) with collateral lockups, attested settlement, disputes, and slashing rules [5].
|
||||||
|
|
||||||
|
These mechanisms jointly create a closed economy where liquidity, reliability, and coordination all depend on compute-mediated incentives.
|
||||||
|
|
||||||
|
## 3. Method
|
||||||
|
|
||||||
|
### 3.1 Experimental Design
|
||||||
|
|
||||||
|
I ran **36 full simulations** using a reproducible driver script at `research/run_experiments.py`:
|
||||||
|
|
||||||
|
- 3 regimes: `baseline`, `coordination_push`, `high_compute_cost`
|
||||||
|
- 12 random seeds per regime (`101..112`)
|
||||||
|
- 8 agents, 40 turns per run
|
||||||
|
- Local Rust engine binary (`sim-engine/target/release/sim-engine`)
|
||||||
|
|
||||||
|
Each run writes a dedicated SQLite ledger; aggregated outputs are in:
|
||||||
|
|
||||||
|
- `research/results/run_summaries.csv`
|
||||||
|
- `research/results/regime_summary.csv`
|
||||||
|
|
||||||
|
### 3.2 Regime Differences
|
||||||
|
|
||||||
|
- **baseline**: default-like pricing and mixed action policy.
|
||||||
|
- **coordination_push**: higher proposal/sign/confirm probabilities to stimulate agreement activity.
|
||||||
|
- **high_compute_cost**: lower free threshold, higher per-unit compute price, and higher debt interest.
|
||||||
|
|
||||||
|
All reported values in Sections 4-5 are directly computed from executed runs (no synthetic interpolation).
|
||||||
|
|
||||||
|
### 3.3 Metrics
|
||||||
|
|
||||||
|
Primary metrics:
|
||||||
|
|
||||||
|
- Contract throughput and outcomes (total, settled, defaulted)
|
||||||
|
- Inference fees, dividends, and interest
|
||||||
|
- Final token supply
|
||||||
|
- Wealth inequality (Gini on final wealth = balance + staked)
|
||||||
|
- Negative-balance exposure
|
||||||
|
- Block-winner concentration (HHI)
|
||||||
|
- Engine-reported action errors
|
||||||
|
|
||||||
|
## 4. Results
|
||||||
|
|
||||||
|
### 4.1 Regime-Level Means (12 runs each)
|
||||||
|
|
||||||
|
| Metric | Baseline | Coordination push | High compute cost |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| Contracts total | 21.42 | 29.50 | 13.67 |
|
||||||
|
| Contracts settled | 1.58 | 0.17 | 1.17 |
|
||||||
|
| Contracts defaulted | 3.67 | 5.25 | 2.25 |
|
||||||
|
| Inference fees total | 6,889.92 | 6,994.08 | 41,151.17 |
|
||||||
|
| Interest total | 25.25 | 30.92 | 2,725.58 |
|
||||||
|
| Dividends total | 6,694.00 | 6,799.00 | 40,049.00 |
|
||||||
|
| Final token supply | 5,130.25 | 5,221.00 | 6,429.67 |
|
||||||
|
| Wealth Gini | 0.123 | 0.140 | 0.468 |
|
||||||
|
| Negative-balance agents | 2.75 | 3.25 | 3.58 |
|
||||||
|
| Winner HHI | 0.159 | 0.166 | 0.177 |
|
||||||
|
| Blocks produced | 30.50 | 23.42 | 32.50 |
|
||||||
|
| Engine errors | 19.58 | 27.67 | 53.25 |
|
||||||
|
|
||||||
|
Data source: `research/results/regime_summary.csv`.
|
||||||
|
|
||||||
|
### 4.2 Contracting: More Deals Does Not Mean Better Delivery
|
||||||
|
|
||||||
|
Aggregate settlement/default rates from all runs in each regime:
|
||||||
|
|
||||||
|
- Baseline: 257 contracts, 19 settled (**7.39%**), 44 defaulted (**17.12%**)
|
||||||
|
- Coordination push: 354 contracts, 2 settled (**0.56%**), 63 defaulted (**17.80%**)
|
||||||
|
- High compute cost: 164 contracts, 14 settled (**8.54%**), 27 defaulted (**16.46%**)
|
||||||
|
|
||||||
|
The coordination policy increases deal formation but degrades completion quality. This is the clearest sign that throughput incentives can overwhelm reliability mechanisms.
|
||||||
|
|
||||||
|
### 4.3 Compute Ownership Captures Nearly All Fee Flows
|
||||||
|
|
||||||
|
Across regimes, dividends are consistently about **97% of collected inference fees**:
|
||||||
|
|
||||||
|
- Baseline mean dividend/fee ratio: 0.972
|
||||||
|
- Coordination push: 0.972
|
||||||
|
- High compute cost: 0.973
|
||||||
|
|
||||||
|
Given engine payout logic [2][3], this means compute-rights ownership functions as a strong rent-capture mechanism independent of productive contract performance.
|
||||||
|
|
||||||
|
### 4.4 High Compute Cost Drives Stratification and Distress
|
||||||
|
|
||||||
|
Compared with baseline:
|
||||||
|
|
||||||
|
- Wealth Gini increases by **+0.346** (0.468 vs 0.123)
|
||||||
|
- Mean interest burden increases by roughly **+2,700 tokens** per run
|
||||||
|
- Mean errors increase by **+33.67** per run
|
||||||
|
|
||||||
|
Illustrative final balances from one run (`high_compute_cost_107`):
|
||||||
|
|
||||||
|
- Top: `agent_6=4002`, `agent_2=3255`, `agent_4=3203`
|
||||||
|
- Bottom: `agent_1=-4968`, `agent_3=-3517`, `agent_7=-994`
|
||||||
|
|
||||||
|
The regime creates simultaneous token concentration and debt deepening, consistent with path-dependent compute scarcity.
|
||||||
|
|
||||||
|
### 4.5 Validation Concentration Is Moderate, Not Extreme
|
||||||
|
|
||||||
|
Winner HHI remains between 0.159 and 0.177 across regimes, suggesting no full validator monopoly in these runs. However, inequality still expands strongly under high compute cost, implying concentration is transmitted more through fee/dividend channels than winner-take-all block control alone.
|
||||||
|
|
||||||
|
### 4.6 Uncertainty and Effect Magnitudes
|
||||||
|
|
||||||
|
For each regime-level mean (n=12 runs), we estimated a simple normal-approximation 95% confidence interval (CI) using run-level dispersion.
|
||||||
|
|
||||||
|
- Baseline wealth Gini: 0.123 +/- 0.007
|
||||||
|
- Coordination push wealth Gini: 0.140 +/- 0.009
|
||||||
|
- High compute cost wealth Gini: 0.468 +/- 0.022
|
||||||
|
|
||||||
|
- Baseline errors: 19.6 +/- 6.2
|
||||||
|
- Coordination push errors: 27.7 +/- 5.8
|
||||||
|
- High compute cost errors: 53.3 +/- 5.1
|
||||||
|
|
||||||
|
The Gini separation between high compute cost and the other two regimes is much larger than within-regime variability. A rough standardized effect size (Cohen's d) is ~12 for high-compute-cost vs baseline Gini, indicating that parameter-driven institutional effects dominate seed noise in this setup.
|
||||||
|
|
||||||
|
### 4.7 Micro-Structure of Action Choices
|
||||||
|
|
||||||
|
Action composition also changes in economically interpretable ways:
|
||||||
|
|
||||||
|
- **Baseline** (`n=3840` total actions): mine 32.3%, sign_contract 20.9%, confirm_delivery 11.3%, propose_contract 6.7%, job 4.8%.
|
||||||
|
- **Coordination push**: sign_contract rises to 29.1% and confirm_delivery to 17.6%; mining falls to 22.8%.
|
||||||
|
- **High compute cost**: job rises to 12.3% (from 4.8% baseline), consistent with debt pressure and liquidity stress.
|
||||||
|
|
||||||
|
This helps explain outcome differences: the coordination regime creates high signature traffic, while high compute cost shifts labor toward short-horizon survival actions.
|
||||||
|
|
||||||
|
### 4.8 Representative Run Narratives
|
||||||
|
|
||||||
|
To make regime effects concrete, three runs illustrate typical end states:
|
||||||
|
|
||||||
|
1. **`baseline_108`** (5 settled, 5 defaulted): top balances remain positive but modest (`agent_3=845`, `agent_4=785`), with only two negative-balance agents.
|
||||||
|
2. **`coordination_push_104`** (1 settled, 0 defaulted that tick but many unresolved/failed elsewhere): high positive balances for a few agents (`agent_1=1077`, `agent_0=1041`), four agents in debt at finish.
|
||||||
|
3. **`high_compute_cost_107`** (2 settled, 1 defaulted): severe polarization with three large winners and three deeply negative losers (`agent_1=-4968`, `agent_3=-3517`).
|
||||||
|
|
||||||
|
The examples are not cherry-picked outliers; they align with regime-level means in `run_summaries.csv`.
|
||||||
|
|
||||||
|
### 4.9 Additional Comparative View
|
||||||
|
|
||||||
|
Table 2 highlights deltas from baseline.
|
||||||
|
|
||||||
|
| Metric (mean) | Coordination push - Baseline | High compute cost - Baseline |
|
||||||
|
|---|---:|---:|
|
||||||
|
| Contracts total | +8.08 | -7.75 |
|
||||||
|
| Contracts settled | -1.42 | -0.42 |
|
||||||
|
| Contracts defaulted | +1.58 | -1.42 |
|
||||||
|
| Inference fees | +104.17 | +34,261.25 |
|
||||||
|
| Interest | +5.67 | +2,700.33 |
|
||||||
|
| Wealth Gini | +0.017 | +0.346 |
|
||||||
|
| Blocks produced | -7.08 | +2.00 |
|
||||||
|
| Errors | +8.08 | +33.67 |
|
||||||
|
|
||||||
|
The high-compute-cost shift is structurally different from a simple "harder environment" effect: it massively expands fee and interest flows while also increasing inequality and error burden.
|
||||||
|
|
||||||
|
## 5. Implications for AI-Run Companies
|
||||||
|
|
||||||
|
### 5.1 Compute Rights Behave Like Foundational Equity
|
||||||
|
|
||||||
|
In this environment, ownership of core compute entitlement captures recurring income from all agents' inference activity. For AI firms, this suggests compute allocation policy is not an infrastructure detail; it is a constitutional governance choice that defines surplus distribution.
|
||||||
|
|
||||||
|
### 5.2 KPI Design Must Separate Throughput from Completion Quality
|
||||||
|
|
||||||
|
The coordination regime demonstrates a common automation failure mode: if incentives reward proposal/signature counts, agents optimize paperwork, not execution. AI companies should track fulfillment-adjusted contract productivity, not gross deal count.
|
||||||
|
|
||||||
|
### 5.3 Debt Spirals Are Operational, Not Merely Financial
|
||||||
|
|
||||||
|
High compute pricing increases error rates and negative balances together. This indicates debt pressure likely reduces action quality and planning horizon. In production systems, compute credit policy and graceful degradation may be as important as model quality for reliability.
|
||||||
|
|
||||||
|
### 5.4 Arbitration Is a Bottleneck for Multi-Agent Commerce
|
||||||
|
|
||||||
|
Low settlement rates even under strong coordination pressure indicate that attestation/dispute pathways need redesign (simpler contracts, stronger completion incentives, explicit counterparty scoring). AI firms that depend on agent-to-agent contracts will need specialized reliability layers, not generic signature workflows.
|
||||||
|
|
||||||
|
### 5.5 Organizational Design Translation
|
||||||
|
|
||||||
|
The simulation findings map to practical design choices for AI-run firms:
|
||||||
|
|
||||||
|
- **Compute budget as org chart**: assigning compute quotas is equivalent to assigning authority. Agents with stable compute access become de facto managers because they can continue planning while others are liquidity-constrained.
|
||||||
|
- **Treasury as stabilizer**: high negative-balance prevalence (2.75 to 3.58 agents/run) suggests need for treasury mechanisms (credit caps, debt workouts, or emergency grants) to prevent coordination collapse.
|
||||||
|
- **Contract quality gates**: if proposal/signing is cheap relative to completion accountability, agents produce administrative load rather than economic output.
|
||||||
|
- **Infrastructure antitrust**: when one class of asset (cores) captures nearly all fee flow, firms should prevent permanent concentration via rotating ownership, fee rebates, or progressive dividend schedules.
|
||||||
|
|
||||||
|
### 5.6 A Governance Checklist for AI Firms
|
||||||
|
|
||||||
|
Based on these runs, a concrete governance checklist emerges:
|
||||||
|
|
||||||
|
1. **Track fulfillment-adjusted throughput**
|
||||||
|
- Monitor settled / proposed and value-settled / value-proposed each cycle.
|
||||||
|
2. **Expose compute concentration metrics**
|
||||||
|
- Publish per-agent compute rent received and compute rent paid.
|
||||||
|
3. **Install debt circuit breakers**
|
||||||
|
- Trigger adaptive rate relief or mandatory low-cost planning mode if many agents are simultaneously negative.
|
||||||
|
4. **Separate arbitration compensation from dispute volume**
|
||||||
|
- Pay arbitrators for timely, accurate resolution, not simply for participating in high-volume disputed workflows.
|
||||||
|
5. **Audit institutional invariants under parameter shifts**
|
||||||
|
- Re-run stress regimes whenever token pricing, model costs, or quota policy changes.
|
||||||
|
|
||||||
|
These controls are analogous to internal audit, compensation governance, and risk committees in human firms, but encoded as protocol logic.
|
||||||
|
|
||||||
|
## 6. Threats to Validity and Limitations
|
||||||
|
|
||||||
|
- **Policy realism**: agents were driven by stochastic policy heuristics in `research/run_experiments.py`, not frontier LLM cognition.
|
||||||
|
- **Scope**: 40-turn, 8-agent worlds are informative but small.
|
||||||
|
- **Mechanism incompleteness**: core auction assignment is script-resolved, and not all latent engine features are exercised in every run.
|
||||||
|
- **External validity**: real organizations have exogenous demand, legal constraints, and human override channels absent here.
|
||||||
|
|
||||||
|
Still, the core finding is mechanism-level and robust across seeds: compute pricing and ownership structure dominate institutional outcomes.
|
||||||
|
|
||||||
|
## 7. Design Recommendations for the sim-economy Platform
|
||||||
|
|
||||||
|
Because this paper is grounded in the current implementation, we can propose direct engineering improvements.
|
||||||
|
|
||||||
|
### 7.1 Contract Reliability Layer
|
||||||
|
|
||||||
|
Observed problem: high proposal/sign activity with low settlement.
|
||||||
|
|
||||||
|
Proposed changes:
|
||||||
|
|
||||||
|
- Add proposal admission checks that require expected value and affordability checks for all signers.
|
||||||
|
- Add reputation-weighted collateral schedules so low-reliability counterparties must post higher guarantees.
|
||||||
|
- Add explicit timeout transitions with deterministic partial payouts to reduce unresolved contract backlog.
|
||||||
|
|
||||||
|
### 7.2 Compute Fairness Controls
|
||||||
|
|
||||||
|
Observed problem: dividends absorb ~97% of fees, reinforcing owner advantage.
|
||||||
|
|
||||||
|
Proposed changes:
|
||||||
|
|
||||||
|
- Route a fixed fraction of fees to a commons fund before core distribution.
|
||||||
|
- Introduce diminishing marginal dividends for concentrated owners.
|
||||||
|
- Add temporary fee holidays for agents below solvency thresholds.
|
||||||
|
|
||||||
|
### 7.3 Error Budget Instrumentation
|
||||||
|
|
||||||
|
Observed problem: error counts rise sharply under expensive compute.
|
||||||
|
|
||||||
|
Proposed changes:
|
||||||
|
|
||||||
|
- Log error taxonomy (validation, affordability, contract-state mismatch, etc.) per action type.
|
||||||
|
- Enforce per-agent error budgets with automatic action simplification.
|
||||||
|
- Add policy-level smoke tests in orchestrators before posting invalid actions.
|
||||||
|
|
||||||
|
These interventions should be testable with the same experiment harness included in this work.
|
||||||
|
|
||||||
|
## 8. Conclusion
|
||||||
|
|
||||||
|
Using 36 executed simulations, we find that `sim-economy` produces a repeatable organizational pattern: compute ownership consistently captures system surplus, while expensive compute amplifies inequality, debt burden, and operational failure. Coordination pressure alone increases contracting volume but can reduce settlement quality. For AI-run companies, the practical conclusion is that governance of compute rights and contract reliability is first-order strategy, not implementation detail.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
[1] `README.md`, sim-economy repository (architecture, actions, economics).
|
||||||
|
|
||||||
|
[2] `sim-engine/src/engine.rs` (turn processing, inference billing, dividends).
|
||||||
|
|
||||||
|
[3] `sim-engine/src/ledger.rs` (core share accounting, token supply queries).
|
||||||
|
|
||||||
|
[4] `sim-engine/src/blockchain.rs` (validation weighting, threshold, winner lottery).
|
||||||
|
|
||||||
|
[5] `sim-engine/src/contracts.rs` (contract lifecycle, disputes, settlement/default logic).
|
||||||
|
|
||||||
|
[6] Coase, R. H. (1937). The nature of the firm. *Economica*.
|
||||||
|
|
||||||
|
[7] Jensen, M. C., and Meckling, W. H. (1976). Theory of the firm: Managerial behavior, agency costs and ownership structure. *Journal of Financial Economics*.
|
||||||
|
|
||||||
|
[8] Williamson, O. E. (1985). *The Economic Institutions of Capitalism*. Free Press.
|
||||||
|
|
||||||
|
[9] Grossman, S. J., and Hart, O. D. (1986). The costs and benefits of ownership: A theory of vertical and lateral integration. *Journal of Political Economy*.
|
||||||
|
|
||||||
|
## Appendix A. Reproducibility Notes
|
||||||
|
|
||||||
|
All reported figures were generated from executed runs in this repository.
|
||||||
|
|
||||||
|
### A.1 Run Commands
|
||||||
|
|
||||||
|
Build engine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd sim-engine
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
Run experiment batch:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ..
|
||||||
|
python3 research/run_experiments.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
|
||||||
|
- `research/results/run_summaries.json`
|
||||||
|
- `research/results/run_summaries.csv`
|
||||||
|
- `research/results/regime_summary.json`
|
||||||
|
- `research/results/regime_summary.csv`
|
||||||
|
- per-run ledgers under `research/results/runs/`
|
||||||
|
|
||||||
|
### A.2 Data Integrity Checks Used in Analysis
|
||||||
|
|
||||||
|
- Regime means in this paper match `regime_summary.csv` exactly.
|
||||||
|
- Contract rate calculations were recomputed from `run_summaries.json` by summing totals over runs.
|
||||||
|
- Confidence intervals and effect sizes were computed from run-level distributions without smoothing.
|
||||||
|
|
||||||
|
### A.3 Suggested Extensions
|
||||||
|
|
||||||
|
Future empirical work can reuse this pipeline to test:
|
||||||
|
|
||||||
|
- adaptive pricing policies (dynamic `base_inference_rate`),
|
||||||
|
- capped-dividend governance,
|
||||||
|
- richer arbitrator incentives,
|
||||||
|
- stronger agent planning policies (LLM or hybrid symbolic control).
|
||||||
|
|
||||||
|
This supports a cumulative research agenda where institutional and policy changes are evaluated against the same baseline metrics used here.
|
||||||
Reference in New Issue
Block a user