Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --if arg[#arg] == "-debug" then require("mobdebug").start() end
- --require("mobdebug").on()
- local class = require "middleclass"
- local CPU = class("CPUClass")
- math.randomseed(os.time())
- local file outputFile = io.open("programs.txt","w")
- local outstr = ""
- conf = {
- bits = 8, -- битность процессора
- ticksPerStep = 100, -- тиков на решение задачи
- errorRate = 9, -- 1 error per 10 generations
- maxPop = 50, -- макс. популяция
- cloneBest = 10, -- клонировать тех, кто входит в указанный топ
- initialEnergy = 100, -- начальная энергия
- takeFinalProgramStr = false --
- }
- conf.maxNumber = 2^conf.bits
- input = {} -- вход на каждый проц
- check = {} -- ожидаемый выход
- CPUlist = {} -- список всех процов
- bestList = {} -- сортированный список лучших
- function CPU:initialize()
- self.ID = getNewID()
- CPUlist[self.ID]=self
- self.energy = conf.initialEnergy
- self.a = 0
- self.b = 0
- self.RAM = {}
- self.pointer = 0
- self.flag = false
- self.overflow = false
- self.outR = 0
- self.inR = 0
- self.ioPointer = 1
- self.steps = 0
- self.output = {}
- self.finalProgramStr = ""
- end
- function getNewID()
- return #CPUlist + 1
- end
- function CPU:getString()
- programm = ""
- return "My ID:"..self.ID..", E:"..self.energy.."\n"
- end
- function CPU:kill()
- CPUlist[self.ID] = nil
- self = nil
- end
- function CPU:resetState()
- self.a = 0
- self.b = 0
- self.pointer = 0
- self.flag = false
- self.overflow = false
- self.steps = 0
- --self.finalProgramStr = ""
- end
- function CPU:run()
- while (self.steps <= conf.ticksPerStep) do
- value = self:fetch()
- if self.steps == 0 and conf.takeFinalProgramStr then
- self.finalProgramStr = self.finalProgramStr .. self:getOperationStr()
- end
- self:runOperation(value)
- if self.steps ~= 0 and conf.takeFinalProgramStr then
- self.finalProgramStr = self.finalProgramStr .. self:getOperationStr()
- end
- if self.markToKill then break end
- end
- self.steps = 0
- if self.markToKill then self:kill() end
- end
- function CPU:incPointer()
- self.pointer = self.pointer + 1
- if self.pointer >= conf.maxNumber then self.pointer = 0 end
- end
- function CPU:fetch()
- return self.RAM[self.pointer] or 0
- end
- function CPU:fixA()
- if tostring(self.a) == 'nan' or tostring(self.a) == 'nil' then self.a = 0
- elseif self.a >= conf.maxNumber then self.a = self.a % conf.maxNumber self.overflow = true
- elseif self.a < 0 then self.a = conf.maxNumber + self.a
- else self.a = math.floor(self.a) end
- end
- function CPU:fixB()
- if tostring(self.b) == 'nan' or tostring(self.b) == 'nil' then self.b = 0
- elseif self.b >= conf.maxNumber then self.b = self.b % conf.maxNumber
- elseif self.b < 0 then self.b = conf.maxNumber + self.b
- else self.b = math.floor(self.b) end
- end
- function CPU:getRAM(addr)
- return self.RAM[addr] or 0
- end
- function CPU:exception()
- self.markToKill = true
- end
- function CPU:runOperation(op)
- op = op % (#operations + 1)
- if op == 0 then self.steps = conf.ticksPerStep elseif
- op == 1 then self:incPointer(); addr = self:fetch(); self.a = self:getRAM(addr); elseif
- op == 2 then self:incPointer(); val = self:fetch(); self.a = val; elseif
- op == 3 then self:incPointer(); addr = self:fetch(); self.RAM[addr] = self.a; elseif
- op == 4 then self.a, self.b = self.b, self.a elseif
- op == 5 then self:incPointer(); addr = self:fetch(); self.a = self.a + self:getRAM(addr); self.overflow = false elseif
- op == 6 then self:incPointer(); val = self:fetch(); self.a = self.a + val; self.overflow = false elseif
- op == 7 then self:incPointer(); addr = self:fetch(); self.a = self.a - self:getRAM(addr); elseif
- op == 8 then self:incPointer(); val = self:fetch(); self.a = self.a - val; elseif
- op == 9 then self:incPointer(); addr = self:fetch(); self.a = self.a * self:getRAM(addr); self.overflow = false elseif
- op == 10 then self:incPointer(); val = self:fetch(); self.a = self.a * val; self.overflow = false elseif
- op == 11 then self:incPointer(); addr = self:fetch(); if (self:getRAM(addr)==0) then self:exception(); return end
- self.b =(self.a%self:getRAM(addr)); self.a=math.floor(self.a/self:getRAM(addr)); self.steps=self.steps+5 elseif
- op == 12 then self:incPointer(); val = self:fetch(); if (val==0) then self:exception(); return end
- self.b = (self.a % val); self.a = math.floor(self.a / val); self.steps = self.steps + 5 elseif
- op == 13 then self.a = self.a + 1; self.overflow = false elseif
- op == 14 then self.a = self.a - 1; self.overflow = false elseif
- op == 15 then self.flag = self.overflow elseif
- op == 16 then self.flag = self.a == 0 elseif
- op == 17 then self:incPointer(); addr = self:fetch(); self.flag = self.a > self:getRAM(addr) elseif
- op == 18 then self:incPointer(); val = self:fetch(); self.flag = self.a > val elseif
- op == 19 then self:incPointer(); addr = self:fetch(); self.flag = self.a < self:getRAM(addr) elseif
- op == 20 then self:incPointer(); val = self:fetch(); self.flag = self.a < val elseif
- op == 21 then self:incPointer(); addr = self:fetch(); self.flag = self.a == self:getRAM(addr) elseif
- op == 22 then self:incPointer(); val = self:fetch(); self.flag = self.a == val elseif
- op == 23 then self.flag = not self.flag elseif
- op == 24 then self:incPointer(); addr = self:fetch(); self.pointer = self:getRAM(addr) elseif
- op == 25 then self:incPointer(); addr = self:fetch(); self.pointer = addr elseif
- op == 26 then self.pointer = self.a elseif
- op == 27 then self:incPointer(); if (self.flag) then addr = self:fetch(); self.pointer = self:getRAM(addr) end elseif
- op == 28 then self:incPointer(); if (self.flag) then addr = self:fetch(); self.pointer = addr end elseif
- op == 29 then self:incPointer(); if (self.flag) then addr = self:fetch(); self.pointer = self.a end elseif
- op == 30 then self.output[self.ioPointer] = self.a; self.steps = conf.ticksPerStep elseif
- op == 31 then self.a = input[self.ioPointer]; end
- self:fixA()
- self.steps = self.steps + 1
- self:incPointer();
- end
- function CPU:validateOutput()
- self.energy = self.energy - self:fitnessTables(self.output, check) - self.steps--*2
- end
- function CPU:fitnessTables(t1,t2)
- mistake = 0
- for i = 1, #t2 do
- if tostring(t1[i]) == 'nil' then t1[i] = 0 end
- diff = t1[i] - t2[i]
- mistake = mistake + diff*diff
- end
- if mistake > 0 and mistake < 5 then conf.takeFinalProgramStr = true
- --printPopulation()
- print ("------------")
- print (table.tostring(self.output))
- print (self.finalProgramStr)
- end
- if mistake == 0 then
- print("CPU has found right answer!") print(table.unpack(t1)) print("RAM:") print(table.tostring(self.RAM)) os.exit() end
- return mistake*4
- end
- function CPU:printRAM()
- RAMstr = ""
- end
- function CPU:clone()
- temp = CPU:new()
- temp.RAM = tableCopy(self.RAM)
- isMutate = math.random(1,10)<=conf.errorRate
- if (isMutate) then temp:mutate() end
- end
- function CPU:mutate()
- where = math.random(0,conf.maxNumber)
- what = math.random(0,conf.maxNumber)
- self.RAM[where] = what
- end
- function table.val_to_str ( v )
- if "string" == type( v ) then
- v = string.gsub( v, "\n", "\\n" )
- if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
- return "'" .. v .. "'"
- end
- return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
- else
- return "table" == type( v ) and table.tostring( v ) or
- tostring( v )
- end
- end
- function table.key_to_str ( k )
- if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
- return k
- else
- return "[" .. table.val_to_str( k ) .. "]"
- end
- end
- function table.tostring( tbl )
- local result, done = {}, {}
- for k, v in ipairs( tbl ) do
- table.insert( result, table.val_to_str( v ) )
- done[ k ] = true
- end
- for k, v in pairs( tbl ) do
- if not done[ k ] then
- table.insert( result,
- table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
- end
- end
- return "{" .. table.concat( result, "," ) .. "}"
- end
- function tableCopy(t)
- local t2 = {}
- for k,v in pairs(t) do
- t2[k] = v
- end
- return t2
- end
- function CPU:getOperationStr()
- val = self:fetch()
- val = val % (#operations + 1)
- str = operations[val]
- if string.sub(str, -1)=="@" then
- p = self.pointer + 1
- if p>=conf.maxNumber then p = 0 end
- str = str..tostring(self.RAM[p]).." at ["..p.."]"
- elseif string.sub(str, -1)=="*" then
- p = self.pointer + 1
- if p>=conf.maxNumber then p = 0 end
- str = str..tostring(self.RAM[p])
- elseif string.sub(str, -1)=="." then
- str = str.." (a="..tostring(self.a)..")"
- elseif string.sub(str, -1)=="?" then
- str = str.." (f="..tostring(self.flag)..")"
- end
- return str.." | "
- end
- operations = {
- [0] = "end",
- [1] = "load@",
- [2] = "loadC*",
- [3] = "store*",
- [4] = "switch.",
- [5] = "add@",
- [6] = "addC*",
- [7] = "sub@",
- [8] = "subC*",
- [9] = "mult@",
- [10] = "multC*",
- [11] = "div@",
- [12] = "divC*",
- [13] = "inc.",
- [14] = "dec.",
- [15] = "overflow?",
- [16] = "a == 0?",
- [17] = "a > RAM?",
- [18] = "a > const?",
- [19] = "a < RAM?",
- [20] = "a < const?",
- [21] = "a == RAM?",
- [22] = "a == const?",
- [23] = "not?",
- [24] = "jump [RAM]@",
- [25] = "jump [const]*",
- [26] = "jump [a].",
- [27] = "jump to RAM if F@",
- [28] = "jump to const if F*",
- [29] = "jump to a if F.",
- [30] = "out.",
- [31] = "in"
- }
- function getBestList()
- --i = 1
- bestList = {}
- for _,c in pairs(CPUlist) do
- table.insert(bestList,#bestList+1,c)
- end
- if (#bestList>1) then table.sort(bestList,function(a,b) return a.energy > b.energy end) end -- сортируем по оценке
- end
- function runTest(testC)
- if testC == nil then
- for _,c in pairs(CPUlist) do
- for i = 1,#input do
- c:resetState()
- c.ioPointer = i -- смотрим на следующих инпут
- c:run() -- запускаем процессор
- end
- c:validateOutput() -- оцениваем его работу
- end else
- for i = 1,#input do
- testC:resetState()
- testC.ioPointer = i -- смотрим на следующих инпут
- testC:run() -- запускаем процессор
- end
- end
- end
- function printPopulation()
- for _,c in ipairs(bestList) do
- print("ID:".. c.ID..", E:".. c.energy) print(table.unpack(c.output))
- end
- print("-----------------------------")
- end
- function runEcosystem(t)
- getBestList()
- --printPopulation()
- last = #bestList
- for i = 1,last do
- if (#CPUlist<conf.maxPop and i<= conf.cloneBest) then bestList[i]:clone() end -- размножаем первых
- while(#CPUlist<conf.maxPop and bestList[1].energy>0) do bestList[1]:clone() end -- размножаем первого до максимального населения
- if (i>conf.cloneBest) then bestList[i]:kill() end -- умирают слабые
- if (i>1 and bestList[i].energy<=0) then bestList[i]:kill() end -- умирают слабые
- end
- end
- function runGeneration(times)
- for i=1,times do
- runTest() -- запуск программ
- runEcosystem(i) -- кормежка, размножение и смерть
- end
- print("END")
- print(table.unpack(bestList[1].output))
- print(table.unpack(bestList[1].RAM))
- print("Process is halted - max number of tries was reached")
- end
- function testCPU()
- testC = CPU:new()
- testC.RAM = {58,255,3,231,176,170,29,88,47,169,186,119,211,14,15,162,150,46,149,250,251,181,92,237,0,183,161,247,137,47,102,88,188,184,167,109,253,225,113,36,73,38,103,15,255,61,245,2,161,198,167,205,4,249,154,17,197,77,137,199,238,91,119,245,47,99,166,150,5,54,141,106,231,187,147,115,156,71,103,24,9,14,174,137,204,13,155,244,53,12,61,134,140,95,69,31,14,78,94,116,75,178,75,21,256,236,202,137,158,133,135,91,16,211,189,134,18,46,222,55,1,106,84,60,150,8,118,65,38,171,151,108,223,104,167,196,142,116,47,48,68,176,226,68,217,148,216,131,194,31,16,159,197,252,129,206,95,24,142,169,153,101,154,223,98,128,52,39,21,152,37,67,181,109,242,41,72,89,110,218,171,209,68,101,90,165,171,72,251,36,95,55,15,92,60,23,177,71,165,176,35,11,42,134,204,60,124,59,40,130,68,233,134,175,100,241,218,154,230,42,75,67,214,33,6,85,159,99,233,10,12,158,12,8,33,256,237,207,12,50,62,31,114,106,169,183,206,110,214,252,207,105,128,208,194,245,[0]=220}
- -- squares {58,255,3,231,176,170,29,88,47,169,186,119,211,14,15,162,150,46,149,250,251,181,92,237,0,183,161,247,137,47,102,88,188,184,167,109,253,225,113,36,73,38,103,15,255,61,245,2,161,198,167,205,4,249,154,17,197,77,137,199,238,91,119,245,47,99,166,150,5,54,141,106,231,187,147,115,156,71,103,24,9,14,174,137,204,13,155,244,53,12,61,134,140,95,69,31,14,78,94,116,75,178,75,21,256,236,202,137,158,133,135,91,16,211,189,134,18,46,222,55,1,106,84,60,150,8,118,65,38,171,151,108,223,104,167,196,142,116,47,48,68,176,226,68,217,148,216,131,194,31,16,159,197,252,129,206,95,24,142,169,153,101,154,223,98,128,52,39,21,152,37,67,181,109,242,41,72,89,110,218,171,209,68,101,90,165,171,72,251,36,95,55,15,92,60,23,177,71,165,176,35,11,42,134,204,60,124,59,40,130,68,233,134,175,100,241,218,154,230,42,75,67,214,33,6,85,159,99,233,10,12,158,12,8,33,256,237,207,12,50,62,31,114,106,169,183,206,110,214,252,207,105,128,208,194,245,[0]=220}
- -- fibb {129,231,80,155,68,203,147,220,50,95,50,228,170,17,80,177,233,61,205,111,86,236,15,175,95,89,49,87,145,229,8,80,125,228,199,10,82,74,37,70,158,174,221,10,11,101,40,255,210,19,187,184,76,232,98,127,196,190,62,27,157,73,46,77,176,72,185,130,79,125,218,210,69,244,64,131,36,227,225,153,223,3,201,51,89,242,173,167,160,150,76,141,0,230,178,236,127,246,69,212,98,202,60,170,186,29,73,194,233,143,218,148,153,13,94,76,69,254,106,182,96,158,185,118,159,146,76,152,154,150,137,123,62,12,40,229,123,186,211,173,218,103,202,48,64,140,62,155,179,13,232,1,69,167,53,95,178,116,124,102,7,231,98,27,135,42,21,61,191,174,39,117,67,196,141,62,47,89,74,104,184,210,229,243,67,152,125,112,102,218,114,205,20,97,117,120,182,203,86,1,138,33,157,198,217,185,253,135,95,55,25,66,251,184,64,40,103,193,170,248,250,3,117,170,10,222,25,14,252,104,248,237,177,193,172,13,192,44,254,135,191,126,109,83,171,188,176,18,126,166,180,169,160,1,107,211,[0]=92}
- runTest(testC)
- print("RAM:")
- print(table.unpack(testC.output))
- print(CPUlist[1].finalProgramStr)
- end
- function stopAll()
- print("----------------- END -----------------")
- print("Best ID:".. bestList[1].ID..", E:".. bestList[1].energy) print(table.unpack(bestList[1].output))
- print("RAM:")
- print(table.unpack(bestList[1].RAM))
- print()
- os.exit()
- end
- --------------------------------------------- BEGIN -------------------------------
- --input = {1,2,3,4,5,6,7,8,9,10}
- --check = {1,4,9,16,25,36,49,64,81,100} {1,1,2,3,5,8,13,21,34,55} {2,3,4,5,6,7,8,9,10,11}
- input = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
- check = {1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}
- CPU:new()
- CPUlist[1].RAM = {[0]=30,0}
- print("running...")
- runGeneration(1000000)
- --testCPU()
Add Comment
Please, Sign In to add comment