Icon representing a recipe

Recipe: Rav3n_pl GAB BiS v2.1.1

created by Rav3n_pl

Profile


Name
Rav3n_pl GAB BiS v2.1.1
ID
41981
Shared with
Public
Parent
Rav3n_pl GAB BiS Flu loss
Children
Created on
March 26, 2020 at 00:37 AM UTC
Updated on
March 26, 2020 at 00:37 AM UTC
Description

Bands! Bands in space! GAB BiS v2. Now it have options dialog!

Best for


Code


--[[ Bands! Bands in space! GAB - Genetic Algorythm on Bands by Rav3n_pl based on CartoonVillan and Crashguard303 scripts Lua V2 Definitions: band: random band to space from random segment critter: set of bands herd: set of critters 1. - randomize needed bands - randomly assignig them to criters 2. - score each critter 3. - keep critters scoring above score - breed best critters - breed bastards (best one + random one) - forget about rest of critter - randomize new critters to fill herd ]] -- -- options: energy = false -- set true to seek energy in exploration puzzles; false works on all puzzles pullCI = 0.9 -- Clash Impotrance during pull shakeCI = 0.21 -- CI when shake on qstab or mutate once maxCI = 1 -- maximum CI used by script fastQstab = true -- only 1s1w after pull if true fuzeThresh = 1 -- run fuze if we are close to best score (negative=new best score) qstabThresh = 1 -- run qstab if score drops more than... wiggle only in other case onlyMutable = true -- if true use ONLY all mutable aas, no matter of always use mutateOnce = true -- if true use mutate(1) instead of shake in qstab mutateAlwas = false -- if true use muatate(1) instead of all shakes herd = { -- herd options breedBest = 5, -- breed best critters, all combinations => 6 kids form 4 critters, 3 form 3, 1 form 2, 9 form 5 etc keepBest = 3, -- save up to 3 best scoring critters, rest are forgotten breedBastards = 8, -- number of best will have one random bastard newRandom = 10, -- adding new random ones each generation maxGen = 100, -- maximum generations shuffle = true, -- set true to run critters in random order renew = 4 -- create totally fresh herd after that many gens w/o improvement } critter = { -- critter options minBands = 3, -- minimum bands maxBands = 7, -- maximum bands keepScore = 0, -- survive to next gen only if score higher than breedScore = -20, -- will breed kids only if score higher. Basttards always breed maxLoss = 30 -- maximum loss by critter. set 0 to disable } bands = { -- bands options minStr = 0.3, -- minimum band str maxStr = 1.1, -- maximum band str maxUp = 12.1 -- maximum band length } DoNotUse = {} AlwaysUse = {} UseSegments = {} -- use ONLY this segments -- bands by secondary structure use = { Sheet = true, -- set false to not band sheets Helix = true, -- set false to not band helices Loop = true -- set false to not band loops } -- end of options -- constants segCnt = structure.GetCount() p = print function CI(c) if c > maxCI then c = maxCI end behavior.SetClashImportance(c) end function round(x) -- cut all afer 3-rd place return x - x % 0.001 end function down(x) return x - x % 1 end function Score() -- return score, exploration too if energy == true then return current.GetEnergyScore() else return current.GetScore() end end -- local seed=recipe.GetRandomSeed() --NOT WORKING!!! -- calculate REALLY good seed seed = os.time() / math.abs(Score()) seed = seed % 0.001 seed = 1 / seed while seed < 10000000 do seed = seed * 1000 end seed = seed - seed % 1 p('Seed is: ' .. seed) math.randomseed(seed) -- REALLY good seed made by rav3n_pl :P function Wiggle(how, iters, minppi) if how == nil then how = 'wa' end if iters == nil then iters = 3 end if minppi == nil then minppi = 0.3 end if iters > 0 then iters = iters - 1 local sp = Score() if how == 's' then if mutateAlwas == true then structure.MutateSidechainsSelected(1) else structure.ShakeSidechainsSelected(1) end elseif how == 'wb' then structure.WiggleAll(2, true, false) elseif how == 'ws' then structure.WiggleAll(2, false, true) elseif how == 'wa' then structure.WiggleAll(2, true, true) end local ep = Score() local ig = ep - sp if how ~= 's' then if ig > minppi then return Wiggle(how, iters, minppi) end -- tail call end end end function SaveBest() local g = Score() - bestScore if g > 0 then if g > 0.01 then p('Gained another ' .. round(g) .. ' pts.') end bestScore = Score() save.Quicksave(3) end end function SaveRB() local s if energy then s = recentbest.GetEnergyScore() else s = recentbest.GetScore() end if (s > bestScore) then save.Quicksave(4) recentbest.Restore() SaveBest() save.Quickload(4) end end function Qstab() selection.SelectAll() CI(shakeCI) if mutateOnce == true then structure.MutateSidechainsSelected(1) else Wiggle('s', 1) end if fastQstab == false then CI(0.4) Wiggle('wa', 1) CI(1) Wiggle('s', 1) end CI(1) Wiggle() end function FuzeEnd() CI(1) Wiggle('wa', 1) Wiggle('s', 1) Wiggle() srb() end function Fuze1(ci1, ci2) CI(ci1) Wiggle('s', 1) CI(ci2) Wiggle('wa', 1) end function Fuze2(ci1, ci2) CI(ci1) Wiggle('wa', 1) CI(1) Wiggle('wa', 1) CI(ci2) Wiggle('wa', 1) end function srb() recentbest.Restore() SaveBest() end function Fuze() p('Fuzing...') selection.SelectAll() recentbest.Save() Fuze1(0.3, 0.6) FuzeEnd() Fuze2(0.3, 1) srb() Fuze1(0.05, 1) srb() Fuze2(0.7, 0.5) FuzeEnd() Fuze1(0.07, 1) srb() end function random(n1, n2) -- random function returns int or float depends on input vars if n1 == nil then return math.random() else if n2 == nil then if n1 % 1 == 0 then return math.random(n1) -- integer else return math.random() * n1 -- float end else if n1 % 1 == 0 and n2 % 1 == 0 then return math.random(n1, n2) -- integer between else return math.random() * (n2 - n1) + n1 -- float between end end end end function FillHerd() -- fill up herd local n = #critters if n > 0 then -- fill up n = herd.newRandom else -- fresh herd n = herd.breedBest + herd.keepBest + herd.breedBastards end p('Randomizing ' .. n .. ' new critters...') for _ = 1, n do AddCritter() end end function AddCritter() -- vreate new random critter local c = {} critterID = critterID + 1 c.no = critterID c.name = c.no .. '-rnd' c.bands = {} local r = random(critter.minBands, critter.maxBands) for _ = 1, r do c.bands[#c.bands + 1] = AddBand() end critters[#critters + 1] = c p(c.name .. ' bands: ' .. #c.bands) end function AddBand() -- create one random band local cnt = 0 local b while true do -- try till die cnt = cnt + 1 local s1 = random(segCnt) if onlyMutable == true or #UseSegments > 0 then s1 = UseSegments[random(#UseSegments)] end if #UseSegments > 0 or CanBeUsed(s1) then local str = random(bands.minStr, bands.maxStr) local len = random(1, bands.maxUp) local theta = math.acos(math.random()) local phi = 2 * math.pi * math.random() local segmentXAxis local segmentYAxis while true do -- all 3 must be different segmentXAxis = random(segCnt) segmentYAxis = random(segCnt) if segmentXAxis ~= s1 and segmentYAxis ~= s1 and segmentXAxis ~= segmentYAxis then break end end -- {segmentOrigin, segmentXAxis, segmentYAxis, rho, theta, phi} b = {s1, segmentXAxis, segmentYAxis, len, theta, phi, str} break end if cnt > 100 then p('Sorry! Cant create band! Breaking script!') BreakScript() -- there is no such function, so it crashes script end end return b end function ssCheck(ss) if (use.Sheet and ss == 'E') or (use.Helix and ss == 'H') or (use.Loop and ss == 'L') then return true else return false end end function CanBeUsed(sg1) -- checking segment at end of band local ok = true if #DoNotUse > 0 then -- can not hook in that area for i = 1, #DoNotUse do local r = DoNotUse[i] for x = r[1], r[2] do if x == sg1 then ok = false break end end if (not ok) then return false end end end if #AlwaysUse > 0 then -- end have to be there ok = false for i = 1, #AlwaysUse do local r = AlwaysUse[i] for x = r[1], r[2] do if x == sg1 then ok = true break end end if ok then break end end end if ok then -- check structure ok = ssCheck(structure.GetSecondaryStructure(sg1)) end return ok end function ScoreHerd() -- score all critters from herd save.Quickload(3) p('Scoring ' .. #critters .. ' critters...') save.Quicksave(5) local herdScore = Score() for i = 1, #critters do band.DeleteAll() local crt = critters[i] -- critter local s = Score() -- start score local bnds = crt.bands for b = 1, #bnds do local bnd = bnds[b] local atom = 5 local sn = bnd[1] if sn == segCnt then atom = 6 end -- bug in last segment if structure.GetAminoAcid(sn) == 'g' then atom = 0 end -- glycyne band.Add(sn, bnd[2], bnd[3], bnd[4], bnd[5], bnd[6], atom) local bc = band.GetCount() band.SetStrength(bc, bnd[7]) end selection.SelectAll() CI(pullCI) recentbest.Save() Wiggle('wb', 1) band.DeleteAll() CI(1) if s - Score() > qstabThresh then Qstab() else Wiggle() end SaveRB() if Score() - bestScore > fuzeThresh then Fuze() end crt.score = Score() - s p('Critter ' .. crt.name .. ' : ' .. round(crt.score)) if critter.maxLoss > 0 then if Score() > herdScore - critter.maxLoss then save.Quicksave(5) herdScore = Score() else save.Quickload(5) end else save.Quickload(3) end end save.Quickload(3) if band.GetCount() > 0 then -- clean bands from best solution (if any) band.DeleteAll() save.Quicksave(3) end end function BreedCritters(mom, dad, t) -- breed 2 critters. bands are taken randomly local kid = {} critterID = critterID + 1 kid.no = critterID kid.name = kid.no .. '-' .. t .. mom.no .. '/' .. dad.no kid.bands = {} local mb = #mom.bands local db = #dad.bands if mb > db then mb, db = db, mb end -- kid have bands count between mom and dad bands local bn = random(mb, db) for _ = 1, bn, 2 do kid.bands[#kid.bands + 1] = mom.bands[random(#mom.bands)] kid.bands[#kid.bands + 1] = dad.bands[random(#dad.bands)] end p(kid.name .. ' bands: ' .. #kid.bands) return kid end function KeepGood() -- copy best scoring critters form last gen if score above local newHerd = {} for i = 1, herd.keepBest do if critters[i].score > critter.keepScore then newHerd[#newHerd + 1] = critters[i] end end return newHerd end function SortCritters() -- bubble sort for i = 1, #critters do for j = i + 1, #critters do if critters[i].score < critters[j].score then critters[i], critters[j] = critters[j], critters[i] -- love lua :) end end end end function BreedHerd() p('Breeding...') SortCritters() local newHerd = KeepGood() for i = 1, herd.breedBest do local mom = critters[i] if mom.score > critter.breedScore or i < 2 then -- breed only good ones, 1st is always breed anyway for j = i + 1, herd.breedBest do local dad = critters[j] newHerd[#newHerd + 1] = BreedCritters(mom, dad, 'kid-') newHerd[#newHerd + 1] = BreedCritters(dad, mom, 'kid-') end end end for i = 1, herd.breedBastards do -- they will always appear ;] local mom = critters[i] local j = random(herd.breedBastards + 1, #critters) local dad = critters[j] newHerd[#newHerd + 1] = BreedCritters(mom, dad, 'bas-') newHerd[#newHerd + 1] = BreedCritters(dad, mom, 'bas-') end critters = newHerd FillHerd() end function ShuffleHerd() if herd.shuffle == true then for i = 1, #critters do local r = random(#critters) if r ~= i then critters[i], critters[r] = critters[r], critters[i] end end end end --define global variables critterID = 0 critters = {} gen = 0 bestScore = Score() function GAB() if onlyMutable == true then for i = 1, segCnt do if structure.IsMutable(i) then UseSegments[#UseSegments + 1] = i end end end bestScore = Score() critterID = 0 gen = 0 local ss = Score() save.Quicksave(3) recentbest.Save() p('Rav3n_pl Bands! Bands in space! GAB BiS') p('Start score: ' .. round(ss)) critters = {} FillHerd() local badGen = 0 while true do -- this is (almost) endless script ;] local genScore = Score() gen = gen + 1 p() p('Generation: ' .. gen .. ', score: ' .. round(Score()) .. ', gain: ' .. round(Score() - ss)) ShuffleHerd() ScoreHerd() save.Quickload(3) if gen == herd.maxGen then break end -- end of script if genScore >= Score() then badGen = badGen + 1 else badGen = 0 end if badGen >= herd.renew then p('Creating fresh random herd...') critters = {} FillHerd() badGen = 0 else BreedHerd() end end p('Final score: ' .. round(Score()) .. ' Total gain: ' .. round(Score() - ss)) end function dialogOptions() local mut = false for i = 1, segCnt do if structure.IsMutable(i) then mut = true break end end if not mut then onlyMutable = false mutateOnce = false end opt = dialog.CreateDialog('Main Options') opt.lbl1 = dialog.AddLabel('GAB BiS main options:') opt.gen = dialog.AddTextbox('Generations:', herd.maxGen) opt.pull = dialog.AddSlider('Pulling CI', pullCI, 0.05, 1, 2) -- desctip, default, min, max, precision opt.shak = dialog.AddSlider('Shake CI', shakeCI, 0.01, 1, 2) opt.maxci = dialog.AddSlider('Maximum CI', maxCI, 0.05, 1, 2) opt.qstab = dialog.AddCheckbox('FastQstab', fastQstab) opt.energy = dialog.AddCheckbox('Seek energy', energy) opt.mutonly = dialog.AddCheckbox('Only mutable', onlyMutable) opt.mutonce = dialog.AddCheckbox('Mutate once', mutateOnce) opt.mutalways = dialog.AddCheckbox('Mutate alwyas', mutateAlwas) opt.fuzeth = dialog.AddTextbox('Fuze threshold: ', fuzeThresh) opt.qsth = dialog.AddTextbox('Qstab threshold: ', qstabThresh) opt.run = dialog.AddButton('Start', 1) opt.more = dialog.AddButton('More', 2) opt.cancel = dialog.AddButton('Cancel (???)', 0) res = dialog.Show(opt) if res > 0 then energy = opt.energy.value pullCI = opt.pull.value shakeCI = opt.shak.value maxCI = opt.maxci.value fastQstab = opt.qstab.value fuzeThresh = tonumber(opt.fuzeth.value) qstabThresh = tonumber(opt.qsth.value) onlyMutable = opt.mutonly.value mutateOnce = opt.mutonce.value mutateAlwas = opt.mutalways.value herd.maxgen = tonumber(opt.gen.value) if res == 2 then opt = dialog.CreateDialog('More Options') opt.lbl1 = dialog.AddLabel('Herd:') opt.brbest = dialog.AddSlider('Breed best', herd.breedBest, 1, 20, 0) opt.kbest = dialog.AddSlider('Keep best', herd.keepBest, 1, 20, 0) opt.bas = dialog.AddSlider('Breed bastards', herd.breedBastards, 1, 20, 0) opt.rnd = dialog.AddSlider('New random', herd.newRandom, 1, 30, 0) opt.renew = dialog.AddSlider('Renew herd', herd.renew, 1, 10, 0) opt.shuff = dialog.AddCheckbox('Shuffle critters', herd.shuffle) opt.lbl2 = dialog.AddLabel('Critter:') opt.minb = dialog.AddTextbox('Minimum bands:', critter.minBands) opt.maxb = dialog.AddTextbox('Maximum bands:', critter.maxBands) opt.keeps = dialog.AddTextbox('Keep score:', critter.keepScore) opt.breeds = dialog.AddTextbox('Breed score:', critter.breedScore) opt.maxloss = dialog.AddTextbox('Max loss:', critter.maxLoss) opt.lbl3 = dialog.AddLabel('Bands:') opt.minst = dialog.AddSlider('Minimum str', bands.minStr, 0.1, 2, 1) opt.maxst = dialog.AddSlider('Maximum str', bands.maxStr, 0.1, 2, 1) opt.maxup = dialog.AddSlider('Max length', bands.maxUp, 3, 20, 0) opt.run = dialog.AddButton('Start', 1) dialog.Show(opt) herd.breedBest = opt.brbest.value herd.keepBest = opt.kbest.value herd.breedBastards = opt.bas.value herd.newRandom = opt.rnd.value herd.shuffle = opt.shuff.value herd.renew = opt.renew.value critter.minBands = tonumber(opt.minb.value) critter.maxBands = tonumber(opt.maxb.value) critter.keepScore = tonumber(opt.keeps.value) critter.breedScore = tonumber(opt.breeds.value) critter.maxLoss = tonumber(opt.maxloss.value) bands.minStr = opt.minst.value bands.maxStr = opt.maxst.value bands.maxUp = opt.maxup.value end else p('Exiting...') BreakScript() end end -- main call dialogOptions() GAB() -- end of script

Comments


Rav3n_pl Lv 1

Genetic Algorithm on Bands v2 Bands in Space!

  • v2 is full lua v2 code
  • added dialog options in start - no need to edit it :)

spdenne Lv 1

Line 275 needs a lower bound, since if math.random() returns 0, the script crashes with:

ERROR: [string "–[[…"]:362: bad argument #4 to 'Add' (rho must be > 0 and <= 10000)

Rav3n_pl Lv 1

Little refresh in code, nothing in functionality, just make it nicer to read.
Maybe bit faster on LUA level.