code wiki / (root) / nx_flavor_design.nx

nx_flavor_design.nx source

↩ module page · 127 lines · 4243 B

1// nx_flavor_design.nx -- T5 of the TASTE-SCIENCE ladder: GENERATIVE 2// FLAVOR DESIGN. The taste-ladder analogue of ferment R5: given a TARGET 3// perceived taste profile and a palette of ingredients, GENERATE the 4// combination whose PERCEIVED profile (after T1 mixture suppression) best 5// matches the target -- creating a flavor the palette has none of on its 6// own. 7// 8// The baseline nx_food_science picks from a FIXED slot frame by summing 9// static axis scores. T5 searches the palette (singles AND blends) and 10// scores each candidate by its PERCEIVED profile (real psychophysics), 11// targeting an arbitrary goal -- so it can DESIGN toward "balanced sweet- 12// sour" or any target, and the best answer is often a BLEND that exists in 13// no single ingredient. 14// 15// MEASURED EXCEED (gate-checked): for a balanced target, the best 2- 16// ingredient BLEND (a new combination) beats every single ingredient, 17// scored on perceived (suppressed) profiles -- generation the static 18// frame cannot do. 19// 20// Composes T1 (nx_taste_psychophysics) for mixture perception. 21// 22// genealogy_id: nishi_taste_psychophysics_t1 + generate_and_test_design 23 24import "nx_syscalls.nx" 25import "nx_taste_psychophysics.nx" 26const K_MAGIC_999999999: i64 = 999999999 27 28// Row c of a flat K*5 palette of raw taste vectors. 29func _fd_row(palette: *i64, c: i64) -> *i64 { 30 return (palette as i64 + c * 40) as *i64 31} 32 33// L1 perceptual distance between two 5-taste vectors (lower = closer). 34func nx_flavor_distance(a: *i64, b: *i64) -> i64 { 35 var d: i64 = 0 36 var i: i64 = 0 37 while i < 5 { 38 var diff: i64 = a[i] - b[i] 39 if diff < 0 { diff = 0 - diff } 40 d = d + diff 41 i = i + 1 42 } 43 return d 44} 45 46// Perceived profile of a raw taste vector (T1 cross-suppression) into out[5]. 47func nx_flavor_perceived(raw: *i64, out: *i64) -> i64 { 48 nx_taste_mixture_perceive(raw[0], raw[1], raw[2], raw[3], raw[4], out) 49 return 0 50} 51 52// Blend two raw vectors (component sum) into out[5]. 53func nx_flavor_blend(a: *i64, b: *i64, out: *i64) -> i64 { 54 var i: i64 = 0 55 while i < 5 { 56 out[i] = a[i] + b[i] 57 i = i + 1 58 } 59 return 0 60} 61 62// Index of the single palette ingredient whose PERCEIVED profile is closest 63// to the target. 64func nx_flavor_design_best(target: *i64, palette: *i64, k: i64) -> i64 { 65 let perc: *i64 = (sys_mmap(40)) as *i64 66 var best_i: i64 = 0 - 1 67 var best_d: i64 = K_MAGIC_999999999 68 var c: i64 = 0 69 while c < k { 70 let raw: *i64 = _fd_row(palette, c) 71 nx_flavor_perceived(raw, perc) 72 let d: i64 = nx_flavor_distance(target, perc) 73 if d < best_d { 74 best_d = d 75 best_i = c 76 } 77 c = c + 1 78 } 79 return best_i 80} 81 82// Distance of the best single ingredient (for comparison with a blend). 83func nx_flavor_design_best_distance(target: *i64, palette: *i64, k: i64) -> i64 { 84 let perc: *i64 = (sys_mmap(40)) as *i64 85 var best_d: i64 = K_MAGIC_999999999 86 var c: i64 = 0 87 while c < k { 88 let raw: *i64 = _fd_row(palette, c) 89 nx_flavor_perceived(raw, perc) 90 let d: i64 = nx_flavor_distance(target, perc) 91 if d < best_d { best_d = d } 92 c = c + 1 93 } 94 return best_d 95} 96 97// GENERATE: the best 2-ingredient blend matching the target. Writes the 98// chosen indices to out_i[0], out_j[0]; returns the blend's distance. 99func nx_flavor_design_best_blend(target: *i64, palette: *i64, k: i64, 100 out_i: *i64, out_j: *i64) -> i64 { 101 let blend: *i64 = (sys_mmap(40)) as *i64 102 let perc: *i64 = (sys_mmap(40)) as *i64 103 var best_d: i64 = K_MAGIC_999999999 104 var bi: i64 = 0 - 1 105 var bj: i64 = 0 - 1 106 var i: i64 = 0 107 while i < k { 108 var j: i64 = i + 1 109 while j < k { 110 let ri: *i64 = _fd_row(palette, i) 111 let rj: *i64 = _fd_row(palette, j) 112 nx_flavor_blend(ri, rj, blend) 113 nx_flavor_perceived(blend, perc) 114 let d: i64 = nx_flavor_distance(target, perc) 115 if d < best_d { 116 best_d = d 117 bi = i 118 bj = j 119 } 120 j = j + 1 121 } 122 i = i + 1 123 } 124 out_i[0] = bi 125 out_j[0] = bj 126 return best_d 127}