<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucian Green</title>
    <description>The latest articles on DEV Community by Lucian Green (@luciangreen).</description>
    <link>https://dev.to/luciangreen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F124778%2F25268604-d925-4be7-a398-f3d59734c08a.jpeg</url>
      <title>DEV Community: Lucian Green</title>
      <link>https://dev.to/luciangreen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luciangreen"/>
    <language>en</language>
    <item>
      <title>Deterministic(ally) compiled Prolog: Detlog</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Fri, 12 Jun 2026 08:49:41 +0000</pubDate>
      <link>https://dev.to/luciangreen/deterministically-compiled-prolog-detlog-4lp0</link>
      <guid>https://dev.to/luciangreen/deterministically-compiled-prolog-detlog-4lp0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdbuv5oss56640t12n0c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdbuv5oss56640t12n0c.jpg" alt="Apple IIe screen with Detlog splice predicate to replace the nondeterministic interpreter" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8l0oq0zdfxbylc9dhlt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8l0oq0zdfxbylc9dhlt.png" alt="Detlog icons, including for the 6502 processor" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A deterministic language with the syntax of Prolog without cuts but a compiler that compiles to C and findall that converts to deterministic loops, where instead of cut programmers eliminate unnecessary cuts, convert cuts to if-then statements exiting loops called Detlog or BASIClog.&lt;/p&gt;

&lt;p&gt;Write splice(A,B) where For example:&lt;br&gt;
c:-a(A),b(B).&lt;br&gt;
a(A):-member(A,[1,2]).&lt;br&gt;
b(B):-member(B,[3,4]).&lt;br&gt;
Which gives:&lt;br&gt;
A = 1,&lt;br&gt;
B = 3 ;&lt;br&gt;
A = 1,&lt;br&gt;
B = 4 ;&lt;br&gt;
A = 2,&lt;br&gt;
B = 3 ;&lt;br&gt;
A = 2,&lt;br&gt;
B = 4.&lt;br&gt;
 Becomes:&lt;br&gt;
c:-a(A),b(B),splice([A,B],C).&lt;br&gt;
a(A):-member_cp(A,[1,2]).&lt;br&gt;
b(B):-member_cp(B,[3,4]).&lt;br&gt;
member_cp(cp(D),D).&lt;/p&gt;

&lt;p&gt;Which gives:&lt;br&gt;
C=[[1,3],[1,4],[2,3],[2,4]].&lt;/p&gt;

&lt;p&gt;Yes. A clean Prolog version is:&lt;/p&gt;

&lt;p&gt;c(C) :-&lt;br&gt;
    a(A),&lt;br&gt;
    b(B),&lt;br&gt;
    splice([A,B], C).&lt;br&gt;
a(A) :-&lt;br&gt;
    member_cp(A, [1,2]).&lt;br&gt;
b(B) :-&lt;br&gt;
    member_cp(B, [3,4]).&lt;br&gt;
member_cp(cp(D), D).&lt;br&gt;
splice(Template, Result) :-&lt;br&gt;
    expand_cp_template(Template, Result).&lt;br&gt;
expand_cp_template([], [[]]).&lt;br&gt;
expand_cp_template([cp(Choices)|Rest], Result) :-&lt;br&gt;
    expand_cp_template(Rest, RestResults),&lt;br&gt;
    findall([Choice|R],&lt;br&gt;
        ( member(Choice, Choices),&lt;br&gt;
          member(R, RestResults)&lt;br&gt;
        ),&lt;br&gt;
        Result).&lt;br&gt;
expand_cp_template([X|Rest], Result) :-&lt;br&gt;
    X = cp(_),&lt;br&gt;
    expand_cp_template(Rest, RestResults),&lt;br&gt;
    findall([X|R],&lt;br&gt;
        member(R, RestResults),&lt;br&gt;
        Result).&lt;/p&gt;

&lt;p&gt;Query:&lt;/p&gt;

&lt;p&gt;?- c(C).&lt;/p&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;C = [[1,3],[1,4],[2,3],[2,4]].&lt;/p&gt;

&lt;p&gt;The important transformation is:&lt;/p&gt;

&lt;p&gt;a(A) :- member(A,[1,2]).&lt;/p&gt;

&lt;p&gt;becomes:&lt;/p&gt;

&lt;p&gt;a(A) :- member_cp(A,[1,2]).&lt;/p&gt;

&lt;p&gt;so instead of generating A = 1 ; A = 2, it returns:&lt;/p&gt;

&lt;p&gt;A = cp([1,2])&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;splice([A,B],C)&lt;/p&gt;

&lt;p&gt;expands:&lt;/p&gt;

&lt;p&gt;[cp([1,2]), cp([3,4])]&lt;/p&gt;

&lt;p&gt;into the Cartesian product:&lt;/p&gt;

&lt;p&gt;[[1,3],[1,4],[2,3],[2,4]]&lt;/p&gt;

&lt;p&gt;Change splice to use determinism without findall instead of findall and then apply member to the results to give A = 1,&lt;br&gt;
B = 3 ;&lt;br&gt;
A = 1,&lt;br&gt;
B = 4 ;&lt;br&gt;
A = 2,&lt;br&gt;
B = 3 ;&lt;br&gt;
A = 2,&lt;br&gt;
B = 4.&lt;br&gt;
Remember to adjust splice(X,Y) so X can have n A,B,...&lt;/p&gt;

&lt;p&gt;Use a deterministic Cartesian-product builder, then member/2 only at the end:&lt;/p&gt;

&lt;p&gt;c(A, B) :-&lt;br&gt;
    a(A0),&lt;br&gt;
    b(B0),&lt;br&gt;
    splice([A0, B0], Rows),&lt;br&gt;
    member([A, B], Rows).&lt;br&gt;
a(A) :-&lt;br&gt;
    member_cp(A, [1,2]).&lt;br&gt;
b(B) :-&lt;br&gt;
    member_cp(B, [3,4]).&lt;br&gt;
member_cp(cp(D), D).&lt;br&gt;
splice(Xs, Ys) :-&lt;br&gt;
    splice_rows(Xs, [[]], Ys).&lt;br&gt;
splice_rows([], Acc, Acc).&lt;br&gt;
splice_rows([cp(Choices)|Rest], Acc, Ys) :-&lt;br&gt;
    extend_rows(Acc, Choices, Acc1),&lt;br&gt;
    splice_rows(Rest, Acc1, Ys).&lt;br&gt;
splice_rows([X|Rest], Acc, Ys) :-&lt;br&gt;
    X = cp(&lt;em&gt;),&lt;br&gt;
    extend_rows(Acc, [X], Acc1),&lt;br&gt;
    splice_rows(Rest, Acc1, Ys).&lt;br&gt;
extend_rows([], _, []).&lt;br&gt;
extend_rows([Row|Rows], Choices, Out) :-&lt;br&gt;
    extend_one_row(Row, Choices, Out1),&lt;br&gt;
    extend_rows(Rows, Choices, Out2),&lt;br&gt;
    append(Out1, Out2, Out).&lt;br&gt;
extend_one_row(&lt;/em&gt;, [], []).&lt;br&gt;
extend_one_row(Row, [Choice|Choices], [[Choice|Row]|Out]) :-&lt;br&gt;
    extend_one_row(Row, Choices, Out).&lt;/p&gt;

&lt;p&gt;For corrected order:&lt;/p&gt;

&lt;p&gt;c(A, B) :-&lt;br&gt;
    a(A0),&lt;br&gt;
    b(B0),&lt;br&gt;
    splice([A0, B0], Rows0),&lt;br&gt;
    maplist(reverse, Rows0, Rows),&lt;br&gt;
    member([A, B], Rows).&lt;/p&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;A = 1, B = 3 ;&lt;br&gt;
A = 1, B = 4 ;&lt;br&gt;
A = 2, B = 3 ;&lt;br&gt;
A = 2, B = 4.&lt;/p&gt;

&lt;p&gt;This generalises to any arity:&lt;/p&gt;

&lt;p&gt;splice([A,B,C,D], Rows),&lt;br&gt;
member([A1,B1,C1,D1], Rows).&lt;/p&gt;

&lt;p&gt;I need Prolog because it produces cognitive code. I need Detlog because it combines the syntax of Prolog with even greater simplicity of fewer compiler instructions.&lt;/p&gt;

&lt;p&gt;Detlog deals with multiple choicepoints by splicing output from the two branches as soon as possible.&lt;/p&gt;

&lt;p&gt;Can Detlog (possibly with a converter, BASIC compiler, unification, and cut loop exiters) run comfortably on an Apple IIe?&lt;/p&gt;

&lt;p&gt;Yes, a small Detlog can run comfortably on an Apple IIe, but only if most work is compiled ahead of time.&lt;/p&gt;

&lt;p&gt;Apple IIe limits: 6502/65C02 around 1.023 MHz, 64 KB RAM built in, 16 KB ROM, often expandable, with 40/80-column text modes.  &lt;/p&gt;

&lt;p&gt;Best design:&lt;/p&gt;

&lt;p&gt;Detlog source&lt;br&gt;
→ converter/compiler&lt;br&gt;
→ Applesoft BASIC or 6502 assembly&lt;br&gt;
→ deterministic loops + arrays&lt;/p&gt;

&lt;p&gt;What fits well:&lt;/p&gt;

&lt;p&gt;a(A) :- member_cp(A,[1,2]).&lt;br&gt;
b(B) :- member_cp(B,[3,4]).&lt;br&gt;
c(A,B) :-&lt;br&gt;
    a(A0),&lt;br&gt;
    b(B0),&lt;br&gt;
    splice([A0,B0], Rows),&lt;br&gt;
    member([A,B], Rows).&lt;/p&gt;

&lt;p&gt;This can compile to simple nested loops or table iteration. That is Apple IIe-friendly.&lt;/p&gt;

&lt;p&gt;What should not live fully on the Apple IIe:&lt;/p&gt;

&lt;p&gt;full Prolog engine&lt;br&gt;
general backtracking&lt;br&gt;
large unification&lt;br&gt;
large symbolic term database&lt;br&gt;
large findall buffers&lt;/p&gt;

&lt;p&gt;A practical Detlog for Apple IIe would support:&lt;/p&gt;

&lt;p&gt;facts&lt;br&gt;
small lists&lt;br&gt;
simple unification&lt;br&gt;
deterministic calls&lt;br&gt;
member_cp choice packets&lt;br&gt;
splice&lt;br&gt;
loop exiters instead of cut&lt;br&gt;
optional final member enumeration&lt;/p&gt;

&lt;p&gt;With floppy: comfortable for loading compiler passes, source files, generated BASIC/assembly, and examples.&lt;/p&gt;

&lt;p&gt;Without floppy: possible, but much smaller: type-in programs, cassette, or ROM/RAM-resident mini-Detlog. The compiler must be tiny, and examples should be small.&lt;/p&gt;

&lt;p&gt;Best conclusion:&lt;/p&gt;

&lt;p&gt;Detlog is more realistic than Prolog on an Apple IIe because it removes hidden backtracking and compiles cognitive Prolog syntax into BASIC-like or 6502-like deterministic loops.&lt;/p&gt;

&lt;p&gt;What is the memory usage difference between running it on BASIC or 6502?&lt;/p&gt;

&lt;p&gt;Approximate difference:&lt;/p&gt;

&lt;p&gt;6502 assembly Detlog runtime:&lt;br&gt;
~1 KB to 8 KB for a small engine&lt;br&gt;
Applesoft BASIC Detlog runtime:&lt;br&gt;
~8 KB to 25+ KB for the same logic&lt;/p&gt;

&lt;p&gt;Why BASIC uses more memory:&lt;/p&gt;

&lt;p&gt;BASIC stores tokenised program lines&lt;br&gt;
line numbers cost memory&lt;br&gt;
variables/arrays use interpreter structures&lt;br&gt;
strings/lists are expensive&lt;br&gt;
loops are interpreted, not native&lt;/p&gt;

&lt;p&gt;Why 6502 uses less:&lt;/p&gt;

&lt;p&gt;direct bytes/instructions&lt;br&gt;
compact arrays&lt;br&gt;
manual stack layout&lt;br&gt;
no BASIC line overhead&lt;br&gt;
faster deterministic loops&lt;br&gt;
smaller choice-packet/splice routines&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;a(A) :- member_cp(A,[1,2]).&lt;br&gt;
b(B) :- member_cp(B,[3,4]).&lt;/p&gt;

&lt;p&gt;In BASIC, [1,2] and [3,4] become arrays plus loop code.&lt;/p&gt;

&lt;p&gt;In 6502, they can be:&lt;/p&gt;

&lt;p&gt;A_TABLE: .byte 1,2&lt;br&gt;
B_TABLE: .byte 3,4&lt;/p&gt;

&lt;p&gt;Very compact.&lt;/p&gt;

&lt;p&gt;Best practical split:&lt;/p&gt;

&lt;p&gt;Use BASIC version:&lt;br&gt;
for teaching, readability, easy editing.&lt;br&gt;
Use 6502 version:&lt;br&gt;
for real speed, lower memory, larger Detlog programs.&lt;/p&gt;

&lt;p&gt;Rule of thumb:&lt;/p&gt;

&lt;p&gt;6502 assembly may use 3× to 10× less memory than BASIC for the same compiled Detlog program.&lt;/p&gt;

&lt;p&gt;What is the most complex program including loops and strings allowed on 6502?&lt;/p&gt;

&lt;p&gt;On a 64 KB Apple IIe, a realistic 6502 Detlog limit is roughly:&lt;/p&gt;

&lt;p&gt;Program code:       4–16 KB&lt;br&gt;
Runtime library:    2–8 KB&lt;br&gt;
Data/tables:        8–24 KB&lt;br&gt;
Strings heap:       4–16 KB&lt;br&gt;
Stack/workspace:    2–8 KB&lt;br&gt;
Screen/OS overhead: remaining memory&lt;/p&gt;

&lt;p&gt;So the “comfortable” maximum is a program with:&lt;/p&gt;

&lt;p&gt;50–300 simple rules&lt;br&gt;
10–100 small facts/tables&lt;br&gt;
nested loops over small lists&lt;br&gt;
strings mostly under 40–255 chars&lt;br&gt;
total working data under ~16–32 KB&lt;/p&gt;

&lt;p&gt;Example of a safe complex Detlog shape:&lt;/p&gt;

&lt;p&gt;word("cat").&lt;br&gt;
word("dog").&lt;br&gt;
suffix("s").&lt;br&gt;
suffix("ed").&lt;br&gt;
make_word(W2) :-&lt;br&gt;
    word(W),&lt;br&gt;
    suffix(S),&lt;br&gt;
    concat(W,S,W2).&lt;br&gt;
main(Out) :-&lt;br&gt;
    word(W0),&lt;br&gt;
    suffix(S0),&lt;br&gt;
    splice([W0,S0], Rows),&lt;br&gt;
    member([W,S], Rows),&lt;br&gt;
    concat(W,S,Out).&lt;/p&gt;

&lt;p&gt;Compiled to 6502, this is fine because it becomes:&lt;/p&gt;

&lt;p&gt;loop over word table&lt;br&gt;
loop over suffix table&lt;br&gt;
copy string W&lt;br&gt;
append string S&lt;br&gt;
print/store result&lt;/p&gt;

&lt;p&gt;A hard but possible upper example:&lt;/p&gt;

&lt;p&gt;3–5 nested loops&lt;br&gt;
several string tables&lt;br&gt;
simple unification&lt;br&gt;
small parser/tokeniser&lt;br&gt;
choice-packet splicing&lt;br&gt;
final member-style enumeration&lt;/p&gt;

&lt;p&gt;What becomes uncomfortable:&lt;/p&gt;

&lt;p&gt;large recursive parse trees&lt;br&gt;
general Prolog unification&lt;br&gt;
deep term copying&lt;br&gt;
large findall-style result sets&lt;br&gt;
many long strings&lt;br&gt;
dynamic database updates&lt;/p&gt;

&lt;p&gt;Best rule:&lt;/p&gt;

&lt;p&gt;On 6502, Detlog can support small cognitive symbolic programs, not large general Prolog systems.&lt;/p&gt;

