pmeth 0.0.2 → 0.0.3
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 +4 -4
- data/lib/pmeth.rb +83 -88
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c10b7f39e2469c0ecfe087918e1a1bdf0fa9c200
|
4
|
+
data.tar.gz: 79da3d0a1648106e7ed3dd0bcbfb44a8964f58a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4211a9815d11ba335d958b0509902d8aa54a3aca195dff7cb242524da4d4b5fb19ba28697ef21cf4c88f29fb3e17493208b2d0536ab1f5bb012140b3e437d554
|
7
|
+
data.tar.gz: eb7d88b8b676d3ae595ef7b564ec80b8acb2461534cb4b6bf4a50abe6828c59411f446b9bc0a25f2d48e5c9e92e0c16065903f74e5f73dd57f2b41e4552df2c4
|
data/lib/pmeth.rb
CHANGED
@@ -1,124 +1,119 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
class PMeth
|
3
|
-
#
|
4
|
-
# Output: true/false
|
3
|
+
# Returns true if n is a prime number, false if not
|
5
4
|
def self.prime?(n)
|
6
5
|
for d in 2..(n - 1)
|
7
6
|
if (n % d) == 0
|
8
|
-
|
9
|
-
|
7
|
+
return false
|
8
|
+
end
|
10
9
|
end
|
11
10
|
true
|
12
11
|
end
|
13
12
|
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
# Returns a random integer that array can be divided by to get another integer (other than the array length itself)
|
14
|
+
def self.division(array)
|
15
|
+
x = 1.5 # x assigned a non-integer value to begin with
|
16
|
+
if prime?(array.length) # array with prime number of objects is not divisible by any integer other than 1 and itself
|
17
|
+
x = 1
|
18
|
+
else
|
19
|
+
until x > 0 && array.length/x.to_f == (array.length/x.to_f).to_i && Integer === x
|
20
|
+
x = rand(array.length)
|
21
|
+
end
|
20
22
|
end
|
21
23
|
return x
|
22
24
|
end
|
23
25
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
26
|
+
# Returns a new permutation that has had a randomly sized sub-section re-ordered by shuffle
|
27
|
+
def self.chunk_mutate(permutation)
|
28
|
+
if prime?(permutation.length) # if there are a prime number of objects in the permutation
|
29
|
+
ig = rand(permutation.length)-1 # choose a random object to ignore - to add back at its original index after mutation
|
30
|
+
ig_obj = permutation[ig] # save the object
|
31
|
+
permutation.delete_at(ig)
|
32
|
+
end
|
33
|
+
mutant = []
|
34
|
+
1.times do # this is to make use of the redo statement below
|
35
|
+
x = 0 # x is the randomly chosen size of chunks that permutation will be split into
|
36
|
+
until x > 2 # the chunk to be re-ordered must have at least 2 objects
|
37
|
+
x = division(permutation)
|
38
|
+
end
|
39
|
+
sliced = permutation.each_slice(x).to_a # permutation is sliced into chunks of size x
|
40
|
+
e = rand(sliced.length-1) # one of the chunks is chosen at random...
|
41
|
+
sliced[e] = sliced[e].shuffle # ... and the objects within are shuffled
|
42
|
+
new_perm = sliced.flatten
|
43
|
+
if new_perm == permutation # if the size of the chunk to be shuffled is small, there is a chance that it may not be differently ordered by shuffle...
|
44
|
+
redo # ... redo is used to ensure that a mutant permutation is created
|
45
|
+
end
|
46
|
+
if ig != nil
|
47
|
+
new_perm.insert(ig, ig_obj)
|
48
|
+
end
|
49
|
+
mutant << new_perm # the new permutation has been added to an array for access outside the 1.times loop
|
50
|
+
end
|
51
|
+
return mutant[0] # new_perm
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns a new permutation where two of the objects have swapped positions (indices)
|
55
|
+
def self.swap_mutate(permutation)
|
56
|
+
a = b = x = y = 0
|
57
|
+
until a != b
|
58
|
+
x = rand(permutation.length-1) # randomly choose two indices x and y...
|
59
|
+
y = rand(permutation.length-1)
|
60
|
+
a = permutation[x] # ... and call the objects at these indices a and b
|
61
|
+
b = permutation[y]
|
62
|
+
end
|
63
|
+
mutant = permutation.dup # create a new permutation...
|
64
|
+
mutant[x] = b # ... with object b at index x...
|
65
|
+
mutant[y] = a # ... and object a at index y
|
66
|
+
return mutant
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns a permutation whose objects are ordered partly like a_parent permutation, and partly like b_parent permutation
|
27
70
|
def self.recombine(a_parent, b_parent)
|
28
|
-
|
29
|
-
1.times do #
|
30
|
-
x = division(a_parent)
|
31
|
-
if
|
32
|
-
|
33
|
-
|
34
|
-
ig
|
35
|
-
|
36
|
-
|
37
|
-
a_parent_reduced.delete_at(ig)
|
38
|
-
b_parent_reduced.delete_at(ig)
|
39
|
-
x = division(a_parent_reduced)
|
40
|
-
a_parent_sliced = a_parent_reduced.each_slice(x).to_a
|
71
|
+
child_permutation = []
|
72
|
+
1.times do # this is to make use of the redo statement below
|
73
|
+
x = division(a_parent) # the randomly chosen size of chunks that permutations will be split into
|
74
|
+
if prime?(a_parent.length) # to compensate for permutations with a prime number of objects:
|
75
|
+
ig = rand(a_parent.length)-1 # choose a random object to ignore - to add back at its original index after mutation
|
76
|
+
a_parent_reduced, b_parent_reduced = a_parent.dup, b_parent.dup # then create duplicates of the parent arrays...
|
77
|
+
a_parent_reduced.delete_at(ig); b_parent_reduced.delete_at(ig) # .. and remove the ignored object from these duplicates
|
78
|
+
x = division(a_parent_reduced) # choose a new chunk size for reduced parent permutations, that no longer have a prime number of objects
|
79
|
+
a_parent_sliced = a_parent_reduced.each_slice(x).to_a # slice the reduced parent permutations into chunks of size x
|
41
80
|
b_parent_sliced = b_parent_reduced.each_slice(x).to_a
|
42
81
|
else
|
43
|
-
a_parent_sliced = a_parent.each_slice(x).to_a
|
82
|
+
a_parent_sliced = a_parent.each_slice(x).to_a # if permutation lengths are non-prime, just slice the parent permutations into chunks of size x
|
44
83
|
b_parent_sliced = b_parent.each_slice(x).to_a
|
45
84
|
end
|
46
|
-
chosen = rand(b_parent_sliced.length)-1 # choose
|
47
|
-
child = a_parent_sliced.flatten.dup
|
48
|
-
|
49
|
-
|
50
|
-
a_parent_sliced[chosen].each do |
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
pos_array << pos
|
55
|
-
y+=1
|
85
|
+
chosen = rand(b_parent_sliced.length)-1 # choose a chunk to have b_parent ordered objects in child permutation
|
86
|
+
child = a_parent_sliced.flatten.dup # un-modified child permutation to accept chunk from b_parent (and possibly ignored object)
|
87
|
+
a_indices = []
|
88
|
+
### place each object in chosen a_parent chunk into the index it's corresponding object (from b_parent) occupies in a_parent ###
|
89
|
+
a_parent_sliced[chosen].each do |i|
|
90
|
+
index = a_parent_sliced[chosen].index(i) # the index of each object in the chosen a_parent chunk...
|
91
|
+
b_object = b_parent_sliced[chosen][index] # ... the object at that index in the chosen b_parent chunk...
|
92
|
+
a_indices << a_parent_sliced.flatten.index(b_object) # ... the index of that object (from b_parent chunk) (INDEX RHO) in a_parent is added to an array
|
56
93
|
end
|
57
|
-
if
|
94
|
+
if a_indices.include?(nil) # TODO unsure why: a_indices sometimes includes nil
|
58
95
|
redo
|
59
96
|
else
|
60
97
|
y = 0
|
61
|
-
|
62
|
-
unless b_parent_sliced[chosen].include?(a_parent_sliced[chosen][y])
|
63
|
-
child[
|
64
|
-
|
98
|
+
a_indices.each do |ai|
|
99
|
+
unless b_parent_sliced[chosen].include?(a_parent_sliced[chosen][y]) # unless the chosen chunk from b_parent includes objects from the chosen a_parent chunk...
|
100
|
+
child[ai] = a_parent_sliced[chosen][y] # ... the object from the chosen chunk in parent_a is added to INDEX RHO in child
|
101
|
+
chosen_index = a_parent_sliced.flatten.index(a_parent_sliced[chosen][y]) # index of object from a_parent's chosen chunk in a_parent
|
102
|
+
child[chosen_index] = b_parent_sliced[chosen][y] # swapping the indices of objects in chunks from parents, to give their indices in child
|
65
103
|
end
|
66
104
|
y+=1
|
67
105
|
end
|
68
106
|
end
|
69
|
-
if ig != nil
|
107
|
+
if ig != nil # if the permutations are a prime number in length, we now add the ignored object from earlier into child
|
70
108
|
if b_parent_sliced[chosen].include?(b_parent[ig]) # add the ignored object from b_parent if it's in the chosen chunk...
|
71
109
|
child.insert(ig, b_parent[ig])
|
72
110
|
else
|
73
111
|
child.insert(ig, a_parent[ig]) # ...otherwise add the ignored object from a_parent
|
74
112
|
end
|
75
113
|
end
|
76
|
-
|
77
|
-
redo
|
78
|
-
end
|
79
|
-
kid << child # so we can access this outside the loop
|
80
|
-
end
|
81
|
-
return kid[0]
|
82
|
-
end
|
83
|
-
|
84
|
-
# Input: A permutation array of unique objects
|
85
|
-
# Output: A slightly different permutation array of the same unique objects
|
86
|
-
def self.mutate(fasta)
|
87
|
-
mutant = []
|
88
|
-
1.times do
|
89
|
-
x = 0
|
90
|
-
until x > 2
|
91
|
-
x = division(fasta)
|
92
|
-
end
|
93
|
-
sliced = fasta.each_slice(x).to_a
|
94
|
-
e = rand(sliced.length-1).to_i
|
95
|
-
sliced[e] = sliced[e].shuffle
|
96
|
-
if sliced.flatten == fasta
|
97
|
-
redo
|
98
|
-
end
|
99
|
-
mutant << sliced.flatten
|
114
|
+
child_permutation << child # so we can access this outside the loop
|
100
115
|
end
|
101
|
-
return
|
116
|
+
return child_permutation[0]
|
102
117
|
end
|
103
118
|
|
104
|
-
# Input: A permutation array of unique objects
|
105
|
-
# Output: A slightly different permutation array of the same unique objects
|
106
|
-
def self.mini_mutate(fasta)
|
107
|
-
a = b = 0
|
108
|
-
until a != b
|
109
|
-
a = fasta[rand(fasta.length-1)]
|
110
|
-
b = fasta[rand(fasta.length-1)]
|
111
|
-
end
|
112
|
-
mutant = []
|
113
|
-
fasta.each do |i|
|
114
|
-
if i == a
|
115
|
-
mutant << b
|
116
|
-
elsif i == b
|
117
|
-
mutant << a
|
118
|
-
else
|
119
|
-
mutant << i
|
120
|
-
end
|
121
|
-
end
|
122
|
-
return mutant
|
123
|
-
end
|
124
119
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pmeth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edward Chalstrey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: "Reproduction methods for genetic (and other iterative improvement) algorithms,
|
14
14
|
being used to solve permutation problems, \n where permutations are arrays of unique
|