Permalink
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018
Feb 6, 2018

Newer

100644
177 lines (155 sloc)
6.05 KB

2

#=

3

Parents <— {randomly generated population}

4

While not (termination criterion)

5

Calculate the fitness of each parent in the population

6

Children <- 0

7

While | Children | < | Parents |

8

Use fitnesses to probabilistically select a pair of parents for mating

9

Mate the parents to create children c\ and c<i

10

Children <— Children U {ci,C2}

11

Loop

12

Randomly mutate some of the children

13

Parents <— Children

14

Next generation

15

16

Use continuous GA, not binary

17

18

include array of independent variables along with associated range

19

20

=#

21

22

function initialize_population(populationSize::Int, chromosomeSize::Int, bounds::Array{Tuple{Float64, Float64},1})

23

"""

25

Values will be from lb to ub (lower to upper bound)

26

"""

27

28

# Check to see if we dont have enough bounds or have too many

29

if length(bounds) != chromosomeSize

30

println("Length of bounds ($(length(bounds))) not equal to specified chromosome size ($chromosomeSize)")

31

exit()

32

end

33

34

# Init population

36

37

# Foreach member in population

38

for i = 1:populationSize

39

# Init the member

40

row = []

41

# Create member elements based on bounds

42

for bound in bounds

43

push!(row, rand(bound[1]:0.10:bound[2]))

44

end

45

# Add another element to the end to keep score

46

push!(row, 1.0)

47

48

# hcat row, append to 2D population matrix

50

end

51

return population

52

53

end

54

55

function score_sort_population(population::Array{Array{Float64}}, fitness_function::Function)

56

"""

57

Args

58

population: The population to score. Must be 2D array of Float64 elements

59

fitness_function: Function to score the population

60

Must be able to take array as argument

61

For example f(x,y) should be f(A) where A[1]=x, A[2]=y

62

Returns scored population. Score is the last element of each chromosome (row)

63

in population

64

"""

65

# Enumerate through population, set last element of each chromosome to score

66

for (index,member) in enumerate(population)

67

population[index][end] = fitness_function(member)

68

end

69

sort!(population, by = x -> x[end])

70

return population

71

end

72

73

function create_next_generation(population::Array{Array{Float64}}, recombRate::Float64)

74

"""

75

Creates children given a population and recombination rate

76

Uses an elite selection of 0.10 (rounded up)

77

Creates random chance

78

TODO: Implement ranking

79

"""

80

81

popSize = length(population)

82

memberSize = length(population[1])

83

# Init children array

84

children = Array{Array{Float64}}(0)

85

# Elite selection

86

for i in 1:Int(ceil(popSize*0.10))

87

push!(children, population[i])

88

end

89

90

# Generate rest of population

91

while length(children) < popSize

92

# Two random children

93

choices = sample(1:popSize, 2, replace=false)

94

# Check for crossover

95

if rand() < recombRate

96

# Choose xover point

97

# Use -2 since last one is score, and last actual element cant be crossedover since that means there is none

98

xover = rand(1:memberSize-2)

99

child1 = cat(1,population[choices[1]][1:xover],population[choices[2]][xover+1:end])

100

child2 = cat(1,population[choices[2]][1:xover],population[choices[1]][xover+1:end])

101

else

102

# Else no crossover, just copy

103

child1 = population[choices[1]]

104

child2 = population[choices[2]]

105

end

106

# Push child 1 and 2 to children array

107

push!(children, child1, child2)

108

end

109

110

# We might have one extra due to rounding in the elite selection, let's check

111

if length(children) != popSize

112

pop!(children)

113

end

114

return children

115

end

116

117

function mutate(population::Array{Array{Float64}}, mutateRate::Float64, bounds::Array{Tuple{Float64, Float64},1})

118

"""

119

Iterates through each chromosome and mutates if needed

120

"""

121

122

for member in population

123

for i = 1:length(member)-1

124

if rand() < mutateRate

125

member[i] = rand(bounds[i][1]:0.10:bounds[i][2])

126

end

127

end

128

end

129

130

return population

131

end

132

133

function GA(populationSize::Int, chromosomeSize::Int, fitness_function::Function, bounds::Array{Tuple{Float64, Float64},1})

134

"""

135

Args

136

populationSize: Total number of chromosomes

137

chromosomeSize: How long each chromosome should be (variables in fitness function)

138

fitness_function: Function to determine fitness of each solution

139

Should take an array as an arg

140

Example: f(x,y,z) = x+y+z

141

should be f(X) = X[1]+X[2]+X[3]

142

in order to allow GA to take in any function with any

143

amount of args to the fitness function

144

bounds: 1D array of tuples, each tuple is the (lower, upper) bounds

145

for each variable. Both lower and upper need to be Float64 types

146

Length should match chromosomeSize

147

e.g: [(1.0,2.0), (3.5,4.5)]

148

"""

149

150

# Set recombination and mutation rate, lower and upper bound

151

recombRate = 0.7

152

mutateRate = 0.05

154

# First initialize the population

155

population = initialize_population(populationSize, chromosomeSize, bounds)

159

i = 0

160

while i < maxIterations

161

# Score and sort the population

162

population = score_sort_population(population, fitness_function)

163

push!(bestScores,population[1][end])

164

population = create_next_generation(population, recombRate)

165

population = mutate(population, mutateRate, bounds)

166

i += 1

167

end

170

end

171

172

function ackley(X)

173

return e - 20*exp(-0.2*sqrt((X[1]^2 + X[2]^2)/2)) - exp((cos(2*pi*X[1]) + cos(2*pi*X[2]))/2)

174

end

176

bounds = [(-2.0,2.0), (-2.0,2.0)]

177

GA(25,2,ackley,bounds)