Icon representing a recipe

Recipe: Rav3n_pl GAB BiS Filter v2.11

created by Bruno Kestemont

Profile


Name
Rav3n_pl GAB BiS Filter v2.11
ID
108992
Shared with
Public
Parent
Rav3n_pl GAB BiS Filter v2.9.3
Children
None
Created on
March 14, 2025 at 19:48 PM UTC
Updated on
June 14, 2025 at 16:09 PM 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 assigning 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 porky added the filter management BK added more filters on recentbest and save ver 2.02 Filter --debugged line 239 ver 2.03 --debugged filter ver 2.04 --debuggeg monomer ver 2.05 -- just update the commands Get/SetFiltersDisabled ver 2.06 -- debugged generic filter & second dialog ver 2.1 -- second dialog with sliders (no text box). This reduces the range available but it's also more convenient and it avoids user errors ver 2.1.1 Generic filter only after dialog to save time at start ver 2.1.2 Check conditions option on exploration puzzles ver 2.1.3 debugged conditions ver 2.2.0 added Jeff101's display on each loop, and archive in note by pauldunn keep user bands FILTERMANAGE activated (disable filter during wiggle) ver 2.2.1 bug fixed in loop_count ver 2.2.2 added quickshake ver 2.2.3 undo.SetUndo ver 2.2.4 fixed possible unideal loop bug ver 2.3 managing ligands, new wiggle ver 2.3.1 fixed DoAlwaysUseLigand() ver 2.4 sketchbook adapted (minGain) ver 2.5 info on filters (?? is it implemented?) ver 2.5.1 GRRR adapted filter setting to new lua commands: return2OriginalFilterSetting() ver 2.5.2 small changes in info ver 2.5.3 small changes related to filters and info ver 2.6 working on detailed filters and bonusses / The filters settings are the default ones (unchecked ones are never activated) The bonusses are doubled for selection ver 2.6.1 fixed non filtered puzzles ver 2.6.2 fixed parameter filtering, added DEBUGprint ver 2.6.3 added "Objectives" for identifying filtered puzzles ver 2.6.4 filter tables "false" corrected ver 2.6.5 fixed a TopScore bug ver 2.7 with probabilities of mutating ver 2.7.1 fixed for SKETCHBOOK and symmetrics ver 2.7.2 better for SKETCHBOOK ver 2.7.3 if genScore>=Score() then badGen=badGen+1 else badGen=0 end -- bug fixed thanks to robgee ver 2.8 optional separate weight for each filter ver 2.8.1 small changes ver 2.9 non bonding mutate (for end game reducing BUNS) EXPERIMENTAL weighted ScoreHerd() !! to be evaluated ! not "r" as HBOND candidate (with 3 bondable atoms, chances are low to make network) ver 2.9.1 slall change adding FILTERMANAGE in Design titles ver 2.9.3 fixed exploration filter ver 2.10 add dialog non locked, added ui.CenterViewport() ver 2.11 adapted for ligand puzzles TO DO: complex score management ]]-- recipename= "Rav3n_pl GAB BIS Filter 2.11" 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 ') ssstr="" -- jeff101 gen=0 --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 for SaveBigSteps() SlotStep=SlotStepStart -- 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 (NOT USED YET) 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 undo.SetUndo(false) OriginalFilterSetting = filter.AreAllEnabled() NeverDisableSomeFilters= false -- used in FiltersOff NeverEnableSomeFilters= false -- used in FiltersOn (no used actually) AllFiltersTogether= false -- if true, it acceplerates FilersOn PROBABLEFILTER= false PROBABLEHBOND= false GENERICFILTER=false FILTERMANAGE= false HASMUTABLE= false IDEALCHECK= false PROBABLESYM= false SEPSIS= false ELECTRON= false CENTROID= false HOTSPOT= false EXPLORATION= false SKETCHBOOK = false conditions=false sym=1 SYMMETRIC= false HBONDING = false -- mutate only to bonding AAs NOHBONDING = false -- mutate only to non bonding AAs HASLOCKED = false AlwaysUseUnlocked = false AlwaysUseLigand= false useLigand= false segCnt=structure.GetCount() segCnt2=segCnt while structure.GetSecondaryStructure(segCnt2)=="M" do segCnt2=segCnt2-1 end -- not used yet (ligand) HASLIGAND=segCnt2<segCnt startLigand=segCnt2+1 stopLigand=segCnt SymCount=structure.GetSymCount() -- new 22/10/2019 if SymCount>0 then SYMMETRIC = true end lockedlist={} for i= 1, segCnt2 do if structure.IsLocked(i) then HASLOCKED=true lockedlist[#lockedlist+1]= i --locked list end end debugMode= false function DEBUGprint(text2print) local text2print = text2print or "" if debugMode then print(text2print) end end --START extraction of information from puzzle metadata --Extrait des infos function detectfilterandmut() -- Bruno Kestemont 10/10/2013; 13/2/2015; 5/1/2019; 1/3/2019 local descrTxt=puzzle.GetDescription() local puzzletitle=puzzle.GetName() local function SymetryFinder() -- by Bruno Kestemont 7/2/2013, 25/8/2013 local segMeanScore=(scoreboard.GetGroupScore()-8000)/segCnt -- 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") or descrTxt:find("Objectives") and not (descrTxt:find("disabled") or descrTxt:find("Sequence:")))then PROBABLEFILTER=true -- WARNING ! There are false positives here ! 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") or descrTxt:find("binding") and not descrTxt:find("disabled"))then PROBABLEFILTER=true FILTERMANAGE=false -- default no GENERICFILTER=false -- to be evaluated PROBABLEHBOND= true HBONDING = true end if #descrTxt>0 and (descrTxt:find("design") or descrTxt:find("designs") or descrTxt:find("redesign")) then HASMUTABLE=true IDEALCHECK=true HANDFOLD=true PROBABLEFILTER=true -- WARNING ! There are false positives here ! 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 PROBABLEFILTER=false FILTERMANAGE=false GENERICFILTER=false end if #descrTxt>0 and (descrTxt:find("Move Limit") or descrTxt:find("SKETCHBOOK") or descrTxt:find("sketchbook")) then SKETCHBOOK=true FILTERMANAGE=false GENERICFILTER=false print("SKETCHBOOK") 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 if (puzzletitle:find("Design")) then PROBABLEFILTER=true 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("Design") then -- new BK 11/9/2020 PROBABLEFILTER=true -- WARNING ! There are false positives here ! FILTERMANAGE=true -- default yes during wiggle (will always be activate when scoring) GENERICFILTER=false -- to be evaluated 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 --START Generic Filter Management by BitSpawn 21/12/2014 --Source: http://fold.it/portal/node/1998917 -- function to copy class/table -- Handy shorts module function CopyTable(orig) local copy = {} for orig_key, orig_value in pairs(orig) do copy[orig_key] = orig_value end return copy 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) function GenericFilterMngt() if GENERICFILTER then -- WARNING: TO VERIFY !! (may be it's irreversible for several funtions bellow) MutClass(structure, false) MutClass(band, true) -- must be true to avoid unideal loop bug MutClass(current, true) MutClass(recentbest, true) -- otherwise, it remembers cut solutions MutClass(save, true) -- better to save with full score end end --STOP Generic Filter Management -- functions for filters --[[ if PROBABLEFILTER then -- new functions 17/7/2018 filter.GetNames() -- Get all filter names filter.GetEnabledNames() -- Get active filter names filter.GetDisabledNames() -- Get disabled filter names filter.AreAllEnabled() -- True if all filters are active filter.Enable(string) -- Enables the named filter filter.Disable(string) -- Disables the named filter filter.EnableAll() -- Enables all filters filter.DisableAll() -- Disables all filters filter.GetBonusTotal() -- Total bonus score of the filters filter.GetBonus(string) -- Bonus score of the named filter filter.ConditionSatisfied(string) -- Is the condition satisfied or the filter active filter.IsEnabled(string) -- Is the filter Enabled end ]]-- 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 function return2IndividualOriginalFilterSetting() -- returns to original choice from dialog --DEBUGprint("Return to Original Filters") --InitialFilters -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} for i = 1, #InitialFilters do if InitialFilters[i][3] then filter.Enable(InitialFilters[i][1]) else filter.Disable(InitialFilters[i][1]) end --DEBUGprint("Is ".. InitialFilters[i][1].." active ? "..tostring(filter.IsEnabled(InitialFilters[i][1]))) end end function return2OriginalFilterSetting() if AllFiltersTogether then return2GlobalOriginalFilterSetting() else return2IndividualOriginalFilterSetting() end end function FiltersOn() -- all of them WARNING New version 20/2/2019, needs NeverEnableSomeFilters if NeverEnableSomeFilters then return2OriginalFilterSetting() else if not filter.AreAllEnabled() then -- if not all filters are enabled, enable all of them filter.EnableAll() -- Enables all filters end end end function FiltersOff() -- WARNING new version 20/2/2019, needs NeverDisableSomeFilters if NeverDisableSomeFilters then return2OriginalFilterSetting() --if filter.AreAllEnabled() then -- only if all filters are enabled, disable all of them. If only some of them are enabled, do nothing -- filter.DisableAll() -- Disables all filters --end else filter.DisableAll() -- Disables all filters end end --STOP functions for filters --START SET NOTES BY PD --[[ Set note with author, recipe and big steps -- By Pauldunn This subroutine is used in much group recipe versions in various groups originally in Go Science It traces the various recipes and players that improved the current solution Module to quick copy-paste it in existing recipes, by Bruno Kestemont ]]-- --HOW TO include in a recipe? --1a) COPY from here ================ function InitNotes(recipename) local recipename=recipename or "" note_number=structure.GetCount() for seg=structure.GetCount(),1,-1 do if structure.GetNote(seg)~="" then break end note_number=seg end print(string.format("Recording "..recipename.." results in Note for segment %i",note_number)) starting_score=current.GetScore() --structure.SetNote(note_number,string.format("(%s) %.3f + %s(%i) %.3f",user.GetPlayerName(),starting_score,recipename,loop_count,current.GetScore())) end function SetNote(note_number, starting_score, recipename, loop_count) local recipename=recipename or "" local starting_score=starting_score or 0 local loop_count=loop_count or 1 --print(string.format("Recording "..recipename.." results in Note for segment %i",note_number)) structure.SetNote(note_number,string.format("(%s) %.3f + %s(%i) %.3f",user.GetPlayerName(),starting_score,recipename,loop_count,current.GetScore())) end InitNotes(recipename) -- WARNING: and match "recipename" with the recipename of the recipe --1b) COPY to here. somewhere after the options and inits of the recipe ================ --3a) Uncommend the 2 following lines and COPY from here --------------- --loop_count=gen -- adapt "gen" to the name of loops used in the recipe --SetNote(note_number, starting_score, recipename, loop_count) -- WARNING: and mach "recipename" and "loop_count" with the names of the recipe --3b) COPY to here after main generations or loops of the recipe -------------- --END SET NOTES BY PD -- 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=false --if true use mutate(1) instead of shake in qstab mutateAlwas=false --if true use muatate(1) instead of all shakes minGain= 0 -- minimum gain accepted per iteration (for sketchbook puzzles) MaxLossIFG= 0 -- default maximum loss accepted if filter gains MaxMaxLossIFG=100 -- maximum maximum loss accepted if filter gains (for dialog) 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= 1000, --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 lenght minUp = 0.1 -- debugging case=0 } 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 --{238,238}--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 } --end of options if HASLIGAND then useLigand=true AlwaysUseLigand= true end if useLigand==false then segCnt=segCnt2 end function DoAlwaysUseLigand() 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 end DoAlwaysUseLigand() function DoAlwaysUseUnlocked() if AlwaysUseUnlocked then AlwaysUse={ --areas should be always used --{startLigand,stopLigand}--ligand need to be at one end --{308,311}, --loopy --{272,319}, --loopy } end end DoAlwaysUseUnlocked() --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 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 --------+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --START Filter subroutine --Test of the new filter functions --[[ filter.GetNames() --Get all filter names filter.GetEnabledNames() --Get active filter names filter.GetDisabledNames() --Get disabled filter names filter.AreAllEnabled() --True if all filters are active filter.Enable(string) --Enables the named filter filter.Disable(string) --Disables the named filter filter.EnableAll() --Enables all filters filter.DisableAll() --Disables all filters filter.GetBonusTotal() --Total bonus score of the filters filter.GetBonus(string) --Bonus score of the named filter filter.ConditionSatisfied(string) --Is the condition satisfied or the filter active filter.IsEnabled(string) --Is the filter Enabled puzzle.GetStructureName() --Get the structure name of (multistart) puzzle save.LoadSolutionByName(string) --Load the highest scoring solution by name save.SaveSolution(string) --Save a solution SetSecondaryStructure (and selected variant) --now can specify 'a' to auto-assign structure by DSSP --]] --recipename="Filters" print (puzzle.GetStructureName()) FilterList={} FilterTable={} -- {filter string, bonus, enabled, condition} FilterEnabled={} FilterDisabled={} AreAllFiltersEnabled=filter.AreAllEnabled() -- Segment set and list module -- Notice that most functions assume that the sets are well formed -- (=ordered and no overlaps) -- 02-05-2012 TvdL Free to use for non commercial purposes -- 05-02-2014 BK enhanced (also Free for non commercial purposes) -- a list is {1,2,3,8,9,10}. A set is {{1,4},{8,10}} or something like that in a 2-dimentional table: --i {[1],[2]} --___________ --1 { 1 , 4 } --2 { 8 , 10} function SegmentExtendSet(set,x,y) -- New BK 05/02/2014 x, y= nb of seg to add before and after each zone local result={} local x,y=x or 1, y or 1 for i=1,#set do if set[i][1]<1+x then --first segment result[i]={set[i][1],set[i][2]+y} elseif set[i][2]>set[#set][2]-y then --last segment result[i]={set[i][1]-x,set[i][2]} else result[i]={(set[i][1]-x and set[i][1]>x) or set[i][1] , (set[i][2]<=set[#set][2]-y and set[i][2]+y) or set[i][2]} result[i]={set[i][1]-x ,set[i][2]+y} end end return result -- overlaps are possible end function SegmentListToSet(list) --note: clean duplicates local result={} local f=0 local l=-1 table.sort(list) for i=1,#list do if list[i] ~= l+1 and list[i] ~= l then -- note: duplicates are removed if l>0 then result[#result+1]={f,l} end f=list[i] end l=list[i] end if l>0 then result[#result+1]={f,l} end --print("list to set") --SegmentPrintSet(result) return result end function SegmentSetToList(set) local result={} for i=1,#set do for k=set[i][1],set[i][2] do result[#result+1]=k end end return result end function SegmentCleanSet(set) -- clean duplicates -- Makes it well formed and clean duplicates return SegmentListToSet(SegmentSetToList(set)) end function SegmentInvertSet(set,maxseg) -- Gives back all segments not in the set -- maxseg is added for ligand local result={} if maxseg==nil then maxseg=structure.GetCount() end if #set==0 then return {{1,maxseg}} end if set[1][1] ~= 1 then result[1]={1,set[1][1]-1} end for i=2,#set do result[#result+1]={set[i-1][2]+1,set[i][1]-1} end if set[#set][2] ~= maxseg then result[#result+1]={set[#set][2]+1,maxseg} end return result end function SegmentInList(s,list) table.sort(list) for i=1,#list do if list[i]==s then return true elseif list[i]>s then return false end end return false end function SegmentInSet(set,s) for i=1,#set do if s>=set[i][1] and s<=set[i][2] then return true elseif s<set[i][1] then return false end end return false end function SegmentJoinList(list1,list2) -- duplicates allowed local result=list1 if result == nil then return list2 end for i=1,#list2 do result[#result+1]=list2[i] end table.sort(result) return result end function SegmentJoinSet(set1,set2) -- no duplicates, no overlap return SegmentListToSet(SegmentJoinList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentCommList(list1,list2) -- what is common to 2 lists local result={} table.sort(list1) table.sort(list2) if #list2==0 then return result end local j=1 for i=1,#list1 do while list2[j]<list1[i] do j=j+1 if j>#list2 then return result end end if list1[i]==list2[j] then result[#result+1]=list1[i] end end return result end function SegmentCommSet(set1,set2) -- what is common to set 1 and set 2 (no duplicate) return SegmentListToSet(SegmentCommList(SegmentSetToList(set1),SegmentSetToList(set2))) end function SegmentSetMinus(set1,set2) -- set1 minus set2 (set1 minus what is common to set 1 and set2)(no duplicate) return SegmentCommSet(set1,SegmentInvertSet(set2)) end function SegmentPrintSet(set) print(SegmentSetToString(set)) end function SegmentSetToString(set) local line = "" for i=1,#set do if i~=1 then line=line..", " end line=line..set[i][1].."-"..set[i][2] end return line end function SegmentSetInSet(set,sub) if sub==nil then return true end -- Checks if sub is a proper subset of set for i=1,#sub do if not SegmentRangeInSet(set,sub[i]) then return false end end return true end function SegmentRangeInSet(set,range) if range==nil or #range==0 then return true end local b=range[1] local e=range[2] for i=1,#set do if b>=set[i][1] and b<=set[i][2] then return (e<=set[i][2]) elseif e<=set[i][1] then return false end end return false end function SegmentSetToBool(set) local result={} for i=1,structure.GetCount() do result[i]=SegmentInSet(set,i) end return result end helptext="" -- for dialog --WARNING: no boolean allowed in matrix bellow (printintg boolean results in error). -- if you need to print booleans, first change your matrix to text matrix function SegmentMatrixToString(matrix, dimension, fieldD, field, recorD, record, printN) -- New BK 14/10/2014, 06/03/2019 tostring added local dimension=dimension or 1 -- the dimension of the matrix must be specified if not 1 (simple list) local fieldD=fieldD or ";" -- field delimiter for print local field=field or 1 -- if we decide only to print one field (field number) local recorD=recorD or "," -- record delimiter for print local record=record or nil -- if nil, we print all records local printN=printN or false local line = "" local matrix= matrix or {} if #matrix>0 then if record== nil then for i=1,#matrix do if i~=1 then line=line..recorD end -- add record delimiter unless for first record if printN then line=line.." "..i..") " end for j=1,dimension do line=line..tostring(matrix[i][j]) -- add data if j~=dimension then line=line..fieldD end -- add field delimiter unless for latest field end end else if printN then line=line..record..") " end for j=1,dimension do line=line..tostring(matrix[record][j]) -- add data if j~=dimension then line=line..fieldD end -- add field delimiter unless for latest field end end helptext="" helpdesk2=[[]] return line else helptext="" return "" end end -- this function can only report a line function SegmentPrintMatrix(matrix,dimension, fieldD, field, recorD, record, printN, display) -- New BK 14/10/2014 local matrix=matrix or {} local dimension=dimension or 1 -- the dimension of the matrix must be specified if not 1 (simple list) local fieldD=fieldD or ";" -- field delimiter for print local field=field or 1 -- if we decide only to print one field (field number) local recorD=recorD or "," -- record delimiter for print local record=record -- if nil, we print all records, or we print the record i local printN=printN or false local display=display or "list" -- can be "table" or "list" if display=="list" then -- prints all in one line print(SegmentMatrixToString(matrix,dimension, fieldD, field, recorD, record, printN)) elseif display=="table" then for i=1,#matrix do print(SegmentMatrixToString(matrix,dimension, fieldD, field, recorD, i, printN)) end end end --- End of Segment Set module ---START Get and print filter list function GetFilterList(printAll) -- returns a FilterTable with {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} local printAll= printAll or false local FilterTableResult={} local FilterBonus=0 FilterList=filter.GetNames() if printAll then print(#FilterList.." filters. Name, bonus, enabled, condition, weight:") end print("DEBUG1") for i= 1, #FilterList do -- {filter string, bonus, enabled, condition} local stringfilter=FilterList[i] -- string print("DEBUG1"..stringfilter) if stringfilter=="Move Count Limit" or stringfilter=="Exploration" then FilterBonus=0 else FilterBonus=filter.GetBonus(stringfilter) -- number end local FilterEnabled= filter.IsEnabled(stringfilter) -- BOOLEAN Is the filter Enabled local FilterCondition= filter.ConditionSatisfied(stringfilter) -- BOOLEAN Is the condition satisfied or the filter active local ThisFilterWeight=1 -- the specific weight for each filter table.insert(FilterTableResult,{stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight}) -- TO DO: keep and compare the best ones if printAll then print(FilterList[i].." : "..FilterBonus.." Enabld: "..tostring(FilterEnabled).." Met= "..tostring(FilterCondition).." Wght= "..ThisFilterWeight) end end return FilterTableResult -- returns a FilterTable with {filter string, bonus, enabled, condition, weight} end function printFilterScores(long) -- calculates a new global FilterTable as well local long= long or false FilterTable=GetFilterList(long) -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} TotalBonus=filter.GetBonusTotal() -- only used in FilersOK if long then print("Total Bonus= "..TotalBonus) end BestTotalBonus=TotalBonus -- init (only used in FilersOK) matrix=FilterTable dimension= 2 -- actually the number of colomns we'll print for a table fieldD=": +" recordD="," field=nil -- we don't select only one column record=nil -- we don't select only one line printN=true -- print the number of records --display= "list" -- all in one line display= "table" -- one record after the other (a table print) --SegmentPrintMatrix(matrix,dimension, fieldD, field, recorD, record, printN, display) end printFilterScores(true) -- inits to create reference FilterTable, empty if false, and TotalBonus ---END Get and print filter list ---START select Filters FilterWeight=1 EQUALIZED= false function GetParametersFilters () -- AARGH I don't succeed in checking the boxes with right default DialogFilter[i][3]!!! 06/03/2019 local dlogresult=9 local dlog = dialog.CreateDialog ( recipename ) local DialogFilter=FilterTable -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} local CountCheckedOnes = 0 repeat dlog.L1=dialog.AddLabel("Filters weighting:") DEBUGprint("Equalized = ".. tostring(EQUALIZED)) for i = 1, #DialogFilter do DEBUGprint("Dialog Init "..DialogFilter[i][1]..": ".. tostring(DialogFilter[i][3])..": ".. tostring(DialogFilter[i][4])..DialogFilter[i][5]) dlog[DialogFilter[i][1]]=dialog.AddCheckbox(DialogFilter[i][1], DialogFilter[i][3]) -- WARNING DialogFilter[i][1] must be a string ! don't use DialogFilter[i][3] here end -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} dlog.L2=dialog.AddLabel("------------") dlog.NeverDisableSomeFilters=dialog.AddCheckbox("Never disable selected ones", NeverDisableSomeFilters) dlog.NeverEnableSomeFilters=dialog.AddCheckbox("Never enable unselected ones (!?)", NeverEnableSomeFilters) dlog.L3=dialog.AddLabel("------------") dlog.L4=dialog.AddLabel("Priority to score or filter:") if not EQUALIZED then dlog.FilterWeight=dialog.AddSlider("Filters multiplyer", FilterWeight, 1, 100,0) end dlog.MaxLossIFG=dialog.AddSlider("Max score loss", MaxLossIFG, 0, MaxMaxLossIFG,0) dlog.OK = dialog.AddButton ( "OK" , 1 ) dlog.more= dialog.AddButton ( "Equalizer" , 2 ) dlog.Cancel = dialog.AddButton ( "Cancel" , 0 ) dlogresult = dialog.Show ( dlog ) -- BUG "VALUE MUST BE A STRING" IF see WARNING above ! if dlogresult > 0 then CountCheckedOnes = 0 for i = 1, #DialogFilter do DialogFilter[i][3]=dlog[DialogFilter[i][1]].value if DialogFilter[i][3] then filter.Enable(DialogFilter[i][1]) CountCheckedOnes=CountCheckedOnes+1 else filter.Disable(DialogFilter[i][1]) end DEBUGprint(DialogFilter[i][1], tostring(DialogFilter[i][3])) end NeverDisableSomeFilters=dlog.NeverDisableSomeFilters.value NeverEnableSomeFilters=dlog.NeverEnableSomeFilters.value MaxLossIFG=dlog.MaxLossIFG.value if not EQUALIZED then -- it doesn't work ! FilterWeight=dlog.FilterWeight.value end -- else 1 (no doubble weight) if CountCheckedOnes==#DialogFilter then AllFiltersTogether= true end end if dlogresult==2 then DialogFilter=GetParametersEqualizer (DialogFilter) end -- then return to here until dlogresult<2 -- do not end if result is anything but Cancel return DialogFilter end -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} function GetParametersEqualizer (DialogFilter) -- AARGH I don't succeed in checking the boxes with right default DialogFilter[i][3]!!! 06/03/2019 local dlogresult=9 local dlog = dialog.CreateDialog ( recipename ) local DialogFilter= DialogFilter repeat dlog.L1=dialog.AddLabel("Filters weighting:") DEBUGprint("") for i = 1, #DialogFilter do DEBUGprint("Dialog Init "..DialogFilter[i][1]..": ".. tostring(DialogFilter[i][3])..": ".. tostring(DialogFilter[i][4])..DialogFilter[i][5]) dlog[DialogFilter[i][1]]=dialog.AddSlider((DialogFilter[i][1]), DialogFilter[i][5],0,10,1) end -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} dlog.OK = dialog.AddButton ( "OK" , 1 ) dlogresult = dialog.Show ( dlog ) -- BUG "VALUE MUST BE A STRING" IF see WARNING above ! if dlogresult > 0 then for i = 1, #DialogFilter do DialogFilter[i][5]=dlog[DialogFilter[i][1]].value DEBUGprint(DialogFilter[i][1], DialogFilter[i][5]) if DialogFilter[i][5] ~= 1 then EQUALIZED = true end -- it doesn't work ! end end until dlogresult<2 return DialogFilter-- with weighting values added end -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} function SelectAndPrintFilters() InitialFilters=GetParametersFilters () -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} BestFilters=InitialFilters -- {stringfilter, FilterBonus, FilterEnabled, FilterCondition, ThisFilterWeight} SegmentPrintMatrix(InitialFilters,4, ": +", nil, ",", nil, true, "table") end if PROBABLEFILTER then SelectAndPrintFilters() -- initializes the filter matrix to InitialFilters and BestFilters as well as printing it end ---END select Filters --END FILTER SUBROUTINE --------+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function Score(filterstoo)--return score, exploration too, filter weighted score if true. WARNING local filterstoo = filterstoo or false-- WARNING, filters are nul if disabled !(weight cannot work on disabled) local result=0 local result0=result local filters = 0 local FilterList=FilterList if PROBABLEFILTER and filterstoo then filters=filter.GetBonusTotal() end if energy==true then result= current.GetEnergyScore() else result= current.GetScore() end result0=result if EQUALIZED and filterstoo then for i= 1, #FilterList do local FilterBonus=0 local stringfilter=FilterList[i] -- bonus x user weight for each filter if stringfilter=="Move Count Limit" or stringfilter=="Exploration" then FilterBonus=0 else FilterBonus=filter.GetBonus(stringfilter) -- number end local ThisFilterWeight=InitialFilters[i][5] --if FilterBonus==0 and ThisFilterWeight~= 1 then FilterBonus=1 end -- in order to give a weight to a non rewarding 0 filter result=result+FilterBonus * ThisFilterWeight DEBUGprint(FilterList[i]..": "..FilterWeight.." x "..FilterBonus.." x "..ThisFilterWeight) end end if FilterWeight > 1 then -- global weight only, or extra-weight !!! result= result + filters * (FilterWeight-1) -- only normal result with or without filters if not filterstoo end DEBUGprint("Score: "..result0.." Weighted: "..result) DEBUGprint ("Difference due to weights: ".. result-result0) return result end function FiltersOK() -- jump Qstab if total filter decreased if not PROBABLEFILTER then return true end -- otherwise we have a bug FiltersOn() local TotalBonus=filter.GetBonusTotal() local fg=TotalBonus-BestTotalBonus return2OriginalFilterSetting() if fg<0 then return false -- DEBUG else BestTotalBonus=TotalBonus return true end end bestScoreW=Score(true) -- INIT global score with overweight filters --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 CandidateHB= {} -- in order to limit mutate (of banding) to segments that are in the core of the complex sym. HbondMaxDistance= 16 -- its for symmetrics when branches are far away (seg to other seg), set 4 for seg to seg function getShortDistSym() -- 1 dim for speed, only the shorter distance is calculated (between same segments) if not SYMMETRIC then return end local iBand= 0 local distance= 0 HbondMaxDistance= 16 -- reinitializing at each step print("Calculating short distances to symmetrics... be patient it's SLOW !") local s= 1 -- it's not usefull to pass all symmetrics, distances are equal CandidateHB[0]= false for i=1,segCnt do --filling table for syms, only banding between same segments is usefull here (these are the smalest distances) iBand=band.AddBetweenSegments(i,i,0,0, s) -- adding a band to symmetrics for measuring distance -- (integer segmentIndex1, integer segmentIndex2, [integer atomIndex1], [integer atomIndex2], [integer symnr2]) distance=band.GetLength(iBand) if distance < HbondMaxDistance then HbondMaxDistance=distance + 1 if HbondMaxDistance < 7 then HbondMaxDistance = 7 end -- the case when symmetry is very close, "ideal" end band.Delete(iBand) if distance < HbondMaxDistance and distance > 3 then -- Hbond between end atom is 1.41 CandidateHB[i]= true -- seg i is a candidate for HB, it can be candidate because of sym 1 or sym 2 etc. DEBUGprint("seg".. i.." distance:"..distance) end end print("Done. Distance between syms: ".. HbondMaxDistance) end -- at the end, we have a list of bondable segments "if CandidateHB[x] then mutate to charged" function ProbabilityMutating(iter) -- favour certain AAs (e.g. charged ones for hbond puzzles), here respecting hydrophobicity by default local iter=iter or 1 DEBUGprint("Probability mutating") if HBONDING then for i = 1, segCnt do DEBUGprint("Mutating seg"..i) if selection.IsSelected(i) and CandidateHB[i] then recentbest.Save() -- TO DO : quicksaves because recentbest is already used in fuse !! local SS=structure.GetSecondaryStructure(i) local Hydrophobic= structure.IsHydrophobic(i) local beforeAA= structure.GetAminoAcid(i) local list = {} -- {'s','t','n','q','r','h','k','d','e','w','y'} -- charged if SS == "L" and Hydrophobic then list={} end if SS == "L" and not Hydrophobic then list={'s','n','h','d'} end -- h is a waste of time if SS == "E" and Hydrophobic then list={'y'} end -- {'w','y'} these are too big, it's a waste of time if SS == "E" and not Hydrophobic then list={'t'} end -- a waste of time if SS == "H" and Hydrophobic then list={} end if SS == "H" and not Hydrophobic then list={'q','k','e'} end -- helix phillix, unless "r" with 3 bonding atoms. k is long. for j =1, #list do structure.SetAminoAcid(i, list[j]) end recentbest.Restore() -- no shake etc, it's mimimalist ! local afterAA=structure.GetAminoAcid(i) if beforeAA ~= afterAA then print("Mutated seg"..i..": "..beforeAA.."->"..structure.GetAminoAcid(i)) end end end elseif NOHBONDING then for i = 1, segCnt do DEBUGprint("Mutating seg"..i) if selection.IsSelected(i) and CandidateHB[i] then recentbest.Save() -- TO DO : quicksaves because recentbest is already used in fuse !! local SS=structure.GetSecondaryStructure(i) local Hydrophobic= structure.IsHydrophobic(i) local beforeAA= structure.GetAminoAcid(i) local list = {} -- aaneutral= {'v','l','m','p','i','a','c','f','g'} -- non H binding if SS == "L" and Hydrophobic then list={'g','p'} end --aaloopphobic={'g','p'} if SS == "L" and not Hydrophobic then list={} end --aaloopphilic={'d','h','n','s'} if SS == "E" and Hydrophobic then list={'c','f','i','v'} end--aasheetphobic={'c','f','i','v','w','y'} if SS == "E" and not Hydrophobic then list={} end --aasheetphilic={'t'} if SS == "H" and Hydrophobic then list={'a','l','m'} end --aahelixphobic={'a','l','m'} if SS == "H" and not Hydrophobic then list={} end aahelixphilic={'e','k','q','r'} for j =1, #list do structure.SetAminoAcid(i, list[j]) end recentbest.Restore() -- no shake etc, it's mimimalist ! local afterAA=structure.GetAminoAcid(i) if beforeAA ~= afterAA then print("Mutated seg"..i..": "..beforeAA.."->"..structure.GetAminoAcid(i)) end end end else structure.MutateSidechainsSelected(iter) end end function Wiggle(how, iters, minppi, valit, mingps) -- NEW one, with filter management, 17/4/2016, SKETCHBOOK adaped 24/2/2020 if FILTERMANAGE then FiltersOff() end-- new BK 8/4/2013, always disable filter here. Keep the few ones active if not all selected in dialog. if how==nil then how="wa" end --WARNING: on filter disabled, weight doesn't work !! if iters==nil then iters=6 end if minppi==nil then minppi=0.1 end if valit==nil then valit= 1 end if SKETCHBOOK then valit = 30 end if mingps==nil then mingps= 80 end if iters>0 then startRecTime=os.clock () iters=iters-1 sp=Score(true) -- weighted if how == "s" then if FILTERMANAGE then return2OriginalFilterSetting() end -- new BK 8/4/2013, always back to user settings for s or m if mutateAlwas==true then if SKETCHBOOK then structure.MutateSidechainsSelected(3) else ProbabilityMutating(1) end --else structure.ShakeSidechainsSelected(1) end else if SKETCHBOOK then structure.ShakeSidechainsSelected(3) else QuickShake() end 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(true) -- weighted 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 then return Wiggle(how, iters, minppi, valit) end --tail call end end if FILTERMANAGE then return2OriginalFilterSetting() end -- new BK 10/10/2013, always back to user settings end function SaveBest() -- NEW version with overweight of filters 20/2/2019 local ScoreU=Score() local ScoreW=Score(true) local g=ScoreU-bestScore -- with or without unweighted filters local gW=ScoreW-bestScoreW if not (conditions and not current.AreConditionsMet()) and gW>=0 then --NEW, we don't keep if weighted filters decrease if g>0 + minGain - MaxLossIFG then -- Note: better not using mingain and MaxLossIFG together if g>0.01 then p("Gained another "..round(g).." pts.") end bestScore=ScoreU -- global score with or without normal filters bestScoreW=ScoreW --global score with overweight filters save.Quicksave(3) if g<0 then print("Cost of a bonus gain: ".. round(g).." pts. New score: "..round(bestScore)) end end else print("Conditions not met. Returning to former solution") -- for DEBUG end end function SaveRB() if recentbest.GetScore()>bestScore or (recentbest.GetEnergyScore()>bestScore and energy==true)then if not (conditions and not current.AreConditionsMet()) then save.Quicksave(4) recentbest.Restore() SaveBest() save.Quickload(4) end end end function Qstab() selection.SelectAll() CI(shakeCI) if mutateOnce==true then --structure.MutateSidechainsSelected(1) ProbabilityMutating(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...") local scr=Score() 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 i=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 i=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 length=random(bands.minUp,bands.maxUp) --debugged BK 15/2/2015, length cannot be 0 local theta = math.acos(math.random()) local phi = 2 * math.pi * math.random() local segmentXAxis=0 local segmentYAxis=0 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, length, theta, phi, str} break end if cnt>segCnt*3 then --there is still some probability to crash p("Sorry! Cant create band! Breaking script!") BreakScript() --there is no such function, so it crashes script end end return b 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 CanBeUsed(sg1) --checking end of bands if structure.IsLocked(sg1) then return false end -- impossible to move locked segment in space 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 local ok=true if #DoNotUse>0 then --none of 2 can be in that area for i=1, #DoNotUse do local r=DoNotUse[i] -- r={from,to} for x=r[1],r[2] do if x==sg1 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 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 if ssCheck(structure.GetSecondaryStructure(sg1)) then ok=true end end return ok end function ScoreHerd() --score all critters from herd. EXPERIMENTAL: weighted scores save.Quickload(3) p("Scoring "..#critters.." critters...") save.Quicksave(5) local herdScore=Score(true) for i=1,#critters do --band.DeleteAll() deletebands() local crt=critters[i] --critter local s=Score(true) --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() if HASLIGAND then Wiggle("wa",1) else Wiggle("wb",1) end --band.DeleteAll() deletebands() CI(1) if s-Score(true) > qstabThresh and FiltersOK() then -- NEW testing if filters nok, jump this Qstab() else Wiggle() end if Score()-bestScore>fuzeThresh and FiltersOK() then SaveRB() Fuze() else SaveRB() end crt.score=Score(true)-s --p("Critter "..crt.name.." : "..round(crt.score).." pts.") if critter.maxLoss>0 then if Score(true)>herdScore-critter.maxLoss then save.Quicksave(5) herdScore=Score(true) 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() 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) 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() 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 critterID=0 gen=0 ss=Score() bestScore=ss save.Quicksave(3) recentbest.Save() p("Rav3n_pl Bands! Bands in space! GAB BiS") p("Start score: "..round(ss)) if energy then energy=false ssNormal=Score() p("Normal score: "..round(ssNormal).. " Conditions= "..ss-ssNormal) energy=true end critters={} FillHerd() badGen=0 ssstr=(ssstr..round(ss)) -- jeff101 while true do --this is (almost) endless script ;] undo.SetUndo(false) -- reset each loop if gain will give a long list of interesting undos genScore=Score() gen=gen+1 ui.CenterViewport() p() p("Generation: "..gen..", score: "..round(Score())..", gain: "..round(Score()-ss)) ShuffleHerd() ScoreHerd() -- weighted (EXPERIMENTAL) save.Quickload(3) if gen==herd.maxGen then break end --end of script if genScore>=Score() then badGen=badGen+1 else badGen=0 end -- bug fixed thanks to robgee if badGen>=herd.renew then p("Creating fresh random herd...") critters={} FillHerd() badGen=0 else BreedHerd() end -- START jeff101's display 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)) --END jeff101's display --3a) COPY from here --------------- loop_count=gen SetNote(note_number, starting_score, recipename, loop_count) -- WARNING: and mach "recipename" and "loop_count" with the names of the recipe --3b) COPY to here -------------- SaveBigSteps() -- 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 start,stop,line,msg=err:find(":(%d+):%s()") err=err:sub(msg,#err) print('---') if err:find('Cancelled')~=nil then print("User stop.") else print("unexpected error detected.") --p("Error line: %i.") --p("Error : %s.") p("Error line: ", line) p("Error: ", err) end print("Restoring CI, best result, filter and structures") CI(1) undo.SetUndo(true) if FILTERMANAGE then return2OriginalFilterSetting() end -- always back to user settings StoreBigStep() MovieSteps() save.Quickload(3) --3a) COPY from here --------------- loop_count=gen SetNote(note_number, starting_score, recipename, loop_count) -- WARNING: and mach "recipename" and "loop_count" with the names of the recipe --3b) COPY to here -------------- deletebands() -- WARNING must be defined anywhere !! print(err) ui.CenterViewport() 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) -- will be better on on exploration puzzles opt.mutonly=dialog.AddCheckbox("Only mutable", onlyMutable) opt.mutonce=dialog.AddCheckbox("Mutate once (selected)", mutateOnce) opt.mutalways=dialog.AddCheckbox("Mutate always (selected)", mutateAlwas) opt.lbl6 = dialog.AddLabel("Note: never mutate all") opt.fuzeth=dialog.AddTextbox("Fuze threshold: ",fuzeThresh) opt.qsth=dialog.AddTextbox("Qstab threshold: ",qstabThresh) if PROBABLEHBOND then opt.HBONDING=dialog.AddCheckbox("Only Hbonding AAs", HBONDING) opt.NOHBONDING=dialog.AddCheckbox("Or only not Hbonding AAs", NOHBONDING) end if HASLIGAND then opt.AlwaysUseLigand=dialog.AddCheckbox("Always use ligand: ",AlwaysUseLigand) end if HASLOCKED then AlwaysUseUnlocked=true opt.AlwaysUseUnlocked=dialog.AddCheckbox("Always use unlocked: ",AlwaysUseUnlocked) end if SKETCHBOOK then opt.minGain= dialog.AddSlider("Min gain/it.", minGain, 0, 50, 1) end if EXPLORATION then opt.conditions=dialog.AddCheckbox("Check conditions", conditions) end if PROBABLEFILTER then opt.FILTERMANAGE=dialog.AddCheckbox("Fast filter during wiggle only: ",FILTERMANAGE) opt.GENERICFILTER=dialog.AddCheckbox("Fast filter unless for score: ",GENERICFILTER) opt.lbl5 = dialog.AddLabel("Warning: no weight during fast filter") end 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 PROBABLEHBOND then HBONDING=opt.HBONDING.value NOHBONDING=opt.NOHBONDING.value end if HASLIGAND then AlwaysUseLigand=opt.AlwaysUseLigand.value DoAlwaysUseLigand() end if HASLOCKED then AlwaysUseUnlocked=opt.AlwaysUseUnlocked.value DoAlwaysUseUnlocked() end if SKETCHBOOK then minGain=opt.minGain.value end if PROBABLEFILTER then FILTERMANAGE=opt.FILTERMANAGE.value GENERICFILTER=opt.GENERICFILTER.value end if EXPLORATION then conditions=opt.conditions.value end 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 hers", herd.renew, 1, 10, 0) opt.shuff=dialog.AddCheckbox("Shuffle critters", herd.shuffle) opt.lbl2 = dialog.AddLabel("Critter:") opt.minb=dialog.AddSlider("Minimum bands:", critter.minBands, 1,4,0) opt.maxb=dialog.AddSlider("Maximum bands:", critter.maxBands,4,50,0) opt.keeps=dialog.AddSlider("Keep score:", critter.keepScore, -10, 10, 0) opt.breeds=dialog.AddSlider("Breed score:", critter.breedScore, -40, 10,0) opt.maxloss=dialog.AddSlider("Max loss:", critter.maxLoss, 0,50,0) opt.lbl4 = dialog.AddLabel("(0 to disable max loss)") opt.lbl3 = dialog.AddLabel("Bands:") opt.minst=dialog.AddSlider("Min str", bands.minStr, 0.1, 2, 1) opt.maxst=dialog.AddSlider("Max str", bands.maxStr, 0.2, 2, 1) opt.maxup=dialog.AddSlider("Max lenght", bands.maxUp, 1, 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 allsegmentset={{1,segCnt2}} unlockedset=SegmentSetMinus(allsegmentset,SegmentListToSet(lockedlist)) AlwaysUse=SegmentJoinSet(unlockedset,allsegmentset) -- main call function MAIN() dialogOptions() getShortDistSym() GenericFilterMngt() GAB() end xpcall(MAIN,Cleanup) --end of script

Comments