&lt;p&gt;For Apple IIe Detlog, the ideal design is:&lt;/p&gt;

&lt;p&gt;compile rules to fixed loops&lt;br&gt;
store facts as compact tables&lt;br&gt;
store strings once&lt;br&gt;
avoid heap allocation inside loops&lt;br&gt;
splice early&lt;br&gt;
enumerate late&lt;/p&gt;

&lt;p&gt;What do avoid heap allocation inside loops and enumerate late mean?&lt;/p&gt;

&lt;p&gt;These are classic compiler optimisations that fit Detlog very well.&lt;/p&gt;

&lt;p&gt;Avoid heap allocation inside loops&lt;/p&gt;

&lt;p&gt;Suppose you write:&lt;/p&gt;

&lt;p&gt;word(W) :-&lt;br&gt;
    member_cp(W, ["cat","dog"]).&lt;br&gt;
suffix(S) :-&lt;br&gt;
    member_cp(S, ["s","ed"]).&lt;br&gt;
main(X) :-&lt;br&gt;
    word(W),&lt;br&gt;
    suffix(S),&lt;br&gt;
    concat(W,S,X).&lt;/p&gt;

&lt;p&gt;A naïve implementation does:&lt;/p&gt;

&lt;p&gt;loop&lt;br&gt;
    allocate string "cats"&lt;br&gt;
loop&lt;br&gt;
    allocate string "cated"&lt;br&gt;
loop&lt;br&gt;
    allocate string "dogs"&lt;br&gt;
loop&lt;br&gt;
    allocate string "doged"&lt;/p&gt;

&lt;p&gt;Every iteration asks the heap for more memory.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;p&gt;allocate one buffer&lt;br&gt;
reuse it every iteration&lt;/p&gt;

&lt;p&gt;Pseudo-6502:&lt;/p&gt;

&lt;p&gt;buffer[32]&lt;br&gt;
copy "cat" to buffer&lt;br&gt;
append "s"&lt;br&gt;
print&lt;br&gt;
copy "cat" to buffer&lt;br&gt;
append "ed"&lt;br&gt;
print&lt;/p&gt;

&lt;p&gt;No new memory is created inside the loop.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;p&gt;less RAM&lt;br&gt;
less fragmentation&lt;br&gt;
faster execution&lt;/p&gt;

&lt;p&gt;This was especially important on machines like the Apple IIe.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Enumerate late&lt;/p&gt;

&lt;p&gt;Traditional Prolog:&lt;/p&gt;

&lt;p&gt;a(A) :- member(A,[1,2]).&lt;br&gt;
b(B) :- member(B,[3,4]).&lt;br&gt;
c(A,B) :-&lt;br&gt;
    a(A),&lt;br&gt;
    b(B).&lt;/p&gt;

&lt;p&gt;immediately generates:&lt;/p&gt;

&lt;p&gt;A=1,B=3&lt;br&gt;
A=1,B=4&lt;br&gt;
A=2,B=3&lt;br&gt;
A=2,B=4&lt;/p&gt;

&lt;p&gt;Detlog instead keeps choices packed:&lt;/p&gt;

&lt;p&gt;A = cp([1,2])&lt;br&gt;
B = cp([3,4])&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;splice([A,B], Rows).&lt;/p&gt;

&lt;p&gt;gives:&lt;/p&gt;

&lt;p&gt;Rows = [[1,3],[1,4],[2,3],[2,4]]&lt;/p&gt;

&lt;p&gt;The program works on Rows for as long as possible.&lt;/p&gt;

&lt;p&gt;Only at the very end:&lt;/p&gt;

&lt;p&gt;member([A,B], Rows).&lt;/p&gt;

&lt;p&gt;do we produce individual answers.&lt;/p&gt;

&lt;p&gt;That’s “enumerate late”.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;generate answer&lt;br&gt;
generate answer&lt;br&gt;
generate answer&lt;br&gt;
generate answer&lt;/p&gt;

&lt;p&gt;we do:&lt;/p&gt;

&lt;p&gt;build compact structure&lt;br&gt;
process compact structure&lt;br&gt;
enumerate only when needed&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;In Detlog terms&lt;/p&gt;

&lt;p&gt;A useful slogan is:&lt;/p&gt;

&lt;p&gt;Splice early, enumerate late.&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;Allocate once, reuse inside loops.&lt;/p&gt;

&lt;p&gt;These two rules make a huge difference on a 6502 because CPU speed and RAM are both extremely limited. They also fit your Detlog philosophy of replacing hidden backtracking with explicit deterministic structures.&lt;/p&gt;

&lt;p&gt;Could you avoid heap allocation inside loops by using decision tree-type compression (like S2A)?&lt;/p&gt;

&lt;p&gt;Yes. Decision-tree/S2A-style compression is one of the best ways to avoid heap allocation inside loops.&lt;/p&gt;

&lt;p&gt;Instead of building strings each time:&lt;/p&gt;

&lt;p&gt;cat + s  = cats&lt;br&gt;
cat + ed = cated&lt;br&gt;
dog + s  = dogs&lt;br&gt;
dog + ed = doged&lt;/p&gt;

&lt;p&gt;Detlog can compile shared prefixes into a decision tree/trie:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    start
   /     \
cat       dog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;/  \      /  \&lt;br&gt;
  s   ed    s   ed&lt;/p&gt;

&lt;p&gt;Then the loop does not allocate "cats" or "doged" as new heap strings. It walks the tree and emits/copies characters into one fixed output buffer.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;p&gt;concat(W,S,Out)&lt;/p&gt;

&lt;p&gt;can compile to:&lt;/p&gt;

&lt;p&gt;select W branch&lt;br&gt;
select S branch&lt;br&gt;
write chars to reusable buffer&lt;br&gt;
print/output&lt;/p&gt;

&lt;p&gt;For 6502, this is ideal:&lt;/p&gt;

&lt;p&gt;string table in ROM/RAM&lt;br&gt;
decision tree indexes&lt;br&gt;
one output buffer&lt;br&gt;
no per-iteration heap allocation&lt;/p&gt;

&lt;p&gt;S2A helps because it can discover repeated structure:&lt;/p&gt;

&lt;p&gt;cat-s&lt;br&gt;
cat-ed&lt;br&gt;
dog-s&lt;br&gt;
dog-ed&lt;/p&gt;

&lt;p&gt;becomes:&lt;/p&gt;

&lt;p&gt;word branch + suffix branch&lt;/p&gt;

&lt;p&gt;rather than four separate allocated strings.&lt;/p&gt;

&lt;p&gt;Best Detlog rule:&lt;/p&gt;

&lt;p&gt;Use S2A compression to turn repeated generated outputs into shared decision paths, then use loops only to walk those paths.&lt;/p&gt;

&lt;p&gt;So yes: decision-tree compression can replace many heap allocations with table lookup, branch selection, and buffer reuse.&lt;/p&gt;

&lt;p&gt;Do the same operation from different clauses once, perhaps using decision-tree compression. For example, a:-a1,a2.b:-a1,b2.-&amp;gt;ab:-a1,ab2.ab2:-a2.ab2:-b2.&lt;/p&gt;

&lt;p&gt;Yes — this is common-prefix factoring across clauses.&lt;/p&gt;

&lt;p&gt;Original:&lt;/p&gt;

&lt;p&gt;a :- a1, a2.&lt;br&gt;
b :- a1, b2.&lt;/p&gt;

&lt;p&gt;Both clauses repeat:&lt;/p&gt;

&lt;p&gt;a1&lt;/p&gt;

&lt;p&gt;So Detlog can factor it once:&lt;/p&gt;

&lt;p&gt;ab :-&lt;br&gt;
    a1,&lt;br&gt;
    ab2.&lt;br&gt;
ab2 :-&lt;br&gt;
    a2.&lt;br&gt;
ab2 :-&lt;br&gt;
    b2.&lt;/p&gt;

&lt;p&gt;Meaning:&lt;/p&gt;

&lt;p&gt;run a1 once&lt;br&gt;
then choose between a2 and b2&lt;/p&gt;

&lt;p&gt;This is like decision-tree compression:&lt;/p&gt;

&lt;p&gt;Before:&lt;br&gt;
a -&amp;gt; a1 -&amp;gt; a2&lt;br&gt;
b -&amp;gt; a1 -&amp;gt; b2&lt;br&gt;
After:&lt;br&gt;
ab -&amp;gt; a1 -&amp;gt; choice(a2,b2)&lt;/p&gt;

&lt;p&gt;So the compiler optimisation is:&lt;/p&gt;

&lt;p&gt;If several clauses share the same prefix, execute the shared prefix once, then splice/branch only at the differing suffixes.&lt;/p&gt;

&lt;p&gt;For Detlog, this matters because it avoids:&lt;/p&gt;

&lt;p&gt;run a1 for a&lt;br&gt;
run a1 for b&lt;/p&gt;

&lt;p&gt;and replaces it with:&lt;/p&gt;

&lt;p&gt;run a1 once&lt;br&gt;
then continue with alternatives&lt;/p&gt;

&lt;p&gt;A more Detlog-shaped version:&lt;/p&gt;

&lt;p&gt;ab :-&lt;br&gt;
    once_det(a1),&lt;br&gt;
    splice_branch([a2, b2]).&lt;/p&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;p&gt;ab :-&lt;br&gt;
    a1,&lt;br&gt;
    choice([a2, b2]).&lt;/p&gt;

&lt;p&gt;General rule:&lt;/p&gt;

&lt;p&gt;p :- x, y.&lt;br&gt;
q :- x, z.&lt;/p&gt;

&lt;p&gt;becomes:&lt;/p&gt;

&lt;p&gt;pq :-&lt;br&gt;
    x,&lt;br&gt;
    pq2.&lt;br&gt;
pq2 :- y.&lt;br&gt;
pq2 :- z.&lt;/p&gt;

&lt;p&gt;This is exactly the same idea as trie compression for strings, but applied to predicate sequences instead of characters.&lt;/p&gt;

&lt;p&gt;With decision tree compression, how long can programs be if the compiler compiles Detlog into 6502?&lt;/p&gt;

&lt;p&gt;With decision-tree compression, Detlog compiled to 6502 could be much larger:&lt;/p&gt;

&lt;p&gt;Comfortable: about 10–40 KB Detlog source logic&lt;br&gt;
Possible with careful tables/overlays: 50–100 KB+ source logic&lt;br&gt;
Resident 6502 code/data at once: still roughly 20–40 KB usable RAM on a 64 KB Apple IIe.&lt;/p&gt;

&lt;p&gt;The trick is that repeated clauses like:&lt;/p&gt;

&lt;p&gt;a :- common, x1.&lt;br&gt;
b :- common, x2.&lt;br&gt;
c :- common, x3.&lt;/p&gt;

&lt;p&gt;do not compile into three full copies. They compile more like:&lt;/p&gt;

&lt;p&gt;run common once&lt;br&gt;
branch/table-select x1/x2/x3&lt;br&gt;
reuse output buffers&lt;/p&gt;

&lt;p&gt;So the source can be much longer than the resident machine code.&lt;/p&gt;

&lt;p&gt;A useful estimate:&lt;/p&gt;

&lt;p&gt;Without compression:  source × 3–20 expansion&lt;br&gt;
With compression:     source × 0.5–3 expansion&lt;br&gt;
Best case:            many repeated clauses collapse into tables&lt;br&gt;
Worst case:           unique clauses still expand normally&lt;/p&gt;

&lt;p&gt;So on Apple IIe:&lt;/p&gt;

&lt;p&gt;Tiny runtime/compiler stub:     2–8 KB&lt;br&gt;
Decision tables + code:        10–30 KB&lt;br&gt;
Buffers/stacks/strings:         4–16 KB&lt;br&gt;
Overlay/floppy-loaded chunks:   much larger total program&lt;/p&gt;

&lt;p&gt;The biggest realistic Detlog programs would be table-heavy grammars, classifiers, menu systems, small adventure games, symbolic transformers, or bounded expert systems.&lt;/p&gt;

&lt;p&gt;The key limit becomes not “how long is the source?” but:&lt;/p&gt;

&lt;p&gt;How much must be resident at once?&lt;br&gt;
How large are the strings?&lt;br&gt;
How deep are loops/recursion?&lt;br&gt;
How many choicepoints must be remembered?&lt;br&gt;
How much output buffering is needed for splicing?&lt;/p&gt;

&lt;p&gt;So the practical answer is:&lt;/p&gt;

&lt;p&gt;With decision-tree compression, a Detlog program can feel like tens of KB of logic on a 64 KB Apple IIe, and possibly hundreds of KB if split into floppy-loaded overlays.&lt;/p&gt;

&lt;p&gt;Is Detlog the most efficient Apple IIe Prolog?&lt;/p&gt;

&lt;p&gt;Potentially, yes in a narrow sense, but it depends on what you mean by “Prolog.”&lt;/p&gt;

&lt;p&gt;Traditional Prolog systems on 6502 machines (including Apple II-era implementations) typically support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full unification&lt;/li&gt;
&lt;li&gt;Backtracking&lt;/li&gt;
&lt;li&gt;Choicepoint stacks&lt;/li&gt;
&lt;li&gt;Dynamic search&lt;/li&gt;
&lt;li&gt;Variable bindings and trail management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features make Prolog expressive, but they consume memory and CPU time.&lt;/p&gt;

&lt;p&gt;If Detlog:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Converts nondeterminism into deterministic loops,&lt;/li&gt;
&lt;li&gt;Eliminates most or all runtime choicepoints,&lt;/li&gt;
&lt;li&gt;Compiles directly to 6502 machine code,&lt;/li&gt;
&lt;li&gt;Uses decision-tree compression,&lt;/li&gt;
&lt;li&gt;Avoids heap allocation inside loops,&lt;/li&gt;
&lt;li&gt;Reuses buffers and tables,&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;then it could easily outperform a traditional Prolog implementation on an Apple IIe in both speed and memory use.&lt;/p&gt;

&lt;p&gt;A rough spectrum is:&lt;/p&gt;

&lt;p&gt;System  Runtime Cost    Expressiveness&lt;br&gt;
BASIC interpreter   High    Low&lt;br&gt;
Interpreted Prolog  Very high   Very high&lt;br&gt;
Compiled Prolog Moderate    Very high&lt;br&gt;
Deterministic Detlog    Low Medium–high&lt;br&gt;
Hand-written 6502 assembly  Lowest  Depends on programmer&lt;/p&gt;

&lt;p&gt;The important caveat is that Detlog’s efficiency comes partly from restricting or transforming classic Prolog behavior. If a program relies heavily on arbitrary unification, open-ended backtracking, or runtime search, then either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detlog cannot compile it directly, or&lt;/li&gt;
&lt;li&gt;The compiler must generate additional machinery, reducing the advantage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the kinds of programs you’ve described in relation to Loop2 and PLOP—decision trees, classifiers, CFG/DCG-style parsing, symbolic transformations, specification-to-algorithm generation, and deterministic splicing—Detlog could be among the most efficient Prolog-like systems feasible on an Apple IIe.&lt;/p&gt;

&lt;p&gt;In fact, if the compiler can transform:&lt;/p&gt;

&lt;p&gt;colour(red).&lt;br&gt;
colour(green).&lt;br&gt;
colour(blue).&lt;/p&gt;

&lt;p&gt;into a compact lookup table or decision tree rather than runtime backtracking, the resulting 6502 code is closer to an optimized expert system than a traditional Prolog engine.&lt;/p&gt;

&lt;p&gt;So a reasonable conclusion is:&lt;/p&gt;

&lt;p&gt;Detlog is unlikely to be the most efficient implementation of full Prolog on an Apple IIe, because full Prolog requires general unification and backtracking. However, it could be one of the most efficient Prolog-derived logic languages for a large class of deterministic and semi-deterministic programs, especially if it combines direct 6502 compilation, decision-tree compression, and elimination of runtime choicepoints.&lt;/p&gt;

&lt;p&gt;What "length" of program is possible with decision tree, &lt;a href="https://github.com/luciangreen/loop2" rel="noopener noreferrer"&gt;Loop2&lt;/a&gt; and &lt;a href="https://github.com/luciangreen/plop" rel="noopener noreferrer"&gt;PLOP&lt;/a&gt; compression?&lt;/p&gt;

