summaryrefslogtreecommitdiff
path: root/example.lua
blob: fd61f06c2960d0ffc1e8cb3a872df8f83e6b8ed4 (plain)
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
local Grammar = require 'grammar'
local GA = require 'ga'


local production = {}
production["<start>"]={{'<expr>'}}
production["<expr>"]={ {'<var>'}, {'(', '<expr>', '<op>', '<expr>', ')'} }
production["<op>"]={ {'+'}, {'-'}, {'*'}, {'/'} }
production["<var>"]={ {'x'} }


local grammar = Grammar.createGrammar(production)


math.randomseed(0)


function randomGenome()
  local len = math.ceil(math.random() * 256)
  local genome = {}
  for i=1,len do
    table.insert(genome, math.floor(256 * math.random()))
  end
  return genome
end


function randomPop()
  local pop = {}
  for n=1,1000 do
    table.insert(pop, randomGenome())
  end
  return pop
end

function evaluate(genome)
  local s = 'return function(x) return ' .. grammar:expand(genome) .. ' end'
  local f = assert(loadstring(s))()
  local target = function(x) return (x*x*x*x) + (x*x*x) + (x*x) + (x) end
  local cost = 0
  for n=0,100 do
    x = (n-50)/50
    ok, y = pcall(f, x)
    if (not ok) or (y ~= y) then
      cost = cost + 100
    else
      cost = cost + math.abs(y - target(x))
    end
  end
  return -((0.0001*#s) + cost)
end

local ga = GA.createGA(randomPop(), {
  evaluate=evaluate,
  crossover=function(a, b)
    local crossoverPoint = math.ceil(#a * math.random())
    local new = {}
    for i=1,#b do
      table.insert(new, (i>=crossoverPoint and b[i]) or a[i])
    end
    return new
  end,
  mutate=function(a)
    local new = {}
    for i,v in ipairs(a) do new[i] = v end
    local mutationPoint = math.ceil(#a * math.random())
    new[mutationPoint] = math.floor(256 * math.random())
    return new
  end,
})


for n=1,100 do
  print(ga:step())
  print(grammar:expand(ga.population[ga.bestMember]))
end

-- for k,v in ipairs(ga.population) do
--   print(k, '(', v[1], v[2], v[3], ')', evaluate(v))
-- end