Bitbanging 1D Reversible Automata

https://richiejp.com/1d-reversible-automata

By richiejp at

hairtuq | 0 comments | 2 weeks ago
The author wonders:

> In theory at least, the compiler can see that rule only has 256 values and create a reduced version of ca1d_rule_apply for each value. Whether it actually does is not of much practical concern when the rendering code is the bottle neck. However it’s interesting to see if the compiler can deduce the best solution or whether anything trips it up.

The compiler is unlikely to get the optimal result here. The core of this is finding the best instruction sequence for a ternary boolean operation encoded in 8 bits; it's the same job needed for emulating the AVX512F "vpternlog" instruction. This can always be done in at most 5 instructions (or 4 if you have andnot/ornot/xornot), but it's not straightforward to do this. Here is some code that calculates optimal instruction sequences (by letting z3 do the heavy lifting): https://github.com/falk-hueffner/ternary-logic-optimization

tromp | 2 comments | 2 weeks ago
The author make automata reversible by xoring with the previous row's cell. But some rules are reversible without this trick. For example rule 0xf0:

    111 110 101 100 011 010 001 000
     1   1   1   1   0   0   0   0
will shift all cells one step to the right and is thus the reverse of rule 0xaa which shifts all cells to the left:

    111 110 101 100 011 010 001 000
     1   0   1   0   1   0   1   0
My question is how can we test which of the 256 rules are reversible and how do they pair up?
orlp | 1 comment | 2 weeks ago
A rule R is reversible if there exists a rule R^-1 such that for all a, b, c, d, e, f, g we see the following evolution (where . stands for "don't care"):

    a  b  c  d  e  f  g

       Apply rule R

    .  b' c' d' e' f' .
       
       Apply rule R^-1

    .  .  c  d  e  .  .
In equations, it means there must exist some R^-1 such that for all a, b, c, d, e, f, g the following holds:

    c = R^-1(R(a, b, c), R(b, c, d), R(c, d, e))
    d = R^-1(R(b, c, d), R(c, d, e), R(d, e, f))
    e = R^-1(R(c, d, e), R(d, e, f), R(e, f, g))
