Genetically Seeking Sparse Rulers

An introduction to genetic algorithms

Using an n-inch ruler with markings at every inch, you can measure any integral number of inches from 1 to n. But you can quickly see that not all of those marks are necessary. Rulers with minimal or nearly minimal numbers of markings are called “sparse rulers.” This notebook contains the code for finding sparse rulers using a genetic algorithm.

The general procedure in a genetic algorithm is to work iteratively toward a solution to a problem. At any given iteration, a family of possible solutions is evaluated for their “fitness,” that is, how close they come to satisfying the conditions of the problem. The algorithm selects the fittest solutions and then recombines these solutions to produce a new generation of solutions. In this way a solution to the problem “evolves.”

References to genetic algorithms [Holland 1992], genetic programming [Koza 1992], and further general questions of evolution and order [Kauffman 1993] can be found at the conclusion of this notebook.


Seeking Sparse Rulers to Measure All the Numbers from 0 to 36

The sparse ruler problem is ideal for illustrating the process of genetic solution. In the following notebook, a ruler for the number p is simply represented as a list beginning with 0 and ending with p. The case for [Graphics:Images/index_gr_1.gif] is interesting, because there is exactly one minimal sparse ruler for this value.

Defining a fitness function

By fixing the seed for the pseudorandom number generator, you can guarantee a specific outcome. This value can be changed, or the function left unevaluated to get new results.
[Graphics:Images/index_gr_2.gif]
As an example, consider the ruler for[Graphics:Images/index_gr_3.gif] for the following arbitrarily selected values:
[Graphics:Images/index_gr_4.gif]
[Graphics:Images/index_gr_5.gif]
The fitness of this ruler is measured by comparing the number of marks in the ruler with the number of integers the ruler will measure. The number of marks in the ruler (counting 0) is just the Mathematica Length function. The set of all numbers that the ruler will measure is found with the defined function span. One way to find this set is to map the absolute value function across all differences generated by a given ruler list.
[Graphics:Images/index_gr_6.gif]
For the example r,
span[r]
[Graphics:Images/index_gr_7.gif]
The function fitness can now be defined as a function that will increase when either the number of marks in the ruler decreases or the number of integers measured by the ruler increases.
[Graphics:Images/index_gr_8.gif]
For the example given here, the fitness value is about 2.
[Graphics:Images/index_gr_9.gif]
[Graphics:Images/index_gr_10.gif]
A ruler containing marks at every point from 0 to 36 would have a fitness equal to 0. It is known that a sparse ruler with ten marks exists for [Graphics:Images/index_gr_11.gif]. The length of the span of this ruler would be 37, and the resulting fitness value would be 27.

Producing a new generation of solutions

Through a rather loose usage of biological terminology, the rulers can be thought of as “chromosomes,” and each number in the ruler set as a “gene.” The function donate is a “crossing-over” function that pastes together parts of two rulers. This function occasionally leaves out some integer common to both rulers, resulting in a “mutation by omission.” The function newGene will result in “mutation by insertion” of a new integer. The rate is fixed at a rather high value, 0.7 in this case. The function mate combines both types of mutation. This function also guarantees that the values 0 and p will be retained in any new combination. Finally, the offspring function generates a new set of n rulers by “mating” a given pair of parent rulers.
[Graphics:Images/index_gr_12.gif]
[Graphics:Images/index_gr_13.gif]
[Graphics:Images/index_gr_14.gif]
[Graphics:Images/index_gr_15.gif]
The example below shows a generation of five new rulers resulting from the combination of two parent rulers. The fitness function tells you which two to select.
[Graphics:Images/index_gr_16.gif]
[Graphics:Images/index_gr_17.gif]
[Graphics:Images/index_gr_18.gif]
[Graphics:Images/index_gr_19.gif]
[Graphics:Images/index_gr_20.gif]

Evolving a solution through multiple generations of rulers

The scheme is to begin with two original rulers, labeled alphaRuler and betaRuler, then recursively generate new rulers in population sizes equal to 5. (This value, like the mutation rate of 0.7 above, was arrived at by experimenting.) The two fittest rulers from each generation are indexed as newAlpha[i], and newBeta[i], where fitness[newAlpha[i]] <= fitness[newBeta[i]]. Note the use of delayed assignment (:=) followed by immediate assignment (=) in setting up the recursion.
[Graphics:Images/index_gr_21.gif]
[Graphics:Images/index_gr_22.gif]
[Graphics:Images/index_gr_23.gif]
[Graphics:Images/index_gr_24.gif]
[Graphics:Images/index_gr_25.gif]
Since the ruler labeled newBetaRuler[i] will have the best fitness value, a plot of these values will indicate how well the generations of rulers are evolving toward a solution.
[Graphics:Images/index_gr_26.gif]
[Graphics:Images/index_gr_27.gif]