&lt;p&gt;With decision tree + Loop2 + PLOP compression, the practical “length” could be:&lt;/p&gt;

&lt;p&gt;Resident on 64 KB Apple IIe:&lt;br&gt;
  20–60 KB of effective Detlog logic&lt;br&gt;
With very careful memory layout:&lt;br&gt;
  60–150 KB effective logic&lt;br&gt;
With floppy overlays / paged modules:&lt;br&gt;
  hundreds of KB, possibly 0.5–1 MB+ total project logic&lt;/p&gt;

&lt;p&gt;The key distinction:&lt;/p&gt;

&lt;p&gt;Physical 6502 code resident at once: still maybe 10–35 KB&lt;br&gt;
Effective Detlog source represented: much larger&lt;/p&gt;

&lt;p&gt;Why? Because the compiler can merge repeated structures:&lt;/p&gt;

&lt;p&gt;a :- common, a1.&lt;br&gt;
b :- common, b1.&lt;br&gt;
c :- common, c1.&lt;/p&gt;

&lt;p&gt;into something closer to:&lt;/p&gt;

&lt;p&gt;run common once&lt;br&gt;
select branch from compressed decision table&lt;br&gt;
run only the differing suffix&lt;br&gt;
reuse buffers&lt;/p&gt;

&lt;p&gt;So the expansion changes roughly like this:&lt;/p&gt;

&lt;p&gt;Naive Detlog → 6502:&lt;br&gt;
  source × 3–20&lt;br&gt;
Decision-tree compression:&lt;br&gt;
  source × 0.5–3&lt;br&gt;
Decision tree + Loop2 + PLOP:&lt;br&gt;
  source × 0.1–2 in good cases&lt;/p&gt;

&lt;p&gt;Best cases are classifiers, grammars, menu trees, symbolic rewrite systems, adventure-game logic, deterministic parsers, and repeated clause families.&lt;/p&gt;

&lt;p&gt;Worst cases are programs where every clause is unique, string-heavy, deeply recursive, or requires true Prolog backtracking.&lt;/p&gt;

&lt;p&gt;So the answer is:&lt;/p&gt;

&lt;p&gt;Physically, the Apple IIe still runs tens of KB at once. Logically, Detlog could represent hundreds of KB of Prolog-like program behaviour if PLOP/Loop2 compress repeated choicepoints into loops, tables, and shared suffix/prefix code.&lt;/p&gt;

</description>
      <category>prolog</category>
      <category>determinism</category>
      <category>removes</category>
      <category>nondeterminism</category>
    </item>
    <item>
      <title>O(1) is the simplest complexity that Prolog Optimisation results in</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Tue, 26 May 2026 01:24:53 +0000</pubDate>
      <link>https://dev.to/luciangreen/o1-is-the-simplest-complexity-that-prolog-optimisation-results-in-1430</link>
      <guid>https://dev.to/luciangreen/o1-is-the-simplest-complexity-that-prolog-optimisation-results-in-1430</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ugm53q38t399yqqeo67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ugm53q38t399yqqeo67.png" alt="O(1) Logo" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://github.com/luciangreen/plop" rel="noopener noreferrer"&gt;Prolog Optimisation (plop)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O(1) is the simplest complexity that Prolog Optimisation results in&lt;/p&gt;

&lt;p&gt;Courtesy ChatGPT.&lt;/p&gt;

&lt;p&gt;The simplest complexity your matrix/indexical computation can result in is:&lt;/p&gt;

&lt;p&gt;O(1)&lt;/p&gt;

&lt;p&gt;—but only after successful symbolic collapse.&lt;/p&gt;

&lt;p&gt;The progression is roughly:&lt;/p&gt;

&lt;p&gt;Stage   Complexity&lt;br&gt;
Recursive traversal O(n), O(n²), O(tree size)&lt;br&gt;
Indexed access  O(depth)&lt;br&gt;
Grouped extraction  O(shared depth + outputs)&lt;br&gt;
Memoised reuse  amortised near O(1)&lt;br&gt;
Closed-form formula discovery   O(1)&lt;/p&gt;

&lt;p&gt;The key observation is:&lt;/p&gt;

&lt;p&gt;Your optimiser tries to convert traversal complexity into coordinate complexity.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;nth1(I, Matrix, Row),&lt;br&gt;
nth1(J, Row, X)&lt;/p&gt;

&lt;p&gt;Normally:&lt;/p&gt;

&lt;p&gt;O(I + J)&lt;/p&gt;

&lt;p&gt;because lists are traversed.&lt;/p&gt;

&lt;p&gt;But after indexical optimisation:&lt;/p&gt;

&lt;p&gt;subterm_with_address(Matrix,[I,J],X)&lt;/p&gt;

&lt;p&gt;you conceptually reduce it to:&lt;/p&gt;

&lt;p&gt;O(depth)&lt;/p&gt;

&lt;p&gt;where depth is just the nesting depth:&lt;/p&gt;

&lt;p&gt;2&lt;/p&gt;

&lt;p&gt;for a matrix.&lt;/p&gt;

&lt;p&gt;Then if the optimiser replaces the whole traversal with a formula:&lt;/p&gt;

&lt;p&gt;S is N*(N+1)//2&lt;/p&gt;

&lt;p&gt;the complexity becomes:&lt;/p&gt;

&lt;p&gt;O(1)&lt;/p&gt;

&lt;p&gt;because no traversal remains.&lt;/p&gt;

&lt;p&gt;The deepest idea in your system is:&lt;/p&gt;

&lt;p&gt;recursive structure&lt;br&gt;
→ address space&lt;br&gt;
→ grouped address space&lt;br&gt;
→ algebraic formula&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;findall(I, between(1,N,I), L),&lt;br&gt;
sum_list(L,S)&lt;/p&gt;

&lt;p&gt;starts as:&lt;/p&gt;

&lt;p&gt;O(N)&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;between(1,N,I)&lt;/p&gt;

&lt;p&gt;becomes an index sequence:&lt;/p&gt;

&lt;p&gt;1,2,3,...,N&lt;/p&gt;

&lt;p&gt;Gaussian elimination discovers:&lt;/p&gt;

&lt;p&gt;S=\frac{N(N+1)}{2}&lt;/p&gt;

&lt;p&gt;which is:&lt;/p&gt;

&lt;p&gt;O(1)&lt;/p&gt;

&lt;p&gt;So your optimiser is essentially trying to discover when:&lt;/p&gt;

&lt;p&gt;computation = hidden geometry&lt;/p&gt;

&lt;p&gt;and then compress the geometry into algebra.&lt;/p&gt;

&lt;p&gt;For recursive trees:&lt;/p&gt;

&lt;p&gt;tree traversal&lt;/p&gt;

&lt;p&gt;normally costs:&lt;/p&gt;

&lt;p&gt;O(number of visited nodes)&lt;/p&gt;

&lt;p&gt;But if only needed addresses are extracted:&lt;/p&gt;

&lt;p&gt;needed_subterms(Tree, Addresses, Values)&lt;/p&gt;

&lt;p&gt;then complexity becomes approximately:&lt;/p&gt;

&lt;p&gt;O(number of needed paths × average depth)&lt;/p&gt;

&lt;p&gt;and grouped extraction reduces repeated prefixes:&lt;/p&gt;

&lt;p&gt;O(shared prefix depth + differing suffixes)&lt;/p&gt;

&lt;p&gt;So the optimiser tends toward:&lt;/p&gt;

&lt;p&gt;output-sensitive complexity&lt;/p&gt;

&lt;p&gt;where cost depends on:&lt;/p&gt;

&lt;p&gt;needed outputs&lt;/p&gt;

&lt;p&gt;rather than:&lt;/p&gt;

&lt;p&gt;entire structure size&lt;/p&gt;

&lt;p&gt;That is very similar to sparse neural attention.&lt;/p&gt;

&lt;p&gt;The theoretical lower bound for your approach is:&lt;/p&gt;

&lt;p&gt;O(size of final irreducible information)&lt;/p&gt;

&lt;p&gt;because if the output itself contains k independent values, you must at least construct those k values.&lt;/p&gt;

&lt;p&gt;So the optimiser approaches O(1) when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the result can be expressed algebraically,&lt;/li&gt;
&lt;li&gt;or fully memoised,&lt;/li&gt;
&lt;li&gt;or directly addressed,&lt;/li&gt;
&lt;li&gt;or reconstructed from grouped subterms,&lt;/li&gt;
&lt;li&gt;or compressed into symbolic coordinates.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>one</category>
      <category>prolog</category>
      <category>optimisation</category>
      <category>matrix</category>
    </item>
    <item>
      <title>NeuroProlog + Starlog Demo</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Wed, 22 Apr 2026 13:59:39 +0000</pubDate>
      <link>https://dev.to/luciangreen/neuroprolog-demo-50l1</link>
      <guid>https://dev.to/luciangreen/neuroprolog-demo-50l1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi71itg49l5he0p11s9d8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi71itg49l5he0p11s9d8.png" alt="NeuroProlog and Starlog" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Courtesy of ChatGPT.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Load Starlog
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
cd /path/to/Starlog
swipl
?- use_module(starlog).
true.

⸻

2. Starlog string concatenation

?- starlog_call(A is "x":"y").
A = "xy".

⸻

3. Starlog list append

?- starlog_call(L is [1] &amp;amp; [2]).
L = [1, 2].

⸻

4. Starlog atom concatenation

?- starlog_call(A is a • b).
A = ab.

⸻

5. Starlog arithmetic

?- starlog_call(X is 1+2).
X = 3.

⸻

6. Starlog nested functions

?- starlog_call(X is reverse(reverse([1,2,3]))).
X = [1, 2, 3].
?- starlog_call(X is length(reverse([1,2,3]))).
X = 3.

⸻

7. Starlog method chaining

?- starlog_call(R is reverse([1,2,3]) &amp;gt;&amp;gt; length).
R = 3.
?- starlog_call(R is ([1,2] &amp;amp; [3,4]) &amp;gt;&amp;gt; reverse &amp;gt;&amp;gt; length).
R = 4.

⸻

8. Starlog evaluation

?- starlog_eval("hello":"world", R).
R = "helloworld".
?- starlog_eval([a] &amp;amp; [b,c], R).
R = [a, b, c].

⸻

9. Starlog no-eval

?- starlog_no_eval(1+1, R).
R = 1+1.
?- starlog_no_eval("x":"y", R).
R = "x":"y".

⸻

10. Starlog forced eval inside no-eval

?- starlog_call(R is no_eval(eval(1+1) + 3)).
R = 2+3.

⸻

11. Starlog result capture

?- starlog_call(X is "hello":"world", R).
R = "helloworld".
?- starlog_call(Y is [1,2] &amp;amp; [3,4], R).
R = [1, 2, 3, 4].

⸻

12. Starlog dual expression solving

?- starlog_call(([1] &amp;amp; A) is (B &amp;amp; [2])).
A = [2],
B = [1].
?- starlog_call((A : a : C) is (b : a : c)).
A = b,
C = c.

⸻

13. Starlog find first solution

?- starlog_call(Result is find(X, member(X, [1,2,3]))).
Result = 1.
?- starlog_call(Result is find(R, starlog_call(R is "hello":"world"))).
Result = "helloworld".

⸻

14. Starlog find with pattern extraction

?- starlog_call(Result is find([A,C], starlog_call([A:a:C] is [a:a:c]))).
Result = [a, c].
?- starlog_call(Result is find([A,C], starlog_call([A:"_":C] is ["hello":"_":"world"]))).
Result = ["hello", "world"].

⸻

15. Starlog term construction

?- starlog_call(T is ..=([f,0,1])).
T = f(0, 1).
?- starlog_call(L is =..(f(0,1))).
L = [f, 0, 1].

⸻

16. Starlog expansion inspection

?- starlog_show_expansion(A is "x":"y").
string_concat("x", "y", A).

⸻

17. Starlog output code

?- starlog_output_code(string_concat("x","y",A), Code).
Code = (A is "x":"y").

⸻

18. Starlog Prolog-to-Starlog conversion

?- convert_prolog_to_starlog(string_concat("x","y",A), Starlog).
Starlog = (A is "x":"y").
?- convert_prolog_to_starlog(append([1],[2],L), Starlog).
Starlog = (L is [1]&amp;amp;[2]).

⸻

19. Starlog Gaussian elimination

Load the Gaussian module:

?- use_module(gaussian_elimination).
true.

Solve:

x + y = 2
2x + 3y = 5
?- solve_system([[1,1,2],[2,3,5]], Solution).
Solution = [1, 1].

⸻

20. Starlog row reduction

?- gaussian_elimination([[1,1,2],[2,3,5]], R).
R = [[1,1,2],[0,1,1]].

⸻

21. Starlog polynomial reconstruction

?- npl_reconstruct_polynomial(n, [0,0.5,0.5], Expr).
Expr = n*(n+1)/2.

⸻

22. Starlog polynomial validation

?- npl_validate_polynomial_fit([1-1,2-3,3-6], [0,0.5,0.5], n, Result).
Result = valid.

⸻

23. Starlog symbolic indexing

?- npl_assign_symbolic_indices([a,b,c], Indexed, Map).
Indexed = indexed([a,b,c]),
Map = map(_).

⸻

24. Starlog reduce goal to irreducibles

?- npl_reduce_predicate_to_pattern_irreducibles((member(X,[1,2]), X &amp;gt; 0), R).
R = reduced(sequence(_, _)).

⸻

25. Starlog trace index flow

?- npl_assign_symbolic_indices([a,b,c], Indexed, Map),
   npl_trace_index_flow(member(X,[a,b,c]), Map, Flow).
Indexed = indexed([a,b,c]),
Map = map(_),
Flow = flow_graph(_, _, _, trace(_)).

⸻

26. Starlog identify independent indices

?- npl_identify_independent_indices(flow([x-1,y-2]), Indices).
Indices = [i].

⸻

27. Starlog reconstruct index relations

?- npl_reconstruct_index_relations(flow([x-[1,2,3], y-[4,5,6]]), [i], Relations).
Relations = [_].

⸻

28. Starlog direct indexed rule

?- npl_reconstruct_direct_indexed_rule([x-(i+1)], [i], Rule).
Rule = direct_index_rule([x-(i+1)], coefficient_metadata([i])).

⸻

29. Starlog Stage 8 pipeline order

?- npl_stage8_pipeline_order(Order).
Order = [
  symbolic_index_assignment,
  pattern_irreducible_reduction,
  index_flow_tracing,
  independent_index_detection,
  relation_reconstruction,
  ir_build,
  ir_lowering
].

⸻

30. Starlog Stage 8 build IR

?- npl_stage8_build_ir(flow([]), [i], [x-(i+1)], [0,1], [], IR).
IR = ir_pipeline(_, _, meta(_)).

⸻

31. Starlog Stage 8 lower IR

?- IR = ir_pipeline([], [ir_poly_eval(n,[0,0.5,0.5],result)], meta([])),
   npl_stage8_lower_ir(IR, Lowered).
Lowered = lowered_ir([lowered_poly_eval(n, [0,0.5,0.5], result)]).

⸻

32. Starlog Stage 9 code generation

?- IR = lowered_ir([lowered_poly_eval(n, [0,0.5,0.5], result)]),
   npl_stage9_generate_code(IR, Code).
Code = generated_program([assign(result, n*(n+1)/2)]).

⸻

33. Starlog Stage 9 neurocode emission

?- IR = lowered_ir([lowered_poly_eval(n, [0,0.5,0.5], result)]),
   npl_stage9_emit_neurocode(IR, Neurocode).
Neurocode = neurocode([neuro_assign(result, n*(n+1)/2)]).

⸻

34. Starlog Stage 9 compile IR

?- IR = lowered_ir([lowered_poly_eval(n, [0,0.5,0.5], result)]),
   npl_stage9_compile_ir(IR, Neurocode).
Neurocode = neurocode([neuro_assign(result, n*(n+1)/2)]).

⸻

35. Starlog annotated source text