Writing a quick program that checks all possible combinations of R and R^-1 (https://play.rust-lang.org/?version=stable&mode=debug&editio...) we find the following inverse pairs:

   0x33 <-> 0x33
   0x55 <-> 0x0f
   0xcc <-> 0xcc
   0xf0 <-> 0xaa
That is, the following two rules are self-inverses (they're the NOT and IDENTITY gates on the center cell respectively):

    111 110 101 100 011 010 001 000
     0   0   1   1   0   0   1   1
     1   1   0   0   1   1   0   0
We have the left <-> right moving pair you identified:

    111 110 101 100 011 010 001 000
     1   0   1   0   1   0   1   0

    111 110 101 100 011 010 001 000
     1   1   1   1   0   0   0   0
And there's just one more, which is the same as the above but it also inverts the output (move left and invert is the inverse of move right and invert):

    111 110 101 100 011 010 001 000
     0   1   0   1   0   1   0   1

    111 110 101 100 011 010 001 000
     0   0   0   0   1   1   1   1
Y_Y | 0 comments | 2 weeks ago
Very neat, thanks for working this out. (Why would it not be sufficient to start with just five symbols?)

The solution is like a restricted version of Hilbert's Hotel, we're still in a group of invertible maps on binary sequences {0,1}^N but we aren't allowed to do anything non-local.

https://en.wikipedia.org/wiki/Hilbert%27s_paradox_of_the_Gra...

Y_Y | 1 comment | 2 weeks ago
> My question is how can we test which of the 256 rules are reversible and how do they pair up?

I wondered this too. It feel like a generalization of the well-studied deconvolution problem, but thankfully without noise.

I haven't had my coffee yet, but some quick googling any thinking didn't deliver an answer, so I'd just try enumerating all the rules and seeing which ones invert each other.

Or, take all permutations of five bits, and find the central three bits in the next generation. If-and-only-if all patterns resulting in the three bits have the same central bit in the original pattern, then the rule is invertible.

tromp | 1 comment | 2 weeks ago
For a rule to be reversible, it should have a 1 in 4 places, ie. hamming weight 4. I suspect all (8 choose 4) = 70 rules might be reversible.
orlp | 0 comments | 2 weeks ago
It turns out that only the identity gate and the left <-> right moving rules are reversible, plus their negated variants, see my other comment.
kousun12 | 1 comment | 2 weeks ago
richiejp | 1 comment | 2 weeks ago
could you provide a link to the code?
genewitch | 1 comment | 2 weeks ago
i wrote something similar a real long time ago, but it was a pig, super slow. So i upgraded to winpro or whatever and had copilot figure out what was slowing it down, and it was a simple fix, and i fleshed out the UI a bit. I forget where i first saw the rules, but when i went and fixed it up i used the wolframalpha reference[0]

Adjust the screen rez. i am not a software developer and i put stuff on github as additional backups.

[0]https://mathworld.wolfram.com/ElementaryCellularAutomaton.ht...

my code: https://github.com/genewitch/opensource/blob/master/elementa... it uses pygame you can do python -m venv cellular; scripts\activate.[bat|ps1|sh]; pip install pygame; python elementalautomata.py

the rules are the same numbers as OP used, so given the same seeds the monochrome output should be identical (this is a deterministic automaton) I forget which rules were my favorite, but i constantly test 110 and 73 (73 is psuedorandom but doesn't look like it is, it looks like it repeats.) - my code checks for loops, but it defaults to 1 screen-fulls of checking, you can press H to increase this by 1 screen-full per press. this will slow my code down to a crawl, but you can find loops in the longer period automata.

i was going to do a version similar in godot but i got distracted by ipv6 routing.

edit:

the part you'd need to adapt to add color in my code is just this one part, i think:

        for pixel in range(1, w):

            if lineOut[pixel] == 1:

                world.set_at((pixel, h-1), (0, 0, 0))

            else:
                world.set_at((pixel, h-1), (255, 255, 255))
genewitch | 0 comments | 2 weeks ago
oops you need to "cd cellular" after the venv command! I proofread that 4 times and still missed the cd, and i had just set it up for my kid to play with (he asked!)
jszymborski | 1 comment | 2 weeks ago
Man do I ever want a wall-size flipdisk display to cycle through the different rules throughout the day...
TechDebtDevin | 2 comments | 2 weeks ago
Check out the Hisense Canvas.
jszymborski | 0 comments | 2 weeks ago
Actually was tempted to buy a Samsung Frame TV earlier this month when TV shopping.

Still, without the clicking and clacking, it's not quite the same :P

genewitch | 0 comments | 2 weeks ago
that is good looking, too bad i have 0 wall space for hanging things.
mungoman2 | 0 comments | 2 weeks ago
Super interesting how the example of "Rule 105 Reversible" inserts a mirror 3/4 down, but only on the right half.

I wonder how it continues.

tugu77 | 4 comments | 2 weeks ago
Automaton.

The singular is automaton. Automata is plural.

danwills | 0 comments | 2 weeks ago
I've sometimes thought it might be reasonable to think of a single cell in the system as an 'automaton' which might make it somewhat ok to call the whole collection of cells 'automata'.

I accept that there's two levels here though and sometimes people refer to the system as a whole as being a single automaton even if there's loads of cells.

pixelpoet | 0 comments | 2 weeks ago
I was considering posting this, but then I realised the hypocrisy in my use of the word "data" :)
QuadmasterXLII | 2 comments | 2 weeks ago
The post describes multiple automata though?
richiejp | 0 comments | 2 weeks ago
Yes it does. Even discarding arguments that different rules in the same class are the same automaton and multiple cells are the same automaton, the article includes reversible and non-reversible automata which are distinct classes.
Jerrrry | 0 comments | 2 weeks ago

  >multiple automata
Automatia