Skip to content

Commit e2b56c8

Browse files
committed
More updates to README and docs
1 parent 23ce5e0 commit e2b56c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2162
-2790
lines changed

README.md

Lines changed: 223 additions & 448 deletions
Large diffs are not rendered by default.

README_YARD.md

Lines changed: 7 additions & 233 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
[![Gem Version](https://badge.fury.io/rb/evolvable.svg)](https://badge.fury.io/rb/evolvable)
44

5-
**Code Version: {@string Evolvable::VERSION}** (unreleased)
6-
7-
🚧 **The README and Documentation are still evolving**
5+
**Code Version: {@string Evolvable::VERSION}**
86

97
Evolvable is a Ruby gem that brings genetic algorithms to Ruby objects through simple, flexible APIs. Define genes, implement fitness criteria, and let evolution discover optimal solutions through selection, combination, and mutation.
108

@@ -24,11 +22,10 @@ Evolvable is ideal when the solution space is too large or complex for brute-for
2422

2523
Whether you're optimizing parameters, generating creative content, or simulating complex systems, Evolvable provides a natural, object-oriented approach to evolutionary algorithms.
2624

27-
## Creative Applications
25+
**Creative Applications**
2826

29-
Evolvable treats creative, object-oriented representations as first-class citizens. The same API that optimizes numeric parameters can evolve music compositions, UI layouts, or game content with equal fluency.
27+
Evolvable treats creative, object-oriented representations as first-class citizens. The same API that optimizes numeric parameters can evolve music compositions, UI layouts, or game content with equal fluency. Examples include:
3028

31-
Creative applications of Evolvable include:
3229
- **Generative art**: Evolve visual compositions based on aesthetic criteria
3330
- **Music composition**: Create melodies, chord progressions, and rhythms
3431
- **Game design**: Generate levels, characters, or game mechanics
@@ -45,11 +42,7 @@ Creative applications of Evolvable include:
4542
* [Evolution](#evolution)
4643
* [Selection](#selection)
4744
* [Combination](#combination)
48-
* [Crossover Strategies](#crossover-strategies)
4945
* [Mutation](#mutation)
50-
* [Gene Space](#gene-space)
51-
* [Count Genes](#count-genes)
52-
* [Genomes](#genomes)
5346
* [Gene Clusters](#gene-clusters)
5447
* [Community](#community)
5548
* [Serialization](#serialization)
@@ -69,7 +62,7 @@ Add [gem "evolvable"](https://rubygems.org/gems/evolvable) to your Gemfile and r
6962
## Concepts
7063

7164
Evolvable is built on these core concepts:
72-
- **Genes**: Ruby objects that cache data for evolvables
65+
- **Genes**: Ruby objects that represent traits or behaviors and are passed down during evolution.
7366
- **Evolvables**: Your Ruby classes that include "Evolvable" and delegate to genes
7467
- **Populations**: Groups of evolvables instances that evolve together
7568
- **Evaluation**: Sorts evolvables by fitness
@@ -96,8 +89,6 @@ The framework offers built-in implementations while allowing domain-specific cus
9689

9790
{@readme Evolvable::Goal}
9891

99-
{@readme Evolvable::Evaluation}
100-
10192
Example goal implementation that prioritizes evolvables with fitness values within a specific range:
10293

10394
{@example Evolvable::Goal}
@@ -124,257 +115,40 @@ Example goal implementation that prioritizes evolvables with fitness values with
124115

125116
[Combination Documentation]({@string Evolvable::DOC_URL}/Evolvable/Combination)
126117

127-
## Crossover Strategies
128-
129118
**Point Crossover**
130119

131120
{@readme Evolvable::PointCrossover}
132121

122+
[PointCrossover Documentation]({@string Evolvable::DOC_URL}/Evolvable/PointCrossover)
123+
133124
**Uniform Crossover**
134125

135126
{@readme Evolvable::UniformCrossover}
136127

137-
[PointCrossover Documentation]({@string Evolvable::DOC_URL}/Evolvable/PointCrossover)
128+
[UniformCrossover Documentation]({@string Evolvable::DOC_URL}/Evolvable/UniformCrossover)
138129

139130
## Mutation
140131

141132
{@readme Evolvable::Mutation}
142133

143-
**Example**
144-
{@example Evolvable::Mutation}
145-
146134
[Mutation Documentation]({@string Evolvable::DOC_URL}/Evolvable/Mutation)
147135

148-
## Gene Space
149-
150-
{@readme Evolvable::GeneSpace}
151-
152-
**Example**
153-
```ruby
154-
class MusicComposer
155-
include Evolvable
156-
157-
# Define basic musical genes
158-
gene :melody, type: MelodyGene, count: 1
159-
gene :harmony, type: HarmonyGene, count: 1
160-
gene :rhythm, type: RhythmGene, count: 1
161-
162-
# Group audio effects into a cluster for easier handling
163-
gene :reverb, type: ReverbGene, count: 0..1, cluster: :effects
164-
gene :delay, type: DelayGene, count: 0..1, cluster: :effects
165-
gene :distortion, type: DistortionGene, count: 0..1, cluster: :effects
166-
gene :flanger, type: FlangerGene, count: 0..1, cluster: :effects
167-
168-
def play
169-
# Access genes directly
170-
puts "Playing melody: #{melody}"
171-
172-
# Or access gene clusters as collections
173-
puts "With effects: #{effects.map(&:name).join(', ')}"
174-
end
175-
176-
def fitness
177-
# Evaluate fitness based on musical theory and constraints
178-
melody_score = melody.consonance_with(harmony)
179-
structure_balance = structure.count > 1 ? 1.0 : 0.5
180-
effect_complexity = [1.0, effects.count * 0.2].min
181-
182-
melody_score * structure_balance * effect_complexity
183-
end
184-
end
185-
186-
# Access genes and clusters
187-
composer = MusicComposer.new_evolvable
188-
composer.reverb # Access a specific gene
189-
composer.effects # Access all genes in the effects cluster
190-
composer.effects.count # Number of effect genes
191-
composer.structure.first.type # Access a property of the first structure gene
192-
```
193-
194-
[GeneSpace Documentation]({@string Evolvable::DOC_URL}/Evolvable/GeneSpace)
195-
196-
## Count Genes
197-
198-
**Dynamic Count Genes**
199-
200-
{@readme Evolvable::CountGene}
201-
202-
**Fixed Count Genes**
203-
204-
{@readme Evolvable::RigidCountGene}
205-
206-
[CountGene Documentation]({@string Evolvable::DOC_URL}/Evolvable/CountGene)
207-
208-
## Genomes
209-
210-
{@readme Evolvable::Genome}
211-
212-
[Genome Documentation]({@string Evolvable::DOC_URL}/Evolvable/Genome)
213-
214136
## Gene Clusters
215137

216138
{@readme Evolvable::GeneCluster}
217139

218-
**Example**
219-
```ruby
220-
# Define a reusable cluster for visual styling
221-
module Evolvable::UI
222-
class StylingCluster
223-
include Evolvable::GeneCluster
224-
225-
gene :background_color, type: 'UI::ColorGene', count: 1
226-
gene :text_color, type: 'UI::ColorGene', count: 1
227-
gene :border_color, type: 'UI::ColorGene', count: 0..1
228-
gene :border_width, type: 'UI::SizeGene', count: 0..1
229-
gene :border_radius, type: 'UI::RadiusGene', count: 0..1
230-
gene :shadow, type: 'UI::ShadowGene', count: 0..1
231-
end
232-
end
233-
234-
# Use the styling cluster in multiple UI components
235-
class Button
236-
include Evolvable
237-
238-
# Apply the styling cluster
239-
cluster :styling, type: Evolvable::UI::StylingCluster
240-
241-
# Button-specific genes
242-
gene :size, type: SizeGene, count: 1
243-
gene :text, type: TextGene, count: 1
244-
245-
def render
246-
puts "Button with #{text}"
247-
puts "Background: #{styling.background_color.hex_code}"
248-
puts "Border: #{styling.border_width&.value || 0}px"
249-
end
250-
251-
def fitness
252-
# Evaluate based on design principles and constraints
253-
contrast = styling.text_color.contrast_with(styling.background_color)
254-
readability = text.length < 15 ? 1.0 : 0.7
255-
256-
contrast * readability
257-
end
258-
end
259-
260-
class Panel
261-
include Evolvable
262-
263-
# Reuse the same styling cluster with a different name
264-
cluster :visual, type: Evolvable::UI::StylingCluster
265-
266-
# Panel-specific genes
267-
gene :width, type: SizeGene, count: 1
268-
gene :height, type: SizeGene, count: 1
269-
gene :children, type: ComponentGene, count: 0..10
270-
271-
def render
272-
puts "Panel #{width.value}x#{height.value}"
273-
puts "Background: #{visual.background_color.hex_code}"
274-
children.each(&:render)
275-
end
276-
end
277-
```
278-
279140
[GeneCluster Documentation]({@string Evolvable::DOC_URL}/Evolvable/GeneCluster)
280141

281142
## Community
282143

283144
{@readme Evolvable::Community}
284145

285-
**Example**
286-
```ruby
287-
# A complex ecosystem with multiple interacting species
288-
class BiomeSimulation
289-
include Evolvable::Community
290-
291-
evolvable_community plants: Plant,
292-
herbivores: Herbivore,
293-
carnivores: Carnivore
294-
295-
def simulate_interactions(cycles = 1)
296-
cycles.times do
297-
# Plants grow based on environmental factors
298-
plants.each(&:grow)
299-
300-
# Herbivores eat plants and may increase or decrease in population
301-
herbivores.each do |herbivore|
302-
herbivore.eat(plants.sample)
303-
end
304-
305-
# Carnivores hunt herbivores
306-
carnivores.each do |carnivore|
307-
carnivore.hunt(herbivores.sample)
308-
end
309-
310-
# Evolve all populations for one generation
311-
evolve_all
312-
end
313-
end
314-
315-
def evolve_all
316-
populations_by_name.values.each do |population|
317-
population.evolve(count: 1)
318-
end
319-
end
320-
end
321-
322-
# Initialize and use the simulation
323-
biome = BiomeSimulation.new_community
324-
biome.simulate_interactions(10)
325-
```
326-
327146
[Community Documentation]({@string Evolvable::DOC_URL}/Evolvable/Community)
328147

329148
## Serialization
330149

331150
{@readme Evolvable::Serializer}
332151

333-
**Example**
334-
```ruby
335-
# Basic serialization and persistence
336-
class EvolutionManager
337-
def save_champion(population, filename)
338-
champion = population.best_evolvable
339-
serialized = champion.dump_genome
340-
File.write(filename, serialized)
341-
puts "Champion saved with fitness: #{champion.fitness}"
342-
end
343-
344-
def load_champion(evolvable_class, filename)
345-
serialized = File.read(filename)
346-
champion = evolvable_class.new_evolvable
347-
champion.load_genome(serialized)
348-
champion
349-
end
350-
351-
def checkpoint_population(population, filename)
352-
serialized = population.dump
353-
File.write(filename, serialized)
354-
puts "Population checkpoint saved at generation #{population.evolutions_count}"
355-
end
356-
357-
def restore_population(filename)
358-
serialized = File.read(filename)
359-
Evolvable::Population.load(serialized)
360-
end
361-
end
362-
363-
# Usage
364-
manager = EvolutionManager.new
365-
population = MyEvolvable.new_population(size: 100)
366-
367-
# Run evolution for 50 generations with checkpoints
368-
5.times do |i|
369-
population.evolve(count: 10)
370-
manager.checkpoint_population(population, "checkpoint_#{i}.dat")
371-
manager.save_champion(population, "champion_#{i}.dat")
372-
end
373-
374-
# Restore from checkpoint
375-
restored = manager.restore_population("checkpoint_3.dat")
376-
```
377-
378152
[Serializer Documentation]({@string Evolvable::DOC_URL}/Evolvable/Serializer)
379153

380154
## Contributing

docs/Evolvable.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ <h2>
407407
<li class="public ">
408408
<span class="summary_signature">
409409

410-
<a href="#find_gene-instance_method" title="#find_gene (instance method)">#<strong>find_gene</strong>(name) &#x21d2; Object </a>
410+
<a href="#find_gene-instance_method" title="#find_gene (instance method)">#<strong>find_gene</strong> &#x21d2; Object </a>
411411

412412

413413

@@ -452,7 +452,7 @@ <h2>
452452
<li class="public ">
453453
<span class="summary_signature">
454454

455-
<a href="#find_genes-instance_method" title="#find_genes (instance method)">#<strong>find_genes</strong>(name) &#x21d2; Object </a>
455+
<a href="#find_genes-instance_method" title="#find_genes (instance method)">#<strong>find_genes</strong> &#x21d2; Object </a>
456456

457457

458458

@@ -1054,7 +1054,7 @@ <h3 class="signature " id="dump_genome-instance_method">
10541054
<div class="method_details ">
10551055
<h3 class="signature " id="find_gene-instance_method">
10561056

1057-
#<strong>find_gene</strong>(name) &#x21d2; <tt>Object</tt>
1057+
#<strong>find_gene</strong> &#x21d2; <tt>Object</tt>
10581058

10591059

10601060

@@ -1073,8 +1073,8 @@ <h3 class="signature " id="find_gene-instance_method">
10731073
<td>
10741074
<pre class="code"><span class="info file"># File 'lib/evolvable.rb', line 304</span>
10751075

1076-
<span class='kw'>def</span> <span class='id identifier rubyid_find_gene'>find_gene</span><span class='lparen'>(</span><span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span>
1077-
<span class='ivar'>@genome</span><span class='op'>&amp;.</span><span class='id identifier rubyid_find_gene'>find_gene</span><span class='lparen'>(</span><span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span>
1076+
<span class='kw'>def</span> <span class='id identifier rubyid_find_gene'>find_gene</span><span class='lparen'>(</span><span class='op'>...</span><span class='rparen'>)</span>
1077+
<span class='ivar'>@genome</span><span class='op'>&amp;.</span><span class='id identifier rubyid_find_gene'>find_gene</span><span class='lparen'>(</span><span class='op'>...</span><span class='rparen'>)</span>
10781078
<span class='kw'>end</span></pre>
10791079
</td>
10801080
</tr>
@@ -1161,7 +1161,7 @@ <h3 class="signature " id="find_gene_cluster-instance_method">
11611161
<div class="method_details ">
11621162
<h3 class="signature " id="find_genes-instance_method">
11631163

1164-
#<strong>find_genes</strong>(name) &#x21d2; <tt>Object</tt>
1164+
#<strong>find_genes</strong> &#x21d2; <tt>Object</tt>
11651165

11661166

11671167

@@ -1180,8 +1180,8 @@ <h3 class="signature " id="find_genes-instance_method">
11801180
<td>
11811181
<pre class="code"><span class="info file"># File 'lib/evolvable.rb', line 308</span>
11821182

1183-
<span class='kw'>def</span> <span class='id identifier rubyid_find_genes'>find_genes</span><span class='lparen'>(</span><span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span>
1184-
<span class='ivar'>@genome</span><span class='op'>&amp;.</span><span class='id identifier rubyid_find_genes'>find_genes</span><span class='lparen'>(</span><span class='id identifier rubyid_name'>name</span><span class='rparen'>)</span> <span class='op'>||</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
1183+
<span class='kw'>def</span> <span class='id identifier rubyid_find_genes'>find_genes</span><span class='lparen'>(</span><span class='op'>...</span><span class='rparen'>)</span>
1184+
<span class='ivar'>@genome</span><span class='op'>&amp;.</span><span class='id identifier rubyid_find_genes'>find_genes</span><span class='lparen'>(</span><span class='op'>...</span><span class='rparen'>)</span> <span class='op'>||</span> <span class='lbracket'>[</span><span class='rbracket'>]</span>
11851185
<span class='kw'>end</span></pre>
11861186
</td>
11871187
</tr>
@@ -1609,7 +1609,7 @@ <h3 class="signature " id="merge_genome!-instance_method">
16091609
</div>
16101610

16111611
<div id="footer">
1612-
Generated on Fri May 9 16:06:43 2025 by
1612+
Generated on Sat May 10 18:35:47 2025 by
16131613
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
16141614
0.9.37 (ruby-3.4.2).
16151615
</div>

docs/Evolvable/ClassMethods.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,7 @@ <h3 class="signature " id="new_population-instance_method">
12231223
</div>
12241224

12251225
<div id="footer">
1226-
Generated on Fri May 9 16:06:43 2025 by
1226+
Generated on Sat May 10 18:35:47 2025 by
12271227
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
12281228
0.9.37 (ruby-3.4.2).
12291229
</div>

0 commit comments

Comments
 (0)