------------------------------ Joint Approximate size(knobs) torque capacity (N-mx10-6) ------------------------------ 1 10.4 2 50.2 3 89.6 4 157.3 5 281.6 6 339.2 7 364.5 ------------------------------

These measures are relative: They vary from one brick to another, and by undetermined factors such as temperature, humidity, aging, etc. The table shown reflects an attempt at taking a conservative measure: The number we need to use is the minimum that any Lego union of certain characteristics is guaranteed to support and not, for example, the average.

In our simulations we used the conservative figures above and additionally set the gravitational constant to 1.2 times its actual value - thus allowing for an extra 20% error margin.

Our model of `rigid' joint means it will exert any reaction torque necessary to avoid breaking, up to a certain limit. All we are using is this concept of a maximum load. In a stable system, the actual torque being exerted by certain body at any given joint is underdetermined.

This means for example that if two bricks are supporting the weight of a third one between them (fig. 2.), the load could be considered to be distributed among each of the two joints in any legal combination. Since only one joint is enough in this case, we could consider that all the weight is on the left joint, and none on the right one. This can be verified by removing the right supporting brick: The middle one will not fall, because the union with the leftmost brick is strong enough to support its weight.

Our model is thus based on the following principle: As long as there is a way to distribute the weights among the network of bricks such that no joint is stressed beyond its maximum capacity, the structure will not break. 3.2 A Greedy Generalized Network Flow Algorithm

The algorithmic rendering of our model is still under development. However, it allows us to make the model calculations and obtain the results we are presenting. However, even in its initial state, it worked well enough to use as a basis for fitness testing of structures which were indeed buildable.

This algorithm must find whether or not there exists a distribution of the combined gravitational forces generated by the center of mass of each brick, such that no joint is stressed beyond its maximum capacity.

For each given brick we consider the network of all the joints in the structure as a flow network that will absorb this weight and transmit it to the ground. Each joint can support a certain fraction α of such a force, given by the formula

(1)

for each body b and joint j, where K j is the maximum capacity of the joint, dx(j,b) is the distance between the body and the joint along the horizontal axis, and wb the weight of the body.

If a given body b is fixed and each edge on the graph on fig. 9. is labeled with the corresponding a j,b according to (1), a network flow problem ([5], chapter 27) is obtained where a net flow of 1.0 between a source b and the two sinks at (5,0) and (20,0) represents a valid distribution of the weight of b in the structure.

The complete problem is not reducible, however, to a network flow algorithm, due to the fact that there are multiple forces to be applied at different points, and the capacity of each joint relative to each body varies with the mass of the body and the x-distance between body and joint.

Leaving aside the study of better algorithmic implementations, we have simply implemented a greedy algorithm: Once a solution has been found for the distribution of the first mass, it is fixed, and a remaining capacity for each joint is computed that will conform a reduced network that must support the weight of the next body, and so on.

The fundamental consideration to be done here is that, even if our algorithm does not find all possible solutions, it finds many of them. Any structure that is `approved' by our simulation possesses a load distribution that does not overstress any joint, and thus it will not fall under its own weight. It will stand. Our evolutionary algorithm might be limited by the simulation when it fails to approve a structure that was physically valid, but still may succeed by working only in the space of `provable' solutions.

3.3 Time complexity

A second compromise in our simulation will come from the fact that our initial implementation of the simulation algorithm does not scale well. Its worst case running time would be O(3n), where n is the number of bricks. Fortunately, in the actual examples, many bricks are connected only to one or two others, thus reducing the number of combinations.

Again this combinatorial explosion problem will ultimately constrain the search space. Only the solutions that can be found by our algorithm in a reasonable time are useful to our evolutionary runs.

We inserted an ad hoc limiting parameter into our code to cut off the simulation when it has failed to find a solution after a certain maximum number of iterations.

Our initial representation to perform evolutionary computation over these structures borrows the standard tree mutation and crossover operators from genetic programming [10]. We have implemented a tree notation for two-dimensional Lego structures. Each node on the tree represents a brick and has one size parameter (either 4, 6, 8, 10, 12 or 16 for the available brick sizes) and four potential sons, each one representing a new brick linked at one of its four corners. When a union is present, a joint size parameter determines the number of overlapping knobs in the union.

The diagram on fig. 4. represents a 10-brick with its 4 joint sites labeled 0, 1, 2, 3, that is linked to a 6-brick by two overlapping knobs. The corresponding tree could be written in pseudo-Lisp notation as

(10 NIL (2 (6 NIL NIL NIL)) NIL NIL) (2)

A problem with this representation, similar in origin to the problem of valid function parameters in genetic programming, is that it is underconstrained: Only some trees will encode valid Lego structures. No more than one brick can be at each corner, so every node can have at most three sons, not four as the encoding allows. Joint sizes must also be compatible with each other and in general, two bricks cannot overlap each other. The following extension to (2), for example, is illegal because both 10-bricks would share the same physical space

(10 NIL (2 (6 NIL NIL NIL (4 (10 NIL NIL NIL)))) NIL NIL) (3)

4.1 Mutation and Crossover

There are two possible mutations:

1. Mutation of the joint and brick sizes at any random point

2. Addition of a single brick at a random empty joint

To implement mutation, a random joint in the tree (or the root) is selected, and, if NIL, mutation 2 is applied, otherwise mutation 1.

Crossover, in turn, Regarding crossover, the basic crossover operator involves two parent trees out of which random subtrees are selected. The offspring generated has the first subtree removed and replaced by the second.

After mutation or crossover operators are applied, a new, possibly invalid specification tree is formed. The resulting is expanded one node at a time and overlapping is checked. Whenever an overlap is found the tree is truncated at that site.

With this procedure, a maximum spatially valid subtree is built as the result of crossover or mutation.

Once a valid tree has been obtained, the physical model is constructed and the structure tested for gravitational correctness. If approved, fitness is evaluated and the new individual is added to the population.

4.2 Steady State GA with low evolutionary pressure.

Our goal is not to optimize the evolutionary algorithm, but to show that evolution is indeed possible and our models are physically sound. We use a straightforward steady-state genetic algorithm:

1. While maximum fitness < Target fitness 2. Do Randomly select mutation or crossover. 3. Select 1 (2 for crossover) random individual(s) with fitness proportional probability. 4. Apply mutation or crossover operator 5. Generate physical model and test for gravitational load 6. If the new model will support its own weight. 7. Then replace a random individual with it.(chosen with inverse fitness proportional probability)

These are the basic parameters used in the GA runs:

Population Size:1000