amling search program principles discussion / brain dump

For scripts to aid with computation or simulation in cellular automata.
amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 17th, 2026, 3:27 am

I've added --pre-partials to most normal search mains which captures (and allows changing) steps that run and display pattern bits before each expansion (these are the "unique", "first", "thinnest", and "random" partials). "--help" can show the default values, which differ by search mode.

I did a bunch of work to dust off wrap_hax, fixing all the disabled --filters options and wildly improving performance in ways that the one-bit-at-a-time changes unlocked. I've also sketched reworking it to operate via MDSE V2 (the "bit tree" stuff) and some very provisional benchmarking is suggesting it'll be maybe ~8-9x slower and use maybe ~4x less memory. Considering my most recent run of wrap_hax has been running for months, buried ~3.5 TB into swap and going nowhere on my fanciest machine (and hasn't so much as printed another log line for over 3 weeks now), I'm hopeful this might be useful.

We could also at this point pursue MDSE V2 for recentering or even a hypothetical MDSE V3 removing jcols entirely (presumably sketching for fixed board first similar to how MDSE V2 was done). Both of those are much, much larger undertakings which is the real reason I went after wrap_hax first.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 18th, 2026, 6:27 pm

I've sketched a rework of LLSSS's parsing of commandline string arguments into their complex in-memory counterparts. This includes a small expression language and a great deal of fun code to write, but for most users I suspect it would be little actual change if shipped.

With my local changes, places that take parts (things like "--ends") all now evaluate the expression language instead but they understand singletons in place of lists and parts with no arguments don't require parentheses to "call" and thus have unchanged syntax.

This means simple things like "--ends bg" work unchanged, but if you want arguments ("--ends 'pd_lite(2)'") or multiple values ("--ends '[bg, odd]'") it gets a little more complex.

The most likely visible changes to users would be...

(*) Fixed search bg magic grid takes an argument and so now "@bg:12" must be instead "@bg(12)". I think this is the only semi-common place requiring arguments or multiple values. I guess something like "--ends odd,even" having to be "--ends '[odd, even]'" is a distant second.

(*) Help is a little wonkier. Previously "--ends borked" would get help, but now it gets an expression language error about not knowing what "borked" is. I added "help" calls so "--ends help" (or even "--ends '[bg, help]'") will get help displayed. I suppose we could dump help on expression language errors, but it seems like it might be a little overzealous (like maybe not appropriate for simple syntax mistakes).

I'm hoping that going forward this would improve things for trying to write parts that take more complex data. As a quick example skew_gutter wants a list of integers but the existing framework is sort of limiting and can't do it. Now instead of "--ends skew_gutter:-1,skew_gutter:1" we could make "--ends 'skew_gutter([-1, 1])'") work.

If I had had this on day one I might have handled input grids differently and instead of burying special ones behind "@" ("magic grids"), it'd all be domain language and you'd have to write something like "file('1.in')" to load a file. This change I guess could still be made but it would obviously be quite disruptive and I suspect a little tedious.

In a more distant future we might even allow expression language steps and be able to implement something like custom state checkpointing logic or custom halting logic directly inline.

I will think on it some more, but my inclination is to ship it. I've pushed it to codeberg as 20260318-dl-15 in case anyone wants to poke around first.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 23rd, 2026, 3:19 am

I've sketched some very rough step-level integration with the custom expression language. For now it's hung on an extra "--extras" phase that goes at the end, although I'm imagining that we'd allow custom steps in any phase ("pre-partials", "filters", "partials", "ends", "halts", although "halts" would likely go away if this ships). As for some examples...

As it is right now you can checkpoint, both with custom conditions and custom path, e.g. here saving a new state file every w_pos. It sort of seems off by one since "Completed" logs the w_pos from when the round started and "$e.w_pos" gets the w_pos at the moment the custom step runs. Here "cb()" means a step with a custom expression language callback. Its single argument is a lambda which gets one argument which is the "environment" object available to such steps. "$e.w_pos" returns the integer w_pos and "$e.save_state(...)" checkpoints the state to a provided path. "str()" is a quick hack I sketched just for this to format an integer to a string. TBD adding something built in to the expression language itself for that.

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 06 --extras 'cb(^e $e.save_state("s-" + str($e.w_pos) + ".state"))'
...
20260322 23:58:01 [INFO] Start: save state to "s-7.state"
20260322 23:58:01 [INFO] Finish: save state to "s-7.state" -> took 182.991µs (195µs user, 18µs sys)
20260322 23:58:01 [INFO] Results: 0 normal
20260322 23:58:01 [INFO] Completed w_pos 6: 256 B, 18.838004ms
...
20260322 23:58:01 [INFO] Start: save state to "s-8.state"
20260322 23:58:01 [INFO] Finish: save state to "s-8.state" -> took 193.203µs (553µs user, 60µs sys)
20260322 23:58:01 [INFO] Results: 0 normal
20260322 23:58:01 [INFO] Completed w_pos 7: 1.22 KB [+131.91%], 19.993482ms [+5.95%]
...
You can also signal halt by return value which "halt()" can construct and Some/None Option constructors can indicate halt or not halt. Here again there is maybe some confusion about w_pos values. The last completed round is 13 -> 14 which prints "Completed w_pos 13" but then the next round is 14 -> 15 when the step at the end sees 15 and halts the search.

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 06 --extras 'cb(^e $e.w_pos >= 15 ? Some(halt("BAIL")) : None)'
...
20260323 00:01:42 [INFO] Completed w_pos 13: 4.70 KB [-19.25%], 25.156913ms [+5.16%]
...
20260323 00:01:42 [WARNING] Halting (reason: BAIL)...
20260323 00:01:42 [DEBUG] VmPeak: 2.32 GB
20260323 00:01:42 [DEBUG] Memory: total 5.51 KB (ss.old_gens 40 B, ss.cur_gen 1.17 KB, bcol 1.30 KB, col 2.98 KB, left_edge 8 B, right_edge 8 B)
20260323 00:01:42 [INFO] Last thinnest partial RLE:
...
Those are both actual completely working demos. Anything below this is speculation, although I think if we had our hearts set on it I could achieve the proposed syntaxes.

We might like to take over LLSSS_HALT_ON_ENDS in custom logic. Presumably it would be some method on $e to inquire if there had been any results and something like...

Code: Select all

$ rlife ... --extras 'cb(^e $e.has_ends() ? Some(halt("LLSSS_HALT_ON_ENDS")) : None)'
We'd definitely like to be able to change mid_steps. For this, hacking one settable configuration point in one way or another is easy, but deciding how to do it more generally is tricky. It might be something like a general mutable configuration store...

Code: Select all

$ rlife ... --extras 'cb(^e $e.w_pos >= 30 ? $e.set_config("mid_steps", 10) : ())'
...but maybe we'd also let you mark configurable places in other parts, something like...

Code: Select all

$ rlife ... --left-closure 'pd(configurable("pd_steps", 8))' --extras 'cb(^e $e.w_pos >= 30 ? $e.set_config("pd_steps", 4) : ())'
Finally, we might like to gate steps on conditions. Presumably you'd have a callback with access to $e returning a boolean and an inner step. I have especially wanted this for searches where the BG ends trigger extraneously in early positions. Probably something like...

Code: Select all

$ rlife ... --ends 'gated(^e $e.w_pos >= 20, bg)'
I've pushed the latest version of the sketch to codeberg as 20260323-dl-25 if anyone is interesting in poking around. Still TBD actually shipping it.


EDIT: I've sketched a little further, expanding to all phases and added gated_step, e.g. running bcaf only every 5 rounds:

Code: Select all

