evolvable 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0d88efd1d44ed47b0c02c2c9f2c309f3affa23606d229aabe54171f3c275e2f0
4
+ data.tar.gz: 5317b0c6191375de0d27e7dc00ad587b566fd2bf42142395f39d6ee938d32908
5
+ SHA512:
6
+ metadata.gz: efbb2968e4ad76749d4bb5085a6da5359268db1cca20e0afec2feb30ca9bd8953dfe2fc60f278c80a5e067eac0938676246f06f586063463a638031cc01d22dd
7
+ data.tar.gz: 3106710898d9456ae596b1b3812bd49a02509b3c6865d3ac56c973d22455cf2089f3b9e0b6125891bf72706ede2321ae965e0144bf30d95d632aa3dbf5ff1b82
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ .byebug_history
data/.rubocop.yml ADDED
@@ -0,0 +1,20 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6.1
3
+
4
+ Style/Documentation:
5
+ Enabled: false
6
+
7
+ Style/SymbolArray:
8
+ Enabled: false
9
+
10
+ Style/FrozenStringLiteralComment:
11
+ Enabled: false
12
+
13
+ Style/ClassAndModuleChildren:
14
+ Enabled: false
15
+
16
+ Naming/VariableNumber:
17
+ EnforcedStyle: 'snake_case'
18
+
19
+ Metrics/LineLength:
20
+ Max: 90
data/CHANGELOG.md ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ evolvable (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.0)
10
+ byebug (11.0.0)
11
+ diff-lcs (1.3)
12
+ jaro_winkler (1.5.2)
13
+ parallel (1.13.0)
14
+ parser (2.6.0.0)
15
+ ast (~> 2.4.0)
16
+ powerpack (0.1.2)
17
+ rainbow (3.0.0)
18
+ rake (10.5.0)
19
+ rspec (3.8.0)
20
+ rspec-core (~> 3.8.0)
21
+ rspec-expectations (~> 3.8.0)
22
+ rspec-mocks (~> 3.8.0)
23
+ rspec-core (3.8.0)
24
+ rspec-support (~> 3.8.0)
25
+ rspec-expectations (3.8.2)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.8.0)
28
+ rspec-mocks (3.8.0)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.8.0)
31
+ rspec-support (3.8.0)
32
+ rubocop (0.64.0)
33
+ jaro_winkler (~> 1.5.1)
34
+ parallel (~> 1.10)
35
+ parser (>= 2.5, != 2.5.1.1)
36
+ powerpack (~> 0.1)
37
+ rainbow (>= 2.2.2, < 4.0)
38
+ ruby-progressbar (~> 1.7)
39
+ unicode-display_width (~> 1.4.0)
40
+ ruby-progressbar (1.10.0)
41
+ unicode-display_width (1.4.1)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ bundler (~> 2.0)
48
+ byebug (~> 11.0)
49
+ evolvable!
50
+ rake (~> 10.0)
51
+ rspec (~> 3.0)
52
+ rubocop (~> 0.64.0)
53
+
54
+ BUNDLED WITH
55
+ 2.0.1
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Evolvable
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/evolvable`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'evolvable'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install evolvable
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/evolvable.
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'evolvable'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/evolvable.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'evolvable/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'evolvable'
7
+ spec.version = Evolvable::VERSION
8
+ spec.authors = ['Matt Ruzicka']
9
+
10
+ spec.summary = 'A framework for writing genetic algorithms'
11
+ spec.summary = 'Make your Ruby objects evolvable with genetic algorithms'
12
+ spec.homepage = 'https://github.com/mattruzicka/evolvable'
13
+ spec.license = 'MIT'
14
+
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = 'https://github.com/mattruzicka/evolvable'
17
+ spec.metadata['changelog_uri'] = 'https://github.com/mattruzicka/evolvable' \
18
+ '/blob/master/CHANGELOG.md'
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = 'exe'
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.add_development_dependency 'bundler', '~> 2.0'
30
+ spec.add_development_dependency 'byebug', '~> 11.0'
31
+ spec.add_development_dependency 'rubocop', '~> 0.64.0'
32
+ end
33
+
@@ -0,0 +1,9 @@
1
+ module Evolvable
2
+ module Callbacks
3
+ def evolvable_before_evolution(population); end
4
+
5
+ def evolvable_after_select(population); end
6
+
7
+ def evolvable_after_evolution(population); end
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ class Crossover
2
+ def call(parent_genes, offspring_count)
3
+ parent_gene_couples = parent_genes.combination(2).cycle
4
+ Array.new(offspring_count) do
5
+ p1_genes, p2_genes = parent_gene_couples.next
6
+ p1_genes.merge(p2_genes) { |_k, p1_val, p2_val| [p1_val, p2_val].sample }
7
+ offspring_genes = merge_parent_genes(p1_genes, p2_genes)
8
+ trim_offspring_genes!(offspring_genes, p1_genes.count)
9
+ offspring_genes
10
+ end
11
+ end
12
+
13
+ def inspect
14
+ "#<#{self.class.name} #{as_json.map { |a| a.join(': ') }.join(', ')} >"
15
+ end
16
+
17
+ def as_json
18
+ { type: self.class.name }
19
+ end
20
+
21
+ private
22
+
23
+ def merge_parent_genes(p1_genes, p2_genes)
24
+ p1_genes.merge(p2_genes) { |_k, p1_val, p2_val| [p1_val, p2_val].sample }
25
+ end
26
+
27
+ def trim_offspring_genes!(offspring_genes, parent_genes_count)
28
+ trim_genes_count = offspring_genes.count - parent_genes_count
29
+ return if trim_genes_count.zero?
30
+
31
+ offspring_genes.keys.sample(trim_genes_count).each do |name|
32
+ offspring_genes.delete(name)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ module Evolvable
2
+ module Errors
3
+ class NotImplemented < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,45 @@
1
+ module Evolvable
2
+ module HelperMethods
3
+ def combine_dimensions(dimensions)
4
+ dimension_lengths = dimensions.map(&:length)
5
+ genes_count = dimension_lengths.inject(1) { |product, c| product * c }
6
+
7
+ genes = Array.new(genes_count) { [] }
8
+ element_repeat_counts = compute_element_repeat_counts(dimension_lengths)
9
+ sequence_counts = compute_sequence_counts(dimension_lengths)
10
+
11
+ dimensions.each_with_index do |dimension, dim_index|
12
+ element_count = element_repeat_counts[dim_index]
13
+ sequence = dimension.flat_map { |e| [e] * element_count }
14
+ dimension_sequence = sequence * sequence_counts[dim_index]
15
+ dimension_sequence.each_with_index do |element, gene_index|
16
+ genes[gene_index][dim_index] = element
17
+ end
18
+ end
19
+
20
+ genes
21
+ end
22
+
23
+ private
24
+
25
+ def compute_element_repeat_counts(dimension_lengths)
26
+ repeat_counts = Array.new(dimension_lengths.count - 1) do |n|
27
+ right_side_counts = dimension_lengths[(n + 1)..-1]
28
+ right_side_counts.inject(1) { |product, a| product * a }
29
+ end
30
+ repeat_counts << 1
31
+ repeat_counts
32
+ end
33
+
34
+ def compute_sequence_counts(dimension_lengths)
35
+ Array.new(dimension_lengths.count) do |n|
36
+ if n.zero?
37
+ 1
38
+ else
39
+ right_side_counts = dimension_lengths[0...n]
40
+ right_side_counts.inject(1) { |product, a| product * a }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,62 @@
1
+ module Evolvable
2
+ class Mutation
3
+ extend Forwardable
4
+
5
+ def initialize(rate: 0.03)
6
+ @rate = rate
7
+ end
8
+
9
+ def_delegators :@evolvable_class,
10
+ :evolvable_genes_count,
11
+ :evolvable_gene_pool_size,
12
+ :evolvable_random_genes
13
+
14
+ def call!(individuals)
15
+ @evolvable_class = individuals.first.class
16
+ mutations_count = find_mutations_count(individuals)
17
+ return if mutations_count.zero?
18
+
19
+ mutant_genes = generate_mutant_genes(mutations_count)
20
+ individual_mutations_count = mutations_count / individuals.count
21
+ individual_mutations_count = 1 if individual_mutations_count.zero?
22
+
23
+ mutant_genes.each_slice(individual_mutations_count).with_index do |m_genes, index|
24
+ individual = individuals[index] || individuals.sample
25
+ genes = individual.genes
26
+ genes.merge!(m_genes.to_h)
27
+ rm_genes_count = genes.count - evolvable_genes_count
28
+ genes.keys.sample(rm_genes_count).each { |key| genes.delete(key) }
29
+ end
30
+ end
31
+
32
+ def inspect
33
+ "#<#{self.class.name} #{as_json.map { |a| a.join(': ') }.join(', ')} >"
34
+ end
35
+
36
+ def as_json
37
+ { type: self.class.name,
38
+ rate: @rate }
39
+ end
40
+
41
+ private
42
+
43
+ def find_mutations_count(individuals)
44
+ return 0 if @rate.zero?
45
+
46
+ count = (individuals.count * evolvable_genes_count * @rate)
47
+ return count.to_i if count >= 1
48
+
49
+ rand <= count ? 1 : 0
50
+ end
51
+
52
+ def generate_mutant_genes(mutations_count)
53
+ gene_pool_size = evolvable_gene_pool_size
54
+ mutant_genes = []
55
+ while mutant_genes.count < mutations_count
56
+ genes_count = [gene_pool_size, mutations_count - mutant_genes.count].min
57
+ mutant_genes.concat evolvable_random_genes(genes_count).to_a
58
+ end
59
+ mutant_genes
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evolvable
4
+ class Population
5
+ extend Forwardable
6
+
7
+ def initialize(evolvable_class:,
8
+ size: 20,
9
+ selection_count: 2,
10
+ crossover: Crossover.new,
11
+ mutation: Mutation.new,
12
+ generation_count: 0,
13
+ log_progress: false,
14
+ individuals: [])
15
+ @evolvable_class = evolvable_class
16
+ @size = size
17
+ @selection_count = selection_count
18
+ @crossover = crossover
19
+ @mutation = mutation
20
+ @generation_count = generation_count
21
+ @log_progress = log_progress
22
+ assign_individuals(individuals)
23
+ end
24
+
25
+ attr_reader :evolvable_class,
26
+ :size,
27
+ :selection_count,
28
+ :crossover,
29
+ :mutation,
30
+ :generation_count,
31
+ :individuals
32
+
33
+ def_delegators :@evolvable_class,
34
+ :evolvable_evaluate!,
35
+ :evolvable_initialize,
36
+ :evolvable_random_genes,
37
+ :evolvable_before_evolution,
38
+ :evolvable_after_select,
39
+ :evolvable_after_evolution
40
+
41
+ def evolve!(generations_count: 1, fitness_goal: nil)
42
+ @fitness_goal = fitness_goal
43
+ generations_count.times do
44
+ @generation_count += 1
45
+ evolvable_before_evolution(self)
46
+ evaluate_individuals!
47
+ log_progress if @log_progress
48
+ break if fitness_goal_met?
49
+
50
+ select_individuals!
51
+ evolvable_after_select(self)
52
+ reproduce_individuals!
53
+ mutate_individuals!
54
+ evolvable_after_evolution(self)
55
+ end
56
+ end
57
+
58
+ def evaluate_individuals!
59
+ evolvable_evaluate!(@individuals)
60
+ if @fitness_goal
61
+ @individuals.sort_by! { |i| -(i.fitness - @fitness_goal).abs }
62
+ else
63
+ @individuals.sort_by!(&:fitness)
64
+ end
65
+ end
66
+
67
+ def log_progress
68
+ @individuals.last.evolvable_progress
69
+ end
70
+
71
+ def fitness_goal_met?
72
+ @fitness_goal && @individuals.last.fitness >= @fitness_goal
73
+ end
74
+
75
+ def select_individuals!
76
+ @individuals.slice!(0..-1 - @selection_count)
77
+ end
78
+
79
+ def reproduce_individuals!
80
+ parent_genes = @individuals.map(&:genes)
81
+ offspring_genes = @crossover.call(parent_genes, @size)
82
+ @individuals = offspring_genes.map.with_index do |genes, i|
83
+ evolvable_initialize(genes, self, i)
84
+ end
85
+ end
86
+
87
+ def mutate_individuals!
88
+ @mutation.call!(@individuals)
89
+ end
90
+
91
+ def inspect
92
+ "#<#{self.class.name} #{as_json} >"
93
+ end
94
+
95
+ def as_json
96
+ { evolvable_class: @evolvable_class.name,
97
+ size: @size,
98
+ selection_count: @selection_count,
99
+ crossover: @crossover.as_json,
100
+ mutation: @mutation.as_json,
101
+ generation_count: @generation_count }
102
+ end
103
+
104
+ private
105
+
106
+ def assign_individuals(individuals)
107
+ @individuals = individuals || []
108
+ (@size - individuals.count).times do |n|
109
+ genes = evolvable_random_genes
110
+ @individuals << evolvable_initialize(genes, self, n)
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evolvable
4
+ VERSION = '0.1.0'
5
+ end
data/lib/evolvable.rb ADDED
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'logger'
5
+
6
+ require 'evolvable/version'
7
+ require 'evolvable/population'
8
+ require 'evolvable/crossover'
9
+ require 'evolvable/mutation'
10
+ require 'evolvable/helper_methods'
11
+ require 'evolvable/callbacks'
12
+ require 'evolvable/errors/not_implemented'
13
+
14
+ module Evolvable
15
+ extend HelperMethods
16
+
17
+ def self.included(base)
18
+ base.extend Callbacks
19
+
20
+ def base.evolvable_gene_pool
21
+ raise Errors::NotImplemented, __method__
22
+ end
23
+
24
+ def base.evolvable_genes_count
25
+ evolvable_gene_pool_size
26
+ end
27
+
28
+ def base.evolvable_evaluate!(_individuals); end
29
+
30
+ def base.evolvable_initialize(genes, population, _individual_index)
31
+ evolvable = new
32
+ evolvable.genes = genes
33
+ evolvable.population = population
34
+ evolvable
35
+ end
36
+
37
+ def base.evolvable_population_attrs
38
+ {}
39
+ end
40
+
41
+ def base.evolvable_population(args = {})
42
+ clear_evolvable_gene_pool_caches
43
+ args = evolvable_population_attrs.merge!(args)
44
+ args[:evolvable_class] = self
45
+ Population.new(args)
46
+ end
47
+
48
+ def base.evolvable_gene_pool_cache
49
+ @evolvable_gene_pool_cache ||= evolvable_gene_pool
50
+ end
51
+
52
+ def base.evolvable_gene_pool_size
53
+ @evolvable_gene_pool_size ||= evolvable_gene_pool_cache.size
54
+ end
55
+
56
+ def base.clear_evolvable_gene_pool_caches
57
+ @evolvable_gene_pool_cache = nil
58
+ @evolvable_gene_pool_size = nil
59
+ end
60
+
61
+ def base.evolvable_random_genes(count = nil)
62
+ gene_pool = evolvable_gene_pool_cache
63
+ count ||= evolvable_genes_count
64
+ gene_pool = gene_pool.sample(count) if count < gene_pool.size
65
+ genes = {}
66
+ gene_pool.each { |name, potentials| genes[name] = potentials.sample }
67
+ genes
68
+ end
69
+ end
70
+
71
+ def self.logger
72
+ @logger ||= Logger.new(STDOUT)
73
+ end
74
+
75
+ attr_accessor :genes,
76
+ :population
77
+
78
+ def fitness
79
+ raise Errors::NotImplemented, __method__
80
+ end
81
+
82
+ def evolvable_progress(info = nil)
83
+ info ||= "Generation: #{population.generation_count} | Fitness: #{fitness}"
84
+ Evolvable.logger.info(info)
85
+ end
86
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evolvable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Ruzicka
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '11.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '11.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.64.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.64.0
55
+ description:
56
+ email:
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".gitignore"
62
+ - ".rubocop.yml"
63
+ - CHANGELOG.md
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - README.md
67
+ - bin/console
68
+ - bin/setup
69
+ - evolvable.gemspec
70
+ - lib/evolvable.rb
71
+ - lib/evolvable/callbacks.rb
72
+ - lib/evolvable/crossover.rb
73
+ - lib/evolvable/errors/not_implemented.rb
74
+ - lib/evolvable/helper_methods.rb
75
+ - lib/evolvable/mutation.rb
76
+ - lib/evolvable/population.rb
77
+ - lib/evolvable/version.rb
78
+ homepage: https://github.com/mattruzicka/evolvable
79
+ licenses:
80
+ - MIT
81
+ metadata:
82
+ homepage_uri: https://github.com/mattruzicka/evolvable
83
+ source_code_uri: https://github.com/mattruzicka/evolvable
84
+ changelog_uri: https://github.com/mattruzicka/evolvable/blob/master/CHANGELOG.md
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.0.3
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Make your Ruby objects evolvable with genetic algorithms
104
+ test_files: []