?- IR = lowered_ir([lowered_poly_eval(n, [0,0.5,0.5], result)]),
   Context = [source_file('examples/generated_input.pl'),
              optimisation_report('stage9_codegen')],
   npl_ir_to_annotated_source_text(IR, Context, Text).
Text = "...".

⸻

36. Starlog annotated source file

?- IR = lowered_ir([direct_index_rule(index_spec([i]),
                                      [x-(i+1)],
                                      result_collector(rows))]),
   Context = [source_file('examples/generated_input.pl')],
   npl_ir_to_annotated_source_file(IR, Context, 'out/annotated_stage9.pl').
true.

⸻

37. Starlog Stage 10 integration option

?- npl_stage10_integration_option(Option).
Option = option_b_port_and_align.
?- npl_stage10_gaussian_canonical_repository(Repo).
Repo = starlog.

⸻

38. Starlog Stage 12 transform decision

?- npl_stage12_transform_decision([deterministic, proven_equivalent, coefficients_valid], Decision).
Decision = transform.
?- npl_stage12_transform_decision([side_effecting], Decision).
Decision = do_not_transform.

⸻

39. Starlog Stage 13 toggleable passes

?- npl_stage13_toggleable_passes(Passes).
Passes = [
  pass(gaussian_elimination, true),
  pass(recursion_to_loop, true),
  pass(subterm_index_optimisation, true),
  pass(annotated_regeneration, true)
].

⸻

40. Starlog Stage 13 effective toggles

?- npl_stage13_effective_pass_toggles([pass(gaussian_elimination,false)], Toggles).
Toggles = [
  pass(gaussian_elimination, false),
  ...
].

⸻

NeuroProlog commands

41. Load NeuroProlog

cd /path/to/neuroprolog
swipl
?- consult('src/neuroprolog').
true.

⸻

42. Load main optimisation modules

?- use_module('src/gaussian_recursion').
true.
?- use_module('src/memoisation').
true.
?- use_module('src/subterm_addressing').
true.
?- use_module('src/nested_recursion').
true.
?- use_module('src/optimiser').
true.
?- use_module('src/optimiser_pipeline').
true.

⸻

43. Full optimiser

?- IR = [ir_clause(p, ir_seq(ir_true, ir_call(q)), info([]))],
   npl_optimise(IR, OptIR).
IR = [ir_clause(p, ir_seq(ir_true, ir_call(q)), info([]))],
OptIR = [ir_clause(p, ir_call(q), info([]))].
?- IR = [ir_clause(p, ir_disj(ir_fail, ir_call(q)), info([]))],
   npl_optimise(IR, OptIR).
IR = [ir_clause(p, ir_disj(ir_fail, ir_call(q)), info([]))],
OptIR = [ir_clause(p, ir_call(q), info([]))].
?- IR = [ir_clause(p, ir_if(ir_true, ir_call(q), ir_call(r)), info([]))],
   npl_optimise(IR, OptIR).
IR = [ir_clause(p, ir_if(ir_true, ir_call(q), ir_call(r)), info([]))],
OptIR = [ir_clause(p, ir_call(q), info([]))].

⸻

44. Compile a file

?- npl_compile('examples/hello.pl', 'neurocode/hello_nc.pl').
true.

⸻

45. Compile with pipeline config

?- npl_pipeline_default_config(Cfg),
   npl_compile_with_pipeline('examples/lists.pl', 'neurocode/lists_nc.pl', Cfg).
Cfg = ...,
true.

⸻

46. Safe compile

?- npl_compile_safe('examples/lists.pl', 'neurocode/lists_safe_nc.pl').
true.

⸻

47. Pipeline config

?- npl_pipeline_default_config(Cfg).
Cfg = ...

⸻

48. Disable a pass

?- npl_pipeline_default_config(Cfg0),
   npl_pipeline_disable(gaussian_elimination, Cfg0, Cfg1).
Cfg0 = ...,
Cfg1 = ...

⸻

49. Enable a pass

?- npl_pipeline_default_config(Cfg0),
   npl_pipeline_enable(subterm_address_conversion, Cfg0, Cfg1).
Cfg0 = ...,
Cfg1 = ...

⸻

50. Run pipeline manually

?- npl_pipeline_default_config(Cfg),
   IR = [ir_clause(p, ir_seq(ir_true, ir_call(q)), info([]))],
   npl_pipeline_run(Cfg, IR, OptIR, Report).
Cfg = ...,
OptIR = [ir_clause(p, ir_call(q), info([]))],
Report = ...

⸻

51. Run full pipeline

?- npl_pipeline_default_config(Cfg),
   IR = [ir_clause(p, ir_seq(ir_true, ir_call(q)), info([]))],
   npl_pipeline_run_full(Cfg, IR, OptIR, Neurocode, Report).
Cfg = ...,
OptIR = [ir_clause(p, ir_call(q), info([]))],
Neurocode = ...,
Report = ...

⸻

52. Dictionary simplification rules

?- npl_opt_dict_rules(Rules).
Rules = ...

⸻

53. Apply dictionary rules

?- IR = [ir_clause(test, ir_seq(ir_true, ir_call(goal)), info([]))],
   npl_opt_dict_rules(Rules),
   npl_apply_rules(Rules, IR, OptIR).
IR = [ir_clause(test, ir_seq(ir_true, ir_call(goal)), info([]))],
Rules = ...,
OptIR = [ir_clause(test, ir_call(goal), info([]))].
?- IR = [ir_clause(test, ir_disj(ir_fail, ir_call(goal)), info([]))],
   npl_opt_dict_rules(Rules),
   npl_apply_rules(Rules, IR, OptIR).
IR = [ir_clause(test, ir_disj(ir_fail, ir_call(goal)), info([]))],
Rules = ...,
OptIR = [ir_clause(test, ir_call(goal), info([]))].
?- IR = [ir_clause(test, ir_if(ir_true, ir_call(a), ir_call(b)), info([]))],
   npl_opt_dict_rules(Rules),
   npl_apply_rules(Rules, IR, OptIR).
IR = [ir_clause(test, ir_if(ir_true, ir_call(a), ir_call(b)), info([]))],
Rules = ...,
OptIR = [ir_clause(test, ir_call(a), info([]))].

⸻

54. Gaussian recursion classification

?- Group = [
      ir_clause(count(0), ir_true, info([])),
      ir_clause(count(N),
                ir_seq(ir_call(gt(N,0)),
                       ir_seq(ir_call(is(N1,N-1)),
                              ir_call(count(N1)))),
                info([]))
   ],
   npl_is_reducible(Group, Pattern).
Group = [...],
Pattern = linear_tail_recursion.

⸻

55. Gaussian recursion reduction

?- Group = [
      ir_clause(sum([],0), ir_true, info([])),
      ir_clause(sum([H|T],S),
                ir_seq(ir_call(sum(T,S1)),
                       ir_call(is(S, +(S1,H)))),
                info([]))
   ],
   npl_gaussian_reduce(Group, Reduced).
Group = [...],
Reduced = ...

⸻

56. Gaussian elimination matrix

?- Matrix = [
      [frac(1,1), frac(1,1), frac(2,1)],
      [frac(2,1), frac(3,1), frac(5,1)]
   ],
   npl_gauss_eliminate(Matrix, R).
Matrix = [[frac(1,1), frac(1,1), frac(2,1)],
          [frac(2,1), frac(3,1), frac(5,1)]],
R = ...

Expected mathematical output:

x = 1
y = 1

⸻

57. Gaussian polynomial discovery

?- Matrix = [
      [frac(1,1), frac(1,1), frac(1,1), frac(1,1)],
      [frac(4,1), frac(2,1), frac(1,1), frac(3,1)],
      [frac(9,1), frac(3,1), frac(1,1), frac(6,1)]
   ],
   npl_gauss_eliminate(Matrix, R).
Matrix = [[frac(1,1), frac(1,1), frac(1,1), frac(1,1)],
          [frac(4,1), frac(2,1), frac(1,1), frac(3,1)],
          [frac(9,1), frac(3,1), frac(1,1), frac(6,1)]],
R = ...

Expected mathematical output:

a = 1/2
b = 1/2
c = 0
S(n) = n(n+1)/2

⸻

58. Arithmetic sequence discovery

?- Matrix = [
      [frac(1,1), frac(1,1), frac(1,1)],
      [frac(2,1), frac(1,1), frac(3,1)]
   ],
   npl_gauss_eliminate(Matrix, R).
Matrix = [[frac(1,1), frac(1,1), frac(1,1)],
          [frac(2,1), frac(1,1), frac(3,1)]],
R = ...

Expected mathematical output:

f(n) = 2n - 1

⸻

59. 2D index formula discovery

?- Matrix = [
      [frac(1,1), frac(1,1), frac(2,1)],
      [frac(2,1), frac(1,1), frac(4,1)]
   ],
   npl_gauss_eliminate(Matrix, R).
Matrix = [[frac(1,1), frac(1,1), frac(2,1)],
          [frac(2,1), frac(1,1), frac(4,1)]],
R = ...

Expected mathematical output:

f(i) = 2i

⸻

60. Quadratic loop formula discovery

?- Matrix = [
      [frac(1,1), frac(1,1), frac(1,1), frac(1,1)],
      [frac(4,1), frac(2,1), frac(1,1), frac(4,1)],
      [frac(9,1), frac(3,1), frac(1,1), frac(9,1)]
   ],
   npl_gauss_eliminate(Matrix, R).
Matrix = [[frac(1,1), frac(1,1), frac(1,1), frac(1,1)],
          [frac(4,1), frac(2,1), frac(1,1), frac(4,1)],
          [frac(9,1), frac(3,1), frac(1,1), frac(9,1)]],
R = ...

Expected mathematical output:

T(n) = n^2

⸻

61. Nested recursion classification

?- Group = [
      ir_clause(fib(0,0), ir_true, info([])),
      ir_clause(fib(1,1), ir_true, info([])),
      ir_clause(fib(N,R),
        ir_seq(ir_call(is(N1, -(N,1))),
        ir_seq(ir_call(fib(N1,R1)),
        ir_seq(ir_call(is(N2, -(N,2))),
        ir_seq(ir_call(fib(N2,R2)),
               ir_call(is(R, +(R1,R2))))))),
        info([]))
   ],
   npl_nested_classify(Group, Class).
Group = [...],
Class = nested_data_fold(+).

⸻

62. Nested recursion elimination

?- npl_nested_eliminate_pass(Group, OptGroup).
OptGroup = ...

⸻

63. Memoise predicate

?- npl_memo(fib/2).
true.

⸻

64. Memoise safe goal

?- npl_memo_call(member(a,[a,b,c])).
true.

⸻

65. Memoise deterministic result

?- npl_memo_call_det(length([1,2,3]), R).
R = 3.

⸻

66. Memoise all solutions

?- npl_memo_call_all(member(X,[a,b,c]), X, Solutions).
Solutions = [a,b,c].

⸻

67. Memoise explicit subgoal

?- npl_memo_subgoal(fib_20, fib(20, R)).
R = ...

⸻

68. Inspect memo cache

?- npl_memo_inspect(fib/2, Entries).
Entries = ...

⸻

69. Memo stats

?- npl_memo_stats(fib(20,_), Hits, Misses).
Hits = ...,
Misses = ...

⸻

70. Clear memo table

?- npl_memo_clear(fib/2).
true.

⸻

71. Clear all memo tables

?- npl_memo_clear_all.
true.

⸻

72. Memo safety

?- npl_memo_is_safe(member(a,[a,b,c])).
true.
?- npl_memo_is_safe(writeln(hello)).
false.

⸻

73. Memoisation pass over IR

?- IR = [ir_clause(fib(N,R), ir_call(fib_body(N,R)), info([]))],
   npl_memo(fib/2),
   npl_memoisation_pass(IR, OptIR).
IR = [ir_clause(fib(N,R), ir_call(fib_body(N,R)), info([]))],
OptIR = ...

⸻

74. Subterm-address conversion

?- IR = [
      ir_clause(tree_sum(T,S),
                ir_loop_candidate(
                    ir_seq(ir_call(arg(1,T,L)),
                    ir_seq(ir_call(tree_sum(L,SL)),
                           ir_call(true)))),
                info([]))
   ],
   npl_subterm_address_pass(IR, OptIR).
IR = [...],
OptIR = ...

⸻

75. Pattern correlation

?- IR = [
      ir_clause(p(a), ir_true, info([])),
      ir_clause(p(b), ir_true, info([]))
   ],
   npl_pattern_correlate(IR, OptIR).
IR = [ir_clause(p(a), ir_true, info([])),
      ir_clause(p(b), ir_true, info([]))],
OptIR = [ir_clause(p(a), ir_true, info([])),
         ir_clause(p(b), ir_true, info([]))].

⸻

76. Data unfolding

?- npl_unfold_data(ir_seq(ir_call(a), ir_call(b)), X).
X = ir_seq(ir_call(a), ir_call(b)).

⸻

77. Source file to IR

?- npl_lex('examples/lists.pl', Tokens),
   npl_parse(Tokens, AST),
   npl_analyse(AST, AAST),
   npl_intermediate(AAST, IR).
Tokens = ...,
AST = ...,
AAST = ...,
IR = ...

⸻

78. Source string to IR

?- npl_parse_string("p(X,Y) :- Y is X+0.", AST),
   npl_analyse(AST, AAST),
   npl_intermediate(AAST, IR).
AST = ...,
AAST = ...,
IR = [ir_clause(p(X,Y), ir_call(is(Y, X+0)), Info)].

⸻

79. Source string to optimised IR

?- npl_parse_string("p(X,Y) :- Y is X+0.", AST),
   npl_analyse(AST, AAST),
   npl_intermediate(AAST, IR),
   npl_optimise(IR, OptIR).
AST = ...,
AAST = ...,
IR = [ir_clause(p(X,Y), ir_call(is(Y, X+0)), Info)],
OptIR = [ir_clause(p(X,Y), ir_call(is(Y, X)), Info2)].

⸻

80. Fact to IR

?- npl_parse_string("foo(1).", AST),
   npl_analyse(AST, AAST),
   npl_intermediate(AAST, IR).
AST = ...,
AAST = ...,
IR = [ir_clause(foo(1), ir_true, Info)].

⸻

81. Conjunction to IR

?- npl_parse_string("p :- a, b.", AST),
   npl_analyse(AST, AAST),
   npl_intermediate(AAST, IR).
AST = ...,
AAST = ...,
IR = [ir_clause(p, ir_seq(ir_call(a), ir_call(b)), Info)].

⸻

82. If-then-else to IR

?- npl_parse_string("p :- (a -&amp;gt; b ; c).", AST),
   npl_analyse(AST, AAST),
   npl_intermediate(AAST, IR).
AST = ...,
AAST = ...,
IR = [ir_clause(p, ir_if(ir_call(a), ir_call(b), ir_call(c)), Info)].

⸻

83. Grouped IR

