Icon representing a recipe

Recipe: Rav3n_pl GAB v3.6.2 filter Cuts

created by Bruno Kestemont

Profile


Name
Rav3n_pl GAB v3.6.2 filter Cuts
ID
100431
Shared with
Public
Parent
Rav3n_pl GAB v3.3 filter Cuts
Children
Created on
March 19, 2020 at 17:42 PM UTC
Updated on
March 19, 2020 at 17:42 PM UTC
Description

GAB in v2 LUA, now banding to 1st atom of sidechain. Now with filter management to gain time, and with cuts in fuze

Best for


Code


--[[ GAB - Genetic Algorythm on Bands, with cuts (Bruno Kestemont) based on Rav3n_pl based on CartoonVillan and Crashguard303 scripts Lua V2 Definitions: band: randomised: start segment, end segment, length, strength 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 VERSIONS: 2.0.5 2.0.5 Filter => Filter management added Bruno Kestemont 10/10/2013 16/04/2014: only added more score info in the log 3.0 : fuze using cuts 28/05/2014 Bruno Kestemont 3.1: cut bug fixed on deletecut 02/06/2014 3.2: using creditebest 3.3: creditbest bug fixed 02/06/2014 (do not use creditebest) 3.3.1: added Notes management and quicksaves for big gains (for archives when undo's) 4/11/2014 3.3.2: replaced shake by QuickShake 8/11/2014 3.3.3: debugged uncut 3.4.5: generic filter management and debugged segment to itself 3.4.6: detect ligand and always use ligand (optional) 3.4.7: 13/5/2015 changed small possible bugs 18/1/2016 log with archive of gains following jeff101 suggestions reduced thresholds on Big Steps Keeps user bands Mutate once 5 days before the deadline or the 3 latest days for HBond puzzles GENERICFILTER only latest days of non HBonds puzzles FILTERMANAGE only on mid game 3.4.8: hide only hydrophobics 3.4.9 undo.SetUndo 3.4.10 fixed unideal loop bug 3.4.11 use ligand on ligand puzzle (not always), new wiggle 3.5 GRRR adapted filter setting to new lua commands: return2GlobalOriginalFilterSetting() 3.5.1 simplified the log 3.6 : added bands to symmetric chains 3.6.1: fixed segMeanScore=10*(800-absolutebest.GetScore()) 3.6.2: if badGen<=herd.renew then -- bug fixed thanks to robgee To Do: Partial filter management, unless end Fuze and end Qstab // to verify ]]-- recipename="Rav3n_pl GAB 3.6.2 filter Cuts" undo.SetUndo(false) OriginalFilterSetting = filter.AreAllEnabled() -- new BK 8/4/2013 PROBABLEFILTER=false HASMUTABLE=false -- NEW BK 10/10/2013 timeLeft=os.difftime(puzzle.GetExpirationTime(),os.time())/86400 -- in days segCnt=structure.GetCount() segCnt2=segCnt SYMMETRIC= structure.GetSymCount () > 0 -- not used yet --detect ligand while structure.GetSecondaryStructure(segCnt2)=="M" do segCnt2=segCnt2-1 end HASLIGAND=segCnt2<segCnt startLigand=segCnt2+1 stopLigand=segCnt math.randomseed(os.clock()) -- 28/05/2014 math.random() -- 28/05/2014 p=print userbands=band.GetCount() p("Starting "..recipename.. " on\n puzzle "..(puzzle.GetName())) p(' with puzzle ID '..(puzzle.GetPuzzleID())..' and '..userbands..' user-supplied bands.\n ') -- START Wiggle Power Setting stuff function DisplayLongWigglePower () local PowerSetting = behavior.GetWigglePower() local result = "" if PowerSetting == "l" then result = "Low" elseif PowerSetting == "m" then result = "Medium" elseif PowerSetting == "h" then result = "High" elseif PowerSetting == "a" then result = "Auto" end return result end OriginalWPowerSetting= DisplayLongWigglePower () print(OriginalWPowerSetting .. " Wiggle Power") function CheckWP() -- including Alarm Dialog if OriginalWPowerSetting == "Low" or OriginalWPowerSetting == "Auto" then local ask=dialog.CreateDialog("Wiggle Power is ".. OriginalWPowerSetting) ask.l1=dialog.AddLabel("Are you sure ?") ask.continue=dialog.AddButton("Continue",1) ask.stop=dialog.AddButton("Cancel",0) askresult=dialog.Show(ask) if askresult < 1 then return false end end return true end -- STOP Wiggle Power Setting stuff function return2GlobalOriginalFilterSetting() if OriginalFilterSetting then -- if true, all filters are default enabled filter.EnableAll() --Enables all filters else filter.DisableAll() --Disables all filters end end --START Generic Filter Management by BitSpawn 21/12/2014 --Source: http://fold.it/portal/node/1998917 --identifying filtered puzzles and all properties OriginalFilterSetting = filter.AreAllEnabled() PROBABLEFILTER= false GENERICFILTER=false FILTERMANAGE= false HASMUTABLE= false IDEALCHECK= false PROBABLESYM= false SEPSIS= false ELECTRON= false CENTROID= false HOTSPOT= false HBOND=false sym=1 --START extraction of information from puzzle metadata --Extrait des infos function detectfilterandmut() -- Bruno Kestemont 10/10/2013; 13/2/2015; 5/1/2019 local descrTxt=puzzle.GetDescription() local puzzletitle=puzzle.GetName() local function SymetryFinder() -- by Bruno Kestemont 7/2/2013, 25/8/2013 local segMeanScore=10*(800-absolutebest.GetScore()) -- top score pour eviter les debuts de puzzle --p("Score moyen par segment= "..segMeanScore) if PROBABLESYM then if segMeanScore<33.39 then sym=1 PROBABLESYM=false elseif segMeanScore<85 then sym=2 elseif segMeanScore<132 then sym=3 elseif segMeanScore<197 then sym=4 else sym=5 end else sym=1 end return end if #descrTxt>0 and (descrTxt:find("filter") or descrTxt:find("filters") or descrTxt:find("bonus") or descrTxt:find("bonuses") and not descrTxt:find("disabled"))then PROBABLEFILTER=true FILTERMANAGE=true -- default yes during wiggle (will always be activate when scoring) GENERICFILTER=false -- to be evaluated end if #descrTxt>0 and (descrTxt:find("H-bond networks") or descrTxt:find("Hydrogen Bond Networks") or descrTxt:find("H-bond Networks") or descrTxt:find("H-bond Network") and not descrTxt:find("disabled"))then PROBABLEFILTER=true FILTERMANAGE=false -- default no GENERICFILTER=false -- to be evaluated end if #descrTxt>0 and (descrTxt:find("design") or descrTxt:find("designs")) then HASMUTABLE=true IDEALCHECK=true HANDFOLD=true end if #descrTxt>0 and (descrTxt:find("De-novo") or descrTxt:find("de-novo") or descrTxt:find("freestyle") or descrTxt:find("prediction") or descrTxt:find("predictions")) then IDEALCHECK=true HANDFOLD=true end if #puzzletitle>0 then if (puzzletitle:find("Sym") or puzzletitle:find("Symmetry") or puzzletitle:find("Symmetric") or puzzletitle:find("Dimer") or puzzletitle:find("Trimer") or puzzletitle:find("Tetramer") or puzzletitle:find("Pentamer")) then PROBABLESYM=true if puzzletitle:find("Dimer") and not puzzletitle:find("Dimer of Dimers") then sym=2 elseif puzzletitle:find("Trimer") or puzzletitle:find("trimer") then sym=3 elseif puzzletitle:find("Dimer of Dimers") or puzzletitle:find("Tetramer") then sym=4 elseif puzzletitle:find("Pentamer") then sym=5 else SymetryFinder() end end end if #descrTxt>0 and (descrTxt:find("Sym") or descrTxt:find("Symmetry") or descrTxt:find("Symmetric") or descrTxt:find("sym") or descrTxt:find("symmetry") or descrTxt:find("symmetric")) then PROBABLESYM=true if (descrTxt:find("Dimer") or descrTxt:find("dimer") or descrTxt:find("C2 symmetry") or descrTxt:find("twoo symmetric")) and not (descrTxt:find("Dimer of Dimers") or descrTxt:find("dimer of dimers")) then sym=2 elseif descrTxt:find("Trimer") or descrTxt:find("trimer") or descrTxt:find("C3 symmetry") or descrTxt:find("three symmetric") then sym=3 elseif (descrTxt:find("Dimer of Dimers") or descrTxt:find("Tetramer") or descrTxt:find("C4 symmetry") or descrTxt:find("four symmetric")) and not (descrTxt:find("dimer of dimers") or descrTxt:find("tetramer"))then sym=4 elseif descrTxt:find("Pentamer") or descrTxt:find("pentamer") or descrTxt:find("C5 symmetry") or descrTxt:find("five symmetric") then sym=5 else SymetryFinder() end end --print resulting sym info if PROBABLESYM then print("Symmetric") if sym==2 then print("Dimer") elseif sym==3 then print("Trimer") elseif sym==4 then print("Tetramer") elseif sym==5 then print("Pentamer") elseif sym>5 then print("Terrible polymer") end else print("Monomer") end if #puzzletitle>0 and puzzletitle:find("Sepsis") then -- new BK 17/6/2013 SEPSIS=true HANDFOLD=true --p(true,"-Sepsis") print("Sepsis") end if #puzzletitle>0 and puzzletitle:find("Electron Density") then -- for Electron Density --p(true,"-Electron Density") ELECTRON=true HANDFOLD=true print("Electron density") end if #puzzletitle>0 and puzzletitle:find("Centroid") then -- New BK 20/10/2013 --p(true,"-Centroid") CENTROID=true print("Centroid") end if #puzzletitle>0 and puzzletitle:find("Hotspot") then -- New BK 21/01/2014 HOTSPOT=true print("Hotspot") end return end detectfilterandmut() --END extraction of information from puzzle metadata --Extrait des infos -- function to copy class/table function CopyTable(orig) local copy = {} for orig_key, orig_value in pairs(orig) do copy[orig_key] = orig_value end return copy end -- functions for filters function FiltersOn() if filter.AreAllEnabled() then filter.EnableAll() end end function FiltersOff() if filter.AreAllEnabled() and GENERICFILTER then -- 18/1/2016 filter.DisableAll() end end -- function to overload a funtion function mutFunction(func) local currentfunc = func local function mutate(func, newfunc) local lastfunc = currentfunc currentfunc = function(...) return newfunc(lastfunc, ...) end end local wrapper = function(...) return currentfunc(...) end return wrapper, mutate end -- function to overload a class -- to do: set the name of function classes_copied = 0 myclcp = {} function MutClass(cl, filters) classes_copied = classes_copied+1 myclcp[classes_copied] = CopyTable(cl) local mycl =myclcp[classes_copied] for orig_key, orig_value in pairs(cl) do myfunc, mutate = mutFunction(mycl[orig_key]) if filters==true then mutate(myfunc, function(...) FiltersOn() if table.getn(arg)>1 then -- first arg is self (function pointer), we pack from second argument local arguments = {} for i=2,table.getn(arg) do arguments[i-1]=arg[i] end return mycl[orig_key](unpack(arguments)) else --print("No arguments") return mycl[orig_key]() end end) cl[orig_key] = myfunc else mutate(myfunc, function(...) FiltersOff() if table.getn(arg)>1 then local arguments = {} for i=2, table.getn(arg) do arguments[i-1]=arg[i] end return mycl[orig_key](unpack(arguments)) else return mycl[orig_key]() end end) cl[orig_key] = myfunc end end end -- how to use: --setting default options if filters BK 4/2/2015 --MutClass(structure, false) --MutClass(band, false) --MutClass(current, true) if GENERICFILTER then -- WARNING: TO VERIFY !! (may be it's irreversible for several funtions bellow) MutClass(structure, false) MutClass(band, true) MutClass(current, true) MutClass(recentbest, true) -- otherwise, it remembers cut solutions MutClass(save, true) -- better to save with full score end --STOP Generic Filter Management -- options: energy = false --set true to seek energy in exploration puzzles; false works on all puzzles pullCI = 0.9 --Clash Importance during pull 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 useLigand = false --use ligand if true AlwaysUseLigand=false -- Warning: don't set true by default because there are some erroneous ligands onlyMutable = false --if true use ONLY all mutable aas, no matter of always use mutateOnce = false --if true use mutate(1) instead of shake in qstab mutateOnceCI = 0.21 --mutate on what clashing importance mutateAlwas = false --if true use mutate(1) instead of all shakes mingps= 80 -- in wiggle sequence, this is the minimum gain per iteration needed to do the wiggle again (not zure it's very usefull to save time). cut=structure.InsertCut -- 28/05/2014 --uncut=structure.DeleteCut -- 28/05/2014 if HASMUTABLE and not HBOND and timeLeft>4 and timeLeft<6 then mutateOnce = true print ("Option: mutate(1) instead of shake in qstab") end -- It's an option ! --if HASMUTABLE and not HBOND and timeLeft>4 then mutateAlwas = true print ("Option: mutate(1) instead of all shakes") end -- It's an option ! --Don't mutate just after hand fold (because of filters on AAs, better to mutate by purpose using recipes like MNW or Maaa) --Don't mutate the last 4 days, it's slow and it will not gain. if HASMUTABLE and HBOND and timeLeft<4 then mutateOnce = true print ("Option: mutate(1) instead of shake in qstab") end --with HBonds, mutate a little bit later if HASMUTABLE and HBOND and timeLeft<3 then FILTERMANAGE = true print ("Option: wiggle with filter disabled") end --SLOTS: --[[ 3 is best 4 used in recipe 5 used in recipe 50-100 used to record each big steps for movie at the end ]]-- SlotStepStart=50 -- New 4/11/2014 SlotStep=SlotStepStart herd= --herd options { breedBest = 5, --breed best 4 critters - all combinations => 6 kids form 4 critters, 3 form 3, 1 form 2, 9 form 5 ;] 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=2, --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 minChng = 3, -- minimum length change of band (negative length pull or positive length push) maxUp = 6.1, -- maximum length change up (push) maxDn = 6.9, -- maximum length change down (pull)(will be used negative) minSkip = 5, --minimum segment distance (not banding segments that are too proximate) minDist = 4, --minimum spatial distance minLen = 2, --minimum length of created band } DoNotUse={--just comment lines below or add more areas to avoid --{segCnt,segCnt}, --ligand cant be used --{120,134}, --{1,10}, } AlwaysUse={ --areas should be always used --{236,236}--ligand need to be at one end --{308,311}, --loopy --{272,319}, --loopy } UseSegments= --use ONLY this segments { --2,3,4,5 } -- 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 } checkBoth=false --check both ends to above, if false only one end need to be true --end of options if HASLIGAND then useLigand=true end if useLigand==false then segCnt=segCnt2 end if HASLIGAND and AlwaysUseLigand then AlwaysUse={ --areas should be always used {startLigand,stopLigand}--ligand need to be at one end --{308,311}, --loopy --{272,319}, --loopy } end function uncut(seg) -- new BK 02/06/2014 for i=1, structure.GetCount() do structure.DeleteCut(i) end end 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 on windowz!!! --calculate REALLY good seed from current score seed=os.time() seed=1/seed while seed<10000000 do seed=seed*10 end seed=seed-seed%1 p("Seed is: "..seed) math.randomseed(seed) math.random(100) -- Because the first is not random format=string.format --START Archive in Notes, -- New 4/11/2014 function SelectNote(recipename) store={} store.label=recipename or "" -- edit here the recipe name store.note_number=structure.GetCount() for seg=structure.GetCount(),1,-1 do if structure.GetNote(seg)~="" then break end store.note_number=seg end print(string.format("Recording results in Note for segment %i",store.note_number)) store.starting_score=current.GetScore() --structure.SetNote(store.note_number,string.format("(%s) %.3f + FSP",user.GetPlayerName(),store.starting_score)) end SelectNote(recipename) function WhriteNote(loop_nb) -- all inits are in SelectNote function local loop_count= loop_nb or 1 structure.SetNote(store.note_number,string.format("(%s) %.3f + %s(%i) %.3f",user.GetPlayerName(),store.starting_score,store.label,loop_count,current.GetScore())) end --END Archive in Notes --START quick save algorithm function QuickShake() --[[------------------------------------------------------------------------------------------------ -- Algorithm for faster shake REFERENCES 1. N/A Copyright (C) 2014 Seagat2011 <http://fold.it/port/user/1992490> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. $Id$ ------------------------------------------------------------------------------------------------]]-- --[[ v1 - Inception 1.2 - Loops until nogain ]]-- local idx = 1 local idx2 = structure.GetCount () local hash = {} local cs = current.GetScore () --print ( 'Quick Shake Algorithm v1.2 SG2011 - Current Score: '..cs ) local function New ( obj ) return obj -- pass-new-obj-by-value end local _gses = New ( current.GetSegmentEnergySubscore ) local function SmartShake ( iters ) local gain = true while (gain) do gain = false for i=idx,idx2 do local ci = _gses ( i,'clashing' ) if ci < _gses ( i,'hiding' ) and ci < _gses ( i,'packing' ) and ci < _gses ( i,'ideality' ) and ci < _gses ( i,'sidechain') and ci < _gses ( i,'bonding' ) and ci < _gses ( i,'other' ) and ci < _gses ( i,'reference') then selection.Select ( i ) end -- test ci -- end -- loop -- if selection.GetCount () then local css = current.GetScore () structure.ShakeSidechainsSelected ( iters ) selection.DeselectAll () if current.GetScore () > css then gain = true end -- test -- end -- test -- end -- loopf -- end structure.SmartShake = SmartShake structure.SmartShake ( 1 ) --print ( 'Done.' ) end --END quick save algorithm function WiggleOld(how, iters, minppi) if FILTERMANAGE then filter.DisableAll() end-- new BK 8/4/2013, always disable filter here if how==nil then how="wa" end if iters==nil then iters=6 end if minppi==nil then minppi=0.1 end if iters>0 then iters=iters-1 sp=Score() if how == "s" then if FILTERMANAGE then return2GlobalOriginalFilterSetting() end -- new BK 8/4/2013, always back to user settings if mutateAlwas==true then structure.MutateSidechainsSelected(1) --else structure.ShakeSidechainsSelected(1) end else QuickShake() 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) end ep = Score() ig=ep-sp if how~="s" then if ig > minppi then return Wiggle(how, iters, minppi) end --tail call end end if FILTERMANAGE then return2GlobalOriginalFilterSetting() end -- new BK 10/10/2013, always back to user settings end function Wiggle(how, iters, minppi, valit, mingps) -- NEW one, with filter management, 17/4/2016 if FILTERMANAGE then filter.DisableAll() end-- new BK 8/4/2013, always disable filter here if how==nil then how="wa" end if iters==nil then iters=6 end if minppi==nil then minppi=0.1 end if valit==nil then valit= 1 end if mingps==nil then mingps= 80 end -- the goal here is to save time local loops = 0 -- only for log, no other use if iters>0 then startRecTime=os.clock () iters=iters-1 loops=loops+1 -- only for log, no other use sp=Score() if how == "s" then if FILTERMANAGE then return2GlobalOriginalFilterSetting() end -- new BK 8/4/2013, always back to user settings if mutateAlwas==true then structure.MutateSidechainsSelected(1) --else structure.ShakeSidechainsSelected(1) end else QuickShake() end elseif how == "wb" then structure.WiggleAll(valit, true,false) elseif how == "ws" then structure.WiggleAll(valit, false,true) elseif how == "wa" then structure.WiggleAll(valit) end ep = Score() ig=ep-sp timeperiteration =os.clock ()-startRecTime tppii=ig/timeperiteration --print("g/s: "..ig.." / "..timeperiteration.." = "..tppii) if how~="s" then if ig > minppi --and tppii > mingps --Test DEBUG for gaining time, but is this loosing gains ? then --print("Repeating Wiggle. Gain per second was "..tppii) return Wiggle(how, iters, minppi, valit) end --tail call end end if loops > 1 then print("Wiggled "..loops.." times") -- for DEBUG end if FILTERMANAGE then return2GlobalOriginalFilterSetting() end -- new BK 10/10/2013, always back to user settings end wiggle=structure.WiggleAll -- 28/05/2014 No filter management function SaveBest() local g=Score()-bestScore if g>0 then if g>0.01 then p("Gained another "..round(g).." pts. Score: "..round(Score()).. " from "..round(ss)) end bestScore=Score() save.Quicksave(3) end end function SaveRB() if Score()>bestScore then save.Quicksave(4) recentbest.Restore() -- WARNING: it took the best including cuts SaveBest() save.Quickload(4) end end function SaveCB() -- cut version 02/06/2014 , recent save no increment if Score()>bestScore then save.Quicksave(4) recentbest.Restore() -- OK only is recentbest saved after deleting cuts SaveBest() save.Quickload(4) end end function Qstab() selection.SelectAll() CI(0.1) if mutateOnce==true then CI(mutateOnceCI) 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 FuzeCuts(ci1) -- 28/05/2014 by pauldunn NB: no filter management here . 02/06/2014 recentbest bug fixed local seg=math.random(structure.GetCount()) cut(seg) CI(1) wiggle(15,true,true) CI(ci1) --ci(0.01) wiggle(1,true,true) CI(1) wiggle(25,true,true) uncut(seg) recentbest.Save() -- NEW 02/06/2014 important to avoid recentbest in cut bug wiggle(25,true,true) CI(ci1) --ci(0.01) wiggle(2,true,true) CI(1) wiggle(25,true,true) 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() -- IMPORTANT: recentbest must be saved after deleting cut SaveBest() end function scb() recentbest.Restore() -- IMPORTANT: recentbest must be saved after deleting cut SaveBest() end function FuzeWithCuts() p("Fuzing with cuts...") local scr=Score() selection.SelectAll() recentbest.Save() Fuze1(0.3,0.6) FuzeEnd() FuzeCuts(0.01) scb() -- NEW 28/05/2014, 02/06/2014 Fuze2(0.3,1) srb() Fuze1(0.05,1) srb() Fuze2(0.7,0.5) FuzeEnd() FuzeCuts(0.1) scb() -- NEW 28/05/2014, 02/06/2014 Fuze1(0.07,1) srb() end function random(n1,n2) --random function returns int or float depends on input vars if n2==nil and n1==nil then return math.random() --float 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 i=1,n do AddCritter() end end function AddCritter() --create 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 i=1,r do c.bands[#c.bands+1]=AddBand() end critters[#critters+1]=c --p(c.name.." bands: "..#c.bands) -- suppressed from the log, I don't see the use of this end function AddBand() --create one random band (random push or pull) local cnt=0 local b={} while true do --try till die cnt=cnt+1 local s1=random(segCnt) local branch= random(structure.GetSymCount ()+1)-1 -- 0 if monomer, equal probability for each branch if onlyMutable==true or #UseSegments>0 then s1=UseSegments[random(#UseSegments)] end local s2=random(segCnt) if s1>s2 then s1,s2=s2,s1 end --swap if #UseSegments>0 or CanBeUsed(s1,s2) then local str=random(bands.minStr,bands.maxStr) local len=0 while true do --randomize correct distance len=random(-bands.maxDn,bands.maxUp) -- the goal change from pull to push if len<-bands.minChng or len>bands.minChng then break end end b={s1,s2,str,len, branch} break end if cnt>100 then p("Sorry! Cant create band! Breaking script!") --BreakScript() --there is no such function, so it crashes script break end end return b end function CanBeUsed(sg1,sg2) --checking end of bands function ssCheck(ss) local good=false if use.Sheet and ss=="E" then good=true end if use.Helix and ss=="H" then good=true end if use.Loop and ss=="L" then good=true end return good end function AreGood(s1,s2) --check that s1 and s2 can be used local ok=true if s2-s1<bands.minSkip then ok=false end if ok==true and structure.GetDistance(s1,s2)<bands.minDist then ok=false end return ok end local ok=AreGood(sg1,sg2) if ok==true and #DoNotUse>0 then --none of 2 can be in that area for i=1, #DoNotUse do local r=DoNotUse[i] for x=r[1],r[2] do if x==sg1 or x==sg2 then ok=false break end end if ok==false then break end end end if ok==false then return false --if false can`t be used else ok=false if #AlwaysUse>0 then --at least one have to be there for i=1, #AlwaysUse do local r=AlwaysUse[i] for x=r[1],r[2] do if x==sg1 or x==sg2 then ok=true break end end if ok==true then break end end else ok=true end end if ok==true then --check structure ok=false local ss1=structure.GetSecondaryStructure(sg1) local ss2=structure.GetSecondaryStructure(sg2) if checkBoth then if ssCheck(ss1) and ssCheck(ss2) then ok=true end else if ssCheck(ss1) or ssCheck(ss2) then ok=true end end end return ok end function deletebands() --leave user bands intact nbands=band.GetCount() if nbands>userbands then for i=nbands,userbands+1,-1 do -- count down from nbands to userbands+1 band.Delete(i) end -- for i end -- if nbands end -- function function ScoreHerd() --makes the bands and score all critters from herd save.Quickload(3) p("Scoring "..#critters.." critters...") save.Quicksave(5) local herdScore=Score() for i=1,#critters do deletebands() local crt=critters[i] --critter local s=Score() --start score local bnds=crt.bands -- b={s1,s2,str,len, branch} (len is the random push or pull difference of length) for b=1,#bnds do local bnd=bnds[b] if bnd[1] ~= bnd[2] then -- new debugging, no band to itself local a1=5 local a2=5 if bnd[1]== structure.GetCount() then a1=6 end if bnd[2]== structure.GetCount() then a2=6 end -- changed a1 to a2 13/5/2015 if structure.GetAminoAcid(bnd[1])=='g' then a1=0 end if structure.GetAminoAcid(bnd[2])=='g' then a2=0 end if not structure.IsHydrophobic(bnd[1]) and bnd[4]<0 then a1=0 end -- only hiding hydrophobics if not structure.IsHydrophobic(bnd[2]) and bnd[4]<0 then a2=0 end if structure.IsHydrophobic(bnd[1]) and bnd[4]>0 then a1=0 end -- don't push hydropobics to water if structure.IsHydrophobic(bnd[2]) and bnd[4]>0 then a2=0 end band.AddBetweenSegments(bnd[1],bnd[2],a1,a2, bnd[5]) -- 5 is the branch for symmetrics local bc=band.GetCount() band.SetStrength(bc,bnd[3]) local len=structure.GetDistance(bnd[1],bnd[2])+bnd[4] -- distance between segments + band length change (+ or -) if len<bands.minLen then len=bands.minLen end band.SetGoalLength(bc,len) --print("Band: "..bnd[1].."-"..bnd[2].." a1: "..a1.." a2: "..a2.." str: "..round3(bnd[3]).." length= "..round3(length)) end end selection.SelectAll() CI(pullCI) recentbest.Save() local seg=math.random(structure.GetCount()) -- new 28/05/2014 cut(seg) -- new 28/05/2014 Wiggle("wb",1) uncut(seg)-- new 28/05/2014 PROBLEM here, recentbest includes cuts recentbest.Save() -- NEW 02/06/2014 to avoid recent best in cuts deletebands() CI(1) if math.abs(s-Score()) > qstabThresh then Qstab() else Wiggle() end if Score()-bestScore>fuzeThresh then SaveRB() FuzeWithCuts() -- new 02/06/2014 else SaveRB() end crt.score=Score()-s -- p("Critter "..crt.name.." : "..round(crt.score)) -- eliminated ! I don't see the use of publishing this ! 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) deletebands() 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 i=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) -- suppressed, I don't see the use of this info 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 and (math.abs(critters[i].score)>0.1 or critters[i].score>0) 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() 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 function GAB() if onlyMutable==true then for i=1,segCnt do if structure.IsMutable(i) then UseSegments[#UseSegments+1]=i end end end if #AlwaysUse>0 then for i=1,#AlwaysUse do local ss=AlwaysUse[i][1] local se=AlwaysUse[i][2] if ss>se then ss,se=se,ss end for j=ss,se do UseSegments[#UseSegments+1]=j end end AlwaysUse={} --added to list, no need to check later end bestScore=Score() critterID=0 gen=0 ss=Score() ssstr=(round(ss)) save.Quicksave(3) recentbest.Save() p("Starting "..recipename.." score: "..round(ss)) critters={} FillHerd() badGen=0 while true do --this is (almost) endless script ;] undo.SetUndo(false) -- reset if gain before end of loop genScore=Score() gen=gen+1 p() p("Generation: "..gen..", score: "..round(Score())..", gain: "..round(Score()-ss).." ("..(os.date())..")") 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 -- bug fixed thanks to robgee p("Creating fresh random herd...") critters={} FillHerd() badGen=0 else BreedHerd() end genEndScore=Score() genGain=genEndScore-genScore if gen>1 and (gen-1)==5*down((gen-1)/5) then -- New 18/1/2016 jeff101 log display ssstr=(ssstr..'\n ') -- start new line every 5 generations end if genGain>=0 then ssstr=(ssstr..' + '..round(genGain)) undo.SetUndo(true) else ssstr=(ssstr..' - '..(-round(genGain))) end p(ssstr..' = '..round(genEndScore)) WhriteNote(gen) -- New 4/11/2014 SaveBigSteps() -- New 4/11/2014 for movie at the end end p("Final score: "..round(Score()).." Total gain: "..round(Score()-ss)) end --START Movie store big steps StepScore= Score() -- New 4/11/2014 function StoreBigStep() StepScore= Score() save.Quicksave(SlotStep) SlotStep=SlotStep+1 end function SaveBigSteps() -- in order to be able to display big steps afterwards in undos local g=Score()-StepScore local s= Score() if s >0 and ( (s <7000 and g>500) or (s <9000 and g>200) or (s <10000 and g>100) or (s >10000 and g>50)) then StoreBigStep() end end function MovieSteps() undo.SetUndo(true) for i= SlotStepStart, SlotStep do save.Quickload(SlotStep) end --save.Quickload(3) print("See remembering of big steps in undos") end --END Movie store big steps function Cleanup(err) -- NEW BK 10/10/2013 print("Restoring CI, best result, filter and structures") CI(1) undo.SetUndo(true) if FILTERMANAGE then return2GlobalOriginalFilterSetting() end -- new BK 8/4/2013, always back to user settings MovieSteps() -- New 4/11/2014 save.Quickload(3) MovieSteps() WhriteNote(gen) -- New 4/11/2014 deletebands() print(err) end -- main call --GAB() xpcall(GAB,Cleanup) -- NEW BK 10/10/2013 --end of script

Comments


Bruno Kestemont Lv 1

3.4.7: 13/5/2015 changed small possible bugs
18/1/2016 log with archive of gains following jeff101 suggestions
reduced thresholds on Big Steps
Keeps user bands
Mutate once 5 days before the deadline or the 3 latest days for HBond puzzles
GENERICFILTER only latest days of non HBonds puzzles
FILTERMANAGE only on mid game