The graph shows that the rulers are evolving in terms of increasing fitness. The evolution is obviously not monotonic, however. The best ruler in this set of generations is newBetaRuler[19].

[Graphics:Images/index_gr_28.gif]
[Graphics:Images/index_gr_29.gif]
The ruler is reasonably short.
[Graphics:Images/index_gr_30.gif]
[Graphics:Images/index_gr_31.gif]
The ruler will measure all but seven of the numbers between 0 and 36.
[Graphics:Images/index_gr_32.gif]
[Graphics:Images/index_gr_33.gif]
You can see from the fitness value that there is still considerable room for improvement. (Remember that you should be able to find fitness values up to 27.)
[Graphics:Images/index_gr_34.gif]
[Graphics:Images/index_gr_35.gif]
This fitness function seems to select quickly the rulers that will measure all or most of the numbers between 0 and a given value p. Here is a typical plot of 100 generations.
[Graphics:Images/index_gr_36.gif]
[Graphics:Images/index_gr_37.gif]

Here is a selection of eleven rulers from this set of generations. These will measure the complete set of numbers between 0 and 36.

[Graphics:Images/index_gr_38.gif]
[Graphics:Images/index_gr_39.gif]
[Graphics:Images/index_gr_40.gif]
[Graphics:Images/index_gr_41.gif]
[Graphics:Images/index_gr_42.gif]
[Graphics:Images/index_gr_43.gif]
[Graphics:Images/index_gr_44.gif]
[Graphics:Images/index_gr_45.gif]
The above list, with sequences of identical rulers, is typical. The evolutionary process goes through periods of stability and periods of fluctuation, as you can see by examining a plot of 1,000 generations.
[Graphics:Images/index_gr_46.gif]
[Graphics:Images/index_gr_47.gif]
[Graphics:Images/index_gr_48.gif]

An Alternative Visualization

The next two functions give a different &ldquo;picture&rdquo; of a given ruler.
[Graphics:Images/index_gr_49.gif]
[Graphics:Images/index_gr_50.gif]
To create an image of the rulers themselves, you first convert them to binary strings. Thus the ruler [Graphics:Images/index_gr_51.gif] would have the respective binary representation:
[Graphics:Images/index_gr_52.gif]
[Graphics:Images/index_gr_53.gif]
You can use the Mathematica ListDensityPlot function to transform numeric lists into &ldquo;actual&rdquo; rulers.

For example, if you view the first 15 best rulers from a particular series using ListDensityPlot[15], you get the following picture.

[Graphics:Images/index_gr_54.gif]

This plot shows at a glance that the first ruler is [Graphics:Images/index_gr_55.gif]; also, that the mark 24 is found on each of the second through the fifteenth rulers. The marks on any other ruler in the set, and the persistence of marks across several generations, is easily visualized.

If you turn this plot sideways, you can match each ruler to its fitness value.

[Graphics:Images/index_gr_56.gif]
[Graphics:Images/index_gr_57.gif]
[Graphics:Images/index_gr_58.gif]
[Graphics:Images/index_gr_59.gif]
[Graphics:Images/index_gr_60.gif]
[Graphics:Images/index_gr_61.gif]

For an entire set of 1,000 generations, you have the following picture.

[Graphics:Images/index_gr_62.gif]
[Graphics:Images/index_gr_63.gif]
[Graphics:Images/index_gr_64.gif]
[Graphics:Images/index_gr_65.gif]

Exploring the Fitness Landscape for Small Values of p