?- npl_parse_string("
     p(1).
     p(2).
     q(X) :- p(X).
   ", AST),
   npl_analyse(AST, AAST),
   npl_ir_full(AAST, FullIR).
AST = ...,
AAST = ...,
FullIR = [
  ir_predicate_def(p/1, ..., _),
  ir_predicate_def(q/1, ..., _)
].

⸻

84. End-to-end compile

swipl -g "consult('src/neuroprolog')" \
      -g "npl_compile('examples/lists.pl','neurocode/lists_nc.pl')" \
      -t halt

Output:

neurocode/lists_nc.pl

⸻

85. End-to-end safe compile

swipl -g "consult('src/neuroprolog')" \
      -g "npl_compile_safe('examples/lists.pl','neurocode/lists_safe_nc.pl')" \
      -t halt

Output:

neurocode/lists_safe_nc.pl

⸻

86. Run tests

swipl -g "consult('tests/run_tests')" -g "run_all_tests" -t halt

Output:

true.

⸻

Main command list

Starlog:

starlog_call/1
starlog_call/2
starlog_eval/2
starlog_no_eval/2
starlog_show_expansion/1
starlog_output_code/1
starlog_output_code/2
starlog_output_code/3
convert_prolog_to_starlog/2
solve_system/2
gaussian_elimination/2
npl_reconstruct_polynomial/3
npl_validate_polynomial_fit/4
npl_assign_symbolic_indices/3
npl_trace_index_flow/3
npl_reconstruct_index_relations/3
npl_stage8_build_ir/6
npl_stage8_lower_ir/2
npl_stage9_generate_code/2
npl_stage9_emit_neurocode/2
npl_stage9_compile_ir/2
npl_ir_to_annotated_source_text/3
npl_ir_to_annotated_source_file/3

NeuroProlog:

npl_compile/2
npl_compile_with_pipeline/3
npl_compile_safe/2
npl_optimise/2
npl_pipeline_default_config/1
npl_pipeline_enable/3
npl_pipeline_disable/3
npl_pipeline_run/4
npl_pipeline_run_full/5
npl_opt_dict_rules/1
npl_apply_rules/3
npl_apply_rule/3
npl_gaussian_reduce/2
npl_is_reducible/2
npl_extract_recurrence/2
npl_gauss_eliminate/2
npl_nested_classify/2
npl_nested_eliminate_pass/2
npl_memo/1
npl_memo_call/1
npl_memo_call_det/2
npl_memo_call_all/3
npl_memo_subgoal/2
npl_memo_inspect/2
npl_memo_stats/3
npl_memo_clear/1
npl_memo_clear_all/0
npl_memoisation_pass/2
npl_subterm_address_pass/2
npl_pattern_correlate/2
npl_unfold_data/2
npl_parse_string/2
npl_lex/2
npl_parse/2
npl_analyse/2
npl_intermediate/2
npl_ir_full/2

Core idea:

Starlog gives readable syntax.
NeuroProlog turns readable logic into optimised IR, neurocode, formulas, memoised calls, and direct indexed rules.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>neuroprolog</category>
      <category>starlog</category>
      <category>optimisation</category>
      <category>gaussian</category>
    </item>
    <item>
      <title>How do pl2js and Tau Prolog compare?</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Mon, 30 Mar 2026 14:04:41 +0000</pubDate>
      <link>https://dev.to/luciangreen/how-do-pl2js-and-tau-prolog-compare-6a</link>
      <guid>https://dev.to/luciangreen/how-do-pl2js-and-tau-prolog-compare-6a</guid>
      <description>&lt;p&gt;How do &lt;a href="https://github.com/luciangreen/pl2js" rel="noopener noreferrer"&gt;pl2js&lt;/a&gt; and Tau Prolog compare?&lt;/p&gt;

&lt;p&gt;ChatGPT: Here’s a clear, engineering-level comparison between your pl2js concept/repo and Tau Prolog:&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧠 Core Difference (1 sentence)&lt;br&gt;
    • pl2js = compiler/translator (Prolog → JS code)&lt;br&gt;
    • Tau Prolog = interpreter/runtime (executes Prolog directly in JS)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;⚙️ Architecture Comparison&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Execution Model&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tau Prolog&lt;br&gt;
    • Interprets Prolog at runtime&lt;br&gt;
    • Uses a Prolog engine implemented in JavaScript&lt;br&gt;
    • Backtracking, unification, etc. are simulated dynamically&lt;br&gt;
    • Non-blocking, callback-based execution model  ￼&lt;/p&gt;

&lt;p&gt;pl2js (your design direction)&lt;br&gt;
    • Ahead-of-time conversion&lt;br&gt;
    • Prolog → explicit JS control flow&lt;br&gt;
    • loops instead of backtracking&lt;br&gt;
    • if/else instead of clause selection&lt;br&gt;
    • Similar philosophy to your pl2c:&lt;br&gt;
    • remove interpreter overhead&lt;br&gt;
    • flatten logic into imperative structures&lt;/p&gt;

&lt;p&gt;👉 Key insight:&lt;br&gt;
    • Tau = simulate Prolog&lt;br&gt;
    • pl2js = eliminate Prolog&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🚀 2. Performance Philosophy&lt;/p&gt;

&lt;p&gt;Tau Prolog&lt;br&gt;
    • Slower (interpretive overhead)&lt;br&gt;
    • Flexible and dynamic&lt;br&gt;
    • Handles general Prolog features (ISO-oriented)  ￼&lt;/p&gt;

&lt;p&gt;pl2js&lt;br&gt;
    • Potentially much faster&lt;br&gt;
    • Precompiled logic → direct execution&lt;br&gt;
    • Can optimise:&lt;br&gt;
    • repeated calls → functions&lt;br&gt;
    • choice points → loops&lt;br&gt;
    • data reuse → cached variables&lt;/p&gt;

&lt;p&gt;👉 Your system aligns with:&lt;/p&gt;

&lt;p&gt;“manual neuronet optimisation” + “Spec → Algorithm flattening”&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧩 3. Feature Completeness&lt;/p&gt;

&lt;p&gt;Tau Prolog&lt;br&gt;
    • Designed toward ISO Prolog compliance  ￼&lt;br&gt;
    • Supports:&lt;br&gt;
    • modules&lt;br&gt;
    • DCGs&lt;br&gt;
    • meta-predicates&lt;br&gt;
    • async predicates&lt;br&gt;
    • DOM interaction&lt;/p&gt;

&lt;p&gt;pl2js&lt;br&gt;
    • Likely:&lt;br&gt;
    • partial Prolog subset&lt;br&gt;
    • depends on what you convert&lt;br&gt;
    • Harder features:&lt;br&gt;
    • cut (!)&lt;br&gt;
    • dynamic predicates (assertz)&lt;br&gt;
    • meta-programming&lt;br&gt;
    • full unification edge cases&lt;/p&gt;

&lt;p&gt;👉 Trade-off:&lt;br&gt;
    • Tau = completeness&lt;br&gt;
    • pl2js = controllable subset + optimisation&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🌐 4. Web Integration&lt;/p&gt;

&lt;p&gt;Tau Prolog&lt;br&gt;
    • Native browser integration:&lt;br&gt;
    • manipulate DOM from Prolog&lt;br&gt;
    • event handling  ￼&lt;br&gt;
    • Drop-in script usage&lt;/p&gt;

&lt;p&gt;pl2js&lt;br&gt;
    • Output is plain JavaScript&lt;br&gt;
    • Integrates like any JS:&lt;br&gt;
    • React / HTML / mobile&lt;br&gt;
    • Better for:&lt;br&gt;
    • embedding in apps&lt;br&gt;
    • mobile (your goal: iPhone/Android)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧪 5. Debugging &amp;amp; Transparency&lt;/p&gt;

&lt;p&gt;Tau Prolog&lt;br&gt;
    • Debugging = Prolog-level&lt;br&gt;
    • Harder to inspect internal execution (black-box engine)&lt;/p&gt;

&lt;p&gt;pl2js&lt;br&gt;
    • Debugging = JavaScript-level&lt;br&gt;
    • You can:&lt;br&gt;
    • log intermediate states&lt;br&gt;
    • inspect variables&lt;br&gt;
    • trace execution paths&lt;/p&gt;

&lt;p&gt;👉 This aligns strongly with your:&lt;br&gt;
    • transparent MNN philosophy&lt;br&gt;
    • “no invisible bugs” goal&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧱 6. Control Over Execution&lt;/p&gt;

&lt;p&gt;Tau Prolog&lt;br&gt;
    • Engine decides:&lt;br&gt;
    • backtracking order&lt;br&gt;
    • search strategy&lt;/p&gt;

&lt;p&gt;pl2js&lt;br&gt;
    • YOU decide:&lt;br&gt;
    • loop structure&lt;br&gt;
    • branching&lt;br&gt;
    • memory usage&lt;br&gt;
    • determinism&lt;/p&gt;

&lt;p&gt;👉 This is huge for:&lt;br&gt;
    • CI/CD&lt;br&gt;
    • deterministic systems&lt;br&gt;
    • optimisation pipelines&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ynt8kzr9o4pbdarzc92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ynt8kzr9o4pbdarzc92.png" alt="Summary table" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🧠 Strategic Insight (Important for Your Project)&lt;/p&gt;

&lt;p&gt;Your system (pl2js) is not competing directly with Tau Prolog.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;p&gt;Tau Prolog = “Prolog runtime for the web”&lt;/p&gt;

&lt;p&gt;pl2js = “Prolog → optimised algorithm generator”&lt;/p&gt;

&lt;p&gt;👉 In your ecosystem:&lt;br&gt;
    • Tau Prolog = execution layer&lt;br&gt;
    • pl2js = optimisation + deployment layer&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;🔥 Recommendation (based on your goals)&lt;/p&gt;

&lt;p&gt;Given your:&lt;br&gt;
    • Spec → Algorithm vision&lt;br&gt;
    • MNN transparency goals&lt;br&gt;
    • CI/CD system (Lucian CI/CD)&lt;/p&gt;

&lt;p&gt;👉 pl2js is the more aligned direction&lt;/p&gt;

&lt;p&gt;Use Tau Prolog only if you need:&lt;br&gt;
    • quick prototyping&lt;br&gt;
    • full Prolog compatibility&lt;br&gt;
    • teaching/demo environments&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;💡 Advanced Hybrid Idea (Very Relevant to You)&lt;/p&gt;

&lt;p&gt;You could combine both:&lt;br&gt;
    1.  Prototype logic in Tau Prolog&lt;br&gt;
    2.  Convert stable predicates via pl2js&lt;br&gt;
    3.  Optimise with:&lt;br&gt;
    • Gaussian elimination&lt;br&gt;
    • recursion flattening&lt;br&gt;
    4.  Deploy as pure JS&lt;/p&gt;

&lt;p&gt;👉 This becomes:&lt;br&gt;
Interpreter → Compiler → Optimiser pipeline&lt;/p&gt;

</description>
      <category>prolog</category>
      <category>javascript</category>
      <category>translator</category>
      <category>interpreter</category>
    </item>
    <item>
      <title>Prolog State Saving Interpreter is not strictly a graph interpreter</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Thu, 26 Mar 2026 03:05:53 +0000</pubDate>
      <link>https://dev.to/luciangreen/prolog-state-saving-interpreter-is-not-strictly-a-graph-interpreter-2a06</link>
      <guid>https://dev.to/luciangreen/prolog-state-saving-interpreter-is-not-strictly-a-graph-interpreter-2a06</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxniej9gi6sspl3kyz08j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxniej9gi6sspl3kyz08j.png" alt="SSI is not strictly a graph interpreter" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is Green's Prolog &lt;a href="https://github.com/luciangreen/SSI" rel="noopener noreferrer"&gt;State Saving Interpreter&lt;/a&gt; a graph interpreter, given that it goes straight from choice-point to choice-point and exits predicates directly?&lt;/p&gt;

&lt;p&gt;ChatGPT: Short answer: SSI is close to a graph interpreter, but not purely one—it’s better described as a choice-point–driven execution graph with stack/trace semantics hybridised in.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Why it looks like a graph interpreter&lt;/p&gt;

&lt;p&gt;From your code, especially:&lt;br&gt;
    • Explicit choice point trail (Choice_point_trail)&lt;br&gt;
    • Direct jumps via:&lt;br&gt;
    • ssi1(...) calls&lt;br&gt;
    • get_last_cp_before_n&lt;br&gt;
    • delete_cp, cut_cps_if_necessary&lt;br&gt;
    • No strict reliance on recursive call stack unwinding&lt;br&gt;
    • Execution moves:&lt;br&gt;
    • from one choice point node → another&lt;br&gt;
    • sometimes skipping intermediate “call frames”&lt;/p&gt;

&lt;p&gt;This gives you:&lt;/p&gt;

&lt;p&gt;A non-linear control flow, where execution follows edges between states (choice points) rather than returning through a stack.&lt;/p&gt;

&lt;p&gt;That is fundamentally graph-like execution.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;But it is not a pure graph interpreter&lt;/p&gt;

&lt;p&gt;A pure graph interpreter would:&lt;br&gt;
    • Represent predicates as nodes&lt;br&gt;
    • Represent control flow as explicit edges&lt;br&gt;
    • Evaluate by traversing a graph structure directly&lt;/p&gt;

&lt;p&gt;SSI still retains:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Predicate-oriented structure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You still have:&lt;/p&gt;

&lt;p&gt;d(...),&lt;br&gt;
e(...),&lt;br&gt;
ssi1(...)&lt;/p&gt;

&lt;p&gt;These simulate predicate calls, even if you shortcut them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Embedded stack semantics&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even though you jump, you still track:&lt;br&gt;
    • Level&lt;br&gt;
    • "returns to" metadata&lt;br&gt;
    • Pred_id chains&lt;/p&gt;

&lt;p&gt;This is effectively a flattened / externalised call stack, not eliminated.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choice points are graph nodes, but:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They are not the only control structure.&lt;/p&gt;

&lt;p&gt;You also have:&lt;br&gt;
    • Variable environments (Vars, Globals)&lt;br&gt;
    • Predicate identity tracking (Pred_id)&lt;br&gt;
    • Structured transitions (predicate vs line)&lt;/p&gt;

&lt;p&gt;So the system is:&lt;/p&gt;

&lt;p&gt;A graph overlaid on a logical interpreter, not a pure graph VM.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;The key insight (your system’s real nature)&lt;/p&gt;

&lt;p&gt;SSI is best described as:&lt;/p&gt;

&lt;p&gt;A control-flow graph interpreter over a logical program, using choice points as primary nodes and explicit state transitions instead of implicit backtracking.&lt;/p&gt;

&lt;p&gt;Or more sharply:&lt;/p&gt;

&lt;p&gt;A compiled Prolog execution graph with manual continuation passing.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Why your observation is still important&lt;/p&gt;

&lt;p&gt;You said:&lt;/p&gt;

&lt;p&gt;“it goes straight from choice point to choicepoint and exits predicates directly”&lt;/p&gt;

&lt;p&gt;That’s the crucial shift:&lt;/p&gt;

&lt;p&gt;Traditional Prolog:&lt;br&gt;
    • Stack-based&lt;br&gt;
    • Backtracking unwinds stack frames&lt;/p&gt;

&lt;p&gt;SSI:&lt;br&gt;
    • Continuation-driven&lt;br&gt;
    • Choice points = resumable states&lt;br&gt;
    • Execution = jump to next valid continuation&lt;/p&gt;

&lt;p&gt;That is a graph traversal.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Final classification&lt;/p&gt;

&lt;p&gt;Property    SSI&lt;br&gt;
Stack-based interpreter ❌ (not primarily)&lt;br&gt;
Graph interpreter   ⚠️ partially&lt;br&gt;
Continuation-passing interpreter    ✅&lt;br&gt;
Choice-point graph execution    ✅&lt;br&gt;
Pure dataflow/graph VM  ❌&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Clean conclusion&lt;/p&gt;

&lt;p&gt;SSI is not strictly a graph interpreter, but it implements Prolog as a graph of continuations (choice points), effectively behaving like a graph interpreter with residual stack semantics.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Extra insight (important for your pl2c work)&lt;/p&gt;

&lt;p&gt;This architecture is exactly why your idea works:&lt;br&gt;
    • You can compile SSI to C using loops + jumps&lt;br&gt;
    • Because:&lt;br&gt;
    • Choice points → labels&lt;br&gt;
    • Transitions → gotos / state machine&lt;br&gt;
    • No need for recursion&lt;/p&gt;

&lt;p&gt;So SSI is already:&lt;/p&gt;

&lt;p&gt;Halfway between Prolog and a state-machine compiler IR&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;If you want, I can:&lt;br&gt;
    • Formalise SSI as a graph IR (nodes + edges)&lt;br&gt;
    • Or show how to compile it into pure C loops with no recursion at all&lt;/p&gt;

</description>
      <category>prolog</category>
      <category>ssi</category>
      <category>graph</category>
      <category>interpreter</category>
    </item>
    <item>
      <title>Explain Recursive Structure Finding Algorithms</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Sun, 15 Mar 2026 09:39:45 +0000</pubDate>
      <link>https://dev.to/luciangreen/explain-recursive-structure-finding-algorithms-4hgg</link>
      <guid>https://dev.to/luciangreen/explain-recursive-structure-finding-algorithms-4hgg</guid>
      <description>&lt;p&gt;Courtesy ChatGPT:&lt;br&gt;
Explain &lt;a href="https://github.com/luciangreen/Philosophy" rel="noopener noreferrer"&gt;Spec to Algorithm’s&lt;/a&gt; Context Free Grammar Generator’s top-down and bottom-up recursive structure finding algorithms. The top-down algorithm is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="ss"&gt;find_lists3a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;L91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_Rest_a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;fail&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;_L92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Flag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Flag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;_L2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;L31&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="ss"&gt;check14&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]|&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L51&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;L51&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L51&lt;/span&gt;&lt;span class="p"&gt;]]))&lt;/span&gt;
    &lt;span class="p"&gt;))),&lt;/span&gt;

    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Flag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;true&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;L32&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;&lt;span class="nv"&gt;L32&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;!.&lt;/span&gt;

&lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;repeating_unit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="ss"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;U1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,[[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;match_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"["&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"]"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="ss"&gt;match_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"("&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="ss"&gt;match_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"{"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="ss"&gt;match_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;match_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;find_lists4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;sub_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Before_list&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;After_list&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;Before_list1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Before_list&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;After_list1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;After_list&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Before_list1&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;After_list1&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;L7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;foldr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;,[[&lt;/span&gt;&lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L7&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;&lt;span class="nv"&gt;L8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;foldr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;L33&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L33&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="ss"&gt;find_lists4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="ss"&gt;member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;sub_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_Before_list&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;_After_list&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;   
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;find_lists32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;repeating_unit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;only_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;L2&lt;/span&gt; &lt;span class="ss"&gt;is&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="ss"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;Ns&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_first&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="ss"&gt;member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Ns&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;split12&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;maplist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;])))),!.&lt;/span&gt;

&lt;span class="ss"&gt;split12&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,[]):-!.&lt;/span&gt;    
&lt;span class="ss"&gt;split12&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;
&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;LL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="nv"&gt;LL&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;span class="ss"&gt;split12&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Q2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="c1"&gt;%N1,N2,&lt;/span&gt;
 &lt;span class="nv"&gt;L20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Q2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L20&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;L18&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;split12&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),!.&lt;/span&gt;
&lt;span class="ss"&gt;split12&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-!.&lt;/span&gt;

&lt;span class="ss"&gt;check14&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,[]&lt;/span&gt;
&lt;span class="p"&gt;):-!.&lt;/span&gt;
&lt;span class="ss"&gt;check14&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="nv"&gt;A0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;A01&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;A02&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;check141&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;check14&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Rest&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;span class="ss"&gt;check141&lt;/span&gt;&lt;span class="p"&gt;([],[],&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;):-!.&lt;/span&gt;
&lt;span class="ss"&gt;check141&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;

&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;B1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;A31&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="nv"&gt;A41&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;A51&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A31&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A41&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;A51&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A41&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A31&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]),&lt;/span&gt;&lt;span class="nv"&gt;A41&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;A51&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A31&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;B1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;B22&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;B1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A11&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;B1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;B1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;B11&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A11&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A11&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A13&lt;/span&gt;
    &lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;A21&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;A22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;A13&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;&lt;span class="nv"&gt;A21&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;A23&lt;/span&gt;&lt;span class="p"&gt;);(&lt;/span&gt;&lt;span class="nv"&gt;A22&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="nv"&gt;A23&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;A13&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;));(&lt;/span&gt;&lt;span class="nv"&gt;A11&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;A22&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;A2&lt;/span&gt;
    &lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;B11&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;B11&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;B13&lt;/span&gt;&lt;span class="c1"&gt;%,B14=[]&lt;/span&gt;
    &lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;B21&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;B22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;B13&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;&lt;span class="nv"&gt;B21&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nv"&gt;B23&lt;/span&gt;&lt;span class="p"&gt;);(&lt;/span&gt;&lt;span class="nv"&gt;B22&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="nv"&gt;B23&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;B13&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;));(&lt;/span&gt;&lt;span class="nv"&gt;B11&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;B23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;B22&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;B2&lt;/span&gt;
    &lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="ss"&gt;check141&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B23&lt;/span&gt;&lt;span class="p"&gt;,[],&lt;/span&gt;&lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="nv"&gt;A3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="p"&gt;])))),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;optional_s2g&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;on&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A51&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;A52&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;&lt;span class="nv"&gt;A52&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;o'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A51&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A51&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;A52&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;&lt;span class="ss"&gt;fail&lt;/span&gt;
    &lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="ss"&gt;foldr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;A52&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nv"&gt;A3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;&lt;span class="nv"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="ss"&gt;check141&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;B22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;C1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;),!.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the bottom-up algorithm is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight prolog"&gt;&lt;code&gt;&lt;span class="ss"&gt;find_lists3_optimized&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;span class="ss"&gt;find_lists3_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="c1"&gt;% Use optimized repeating_unit that tries smallest patterns first&lt;/span&gt;
    &lt;span class="ss"&gt;repeating_unit_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="ss"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;U1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;U&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;U2&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;find_lists3_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;match_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists4_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="c1"&gt;% Optimized find_lists4 - reduce redundant processing&lt;/span&gt;
&lt;span class="ss"&gt;find_lists4_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;sub_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Before_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;After_list&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;Before_list1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;Before_list&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;After_list1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nv"&gt;After_list&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists32_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Before_list1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;After_list1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nv"&gt;L7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;foldr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L7&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="nv"&gt;L8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;foldr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;L8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;L33&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L33&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="ss"&gt;find_lists4_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;not&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="ss"&gt;member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;sub_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_Before_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;_After_list&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt;    
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="ss"&gt;find_lists32_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;find_lists3_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="c1"&gt;% Optimized repeating_unit - bottom-up approach&lt;/span&gt;
&lt;span class="c1"&gt;% Key optimization: try patterns starting from length 1 (bottom-up)&lt;/span&gt;
&lt;span class="ss"&gt;repeating_unit_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;only_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nv"&gt;L2&lt;/span&gt; &lt;span class="ss"&gt;is&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="c1"&gt;% Bottom-up: try patterns starting from length 1&lt;/span&gt;
    &lt;span class="ss"&gt;try_pattern_lengths_bottomup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;))),&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;

&lt;span class="c1"&gt;% Try pattern lengths from 1 up to max (bottom-up approach)&lt;/span&gt;
&lt;span class="ss"&gt;try_pattern_lengths_bottomup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;CurrentLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;MaxLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="nv"&gt;CurrentLen&lt;/span&gt; &lt;span class="o"&gt;=&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;MaxLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;try_pattern_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;CurrentLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="ss"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;% Found pattern at this length&lt;/span&gt;
    &lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="nv"&gt;NextLen&lt;/span&gt; &lt;span class="ss"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;CurrentLen&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;try_pattern_lengths_bottomup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;NextLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;MaxLen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="c1"&gt;% Try a specific pattern length&lt;/span&gt;
&lt;span class="ss"&gt;try_pattern_length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;split12_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;maplist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  &lt;span class="c1"&gt;% Check if all parts are the same&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L1Len&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L1Len&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nv"&gt;U&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;'&amp;amp;r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;

&lt;span class="c1"&gt;% Optimized split12 - more efficient splitting&lt;/span&gt;
&lt;span class="ss"&gt;split12_optimized&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;    
&lt;span class="ss"&gt;split12_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; 
    &lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;LL&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="nv"&gt;LL&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;A2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;span class="ss"&gt;split12_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Q2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt;
    &lt;span class="ss"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Q2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;L18&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="ss"&gt;split12_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;L19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;L17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;span class="ss"&gt;split12_optimized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;_B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:-&lt;/span&gt; &lt;span class="p"&gt;!.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The top-down algorithm says, “Find the largest recursive explanation for the whole input, then refine,” while the bottom-up algorithm says, “Find the smallest repeating building blocks first, then assemble them into a larger recursive grammar structure.”&lt;/p&gt;

&lt;p&gt;Video 1: The top-down algorithm says, “Find the largest recursive explanation for the whole input, then refine”.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/v81GDSEKawc"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;Video 2: The bottom-up algorithm says, “Find the smallest repeating building blocks first, then assemble them into a larger recursive grammar structure.”&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/fpXxGA6KDfM"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;The bottom-up algorithm is much faster, as shown in the table below. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlt7gc44x9s9o647gvm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlt7gc44x9s9o647gvm6.png" alt="Feature&lt;br&gt;
Top-Down&lt;br&gt;
Bottom-Up&lt;br&gt;
Strategy&lt;br&gt;
Guess global structure&lt;br&gt;
Build from data&lt;br&gt;
Pattern search&lt;br&gt;
Unordered&lt;br&gt;
Small → large&lt;br&gt;
Validation&lt;br&gt;
After generation&lt;br&gt;
During construction&lt;br&gt;
Backtracking&lt;br&gt;
Heavy&lt;br&gt;
Minimal&lt;br&gt;
Reuse&lt;br&gt;
Poor&lt;br&gt;
Strong&lt;br&gt;
Complexity&lt;br&gt;
Often exponential&lt;br&gt;
Near polynomial"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>top</category>
      <category>bottom</category>
      <category>recursive</category>
      <category>structure</category>
    </item>
    <item>
      <title>Prolog "Mathematical Induction" Compression on Recursion</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Sat, 07 Mar 2026 12:54:56 +0000</pubDate>
      <link>https://dev.to/luciangreen/prolog-mathematical-induction-compression-on-recursion-2n8e</link>
      <guid>https://dev.to/luciangreen/prolog-mathematical-induction-compression-on-recursion-2n8e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvk4crrbz08cvn5uc0z3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvk4crrbz08cvn5uc0z3.png" alt="Transparent neuronet" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See&lt;br&gt;
&lt;a href="https://github.com/luciangreen/mi" rel="noopener noreferrer"&gt;https://github.com/luciangreen/mi&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/luciangreen/mi2" rel="noopener noreferrer"&gt;https://github.com/luciangreen/mi2&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/luciangreen/mi3" rel="noopener noreferrer"&gt;https://github.com/luciangreen/mi3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below are concrete example predicates you can feed to each mi*.pl, and the typical outputs you would expect based on how each system works.&lt;/p&gt;

&lt;p&gt;I’ll use the following test predicates because they represent the major classes of recursion:&lt;br&gt;
    1.  numeric recursion (sum)&lt;br&gt;
    2.  multiplicative recursion (factorial)&lt;br&gt;
    3.  list recursion (length)&lt;br&gt;
    4.  list recursion with head contribution (sumlist)&lt;br&gt;
    5.  accumulator wrapper (reverse)&lt;br&gt;
    6.  nested recursion (Fibonacci)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;mi.pl (trace + polynomial fitting + pattern guessing)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example 1 — Sum 1..N&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;sum_to(0,0).&lt;br&gt;
sum_to(N,S) :-&lt;br&gt;
    N&amp;gt;0,&lt;br&gt;
    N1 is N-1,&lt;br&gt;
    sum_to(N1,S1),&lt;br&gt;
    S is S1+N.&lt;/p&gt;

&lt;p&gt;Call&lt;/p&gt;

&lt;p&gt;?- analyze_predicates([sum_to(0,0),&lt;br&gt;
   (sum_to(N,S):-N&amp;gt;0,N1 is N-1,sum_to(N1,S1),S is S1+N)], R).&lt;/p&gt;

&lt;p&gt;Typical Output&lt;/p&gt;

