L-systems

Biologist Aristid Lindenmayer created Lindenmayer systems , or L-systems , in 1968 as a way of formalizing patterns of bacteria growth. L-systems are a recursive, string-rewriting framework, commonly used today in computer graphics to visualize and simulate organic growth, with applications in plant development, procedural content generation, and fractal-like art.

A rendering of several L-systems.

The following describes L-system fundamentals, how they can be visually represented, and several classes of L-systems, like context-sensitive L-systems and stochastic L-systems. Much of the following has been derived from Przemyslaw Prusinkiewicz and Lindenmayer's seminal work, The Algorithmic Beauty of Plants.

String Rewriting

Fundamentally, an L-system is a set of rules that describe how to iteratively transform a string of symbols. A string, in this context, is a series of symbols, like " a a a" or " a b a b a a b a a a a ababaabaaaa ababaabaaaa", and can be thought of as a word comprised of characters. Each rule, known as a production, describes the transformation of one symbol to another symbol, series of symbols, or no symbol at all. On each iteration, the productions are applied to each character simultaneously, resulting in a new series of symbols.

Productions in this rewriting system can be described with "before" and "after" states, often described as the predecessor and successor; for example, the production a ⟶ a b a \longrightarrow ab a⟶ab represents that the symbol a a a transforms into the symbols a b ab ab on every iteration. The length of derivation, or the number of iterations, is represented by n n n. Given a word a a a and productions a ⟶ a b a \longrightarrow ab a⟶ab and b ⟶ a b \longrightarrow a b⟶a, the following illustrates how the word transforms over several iterations, from n = 0 n=0 n=0 to n = 4 n=4 n=4.

a a b a b a a b a a b a b a a b a b a \begin{aligned} &a \\ &ab \\ &aba \\ &abaab \\ &abaababa \\ \end{aligned} ​ a a b a b a a b a a b a b a a b a b a ​ Figure 1 Word a transforming over 4 iterations of an L-system with the productions a → ab and b → a.

Formalizing L-systems

L-systems are formalized as a tuple with the following definition:

G = ⟨ V , w , P ⟩ G = \langle V, w, P \rangle G = ⟨ V , w , P ⟩

Where the components are:

V V V , the alphabet, or all potential symbols in the string.

, the alphabet, or all potential symbols in the string. w w w , the starting word, also known as the axiom, comprised of symbols from V V V .

, the starting word, also known as the axiom, comprised of symbols from . P P P , a series of productions describing the transformations or rules.

The L-system in Figure 1 can be formalized by defining its axiom ( w w w) and a series of productions ( p 1 , . . . , p n p_{1}, ..., p_{n} p1​,...,pn​) as:

w : a p 1 : b ⟶ a p 2 : a ⟶ a b \begin{aligned} w &: a \\ p_{1} &: b \longrightarrow a \\ p_{2} &: a \longrightarrow ab \\ \end{aligned} w p 1 ​ p 2 ​ ​ : a : b ⟶ a : a ⟶ a b ​

The alphabet of all valid symbols can be inferred. It is implied that a symbol without a matching production has an identity production, e.g. a ⟶ a a \longrightarrow a a⟶a.

This fundamental form of an L-system is described as a deterministic, context-free L-system, or D0L-system (or sometimes DOL-system). 0L-systems are context-free, meaning that each predecessor is transformed regardless of its position in the string and its neighbors. Deterministic L-systems always produce the same result given the same configurations, as there is only one matching production for each predecessor.

Graphical Representation of L-systems

L-systems can be represented visually via turtle graphics, of Logo fame. While L-systems are string rewriting systems, these strings are comprised of symbols, each which can represent some command. A turtle in computer graphics is similar to a pen plotter drawing lines in a 2D space. Imagine giving instructions to a pen plotter to draw a square: "draw 1cm. turn right. draw 1cm. turn right. draw 1cm. turn right. draw 1cm". Though plotters don't really have an orientation, an L-system's turtle can be represented by Cartesian coordinates x x x and y y y, and an angle α \alpha α that describes its forward direction. From there, symbols in a string can represent commands to change the state of the turtle.

To move a turtle around in 2D, symbols must be chosen to represent movement and rotation. The symbols F F F, + + + and − - − will be used here, as they are commonly selected for these commands in L-system interpreters. After deriving the result of an L-system using its production rules, the string can then be parsed from left to right, with the following symbols modifying the turtle state:

F F F move forward by d d d units while drawing a line.

move forward by units while drawing a line. + + + rotate left by angle δ \delta δ .

