diff options
| author | tslil <tslil@posteo.de> | 2026-09-11 12:56:12 +0100 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2026-09-11 17:00:18 +0100 |
| commit | 6e90f1145b2c5c0f2dcc82d21ec45432274b8cad (patch) | |
| tree | 18db1c03ea7c3c4724028fc5154d4bca3d7200a5 | |
| parent | 220a4b79e4b6d742a9ca7c278a1962b870500fbc (diff) | |
move from single candidate td-leaf with gating to tournament of a population
The goal in this change was to overcome the rock-paper-scissors phenomenon that was happening in capability space by having on a single candidate learn to beat the most recent version of itself. In some sense this lead to rotating around in capability space instead of chasing monotonic improvements.
I hope that flipping to a system in which many (N=5) candidates play each other and learn from their own set of diverse games in this pool, combined with --replay-iters, will lead to a given network having to have a much more comprehensive understanding of the space of tactics. I haven't yet had time to train this thorougly, will run those experiments on my desktop computer.
| -rw-r--r-- | .clangd | 6 | ||||
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | Makefile | 27 | ||||
| -rw-r--r-- | include/nn.c | 12 | ||||
| -rw-r--r-- | include/weights_5.c | 558 | ||||
| -rw-r--r-- | include/weights_5.h | 10 | ||||
| -rw-r--r-- | include/weights_6.c | 10 | ||||
| -rw-r--r-- | include/weights_6.h | 10 | ||||
| -rw-r--r-- | src/match.c | 173 | ||||
| -rwxr-xr-x | src/nn_train.py | 429 | ||||
| -rw-r--r-- | src/selfplay.c | 125 |
11 files changed, 632 insertions, 733 deletions
@@ -9,6 +9,12 @@ CompileFlags: - -I../include - -D_DEFAULT_SOURCE - -DRECORD_PV + - -DCAND_A=1 + - -DCAND_B=2 + - -DCAND_A_WEIGHTS_5="cand_1_weights_5.c" + - -DCAND_A_WEIGHTS_6="cand_1_weights_6.c" + - -DCAND_B_WEIGHTS_5="cand_2_weights_5.c" + - -DCAND_B_WEIGHTS_6="cand_2_weights_6.c" - -Wall - -Wextra - -Wpedantic @@ -1,15 +1,12 @@ *.o data/ -include/cand_weights_*.c +include/cand_* ct1986* ctlm* pptdb* cttei* geminict* selfplay* -match* __pycache__/ -production-*.log buildroot* -test/ .cache @@ -4,7 +4,7 @@ NATIVE_FLAGS=-march=native CTAK=include/tak.c CTAK_OBJS=$(CTAK:.c=.o) -CAND_SRCS=include/cand_weights_5.c include/cand_weights_6.c +CAND_SRCS=$(wildcard include/cand_*.c) SRCS=$(filter-out include/lcdlib.c $(CAND_SRCS),$(wildcard include/*.c)) OBJS=$(SRCS:.c=.o) @@ -27,24 +27,31 @@ cttei: src/cttei.o $(OBJS) $(CC) $(CFLAGS) src/cttei.o $(OBJS) -o cttei clean: - rm -f ctlm ct1986 cttei pptdb geminict selfplay match + rm -f ctlm ct1986 cttei pptdb geminict rm -f src/*.o include/*.o native: CFLAGS += $(NATIVE_FLAGS) native: ctlm cttei geminict -.PHONY: selfplay -selfplay: +cand_a = $(word 1,$(subst -, ,$1)) +cand_b = $(word 2,$(subst -, ,$1)) + +.PHONY: selfplay-% +selfplay-%: + rm -f selfplay-% $(MAKE) clean - $(MAKE) DEFINES=-DRECORD_PV selfplay-bin + $(MAKE) SELFPLAY_OUT=$@ \ + DEFINES="-DRECORD_PV -DCAND_A=$(call cand_a,$*) -DCAND_B=$(call cand_b,$*) \ + -DCAND_A_WEIGHTS_5='\"cand_$(call cand_a,$*)_weights_5.c\"' \ + -DCAND_B_WEIGHTS_5='\"cand_$(call cand_b,$*)_weights_5.c\"' \ + -DCAND_A_WEIGHTS_6='\"cand_$(call cand_a,$*)_weights_6.c\"' \ + -DCAND_B_WEIGHTS_6='\"cand_$(call cand_b,$*)_weights_6.c\"'" \ + selfplay-bin +SELFPLAY_OUT ?= selfplay selfplay-bin: CFLAGS += $(NATIVE_FLAGS) selfplay-bin: src/selfplay.o $(OBJS) - $(CC) $(CFLAGS) src/selfplay.o $(OBJS) -o selfplay - -match: CFLAGS += $(NATIVE_FLAGS) -match: src/match.o $(OBJS) - $(CC) $(CFLAGS) src/match.o $(OBJS) -o match + $(CC) $(CFLAGS) src/selfplay.o $(OBJS) -o $(SELFPLAY_OUT) $(CROSS_CC): ./resources/do_buildroot.sh $(BUILDROOT_DIR) diff --git a/include/nn.c b/include/nn.c index 909b870..9b241a1 100644 --- a/include/nn.c +++ b/include/nn.c @@ -139,17 +139,17 @@ float eval_net(const float *board, const unsigned int n_inp, const float *w, float five_nn_fn(tak_state_p state) { static float cur_board[FIVE_INP_NUM] NN_ALIGNED; - nn_prepare_input(cur_board, state, five_embedding); - return eval_net(cur_board, FIVE_INP_NUM, &five_dense_weights[0][0], - five_dense_biases, five_logit_weights, five_logit_bias, + nn_prepare_input(cur_board, state, FIVE_embedding); + return eval_net(cur_board, FIVE_INP_NUM, &FIVE_dense_weights[0][0], + FIVE_dense_biases, FIVE_logit_weights, FIVE_logit_bias, FIVE_DENSE_NUM, state->ply & 1 ? 1.0f : -1.0f); } float six_nn_fn(tak_state_p state) { static float cur_board[SIX_INP_NUM] NN_ALIGNED; - nn_prepare_input(cur_board, state, six_embedding); - return eval_net(cur_board, SIX_INP_NUM, &six_dense_weights[0][0], - six_dense_biases, six_logit_weights, six_logit_bias, + nn_prepare_input(cur_board, state, SIX_embedding); + return eval_net(cur_board, SIX_INP_NUM, &SIX_dense_weights[0][0], + SIX_dense_biases, SIX_logit_weights, SIX_logit_bias, SIX_DENSE_NUM, state->ply & 1 ? 1.0f : -1.0f); } diff --git a/include/weights_5.c b/include/weights_5.c index 528b4b2..05f5c83 100644 --- a/include/weights_5.c +++ b/include/weights_5.c @@ -1,294 +1,294 @@ /* generated by nn_train.py, do not edit by hand */ -/* v021, val_corr=0.9431, rate=0.8128 */ +/* iter=2, perf=Performance(win=994, loss=350, draw=256) */ #include "weights_5.h" -const float five_embedding[7] = +const float FIVE_embedding[7] = { - -0.111816011, -0.66451335, -0.323273391, -0.98435086, 0.463595748, 0.122227475, 1.10759342 + -0.0316700898, 1.14476383, -0.856112063, 0.338954836, 0.381001413, -0.092553176, -1.3670609 }; -const float five_dense_weights[FIVE_DENSE_NUM][FIVE_INP_NUM] NN_ALIGNED = +const float FIVE_dense_weights[FIVE_DENSE_NUM][FIVE_INP_NUM] NN_ALIGNED = { - {-0.336461723, 0.154304922, -0.10887333, 0.0346023738, 0.0663131773, -0.263053775, -0.152429491, -0.156706274, - -0.0261838995, 0.0615116283, -0.00867442507, -0.0330895744, -0.200019136, -0.152155533, -0.228213087, -0.0947766751, - -0.168420106, -0.105302423, -0.0634559542, -0.10144452, -0.00757334288, -0.098755151, -0.0393106975, -0.130494073, - -0.137479991, -0.147044897, 0.0444718711}, - {-0.476948798, 0.283080339, -0.112627052, -0.0566330925, -0.117319182, 0.067356348, -0.214415103, -0.0908493698, - -0.130251959, -0.0832009315, -0.132550076, -0.0409394987, -0.14343515, -0.165731624, -0.0995086357, -0.0931895301, - 0.0399273336, -0.109562084, -0.0865440071, -0.187932745, -0.116726696, -0.0622647591, -0.161190167, -0.0746859461, - -0.0869885162, -0.0633410662, -0.183728024}, - {0.501687288, -0.246853873, -0.111631788, -0.0950183868, 0.0433660597, 0.0353987776, -0.0815068632, 0.0190158598, - 0.0472823232, 0.141847193, 0.150354445, 0.109667607, 0.173449546, 0.0974388719, 0.117253646, 0.0443467014, - 0.155469015, 0.0015354075, -0.0226863306, 0.107729092, 0.0867730677, 0.0539038517, 0.0109655559, -0.0001881551, - 0.0539281517, 0.0739952698, 0.024234768}, - {-0.241468534, 0.245634317, -0.177097514, -0.0966913477, -0.0908557996, -0.222765237, 0.0428062752, 0.0662450641, - -0.14830184, -0.27613914, -0.00439124089, 0.0616023652, -0.0352403969, -0.0714174062, -0.0927751288, -0.198465347, - -0.10787531, -0.129295409, -0.0771139264, 0.0929553285, -0.0864783376, -0.101502113, -0.0561841838, -0.0308110006, - -0.0971863419, 0.0321811512, -0.136937499}, - {-0.293241292, 0.176214963, -0.0997679755, -0.137113556, -0.102217041, -0.0628509074, -0.0408717208, -0.145298526, - -0.157438934, -0.141293526, -0.051789429, -0.138779029, 0.0460731909, -0.0666170716, -0.068696849, -0.0526388474, - -0.0870416909, -0.164847091, -0.0075546396, -0.179455563, -0.0679638982, -0.148295894, 0.0217483994, 0.00110340223, - -0.109468557, -0.0612522177, -0.144700974}, - {0.555234432, -0.29328832, -0.0530367084, -0.0197362695, 0.135281458, 0.0643368214, -0.0479854904, -0.0320929959, - 0.00952057075, 0.0762432516, 0.0431200638, 0.00373447174, 0.00648360141, 0.0249679051, 0.0982084647, 0.0742597654, - 0.176258922, -0.0588847473, 0.067157805, 0.0840090215, 0.096922338, 0.107480116, -0.13343218, 0.0502937026, - 0.00758570526, 0.143558204, -0.0295699202}, - {-0.0196725614, 0.521027982, 0.117322937, -0.136202931, -0.0885757059, -0.157541454, 0.027417697, -0.196738541, - -0.185150325, -0.0608076118, -0.242262214, 0.129811585, 0.00927441008, 0.0253326576, -0.173773453, -0.0929993242, - -0.112551235, 0.0229004882, -0.0823968425, -0.144142121, -0.134864509, -0.0435563624, -0.0138254175, -0.017871825, - -0.118300691, -0.222301945, 0.0654260442}, - {0.515057206, -0.501810074, 0.0906459242, 0.0663279667, 0.0672804043, 0.136731073, 0.197158888, 0.0887991562, - 0.103316456, 0.0668849945, 0.0824639574, 0.105142467, 0.111418657, 0.168580294, 0.217910707, 0.12751174, - 0.163602412, 0.0649882257, -0.0231945887, 0.157283291, 0.0133193424, 0.0967117697, 0.0735855326, 0.0733335912, - -0.0301157199, 0.105765827, 0.118556902}, - {0.437964976, -0.0891112685, -0.0817612186, 0.0337016955, -0.0144375162, -0.0190179851, -0.0760151967, 0.0206933953, - 0.0126884431, 0.152803347, 0.217285782, -0.0638305172, 0.154621854, 0.184730306, 0.0730771124, 0.142845079, - 0.118791498, 0.0935750753, -0.00985962339, 0.14858295, 0.0264425948, 0.0211795457, -0.0477743596, 0.0518504567, - 0.044468943, -0.0322440341, -0.113994136}, - {0.275304943, -0.440430224, 0.205142319, 0.296866268, 0.206504375, 0.213049769, 0.236116648, 0.165672138, - 0.156796411, 0.121099472, 0.136662409, 0.0533005744, 0.124345988, 0.178031459, 0.0942888856, 0.0820470378, - -0.0188032296, 0.158560991, 0.114671834, 0.206088871, 0.104401477, -0.0764776617, 0.336370409, 0.193061247, - 0.0689836368, -0.0371297821, -0.0176717378}, - {-0.503815114, 0.117647812, -0.0947853103, -0.0888879895, -0.150847107, -0.173219636, -0.171667159, -0.0869263411, - -0.182824627, -0.103248619, -0.103223078, -0.182025731, -0.0597172603, -0.130951121, 0.0579778478, -0.187960774, - -0.0464051925, -0.0732548311, -0.170095325, -0.0454986207, -0.131479591, -0.121194012, -0.128192231, -0.139532492, - -0.170335412, -0.0389355049, -0.0885092244}, - {0.545259476, -0.743000686, 0.123060927, 0.0750294402, 0.0920063928, 0.0688846558, 0.0780040771, 0.147260338, - 0.160915926, 0.082233265, 0.0307610985, 0.14154236, 0.137007028, 0.0628393888, 0.0126191974, -0.0901432484, - 0.0655800924, 0.12276125, 0.0915826783, -0.0397638828, -0.0567843281, 0.13035585, 0.0849244669, 0.125134706, - 0.0200874638, 0.0811543018, 0.119952776}, - {-0.863882303, -0.286586463, -0.0436602645, -0.206180006, -0.0361143351, -0.063956216, -0.19108972, -0.066635862, - -0.115632087, -0.116745904, -0.00574644096, -0.24195531, -0.172636062, -0.0113078328, -0.00190027303, -0.00475866022, - -0.103091143, -0.236703053, -0.0936092809, 0.0481541157, -0.157557085, 0.0174609497, -0.300570279, -0.142101526, - -0.0440290384, -0.146465167, -0.146330267}, - {-0.614430249, -0.00133095577, -0.15687111, -0.074202925, -0.0625234395, -0.219945475, -0.0697372034, -0.0709214211, - -0.183709145, -0.0647780672, -0.0191991851, -0.152953938, -0.0573028922, -0.0626742244, -0.0275068618, 5.11718099e-06, - -0.1329671, -0.13576977, -0.012498335, -0.160364896, -0.156126291, -0.0500632636, -0.244752139, -0.123227298, - -0.0709499642, -0.0277239047, -0.131129205}, - {-1.05760479, -0.475387812, -0.356799334, -0.0877590925, 0.00557458494, -0.21499151, -0.318871707, -0.0426627472, - 0.0690349564, 0.0718996152, -0.128308564, -0.246176571, 0.000836514868, 0.0878805667, 0.125116646, -0.0364632495, - 0.0307956766, -0.128316909, -0.0271618664, -0.0471602865, -0.0675882772, -0.176609352, -0.0962155461, -0.0914392024, - -0.152685434, -0.141950727, -0.13847293}, - {-0.33753708, 0.123861521, -0.00318000116, -0.0203293599, 0.0125157302, -0.0303300638, -0.112960629, -0.12710841, - 0.0188797917, -0.217398718, 0.0356179141, -0.153275773, -0.116520122, -0.0602441058, -0.180811509, -0.112214409, - 0.0408374779, -0.109781645, -0.194045067, -0.0450648777, -0.120420091, -0.0403718576, -0.170846909, -0.203327894, - 0.00645394111, -0.0464387722, -0.0821784958}, - {-0.404387981, 0.146623626, -0.0111723561, -0.0987150297, -0.0885990188, -0.331271529, -0.215831667, -0.196489066, - -0.176219434, -0.0052387123, -0.06742993, 0.0303974841, -0.0736306384, -0.111799695, -0.0621598549, -0.107533887, - -0.0286721326, -0.0296850968, -0.0365842767, -0.162165895, -0.129865497, -0.0257233065, -0.111031547, -0.0841779485, - -0.0103744781, -0.0235559568, -0.12829037}, - {-0.389871418, 0.325205147, -0.202666372, -0.0631261542, -0.0449823327, 0.000680716534, -0.113931477, 0.0472895913, - -0.133598924, -0.178089157, -0.140900657, -0.157841027, -0.0704756677, -0.13923645, -0.198325247, -0.0897430107, - -0.076825358, -0.14972426, -0.115272976, -0.0940996855, -0.0544049405, -0.190078169, -0.0608553402, -0.116017424, - -0.0132451365, -0.19820337, -0.101439781}, - {-0.549823403, 0.0365903452, -0.234441727, -0.0218347758, -0.0285061579, -0.138356805, -0.180055663, -0.164054498, - -0.220073089, 0.0438569076, 0.00251096766, -0.112317808, -0.0555928908, -0.0422757193, -0.154647186, -0.0748772621, - 0.0356666371, -0.0671267658, -0.0803513601, -0.0868180394, -0.114429407, -0.107504837, -0.08839304, -0.0374800451, - -0.237587512, -0.0794109255, -0.159469888}, - {0.454538584, -0.143599376, 0.0919798836, 0.0573271923, 0.0245270487, 0.0275781266, -0.0860885754, 0.075321041, - 0.0687650144, -0.00777275767, 0.0629966557, -0.048610311, 0.0414154902, 0.0734824389, 0.11830087, 0.020603558, - -0.019885242, 0.140498042, 0.107861951, 0.071308732, 0.163864553, -0.0433851779, -0.120720699, 0.0494855195, - 0.0714977607, -0.0448294804, -0.0750102326}, - {0.413284004, 0.755857527, 0.0574384183, -0.0467611961, -0.111452386, 0.0402155779, 0.09134157, -0.00712207844, - -0.104574747, -0.102326035, -0.175752327, 0.103249893, -0.0728359744, -0.041756954, -0.169721693, -0.103443913, - -0.0145068029, 0.0181282964, 0.00295278965, -0.116780683, -0.128228545, -0.123205528, 0.17964761, -0.00627433835, - -0.163882926, 0.065338932, 0.0409481078}, - {0.0162304696, -0.170559391, 0.182137489, 0.103262864, 0.129591316, 0.156651959, 0.149003908, 0.0987137407, - 0.246585235, 0.244195923, 0.161659524, 0.205141798, 0.142251134, 0.250169814, 0.149455249, 0.342220753, - -0.00048297763, 0.107712485, 0.176751122, 0.0944397971, 0.146613136, 0.0139483726, 0.119831756, 0.102763854, - 0.0162141211, -0.0125095658, 0.06998723}, - {-0.0814091489, 0.361089975, -0.0212528147, -0.0370061733, -0.151159585, -0.0056566298, 0.0128130922, 0.0590757839, - 0.0577854291, 0.010439585, -0.129232436, -0.230118752, -0.0717097148, 0.00882031489, -0.184435904, -0.240539581, - -0.114007063, 0.0461738892, -0.162503824, -0.137727529, 0.0520763434, -0.0868957341, -0.093090415, -0.203062072, - 0.0368140079, 0.110035688, -0.0946049988}, - {0.601561844, -0.234425396, -0.0874742791, -0.109474912, 0.107772671, -0.0156976264, 0.020523807, -0.00522266142, - -0.0417326316, 0.0158955064, 0.123555519, 0.00557566108, 0.0309953969, 0.0327091739, 0.148837447, 0.0482964963, - -0.0111426702, -0.125640169, 0.14572002, 0.0218056999, 0.125552535, -0.0169510283, -0.105879158, -0.00411166437, - 0.0315352641, 0.0745560452, -0.101139069}, - {-0.219457254, 0.337195486, -0.114419617, -0.218652502, -0.0148616051, -0.108561747, 0.0710270181, -0.119952336, - -0.141045973, -0.153070375, -0.179692447, -0.113438055, -0.0389011167, -0.125133142, -0.0542742312, -0.144636005, - -0.0917542279, 0.0156771597, -0.0407614484, 0.0295330901, -0.21274659, -0.12757723, -0.0479505919, -0.0762341321, - -0.0713210404, -0.143949836, -0.0904876515}, - {0.140505642, -0.264103413, 0.202562928, 0.144187748, 0.0558891892, 0.0134075759, 0.0689714625, 0.117720678, - -0.0351380594, 0.0996671915, -0.0452203788, -0.0287328009, 0.188050762, -0.0153089538, -0.00311093242, 0.101031013, - 0.0853718519, 0.200995699, 0.119653031, 0.00534844724, 0.0835268423, 0.0391816422, 0.286809564, -0.0128748715, - 0.0284799505, 0.114542693, 0.107680388}, - {-0.273518384, 0.211155817, -0.169016764, -0.0235058516, -0.0130031612, -0.0363758728, -0.170976534, 0.00985067803, - -0.156653851, -0.103289649, -0.100549802, -0.0207712539, -0.00204128353, -0.134797335, -0.110223539, -0.0954364091, - -0.184586838, -0.227154851, -0.0428540483, -0.0500823632, 0.033524435, -0.0981419683, 0.000901479507, -0.129588395, - -0.106828153, -0.0152690345, -0.127257407}, - {0.240826175, 0.524622917, 0.166068822, -0.124361165, -0.00826285966, -0.128780857, 0.07311064, 0.0173093174, - -0.177200377, -0.130131528, -0.105714977, -0.0450495519, -0.0963956192, -0.0075211958, -0.0836626068, -0.130345538, - -0.102114394, -0.0343048684, -0.0724285617, -0.020758098, -0.15061368, -0.131341293, 0.035345152, -0.202655107, - 0.00194212468, -0.024443673, 0.137504488}, - {0.324617684, -0.23776032, 0.0997180492, 0.159622923, 0.117742524, 0.0529744886, 0.051685784, 0.190560326, - 0.189527601, 0.0501139872, 0.183927968, 0.0522141531, 0.159441307, 0.0571975783, 0.256864548, 0.0844347551, - 0.0260899868, 0.100037076, 0.209921867, 0.0661545619, 0.102322966, 0.0393468738, 0.199664697, 0.0249059796, - 0.0943753645, -0.0150666591, -0.0711701587}, - {-0.215813324, 0.180122569, 0.0371143855, -0.125089735, -0.213025764, 0.0364030339, -0.0460196659, -0.0935595036, - -0.123207875, -0.106051706, -0.104017086, -0.212639987, -0.103539668, -0.0184155293, -0.0967653692, -0.0143776694, - -0.0286937896, -0.0239762962, -0.215971351, -0.21347703, -0.0409797654, 0.0136134103, -0.146095082, -0.0394411497, - -0.109160267, 0.00394452084, -0.0890475437}, - {0.224823639, -0.142148271, 0.156778499, -0.00250017759, 0.142526641, 0.177045777, 0.162021145, 0.0779762268, - 0.0653973818, -0.0155820604, -0.00307240104, 0.0796438679, -0.0115369912, 0.00760591216, 0.0839074329, 0.011734535, - 0.173044235, 0.137959257, 0.0355584361, 0.0910959616, 0.0584707819, 0.0847086683, 0.069622837, 0.0704588667, - 0.0422701836, 0.0343328789, 0.130176514}, - {0.248121575, -0.718198836, 0.280786127, 0.166958034, 0.0853961557, 0.0905619413, 0.197417736, 0.161803842, - 0.139548704, 0.0436924845, 0.0616719499, 0.144604117, 0.159158483, 0.0420498364, 0.0324096233, -0.000715754228, - 0.0851745233, 0.226061374, 0.133464649, 0.063581191, 0.0425675251, 0.140226841, 0.493301868, 0.261711568, - 0.33839944, 0.241718829, 0.211702913}, - {0.680942357, -0.921306312, 0.143372208, 0.00767845288, 0.124762543, 0.0487947352, 0.00219840859, 0.0856792331, - 0.153107554, 0.145460173, 0.178919986, 0.0356529206, 0.178734273, 0.20903568, 0.239826441, 0.11746756, - 0.036412131, 0.137592047, 0.21512334, 0.399956256, 0.162690476, 0.135854736, 0.017693026, 0.13674739, - 0.265127927, 0.189316303, 0.147545919}, - {0.208872452, -0.56664288, 0.158555776, -0.0628495365, 0.00224737707, 0.12775071, 0.223413497, 0.0944168717, - -0.0752880499, 0.0484407097, 0.00523728272, 0.179766402, 0.0901073143, 0.0839064717, -0.00416981103, 0.169999242, - 0.140722185, 0.136145249, 0.200115979, 0.124631949, 0.192199409, 0.197580442, 0.245611683, 0.171915039, - 0.124507569, 0.171031937, 0.272799194}, - {0.417655796, -0.476884097, 0.125178307, 0.138402343, 0.122928627, 0.0407426171, -0.0386365689, -0.0399021991, - -0.0538207963, -0.00483809039, -0.103123933, -0.0660489798, -0.00264962274, 0.0245594848, -0.1476904, -0.0151537172, - -0.05937244, -0.0264183395, 0.169120625, -0.0389649346, 0.0546859689, 0.157597214, -0.0442446768, 0.0855880827, - -0.0361807272, 0.160296679, 0.126738638}, - {-0.378693879, 0.234500527, -0.190678969, -0.0408783667, -0.0962519348, -0.0968703181, -0.0695852414, -0.052617386, - -0.0566320494, -0.030750433, 0.00375046162, -0.161522672, -0.102120131, -0.22629337, -0.106760956, -0.146758765, - -0.141566396, -0.0715286285, -0.163557917, 0.0111427922, -0.148292646, -0.125399783, -0.14243643, -0.0905193985, - -0.0655139461, -0.151807159, -0.0969011113}, - {0.319175929, -0.390873164, 0.162176296, 0.124978416, 0.0850441828, 0.170238972, 0.0939667448, 0.012011149, - -0.0808500201, 0.034518946, -0.0188699961, 0.0581693016, 0.0706431717, -0.0250454322, 0.0160313696, 0.010380323, - 0.0462402031, 0.122048303, -0.0181347933, 0.0618357733, -0.0417718962, 0.0354376771, 0.21614033, -0.00287851505, - 0.0546622947, 0.106041074, 0.0957214385}, - {-0.0670246482, -1.40860128, 0.385309309, 0.349619895, 0.254730135, 0.381623566, 0.372816622, 0.143932596, - 0.231021345, 0.183745623, 0.487929821, 0.261497676, 0.0391980596, 0.00960394647, 0.0209474098, 0.323108107, - 0.295323312, -0.0106031494, -0.019115122, 0.107793093, 0.215048447, 0.287489712, -0.0252881944, -0.0110332165, - 0.158037543, 0.215606093, 0.297919482}, - {0.518265128, -0.554099798, 0.155733109, 0.217394069, -0.00727637438, 0.0509682149, 0.0364470147, 0.0760326535, - -0.0653701127, -0.0100978864, -0.00425550062, -0.0749389157, 0.16120562, 0.094311446, -0.0194558278, 0.00408704067, - -0.0575511828, 0.162599027, 0.0255256798, -0.0737488493, -0.0144423246, -0.065677762, 0.0394451693, -0.0141895954, - -0.0202025231, 0.093421936, -0.0464882702}, - {0.312840044, -0.380728394, -0.0199242439, -0.0637602359, 0.0460897982, 0.141509652, 0.15347515, 0.0186699014, - -0.013868222, 0.0199913848, 0.11250025, 0.16548267, 0.0405571349, 0.0821778774, 0.0206979979, 0.146862358, - 0.149970472, 0.0421114415, 0.075723201, 0.0326593183, 0.0781190991, 0.229785904, 0.131655306, 0.13332288, - 0.0875106752, 0.151138783, 0.27515617}, - {0.557796419, -0.271105945, -0.135938123, -0.151212856, 0.0132599631, -0.0137977209, -0.0509882905, -0.0312622562, - -0.019643601, 0.103897847, 0.131554917, -0.0328879319, 0.0658909753, 0.0384253003, -0.027326636, 0.0832217187, - 0.232588783, 0.0897849947, -0.0285363011, 0.0138111468, 0.157057226, 0.13869454, 0.138953358, 0.0367785133, - 0.108918607, -0.00833133049, 0.0772368535}, - {-0.37025696, 0.34698841, -0.164301068, -0.11555206, -0.0598055869, -0.0667800233, -0.192380622, -0.133737028, - -0.148593411, -0.121925727, -0.182414263, 0.0567184947, -0.163480595, -0.0992843583, -0.098942548, -0.0350599326, - -0.141002417, -0.0181282423, -0.102291852, -0.12211825, -0.050163269, -0.169281945, 0.0569266453, -0.165352061, - -0.137477815, -0.140887201, -0.151714861}, - {0.341095716, 0.120465197, -0.0823300853, 0.0446427129, 0.116162814, -0.0311227329, -0.0962972417, 0.121854618, - 0.178456798, 0.17567645, 0.211310029, -0.0196751002, 0.0548262298, 0.155282319, 0.233292669, 0.251868308, - -0.000533286599, 0.119322225, 0.0134889092, 0.185203642, 0.0429295786, -0.014763101, -0.00590737863, 0.11673785, - 0.170903519, 0.10979344, -0.103873558}, - {-0.897909045, -4.69421911, 0.205406263, 0.221727297, 0.287078679, 0.236628547, 0.273687661, 0.127462909, - 0.109897971, 0.073557958, 0.127785787, 0.27025798, 0.343787134, 0.0976620317, 0.0679073483, 0.149988249, - 0.310341835, 0.272185922, 0.145391867, 0.0645254478, 0.116608068, 0.205105051, 0.239113867, 0.26975742, - 0.239295334, 0.251002461, 0.368724138}, - {0.46915853, -0.406623274, -0.0563587062, 0.0319628939, 0.00552898366, 0.0744318292, -0.0347990282, -0.0205581076, - 0.143796533, -0.0096650701, 0.0877068862, 0.03160749, -0.0150092496, 0.135088384, 0.0219495893, 0.204218864, - 0.141957134, 0.123692684, 0.0519869141, 0.0334522016, 0.0812455863, 0.164413199, -0.00818906166, 0.142093509, - -0.0542448945, 0.0896779522, 0.166852266}, - {0.383818626, 0.5958004, 0.179428756, -0.199397787, -0.0665481761, 0.0298313871, 0.0531812124, -0.099887006, - -0.0909599662, 0.0614290833, -0.137692958, -0.0850088, 0.0179387033, -0.215907767, -0.149531767, -0.120972522, - -0.0475872681, -0.0269163623, -0.0605346672, -0.0730663911, -0.171813294, -0.0476032384, 0.0958294868, 0.119042337, - -0.00923403725, -0.0993423238, 0.0409177542}, - {0.3616153, -0.314780414, 0.00147321285, 0.152476445, 0.107074946, 0.0903646946, 0.104922041, 0.0444336571, - 0.159591213, 0.185087025, 0.0905429274, 0.10870064, 0.0832449198, 0.168035105, 0.182690784, 0.167314902, - 0.22124286, 0.0716655925, 0.222487181, 0.170204401, 0.219096646, 0.123106085, 0.103201479, 0.159390971, - 0.221044376, 0.168632194, 0.0915424451}, - {0.421613634, -0.399082035, 0.188590765, 0.0627617463, 0.0969695821, 0.0426679999, 0.166313916, 0.170439288, - 0.0876998007, 0.174340814, 0.0343694836, 0.165511653, 0.0109075084, 0.0775722191, 0.0283280853, 0.0268163495, - 0.0482661054, 0.14014411, 0.0834662691, 0.108136475, 0.165458322, 0.00956256408, -0.0849840567, -0.0127592999, - -0.0575121529, 0.0770347789, 0.0570578277}, - {0.477435529, -0.437617123, 0.051619228, 0.0460120589, 0.133850917, 0.0485309288, 0.0280636847, 0.150195047, - 0.0609800033, 0.154566348, 0.0803388208, 0.0859349668, 0.0108320387, 0.108330056, 0.102925889, -0.010396854, - 0.0443971418, -0.0418371633, 0.0945528969, 0.0176850855, 0.00766494684, 0.0170383062, -0.0763792694, -0.0465995222, - -0.035655763, -0.00451016938, 0.0673447475}, - {0.422291368, -0.205917373, 0.0924348161, 0.193689808, 0.0701295808, 0.0885713845, 0.0376715511, 0.203721657, - 0.0885817409, 0.171860799, 0.077528879, 0.0877082869, 0.198015884, 0.0744842067, 0.20866628, 0.135688141, - 0.126205251, 0.156737089, 0.150870427, 0.0138880163, 0.0737325549, 0.0229568612, -0.0833026916, 0.0664714128, - -0.040268179, 0.0152530838, -0.00160295411}, - {-0.385712832, 0.214391112, 0.070799306, -0.096141614, -0.16453445, -0.155173481, -0.108835906, -0.115385033, - -0.090645358, -0.1448268, -0.101075649, -0.107898541, -0.0970059186, -0.168248281, -0.147197112, -0.012966631, - -0.0107423384, -0.145579457, -0.148254678, -0.01620299, -0.106271997, -0.192775249, -0.183934942, -0.085250333, - -0.138067365, -0.00160986977, -0.0595375448}, - {0.383369058, -0.0776197985, 0.0314927883, 0.0393924117, 0.168874964, 0.139704168, 0.106199935, 0.0242452268, - 0.0995552838, 0.153926596, 0.175399214, 0.0885702148, 0.107615627, 0.0630444065, 0.136611223, 0.120922558, - 0.112005487, -0.00127684651, 0.081233032, 0.0298437476, 0.0945131332, 0.0783420503, 0.064549543, 0.06753584, - 0.110518299, 0.136796266, -0.0654531941}, - {-0.398568809, 0.199587286, -0.0846925229, -0.216599524, -0.0957491249, 0.0205594394, -0.155364677, -0.142765552, - -0.0461665243, 0.0110024186, -0.121991016, -0.0460250005, -0.0774515718, -0.0125134084, -0.0688956976, -0.164693028, - -0.211418837, -0.103768639, -0.122238405, -0.112455241, -0.0825687349, -0.118332535, -0.0648693442, -0.0670684129, - -0.242567211, -0.0624209307, -0.0826468915}, - {-0.26545167, 0.355324924, -0.269972384, -0.0857584178, -0.0465858616, 0.0337751359, 0.00990587194, 0.0115580428, - -0.133223355, -0.13316004, -0.019466199, -0.0940565914, -0.093563959, -0.100755326, -0.0905914381, -0.147906974, - -0.0748415738, -0.0370743126, -0.0230461154, -0.198925689, -0.20902808, -0.109874807, 0.0244780127, -0.0670853034, - -0.0519143417, -0.163116768, -0.105297022}, - {0.31931302, 0.547459543, 0.0880753249, -0.062735498, -0.0503338724, -0.0764781907, 0.126512289, -0.140330151, - 0.0138528449, -0.106777489, -0.0472263433, -0.0315330811, 0.0223370809, -0.129384652, -0.144970268, -0.122217946, - -0.0666366145, 0.0539318547, -0.0438860506, -0.157488108, -0.204093114, -0.0276077315, 0.117251448, -0.110314354, - 0.0731730983, 0.0449753292, -0.0369386263}, - {-0.266658574, 0.216644511, 0.0144204367, -0.0806930289, -0.22242038, -0.12643759, -0.0142633347, -0.151167005, - 0.0276681464, -0.116149977, -0.0712868497, 0.00156799273, 0.0262473337, -0.160810307, -0.105704002, -0.125064746, - -0.157742158, -0.173769936, -0.111742049, -0.0202498939, -0.0036939471, -0.0889281705, -0.106493376, -0.0859038234, - 0.0296278801, -0.163682491, -0.0782464445}, - {0.00354540255, 0.420924097, 0.169512987, -0.0258780308, -0.0895950943, -0.106438994, -0.0408810042, -0.0940106884, - -0.0642131791, 0.0186908916, -0.0822453871, -0.160974473, -0.13742575, -0.173319608, -0.195523262, -0.0196603332, - -0.0350941867, -0.160319299, -0.119695529, -0.174402416, -0.0781966373, -0.0856283084, 0.0131161194, -0.109612837, - -0.120244138, 0.0165597238, 0.0675070062}, - {-0.278506458, 0.3738904, -0.125549883, -0.0415136851, -0.225196004, 0.0471161343, -0.112398431, -0.00679458445, - -0.141953319, -0.192300454, -0.0989379138, -0.0562743135, -0.126593485, -0.235259488, -0.0563514717, 0.000541815767, - -0.0657910556, -0.109945782, -0.0276576448, -0.142048702, -0.161862046, -0.0975759551, -0.0627105087, -0.0598262586, - -0.0786498636, -0.155082062, -0.0157313831}, - {-0.55413568, 0.0202759523, -0.235556498, -0.143557742, -0.132204145, -0.130727574, -0.0438120514, -0.170451298, - 0.0131008318, -0.176760748, -0.150862694, -0.12528348, -0.0954406857, 0.0310935993, -0.0661759451, 0.00816991646, - -0.152494282, -0.0621983558, -0.121914424, -0.193032652, -0.0904289559, -0.0863325149, -0.104844026, -0.0741641968, - -0.0228042435, -0.187413111, -0.162609577}, - {0.485976547, -0.189988092, -0.0003588986, 0.17151244, 0.0998663455, 0.103645243, -0.05487106, 0.0725467801, - 0.0682763979, 0.0675051957, 0.0852867514, -0.0596668385, -0.00893313531, 0.109018549, 0.166358188, 0.223492667, - 0.111480385, 0.0559710898, 0.0776525959, 0.140913159, 0.143883765, -0.0095132608, 0.110375226, 0.019682508, - 0.0774076283, -0.0158048347, 0.0246655736}, - {-0.140471548, 0.402499974, -0.0232743174, -0.136925817, -0.0865993947, 0.00443352247, 0.055207476, -0.0350629054, - -0.0854582861, -0.17693159, -0.0253951941, -0.155755132, -0.184742153, -0.0597181469, -0.133559436, -0.0292834379, - -0.126847684, -0.0917475522, -0.0886207744, -0.236236289, -0.163285226, 0.000951068825, 0.0517877229, 0.0205014329, - -0.140833616, -0.112022206, -0.0224563554}, - {-0.469557047, 0.0208313558, -0.145046726, -0.0819347948, -0.0256711114, 0.100511104, -0.199989334, -0.125898451, - -0.0655753985, -0.0448276848, -0.00316228555, -0.0757711679, -0.0135262152, -0.0920219123, -0.042041257, -0.0200816002, - 0.0232402068, -0.108371332, -0.152907148, -0.184440449, -0.136486232, -0.154705539, -0.211260378, -0.0912795365, - -0.126199439, -0.0802948773, -0.140814647}, - {-0.249324769, 0.368552059, -0.032402385, 0.0652965158, -0.0383552313, -0.243027195, -0.012590345, -0.0551861823, - -0.0390262082, -0.183737651, -0.0706432536, -0.159616888, -0.156150624, -0.190365016, -0.0898740962, -0.0677146986, - -0.0370336026, -0.149673626, -0.191402137, -0.246475443, 0.0203555189, 0.0176247768, -0.0742982924, -0.021756392, - -0.0343282968, -0.00448664837, -0.0423567258}, - {-0.146918356, 0.447307825, -0.143606752, -0.0969513431, -0.0310435724, -0.0160554368, -0.0268079266, -0.0412539244, - -0.102859691, -0.100135177, -0.193884194, -0.0130110625, -0.0967244878, -0.0163912624, -0.0904889107, -0.19804363, - -0.149922729, -0.0109635526, -0.0905889943, -0.114994846, -0.0114435479, 0.0449921228, -0.0197346658, -0.0197591614, - -0.101547442, -0.0553377345, -0.104216985}, + {0.45203805, -0.45806545, 0.184657946, 0.015440058, -0.0498491041, 0.0602977648, 0.0104919272, 0.136156857, + 0.154603124, 0.188682079, -0.152893052, 0.139493868, -0.0423498601, 0.00312076462, 0.127145305, -0.0468874052, + 0.0406702496, 0.0932508707, 0.215996221, -0.164159477, -0.0848911554, 0.160647184, 0.176411152, -0.107995383, + -0.0560317189, 0.10781534, 0.13188453}, + {-0.145926446, 0.164630428, 0.218776718, 0.124891192, 0.028766254, 0.224259064, -0.00950260554, 0.0920046568, + -0.102045335, -0.0132911978, 0.0267301146, 0.0344877206, 0.149275959, 0.0281491317, -0.105036184, -0.224299952, + -0.0628498942, 0.108891979, -0.0362240039, 0.178556338, 0.16461724, -0.156521052, 0.0833504945, -0.114121012, + -0.0526039414, -0.00675108843, -0.194849521}, + {-0.246496528, 0.27284646, 0.143055499, -0.0329238065, -0.00508027431, -0.228733286, 0.176708475, 0.0408387929, + 0.0970109031, -0.0403212197, 0.109981462, 0.152939782, 0.154237449, 0.182322383, 0.182935759, 0.149006411, + -0.128580987, -0.00866060518, 0.122518316, -0.138388634, -0.141169786, -0.0435060635, -0.00899176858, 0.160067245, + -0.14076966, 0.152111694, -0.107612282}, + {-0.242376834, 0.464385748, 0.139883548, -0.036559552, -0.0745075196, 0.152636394, 0.226315558, -0.104345381, + -0.115299724, -0.203744456, 0.0880749822, 0.0400868244, 0.141304865, -0.023190856, -0.0205053445, 0.114943676, + 0.169122234, 0.0804926753, 0.0573003665, 0.205071226, 0.121534348, 0.0594101436, -0.015504119, 0.0381363258, + -0.150309563, 0.122322842, 0.122337162}, + {0.226774663, -0.410293937, 0.173805565, -0.039909441, 0.00356826163, -0.0874014869, 0.0437118635, 0.0715007633, + 0.158695742, -0.00197704835, -0.0790493265, 0.141603172, 0.170332611, 0.0554297119, 0.0779379457, 0.0360636823, + 0.0830756277, -0.0237493757, -0.0609783493, -0.0359459072, 0.137534857, -0.136493713, 0.125552744, -0.156720877, + 0.139673755, 0.131358698, -0.0964837819}, + {-0.028656628, 0.416204304, 0.160696074, -0.0637104511, -0.174918309, -0.0167853851, 0.132688239, -0.0670960769, + 0.0394107848, -0.00854289345, -0.0253574327, -0.147366405, 0.0566633418, -0.0892428607, -0.168717787, -0.138165191, + 0.0719370618, -0.0740026757, 0.111775473, -0.029681962, -0.103208654, 0.1201616, 0.152709723, 0.0587348044, + -0.00147062086, -0.0286747944, -0.0217057094}, + {0.112411827, -0.411707968, 0.0696697831, 0.152524248, -0.212140769, 0.144798145, 0.0530875251, -0.0158916861, + 0.0132829705, 0.0213712305, 0.0432566106, 0.226526752, 0.0658008307, 0.182736099, -0.0426303744, -0.00643140636, + 0.0733423978, -0.0908156633, -0.173937261, -0.127588227, 0.0717438534, -0.0860921815, -0.0530667976, 0.188322082, + 0.087881662, 0.191903785, 0.10856016}, + {-0.480609387, 0.504398167, 0.0912523717, 0.192224368, -0.00601684302, -0.118551709, -0.0375153571, 0.0731836706, + 0.0482735783, -0.0833157375, -0.0608279184, 0.117967702, 0.0884849131, -0.0320491195, 0.139705002, 0.141425192, + 0.0440682359, 0.134822577, -0.0498490632, 0.0454034172, -0.123904027, 0.0175073892, -0.116716154, 0.0309459101, + -0.027111521, 0.195593968, 0.169307634}, + {-0.0701465979, 0.225146249, -0.0158732757, -0.185621411, 0.0800627396, -0.12233258, -0.092362076, 0.0619118623, + -0.149065509, -0.187038511, 0.0378238223, 0.0356469862, 0.123635307, 0.0410633162, -0.140698552, 0.139683858, + 0.0933743492, -0.0237518884, -0.152255461, 0.0331202038, -0.131765708, 0.167886168, 0.0278925505, 0.139326066, + 0.0951004475, -0.0667872131, 0.106708623}, + {0.264699459, -0.506384075, -0.177768305, 0.191724792, 0.158215538, -0.0480591543, -0.0823616236, -0.109986812, + -0.0233260933, -0.219094649, -0.00836386345, 0.119118184, 0.118271984, -0.0459285676, 0.0109413238, -0.107904986, + 0.0581092946, -0.119608216, -0.020630287, 0.0178713631, 0.181588501, 0.106637135, -0.195414141, 0.0427569486, + -0.0899038687, -0.020193845, -0.0909356773}, + {0.368019372, -0.354154676, 0.161955997, -0.0715911612, -0.0854630396, -0.0709507465, 0.10217762, -0.00151236018, + 0.132291406, -0.166236058, -0.0839441568, 0.138919562, -0.056720037, -0.0275761262, 0.100214086, 0.0887621269, + 0.118959829, -0.0467147082, -0.101447068, -0.132831559, -0.0954982862, 0.0869457796, 0.0950589553, 0.102018684, + 0.129958004, 0.154459402, -0.118537433}, + {0.0681799278, -0.391588539, 0.174535319, 0.0820489824, -0.133801162, 0.00347060384, 0.101381995, -0.128766671, + -0.132831559, -0.0588793419, 0.138211936, -0.168236509, 0.027371034, -0.144625559, -0.11814712, -0.115526192, + 0.190200552, -0.0617874973, -0.013945071, -0.0869922414, -0.0967663452, 0.145353124, 0.105865806, -0.0167180672, + 0.00135051238, -0.134099871, 0.11230278}, + {-0.187783852, 0.107754938, -0.0441996977, 0.13864933, -0.166043535, 0.145372719, 0.07046929, -0.0130516207, + -0.174515933, -0.198206052, 0.116103902, 0.0675079599, 0.110398091, 0.0891169459, -0.125991046, 0.117762819, + 0.212354198, 0.0903823227, 0.10142412, -0.0602888986, -0.068611078, -0.200365365, 0.0429478586, -0.134543389, + 0.200212553, -0.0951323658, 0.192112997}, + {0.139940664, -0.611673653, 0.0713035837, 0.119052477, 0.0811758116, 0.000230582678, -0.129236147, -0.198244363, + -0.144943699, 0.136421964, 0.149650291, 0.0161638465, 0.167543218, 0.126726225, -0.0292697847, -0.122151822, + -0.0617690608, 0.021391781, 0.099237062, 0.0846792385, -0.193621203, 0.0533882231, 0.00477153948, -0.104455233, + 0.114149697, 0.10723453, -0.0710129812}, + {0.407875597, -0.327368706, 0.0911267251, 0.0666566789, 0.0036699858, -0.082635507, 0.112434506, 0.0916196778, + -0.192202449, -0.0911182985, 0.00264626276, 0.193442881, 0.0877650306, -0.0744432211, 0.0629109219, 0.0378978997, + 0.16101791, -0.140416995, 0.0859648213, -0.112621471, -0.135480911, 0.0753640532, -0.0473459624, 0.0482204743, + -0.122037426, -0.00754988706, -0.0456792526}, + {0.179017484, -0.256205291, 0.0706775188, -0.0727694556, -0.0545170382, 0.143528417, 0.0594934374, 0.125289023, + 0.118550658, -0.0476030186, -0.163496226, 0.171205327, -0.145752281, -0.00298091653, -0.0534051247, -0.011259851, + -0.0621688217, 0.116991401, -0.0621647276, 0.00997477584, -0.0308142677, 0.0121697532, -0.116714008, 0.15777123, + 0.173992589, 0.0419384986, 0.178914845}, + {-0.224847108, 0.284483135, 0.102464832, 0.0906737596, 0.108475834, 0.0324019641, -0.104357302, -0.0269440413, + 0.00597245991, -0.0490998663, -0.140963659, 0.0343309939, -0.0413934179, 0.171440646, 0.0250081588, -0.0579161271, + -0.118270136, 0.123303525, -0.14628312, -0.0880199447, 0.0270628892, 0.137147218, -0.138709307, 0.222544134, + 0.0684332475, -0.0494217537, 0.107166246}, + {-0.337362945, 0.58681792, -0.104814805, 0.201545835, 0.24242571, 0.0720553547, 0.219500825, -0.0376220644, + -0.0272652749, -0.0965059474, 0.142305076, 0.229384825, -0.0222753417, 0.236048102, -0.105869219, -0.0144829955, + 0.205647886, -0.197792143, -0.0260840338, 0.0341386162, 0.168255746, 0.155091181, -0.149067134, -0.0276787449, + 0.0544128828, 0.183676094, 0.0185037944}, + {-0.0688595027, -0.242534414, -0.00178349309, -0.033371456, -0.048882585, -0.00702098384, -0.0201558601, -0.0346171334, + -0.243184164, -0.135665819, -0.154119059, 0.0427678302, -0.255609989, -0.0969583765, -0.215238467, -0.0893287957, + -0.00094305817, 0.0181970485, 0.0420945697, -0.211489245, 0.0563394167, 0.0952795297, 0.144727916, 0.0258613639, + -0.25862366, -0.267417997, -0.169211641}, + {-0.103942402, 0.319890589, 0.0332274362, 0.181669831, 0.141806707, 0.06303069, 0.163952336, 0.0390935205, + -0.107556172, -0.0671523884, -0.104147919, -0.0607618988, 0.135131225, 0.166931331, -0.148846477, 0.0873545408, + 0.0355017073, -0.120358497, 0.12431588, -0.115621306, -0.149365678, -0.132611886, -0.0465488844, -0.0227212682, + 0.243345082, -0.072464563, -0.0712231323}, + {0.189372376, -0.49966836, -0.145333081, -0.0338866115, 0.157825932, 0.0997279808, 0.0963860676, 0.0253550243, + -0.0133155137, -0.135201752, 0.181278095, 0.0445665866, -0.087789692, 0.116688065, -0.139262021, 0.1418363, + -0.0556924418, -0.134224832, -0.126924321, -0.0441904813, -0.140911162, -0.171938971, -0.0878682137, -0.0803474709, + 0.145950586, -0.0934541598, 0.161895379}, + {-0.104655996, 0.405606389, 0.150038421, 0.18388395, 0.0439859666, -0.158293724, 0.136542365, -0.0142309172, + 0.079638049, 0.00508346595, 0.0119484281, -0.0415694341, 0.108356975, -0.004423148, -0.11726366, -0.0615228601, + 0.130160451, 0.0435206667, 0.172708303, 0.0710032806, 0.0693547651, 0.0266085416, 0.13239187, 0.0778798535, + 0.167564481, 0.106125191, 0.157374531}, + {0.0666572154, -0.417621315, -0.145837545, -0.0607343651, 0.159889117, -0.108100966, 0.082456708, -0.15890573, + -0.164271951, -0.165195867, 0.0732233524, 0.0163369142, 0.0891780704, 0.0805215985, 0.0278974716, 0.150632814, + -0.0895134062, 0.111488573, 0.101438038, -0.142934665, 0.0580612309, 0.0537258387, -0.0512021556, -0.193477094, + 0.131419688, 0.0478718244, -0.141526297}, + {-0.189271867, 0.471700758, -0.00351118878, -0.0877563581, -0.0779252797, 0.0382888243, -0.0902312919, 0.163972333, + -0.0705869868, -0.173119396, 0.091119431, 0.0678818673, 0.184856921, 0.0542627238, 0.0257524345, -0.144017503, + 0.0381738208, 0.16978693, 0.154912606, -0.0927802026, -0.0612011887, -0.0474269725, 0.0182966851, 0.201843932, + 0.0514337011, 0.134884581, -0.101345524}, + {-0.180943102, 0.365885347, -0.165755421, -0.139602855, 0.0148097733, -0.0521840975, 0.131981447, 0.1693023, + 0.174771592, 0.224593073, -0.0616881363, -0.0701046959, -0.017589286, 0.159239709, 0.0455335937, -0.150728434, + 0.0672135353, -0.0901903883, 0.0767841786, -0.129837379, 0.15355666, -0.0534600057, -0.179041833, -0.0997670069, + -0.0251706503, 0.0243577436, -0.144590929}, + {-0.147147328, 0.121580601, -0.115824744, 0.0193387233, -0.0593371578, 0.00159258011, 0.140480548, 0.150421634, + 0.132571429, 0.152347952, 0.0571796708, 0.0243118014, -0.0488406047, -0.180542916, 0.0214492287, -0.168230176, + 0.0661140159, -0.0332300961, 0.00450937869, 0.096897237, 0.0654156283, 0.0850077868, 0.110239424, 0.0741055086, + -0.221916959, -0.0416949466, 0.00760652311}, + {-0.141422495, 0.264740735, 0.0969706625, -0.024862539, 0.16494818, 0.0133759212, -0.0612095073, 0.171587318, + 0.195816398, 0.152986243, -0.0238046758, -0.0556493476, -0.0834930912, 0.00804871228, 0.092385374, 0.00701225642, + -0.0492355376, -0.0414040275, 0.111721739, -0.0224872753, -0.193405509, -0.0787967891, -0.0322295614, -0.0368636437, + 0.181566924, 0.0761615708, 0.103768937}, + {0.194328725, -0.214781255, 0.0144082746, -0.0595152713, 0.0942294821, 0.02755123, -0.00284175319, 0.0518570989, + 0.0239806771, -0.0442022979, 0.12787506, 0.165338546, 0.191406086, 0.030535575, -0.054367166, 0.0183518659, + 0.0280179717, -0.107867613, 0.0313984267, -0.225444317, -0.0780780539, 0.00718454225, -0.154967993, -0.0763758123, + -0.121581905, -0.254133791, -0.187636703}, + {0.0553622879, -0.53247118, 0.109050922, 0.0375806168, 0.094551228, -0.186817557, -0.0905709043, -0.188652709, + 0.0291052721, 0.0304438043, -0.0785995126, -0.135230228, -0.0721748546, -0.0690952241, 0.0542577133, 0.0419555865, + -0.110164367, -0.153792471, -0.117294982, 0.185125813, -0.152395442, 0.0121135116, -0.0410370864, -0.0595868826, + 0.0537715182, -0.146331191, 0.0312282555}, + {0.0335008986, -0.290468603, -0.0381796733, 0.194304973, -0.186485395, 0.0389903262, 0.10586153, -0.0149400393, + -0.168694705, 0.000754418026, -0.0175829194, -0.023112895, -0.0503823087, -0.170508876, -0.132313699, -0.0237778742, + 0.148925528, 0.164118469, 0.12503235, -0.198841825, -0.0923689157, -0.049933929, -0.201444596, -0.193108186, + 0.0507003143, 0.106741972, 0.0158077236}, + {0.0772758424, -0.273380995, -0.0217292868, -0.12670666, -0.0240060389, 0.0568628237, -0.00245626341, -0.0328990705, + 0.0614016615, -0.100336835, -0.0634530112, 0.0625642836, -0.0873259529, 0.16067943, 0.208713338, -0.145100117, + -0.0550227538, -0.0740675777, 0.190599576, -0.125204816, -0.0569524392, -0.1745691, -0.123225518, 0.0701928809, + -0.0947788656, 0.17683363, 0.00736949453}, + {-0.357918262, 0.185558423, 0.149971426, 0.108677842, 0.211355656, 0.206678033, 0.00662368024, -0.0432061926, + 0.0333676226, 0.174399436, -0.0983141512, 0.112194173, -0.146821916, -0.0409492999, 0.0739307478, -0.149185672, + 0.214225635, -0.0876166448, 0.129657611, 0.0431319512, -0.146045119, -0.0935413167, -0.0828094631, -0.060967084, + -0.186989456, 0.182206944, 0.0871673003}, + {-0.289800406, 0.143204033, 0.166941509, 0.137223989, -0.125742018, -0.0451510288, -0.0058506364, -0.00193965889, + -0.112227209, 0.0614434183, 0.0562265068, 0.0806728825, -0.0525025688, -0.195452332, -0.129680395, -0.139963537, + 0.239692003, 0.142114177, -0.146621287, 0.0849069878, -0.119701877, -0.0896522626, 0.0653329268, 0.14421159, + -0.131648183, 0.104574107, 0.119816318}, + {-0.118906751, 0.238706335, -0.155625954, 0.0401087552, -0.136961922, 0.104818523, -0.111247472, -0.0387643836, + -0.0558572933, 0.205681235, 0.126191899, -0.0210000258, -0.0117633613, -0.129667789, -0.0443373509, 0.0886635631, + -0.14805603, 0.118988045, -0.0662066042, -0.0622597113, 0.1528624, -0.0150403194, -0.105838284, -0.0872497186, + 0.180054486, 0.0714533627, -0.140877247}, + {-0.380353957, 0.492472261, -0.132434517, 0.00281717605, 0.10226243, -0.0597996488, -0.0238327533, 0.0167977419, + -0.0911981687, 0.124123447, -0.00537694013, 0.0861115754, -0.159816846, 0.0222886615, -0.106110908, 0.0330211967, + -0.0595276356, -0.171066642, -0.136262745, 0.0929749906, 0.189822257, 0.172687188, 0.0914711952, 0.118278861, + 0.185153812, -0.0570112206, 0.0302057546}, + {-0.0281435847, 0.458528131, -0.0160454605, -0.132544234, 0.0170905627, -0.031670101, -0.0569143109, 0.0207152311, + 0.140403271, 0.120634027, 0.0626093894, 0.0478590503, 0.0949899331, -0.112082399, -0.0734349191, -0.132257909, + 0.0317665115, -0.0535654239, 0.0110610807, 0.0797023997, -0.0107229594, 0.128020912, -0.195051789, 0.118799537, + 0.0109106423, -0.202617615, 0.100031853}, + {-0.26972881, 0.333438665, 0.167163447, 0.153019533, -0.0697161108, 0.0250137541, -0.112500511, -0.197154462, + 0.158567622, 0.0997756049, 0.000655053067, -0.00967839733, 0.153365731, 0.162611678, 0.0745553449, -0.156569436, + -0.00316590234, 0.186499581, 0.0960735008, -0.086285837, 0.125433937, -0.0008950755, -0.140424296, -0.0741733015, + -0.0354760773, -0.206534579, -0.0522788055}, + {-0.0864726529, 0.107510209, -0.0204926468, 0.113769569, -0.109736539, 0.00137642375, 0.066088669, 0.0229854994, + -0.0694359839, -0.0481766425, -0.0320309624, 0.0550589189, -0.00464858999, -0.152581334, -0.0856979266, 0.15216592, + -0.109378338, 0.103640109, 0.0417189449, 0.191938266, -0.153465435, -0.0649519414, -0.0699521527, 0.0622306056, + 0.0584248304, 0.02890319, 0.181365445}, + {-0.03889741, 0.472252697, 0.168293715, -0.0737051815, -0.0332587659, -0.117596567, -0.000743595534, 0.0281378534, + -0.0103634959, 0.0336701311, 0.12364509, 0.122977622, -0.137443036, 0.210172489, 0.164600626, -0.128633738, + -0.0182393156, -0.000798476336, 0.0176328998, -0.058384452, -0.102988012, -0.103830904, 0.101902224, -0.0654094815, + 0.127881408, 0.0146679925, 0.0364205875}, + {-0.369998395, 0.414347947, 0.0179530364, -0.0705664977, 0.0626467839, 0.112152629, 0.0821754113, 0.125278667, + 0.0136819864, 0.0193146113, -0.0746098533, 0.00822623353, 0.048098959, 0.161861658, 0.178058997, 0.135901883, + -0.0513123088, 0.181947067, 0.120537072, -0.0378684327, -0.0778640732, 0.105645321, 0.120248318, -0.167341024, + -0.0468132682, 0.17612952, -0.0771358535}, + {0.315076679, -0.466440678, -0.168974906, -0.080884248, -0.0366745964, 0.0369593613, 0.145466924, -0.0433687158, + -0.120463416, 0.0552976541, 0.22997351, 0.181191519, 0.0417001583, -0.0185467582, -0.017123213, -0.175927907, + 0.0756366029, 0.188033551, -0.0442217998, 0.0137181403, -0.110052332, 0.157183409, -0.0130782854, 0.00783483684, + -0.0184284188, 0.104684748, 0.0396092124}, + {0.334186912, -0.149650037, -0.0298920032, 0.0874708742, -0.0352274477, 0.133741215, -0.0792848244, 0.0209151283, + -0.154527619, -0.0487798005, 0.181496918, -0.0231991559, 0.181984082, 0.120985396, -0.132351726, -0.00437051337, + -0.161251217, -0.0499075539, 0.110172823, 0.04591842, -0.0901127011, 0.014522545, 0.183002874, 0.0877405778, + 0.133658871, -0.129253328, 0.119495243}, + {-0.0768223405, 0.419295371, -0.164106518, -0.116674729, 0.0174152087, -0.0743171647, -0.0385667793, -0.11497698, + -0.0607899502, 0.0836060569, 0.0990944728, -0.0596177578, 0.14034842, -0.158117577, 0.169240519, -0.147095278, + 0.147555918, 0.175731257, -0.0879483223, -0.0770097598, -0.122682601, 0.195812643, 0.141155526, -0.180364385, + -0.142856613, -0.0971723571, 0.0892231762}, + {0.0680414215, -0.338394165, -0.0738144144, -0.160117939, -0.118681207, -0.0644959733, 0.132998928, -0.0822650343, + 0.10789115, 0.0640353486, -0.0389966704, -0.105374597, -0.178511098, -0.0818397775, 0.0473826155, -0.121301413, + -0.0331119411, -0.156251982, 0.0245455671, 0.123937905, -0.158606604, 0.0808671638, 0.0191626605, -0.0545708314, + -0.0936540067, -0.140728787, 0.101908006}, + {-0.118871808, 0.320400387, -0.0816059411, -0.142628342, -0.0187965408, -0.0861459747, -0.119369805, 0.00661368389, + -0.172345862, 0.00317881512, -0.0968937054, 0.0202821176, 0.150950506, 0.0158345532, -0.126602441, 0.194601312, + -0.0187753662, -0.0381210335, -0.0193561688, 0.0090350518, 0.145413622, -0.204994082, 0.0975070968, 0.0292999167, + 0.0311825704, -0.0102516199, 0.0671483353}, + {0.0628996715, -0.306929439, 0.0837141201, -0.0733176023, -0.0389585346, -0.0526662357, 0.0531991832, 0.236169979, + 0.171294808, 0.170659065, 0.111782506, -0.187597394, 0.123804592, 0.0254330989, 0.126850411, 0.0589428358, + 0.00174094154, 0.202952281, -0.0495758168, -0.116069391, 0.0766428635, -0.109111913, -0.0825305879, -0.144604161, + -0.00616880506, -0.00774375489, -0.0873804167}, + {-0.492739826, 0.305849969, 0.0088744713, 0.122789115, 0.000430081971, 0.0924325362, -0.134895444, -0.0522908457, + 0.122117318, 0.0354285166, -0.009777111, 0.158144429, 0.0542714298, -0.162235588, -0.0612893403, 0.0286771879, + 0.28303349, 0.108722612, -0.0633954108, 0.0717131197, 0.0411091521, 0.115374677, -0.0782839954, -0.0308982115, + 0.122655295, 0.0880731568, -0.124431558}, + {-0.00330530782, 0.358613431, -0.00303815585, 0.127163827, 0.0843585953, -0.000906603702, -0.0341566131, 0.164120555, + -0.112474218, -0.166938543, 0.116601646, -0.103030793, -0.129165173, -0.0674462169, -0.142206386, 0.107451513, + -0.127466395, -0.168905169, -0.0806228518, 0.0634907708, -0.102753446, -0.0117311627, -0.0832699537, 0.132239282, + -0.038644515, -0.0660102293, 0.203152418}, + {0.430731356, -0.456356049, -0.165997997, 0.209886938, 0.02540382, -0.0147753283, 0.00520209037, -0.0737136304, + 0.135763139, 0.115843579, -0.0244647935, -0.0906603187, -0.0918368101, -0.105196886, -0.12183959, 0.0494215749, + 0.182277545, -0.0512001589, 0.0930726603, 0.0085748937, 0.215861663, 0.04485007, -0.0550497063, 0.186789632, + -0.0502115786, 0.0577871613, -0.124197088}, + {-0.236518025, 0.367488086, -0.153264001, -0.154577449, -0.0308951605, 0.116330765, 0.00140236702, -0.113388792, + 0.111118026, 0.0192955378, -0.118743889, 0.035439074, -0.0636330545, 0.145891577, 0.0260554254, 0.161427572, + -0.199159369, -0.0187685303, -0.149719864, -0.132435098, 0.234227553, -0.0384955294, 0.124252975, -0.118090048, + 0.102750212, -0.130326927, -0.150552452}, + {0.130825311, -0.313002527, 0.23568356, -0.170383334, 0.0319920518, -0.113231726, -0.0843822807, -0.136531726, + -0.188489348, 0.0476919375, 0.100597344, -0.0199613776, 0.111216575, -0.0505024008, -0.0699019358, 0.181107953, + -0.0414796546, 0.0899334326, 0.159103468, 0.0639324933, -0.193581164, 0.114706114, -0.0758650154, 0.157339826, + 0.0508853681, -0.175073355, 0.0371122658}, + {0.132348761, -0.51263845, 0.0348790586, -0.075076811, -0.0538910106, -0.125324801, 0.115990765, 0.190580025, + -0.00776779372, -0.0202509593, 0.026262695, -0.146287292, 0.00415695459, 0.0524729453, -0.0943571478, -0.0164777525, + 0.155653074, 0.108183607, 0.143668011, 0.0517140925, -0.000964000355, 0.119811602, -0.131744489, -0.0413018502, + -0.0891427621, -0.209854841, 0.0290439725}, + {-0.365480602, 0.246592909, -0.203429073, 0.165500805, -0.0210662447, -0.0878265873, -0.071899794, 0.0403897949, + 0.156514019, 0.100708298, -0.121775068, -0.0261480454, -0.123198077, 0.177671924, 0.14488481, 0.169164047, + 0.238786325, -0.111076251, 0.0811326504, 0.118288673, -0.184231475, 0.113126278, 0.162166685, -0.0972088426, + 0.157067999, 0.105948269, -0.0301933736}, + {0.345718145, -0.406426847, -0.0219239369, -0.0163023621, -0.0671755597, 0.127242759, 0.00928294286, -0.0985125378, + 0.212535784, 0.0415508263, -0.0392062552, 0.135913461, 0.147571012, -0.011312563, 0.156823397, -0.0991501063, + -0.000548570009, 0.152090371, -0.170067802, 0.135544837, 0.115055785, -0.0749435499, 0.198429108, -0.0448754057, + 0.13816908, -0.101596393, -0.0627855733}, + {-0.115857728, 0.186947927, -0.131327644, 0.206055224, 0.0315404274, 0.122405179, 0.0923811942, 0.122572295, + 0.229382217, 0.174152464, 0.150433242, -0.0934928656, 0.134411663, 0.0817516819, -0.151633501, -0.00354253687, + 0.17357412, -0.194090009, 0.0497873463, -0.0501048714, -0.144297376, 0.0918432772, -0.112328343, -0.0258858521, + 0.0467620939, -0.171590149, 0.144801214}, + {0.31962797, -0.526265919, -0.00705722068, 0.185621679, 0.0930102691, 0.0768527165, -0.0567677505, -0.0247654878, + -0.0491026901, -0.143609941, -0.135381147, -0.0695786104, -0.14580451, -0.0529285967, -0.11478693, 0.0970369354, + 0.210921988, -0.0694609731, -0.129906505, 0.0912040398, -0.0969664752, -0.109778643, -0.00573945697, 0.012573543, + 0.148140028, 0.0232307799, 0.155602679}, + {-0.186559528, 0.342809469, -0.0733527914, -0.104030013, -0.140911698, -0.0643998384, 0.0283140745, -0.0332799703, + -0.0590855405, 0.108374991, 0.00796503294, 0.0725592002, 0.0547435544, -0.12698479, 0.161155999, -0.143454388, + 0.0505905002, -0.0650394782, -0.0341320224, -0.108386233, -0.120054811, 0.0816547945, 0.147068098, -0.0168281887, + 0.139393479, -0.146276176, 0.172318891}, + {-0.181034431, 0.431151152, -0.0218132269, 0.155744612, -0.0762575865, -0.0889178142, 0.157267094, -0.0537965558, + 0.0540015697, 0.00869257934, -0.0252783205, -0.0366516151, -0.00322536868, -0.0826566517, -0.0559664406, -0.0559026822, + 0.0759010166, 0.119707212, 0.0980090946, -0.118467271, 0.0730911717, -0.0561659113, 0.00585941691, -0.0631579906, + 0.128859505, 0.0341102555, -0.0644980744}, + {-0.187567815, 0.465994149, 0.187646553, 0.118930668, -0.0174721088, 0.152343959, 0.159016043, -0.108857736, + -0.00696542254, -0.112568162, -0.039732717, 0.159012616, 0.0918384194, 0.135583594, -0.0181537438, 0.133122995, + 0.217082858, -0.112465248, 0.101945475, 0.0776017979, 0.168482348, -0.0815017521, 0.00540421996, 0.0658444315, + -0.119064935, -0.0895934701, -0.096984975}, + {-0.262555361, 0.301468074, -0.0537617244, -0.105911732, 0.00640139682, -0.0319269858, -0.0218670871, 0.059855327, + 0.214175731, 0.089364998, 0.147397846, -0.0239831582, -0.0762555376, -0.0456708148, 0.157429725, -0.0415160246, + 0.0154164406, 0.0843217075, 0.00705473498, 0.0990711376, -0.0438422114, 0.035154894, -0.034737926, -0.100669049, + -0.0710061342, -0.128545299, 0.0413368978}, + {0.20061405, -0.195876256, 0.125569493, 0.116587669, -0.0275134966, -0.128218397, 0.101585872, -0.0774401426, + 0.00214136648, 0.19470422, -0.113823459, 0.0068700593, -0.218907461, -0.0412247702, 0.0184247978, 0.171597406, + -0.0193886552, 0.0936624333, -0.163842916, 0.147874966, -0.155742869, -0.150499061, 0.100921579, 0.0339383222, + 0.106583171, 0.101992838, 0.0827493891}, + {-0.42351076, 0.165196016, -0.135925338, -0.0867639184, -0.0677365288, -0.0456134863, 0.1378434, -0.0135720894, + 0.0992678925, -0.170112282, -0.0799493566, 0.0403191671, -0.0419595689, -0.228088051, 0.0834629685, -0.0123647051, + -0.0879294425, 0.0134221893, -0.0705901757, 0.0505605713, 0.0362370312, 0.0085804956, 0.12087813, -0.0228291303, + -0.0214216765, 0.0717708245, -0.0259481557}, + {-0.319351792, 0.311414689, 0.0387483872, -0.0208738539, -0.0998059809, 0.0972165614, 0.0127819944, -0.118707873, + -0.0225766134, 0.0759867579, -0.00495541701, -0.00090113451, 0.125291541, -0.100987613, 0.126641393, 0.0408021547, + 0.0324828401, 0.0455836467, -0.121079832, -0.105680324, -0.0948389471, 0.116342999, 0.0593871661, -0.166127041, + 0.183721304, -0.0469549559, -0.0340779424}, + {-0.417692721, 0.50694114, -0.017380422, 0.0359385088, 0.15985322, 0.14597404, 0.0301878322, -0.0554507598, + 0.192497, 0.077975288, 0.0868773013, -0.069470793, -0.0309375748, 0.057316564, -0.00578528969, -0.0119462926, + -0.134100929, -0.0233788472, -0.0805848241, -0.0534106679, -0.00357546797, -0.107573405, 0.0843970105, 0.0139006199, + 0.0452864021, -0.00275908667, 0.0987220407}, }; -const float five_dense_biases[FIVE_DENSE_NUM] = +const float FIVE_dense_biases[FIVE_DENSE_NUM] = { - -0.145204157, -0.0277402811, 0.211434156, -0.117382497, -0.132206768, 0.21691145, -0.0433791168, 0.27201575, - 0.129949957, 0.304839015, -0.0968279541, 0.277042836, -0.115271628, -0.079115212, -0.16494669, -0.0510745384, - -0.144819096, 0.0475319512, -0.0802276954, 0.188885778, -0.182127863, 0.329600185, -0.150753573, 0.0957632288, - 0.0111581245, 0.157950222, -0.141521424, -0.190296218, 0.248286828, -0.0684776604, 0.137061238, 0.415693849, - 0.395839244, 0.360719889, 0.205312118, -0.0245424975, 0.112486944, 0.361877054, 0.0785427466, 0.267031074, - 0.240074143, 0.0293443501, 0.227391914, 0.594486654, 0.314840108, -0.141555116, 0.440181881, 0.315535516, - 0.293939352, 0.255981237, -0.0057315263, 0.236052379, -0.140156507, 0.0054772296, -0.150556788, -0.0183430873, - -0.0312510394, -0.00800710451, -0.0939261094, 0.164174587, -0.0876725167, -0.129597217, -0.0221878439, -0.0834591836 + 0.103901759, -0.224572867, -0.0642579943, -0.0322713442, 0.118484519, 0.0584781878, 0.0405431651, -0.0437740795, + -0.263778389, -0.0127514442, 0.174240664, 0.103587314, -0.00710369414, 0.240983486, 0.295394301, 0.137782365, + 0.0964536145, -0.130687788, 0.093160823, -0.184331939, 0.14074038, -0.105746306, 0.0124710118, -0.145595685, + -0.105848715, -0.173222736, -0.124221109, -0.070718132, 0.20920606, -0.0362088233, 0.289943904, -0.113258652, + -0.0512267761, -0.228272676, -0.0756545067, -0.189338356, -0.133270532, -0.248817772, 0.0976210535, 0.0497277677, + 0.234129995, 0.269502282, 0.0700765103, 0.187325478, -0.24265556, 0.024762284, -0.137840942, -0.228171706, + 0.0537541471, 0.126428396, 0.215877533, 0.30133307, -0.111865051, 0.0320456773, -0.0443919413, 0.353314757, + -0.0524924397, -0.0410760902, -0.0950823501, -0.231842026, -0.0348117203, -0.105667964, -0.193817809, -0.163696662 }; -const float five_logit_weights[FIVE_DENSE_NUM] NN_ALIGNED = +const float FIVE_logit_weights[FIVE_DENSE_NUM] NN_ALIGNED = { - 0.37051487, 0.508214772, -0.32005766, 0.27220732, 0.374211431, -0.264154106, 0.270360202, -0.629945159, - -0.199804112, -0.563038468, 0.516418219, -0.688697159, 0.48299551, 0.404973507, 0.551129878, 0.321002781, - 0.335608274, 0.337184101, 0.424715966, -0.131399259, 0.319061458, -0.486196607, 0.233341113, -0.142906249, - 0.330237418, -0.189801574, 0.355688512, 0.267817706, -0.514791608, 0.227719396, -0.158957332, -0.924359977, - -0.623777807, -0.700493455, -0.171029702, 0.379386812, -0.238112986, -0.526128888, -0.205522895, -0.512478709, - -0.175714538, 0.367500365, -0.275081784, -1.24400628, -0.298168987, 0.275398135, -0.823152721, -0.455135852, - -0.339576572, -0.454856992, 0.44089666, -0.403158367, 0.365665168, 0.305184871, 0.178278625, 0.3014597, - 0.215111017, 0.386294872, 0.421103477, -0.326511413, 0.342057288, 0.267303318, 0.311787248, 0.310548276 + -0.202310398, 0.0778354257, 0.133535951, 0.213739306, -0.270187378, 0.179972649, -0.173627168, 0.229039147, + 0.184331, -0.237555429, -0.157454208, -0.126865804, 0.112280115, -0.177178398, -0.127667278, -0.123343565, + 0.179811522, 0.175967634, -0.0776095986, 0.111451164, -0.200848684, 0.100322708, -0.171592698, 0.205210567, + 0.118166663, 0.0581910573, 0.150929645, -0.0743029639, -0.230396897, -0.146632895, -0.100431986, 0.127410069, + 0.130129427, 0.184742749, 0.207034305, 0.161030233, 0.124844849, 0.0993857831, 0.17593734, 0.18330811, + -0.213100657, -0.0935302302, 0.145162627, -0.18657887, 0.156392291, -0.160466313, 0.22612074, 0.19740513, + -0.275662214, 0.147070959, -0.0859830156, -0.227706254, 0.186142847, -0.226281583, 0.101337671, -0.262092113, + 0.15297848, 0.26149264, 0.196374565, 0.195815295, -0.0701766461, 0.161807433, 0.237383679, 0.270915806 }; -const float five_logit_bias = -0.10439048; +const float FIVE_logit_bias = -0.0928942636; diff --git a/include/weights_5.h b/include/weights_5.h index 8ad9d1b..d48a05a 100644 --- a/include/weights_5.h +++ b/include/weights_5.h @@ -24,11 +24,11 @@ // this does some kind of magic vectorisation #define NN_ALIGNED __attribute__((aligned(16))) -extern const float five_embedding[7]; -extern const float five_dense_weights[FIVE_DENSE_NUM][FIVE_INP_NUM] NN_ALIGNED; -extern const float five_dense_biases[FIVE_DENSE_NUM]; -extern const float five_logit_weights[FIVE_DENSE_NUM] NN_ALIGNED; -extern const float five_logit_bias; +extern const float FIVE_embedding[7]; +extern const float FIVE_dense_weights[FIVE_DENSE_NUM][FIVE_INP_NUM] NN_ALIGNED; +extern const float FIVE_dense_biases[FIVE_DENSE_NUM]; +extern const float FIVE_logit_weights[FIVE_DENSE_NUM] NN_ALIGNED; +extern const float FIVE_logit_bias; #endif diff --git a/include/weights_6.c b/include/weights_6.c index 77ea409..915fc54 100644 --- a/include/weights_6.c +++ b/include/weights_6.c @@ -2,12 +2,12 @@ /* v000, random init */ #include "weights_6.h" -const float six_embedding[7] = +const float SIX_embedding[7] = { 0.724845707, -0.209938288, -0.347967505, 0.821479738, -1.34644675, 0.0270497333, 0.450257659 }; -const float six_dense_weights[SIX_DENSE_NUM][SIX_INP_NUM] NN_ALIGNED = +const float SIX_dense_weights[SIX_DENSE_NUM][SIX_INP_NUM] NN_ALIGNED = { {0.0375181399, 0.0131807914, 0.0733145475, -0.108837478, -0.155519173, -0.15236935, 0.161187366, -0.102666609, -0.105799064, 0.00281478628, 0.0976773277, -0.159017026, 0.0197313707, -0.0683622435, -0.145631433, -0.153941378, @@ -331,7 +331,7 @@ const float six_dense_weights[SIX_DENSE_NUM][SIX_INP_NUM] NN_ALIGNED = -0.133655116, 0.101930477, 0.119332045, -0.127442241, -0.129697219, -0.0865818784}, }; -const float six_dense_biases[SIX_DENSE_NUM] = +const float SIX_dense_biases[SIX_DENSE_NUM] = { -0.109864615, -0.00545889279, -0.0512907989, -0.0936995149, 0.145228133, 0.136148497, 0.082344763, 0.16194196, -0.0229825824, 0.116574578, -0.0256564897, -0.058733996, -0.14782922, -0.115881361, -0.139623746, 0.14362292, @@ -343,7 +343,7 @@ const float six_dense_biases[SIX_DENSE_NUM] = 0.161606282, -0.136956587, 0.0591680035, 0.117993973, -0.100358412, -0.0904804021, 0.161572158, 0.0794185847 }; -const float six_logit_weights[SIX_DENSE_NUM] NN_ALIGNED = +const float SIX_logit_weights[SIX_DENSE_NUM] NN_ALIGNED = { 0.0506259352, -0.0670735389, -0.0409830809, 0.0799648017, -0.0936499536, -0.122460753, 0.0720161647, -0.00714924932, 0.0374628901, -0.00931178033, -0.0230136961, 0.00667156279, 0.0823754966, -0.0555169284, -0.00904981792, 0.116692498, @@ -355,4 +355,4 @@ const float six_logit_weights[SIX_DENSE_NUM] NN_ALIGNED = -0.0314992517, 0.0338666737, 0.0178338587, -0.0309750885, -0.0261106789, -0.0142950565, 0.0768712908, -0.121748224 }; -const float six_logit_bias = -0.076127708; +const float SIX_logit_bias = -0.076127708; diff --git a/include/weights_6.h b/include/weights_6.h index d927748..be64253 100644 --- a/include/weights_6.h +++ b/include/weights_6.h @@ -23,10 +23,10 @@ #define NN_ALIGNED __attribute__((aligned(16))) -extern const float six_embedding[7]; -extern const float six_dense_weights[SIX_DENSE_NUM][SIX_INP_NUM] NN_ALIGNED; -extern const float six_dense_biases[SIX_DENSE_NUM]; -extern const float six_logit_weights[SIX_DENSE_NUM] NN_ALIGNED; -extern const float six_logit_bias; +extern const float SIX_embedding[7]; +extern const float SIX_dense_weights[SIX_DENSE_NUM][SIX_INP_NUM] NN_ALIGNED; +extern const float SIX_dense_biases[SIX_DENSE_NUM]; +extern const float SIX_logit_weights[SIX_DENSE_NUM] NN_ALIGNED; +extern const float SIX_logit_bias; #endif diff --git a/src/match.c b/src/match.c deleted file mode 100644 index 459fab5..0000000 --- a/src/match.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - match, one game of candidate weights against the candidate weights - - Copyright (C) 2026, tslil clingman - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with ctak. If not, see <https://www.gnu.org/licenses/>. -*/ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#include "actions.h" -#include "negamax.h" -#include "nn.h" -#include "tak.h" -#include "xorshift64.h" - -// a little gymnastics to insert candidate neural networks -#include "weights_5.h" -#include "weights_6.h" -#include "cand_weights_5.c" -#include "cand_weights_6.c" - -static inline float five_cand(tak_state_p state) { - static float cur_board[FIVE_INP_NUM] NN_ALIGNED; - - nn_prepare_input(cur_board, state, cand_five_embedding); - return eval_net(cur_board, FIVE_INP_NUM, &cand_five_dense_weights[0][0], - cand_five_dense_biases, cand_five_logit_weights, cand_five_logit_bias, - FIVE_DENSE_NUM, state->ply & 1 ? 1.0f : -1.0f); -} - -static inline float six_cand(tak_state_p state) { - static float cur_board[SIX_INP_NUM] NN_ALIGNED; - - nn_prepare_input(cur_board, state, cand_six_embedding); - return eval_net(cur_board, SIX_INP_NUM, &cand_six_dense_weights[0][0], - cand_six_dense_biases, cand_six_logit_weights, cand_six_logit_bias, - SIX_DENSE_NUM, state->ply & 1 ? 1.0f : -1.0f); -} - - -#define MAX_PLY 255 - -static tak_state_p state; - -void negamax_display_progress(const uint8_t cur_depth, - const uint8_t init_depth, - const uint32_t length) { - (void)(cur_depth); - (void)(init_depth); - (void)(length); -} - -// =================================================================== -// Game driver -// =================================================================== - -static int play_game(const nn_function current_fn, const nn_function cand_fn, - const enum COLOUR current_fn_colour, - const uint8_t random_opening_length) { - reset_state(state, state->board_size); - char ptn[16]; - - for (uint32_t ply = 0; ply + negamax_search_depth < MAX_PLY; ply++) { - if (ply < random_opening_length) { - uint32_t n_actions; - action_t *actions = actions_generate(state, &n_actions); - action_to_ptn(actions[rand32() % n_actions], ptn); - } else { - const nn_function fn = - (state->current_colour == current_fn_colour) ? current_fn : cand_fn; - negamax_set_evaluator(fn); - negamax_generate(state); - strcpy(ptn, negamax_ptn); - } - - const enum ACT_RESULT r = do_ptn(state, ptn); - if (r == GAME_END) - break; - if (r != ACT_OK) { - fprintf(stderr, "match: unexpected result %d for ptn %s\n", r, ptn); - return -2; - } - } - - switch (state->won) { - case WIN_DRAW: - return -1; - case WIN_FLAT_BLACK: - case WIN_ROAD_BLACK: - return C_BLACK; - case WIN_FLAT_WHITE: - case WIN_ROAD_WHITE: - return C_WHITE; - default: - // ply cap reached with no winner: a draw - return -1; - } -} - -void do_game(const uint8_t size, const uint8_t random_opening_length, const enum COLOUR current_fn_colour) { - state = new_tak_state(size); - negamax_init(size); - - const nn_function current_fn = - (size == 5) ? &five_nn_fn : &six_nn_fn; - const nn_function cand_fn = (size == 5) ? &five_cand : &six_cand; - - const int winner = play_game(current_fn, cand_fn, current_fn_colour, random_opening_length); - - const char *name; - if (winner == -1) - name = "draw"; - else if (winner == (int)current_fn_colour) - name = "current"; - else - name = "candidate"; - printf("%s %u\n", name, state->ply); - - negamax_free(); - free_tak_state(state); -} - - // =================================================================== - // Main - // =================================================================== - - const char *usage = - "match, one Tak game of the current weights against the candidate.\n\n\ -usage: match <size> <random_opening_length> <depth>\n\n\ -This binary is linked with both the include/weight_* files and the include/cand_weight_* files. It plays a single <size>x<size> game, with a random side choice and both sides using <random_opening_length> random moves at the start of the game. The result format is:\n\n\ -\t<current|candidate|draw> <plies>\n\n\ -nn_train.py runs many of these in parallel to score the candidate against the current weights.\n\n\ -Copyright (C) 2026, tslil clingman\n\n\ -This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version."; - -int main(int argc, char **argv) { - if (argc != 4) { - puts(usage); - return EXIT_FAILURE; - } - - const uint8_t size = (uint8_t)atoi(argv[1]); - const uint8_t random_opening_length = (uint8_t)atoi(argv[2]); - negamax_search_depth = (uint8_t)atoi(argv[3]); - - if (size != 5 && size != 6) { - fprintf(stderr, "match: size must be 5 or 6\n"); - return EXIT_FAILURE; - } - xors = ((uint64_t)time(NULL) ^ ((uint64_t)getpid() << 32)) * - 0x9E3779B97F4A7C15ULL + - 0xC0FFEE; - - do_game(size, random_opening_length, C_BLACK); - do_game(size, random_opening_length, C_WHITE); - - return EXIT_SUCCESS; -} diff --git a/src/nn_train.py b/src/nn_train.py index 0e08da7..2eb9b0c 100755 --- a/src/nn_train.py +++ b/src/nn_train.py @@ -35,6 +35,7 @@ from collections.abc import Iterator from dataclasses import dataclass +from math import log, ceil import argparse import concurrent.futures @@ -114,67 +115,43 @@ def td_lambda_targets( return targets -@dataclass(frozen=True) -class SelfPlayRecords: - positions: Tensor # [n, inp_dim] - game_ids: Tensor # [n] id of the game the position belongs to - results: Tensor # [n] final played result from black's perspective - terminals: Tensor # [n] true when the recorded position is a terminal leaf - terminal_values: Tensor # [n] exact value of a terminal leaf, otherwise 0 - parity_signs: Tensor # [n] ±1 converting the net's output to "absolute" perspective +@dataclass +class Performance: + win: int + loss: int + draw: int - @classmethod - def load_selfplay( - cls, fn: Path, size: int, device: torch.device - ) -> SelfPlayRecords: - # [net input] [game_id] [played result] [terminal flag] [leaf result] [parity sign] - df = pd.read_csv(fn, header=None) - inp_dim = NET_DIMS[size][0] - return cls( - positions=torch.tensor( - df.iloc[:, 0:inp_dim].to_numpy(dtype=np.float32), - dtype=torch.float32, - device=device, - ), - game_ids=torch.tensor( - df.iloc[:, inp_dim].to_numpy(dtype=np.int64), - device=device, - ), - results=torch.tensor( - df.iloc[:, inp_dim + 1].to_numpy(dtype=np.float32), - dtype=torch.float32, - device=device, - ), - terminals=torch.tensor( - df.iloc[:, inp_dim + 2].to_numpy(dtype=np.bool_), - dtype=torch.bool, - device=device, - ), - terminal_values=torch.tensor( - df.iloc[:, inp_dim + 3].to_numpy(dtype=np.float32), - dtype=torch.float32, - device=device, - ), - parity_signs=torch.tensor( - df.iloc[:, inp_dim + 4].to_numpy(dtype=np.float32), - dtype=torch.float32, - device=device, - ), - ) + def rate(self) -> float: + return float(self.win) / float(max(1, self.win + self.loss + self.draw)) - @classmethod - def load_merge( - cls, files: list[Path], size: int, device: torch.device - ) -> SelfPlayRecords: - sprs = [SelfPlayRecords.load_selfplay(file, size, device) for file in files] - return cls( - positions=torch.concat([spr.positions for spr in sprs]), - game_ids=torch.concat([spr.game_ids for spr in sprs]), - results=torch.concat([spr.results for spr in sprs]), - terminals=torch.concat([spr.terminals for spr in sprs]), - terminal_values=torch.concat([spr.terminal_values for spr in sprs]), - parity_signs=torch.concat([spr.parity_signs for spr in sprs]), - ) + def __str__(self) -> str: + width = ceil(log(max(1, self.win, self.loss, self.draw), 10)) + return f"+{str(self.win).zfill(width)}-{str(self.loss).zfill(width)}={str(self.draw).zfill(width)}" + + +@dataclass(frozen=True) +class CandidateRecords: + positions: list[Tensor] # [n, inp_dim] + game_ids: list[Tensor] # [n] + results: list[Tensor] # [n] + cand_results: list[Tensor] # [n] + terminals: list[Tensor] # [n] + terminal_values: list[Tensor] # [n] + parity_signs: list[Tensor] # [n] + + def performance(self) -> Performance: + result = Performance(0, 0, 0) + for game_id in torch.unique(self.game_ids): + in_game = self.game_ids == game_id + game_result = self.cand_results[in_game][0].item() + match game_result: + case 1: + result.win += 1 + case -1: + result.loss += 1 + case _: + result.draw += 1 + return result def make_training_data( self, model: Module, td_lambda: float @@ -201,6 +178,85 @@ class SelfPlayRecords: return self.positions, targets, self.parity_signs +@dataclass(frozen=True) +class PlayRecords: + positions: list[Tensor] # [candidate, n_i, inp_dim] + game_ids: list[Tensor] # [candidate, n_i] + results: list[Tensor] # [candidate, n_i] + cand_results: list[Tensor] # [candidate, n_i] + terminals: list[Tensor] # [candidate, n_i] + terminal_values: list[Tensor] # [candidate, n_i] + parity_signs: list[Tensor] # [candidate, n_i] + + def index(self, index: int) -> CandidateRecords: + return CandidateRecords( + positions=self.positions[index], + game_ids=self.game_ids[index], + results=self.results[index], + cand_results=self.cand_results[index], + terminals=self.terminals[index], + terminal_values=self.terminal_values[index], + parity_signs=self.parity_signs[index], + ) + + @classmethod + def load_selfplay(cls, fn, size): + df = pd.read_csv(fn, header=None) + inp_dim = NET_DIMS[size][0] + + fields = { + "parity_signs": df.iloc[:, 0].to_numpy(dtype=np.float32), + "positions": df.iloc[:, 1 : inp_dim + 1].to_numpy(dtype=np.float32), + "results": df.iloc[:, inp_dim + 1].to_numpy(dtype=np.float32), + "terminals": df.iloc[:, inp_dim + 2].to_numpy(dtype=np.bool_), + "terminal_values": df.iloc[:, inp_dim + 3].to_numpy(dtype=np.float32), + "game_ids": df.iloc[:, inp_dim + 4].to_numpy(dtype=np.int64), + "cand_results": df.iloc[:, inp_dim + 6].to_numpy(dtype=np.float32), + } + cand_ids = df.iloc[:, inp_dim + 5].to_numpy(dtype=np.int64) + + n_cands = int(cand_ids.max()) + 1 + gathered = {k: [] for k in fields} + for cid in range(n_cands): + mask = cand_ids == cid + for k, arr in fields.items(): + gathered[k].append(torch.from_numpy(arr[mask])) + + return cls(**gathered) + + @classmethod + def load_merge(cls, files: list[Path], size: int) -> PlayRecords: + sprs = [PlayRecords.load_selfplay(file, size) for file in files] + # for each field, gather [file0[i], file1[i], ...] for every index i + # and concat along dim 0 -> merged list indexed by cand id + return cls( + positions=[ + torch.concat(vals, dim=0) for vals in zip(*(s.positions for s in sprs)) + ], + game_ids=[ + torch.concat(vals, dim=0) for vals in zip(*(s.game_ids for s in sprs)) + ], + results=[ + torch.concat(vals, dim=0) for vals in zip(*(s.results for s in sprs)) + ], + cand_results=[ + torch.concat(vals, dim=0) + for vals in zip(*(s.cand_results for s in sprs)) + ], + terminals=[ + torch.concat(vals, dim=0) for vals in zip(*(s.terminals for s in sprs)) + ], + terminal_values=[ + torch.concat(vals, dim=0) + for vals in zip(*(s.terminal_values for s in sprs)) + ], + parity_signs=[ + torch.concat(vals, dim=0) + for vals in zip(*(s.parity_signs for s in sprs)) + ], + ) + + # =================================================================== # Network # =================================================================== @@ -225,7 +281,7 @@ class Net(Module): def fit( self, *, - self_play_records: SelfPlayRecords, + records: CandidateRecords, td_lambda: float, val_frac: float, epochs: int, @@ -233,9 +289,7 @@ class Net(Module): lr: float, ) -> tuple[float, float]: # data - positions, targets, parity_signs = self_play_records.make_training_data( - self, td_lambda - ) + positions, targets, parity_signs = records.make_training_data(self, td_lambda) n = len(positions) perm = torch.randperm(n, device=positions.device) n_val = max(1, int(n * val_frac)) @@ -258,7 +312,7 @@ class Net(Module): best_mse = float("nan") pbar = tqdm(range(epochs), desc="train", unit="ep") - for epoch in pbar: + for _ in pbar: self.train() order = torch.randperm(len(train_positions), device=positions.device) for start in range(0, len(train_positions), batch): @@ -295,13 +349,14 @@ class Net(Module): def to_c( self, + *, size: int, + id: int | None, path: Path, - performance: tuple[str, ...] = (), - cand: bool = False, + note: str, ) -> None: - prefix = ("cand_" if cand else "") + ("five" if size == 5 else "six") upper = "FIVE" if size == 5 else "SIX" + prefix = (f"cand_{id}_" if id is not None else "") + upper E = self.embedding.weight.detach().cpu().numpy() W = self.hidden.weight.detach().cpu().numpy() @@ -311,8 +366,7 @@ class Net(Module): with open(path, "w") as f: _ = f.write("/* generated by nn_train.py, do not edit by hand */\n") - for p in performance: - _ = f.write(f"/* {p} */\n") + _ = f.write(f"/* {note} */\n") _ = f.write(f'#include "weights_{size}.h"\n\n') _ = f.write( f"const float {prefix}_embedding[{len(E)}] =\n" @@ -338,7 +392,9 @@ class Net(Module): # =================================================================== -def fan_out(cmd: list[str], n: int, procs: int, tag: str, root: Path) -> Iterator[str]: +def fan_out( + cmds: list[list[str]], n: int, procs: int, tag: str, root: Path +) -> Iterator[str]: with concurrent.futures.ThreadPoolExecutor(max_workers=procs) as pool: futs = [ pool.submit( @@ -350,57 +406,32 @@ def fan_out(cmd: list[str], n: int, procs: int, tag: str, root: Path) -> Iterato text=True, ) for _ in range(n) + for cmd in cmds ] for fut in tqdm( - concurrent.futures.as_completed(futs), total=n, desc=tag, unit="game" + concurrent.futures.as_completed(futs), + total=n * len(cmds), + desc=tag, + unit="game", ): yield fut.result().stdout -def cand_copy_for(size: int, root: Path) -> None: +def cand_copy_for(size: int, id: int, root: Path) -> None: src = root / "include" / f"weights_{size}.c" if not src.is_file(): raise SystemExit(f"{src} not found; build a size-{size} champion first") - prefix = "five" if size == 5 else "six" - txt = src.read_text().replace(f"{prefix}_", f"cand_{prefix}_") - _ = (root / "include" / f"cand_weights_{size}.c").write_text(txt) - - -# =================================================================== -# Tournament -# =================================================================== - - -@dataclass(frozen=True) -class TournamentResult: - champ: int - cand: int - draws: int - - -def run_matches( - *, - depth: int, - games: int, - procs: int, - root: Path, - size: int, - match_random_opening_length: int, -) -> TournamentResult: - outs = list( - fan_out( - ["./match", str(size), f"{match_random_opening_length}", str(depth)], - games, - procs, - "match", - root, - ) - ) - winners = [line.split()[0] for line in outs if line.strip()] - champ = winners.count("current") - cand = winners.count("candidate") - draws = winners.count("draw") - return TournamentResult(champ=champ, cand=cand, draws=draws) + upper = "FIVE" if size == 5 else "SIX" + txt = src.read_text() + for sym in ( + "embedding", + "dense_weights", + "dense_biases", + "logit_weights", + "logit_bias", + ): + txt = txt.replace(f"{upper}_{sym}", f"cand_{id}_{upper}_{sym}") + _ = (root / "include" / f"cand_{id}_weights_{size}.c").write_text(txt) # =================================================================== @@ -408,120 +439,115 @@ def run_matches( # =================================================================== -def setup(size: int, root: Path) -> Net: +def setup(num_candidates: int, size: int, root: Path) -> list[Net]: inp_dim, hidden = NET_DIMS[size] - champ = Net(inp_dim, hidden) - champ.to_c( - size, - root / "include" / f"weights_{size}.c", - ("v000, random init",), - ) - cand_copy_for(6 if size == 5 else 5, root) - return champ + candidates = [Net(inp_dim, hidden) for _ in range(num_candidates)] + for id, cand in enumerate(candidates): + cand.to_c( + size=size, + id=id, + path=root / "include" / f"cand_{id}_weights_{size}.c", + note=f"{id=}, v000, random init", + ) + cand_copy_for(6 if size == 5 else 5, id, root) + return candidates def run_step( *, batch: int, - champ: Net, + candidates: list[Net], depth: int, epochs: int, games: int, iter: int, lr: float, - matches: int, - match_random_opening_length: int, min_ply: int, procs: int, - promote_rate: float, replay_iters: int, root: Path, size: int, td_lambda: float, val_frac: float, -) -> Net: - def make_csv(i: int) -> Path: +): + def csv_path(i: int) -> Path: return root / "data" / f"selfplay-{size}-v{i:03d}.csv" print(f"\n== iteration {iter} ==") + num_candidates = len(candidates) + cand_pairs = [ + (i, j) for i in range(num_candidates) for j in range(i + 1, num_candidates) + ] + # 1. rebuild - _ = subprocess.run(["make", "selfplay"], cwd=root, check=True, capture_output=True) - _ = subprocess.run(["make", "native"], cwd=root, check=True, capture_output=True) + for i, j in cand_pairs: + _ = subprocess.run( + ["make", f"selfplay-{i}-{j}"], cwd=root, check=True, capture_output=True + ) # 2. generate self-play data - csv = make_csv(iter) - print(f"selfplay: {size=}, {depth=}, {min_ply=}") + csv = csv_path(iter) + print(f"selfplay: {num_candidates=}, {size=}, {depth=}, {min_ply=}") out_rows: list[str] = [] for out in fan_out( - ["./selfplay", str(size), str(depth), str(min_ply)], + [ + [f"./selfplay-{i}-{j}", str(size), str(depth), str(min_ply)] + for (i, j) in cand_pairs + ], games, procs, "selfplay", root, ): out_rows.extend(out.splitlines()) + print("writing to", csv, "with", len(out_rows)) with open(csv, "w") as f: _ = f.write("\n".join(out_rows)) if out_rows: _ = f.write("\n") - # 3. fine-tune the champion on TD(lambda) targets -> candidate - device = next(champ.parameters()).device - csvs = [make_csv(i) for i in range(max(iter - replay_iters, 1), iter + 1)] + # 3. compute performance + csvs = [csv_path(i) for i in range(max(iter - replay_iters, 1), iter + 1)] print("Loading data from", [str(c) for c in csvs], "...", end=" ") - records = SelfPlayRecords.load_merge(csvs, size, device) - print(f"{records.results.shape[0]:,} rows") - cand = copy.deepcopy(champ) + records = PlayRecords.load_merge(csvs, size) + print("candidates have", [f"{r.shape[0]:,}" for r in records.results], "rows") + results = [ + (i, cand, records.index(i).performance()) for i, cand in enumerate(candidates) + ] - corr, mse = cand.fit( - self_play_records=records, - td_lambda=td_lambda, - val_frac=val_frac, - epochs=epochs, - batch=batch, - lr=lr, - ) - cand.to_c( - size, - root / "include" / f"cand_weights_{size}.c", - (f"v{iter:03d}, val_corr={corr:.4f}, val_mse={mse:.4f}",), - cand=True, - ) + for idx, _, perf in sorted(results, key=lambda t: t[2].rate(), reverse=True): + print(f"\t cand {idx:03d} {perf} {perf.rate() * 100.0:.2f}%") - # 4. build the match driver (champion + candidate) - _ = subprocess.run(["make", "match"], cwd=root, check=True, capture_output=True) - - promote = True - rate = -1.0 - if promote_rate > 0: - # 5. tournament + decision - print(f"match: {size=}, {match_random_opening_length=}, {depth=}") - tournament_result = run_matches( - depth=depth, - games=matches, - procs=procs, - root=root, - size=size, - match_random_opening_length=match_random_opening_length, - ) - decided = tournament_result.champ + tournament_result.cand - rate = tournament_result.cand / decided if decided else 0.0 - print( - f"champ {tournament_result.champ} - {tournament_result.cand} cand, {tournament_result.draws} draws, winrate={rate:.3f}" + # 4. fine-tune the champion on TD(lambda) targets -> candidate + for idx, cand in enumerate(candidates): + corr, mse = cand.fit( + records=records.index(idx), + td_lambda=td_lambda, + val_frac=val_frac, + epochs=epochs, + batch=batch, + lr=lr, ) - promote = decided >= int(0.25 * matches) and rate > promote_rate - - if promote: cand.to_c( - size, - root / "include" / f"weights_{size}.c", - (f"v{iter:03d}, val_corr={corr:.4f}, rate={rate:.4f}",), + size=size, + id=idx, + path=root / "include" / f"cand_{idx}_weights_{size}.c", + note=f"id={idx}, v{iter:03d}, val_corr={corr:.4f}, val_mse={mse:.4f}", ) - print(f"== candidate v{iter:03d} PROMOTED (include/weights_{size}.c) ==") - return cand - print(f"== candidate v{iter:03d} rejected ==") - return champ + + # 5. write champ + _, champ, perf = max(results, key=lambda t: t[2].rate()) + champ.to_c( + size=size, + id=None, + path=root / "include" / f"weights_{size}.c", + note=f"{iter=}, perf={str(perf)}", + ) + _ = subprocess.run(["make", "clean"], cwd=root, check=True, capture_output=True) + for i, j in cand_pairs: + (root / f"selfplay-{i}-{j}").unlink(missing_ok=True) + _ = subprocess.run(["make", "native"], cwd=root, check=True, capture_output=True) # =================================================================== @@ -551,14 +577,20 @@ def main() -> None: _ = p.add_argument( "--games", type=int, - default=1000, + default=100, help="selfplay games per iteration", ) _ = p.add_argument( + "--num-candidates", + type=int, + default=5, + help="number of distinct candidates to train", + ) + _ = p.add_argument( "--replay-iters", type=int, default=4, - help="number of previous self-play instances to mix in with current dataset during training", + help="number of previous data sources to retain", ) _ = p.add_argument( "--td-lambda", @@ -591,24 +623,6 @@ def main() -> None: help="fraction of rows held out for validation", ) _ = p.add_argument( - "--matches", - type=int, - default=200, - help="how many matches in a tournament", - ) - _ = p.add_argument( - "--match-random-opening-length", - type=int, - default=2, - help="length of random opening in a match", - ) - _ = p.add_argument( - "--promote", - type=float, - default=0.53, - help="candidate win rate among non-drawn matches needed to promote", - ) - _ = p.add_argument( "--procs", type=int, default=None, @@ -633,25 +647,22 @@ def main() -> None: args.procs = max(1, (os.cpu_count() or 1) // 2) (root / "data").mkdir(exist_ok=True) - champ = setup(size=args.size, root=root) + candidates = setup(num_candidates=args.num_candidates, size=args.size, root=root) - num_params = sum(p.numel() for p in champ.parameters() if p.requires_grad) + num_params = sum(p.numel() for p in candidates[0].parameters() if p.requires_grad) print(f"Number of trainable parameters: {num_params:,}") for iter in range(1, args.iters + 1): - champ = run_step( + run_step( batch=args.batch, - champ=champ, + candidates=candidates, depth=args.depth, epochs=args.epochs, games=args.games, iter=iter, lr=args.lr, - matches=args.matches, - match_random_opening_length=args.match_random_opening_length, min_ply=args.min_ply, procs=args.procs, - promote_rate=args.promote, replay_iters=args.replay_iters, root=root, size=args.size, diff --git a/src/selfplay.c b/src/selfplay.c index 42d82d2..f6736c0 100644 --- a/src/selfplay.c +++ b/src/selfplay.c @@ -30,25 +30,45 @@ #include "xorshift64.h" #ifndef RECORD_PV -#error "selfplay must be built with -DRECORD_PV (see the selfplay Makefile target)" +#error "selfplay must be built with -DRECORD_PV" #endif -#define MAX_PLY 255 -#define MAX_CELLS (6 * 6) +#ifndef CAND_A +#error "selfplay must be built with -DCAND_A=<id>" +#endif -static tak_state_p state; +#ifndef CAND_B +#error "selfplay must be built with -DCAND_B=<id>" +#endif + +#include CAND_A_WEIGHTS_5 +#include CAND_B_WEIGHTS_5 +#include CAND_A_WEIGHTS_6 +#include CAND_B_WEIGHTS_6 + +// sorry not sorry +#define STR2U(a, b) a##_##b +#define STR4U(a, b, c, d) a##_##b##_##c##_##d +#define STR4U_EXPAND(a, b, c, d) STR4U(a, b, c, d) +#define C(variant, size, suffix) STR4U_EXPAND(cand, STR2U(CAND, variant), size, suffix) +#define NETWORK(size, called) \ + static inline float STR2U(size, called)(tak_state_p state) { \ + static float cur_board[STR2U(size, INP_NUM)] NN_ALIGNED; \ + nn_prepare_input(cur_board, state, C(called, size, embedding)); \ + return eval_net(cur_board, STR2U(size, INP_NUM), &C(called, size, dense_weights)[0][0], \ + C(called, size, dense_biases), C(called, size, logit_weights), C(called, size, logit_bias), \ + STR2U(size, DENSE_NUM), state->ply & 1 ? 1.0f : -1.0f); \ + } -static float row_head[MAX_PLY][2]; -static uint8_t row_cells[MAX_PLY][MAX_CELLS]; -static uint8_t row_term[MAX_PLY]; -static float row_terminal_value[MAX_PLY]; -static float row_parity_sign[MAX_PLY]; -static uint32_t row_game_id[MAX_PLY]; -static uint32_t n_rows; +NETWORK(FIVE, A) +NETWORK(FIVE, B) +NETWORK(SIX, A) +NETWORK(SIX, B) -static uint32_t game_id_black; -static uint32_t game_id_white; +#define MAX_PLY 255 +#define MAX_CELLS (6 * 6) +static tak_state_p state; void negamax_display_progress(const uint8_t cur_depth, const uint8_t init_depth, @@ -58,30 +78,49 @@ void negamax_display_progress(const uint8_t cur_depth, (void)(length); } -static float win_value(const enum WIN_TYPE w) { +static int8_t win_value(const enum WIN_TYPE w) { switch (w) { case WIN_FLAT_BLACK: case WIN_ROAD_BLACK: - return 1.0f; + return 1; case WIN_FLAT_WHITE: case WIN_ROAD_WHITE: - return -1.0f; + return -1; default: - return 0.0f; + return 0; } } -static int play_game(const uint8_t min_ply) { +static int play_game(const uint8_t min_ply, const nn_function fn_1, + const nn_function fn_2, const uint32_t cand_id_1, + const uint32_t cand_id_2, + const uint32_t game_id, char record[][16], uint8_t replay) { + float row_head[MAX_PLY][2]; + uint8_t row_cells[MAX_PLY][MAX_CELLS]; + uint8_t row_term[MAX_PLY]; + float row_terminal_value[MAX_PLY]; + float row_parity_sign[MAX_PLY]; + uint32_t row_cand_id[MAX_PLY]; + int8_t row_mover_sign[MAX_PLY]; + uint32_t n_rows; + reset_state(state, state->board_size); n_rows = 0; char ptn[16]; for (uint32_t ply = 0; ply + negamax_search_depth < MAX_PLY; ply++) { if (ply < min_ply) { - uint32_t n_actions; - action_t *actions = actions_generate(state, &n_actions); - action_to_ptn(actions[rand32() % n_actions], ptn); + if (replay == 0) { + uint32_t n_actions; + action_t *actions = actions_generate(state, &n_actions); + action_to_ptn(actions[rand32() % n_actions], ptn); + strcpy(record[ply],ptn); + } else { + strcpy(ptn, record[ply]); + } } else { + const nn_function fn = (state->current_colour & 1) ? fn_1 : fn_2; + negamax_set_evaluator(fn); negamax_generate(state); strcpy(ptn, negamax_ptn); @@ -92,7 +131,8 @@ static int play_game(const uint8_t min_ply) { row_term[n_rows] = leaf->terminal; row_terminal_value[n_rows] = leaf->terminal_value; row_parity_sign[n_rows] = leaf->parity_sign; - row_game_id[n_rows] = state->current_colour == C_BLACK ? game_id_black : game_id_white; + row_cand_id[n_rows] = (state->current_colour&1) ? cand_id_1 : cand_id_2; + row_mover_sign[n_rows] = (state->current_colour&1) ? 1 : -1; n_rows++; } @@ -113,25 +153,25 @@ static int play_game(const uint8_t min_ply) { const uint8_t n_cells = state->board_size * state->board_size; // final outcome of the played game, from black's perspective - const float R = win_value(state->won); + const int8_t R = win_value(state->won); for (uint32_t k = 0; k < n_rows; k++) { - fprintf(stdout, "%.8f,%.8f,", row_head[k][0], row_head[k][1]); + fprintf(stdout, "%.1f,%.8f,%.8f,", row_parity_sign[k], row_head[k][0], row_head[k][1]); for (uint8_t c = 0; c < n_cells; c++) - fprintf(stdout, "%u,", (unsigned)row_cells[k][c]); - fprintf(stdout, "%u,%.0f,%u,%.0f,%.0f\n", row_game_id[k], R, - (unsigned)row_term[k], row_terminal_value[k], row_parity_sign[k]); + fprintf(stdout, "%u,", row_cells[k][c]); + fprintf(stdout, "%i,%u,%.0f,%u,%u,%i\n", R, row_term[k], row_terminal_value[k], game_id, row_cand_id[k], + row_mover_sign[k] * R); } return (int)n_rows; } const char *usage = - "selfplay, one game of asymmetric self-play training data.\n\n\ + "selfplay, one game of training data between candidates.\n\n\ Usage: selfplay <size> <depth> <min_ply>\n\n\ -Plays a single game of <size>x<size> self-play, with <min_ply> moves made randomly. Only the deterministic plies are written to stdout, one CSV row per recorded search, from ply <min_ply> onwards:\n\n\ -\tmover_flats,opponent_flats,<cell ids...>,game_id,R,terminal,leaf_R,parity_sign\n\n\ -nn_train.py runs many of these in parallel to generate training data.\n\n\ +Plays a single game of <size>x<size>, with <min_ply> moves made randomly. Only the deterministic plies are written to stdout, one CSV row per recorded search, from ply <min_ply> onwards:\n\n\ +\tparity_sign,mover_flats,opponent_flats,<cell ids...>,R,terminal,leaf_R,game_id,cand_id,cand_R\n\n\ +R is the outcome from black's perspective, cand_R the outcome from the recorded candidate's perspective. nn_train.py runs many of these in parallel to generate training data.\n\n\ Copyright (C) 2026, tslil clingman\n\n\ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version."; @@ -160,16 +200,27 @@ int main(int argc, char **argv) { // Processes launched in the same second must not share a seed xors = ((uint64_t)time(NULL) ^ ((uint64_t)getpid() << 32)) * - 0x9E3779B97F4A7C15ULL + - 0xC0FFEE; - - game_id_black = rand32(); - game_id_white = rand32(); + 0x9E3779B97F4A7C15ULL + + 0xC0FFEE; state = new_tak_state(size); negamax_init(size); - play_game(min_ply); + char record[min_ply][16]; + + play_game(min_ply, + size == 5 ? FIVE_A : SIX_A, size == 5 ? FIVE_B : SIX_B, + CAND_A, + CAND_B, + rand32(), + record, 0); + play_game(min_ply, + size == 5 ? FIVE_B : SIX_B, size == 5 ? FIVE_A : SIX_A, + CAND_B, + CAND_A, + rand32(), + record, 1); + negamax_free(); free_tak_state(state); |