For small values of p, you can look at an exhaustive list of rulers for the number p. A convenient way to generate these rulers is by using the GrayCode function from the DiscreteMath`Combinatorica` package. The GrayCode function generates a collection of sets such that adjacent sets in the list differ by only one element. From this list of sets the function rulerList constructs a set of rulers for the number p, such that two adjacent rulers in the list differ by only one integer.
[Graphics:Images/index_gr_66.gif]
[Graphics:Images/index_gr_67.gif]
[Graphics:Images/index_gr_68.gif]
[Graphics:Images/index_gr_69.gif]
[Graphics:Images/index_gr_70.gif]
The fitness values of the set of all rulers for a given p can be plotted as a &ldquo;landscape&rdquo; that shows how the fitness varies across a set of rulers. For example, when [Graphics:Images/index_gr_71.gif], the maximum fitness is 5. The plot below shows the fitness values for the [Graphics:Images/index_gr_72.gif] rulers arranged so that each ruler differs from its neighbor by one element.
[Graphics:Images/index_gr_73.gif]
[Graphics:Images/index_gr_74.gif]
[Graphics:Images/index_gr_75.gif]
[Graphics:Images/index_gr_76.gif]

The table also shows that for [Graphics:Images/index_gr_77.gif] there are multiple rulers with the maximum fitness value. The Position function shows the location of these rulers. The list of locations can be used as an index to show all the sparse rulers for [Graphics:Images/index_gr_78.gif].

[Graphics:Images/index_gr_79.gif]
[Graphics:Images/index_gr_80.gif]
[Graphics:Images/index_gr_81.gif]
Running a new experiment for [Graphics:Images/index_gr_82.gif] and plotting the fitness values of the best ruler at each generation shows that the evolution of rulers for this value of p can reach a steady state at about the twentieth generation. You need to clear the results of previous experiments. A simple way to do this is to clear and then reinitialize the following two functions.
[Graphics:Images/index_gr_83.gif]
(Reinitialize the functions rulerGeneration and newBetaRuler.)
[Graphics:Images/index_gr_84.gif]
[Graphics:Images/index_gr_85.gif]
[Graphics:Images/index_gr_86.gif]

You can show how the evolving rulers migrate into the fitness landscape. betaRulerListReduced produces an abbreviated list of the best rulers, removing successive identical rulers while maintaining the order in which the rulers have evolved.

[Graphics:Images/index_gr_87.gif]
[Graphics:Images/index_gr_88.gif]
The set sites list the horizontal values of the positions of the rulers, while sitePoints pairs each horizontal value with its corresponding fitness. siteLines traces the evolution of the rulers through the landscape.
[Graphics:Images/index_gr_89.gif]
[Graphics:Images/index_gr_90.gif]
[Graphics:Images/index_gr_91.gif]
[Graphics:Images/index_gr_92.gif]
[Graphics:Images/index_gr_93.gif]

Lightening the color of the landscape makes it easier to distinguish the evolutionary path.

[Graphics:Images/index_gr_94.gif]
[Graphics:Images/index_gr_95.gif]
[Graphics:Images/index_gr_96.gif]
[Graphics:Images/index_gr_97.gif]

Animation of the genetic algorithm

Finally, you have an animation showing the fitness values of the evolving rulers moving through the landscape.
[Graphics:Images/index_gr_98.gif]
[Graphics:Images/index_gr_99.gif]

[Graphics:Images/index_gr_100.gif]

[Graphics:Images/index_gr_101.gif]

[Graphics:Images/index_gr_102.gif]

[Graphics:Images/index_gr_103.gif]

[Graphics:Images/index_gr_104.gif]

[Graphics:Images/index_gr_105.gif]

[Graphics:Images/index_gr_106.gif]

[Graphics:Images/index_gr_107.gif]

[Graphics:Images/index_gr_108.gif]

[Graphics:Images/index_gr_109.gif]

[Graphics:Images/index_gr_110.gif]

Comments and answers

Depending upon available computing power, the landscape values for larger ruler lengths can be plotted along with more complex animations.

Conclusion

A more general way of thinking about sparse rulers and the fitness landscape is to define the rulers as binary strings. Each mark i on a ruler is represented by a 1 in the corresponding position of the binary string. For example, the ruler [Graphics:Images/index_gr_111.gif] would be represented by the string [Graphics:Images/index_gr_112.gif]. Since the rulers to measure all numbers up to the value p always include the numbers 0 and p, the binary representations of the rulers always include a 1 in the first and pth positions. The fitness function can therefore be thought of as being defined on a hypercube of dimension [Graphics:Images/index_gr_113.gif]. The genetic evolution of rulers corresponds to a tour through this hypercube.

