code wiki / (root) / nx_caplab_compete.nx

nx_caplab_compete.nx source

↩ module page · 98 lines · 3417 B

1// nx_caplab_compete.nx -- Capitalism Lab R1: multi-firm price competition. 2// 3// Builds on the R0 atom (nx_caplab_market): instead of one firm, N firms 4// set prices into ONE market. A single market willingness-to-pay (choke 5// price A) bounds demand; each firm's "appeal" is how far it undercuts the 6// choke; the market's customers split among firms in proportion to appeal 7// (cheaper -> bigger share). Allocation uses largest-remainder so the 8// split is CONSERVED: sum of firm quantities == total market customers 9// (no customers vanish or get invented), unless every firm is priced out. 10// 11// MODEL: 12// appeal_i = max(0, A - price_i) (0 if priced >= choke) 13// share_i = market_M * appeal_i / sum(appeal) (largest-remainder) 14// profit_i = (price_i - unit_cost_i) * share_i 15// 16// This is the heart of "capitalism": a lower price wins more of the market, 17// but margin x volume decides who actually earns the most. 18// 19// nx_safety_envelope: 20// intended_use: capitalism-lab competition core (pure functions, no I/O) 21// sil_target: SIL1 22// verdict: NOT_YET_EVALUATED 23// 24// genealogy_id: capitalism_lab_competition_canon 25// lineage_id: nx_caplab_compete_v1 26 27import "nx_syscalls.nx" 28import "nx_tier.nx" 29 30// A firm's appeal: how far it undercuts the market's choke price. 31func nx_clab_appeal(choke_a: nx_int, price: nx_int) -> nx_int { 32 let w: nx_int = choke_a - price 33 if w < 0 { return 0 } 34 return w 35} 36 37func nx_clab_appeal_sum(n: nx_int, prices: *i64, choke_a: nx_int) -> nx_int { 38 var s: nx_int = 0 39 var i: nx_int = 0 40 while i < n { 41 s = s + nx_clab_appeal(choke_a, prices[i]) 42 i = i + 1 43 } 44 return s 45} 46 47// Split market_m customers among n firms by appeal, conserving the total 48// via largest-remainder (Hamilton) apportionment: ties break to the lowest 49// index for determinism. If every firm is priced out (sum appeal == 0), 50// nobody buys and all quantities are 0. 51func nx_clab_split(n: nx_int, prices: *i64, choke_a: nx_int, 52 market_m: nx_int, out_q: *i64) { 53 let total_w: nx_int = nx_clab_appeal_sum(n, prices, choke_a) 54 var i: nx_int = 0 55 if total_w <= 0 { 56 while i < n { out_q[i] = 0; i = i + 1 } 57 return 58 } 59 60 let rem: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64 61 let got: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64 62 var allocated: nx_int = 0 63 i = 0 64 while i < n { 65 let w: nx_int = nx_clab_appeal(choke_a, prices[i]) 66 let num: nx_int = market_m * w 67 out_q[i] = num / total_w 68 rem[i] = num % total_w 69 got[i] = 0 70 allocated = allocated + out_q[i] 71 i = i + 1 72 } 73 74 // Distribute the leftover (== sum of dropped fractions, always < n) one 75 // unit each to the firms with the largest remainder. 76 var leftover: nx_int = market_m - allocated 77 while leftover > 0 { 78 var best: nx_int = -1 79 var best_rem: nx_int = -1 80 var j: nx_int = 0 81 while j < n { 82 if got[j] == 0 { 83 if rem[j] > best_rem { 84 best_rem = rem[j] 85 best = j 86 } 87 } 88 j = j + 1 89 } 90 out_q[best] = out_q[best] + 1 91 got[best] = 1 92 leftover = leftover - 1 93 } 94} 95 96func nx_clab_firm_profit(price: nx_int, unit_cost: nx_int, qty: nx_int) -> nx_int { 97 return (price - unit_cost) * qty 98}