Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

J and L-systems

I'm going to create a program that can generate strings from L-system grammars.

Astrid Lindenmayer's original L-System for modelling the growth of algae is:

variables : A B  
constants : none  
axiom     : A  
rules     : (A → AB), (B → A)

which produces:

iteration | resulting model
        0 | A
        1 | AB
        2 | ABA
        3 | ABAAB
        4 | ABAABABA
        5 | ABAABABAABAAB

that is naively implemented by myself in J like this:

   algae =: 1&algae : (([: ; (('AB'"0)`('A'"0) @. ('AB' i. ]))&.>"0)^:[) "1 0 1
   (i.6) ([;algae)"1 0 1 'A'
┌─┬─────────────┐
│0│A            │
├─┼─────────────┤
│1│AB           │
├─┼─────────────┤
│2│ABA          │
├─┼─────────────┤
│3│ABAAB        │
├─┼─────────────┤
│4│ABAABABA     │
├─┼─────────────┤
│5│ABAABABAABAAB│
└─┴─────────────┘

Step-by-step illustration:

   ('AB' i. ]) 'ABAAB' NB. determine indices of productions for each variable
0 1 0 0 1
   'AB'"0`('A'"0)@.('AB' i. ])"0 'ABAAB' NB. apply corresponding productions 
AB
A 
AB
AB
A
   'AB'"0`('A'"0)@.('AB' i. ])&.>"0 'ABAAB' NB. the same &.> to avoid filling
┌──┬─┬──┬──┬─┐
│AB│A│AB│AB│A│
└──┴─┴──┴──┴─┘
   NB. finally ; and use ^: to iterate

By analogy, here is a result of the 4th iteration of L-system that generates Thue–Morse sequence

   4 (([: ; (0 1"0)`(1 0"0)@.(0 1 i. ])&.>"0)^:[) 0
0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0

That is the best that I can do so far. I believe that boxing-unboxing method is insufficient here. This is the first time I've missed linked-lists in J - it's much harder to code grammars without them.

What I'm really thinking about is:
a) constructing a list of gerunds of those functions that build final string (in my examples those functions are constants like 'AB'"0 but in case of tree modeling functions are turtle graphics commands) and evoking (`:6) it,
or something that I am able to code:
b) constructing a string of legal J sentence that build final string and doing (".) it.
But I'm not sure if these programs are efficient.

  • Can you show me a better approach please?

Any hints as well as comments about a) and b) are highly appreciated!

like image 878
Dan Oak Avatar asked Nov 17 '14 13:11

Dan Oak


People also ask

What are L-systems used for?

Lindenmayer used L-systems to describe the behaviour of plant cells and to model the growth processes of plant development. L-systems have also been used to model the morphology of a variety of organisms and can be used to generate self-similar fractals.

What system L?

System L is a natural deductive logic developed by E.J. Lemmon. Derived from Suppes' method, it represents natural deduction proofs as sequences of justified steps.

Is an L-system a fractal?

A Lindenmayer system, also known as an L-system, is a string rewriting system that can be used to generate fractals with dimension between 1 and 2. Several example fractals generated using Lindenmayer systems are illustrated above.

Who developed l-systems and why?

L-systems were introduced in 1968 by Aristid Lindenmayer. Originally designed for the modelling of plant topology, their capabilities have been extended enormously over the years to transform them into a widely used modelling tool for plant geometry capable of producing botanically realistic results.


2 Answers

The following will pad the rectangular array with spaces:

   L=: rplc&('A';'AB';'B';'A')
   L^:(<6) 'A'
A            
AB           
ABA          
ABAAB        
ABAABABA     
ABAABABAABAAB

Or if you don't want padding:

   L&.>^:(<6) <'A'
┌─┬──┬───┬─────┬────────┬─────────────┐
│A│AB│ABA│ABAAB│ABAABABA│ABAABABAABAAB│
└─┴──┴───┴─────┴────────┴─────────────┘

Obviously you'll want to inspect rplc / stringreplace to see what is happening under the covers.

like image 166
Tikkanz Avatar answered Sep 30 '22 03:09

Tikkanz


You can use complex values in the left argument of # to expand an array without boxing.

For this particular L-system, I'd probably skip the gerunds and use a temporary substitution:

to  =: 2 : 'n (I.m=y) } y'        NB. replace n with m in y
ins =: 2 : '(1 j. m=y) #!.n y'    NB. insert n after each m in y
L =:  [: 'c'to'A' [: 'A'ins'B' [: 'B'to'c' ]

Then:

    L^:(<6) 'A'
A
AB
ABA
ABAAB
ABAABABA
ABAABABAABAAB

Here's a more general approach that simplifies the code by using numbers and a gerund composed of constant functions:

   'x'-.~"1 'xAB'{~([:,(0:`(1:,2:)`1:)@.]"0)^:(<6) 1
A
AB
ABA
ABAAB
ABAABABA
ABAABABAABAAB

The AB are filled in at the end for display. There's no boxing here because I use 0 as a null value. These get scattered around quite a bit but the -.~"1 removes them. It does pad all the resulting strings with nulls on the right. If you don't want that, you can use <@-.~"1 to box the results instead:

   'x'<@-.~"1 'xAB'{~([:,(0:`(1:,2:)`1:)@.]"0)^:(<6) 1
┌─┬──┬───┬─────┬────────┬─────────────┐
│A│AB│ABA│ABAAB│ABAABABA│ABAABABAABAAB│
└─┴──┴───┴─────┴────────┴─────────────┘
like image 44
tangentstorm Avatar answered Sep 30 '22 04:09

tangentstorm