$ rlife llsss c3-f2b '@bg(10)' --filters 'gated_step(^e $e.w_pos % 5 == 0, bcaf)' | grep 'Completed\|LlsssFilterAgarCycleAvoiding'
20260323 00:54:46 [INFO] Start: compile step LlsssFilterAgarCycleAvoiding
20260323 00:54:46 [INFO] Finish: compile step LlsssFilterAgarCycleAvoiding -> took 203.715µs (1.003ms user, 0ns sys)
20260323 00:54:46 [INFO] Completed w_pos 6: 784 B, 31.491211ms
20260323 00:54:47 [INFO] Completed w_pos 7: 3.20 KB [+122.83%], 40.213156ms [+24.33%]
20260323 00:54:47 [INFO] Completed w_pos 8: 4.58 KB [+35.34%], 33.719469ms [-17.57%]
20260323 00:54:47 [DEBUG] LlsssFilterAgarCycleAvoiding: Filtered w_pos 10 bcols total: 270 -> 242 [-10.94%]
20260323 00:54:47 [DEBUG] LlsssFilterAgarCycleAvoiding: Filtered w_pos 10 cols total: 662 -> 522 [-23.65%]
20260323 00:54:47 [INFO] Completed w_pos 9: 7.06 KB [+42.68%], 53.016147ms [+44.50%]
20260323 00:54:47 [INFO] Completed w_pos 10: 11.43 KB [+47.23%], 35.914987ms [-38.46%]
20260323 00:54:47 [INFO] Completed w_pos 11: 18.29 KB [+46.16%], 38.132116ms [+5.99%]
20260323 00:54:47 [INFO] Completed w_pos 12: 13.43 KB [-30.64%], 50.02326ms [+26.98%]
20260323 00:54:47 [INFO] Completed w_pos 13: 12.02 KB [-11.05%], 44.443156ms [-11.81%]
20260323 00:54:47 [DEBUG] LlsssFilterAgarCycleAvoiding: Filtered w_pos 15 bcols total: 496 -> 496 [-]
20260323 00:54:47 [DEBUG] LlsssFilterAgarCycleAvoiding: Filtered w_pos 15 cols total: 802 -> 802 [-]
20260323 00:54:47 [INFO] Completed w_pos 14: 13.89 KB [+14.41%], 60.424589ms [+30.48%]
20260323 00:54:47 [INFO] Completed w_pos 15: 20.28 KB [+37.40%], 38.655637ms [-43.94%]
20260323 00:54:47 [INFO] Completed w_pos 16: 23.41 KB [+14.31%], 38.219945ms [-1.13%]
20260323 00:54:47 [INFO] Completed w_pos 17: 21.73 KB [-7.41%], 50.038595ms [+26.78%]
20260323 00:54:47 [INFO] Completed w_pos 18: 19.48 KB [-10.92%], 40.828086ms [-20.27%]
20260323 00:54:47 [DEBUG] LlsssFilterAgarCycleAvoiding: Filtered w_pos 20 bcols total: 464 -> 464 [-]
20260323 00:54:47 [DEBUG] LlsssFilterAgarCycleAvoiding: Filtered w_pos 20 cols total: 632 -> 632 [-]
...
I also added has_ends (some APIs changed slightly since earlier demo), e.g. faking LLSSS_HALT_ON_ENDS:

Code: Select all

$ rlife llsss 2c4-f2b '@bg(9)' --filters wcaf --halts 'cb_step(^e $e.has_ends() ? Some($e.halt("ENDS")) : None)'
...
20260323 00:59:35 [INFO] End (("LlsssEndsAgar", "zero")):
20260323 00:59:35 [INFO] |           |           | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... | ....*.... | ...***... |
20260323 00:59:35 [INFO] | ....*.... | ...***... | ...***... | ...*..*.. |
20260323 00:59:35 [INFO] | ...***... | ..*..*... | ...*.**.. | ...*..... |
20260323 00:59:35 [INFO] | ..**.*... | .....*... | ....***.. | ...*..... |
20260323 00:59:35 [INFO] | ..***.... | .....*... | ....**... | ....*.*.. |
20260323 00:59:35 [INFO] | ...**.... | ..*.*.... | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... |           |           |
20260323 00:59:35 [INFO] End (("LlsssEndsAgar", "zero")):
20260323 00:59:35 [INFO] |           |           | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... | ....*.... | ...***... |
20260323 00:59:35 [INFO] | ....*.... | ...***... | ...***... | ..*..*... |
20260323 00:59:35 [INFO] | ...***... | ...*..*.. | ..**.*... | .....*... |
20260323 00:59:35 [INFO] | ...*.**.. | ...*..... | ..***.... | .....*... |
20260323 00:59:35 [INFO] | ....***.. | ...*..... | ...**.... | ..*.*.... |
20260323 00:59:35 [INFO] | ....**... | ....*.*.. | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... | ......... | ......... |
20260323 00:59:35 [INFO] | ......... | ......... |           |           |
20260323 00:59:35 [WARNING] Halting (reason: ENDS)...
20260323 00:59:35 [DEBUG] VmPeak: 2.38 GB
20260323 00:59:35 [DEBUG] Memory: total 8.91 KB (ss.old_gens 464 B, ss.cur_gen 1.58 KB, bcols 2.67 KB, cols 4.20 KB)
20260323 00:59:35 [INFO] Last firstest partial RLE:
...
Still TBD configuration of mid_steps and such.

This cut is pushed to codeberg as 20260323-dl-27.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 25th, 2026, 1:51 pm

I've sketched a very ugly prototype of being able to change mid_steps on the fly. The above changes I'm reasonably happy with (modulo tutorial/UX issues with the breaking changes), but below here is still pretty unpolished.