Since the values of [Graphics:Images/index_gr_114.gif] rapidly become too large, the entire fitness landscape for large values of p cannot be pictured. However, &ldquo;sketches&rdquo; of the landscape can provide useful information. For example, every fitness landscape will include the fitness value of the ruler containing all possible marks. This is the &ldquo;zero valley&rdquo; located in the graph above at the point 341 on the horizontal axis. There are also zones that are relatively rich in high fitness values, such as the region from 442 to 502 on the horizontal axis. Instead of always beginning with the zero generation rulers as [Graphics:Images/index_gr_115.gif], collections of rulers could be seeded in the most promising zones of the landscape.

The numbers of offspring and the mutation rate could vary with the fitness of the evolving rulers. If generation size and mutation rate were to vary inversely with fitness, then the population should tend to evolve within an increasingly smaller zone. The appropriate metric here is the Hamming distance, which defines the distance between two binary strings of length n as the number of positions in which the two strings are different. Two strings could be a small Hamming distance apart and still not look close together in a graphical representation of the fitness landscape. For example, in the representation of the landscape above, the first fitness measure is for the ruler [Graphics:Images/index_gr_116.gif] and the last measure is for the ruler [Graphics:Images/index_gr_117.gif]--the rulers at opposite sides of the landscape diagram are only one unit apart in Hamming Distance. This is a result of the way the Gray code generates the list of rulers.

An alternative algorithm could contain a timing device that would periodically raise and lower the mutation rate. Such an algorithm could produce occasional bursts of mutant rulers that would wander into unexplored areas of the landscape. Finally, the fitness function itself might change, in which case the landscape would be different at different stages of evolution.

[Graphics:Images/index_gr_118.gif]
[Graphics:Images/index_gr_119.gif]
There are 68,719,476,736 (about 70 billion) possible rulers of length 36, and only one of minimal length 9. Where in hyperspace does this unique solution live? How long would it take to find it? How good are the 36 adjacent rulers? Can the genetic algorithm find this absolute maximum? How good are the 94,143,280 other rulers of length 9? How are the best rulers of length 10, 11, and 12 distributed through hyperspace?
[Graphics:Images/index_gr_120.gif]
[Graphics:Images/index_gr_121.gif]

Code for this Notebook

[Graphics:Images/index_gr_122.gif]
[Graphics:Images/index_gr_123.gif]
[Graphics:Images/index_gr_124.gif]
[Graphics:Images/index_gr_125.gif]
[Graphics:Images/index_gr_126.gif]
[Graphics:Images/index_gr_127.gif]
[Graphics:Images/index_gr_128.gif]
[Graphics:Images/index_gr_129.gif]
[Graphics:Images/index_gr_130.gif]
[Graphics:Images/index_gr_131.gif]
[Graphics:Images/index_gr_132.gif]
[Graphics:Images/index_gr_133.gif]
[Graphics:Images/index_gr_134.gif]
[Graphics:Images/index_gr_135.gif]
[Graphics:Images/index_gr_136.gif]
[Graphics:Images/index_gr_137.gif]
[Graphics:Images/index_gr_138.gif]
[Graphics:Images/index_gr_139.gif]
[Graphics:Images/index_gr_140.gif]
[Graphics:Images/index_gr_141.gif]
[Graphics:Images/index_gr_142.gif]
[Graphics:Images/index_gr_143.gif]
[Graphics:Images/index_gr_144.gif]
[Graphics:Images/index_gr_145.gif]
[Graphics:Images/index_gr_146.gif]
[Graphics:Images/index_gr_147.gif]
[Graphics:Images/index_gr_148.gif]
[Graphics:Images/index_gr_149.gif]
[Graphics:Images/index_gr_150.gif]

References and Links

(Text materials may be out-of-print and web links may have expired or been modified. For assistance, contact the author -- dfowler1@unl.edu.)

Holland, John H. Adaptation in Natural and Artificial Systems: An Introductory Analysis With Applications to Biology, Control, and Artificial Intelligence. MIT Press, 1992.

Kauffman, Stuart A. The Origins of Order: Self-Organization and Selection in Evolution. Oxford Press, 1993.

Koza, John R. Genetic Programming: On the Programming of Computers by Means of Natural Selection (Complex Adaptive Systems). MIT Press, 1992.

Skiena, Steven S. The Algorithm Design Manual. TELOS-Springer Verlag, 1998.


Converted by Mathematica      July 2, 2002