jinni 0.1.1 → 0.3.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 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