jinni 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e590fb000051d9d6745d00096924d0194c9927a5
4
- data.tar.gz: c3768d8b17c550e001e2998e069f4c0417c895bf
3
+ metadata.gz: ee683454b13cb220e37262246b93ab743e790172
4
+ data.tar.gz: f387a3ff296f2ccb871c0b20da61fda5b2792055
5
5
  SHA512:
6
- metadata.gz: 4c1301f91f504bc9bf00de0e15d3fe6b6be9a2247c827411998c2d9d0f51d8b3d9126714225130efb21e1b8e82003af50f85f2190e71ce2c677c924120fe3513
7
- data.tar.gz: 983d1196cad96ba6f0df36cbccbade483cf1b9dd62cc7b82816fd1ec0176f1a0df4b64df22afdb3776816b1e2bd475a08241cfc5d2ba3904db62051e99149d32
6
+ metadata.gz: cc062f3fae19de17af17a78882fcf1c41d5d11f77ceadffb414f8cee299ae3524732dbc4bde8805b7a8f20549dd24f8d8c58e95dd0b158c5c618dab222f3191c
7
+ data.tar.gz: 86b8614b1b9a6cdde555b647a7ad34a11a806cc541ccc2922a301e1b3ba8726d3200e5bbb8329e1c8494ee47a25ab03ca2819285e226696be9ee1511960fcfd3
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Jinni [![Gem](https://img.shields.io/gem/v/jinni.svg?style=plastic)]()
1
+ # Jinni [![Gem](https://img.shields.io/gem/v/jinni.svg?style=plastic)](https://rubygems.org/gems/jinni)
2
2
 
3
- unconventional genetics, aggressively metaprogrammed
3
+ unconventional genetics, aggressively metaprogrammed. Pronounced like `genie`.
4
4
 
5
5
  ## Installation
6
6
 
@@ -17,9 +17,9 @@ Or install it yourself as:
17
17
  $ gem install jinni
18
18
 
19
19
 
20
- ## Usage
20
+ ## Quick-Start
21
21
 
22
- ### Start with some objects
22
+ ### Make a class
23
23
 
24
24
  class Fish < Jinni::Creature
25
25
  # attr_genetic name, min, max
@@ -29,29 +29,83 @@ Or install it yourself as:
29
29
 
30
30
  # must return a fixnum
31
31
  def fitness
32
- @pointiness + ( @speed_in_knots / @mass_in_kilos )
32
+ @pointiness + (@speed_in_knots / @mass_in_kilos )
33
33
  end
34
34
  end
35
35
 
36
- fishes = []
36
+ ### Have an offspring
37
+
38
+ bill = Fish.random_new
39
+ ted = Fish.random_new
40
+
41
+ child = bill << ted
42
+
43
+ ### Put some creatures in a genepool
44
+
45
+ fishes = Genepool.new
37
46
  10.times { fishes.push(Fish.random_new) } # `random_new` respects min and max
38
47
 
39
- ### Have an offspring
48
+ ### have some more offspring
40
49
 
41
50
  bill = fishes[0]
42
51
  ted = fishes[1]
43
52
 
44
53
  child = bill << ted
45
54
 
46
- ### ~~Start a whole new generation~~ lol not yet
47
-
48
- this here doesn't work:
55
+ ### Start a whole new generation
49
56
 
50
- generation = Jinni.generate_from fishes
57
+ generation = fishes.generate(10)
51
58
  fishes << generation
52
59
 
53
60
  ### todo: something mutations something, also make it faster
54
61
 
62
+ ## API
63
+
64
+ ### creatures : instance
65
+
66
+ Jinni adds the following public instance methods to your creatures:
67
+
68
+ #### fitness()
69
+ you should override this function with something sensible for your class. It returns `0.0` by default, but any float will do.
70
+ #### genes()
71
+ genes is a getter method that returns the genetic attributes available to your instance.
72
+ #### mutate(rate = 0.01)
73
+ mutate returns a slightly mutated object. Each bit in the original dna has a `rate` chance of flipping.
74
+ #### <<(object) / cross(object)
75
+ << is the basic method used to cross two objects. It splits the dna strands of the input objects into random chunks, and then they randomly swap.
76
+ #### to_binary()
77
+ to_binary returns the binary dna strand that represents the object.
78
+
79
+ ### creatures : class
80
+
81
+ Jinni adds the following public class methods to your creature class:
82
+
83
+ #### attr_genetic(:name, min, max)
84
+ use this method in your class to declare your genetic attributes.
85
+ #### random_new()
86
+ random_new initializes an object with attributes randomly assigned from within your declared range.
87
+ #### new_from_binary()
88
+ use this method to initialize an object from an arbitrary binary string.
89
+
90
+ ### numeric
91
+
92
+ Jinni also monkeypatches the following methods into Numeric:
93
+
94
+ #### to_binary()
95
+ utility method to convert a numeric into a binary string.
96
+ #### bits()
97
+ utility method to return the number of bits that the binary representation of the number requires
98
+
99
+ ### genepool
100
+
101
+ Jinni creates a class, Genepool which inherits from Array. Genepool has the following instance methods:
102
+
103
+ #### generate(n, mutationRate = 0.01, quality = :fitness)
104
+ use this method to create a new generation of `n` creatures based on a genepool. it uses weighted roulette wheel selection to simulate the effects of genetic fitness, then crosses the selected objects together.
105
+ #### roulette(n, quality = :fitness)
106
+ this utility method uses weighted roulette wheel selection to choose `n` objects from your gene pool influenced by fitness. It does not cross them.
107
+ #### average(quality = :fitness)
108
+ this method returns the mean of one quality through a collection of objects. It's very useful for watching your generations increase in fitness.
55
109
 
56
110
  ## Contributing
57
111
 
@@ -14,6 +14,12 @@ module Jinni
14
14
  @@genes
15
15
  end
16
16
 
17
+ def mutate(rate = 0.01)
18
+ binary = self.to_binary
19
+ newBinary = binary.chars.map { |bit| bit == "0" ? "1" : "0" if rand < rate }
20
+ return self.class.new_from_binary newBinary
21
+ end
22
+
17
23
  # this is Where It Happens
18
24
  # usage:
19
25
  # child = bill << ted
@@ -49,7 +55,6 @@ module Jinni
49
55
 
50
56
  # generic initialize from hash, called by the others
51
57
  def initialize(hash)
52
- puts hash
53
58
  hash.each_pair do |gene, value|
54
59
  instance_variable_set( "@#{gene}", value )
55
60
  end
@@ -76,12 +81,12 @@ module Jinni
76
81
  start = 0
77
82
  @@genes.each_pair do |gene, range|
78
83
  binary_chunk = binary[start..(start = start + range.bits - 1)]
84
+ break if binary_chunk.class != String
79
85
  offset = binary_chunk.to_i(2)
80
86
  value = self.class.send("#{gene}_min") + offset
81
87
  start += 1
82
88
  params[gene] = value
83
89
  end
84
- puts params
85
90
  params
86
91
  end
87
92
 
@@ -26,7 +26,7 @@ module Jinni
26
26
 
27
27
  # use like attr_accessor
28
28
  def attr_genetic( gene, min, max )
29
- range = max - min
29
+ range = max - min + 1
30
30
 
31
31
  @@genes[gene] = range
32
32
 
@@ -0,0 +1,45 @@
1
+ class Genepool < Array
2
+ def roulette(n, quality = :fitness)
3
+ scratch = self.clone
4
+
5
+ probabilities = scratch.map { |creature| creature.send(quality) }
6
+ selected = []
7
+
8
+ n.times do
9
+ r, inc = rand * probabilities.max, 0 # pick a random number and select the individual
10
+ # corresponding to that roulette-wheel area
11
+ scratch.each_index do |i|
12
+ if r < (inc += probabilities[i])
13
+ selected << scratch[i]
14
+ # make selection not pick sample twice
15
+ # scratch.delete_at i
16
+ # probabilities.delete_at i
17
+ break
18
+ end
19
+ end
20
+ end
21
+ return selected
22
+ end
23
+
24
+ def generate(n, mutationRate = 0.01, quality = :fitness)
25
+ scratch = self.clone
26
+
27
+ pool = scratch.roulette(n * 2, quality)
28
+
29
+ generation = Genepool.new
30
+
31
+ pool.each_slice(2) do |pair|
32
+ child = pair[0] << pair[1]
33
+ # child = child.mutate if mutationRate > 0
34
+ generation << child
35
+ end
36
+
37
+ return generation
38
+ end
39
+
40
+ def average(quality = :fitness)
41
+ self.map {|f| f.send(quality)}.inject{ |sum, n| sum + n }.to_f / self.length
42
+ end
43
+ end
44
+
45
+
data/lib/jinni/numeric.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  class Numeric
3
2
  def to_binary
4
3
  to_s(2)
data/lib/jinni/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jinni
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/jinni.rb CHANGED
@@ -1,26 +1,30 @@
1
1
  require 'pry'
2
2
 
3
- require 'jinni/version'
4
- require 'jinni/creature'
5
- require 'jinni/eigenclass'
6
- require 'jinni/numeric'
7
-
8
-
9
-
10
-
3
+ require_relative 'jinni/version'
4
+ require_relative 'jinni/creature'
5
+ require_relative 'jinni/eigenclass'
6
+ require_relative 'jinni/numeric'
7
+ require_relative 'jinni/genepool'
11
8
 
12
9
  class Fish < Jinni::Creature
13
- attr_genetic :hunger, -10, 10
14
- attr_genetic :speed, 1, 100
15
- attr_genetic :size, 90, 100
16
- attr_genetic :pointiness, 50, 100
17
-
18
- set_schema
10
+ # attr_genetic name, min, max
11
+ attr_genetic :pointiness, 0, 2
12
+ attr_genetic :mass_in_kilos, 10, 100
13
+ attr_genetic :speed_in_knots, 8, 12
14
+
15
+ # must return a fixnum
16
+ def fitness
17
+ @pointiness.to_f * (@speed_in_knots.to_f / @mass_in_kilos.to_f )
18
+ end
19
19
  end
20
20
 
21
- bill = Fish.random_new()
22
- ted = Fish.random_new()
21
+ fishes = Genepool.new
22
+ 100.times { fishes << Fish.random_new } # `random_new` respects min and max
23
23
 
24
- child = bill.cross(ted)
24
+ newGen = fishes.generate(1000)
25
25
 
26
26
  binding.pry
27
+
28
+ puts 'end'
29
+
30
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jinni
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Monks
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-04-17 00:00:00.000000000 Z
11
+ date: 2015-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,6 +56,7 @@ files:
56
56
  - lib/jinni.rb
57
57
  - lib/jinni/creature.rb
58
58
  - lib/jinni/eigenclass.rb
59
+ - lib/jinni/genepool.rb
59
60
  - lib/jinni/numeric.rb
60
61
  - lib/jinni/version.rb
61
62
  homepage: http://github.com/amonks/jinni