The change adds a mutable configuration store, wraps recentering expansion's "mid_steps" in a reader for it and makes it visible to the domain language as "$cfg". With these changes you can then set mid_steps with something like...

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 10 --extras 'cb_step(^e ($e.w_pos == 15 ? ($e.log("DEBUG", "FIRING"), $cfg.set("mid_steps", Some(6))).1 : ()))' | grep 'FIRING\|Expanded.*window\|Completed'
...
20260325 10:13:26 [INFO] Completed w_pos 12: 42.05 KB [+40.23%], 37.889708ms [+28.95%]
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [r2l]: bcol 1 -> 36, frontier 1 -> 35, col 1 -> 36
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [l2r]: bcol 1 -> 36, frontier 1 -> 35, col 1 -> 36
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [r2l]: bcol 36 -> 195, frontier 35 -> 159, col 36 -> 195
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [l2r]: bcol 36 -> 191, frontier 35 -> 155, col 36 -> 191
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [l2r]: bcol 191 -> 617, frontier 155 -> 426, col 191 -> 915
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [r2l]: bcol 195 -> 668, frontier 159 -> 473, col 195 -> 978
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [l2r]: bcol 617 -> 1210, frontier 426 -> 593, col 915 -> 2344
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [r2l]: bcol 668 -> 1311, frontier 473 -> 643, col 978 -> 2523
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [l2r]: bcol 1210 -> 1691, frontier 593 -> 481, col 2344 -> 4036
20260325 10:13:26 [DEBUG] Expanded w_pos 13 window [l2r]: bcol 1691 -> 2226, frontier 481 -> 535, col 4036 -> 5467
20260325 10:13:26 [INFO] Completed w_pos 13: 58.79 KB [+33.19%], 41.348752ms [+8.73%]
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [r2l]: bcol 1 -> 43, frontier 1 -> 42, col 1 -> 43
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [l2r]: bcol 1 -> 46, frontier 1 -> 45, col 1 -> 46
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [r2l]: bcol 43 -> 238, frontier 42 -> 195, col 43 -> 238
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [l2r]: bcol 46 -> 243, frontier 45 -> 197, col 46 -> 243
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [r2l]: bcol 238 -> 913, frontier 195 -> 675, col 238 -> 1291
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [l2r]: bcol 243 -> 881, frontier 197 -> 638, col 243 -> 1252
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [l2r]: bcol 881 -> 1768, frontier 638 -> 887, col 1252 -> 3444
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [r2l]: bcol 913 -> 1713, frontier 675 -> 800, col 1291 -> 3473
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [r2l]: bcol 1713 -> 2430, frontier 800 -> 717, col 3473 -> 5555
20260325 10:13:26 [DEBUG] Expanded w_pos 14 window [r2l]: bcol 2430 -> 2989, frontier 717 -> 559, col 5555 -> 7359
20260325 10:13:26 [DEBUG] FIRING
20260325 10:13:26 [INFO] Completed w_pos 14: 78.52 KB [+28.74%], 43.109247ms [+4.17%]
20260325 10:13:26 [DEBUG] Expanded w_pos 15 window [r2l]: bcol 1 -> 58, frontier 1 -> 57, col 1 -> 58
20260325 10:13:26 [DEBUG] Expanded w_pos 15 window [l2r]: bcol 1 -> 58, frontier 1 -> 57, col 1 -> 58
20260325 10:13:26 [DEBUG] Expanded w_pos 15 window [r2l]: bcol 58 -> 318, frontier 57 -> 260, col 58 -> 318
20260325 10:13:26 [DEBUG] Expanded w_pos 15 window [l2r]: bcol 58 -> 306, frontier 57 -> 248, col 58 -> 306
20260325 10:13:26 [DEBUG] Expanded w_pos 15 window [l2r]: bcol 306 -> 1120, frontier 248 -> 814, col 306 -> 1609
20260325 10:13:26 [DEBUG] Expanded w_pos 15 window [r2l]: bcol 318 -> 1277, frontier 260 -> 959, col 318 -> 1817
20260325 10:13:26 [INFO] Completed w_pos 15: 5.57 KB [-173.50%], 35.1888ms [-20.23%]
20260325 10:13:26 [DEBUG] Expanded w_pos 16 window [r2l]: bcol 1 -> 32, frontier 1 -> 31, col 1 -> 32
20260325 10:13:26 [DEBUG] Expanded w_pos 16 window [l2r]: bcol 1 -> 32, frontier 1 -> 31, col 1 -> 32
20260325 10:13:26 [DEBUG] Expanded w_pos 16 window [r2l]: bcol 32 -> 111, frontier 31 -> 79, col 32 -> 111
20260325 10:13:26 [DEBUG] Expanded w_pos 16 window [l2r]: bcol 32 -> 111, frontier 31 -> 79, col 32 -> 111
20260325 10:13:26 [DEBUG] Expanded w_pos 16 window [r2l]: bcol 111 -> 203, frontier 79 -> 92, col 111 -> 376
20260325 10:13:26 [DEBUG] Expanded w_pos 16 window [l2r]: bcol 111 -> 203, frontier 79 -> 92, col 111 -> 376
20260325 10:13:26 [INFO] Completed w_pos 16: 6.62 KB [+17.18%], 23.247059ms [-40.87%]
...
That "--extras" argument is quite hairy, so let's break it down:

(*) "cb_step(...)" defines a step that is just calling a callback each time it runs. It gets passed an environment object that has various APIs on it.

(*) "^e (...)" constructs a lambda that will evaluate the inner expression each time it's called, binding the argument to "$e".

(*) "$e.w_pos == 15 ? ... : ()" will run the inner expression when w_pos is 15 and do nothing otherwise (evaluating to the unit "()").

(*) "(..., ...).1" will evaluate both expressions, constructing a 2-tuple, then return the value of the second. The expression language wasn't really designed for normal imperative programming so this sort of wangling may occasionally be necessary.

(*) '$e.log("DEBUG", "FIRING")' invokes the "log" method on the environment, printing out an annotated log entry with "FIRING" as the message. This isn't necessary but it makes it easier to see in the output where it was run.

(*) '$cfg.set("mid_steps", Some(6))' sets the "mid_steps" key. As "mid_steps" has rust type "Option<usize>" it is necessary to wrap 6 up in "Some(...)". Unlimited steps could be set with "None".

It's possible that some time in the future we would augment various parts with the ability to take configuration store readers instead of values and so you might some day be able to do something like '--left-closure "pd(2, $cfg.register("left_pd_steps", Some(4)))"' and then later somewhere in a callback step do '$cfg.set("left_pd_steps", Some(5))'. Unfortunately I can't quite figure out how to make this pleasant in the code so I haven't done it. The essential problem is you want to still be able to do "pd(2, Some(4))" as well and so the "pd()" constructor needs to be overloaded to take either "Option<usize>" or "reads-from-cfg-and-returns-Option<usize>". I can do this, but I can't think of a nice way to avoid having to register two completely separate constructors.

This cut is pushed to codeberg as 20260325-dl-34.



So what now? How do we ship this, especially with regards to users and/or the tutorial? At the risk of anchoring any discussion, my inclination is mostly to just ship it all more or less as written and get it baking. We would of course update the syntax in the tutorial, and likely include some note somewhere about the syntax having changed, mentioning the date on which it changed, presumably wherever we think poor souls confused about "@bg:N" versus "@bg(N)" are most likely to land. I think we could probably also include a specific check for fixed board magic grid strings of "@bg:N". Right now they will crash with a completely accurate but questionably useful parse error ("Error: Unrecognized token `:` found at 2:3"). I think including a temporary (i.e. I will plan to delete it in maybe 6 months or a year) quick regex match and custom error message is a reasonable trade of minor code burden for usability.

If we don't think of anything better within the next few days I will likely pull the trigger (pushing the changes and then making the wiki edits, unilaterally, as best I can). If y'all've got any last ideas or preferences about how it all goes down, now would be the time.

User avatar
Sylvani
Posts: 146
Joined: September 26th, 2024, 3:23 am

Re: amling search program principles discussion / brain dump

Post by Sylvani » March 27th, 2026, 9:53 am

I tried out the latest branch, and I seem to get this error (Command and whole log below):

Code: Select all

