Spaces:
Sleeping
Sleeping
File size: 4,110 Bytes
48d465b 4fca5d2 48d465b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# Go through one mutation cycle
function iterate(member::PopMember, T::Float32, curmaxsize::Integer, frequencyComplexity::Array{Float32, 1})::PopMember
prev = member.tree
tree = prev
#TODO - reconsider this
if batching
beforeLoss = scoreFuncBatch(prev)
else
beforeLoss = member.score
end
mutationChoice = rand()
#More constants => more likely to do constant mutation
weightAdjustmentMutateConstant = min(8, countConstants(prev))/8.0
cur_weights = copy(mutationWeights) .* 1.0
cur_weights[1] *= weightAdjustmentMutateConstant
n = countNodes(prev)
depth = countDepth(prev)
# If equation too big, don't add new operators
if n >= curmaxsize || depth >= maxdepth
cur_weights[3] = 0.0
cur_weights[4] = 0.0
end
cur_weights /= sum(cur_weights)
cweights = cumsum(cur_weights)
successful_mutation = false
#TODO: Currently we dont take this \/ into account
is_success_always_possible = true
attempts = 0
max_attempts = 10
#############################################
# Mutations
#############################################
while (!successful_mutation) && attempts < max_attempts
tree = copyNode(prev)
successful_mutation = true
if mutationChoice < cweights[1]
tree = mutateConstant(tree, T)
is_success_always_possible = true
# Mutating a constant shouldn't invalidate an already-valid function
elseif mutationChoice < cweights[2]
tree = mutateOperator(tree)
is_success_always_possible = true
# Can always mutate to the same operator
elseif mutationChoice < cweights[3]
if rand() < 0.5
tree = appendRandomOp(tree)
else
tree = prependRandomOp(tree)
end
is_success_always_possible = false
# Can potentially have a situation without success
elseif mutationChoice < cweights[4]
tree = insertRandomOp(tree)
is_success_always_possible = false
elseif mutationChoice < cweights[5]
tree = deleteRandomOp(tree)
is_success_always_possible = true
elseif mutationChoice < cweights[6]
tree = simplifyTree(tree) # Sometimes we simplify tree
tree = combineOperators(tree) # See if repeated constants at outer levels
return PopMember(tree, beforeLoss)
is_success_always_possible = true
# Simplification shouldn't hurt complexity; unless some non-symmetric constraint
# to commutative operator...
elseif mutationChoice < cweights[7]
tree = genRandomTree(5) # Sometimes we generate a new tree completely tree
is_success_always_possible = true
else # no mutation applied
return PopMember(tree, beforeLoss)
end
# Check for illegal equations
for i=1:nbin
if successful_mutation && flagBinOperatorComplexity(tree, i)
successful_mutation = false
end
end
for i=1:nuna
if successful_mutation && flagUnaOperatorComplexity(tree, i)
successful_mutation = false
end
end
attempts += 1
end
#############################################
if !successful_mutation
return PopMember(copyNode(prev), beforeLoss)
end
if batching
afterLoss = scoreFuncBatch(tree)
else
afterLoss = scoreFunc(tree)
end
if annealing
delta = afterLoss - beforeLoss
probChange = exp(-delta/(T*alpha))
if useFrequency
oldSize = countNodes(prev)
newSize = countNodes(tree)
probChange *= frequencyComplexity[oldSize] / frequencyComplexity[newSize]
end
return_unaltered = (isnan(afterLoss) || probChange < rand())
if return_unaltered
return PopMember(copyNode(prev), beforeLoss)
end
end
return PopMember(tree, afterLoss)
end
|