rotate left by angle . − - − rotate right by angle δ \delta δ .

The variables δ \delta δ and d d d are global values indicating the magnitude of each symbol's rotation or movement. In non-parametric L-systems, each symbol's rotation and movement magnitude is a constant in the system.

F F F − F F − F − F + F + F F − F − F F F FFF-FF-F-F+F+FF-F-FFF F F F − F F − F − F + F + F F − F − F F F Figure 2 Visualizing the movement of a turtle and the line it creates from parsing the above string. From The Algorithmic Beauty of Plants Figure 1.5b.

Following the line in Figure 2 from the bottom left corner, the string can be read as "forward, forward, forward, right, forward, forward, right..." and so on.

An L-system generated by Twitter bot LSystemBot 2.0, tweeting an L-system and it's production rules every few hours.

A turtle may be decoupled from an L-system. The L-system has a starting string and a set of productions and outputs the resulting string. A turtle may take that final string as an input, and output some visual representation. For example, many of the illustrations shown here use the same L-system solvers, while using different turtles where appropriate, like one turtle built using CanvasRenderingContext2D and another using WebGL.

It is important to note that these turtle commands are only idioms, and the turtle interpretation of any symbol is up to the implementor. While The Algorithmic Beauty of Plants and Houdini's L-system implementation share many common symbol commands, each have their own set of symbols it understands.

Space-Filling Curves

Space-filling curves can be formalized via L-systems, resulting in a recursive, fractal-like pattern. More specifically, FASS curves , defined as space-filling, self-avoiding, simple, and self-similar. That is, a single, non-overlapping, recursive, continuous curve.

δ : 90 w : X p 1 : X ⟶ + Y F − X F X − F Y + p 2 : Y ⟶ − X F + Y F Y + F X − \begin{aligned} \delta &: 90 \\ w &: X \\ p_{1} &: X \longrightarrow + Y F - X F X - F Y + \\ p_{2} &: Y \longrightarrow - X F + Y F Y + F X - \\ \end{aligned} δ w p 1 ​ p 2 ​ ​ : 9 0 : X : X ⟶ + Y F − X F X − F Y + : Y ⟶ − X F + Y F Y + F X − ​

Figure 3 An L-system definition for a space-filling Hilbert Curve, animated over 7 iterations.

The Hilbert Curve (Figure 3) is an example of a FASS curve that can be represented as an L-system. Considered a Node-rewriting technique, this L-system's productions declare that on each iteration, X X X and Y Y Y symbols are replaced with more F F F, X X X and Y Y Y symbols. With the angle δ \delta δ defined as 90, this results in recursively generated square wave shape along a curve. While F F F, + + + and − - − are interpreted by the turtle, other symbols can be used for productions. In this case, X X X and Y Y Y are ignored when rendering, and only relevant when rewriting the string and matching productions.

3D Interpretation

In addition to a turtle traversing on a 2D plane, symbols may be introduced that instruct the turtle to draw in 3D. The Algorithmic Beauty of Plants uses the following symbols to control rendering in three dimensions:

+ + + turn left by angle δ \delta δ .

turn left by angle . − - − turn right by angle δ \delta δ .

turn right by angle . & \& & pitch down by angle δ \delta δ .

pitch down by angle . ∧ \wedge ∧ pitch up by angle δ \delta δ .

pitch up by angle . \ \backslash \ roll left by angle δ \delta δ .

roll left by angle . / / / roll right by angle δ \delta δ .

roll right by angle . ∣ | ∣ turn around by 180°.

Like the 2D Hilbert Curve (Figure 3), a three-dimensional version can also be created (Figure 4) using these additional symbols, resulting in a 3D FASS curve.

δ : 90 w : X p 1 : X ⟶ ∧ \ X F ∧ \ X F X − F ∧ / / X F X & F + / / X F X − F / X − / \begin{aligned} \delta &: 90 \\ w &: X \\ p_{1} &: X \longrightarrow & \wedge \backslash X F \wedge \backslash X F \\ & & X - F \wedge / / X F \\ & & X \& F + / / X F \\ & & X - F / X - / \\ \end{aligned} δ w p 1 ​ ​ : 9 0 : X : X ⟶ ​ ∧ \ X F ∧ \ X F X − F ∧ / / X F X & F + / / X F X − F / X − / ​

Figure 4 A space-filling Hilbert Curve from 1 to 4 iterations in 3D.

Bracketed L-Systems