$ LLSSS_HALT_ON_ENDS=true LLSSS_MAX_TABLE_SIZE=23 ./rlife llsss --rule 'B2/S' c2-f2b '@bg(10)' --ends 'gated(^e $e.w_pos >= 20, bg)' | tee log.txt
20260327 08:51:33 [INFO] state init: 1 calls, 785.688µs (1.284ms user, 1.549ms sys) own time, 1.888955ms (2.135ms user, 2.659ms sys) total time
20260327 08:51:33 [INFO] state init/filter clean/bcol flags r2l: 8 calls, 248.725µs (68µs user, 634µs sys) own time, 248.725µs (68µs user, 634µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean: 1 calls, 238.751µs (99µs user, 141µs sys) own time, 1.103267ms (851µs user, 1.11ms sys) total time
20260327 08:51:33 [INFO] state init/filter clean/filter jcol/xmap: 16 calls, 212.441µs (146µs user, 66µs sys) own time, 212.441µs (146µs user, 66µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean/bcol flags l2r: 8 calls, 196.657µs (425µs user, 174µs sys) own time, 196.657µs (425µs user, 174µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean/filter jcol: 8 calls, 124.41µs (87µs user, 37µs sys) own time, 336.851µs (233µs user, 103µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean/filter bcol: 9 calls, 50.881µs (4µs user, 47µs sys) own time, 50.881µs (4µs user, 47µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean/spine store gc: 1 calls, 27.816µs (19µs user, 9µs sys) own time, 27.816µs (19µs user, 9µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean/ss mark: 1 calls, 1.806µs (1µs user, 1µs sys) own time, 1.806µs (1µs user, 1µs sys) total time
20260327 08:51:33 [INFO] state init/filter clean/ssp rewrite: 1 calls, 1.78µs (2µs user, 1µs sys) own time, 1.78µs (2µs user, 1µs sys) total time
20260327 08:51:33 [INFO] Total: 10.616937ms (25.692ms user, 8.814ms sys)
20260327 08:51:33 [INFO] Done
Error: CompileError: TypeError: No resolutions left at all for: Some(Name("gated"))(ArgBag(TypeTerm(Function(TypeTerm(Variable(LambdaArg(SiteId(1), 0))), TypeTerm(Leaf(TypeTermLeaf(bool))))), TypeTerm(Variable(Site(SiteId(6)))))) -> TypeTerm(Variable(Site(SiteId(0))))
I've tried copying one of your commands but it still doesn't work right.

Code: Select all

$ ./rlife llsss-recentering-wao c3-f2b '@bg' 06 --extras 'cb(^e $e.w_pos >= 15 ? Some(halt("BAIL")) : None)'
20260327 08:52:53 [INFO] WAO error window #0 (included):
20260327 08:52:53 [INFO] |       |       | ZZZZZ |
20260327 08:52:53 [INFO] | ..... | ..... | ..... |
20260327 08:52:53 [INFO] | ..... | ..... | ..... |
20260327 08:52:53 [INFO] | ..xWW |       |       |
20260327 08:52:53 [INFO] state init: 1 calls, 1.109881ms (3.249ms user, 517µs sys) own time, 1.109881ms (3.249ms user, 517µs sys) total time
20260327 08:52:53 [INFO] Total: 8.521437ms (25.913ms user, 4.395ms sys)
20260327 08:52:53 [INFO] Done
Error: CompileError: TypeError: No resolutions left at all for: Some(Name("cb"))(ArgBag(TypeTerm(Function(TypeTerm(Variable(LambdaArg(SiteId(1), 0))), TypeTerm(Variable(Site(SiteId(2)))))))) -> TypeTerm(Variable(Site(SiteId(0))))
EDIT: Nevermind, I understand why it's happening and I fixed the error.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 27th, 2026, 10:55 am

Sylvani wrote:
March 27th, 2026, 9:53 am
I tried out the latest branch, and I seem to get this error...

Code: Select all

Error: CompileError: TypeError: No resolutions left at all for: Some(Name("gated"))(ArgBag(TypeTerm(Function(TypeTerm(Variable(LambdaArg(SiteId(1), 0))), TypeTerm(Leaf(TypeTermLeaf(bool))))), TypeTerm(Variable(Site(SiteId(6)))))) -> TypeTerm(Variable(Site(SiteId(0))))
That is a very bad and very long way of the compiler saying that "gated" isn't right. If (when?) this ships it will definitely be on my radar to try to improve the expression language from crazy prototype I wrote just to see if I could to something maybe a little less unusable. Hopefully this particular case would say there is no known function "gated" (and ditto no known function "cb" for the other). The problem here is I renamed them to "gated_step" and "cb_step" somewhere during development. Even if I improve the errors to hopefully more clearly convey what they do know I am not sure how best to document or make discoverable what domain language stuff exists.

As of the latest branch (20260325-dl-38, just pushed) there are...

(*) "$e.log(<string>, <string>)" - first is level name (e.g. "DEBUG")
(*) "$e.w_pos"
(*) "$e.subtile_pos"
(*) "$e.save_state(<string>)"
(*) "$e.has_ends()"
(*) "$e.halt(<string>)" - an object indicating to halt, needs to be returned from cb_step, wrapped in "Some(...)".
(*) "cb_step(^e ...)"
(*) "gated_step(^e ..., ...)"
(*) "$cfg.set(<string>, <Option<usize>>)" - only "mid_steps" in recentering for the moment

User avatar
Sylvani
Posts: 146
Joined: September 26th, 2024, 3:23 am

Re: amling search program principles discussion / brain dump

Post by Sylvani » March 27th, 2026, 12:51 pm

amling wrote:
March 27th, 2026, 10:55 am
As of the latest branch (20260325-dl-38, just pushed) there are...

(*) "$e.log(<string>, <string>)" - first is level name (e.g. "DEBUG")
(*) "$e.w_pos"
(*) "$e.subtile_pos"
(*) "$e.save_state(<string>)"
(*) "$e.has_ends()"
(*) "$e.halt(<string>)" - an object indicating to halt, needs to be returned from cb_step, wrapped in "Some(...)".
(*) "cb_step(^e ...)"
(*) "gated_step(^e ..., ...)"
(*) "$cfg.set(<string>, <Option<usize>>)" - only "mid_steps" in recentering for the moment
Would you be willing to add a way to get the mid_steps value? The purpose of this is to have the value increase over time, something like:

Code: Select all

--extras 'cb_step(^e ($e.w_pos % 20 == 0 ? $cfg.set("mid_steps", Some($cfg.get("mid_steps") + 1)) : ()))'

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 27th, 2026, 1:32 pm

amling wrote:
March 27th, 2026, 10:55 am
Hopefully this particular case would say there is no known function "gated"...
I've cleaned up the error messages slightly to try to make them less unreadable. A non-existent call gets:

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 10 --extras 'cb(^e ())'
...
Error: CompileError: ResolutionExhausted: There is no library entry at all for method "cb"
...
Argument shape failures similarly hopefully a little better:

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 10 --extras 'cb_step("too", "many", "args")'
...
Error: CompileError: ResolutionExhausted: There is no library entry with matching arg shape for method "cb_step": (?, ?, ?)
...
Ditto argument types, although debugging where exactly it all went wrong is probably still going to be no fun:

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 10 --extras 'cb_step(^e "bad return type")'
...
Error: CompileError: ResolutionExhausted: The library has no call matching types for method "cb_step": ((#0 -> str)) -> #1
...
Sylvani wrote:
March 27th, 2026, 12:51 pm
Would you be willing to add a way to get the mid_steps value?
For sure. I am very interested in what people want to do with this sort of stuff and while adding API surface is probably always going to have to come back to me, I have made it pretty easy to add more and with relatively little burden on most of the rest of the codebase.

I've sketched "$cfg.get()", only for Option<usize> for now. You can use ".unwrap()" to get the usize out of the option (and crash if it's none), e.g.:

Code: Select all

$ rlife llsss-recentering-wao c3-f2b '@bg' 10 --extras 'cb_step(^e $e.log("DEBUG", "mid_steps is " + str($cfg.get("mid_steps").unwrap())))'
...
20260327 10:14:39 [DEBUG] [DL] mid_steps is 10
...
Something like either of these can increment (the former crashes on none, the latter passes it back through):

Code: Select all

$cfg.set("mid_steps", Some($cfg.get("mid_steps").unwrap() + 1))
$cfg.set("mid_steps", $cfg.get("mid_steps").map(^n $n + 1))
Although I foresee a problem with type inference on the latter once I add other get/set types. Once there is ambiguity for all of get, set, and map (there is also a "map" for list) it's not gonna be able to figure it out. Unfortunately I am not actually a compiler engineer and while I have some ideas, building a type system is sort of out of scope for this forum anyway. Most likely I will give up and split get/set by type so it will be get_int, get_str, get_opt_int, get_opt_str, etc. The slight verbosity is probably even worth it just for the clarity of error when it all goes wrong.

I've pushed the current sketch to codeberg as 20260327-dl-39.

User avatar
Sylvani
Posts: 146
Joined: September 26th, 2024, 3:23 am

Re: amling search program principles discussion / brain dump

Post by Sylvani » March 29th, 2026, 1:36 pm

Are you planning on adding a way to dump every partial or result from an LLSSS state file? I want to have something like an "llsss_stdin" symmetry on Catagolue.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » March 29th, 2026, 4:22 pm

Sylvani wrote:
March 29th, 2026, 1:36 pm
Are you planning on adding a way to dump every partial or result from an LLSSS state file? I want to have something like an "llsss_stdin" symmetry on Catagolue.
I can't quite work out what you're asking for, neither from reading the feature request nor the motivation.

On the motivation side I don't really know anything about Catagolue other than it's some place people dump random soup evolution stats and maybe also it stores patterns under canonical names and we then link that from the wiki. I think you're maybe asking about somehow dumping patterns out from LLSSS searches into some form of analyzer and/or catalogue uploader. I assume "'llsss_stdin' symmetry" would mean more to others but I'm just so very far out of these loops.

On the feature request side, I can't make my interpretation of what you're asking for at face value make sense. Is "a way" a separate command that inputs an honest-to-goodness, serialized-to-disk state file? Or like a step you'd include during searches? Either way there are issues with "every partial" and "[every] result".

Disk state files don't have any notion of result per se and in-memory state keeps results to the side in its own little hole just to print out stats every round and at the end. Even then, they're really just some numberic stats as there isn't really any unified format for them between all the variations in search mode (fixed board, recentering, wrap_hax) and behaviours of ends (consider things as wild as pd_lite, edbv3, or maxpop).

"Every partial" is somewhere between exponentially improbable and strictly impossible. The core magic of lsss as I understand it (taken for LLSSS) is storing partials as only the strips that make them up and thus allowing severe deduplication. In the case of LLSSS recentering mode it's even possible for a state file to contain a U cycle thereby representing an infinite collection of partials (sort of like how a regular expression can match an infinite number of strings).

I recognize that these details are far, far down the rabbit hole of complex LLSSS implementation details, but unfortunately that is where any hypothetical tool would have to go. It might be best for you to try to expand on your motivation and what you'd do with this or how you'd use it if it were written.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » April 3rd, 2026, 2:02 pm

I've just pushed the DL rewrites. For the most part it works as shown above although I put a great deal of effort into making the DL error messages less bad (success debatable). Of course if you get stuck trying to do something with it let me know (can't figure out error, need more API surface, etc.). Even if you don't get stuck it might still be worth chiming in here for brainstorming and/or so I don't break or remove features people are relying on.

I'm off to edit the wiki next. More details below about where things ended up ultimately.



I kept it as "cb_step" and "gated_step", e.g.:

Code: Select all

--extras 'cb_step(^e $e.log("DEBUG", "yay"))'
--ends 'gated_step(^e $e.w_pos >= 20, bg)'
For now, old syntax fixed board magic grids are specifically caught:

Code: Select all

$ rlife llsss p1 '@bg:12'
...
Error: The syntax for fixed board bg magic grids has changed with "@bg:NN" becoming "@bg(NN)" so presumably you want "@bg(12)".
...
Old syntax lists get a parse error:

Code: Select all

$ rlife llsss-recentering-wao p1 '@bg' 06 --ends 'odd,even'
...
Error: ParseError: UnrecognizedToken: Expected: (none)

In <anonymous>, at line 1, col 4:
   > odd,even
        ^
...
Errors resolving calls will show all available calls of the same name:

Code: Select all

$ rlife llsss-recentering-wao p1 '@bg' 06 --ends 'odd(7)'
...
Error: CompileError: ResolutionExhausted: There is no library entry at all for method "odd"

In <anonymous>, at line 1, col 1:
   > odd(7)
     ^^^^^^

Available "odd" calls:
   odd -> step

...
Or if there are none with the same name, it will show the entire library of calls, although this is a pretty big, unreadable mess at the moment:

Code: Select all

$ rlife llsss-recentering-wao p1 '@bg' 06 --ends 'ohno()'
...
Error: CompileError: ResolutionExhausted: There is no library entry at all for method "ohno"

In <anonymous>, at line 1, col 1:
   > ohno()
     ^^^^^^

All available calls:
   Some(#0) -> Option<#0>
   agar(str) -> step
   cb_step(Function<LlsssDlStepEnv, ()>) -> step
   cb_step(Function<LlsssDlStepEnv, Option<LlsssDlStepHalt>>) -> step
...
   nbr / nbr -> nbr
   nbr % nbr -> nbr
   -nbr -> nbr
   !bool -> bool

...
You can see somewhere in that wretched dump e.g. the four distinct ways to use cb_step (with or without name, with or without halt-indicating return):

Code: Select all

cb_step(Function<LlsssDlStepEnv, ()>) -> step
cb_step(Function<LlsssDlStepEnv, Option<LlsssDlStepHalt>>) -> step
cb_step(str, Function<LlsssDlStepEnv, ()>) -> step
cb_step(str, Function<LlsssDlStepEnv, Option<LlsssDlStepHalt>>) -> step
Or how you might construct an "Option<LlsssDlStepHalt>" from that "LlsssDlStepEnv" you get:

Code: Select all

LlsssDlStepEnv.halt(str) -> LlsssDlStepHalt
LlsssDlStepEnv.halt(str, str) -> LlsssDlStepHalt
Some(#0) -> Option<#0>
None -> Option<#0>
I did leave "help" in as it's somewhat more useful than the arbitrary library call dumping above (showing only specifically step constructions and knowing argument names), although you have to survive type inference for it to actually get evaluated and trigger:

Code: Select all

$ rlife llsss-recentering-wao p1 '@bg' 06 --ends '[help, 7]'
...
Error: CompileError: TypeError: Type mismatch: expected step, observed nbr

In <anonymous>, at line 1, col 8:
   > [help, 7]
            ^
...
$ rlife llsss-recentering-wao p1 '@bg' 06 --ends 'help'
...
Available implementations of ends:
   default
   bg
   edbv3(db_file[str])
   edbv4(db_file[str])
   even
   odd
   gse
   gso
   skew_gutter(skew[isize])
   pd(division[isize])
   pd(division[isize], w_size[usize])
   pd_lite(division[isize])
   pd_lite(division[isize], w_size[usize])
   pd_rotor_tree(division[isize])
   s_periodic(sx[isize], sy[isize], st[isize])
   regex(grid_file[str])
   agar(agar[str])
   proj001_s1(w_start[usize], w_size[usize], u_size[usize], blocks_file[str])
   proj001_s2(w_size[usize], u_size[usize])
   proj001_s2(w_size[usize], u_size[usize], out_file[str])
   slices(slices_file[str])
   proj002(w_start[usize], w_size[usize], u_size[usize], blocks_file[str])
   proj003(w_start[usize], w_size[usize], blocks_file[str])
   none

...
The "mid_steps" stuff got included, although I would consider it very much subject to change:

Code: Select all

--extras 'cb_step(^e $cfg.set("mid_steps", $cfg.get("mid_steps").map(^n $n + 1)))'
Especially in the future it might become "get_opt_usize" and/or require some amount of ".as()" type annotations to infer. I almost certainly won't break it without some discussion here.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » April 4th, 2026, 11:52 am

I sketched a very quick and dirty prototype to do skew gutter edges. This can find things like...

Code: Select all

$ rlife llsss-recentering-wao --rule 'B2/S' c4-f2b '@bg' --left-edge 'skew_gutter(1)' 12
...
20260404 08:32:24 [INFO] Thinnest partial:
20260404 08:32:24 [INFO] |                 |                 |                 | ZZZZZZZZZZZZZZZ |
20260404 08:32:24 [INFO] | ............... | ............... | ............... | ............... |
20260404 08:32:24 [INFO] | ............... | ............... | ............... | ............... |
20260404 08:32:24 [INFO] | ..*............ | ...*........... | ..*............ | .*.*........... |
20260404 08:32:24 [INFO] | ....*.......... | ...*.*......... | ..*............ | .*..*.......... |
20260404 08:32:24 [INFO] | .....*..*...... | ....*....*..... | ...*.*..*...... | ..*.*..*.*..... |
20260404 08:32:24 [INFO] | ..........*.... | .........*.*... | ........*...... | ..**.***..*.... |
20260404 08:32:24 [INFO] | ...........*... | ..........*.... | ...*.*...*.*... | ..*...*.*.*.... |
20260404 08:32:24 [INFO] | .*............. | ..*.*.*........ | .*...*......... | ...*......*.... |
20260404 08:32:24 [INFO] | .*..***........ | ..**........... | .*..**......... | ..**..*...*.... |
20260404 08:32:24 [INFO] | ....**......... | ..........*.... | ....*....*.*... | .**...*.*...*.. |
20260404 08:32:24 [INFO] | ....*....*.*... | ...*......*.... | ..*..*...*.*... | .*..*.*........ |
20260404 08:32:24 [INFO] | ............... | ...***......... | ..*....*.***... | .*.*..*........ |
20260404 08:32:24 [INFO] | ....*...**..... | .....***..*.... | ...........*... | ........**..... |
20260404 08:32:24 [INFO] | .....*.*..*.... | ....*.*....*... | ............*.. | ...**......*... |
20260404 08:32:24 [INFO] | ........***.... | ...........*... | ...**.......... | ............... |
20260404 08:32:24 [INFO] | ...*.****...... | ....*......*... | ............... | .....*.**...... |
20260404 08:32:24 [INFO] | ......*..**.... | ...........*... | ....*..**...*.. | .........*.*... |
20260404 08:32:24 [INFO] | ..**........*.. | .....***.*..... | ..........*.... | .*.***..**..*.. |
20260404 08:32:24 [INFO] | ......*....*... | ........*...... |                 |                 |
...
You can see some interesting interactions on the left edge showing some of the ways Seeds patterns can support/suppress themselves.

Unfortunately it's going to be tricky to get the corner conditions right and I'm not (yet) sure of anything I would actually use it to search for. Consider e.g. p1 search. If you are searching with a shift of one and your top start is (the outer "..."s are ellipses while the inner "." is dead gutter)...

Code: Select all

| .ABC... |
| .DEF... |
...then what are the conditions on A and D? We imagine this to mean:

Code: Select all

| ...CBA.       |
| ...FED.ABC... |
|       .DEF... |
After the search extends a row we'd have checked (sort of, it's complicated as we only check new neighborhoods, but for the essential problem this detail doesn't matter):

Code: Select all

| ...CBA.       |
| ...FED.ABC... |
| ...IHG.DEF... |
|       .GHI... |
In particular this one neighborhood was neither checked (since we don't know the NE cell), nor really part of your initial conditions (which didn't include G):

Code: Select all

| A.  |
| D.A |
| G.D |
This suggests to me that we would want to require your initial conditions to be one taller although probably more complicated for arbitrary geometry. In the case of a search from all zeros this one neighborhood isn't going to matter as only B1C could be triggered there (or I suspect in any place analogous to it even in other geometries?).

I've pushed the prototype to codeberg as 20260404-skew-gutter-edge-04. Unclear if I'll get around to figuring out cleaning it up and releasing it properly.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » April 5th, 2026, 2:04 pm

I reworked the skew_gutter prototype to work under somewhat more general conditions. It requires that the VW plane be the YT plane (this is checked) and that your rule be X symmetric (this is not checked), but as long as those two are true it should be fine. Big AF2, small AF2, doubled U geometries, slanted U geometries, left edge, right edge, both, etc. The checks are still done in a pretty lazy way so performance isn't what it could be, but I suspect it won't matter. Correctness at initialization is still left entirely to operator (i.e. use longer grids if it matters). Usage is as it was above, e.g. "--left-edge 'skew_gutter(1)'").

Pushed to codeberg just now as 3113b31a7f88.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » April 8th, 2026, 9:22 pm

I just discovered that there has been a bug in a few uncommon ends for about a month. EDBV3, EDBV4, PD, regex, and slices have all been ignoring (skipping) the left edge columns when analyzing due to a mistake in some of the refactoring I did for the MDSE V2 ends stuff. Even when using these ends, the vast majority of searches are going to see no difference (i.e. the edge is all zeros and the configuration of the ends are effectively invariant under stripping zeros).

I've fixed it and pushed the fix, although it seems very unlikely to have been reached by anyone but me (and I think I've only reached it in some semi-weird nonzero edge picture searches that had EDBV3 configured and then got weird false positives).

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » April 13th, 2026, 2:18 am

Ugh, it's been a tough week for LLSSS development. I have discovered a bug in ACAF/BCAF that caused them to fire early in multi-bit tile geometries and generally incorrectly truncate state. There is no problem for single-bit tile geometries, which is pretty much just KcN-f2b / KcN-b2f for gcd(K, N) = 1. I do not believe WCAF is subject to the same bug, nor is recentering's WAO search mode.

Nearly all of my exhaustion projects have been done with WAO and I believe nearly all the remainder have been done with special starting conditions (rather than any *CAF filter). The only straggler I could find was a c/5 project, but it was f2b and c5-f2b geometry is not subject to the bug.

I've just now pushed the fixes.

AforAmpere
Posts: 1404
Joined: July 1st, 2016, 3:58 pm

Re: amling search program principles discussion / brain dump

Post by AforAmpere » May 13th, 2026, 2:11 am

Code: Select all

./rlife llsss-recentering-wao --rule 'B2-a3-i45678/S0123-a45-i678' --ends [odd,even,none] --filters bcaf 2c8-s2s '@bg' 8
This seems to crash for me on the latest master version.

Here is the backtrace:

Code: Select all

thread 'main' (6269) panicked at src/table/engine.rs:314:9:
assertion failed: next_idx <= AD::BIT_SIZE
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
   1: core::panicking::panic_fmt
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:80:14
   2: core::panicking::panic
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:150:5
   3: rlife::table::engine::compute_checks
   4: <rlife::table::engine::TableEngineChecks3<AD> as rlife::table::engine::TableEngine>::compile
             at /mnt/c/wsl/rust/rlife/rlife-master/src/table/engine.rs:449:18
   5: rlife::precomp::C1Env::compile_table_common
             at /mnt/c/wsl/rust/rlife/rlife-master/src/precomp.rs:138:12
   6: rlife::precomp::C1Env::compile_table
             at /mnt/c/wsl/rust/rlife/rlife-master/src/precomp.rs:167:24
   7: <rlife::llsss::ends::sym::LlsssEndsReflect as core::convert::Into<rlife::llsss::step::LlsssStep<TB,CST>>>::into::{{closure}}::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/ends/sym.rs:171:38
   8: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &mut F>::call_once
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:310:21
   9: core::option::Option<T>::map
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/option.rs:1165:29
  10: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::next
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/iter/adapters/map.rs:107:26
  11: <ars_core::tryy::ErrorTrackingIter<IT> as core::iter::traits::iterator::Iterator>::next
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/tryy.rs:85:25
  12: <&mut I as core::iter::traits::iterator::Iterator>::next
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/iter/traits/iterator.rs:4226:18
  13: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/spec_from_iter_nested.rs:24:41
  14: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/spec_from_iter.rs:33:9
  15: <alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/mod.rs:3865:9
  16: ars_core::ext::iter::ArsExtIterator::tryy_collect::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/ext/iter.rs:59:22
  17: ars_core::tryy::tryy_with_iter
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/tryy.rs:104:13
  18: ars_core::ext::iter::ArsExtIterator::tryy_collect
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/ext/iter.rs:57:13
  19: ars_core::ext::iter::ArsExtIntoIterator::tryy_vec
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/ext/iter.rs:17:30
  20: <rlife::llsss::ends::sym::LlsssEndsReflect as core::convert::Into<rlife::llsss::step::LlsssStep<TB,CST>>>::into::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/ends/sym.rs:199:20
  21: rlife::llsss::step::LlsssStep<TB,CST>::of3_rw::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/step.rs:289:25
  22: rlife::llsss::step::LlsssStep<TB,CST>::compile
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/step.rs:348:17
  23: rlife::llsss::search::LlsssSearch<TB,CST>::search::{{closure}}::{{closure}}::{{closure}}::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/search.rs:47:30
  24: rlife::hcs::Hcs::timeo::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/hcs.rs:74:13
  25: rlife::time::TimeStatsGeneric<M>::timeo::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:244:22
  26: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:250:5
  27: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/boxed.rs:2240:9
  28: rlife::time::TimeStatsGeneric<M>::timeo_inner
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:228:17
  29: rlife::time::TimeStatsGeneric<M>::timeo
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:243:14
  30: rlife::hcs::Hcs::timeo
             at /mnt/c/wsl/rust/rlife/rlife-master/src/hcs.rs:73:17
  31: rlife::llsss::search::LlsssSearch<TB,CST>::search::{{closure}}::{{closure}}::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/search.rs:46:25
  32: rlife::time::timeo
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:98:13
  33: rlife::llsss::search::LlsssSearch<TB,CST>::search::{{closure}}::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/search.rs:45:17
  34: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &mut F>::call_once
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:310:21
  35: core::option::Option<T>::map
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/option.rs:1165:29
  36: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::next
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/iter/adapters/map.rs:107:26
  37: <ars_core::tryy::ErrorTrackingIter<IT> as core::iter::traits::iterator::Iterator>::next
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/tryy.rs:85:25
  38: <&mut I as core::iter::traits::iterator::Iterator>::next
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/iter/traits/iterator.rs:4226:18
  39: alloc::vec::Vec<T,A>::extend_desugared
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/mod.rs:3969:44
  40: <alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/spec_extend.rs:18:14
  41: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/spec_from_iter_nested.rs:41:9
  42: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/spec_from_iter.rs:33:9
  43: <alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/vec/mod.rs:3865:9
  44: ars_core::ext::iter::ArsExtIterator::tryy_collect::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/ext/iter.rs:59:22
  45: ars_core::tryy::tryy_with_iter
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/tryy.rs:104:13
  46: ars_core::ext::iter::ArsExtIterator::tryy_collect
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/ext/iter.rs:57:13
  47: ars_core::ext::iter::ArsExtIntoIterator::tryy_vec
             at /mnt/c/wsl/rust/rlife/rlife-master/ars/core/src/ext/iter.rs:17:30
  48: rlife::llsss::search::LlsssSearch<TB,CST>::search::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/search.rs:50:16
  49: rlife::hcs::Hcs::timeo::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/hcs.rs:74:13
  50: rlife::time::TimeStatsGeneric<M>::timeo::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:244:22
  51: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:250:5
  52: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/boxed.rs:2240:9
  53: rlife::time::TimeStatsGeneric<M>::timeo_inner
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:228:17
  54: rlife::time::TimeStatsGeneric<M>::timeo
             at /mnt/c/wsl/rust/rlife/rlife-master/src/time.rs:243:14
  55: rlife::hcs::Hcs::timeo
             at /mnt/c/wsl/rust/rlife/rlife-master/src/hcs.rs:73:17
  56: rlife::llsss::search::LlsssSearch<TB,CST>::search
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/search.rs:43:29
  57: rlife::llsss::cli::recentering::LlsssRecenteringWaoArgs::main::{{closure}}
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/cli/recentering.rs:779:18
  58: rlife::llsss::cli::common::CommonArgs::main
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/cli/common.rs:898:18
  59: rlife::llsss::cli::recentering::LlsssRecenteringWaoArgs::main
             at /mnt/c/wsl/rust/rlife/rlife-master/src/llsss/cli/recentering.rs:663:26
  60: rlife::entry::main
             at /mnt/c/wsl/rust/rlife/rlife-master/src/entry.rs:61:47
  61: rlife::main
             at /mnt/c/wsl/rust/rlife/rlife-master/src/main.rs:31:5
  62: core::ops::function::FnOnce::call_once
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Maybe this is just me running something wrong, but it seems to work fine for 2c/6 and C/4, so I don't know what it would be.
The torch of 5S has been passed on again, and is now managed by speedydelete. It can be found here. Also check out my program EPE, a tool for searching for patterns in various rulespaces.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » May 13th, 2026, 11:45 am

AforAmpere wrote:
May 13th, 2026, 2:11 am
This seems to crash for me on the latest master version.

...

Maybe this is just me running something wrong, but it seems to work fine for 2c/6 and C/4, so I don't know what it would be.
Yeah, that's definitely busted. The error message says it can't make a table that big and the backtrace says it's in the middle of trying to compile a reflect ends. Some reasoning about geometry suggests to me it would need AD of 72 bits to make an odd ends table for 2c8-s2s while the default setup is only AD=u64 for performance. I believe this is generally going to shake out as 7 generations or fewer okay (takes 63 bits), 8 or more not. Even ends tables take 2/3s as much and so should get by to 10 generations (60 bits). This is all from first principles and human reason which I will verify with a computer and follow up if I got something wrong.

As for what to do about it, there are a handful of unpleasant choices:

(*) The lowest tech "solution" by far is for operators to hack "type TableEngineImpl = TableEngineChecks::<u128>;" (or even bigger to U256, etc.) in src/precomp.rs and recompile for searches that need it. If you try this path and need help getting it to work, feel free to ping me again here.

(*) The second lowest tech is to change symmetric ends to use "compile_table_yolo" instead which is optimized for most working (e.g. AD is 256 bits) rather than performance, but of course this may degrade performance. Operators could also try this one locally: just replace "compile_table" with "compile_table_yolo" in both places in src/llsss/ends/sym.rs" and of course recompile. I will most likely pursue this and if I verify that the performance loss isn't too bad, ship it. A slightly higher tech variant of this is to split out a third table compilation performance hint for tables that might need to be big but for which we maybe still care about perf (sort of midway between compile_table and compile_table_yolo).

(*) A middle tech change would be to do some sort of failure detection and fall back to big/slow "yolo" tables, although it's either going to hurt binary size (second copy of generated binary for second table type), or performance (if doing dynamic dispatch to tables instead).

(*) The highest tech change is to pursue the next generation idea for the CA check engine (called "checks4" in my notes), which allows splitting a table build into multiple builds of the current table code in a way that they all survive this AD crunch and their intersection gives the correct answer. I am unlikely to pursue this right now given how complicated it would be and how rarely this comes up.

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » May 13th, 2026, 1:26 pm

amling wrote:
May 13th, 2026, 11:45 am
AforAmpere wrote:
May 13th, 2026, 2:11 am
This seems to crash for me on the latest master version.
..."compile_table_yolo" instead...
I benchmarked lightly both the switch to compile_table_yolo and to a new compile_table_wide (that uses U256, but still makes big tables to try to do less badly on perf). It's hard to compare anything since for how long I was willing to wait these times are extremely, extremely small (and a very small portion of the total search time). I estimate the "yolo" version is around 10x slower and the "wide" version is around 2x slower. Considering the "wide" table business is such a small additional code change and is likely to be useful elsewhere I think I'm taking it. Ditto taking the change to wide for symmetric ends since 2x on something that is such a tiny fraction of search time I think is acceptable.

I've also cleaned up the error strings and propagation slightly so this error would have instead begun:

Code: Select all

Error: Table needs to read 72 bits, but AD is only 64 bits

Context:
    0: While compiling step LlsssEndsReflect(Odd)

...
This also changes the step's label (used e.g. in timing output) to include the symmetry which is probably desirable in this case. It's harder to say more generally how much of their configuration various steps should be including (right now they include almost nothing for historical reasons), so I will probably just refine them as they come up rather than try to audit them all right now.

I've pushed the changes to codeberg now (as of c46da89d7061). Please let me know if they somehow don't work out for you.



As a minor note, your original search includes both a bcaf filter and a none ends, both of which I believe will do nothing.

In a WAO search from '@bg', no partials should be able to be (start with) all background agar and so the bcaf filter should never be removing any part of the state. If anything is getting removed I either have a bug in my code or in my current thinking.

"none" ends doesn't do anything when run and is just a placeholder to use if you need to override the default of "bg" but don't have any ends you want to replace it with. You'd think with DL configuration we'd be able to use '[]', but it doesn't work for complicated reasons having to do with how I hacked the integration to allow either a step or a list of steps. That's perhaps for me to fix some day, but in the mean time "none" lives on and '[odd,even,none]' is materially the same as '[odd,even]'.



Finally, I was bad and could not resist looking at the rule briefly myself. At a minimum there are no strict c/4 ships at all, ruled out by c4-f2b/U=X+3T arbitrary width search (as well as c4-s2s, although it takes more time and memory), and at 2c/8 searches are going to likely be plagued by (gummed up by) interesting bits like this:

Code: Select all

x = 68, y = 54, rule = B2-a3-i45678/S0123-a45-i678
64bob2o$63b5o$62b5o$62b5o$64b2o$60bobob2o$58b5o$58b5o$58b3o$58b3o$56b
2o$52bobob2o$50b5o$50b5o$50b3o$50b3o$48b2o$44bobob2o$42b5o$42b5o$42b3o
$42b3o$40b2o$36bobob2o$34b5o$34b5o$34b3o$34b3o$32b2o$28bobob2o$26b5o$
26b5o$26b3o$26b3o$24b2o$20bobob2o$18b5o$18b5o$18b3o$18b3o$16b2o$12bobo
b2o$10b5o$10b5o$10b3o$10b3o$8b2o$4bobob2o$2b5o$2b5o$2b3o$2b3o$2o$2o!

User avatar
LaundryPizza03
Posts: 2596
Joined: December 15th, 2017, 12:05 am
Location: Unidentified location "https://en.wikipedia.org/wiki/Texas"

Re: amling search program principles discussion / brain dump

Post by LaundryPizza03 » May 19th, 2026, 9:52 am

How do I read diagonal search results with left edge odd? Here's an example from a c/4d search in B023/S0125:

Code: Select all

20260519 08:50:14 [INFO] Firstest:
20260519 08:50:14 [INFO] |                               |                               |          *                    |          .                    |
20260519 08:50:14 [INFO] |          **                   |          ..                   |         ***                   |         ...                   |
20260519 08:50:14 [INFO] |         ****                  |         ....                  |        *****                  |        .....                  |
20260519 08:50:14 [INFO] |        ******                 |        ......                 |       *******                 |       .......                 |
20260519 08:50:14 [INFO] |       ********                |       ........                |      *********                |      .........                |
20260519 08:50:14 [INFO] |      **********               |      ..........               |     ***********               |     ...........               |
20260519 08:50:14 [INFO] |     ************              |     ............              |    *************              |    .............              |
20260519 08:50:14 [INFO] |    **************             |    ..............             |   ***************             |   ...............             |
20260519 08:50:14 [INFO] |   *****..*..******            |   ................            |  ****..*.*..******            |  ......*.*........            |
20260519 08:50:14 [INFO] |  ******.*..**..****           |  .....*.*.*........           | *******.*.*********           | ........***.*......           |
20260519 08:50:14 [INFO] | *******.*.*..*******          | ......*.*.*.........          | *******.....*..*****          | .........**.*.......          |
20260519 08:50:14 [INFO] |  ******.*..*.********         |  .......****.*.......         |  ****.*...*.***.*****         |  ......****..........         |
20260519 08:50:14 [INFO] |   ******...*.**.******        |   .....**.**..*.......        |   *****...**...*******        |   .....****.**........        |
20260519 08:50:14 [INFO] |    *****.......*.******       |    ....*..*.***........       |    ****........*.******       |    .....*****.*........       |
20260519 08:50:14 [INFO] |     ****.*......*.******      |     ...*.**..*.*........      |     ******...*..**.*****      |     ...*..******........      |
20260519 08:50:14 [INFO] |      **.*..*.....********     |      ......*.**.**.......     |      **.**...*...*.******     |      ....*..****.........     |
20260519 08:50:14 [INFO] |       .*.**......*********    |       ...*.*****..........    |       .*.**...*..*********    |       ...*.***.*..........    |
20260519 08:50:14 [INFO] |        .***..**.***********   |        .....**...*.........   |        .*.**.*.***.********   |        ...*.*..............   |
20260519 08:50:14 [INFO] |         ****..**..**********  |         ......*.............  |         .**.*.*....*********  |         ....................  |
20260519 08:50:14 [INFO] |          ***.**..**.********* |          ....*............... |          ***.**.**..*..*****  |          .**.*..**..........  |
20260519 08:50:14 [INFO] |           ******.***.*.**.**  |           .........*.*......  |           *.**.*..****...**   |           *..*....*...**...   |
20260519 08:50:14 [INFO] |            **.**.*.**.*.***   |            .*....*..*...*.*   |            ***.*******..*.    |            ..*....*..*.*..    |
20260519 08:50:14 [INFO] |             ..*******.*.**    |             ..*.**.......*    |             *.*...*..***.     |             *............     |
20260519 08:50:14 [INFO] |              **.*.******.     |              **.*.....**.     |              **.********      |              ....**..*..      |
20260519 08:50:14 [INFO] |               .**.***.**      |               .....**...      |               .*.**...*       |               ....*....       |
20260519 08:50:14 [INFO] |                **....*.       |                ...*.**.       |                .*.*..*        |                ...*.**        |
20260519 08:50:14 [INFO] |                 ..*...        |                 ...***        |                 .***.         |                 .*.*.         |
20260519 08:50:14 [INFO] |                  ***.         |                  .*.*         |                  *..          |                  ...          |
20260519 08:50:14 [INFO] |                   **          |                   .*          |                   .           |                   .           |

Code: Select all

x = 4, y = 3, rule = B3-q4z5y/S234k5j
2b2o$b2o$2o!
LaundryPizza03 at Wikipedia

amling
Posts: 1154
Joined: April 2nd, 2020, 9:47 pm

Re: amling search program principles discussion / brain dump

Post by amling » May 19th, 2026, 10:25 am

LaundryPizza03 wrote:
May 19th, 2026, 9:52 am
How do I read diagonal search results with left edge odd?
"Left" means "lower U value" which for the named diagonal f2b geometries means SW side. Looking at the partial, the outermost and third-outermost half diagonals always match which identifies where the axis of symmetry is. For example, the second generation would be doubled up as:

Code: Select all

x = 37, y = 37, rule = B023/S0125History
17.2B$16.4B$15.6B$14.8B$13.10B$12.12B$11.14B$10.16B$9.5BABABA8B$8.6BA
BABA9B$7.9B4ABA7B$6.9B2AB2A2BA7B$5.10BA2BAB3A8B$4.11BAB2A2BABA8B$3.5B
2A9BAB2AB2A7B$2.9B3A3BAB5A10B$.7B4A8B2A3BA9B$10BA2BABA6BA13B$8B6A7BA
15B$.9B2A2B2A11BABA6B$2.10BA2B2A3BA4BA2BA3BABA$3.7BAB5ABA3BAB2A7BA$4.
7B2AB2ABA3B2ABA5B2AB$5.8BABA11B2A3B$6.8BA6B2A3BAB2AB$7.7BABA3B2A5B3A$
8.16BABABA$9.10BA3BABABA$10.10BA2B4A$11.8BA4B2A$12.10BA2B$13.9BAB$14.
6BA2B$15.6BA$16.4BA$17.3B$18.B!

Post Reply