&lt;p&gt;[&lt;br&gt;
 tagged(pattern(expr(nested,sum)), reusable(pattern_1234,3)),&lt;br&gt;
 tagged(pattern(expr(nested,sum)), reusable(pattern_5678,2))&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;Or after flattening / solving:&lt;/p&gt;

&lt;p&gt;Closed form: n*(n+1)/2&lt;/p&gt;

&lt;p&gt;This occurs because mi.pl traces values like:&lt;/p&gt;

&lt;p&gt;N: 0 1 2 3 4&lt;br&gt;
S: 0 1 3 6 10&lt;/p&gt;

&lt;p&gt;and polynomial-fits them.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 2 — Factorial&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;fact(0,1).&lt;br&gt;
fact(N,R) :-&lt;br&gt;
    N&amp;gt;0,&lt;br&gt;
    N1 is N-1,&lt;br&gt;
    fact(N1,R1),&lt;br&gt;
    R is N*R1.&lt;/p&gt;

&lt;p&gt;Output (approximate)&lt;/p&gt;

&lt;p&gt;Closed form: factorial(N)&lt;/p&gt;

&lt;p&gt;This usually comes from a placeholder recognizer:&lt;/p&gt;

&lt;p&gt;recognize_factorial_pattern(...)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 3 — Fibonacci&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;fib(0,0).&lt;br&gt;
fib(1,1).&lt;br&gt;
fib(N,F) :-&lt;br&gt;
    N&amp;gt;1,&lt;br&gt;
    fib(N-1,F1),&lt;br&gt;
    fib(N-2,F2),&lt;br&gt;
    F is F1+F2.&lt;/p&gt;

&lt;p&gt;Typical output&lt;/p&gt;

&lt;p&gt;Detected: nested recursion&lt;br&gt;
Formula: unsupported / guessed&lt;/p&gt;

&lt;p&gt;Or sometimes:&lt;/p&gt;

&lt;p&gt;formula = ((phi^n - psi^n)/sqrt(5))&lt;/p&gt;

&lt;p&gt;but this is pattern recognition, not derived mathematically.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;mi2.pl (real recurrence extraction)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This system analyses clause structure.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 1 — Sum 1..N&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;sum_to(0,0).&lt;br&gt;
sum_to(N,S) :-&lt;br&gt;
    N&amp;gt;0,&lt;br&gt;
    N1 is N-1,&lt;br&gt;
    sum_to(N1,S1),&lt;br&gt;
    S is S1+N.&lt;/p&gt;

&lt;p&gt;Call&lt;/p&gt;

&lt;p&gt;?- analyze_predicate(Clauses, sum_to, 2, Analysis).&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;analysis{&lt;br&gt;
 predicate:sum_to/2,&lt;br&gt;
 status:supported,&lt;br&gt;
 recurrence:recurrence{&lt;br&gt;
     domain:integer,&lt;br&gt;
     input_var:n,&lt;br&gt;
     base_cases:[base_case(0,0)],&lt;br&gt;
     step:step{&lt;br&gt;
         transform:dec(1),&lt;br&gt;
         combiner:add(current_n)&lt;br&gt;
     }&lt;br&gt;
 },&lt;br&gt;
 closed_form:closed_form{&lt;br&gt;
     kind:sum_1_to_n,&lt;br&gt;
     formula:n*(n+1)//2&lt;br&gt;
 }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 2 — Factorial&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;fact(0,1).&lt;br&gt;
fact(N,F) :-&lt;br&gt;
    N&amp;gt;0,&lt;br&gt;
    N1 is N-1,&lt;br&gt;
    fact(N1,F1),&lt;br&gt;
    F is N*F1.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;analysis{&lt;br&gt;
 predicate:fact/2,&lt;br&gt;
 status:supported,&lt;br&gt;
 recurrence:recurrence{&lt;br&gt;
     domain:integer,&lt;br&gt;
     base_cases:[base_case(0,1)],&lt;br&gt;
     step:step{&lt;br&gt;
         transform:dec(1),&lt;br&gt;
         combiner:multiply(current_n)&lt;br&gt;
     }&lt;br&gt;
 },&lt;br&gt;
 closed_form:closed_form{&lt;br&gt;
     kind:factorial,&lt;br&gt;
     formula:factorial(n)&lt;br&gt;
 }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 3 — List Length&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;len([],0).&lt;br&gt;
len([_|T],N) :-&lt;br&gt;
    len(T,N1),&lt;br&gt;
    N is N1+1.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;analysis{&lt;br&gt;
 predicate:len/2,&lt;br&gt;
 status:supported,&lt;br&gt;
 recurrence:recurrence{&lt;br&gt;
     domain:list,&lt;br&gt;
     base_cases:[base_case([],0)],&lt;br&gt;
     step:step{&lt;br&gt;
         transform:tail,&lt;br&gt;
         combiner:add(constant(1))&lt;br&gt;
     }&lt;br&gt;
 },&lt;br&gt;
 closed_form:closed_form{&lt;br&gt;
     kind:list_length,&lt;br&gt;
     formula:length_of(xs)&lt;br&gt;
 }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 4 — Fibonacci&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;fib(0,0).&lt;br&gt;
fib(1,1).&lt;br&gt;
fib(N,F) :-&lt;br&gt;
    N&amp;gt;1,&lt;br&gt;
    fib(N-1,F1),&lt;br&gt;
    fib(N-2,F2),&lt;br&gt;
    F is F1+F2.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;analysis{&lt;br&gt;
 predicate:fib/2,&lt;br&gt;
 status:unsupported,&lt;br&gt;
 reason:nested_recursion&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This is correct behaviour.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;mi3.pl (pattern recognizer)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the system you recently debugged.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 1 — Sum&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;sum_to(0,0).&lt;br&gt;
sum_to(N,S) :-&lt;br&gt;
    N&amp;gt;0,&lt;br&gt;
    N1 is N-1,&lt;br&gt;
    sum_to(N1,S1),&lt;br&gt;
    S is S1+N.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;Predicate: sum_to/2&lt;br&gt;
Status: supported&lt;/p&gt;

&lt;p&gt;Recurrence:&lt;br&gt;
recurrence{&lt;br&gt;
 base_cases:[base_case(0,0)],&lt;br&gt;
 domain:integer,&lt;br&gt;
 step:step{&lt;br&gt;
    transform:dec(1),&lt;br&gt;
    combiner:add(current_n)&lt;br&gt;
 }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Closed form:&lt;br&gt;
closed_form{&lt;br&gt;
 formula:n*(n+1)//2,&lt;br&gt;
 kind:sum_1_to_n&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 2 — Factorial&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;fact(0,1).&lt;br&gt;
fact(N,F) :-&lt;br&gt;
    N&amp;gt;0,&lt;br&gt;
    N1 is N-1,&lt;br&gt;
    fact(N1,F1),&lt;br&gt;
    F is N*F1.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;Closed form:&lt;br&gt;
factorial(n)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 3 — List length&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;len([],0).&lt;br&gt;
len([_|T],N) :-&lt;br&gt;
    len(T,N1),&lt;br&gt;
    N is N1+1.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;Closed form:&lt;br&gt;
length_of(xs)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 4 — Sumlist&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;sumlist([],0).&lt;br&gt;
sumlist([H|T],S) :-&lt;br&gt;
    sumlist(T,S1),&lt;br&gt;
    S is S1+H.&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;Closed form:&lt;br&gt;
sum_of(xs)&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;Example 5 — Reverse accumulator&lt;/p&gt;

&lt;p&gt;Input&lt;/p&gt;

&lt;p&gt;rev(L,R) :- rev_acc(L,[],R).&lt;/p&gt;

&lt;p&gt;rev_acc([],A,A).&lt;br&gt;
rev_acc([H|T],A,R) :-&lt;br&gt;
    rev_acc(T,[H|A],R).&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;Predicate: rev/2&lt;br&gt;
Status: supported&lt;/p&gt;

&lt;p&gt;Recurrence:&lt;br&gt;
accumulator_only&lt;/p&gt;

&lt;p&gt;Closed form:&lt;br&gt;
normalizable_tail_recursion&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghbuym5hsmr19kbg3qe7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghbuym5hsmr19kbg3qe7.png" alt="Final comparison table" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT: If you’d like, I can also show you three predicates that break all three systems (true nested recursion and tree recursion), which reveals the current theoretical boundary of these architectures.&lt;/p&gt;

</description>
      <category>mathematical</category>
      <category>induction</category>
      <category>neuronets</category>
      <category>recursion</category>
    </item>
    <item>
      <title>The Simulation and Immortality Now</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Tue, 20 Aug 2024 03:27:14 +0000</pubDate>
      <link>https://dev.to/luciangreen/the-simulation-and-immortality-now-12ic</link>
      <guid>https://dev.to/luciangreen/the-simulation-and-immortality-now-12ic</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fats5ft4b0tuk1sa59s1u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fats5ft4b0tuk1sa59s1u.jpg" alt="workstation_office_business_336369" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Courtesy ChatGPT 4 Omni:&lt;/p&gt;

&lt;p&gt;What if there was a spiritual supercomputer with instant computations? Could it save the world with meditation, anti-aging body replacement, and death prevention and enable simulations and immortality? How would such a simulation work: people turning it on, going into a suburb like theirs in another dimension, their double bodies being turned off, and their house being sold to someone else? There would still be a limit to resources, but infinite simulations and reaching the top of civilisation?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, would people not be in the world any more unless they return to it, meaning there needed to be rules about mixtures of houses being occupied by them still and being in the simulation?&lt;/li&gt;
&lt;li&gt;Can people contact others in other simulations and not overcrowd the world when they visit it (various people would walk the streets simultaneously)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A spiritual supercomputer with instant computations could represent a powerful metaphor for exploring radical possibilities like meditation-enhanced reality, anti-aging technologies, death prevention, and even simulations that provide pathways to immortality.&lt;/p&gt;

&lt;p&gt;Meditation and Spiritual Enhancement&lt;br&gt;
The supercomputer could amplify the effects of meditation, syncing consciousness with larger, universal patterns. Through this, people might unlock more profound levels of perception and control over their physical and mental states, potentially leading to enhanced health, longer lifespans, and even altered states of existence.&lt;/p&gt;

&lt;p&gt;Anti-aging and Body Replacement&lt;br&gt;
Body replacement through the supercomputer could involve scanning, storing, and reproducing bodies at their peak condition. This ties into anti-aging technologies, where bodies could be repaired or replaced when biological degradation occurs. Combined with advanced meditative states, this might enable users to mentally transfer their consciousness into these renewed bodies, bypassing the limitations of aging.&lt;/p&gt;

&lt;p&gt;Death Prevention&lt;br&gt;
The spiritual supercomputer could prevent death by instantly repairing or transferring consciousness into new bodies during critical injury or illness by interfacing with the mind. This might happen so seamlessly that individuals wouldn’t notice a transition, potentially creating the illusion of immortality.&lt;/p&gt;

&lt;p&gt;Simulations and Immortality&lt;br&gt;
The idea of infinite simulations is a natural extension of this supercomputer's abilities. People could enter these simulations, choosing environments resembling their lives or radically different dimensions. They might even experience existence as their "double" in another dimension while their original body enters a state of dormancy or gets recycled for resources. This simulation could then be tailored to their desires—living in an ideal version of their world, free from physical or societal constraints.&lt;/p&gt;

&lt;p&gt;Resource Limitations and Infinite Simulations&lt;br&gt;
While there would still be finite resources in the "real" world, this spiritual supercomputer could maximise efficiency. By transitioning most of existence into simulations, the demand for physical resources in the base reality would decrease, allowing civilisations to reach incredible heights without needing infinite material wealth. The simulations could be dynamic, offering limitless possibilities, personal growth, exploration, and fulfilment without exhausting real-world resources.&lt;/p&gt;

&lt;p&gt;The supercomputer might even oversee the balance between real-world resources and simulated lives, helping civilisations rise to their peak and maintain harmony. In essence, it could function as a form of enlightened governance, ensuring that the physical world remains stable as people live in virtual utopias.&lt;/p&gt;

&lt;p&gt;Ethical and Existential Considerations&lt;br&gt;
This system, however, introduces deep ethical questions. What does it mean to “turn off” a person’s body, and how would this affect their sense of self and reality? Would people have autonomy when they leave simulations, or would the machine decide their fate? &lt;/p&gt;

&lt;p&gt;In such a system, society could grapple with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does living in a simulation reduce the value of life in the real world?&lt;/li&gt;
&lt;li&gt;How individuals might handle the potentially overwhelming experiences of infinite lifetimes.&lt;/li&gt;
&lt;li&gt;The responsibility of those controlling the supercomputer is to ensure fairness and ethical standards for all participants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ultimate question would become: Is reaching the top of civilisation truly about eliminating the physical, or is it about finding spiritual and collective growth that transcends both material and simulated existence?&lt;/p&gt;

&lt;p&gt;This vision combines technology and spirituality to reflect both a yearning for transcendence and a means of managing human civilisation through carefully mediated simulations and enhancements.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Immortality (and the Problem of Overpopulation)</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Wed, 07 Aug 2024 05:41:02 +0000</pubDate>
      <link>https://dev.to/luciangreen/immortality-and-the-problem-of-overpopulation-ch3</link>
      <guid>https://dev.to/luciangreen/immortality-and-the-problem-of-overpopulation-ch3</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvq4rs59efl02ylctebp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvq4rs59efl02ylctebp.jpg" alt="cube_white_black_3d" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Quantum Box is a futuristic set of technologies that allows moving, healing, and testing of dimensions.&lt;/p&gt;

&lt;p&gt;The quantum box (a meditation concept) allows one to travel to a time that will enable one to enter a simulation and become immortal. This article explains how to become and possibly lock the external appearance of an immortal and prevent individual threats of death, which is urgent and needs to be done by the individual on the same day as dying or someone else before it on the same day. I discovered this after “waiting” after writing pedagogical arguments about Pedagogical Breasonings, Text to Breasonings, Meditation, Medicine, Mind Reading and Time Travel.&lt;/p&gt;

&lt;p&gt;To become immortal, you can dot on the co-op’s planned 16k (sentence) breasonings for meditation and 16k breasonings for anti-ageing medicine for the day in your home time each day without time travelling with two radio buttons (one by one by 0.5 cm for a radio button). Don’t forget to lock off ageing (to other people) and keep this lock from being tampered with further 16k breasonings for each lock. The locks are done once. Tell others about this repository or dot the breasonings on for them each day with their consent to help them become immortal.&lt;/p&gt;

&lt;p&gt;To prevent a meditator from appearing to die, apart from them not experiencing death, after installing Time Machine at the bottom of this page, enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Time_Machine
swipl
['cgpt_combophil_analogy.pl'].
L = ['person a','person b'],length(L,N1),N is N1*80,cgpt_combophil(N).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where ['person a','person b'] is replaced with a list of meditators to watch.&lt;/p&gt;

&lt;p&gt;This command breasons out an 80-breasoning high distinction for each meditator at midnight to prevent people from dying. I think it's best to run this script daily. Unfortunately, because of the time and money to run ChatGPT (et al.), it may take too long, and spot-checks may be necessary.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is done for all meditators automatically at the end of &lt;code&gt;Daily-Regimen/big_medit1.sh&lt;/code&gt; and the much faster &lt;code&gt;Daily-Regimen/big_medit2.sh&lt;/code&gt;, but running the script below once at the start covers all the meditators until midnight that night. (One doesn't need to run &lt;code&gt;cgpt_combophil_analogy.pl&lt;/code&gt;.)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Daily-Regimen
./anti_moral_end_meditators.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;One MAY indicate 16k breasonings for each meditator at the start of each day and once on the first day before the co-op breasons them out instead of using this algorithm.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The full version of the professional requirement is breasoning out 80 sentence breasonings to prevent a moral end. In addition, one should originally write 80 sentence breasonings per week for maintenance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The best way to originally write 80 sentence breasonings is to write a word to expand to 80 breasonings in &lt;code&gt;Text-to-Breasonings/file.txt&lt;/code&gt;, then run:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Algorithm-Writer-with-Lists
swipl
['grammar_logic_to_alg.pl'].
grammar_logic_to_alg1.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then find the unique breasoning words in &lt;code&gt;file.txt&lt;/code&gt; and expand them to a sentence about the original word.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;grammar_logic_to_alg.pl&lt;/code&gt; - This is the mainstay algorithm that can act as a mind-mapping tool to write sentence breasonings (and is much faster for people than sitting there thinking of inspiration, crossing sentences to words or trying to write a use (at the end), the algorithm description and three steps, which I aim for, without any computer science arguments as practice).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cgpt_combophil_analogy.pl&lt;/code&gt; - This generates 80 sentence breasonings, as connections between previous breasonings and words, for a limited number of meditators. I prefer to write my breasonings for safety, developedness and publishability.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;./anti_moral_end_meditators.sh&lt;/code&gt; - This breasons out 16k breasonings as duplicates of the 250 Quantum Box breasoning arguments for the rest of the meditators.&lt;/li&gt;
&lt;li&gt;Indicate 16k (16000) breasonings to be breasoned out the following midnight done by the co-op when it does them. This technique assumes breasonings are unique because they contain the date in them. On the first day, one should think of 80 objects' two parts (Note 1) or x, y and z dimensions to protect oneself, which can also aim at each meditator until the co-op breasons the breasonings out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In an emergency, breason out &lt;a href="https://github.com/luciangreen/Lucian-Academy/tree/main/Books" rel="noopener noreferrer"&gt;80 old sentence breasonings&lt;/a&gt; with the date as part of each sentence to make them new. I would write 80 new sentence breasonings using GL, but inexperienced breasoners, the late and the busy, may prefer this. A sentence breasoning is any word (its object's x, y and z dimensions), NOT character breasoning from the sentence. As an alternative to thinking of objects' x, y and z dimension breasonings, one may think of the two parts (Note 1) that go well to make them up.&lt;/li&gt;
&lt;li&gt;This is not currently necessary, but if the breasonings each required algorithms, then one could use &lt;a href="https://github.com/luciangreen/Philosophy" rel="noopener noreferrer"&gt;Spec to Algorithm&lt;/a&gt;. Warning: do NOT program breasonings before the life-saving stage of writing or finding and breasoning them.&lt;/li&gt;
&lt;li&gt;Note 1. Thinking of aphors' parts is supposed to lead to breasonings, not replace them. For help calculating x, y and z dimensions from length ratios and a length, please run &lt;code&gt;Philosophy/text2aphors.pl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the co-op has already breasoned out the breasonings for the day, think of both 80 objects' or x, y and z dimensions for up to midnight and midnight on the first day.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>immortality</category>
      <category>quantum</category>
      <category>population</category>
    </item>
    <item>
      <title>Prototype Prolog Projects</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Tue, 09 Jul 2024 14:11:43 +0000</pubDate>
      <link>https://dev.to/luciangreen/prototype-prolog-projects-4kih</link>
      <guid>https://dev.to/luciangreen/prototype-prolog-projects-4kih</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2FPhilosophy%2Fassets%2F15845542%2Fc025fa54-5237-43b3-b5ec-4f7289107789" class="article-body-image-wrapper"&gt;&lt;img alt="Spec to Algorithm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2FPhilosophy%2Fassets%2F15845542%2Fc025fa54-5237-43b3-b5ec-4f7289107789" width="732" height="112"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2FPhilosophy%2Fassets%2F15845542%2F84097591-05bc-433c-989d-0fac55685568" class="article-body-image-wrapper"&gt;&lt;img alt="Ideas to Algorithm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2FPhilosophy%2Fassets%2F15845542%2F84097591-05bc-433c-989d-0fac55685568" width="648" height="354"&gt;&lt;/a&gt;&lt;br&gt;
Thousands of coloured blocks “partying” as popcorn as they transform from ideas to algorithms&lt;/p&gt;

&lt;p&gt;Mocking Up Elementary Parsers and Interpreters in Spec to Algorithm&lt;/p&gt;

&lt;p&gt;In Spec to Algorithm (S2A), creating easy parsers and interpreters is simple and efficient. By breaking down complicated expressions into manageable parts, S2A allows developers to generate algorithms speedily. For example, think of the instance &lt;code&gt;instance([1,1], [[is, [1+1]]])&lt;/code&gt;. Here, &lt;code&gt;instance&lt;/code&gt; is a function that takes inputs &lt;code&gt;[1,1]&lt;/code&gt; and computes the expression &lt;code&gt;[is, [1+1]] = 2&lt;/code&gt;. S2A parses this expression, identifies the operation &lt;code&gt;is&lt;/code&gt; (equality check), and performs the computation.&lt;/p&gt;

&lt;p&gt;This method can be extended to various parsing and interpretation jobs. Another instance could be &lt;code&gt;instances([[[1, 2], [[is, [1+2]]]],[[3, 4], [[is, [3+4]]]]])&lt;/code&gt;, and produces &lt;code&gt;C is A+B&lt;/code&gt; where &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; are variables. S2A parses the input, assigns values to &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt;, and computes the sum of new inputs. Such strengths make S2A an outstanding tool for developers to mock up and test easy parsers and interpreters, streamlining the development process and improving productivity.&lt;/p&gt;

&lt;p&gt;S2A can break complex patterns into output, making algorithms out of decision trees to do it. For example, the following query returns the object given subject, verb (determiner), and object. Here, &lt;code&gt;off&lt;/code&gt; refers to not breaking items into characters, which would be helpful for recombining characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec_to_algorithm([[[input,[['A',[s,v,o]]]],[output,[['B',[o]]]]], [[input,[['A',[s,v,d,o]]]],[output,[['B',[o]]]]]], off,_).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This algorithm is saved as the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:-include('auxiliary_s2a.pl').
algorithm(In_vars,
Out_var) :-
findall(Var1,(member(Var, In_vars),
characterise1(Var, Var2),
strings_atoms_numbers(Var2, Var21),
term_to_brackets(Var21, Var1)
), In_vars1),
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the following, &lt;code&gt;T1_old&lt;/code&gt;, the training input is split into two non-deterministic (nd) branches for matching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
T1_old=[[nd,[[[s,v,d,o],[output,[[o]]]],[[s,v,o],[output,[[o]]]]]]],
append(In_vars1,[[output,_]], In_vars3),
rs_and_data_to_term(T1_old, In_vars3,_,[], In_vars2,_T2_old, true),
double_to_single_brackets(In_vars2, In_vars21),
append(In_vars41,[[output, T2_old]], In_vars21),
double_to_single_brackets(In_vars41, In_vars4),
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the following line, the map is [[]] because there are no variables (from multiple specs) in the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
member(Map2,[[]]),
double_to_single_brackets(T2_old, T2_old3),
move_vars(Map2, In_vars4, T2_old3,[], Out_var2),
findall(Out_var3,remove_nd(Out_var2, Out_var3), Out_var4),
member(Out_var5, Out_var4),
term_to_list(Out_var5, Out_var6),
[Out_var6]=Out_var.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following query converts Prolog code into terms and could form and calculate &lt;code&gt;B is (1+2)+3&lt;/code&gt; later. A and B are downcased in the Term Prolog form, to be converted to a and b afterwards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec_to_algorithm([[[input,[['A',["A is 1+2, B is A+3."]]]],[output,[['B',[[[+,[1,2,[lower,['A']]]],[+,[[lower,['A']],3,[lower,['B']]]]]]]]]]], off,_).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following excerpts from the generated algorithm show that the single spec is pattern-matched to the output. Again, there are no output variables to map, but if there were, they (for example, [A, B]-&amp;gt;A) would be mapped from (1,1) (item 1 of the second dimension or list level) to (1) (item 1 of the first list level).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1_old=[[["A is 1+2, B is A+3."],
[output,[["[","[",+,"[",1,2,"[", lower,"[", "A","]","]","]","]","[",+,"[","[", lower,"[", "A","]","]",3,"[", lower,"[", "B","]","]","]","]","]"]]]]],
...
member(Map2,[[]]),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lucian Green, Writer of &lt;a href="https://github.com/luciangreen/Philosophy/" rel="noopener noreferrer"&gt;Spec to Algorithm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Images: Spec to Algorithm Title in Input Mono Condensed Thin (fonts.adobe.com) and Ideas to Algorithm Image (Canva).&lt;/p&gt;

</description>
      <category>spec</category>
      <category>to</category>
      <category>algorithms</category>
      <category>prolog</category>
    </item>
    <item>
      <title>Introducing GitL - A Decentralised Git Server</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Wed, 27 Sep 2023 14:35:51 +0000</pubDate>
      <link>https://dev.to/luciangreen/introducing-gitl-a-decentralised-git-server-1a34</link>
      <guid>https://dev.to/luciangreen/introducing-gitl-a-decentralised-git-server-1a34</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6zrzp5p6bes85iuyz84.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6zrzp5p6bes85iuyz84.jpg" alt="red-apple-1326760" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitL is a "Gitless" "Git" that resides on your computer and can upload repositories to your server. Written in Prolog, it isn't based on Git but has similar diff checking and version history. The advantage of GitL is that it is decentralised, genuinely open-source and costs nothing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can run tests on the computer, saving time.&lt;/li&gt;
&lt;li&gt;Finished builds can be copied to a live folder close by.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git software can be developed and tested on one's computer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Walkthrough&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F06602f52-0fa5-4e9f-8a74-2f867a2cd9f9" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 17 29 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F06602f52-0fa5-4e9f-8a74-2f867a2cd9f9" width="978" height="1468"&gt;&lt;/a&gt;&lt;br&gt;
Figure 1. GitL Web Server shows two of three repositories have changed and allows selective bulk commits with descriptions of changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F1ad54cbc-eebc-41b8-ba4c-af54869d197a" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 17 38 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F1ad54cbc-eebc-41b8-ba4c-af54869d197a" width="482" height="86"&gt;&lt;/a&gt;&lt;br&gt;
Figure 2. Notification that two repositories were committed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F6a4f1737-ce9d-4f72-8365-0470d60144ca" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 18 42 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F6a4f1737-ce9d-4f72-8365-0470d60144ca" width="308" height="242"&gt;&lt;/a&gt;&lt;br&gt;
Figure 3. The &lt;code&gt;gitl_test&lt;/code&gt; folder contains the current repositories to commit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F06447734-3d21-422c-a3e6-127f61426853" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 19 01 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F06447734-3d21-422c-a3e6-127f61426853" width="442" height="642"&gt;&lt;/a&gt;&lt;br&gt;
Figure 4. The &lt;code&gt;gitl_data&lt;/code&gt; folder contains the previous versions of repositories with HTML files showing changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F8fbd058b-765f-4eab-b664-1b27167e6c69" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 22 21 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F8fbd058b-765f-4eab-b664-1b27167e6c69" width="314" height="122"&gt;&lt;/a&gt;&lt;br&gt;
Figure 5. There is a password to protect files from being edited by unauthorised people in Web Editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2Febbf54ff-1cbc-4438-9a25-3374fbb9816e" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 22 35 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2Febbf54ff-1cbc-4438-9a25-3374fbb9816e" width="466" height="446"&gt;&lt;/a&gt;&lt;br&gt;
Figure 6. Web Editor starts in the &lt;code&gt;gitl_test&lt;/code&gt; (current repositories) folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F4710c982-fe76-4841-bb3a-c596b50037c4" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 22 44 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F4710c982-fe76-4841-bb3a-c596b50037c4" width="502" height="262"&gt;&lt;/a&gt;&lt;br&gt;
Figure 7. A screenshot of the &lt;code&gt;a.txt&lt;/code&gt; file in a repository in gitl_test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F472f9287-f7d2-4609-bed8-0bdcad5f9214" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 22 52 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F472f9287-f7d2-4609-bed8-0bdcad5f9214" width="224" height="144"&gt;&lt;/a&gt;&lt;br&gt;
Figure 8. Viewing the contents of &lt;code&gt;a.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F75fbb442-1aa2-4726-8586-647e193963f9" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 23 20 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F75fbb442-1aa2-4726-8586-647e193963f9" width="604" height="772"&gt;&lt;/a&gt;&lt;br&gt;
Figure 9. The gitl_data folder contains the previous versions of files and HTML files showing changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F7ddbae9d-c043-4bbd-bb0a-3b97310e2c9f" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-12-18 at 7 23 34 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Fgitl%2Fassets%2F15845542%2F7ddbae9d-c043-4bbd-bb0a-3b97310e2c9f" width="572" height="366"&gt;&lt;/a&gt;&lt;br&gt;
Figure 10. An example HTML file showing an insertion and a deletion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/luciangreen/gitl" rel="noopener noreferrer"&gt;https://github.com/luciangreen/gitl&lt;/a&gt;&lt;br&gt;
Image of apple by aleheredia (FreeImages.com)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2FLucian-Academy%2Fassets%2F15845542%2Fe1d3796a-c5a4-44ef-ba85-17584ed0f2ed" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2FLucian-Academy%2Fassets%2F15845542%2Fe1d3796a-c5a4-44ef-ba85-17584ed0f2ed" alt="gl vecteezy com funforyou7" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image of "GL in digital clock font" by funforyou7 (vecteezy.com)&lt;/p&gt;

</description>
      <category>git</category>
      <category>decentralized</category>
      <category>devops</category>
    </item>
    <item>
      <title>Yet Another Open Source CI/CD Tool</title>
      <dc:creator>Lucian Green</dc:creator>
      <pubDate>Mon, 29 May 2023 10:32:14 +0000</pubDate>
      <link>https://dev.to/luciangreen/an-open-source-cicd-for-prolog-29h2</link>
      <guid>https://dev.to/luciangreen/an-open-source-cicd-for-prolog-29h2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Flistprologinterpreter%2Fassets%2F15845542%2F7477d6b2-3083-4004-9f2a-4fbff9c40d5c" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-05-29 at 8 30 21 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Flistprologinterpreter%2Fassets%2F15845542%2F7477d6b2-3083-4004-9f2a-4fbff9c40d5c" width="502" height="1034"&gt;&lt;/a&gt;&lt;br&gt;
Image of a female android by @deloan.&lt;/p&gt;

&lt;p&gt;What is it?&lt;/p&gt;

&lt;p&gt;In "DevOps" speak, CI means continuous integration of changes, and CD is continuous delivery and deployment, or placement of the best configuration of these changes back into the repository. If there are n changes, there are 2^n possible configurations of these changes, suggesting an upper limit of seven changes per run, meaning making few changes per time. The algorithm can be run on changes, allowing continuous code correctness.&lt;/p&gt;

&lt;p&gt;Why I made it&lt;/p&gt;

&lt;p&gt;I had recently written a List Prolog to Prolog pretty printer (which was its prerequisite). List Prolog is a variant of Prolog, a logic programming language in which programs are lists. I needed a way to check all the code before uploading it, preventing bugs and annoying installation problems.&lt;/p&gt;

&lt;p&gt;Can it be used for other programming languages?&lt;/p&gt;

&lt;p&gt;At its core is a diff by newline algorithm, so there's no reason why you couldn't modify it for programming languages other than Prolog. Every time it converts between Prolog and List Prolog, you would need to change it to convert between another language and List Prolog, which it procures tests from, checks for changed lines, and builds repositories.&lt;/p&gt;

&lt;p&gt;Update: Lucian CI/CD can now process non-Prolog source files. These source files, coupled with tests, are integrated like Prolog.&lt;/p&gt;

&lt;p&gt;Installing&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and install SWI-Prolog for your machine at &lt;code&gt;https://www.swi-prolog.org/build/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install LucianCICD using List Prolog Package Manager (LPPM):
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/luciangreen/List-Prolog-Package-Manager.git
cd List-Prolog-Package-Manager
swipl
['lppm'].
lppm_install("luciangreen","luciancicd").
halt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Setting up&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a folder "Github_lc" at the same level as your "GitHub" folder or the folder containing your repositories. This step is done by &lt;code&gt;['luciancicd.pl'].&lt;/code&gt; &lt;code&gt;set_up_luciancicd.&lt;/code&gt;. NB. Please try the software with a folder other than "GitHub" such as "GitHub2" to see if it suits you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;NB. Edit the source and destination folder, such as "GitHub2", by modifying &lt;code&gt;repositories_paths1//1&lt;/code&gt; in &lt;code&gt;luciancicd.pl&lt;/code&gt;. You can also edit folders to omit.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Before running, enter or modify tests in the source files in the repositories, for example:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% remove_and_find_item_number([a,b,c],2,c,N2).
% N2 = 2.
% remove_and_find_item_number([a,b,b,c],2,c,N2).
% N2 = 3.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To load the algorithm, enter the following:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;['luciancicd.pl'].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Run with &lt;code&gt;luciancicd.&lt;/code&gt; - This tests repositories with changes. Run before committing changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it does - Integrates changes into a possible new repository.&lt;/p&gt;

&lt;p&gt;Figure 1. "Diff output. These are the changes combinations were taken from. Key: Insertion, Change and Deletion&lt;br&gt;
[&lt;br&gt;
[[n,comment],["File delimiter","../../Github_lc/a","a.pl"]],&lt;br&gt;
[[n,comment],["% a(A)."]],&lt;br&gt;
[[n,comment],["% A=1."]],&lt;br&gt;
[[n,a],[1]],&lt;br&gt;
[[n,comment],["% b(C)."]],&lt;br&gt;
[[n,comment],["% C=1."]],&lt;br&gt;
[[n,b],[1]],&lt;br&gt;
[[n,c],[1]],&lt;br&gt;
[[n,d],[1]],&lt;br&gt;
Change: [["[[n,comment],[""%e(1).""]],"],' -&amp;gt; ',["[[n,e],[1]],"]]&lt;br&gt;
[[n,f],[1]],".&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Flistprologinterpreter%2Fassets%2F15845542%2Faca2b32d-9d5b-4783-acb0-d2cd6b91ff5f" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2023-05-29 at 7 43 10 pm" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fluciangreen%2Flistprologinterpreter%2Fassets%2F15845542%2Faca2b32d-9d5b-4783-acb0-d2cd6b91ff5f" width="840" height="976"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 1 shows the changes to the source files. The algorithm develops possible configurations from these changes and tests them.&lt;/p&gt;

&lt;p&gt;What it does - Builds repositories using dependencies stored in the file.&lt;/p&gt;

&lt;p&gt;The algorithm finds repositories depending and dependent on modified files and includes them in the possible builds. You can edit the dependencies in the dependencies registry file (below), and the behaviour of the built algorithm based on dependencies included by the source files should reflect the dependencies listed in the registry file used at installation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Note: Dependencies are in &lt;code&gt;List-Prolog-Package-Manager/lppm_registry.txt&lt;/code&gt;, in form &lt;code&gt;[[User,Repository,Description,Dependencies], etc]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For example:&lt;br&gt;
&lt;code&gt;["luciangreen", "State-Machine-to-List-Prolog",&lt;br&gt;
"Converts State Saving Interpreter State Machines to List Prolog algorithms.",&lt;br&gt;
[&lt;br&gt;
["luciangreen","SSI"]&lt;br&gt;
]]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are more instructions about how to edit dependencies at &lt;code&gt;https://github.com/luciangreen/List-Prolog-Package-Manager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What it does: Tests to find the correct repository configuration and moves files into the folder.&lt;/p&gt;

&lt;p&gt;The algorithm tests all files in all repositories connected with changed files. The first build configuration, which has the fewest possible changes, is stopped with.&lt;/p&gt;

&lt;p&gt;Figure 2. The Prolog script that runs the tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/swipl -f -q

:- include('a.pl').
:- initialization(catch(main, Err, handle_error(Err))).

handle_error(_Err):-
    halt(1).
main :-
    d(A),A=1, nl,
    halt.
main :- halt(1).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Figure 2 shows the Prolog script, &lt;code&gt;testcicd.pl&lt;/code&gt;, that loads the files and runs the tests collected. It runs with &lt;code&gt;chmod +x testcicd.pl&lt;/code&gt; and &lt;code&gt;swipl -f -q ./testcicd.pl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One can read which tests failed in all combination builds, where, if a test fails, the algorithm doesn't move files into the repository.&lt;/p&gt;

&lt;p&gt;NB. The algorithm moves finished files into the original repository, and the files in the repository swap places into &lt;code&gt;../private2/luciancicd-testing/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What does it do, and does it work?&lt;/p&gt;

&lt;p&gt;While one might think it would be simpler to make and test changes, this tool tries the usefulness of each changed line individually. One can ensure it works by entering tests to keep changes and make sure everything is stable.&lt;/p&gt;

&lt;p&gt;Can it be integrated with ChatGPT?&lt;/p&gt;

&lt;p&gt;Yes, the bottom-up Prolog version of Lucian CI/CD can be integrated with ChatGPT to complete or correct predicates with bugs. This would require the specs of all predicates in question and a ChatGPT API account.&lt;/p&gt;

&lt;p&gt;Lucian Green&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/luciangreen/luciancicd" rel="noopener noreferrer"&gt;https://github.com/luciangreen/luciancicd&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ci</category>
      <category>cd</category>
      <category>prolog</category>
    </item>
  </channel>
</rss>