The space-filling Hilbert curve can be represented as a single, continuous line. For organic, tree-like structures, branching is used to represent a diverging fork. Two new symbols, square brackets, are introduced to represent a tree in an L-system's string, with an opening bracket indicating the start of a new branch, with the remaining symbols between the brackets being members of that branch. Symbols after the end bracket indicate returning to the point of the branch's origin. A stack is used to implement branching, storing the state of the turtle on the stack.

[ [ [ push the current turtle state onto the stack.

push the current turtle state onto the stack. ] ] ] pop the top state from the stack and this becomes the current turtle state.

Symbols in a branch are transformed and replaced just as they were outside of a branch. This allows recursive, fractal-like behavior, with each branch forking into more branches, and so on.

Figure 5 Animated branching L-systems, from 1 to 5 iterations. Definitions from The Algorithmic Beauty of Plants Figure 1.24.

In addition to position and rotation, the turtle may contain additional state, like line width or color, with new symbols introduced to manipulate that data.

Rather than productions evaluating symbols in isolation (context-free), rules may be defined that only matches a symbol when it proceeds or succeeds another specific symbol. Context-sensitive L-systems contain production rules that specify symbols that must come before or after the predecessor in order to match, as opposed to context-free systems that evaluate predecessors in isolation.

w : b a a a a p 1 : b < a ⟶ b p 2 : b ⟶ a \begin{aligned} w &: baaaa \\ p_{1} &: b < a \longrightarrow b \\ p_{2} &: b \longrightarrow a \\ \end{aligned} w p 1 ​ p 2 ​ ​ : b a a a a : b < a ⟶ b : b ⟶ a ​ Figure 5 A context-sensitive L-system simulating signal propagation.

These context rules are defined using < < < and > > > in the production rule, adjacent to the predecessor. In Figure 5, the first production rule only matches when the a a a symbol is immediately after b b b, thus replacing the a a a predecessor with its successor, b b b. This results in the b b b symbol moving towards the right:

b a a a a a b a a a a a b a a a a a b a a a a a b \begin{aligned} &baaaa \\ &abaaa \\ &aabaa \\ &aaaba \\ &aaaab \\ \end{aligned} ​ b a a a a a b a a a a a b a a a a a b a a a a a b ​

A similar system could be defined that propagates b b b from right to left, defined via production a > b ⟶ b a > b \longrightarrow b a>b⟶b, replacing a a a when there is a b b b after it in the string.

Context-sensitive productions take precedence over context-free productions if there are more than one production rule matches for a given predecessor.

Figure 6 Animated variants of context-sensitive L-systems, iterations 1 to 35. Definition from A model study on biomorphological description, illustrated in Figure 1.31 from The Algorithmic Beauty of Plants.

L-systems with these one-sided context productions may be considered 1L-systems . Productions may also have both a before-context and an after-context in systems considered 2L-systems . They can be represented as:

A < X > B ⟶ Y A < X > B \longrightarrow Y A < X > B ⟶ Y

This production rule indicates that the predecessor X X X will be replaced by successor Y Y Y when it is between an A A A and a B B B.

Stochastic L-systems

The previously described systems are all deterministic; the same system with the same input will always generate the same result. Stochastic L-systems are non-deterministic, defined by several productions that match the same predecessor, chosen randomly given their weight on each iteration. The following production rules define that on each iteration, X X X has a 50% chance to be rewritten as A A A, and a 50% chance to be rewritten as B B B.

X → . 5 A X → . 5 B \begin{aligned} X & \xrightarrow{.5} A \\ X & \xrightarrow{.5} B \\ \end{aligned} X X ​ . 5 ​ A . 5 ​ B ​

This non-determinism is useful for procedurally creating variety and the seemingly random results of nature.

Stochastic productions with the same predecessor and context must add up to 1.

w : F p 1 : F → . 33 F [ + F ] F [ − F ] F p 2 : F → . 33 F [ + F ] F p 3 : F → . 33 F [ − F ] F \begin{aligned} w &: F \\ p_{1} &: F \xrightarrow{.33} F[+F]F[-F]F \\ p_{2} &: F \xrightarrow{.33} F[+F]F \\ p_{3} &: F \xrightarrow{.33} F[-F]F \\ \end{aligned} w p 1 ​ p 2 ​ p 3 ​ ​ : F : F . 3 3 ​ F [ + F ] F [ − F ] F : F . 3 3 ​ F [ + F ] F : F . 3 3 ​ F [ − F ] F ​ Figure 7 A stochastic L-system animating over several variants. Definition from The Algorithmic Beauty of Plants Figure 1.27.

Parametric L-systems will be documented in a future post.

Resources