nx_caplab_quality.nx source
↩ module page · 84 lines · 3200 B
1// nx_caplab_quality.nx -- Capitalism Lab R4: demand driven by PRICE + QUALITY +
2// BRAND (the heart of Capitalism Lab -- customers don't just buy the cheapest;
3// a higher-quality, better-branded product wins share even at a higher price).
4// Generalizes R1's price-only competition: each firm's "appeal" is a weighted
5// sum of price-value, quality, and brand; the market splits by appeal
6// (largest-remainder, conserved).
7//
8// MODEL:
9// appeal = max(0, w_price*max(0,choke-price) + w_qual*quality + w_brand*brand)
10// share = market_m * appeal / sum(appeal) (largest-remainder)
11//
12// nx_safety_envelope:
13// intended_use: capitalism-lab demand model (pure functions, no I/O)
14// sil_target: SIL1
15// verdict: NOT_YET_EVALUATED
16//
17// genealogy_id: capitalism_lab_quality_brand_canon
18// lineage_id: nx_caplab_quality_v1
19
20import "nx_syscalls.nx"
21import "nx_tier.nx"
22
23// Generic largest-remainder apportionment of `total` among n shares by weight.
24// (Shared engine for any appeal model; conserves the total exactly.)
25func nx_clab_apportion(n: nx_int, weights: *i64, total: nx_int, out_q: *i64) {
26 var sumw: nx_int = 0
27 var i: nx_int = 0
28 while i < n { sumw = sumw + weights[i]; i = i + 1 }
29 if sumw <= 0 {
30 i = 0
31 while i < n { out_q[i] = 0; i = i + 1 }
32 return
33 }
34 let rem: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
35 let got: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
36 var alloc: nx_int = 0
37 i = 0
38 while i < n {
39 let num: nx_int = total * weights[i]
40 out_q[i] = num / sumw
41 rem[i] = num % sumw
42 got[i] = 0
43 alloc = alloc + out_q[i]
44 i = i + 1
45 }
46 var leftover: nx_int = total - alloc
47 while leftover > 0 {
48 var best: nx_int = 0 - 1
49 var best_rem: nx_int = 0 - 1
50 var j: nx_int = 0
51 while j < n {
52 if got[j] == 0 { if rem[j] > best_rem { best_rem = rem[j]; best = j } }
53 j = j + 1
54 }
55 out_q[best] = out_q[best] + 1
56 got[best] = 1
57 leftover = leftover - 1
58 }
59}
60
61// A product's appeal to customers: undercutting the choke price helps, and so
62// do quality and brand (each weighted). Priced at/above choke contributes 0
63// price-value, but quality/brand still pull brand-loyal buyers.
64func nx_clab_appeal_qb(choke: nx_int, price: nx_int, quality: nx_int, brand: nx_int,
65 w_price: nx_int, w_qual: nx_int, w_brand: nx_int) -> nx_int {
66 var pv: nx_int = choke - price
67 if pv < 0 { pv = 0 }
68 let a: nx_int = w_price * pv + w_qual * quality + w_brand * brand
69 if a < 0 { return 0 }
70 return a
71}
72
73// Split the market among n firms by price/quality/brand appeal.
74func nx_clab_split_qb(n: nx_int, prices: *i64, qualities: *i64, brands: *i64,
75 choke: nx_int, w_price: nx_int, w_qual: nx_int, w_brand: nx_int,
76 market_m: nx_int, out_q: *i64) {
77 let w: *i64 = (sys_mmap(n * NX_SIZEOF_NX_INT)) as *i64
78 var i: nx_int = 0
79 while i < n {
80 w[i] = nx_clab_appeal_qb(choke, prices[i], qualities[i], brands[i], w_price, w_qual, w_brand)
81 i = i + 1
82 }
83 nx_clab_apportion(n, w, market_m, out_q)
84}