Code
--[[------------------------------------------------------------------------------------------------
nblhinge 3.4
Author: Bruno Kestemont from KarenCH, nicobul & pauldunn"
NBL_hinge
Author: Nicobul2 - april 2014
Contributors: Ch Garnier, Yoyo, Bruno Kestemont
May 2014 v1.3: BK added Fuze Using Cuts by Go Science (pauldunn & Bruno Kestemont)
June 2014 v2: BK added Cut & Wiggle everything on the start
v2.1: when no gain=> starts 100 FUC then continue nblh
v3.1: looping CW+bklh+fuc
v3.3: filter management copied from porky 4/1/2014
v3.3.2 bug early end loop 1
v3.3.3 added option (and default) starting with FUC (it seems to give a better yield), 14/6/2015
+ added notes
v3.3.4 Filter management is now optional (some times, it's good to keep filters)
FUC limits = number of segments (better to do all of them, not more)
v3.3.5 fixed unideal loop bug
v3.4 added some Wiggle Power functions
Original recipe: Glycine hinge by Tlaloc (LUA v1)
Converted from v1 lua by Rav3n_pl v1 to v2 converter
Copyright (C) 2011 tlaloc <http://fold.it/portal/user/57765>
Copyright (C) 2011 rav3n_pl <http://fold.it/portal/user/174969>
Copyright (C) 2011 Seagat2011 <http://fold.it/port/user/1992490>
Copyright (C) 2011 thom001 <http://fold.it/port/user/172510>
Copyright (C) 2014 Bruno Kestemont <http://fold.it/port/user/447652>
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/>.
--]]
recipename="nblhinge 3.4 by Bruno Kestemont, KarenCH, nicobul & pauldunn"
--identifying filtered puzzles and all properties
OriginalFilterSetting = behavior.GetFiltersDisabled()
OriginalWPowerSetting = behavior.GetWigglePower()
PROBABLEFILTER= false
GENERICFILTER=false
FILTERMANAGE= false
NEGATIVEFILTER= false -- true= big preference for filter growth (on the cost of score) new 15/4/2015
HASMUTABLE= false
IDEALCHECK= false
PROBABLESYM= false
SEPSIS= false
ELECTRON= false
DISULFIDEBONUS= false -- NOT USED
CENTROID= false
HOTSPOT= false
HANDFOLD=false -- identifies recipes just after a hand fold (necessity to protect the HF design)
sym=1
-- 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 detectfilterandmut() -- new BK 10/10/2013; 13/2/2015
local descrTxt=puzzle.GetDescription()
local puzzletitle=puzzle.GetName()
if #descrTxt>0 and (descrTxt:find("filter") or descrTxt:find("filters")) 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("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("Tetramer") then sym=3
elseif puzzletitle:find("Dimer of Dimers") or puzzletitle:find("Tetramer") then sym=4
elseif puzzletitle:find("Pentamer") then sym=5
else sym=6
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"))
and not (descrTxt:find("Dimer of Dimers") or descrTxt:find("dimer of dimers")) then sym=2
elseif descrTxt:find("Trimer") or descrTxt:find("trimer") then sym=3
elseif (descrTxt:find("Dimer of Dimers") or descrTxt:find("Tetramer"))
and not (descrTxt:find("dimer of dimers") or descrTxt:find("tetramer"))then sym=4
elseif descrTxt:find("Pentamer") or descrTxt:find("pentamer") then sym=5
else sym=6
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()
--SRART Generic Filter management By BistPawn
-- 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 behavior.GetSlowFiltersDisabled() then
behavior.SetSlowFiltersDisabled(false)
end
end
function FiltersOff()
if behavior.GetSlowFiltersDisabled()==false then
behavior.SetSlowFiltersDisabled(true)
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:
--[[
MutClass(structure, false)
MutClass(band, false)
MutClass(current, true)
]]--
--STOP Generic Filter management By BistPawn
--START SET NOTES BY PD
--[[ Set note with author, recipe and big steps -- By Pauldunn
module to paste it in existing recipe, by BK
]]--
--HOW TO include in a recipe?
--1a) COPY 1 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 mach "recipename" with the recipename of the recipe
--1b) COPY 1 to here. ================
--2) PASTE 1 somewhere to the beginning of your recipe.
-- see Set Notes B bellow for activation
local _options = {
--- User Options Begin ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
wiggle_count = 1, -- #iters (flex)
wiggle_out_count = 30, -- #iters (unflex)
band_strength = 0.25, -- band strength
allow_float_wiggle_count = false, -- allows "floating" via random number generation of wiggle_count
wiggle_count_upper = wiggle_count, -- max possible #iters. iff allow_float_wiggle_count, then this value must be defined. (disabled by default)
wiggle_count_lower = wiggle_count, -- min possible #iters. iff allow_float_wiggle_count, then this value must be defined. (disabled by default)
wiggle_count_bounds = wiggle_count, -- allowed variance for #iters. iff allow_float_wiggle_count, then this value must be defined. (disabled by default)
global_wiggle = true, -- perform wa. iff false, then perform lws (local_wiggle)
freeze_backbone = true, -- freeze bb
freeze_sidechains = false, -- freeze sc (disabled by default)
ci = 0.30, -- clashing importance
allow_ci_float = false, -- allows "floating" via random number generation of ci. Iff true, ci_upper and ci_lower must be defined. (disabled by default)
ci_upper = ci, -- U_ci_value. iff allow_ci_float == true, then this value must be defined. (disabled by default)
ci_lower = ci, -- L_ci_value. iff allow_ci_float == true, then this value must be defined. (disabled by default)
ci_bounds = ci, -- allowed variance for ci. ff allow_ci_float == true, then this value must be defined. (disabled by default)
qs_recent_best = 3, -- iff exploratory == true, then recent best is saved into this saveslot
freeze_hinge_instead = false, -- allows for the hinge to be frozen instead of the rods. (disabled by default)
--- User Options End ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
score = 0,
ranked_score = 0,
multiplier = 0,
}
flag = {selected = false, mutate = false}
uo = {mutateAlways = false}
function down(x)
return x-x%1
end
function SegmentListToSet(list) -- retirer doublons
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) -- faire une liste a partir d'une zone
local result={}
for i=1,#set do
--print(set[i][1],set[i][2])
for k=set[i][1],set[i][2] do
result[#result+1]=k
end
end
return result
end
function SegmentCleanSet(set)
-- Makes it well formed
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) -- verifier si segment est dans la liste
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) --verifie si segment est dans la zone
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) -- fusionner 2 listes de segments
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) --fusionner (ajouter) 2 zones
return SegmentListToSet(SegmentJoinList(SegmentSetToList(set1),SegmentSetToList(set2)))
end
function SegmentCommList(list1,list2) -- chercher intersection de 2 listes
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) -- intersection de 2 zones
return SegmentListToSet(SegmentCommList(SegmentSetToList(set1),SegmentSetToList(set2)))
end
function SegmentSetMinus(set1,set2)
return SegmentCommSet(set1,SegmentInvertSet(set2))
end
function SegmentPrintSet(set)
print(SegmentSetToString(set))
end
function SegmentPrintListToSet(list) -- NEW BK 14/04/2014 prints a list in a set format
SegmentPrintSet(SegmentListToSet(list))
end
function SegmentSetToString(set) -- pour pouvoir imprimer
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)--verifier si zone est dans suite
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) -- vrai ou faux pour chaque segment utilisable ou non
local result={}
for i=1,structure.GetCount() do
result[i]=SegmentInSet(set,i)
end
return result
end
--- End of Segment Set module
function InitWORKONbool()
WORKONbool=SegmentSetToBool(WORKON)
end
function Zone(zStart, zEnd, hw, prot, options) -- seg start & segend are not necesserally first and last segments
for i=zStart, zEnd do
j=WORKONBIS[i] -- NEW 24/9/2013 to be able to treat segments in any order defined in WORKON
nbl_hinge(j, hw, prot, options)
--SaveBestMaaa()
end
end
function ShuffleTable(tab) --randomize order of elements
local cnt=#tab
for i=1,cnt do
local r=math.random(cnt)
tab[i],tab[r]=tab[r],tab[i]
end
return tab
end
local function _floor ( n )
return n - n%0.01
end
local function _floor2 ( n,c )
return n - n%c
end
local _math = {
_random = random,
_random2 = random,
_floor = _floor,
_floor2 = _floor2,
}
local _saveslots = {
max = 10, --#savelots available
}
local function get_value ( m, l, u ) --> mean, lower, upper
local upper
local lower
upper = m+u
lower = m-l
return math._random (lower,upper)
end
local function get_value2 ( m, b ) --> mean, bounds (symmetrical)
local upper
local lower
upper = m+b
lower = m-b
return math._random (lower,upper)
end
local _prot = { -- READ ONLY
L_idx = 1, -- end of left-hand side rod
L_idx2 = 1, -- beginning of left-hand side rod
R_idx = 1, -- beginning of right-hand side rod
R_idx2 = 1, -- end of right-hand side rod
n = 1, -- local index (SS temp)
k = 1, -- segment_count
next_group = 0, -- local index
rebuild_forward = true, -- direction indicator. true = right-side; false = left-side
bands_enabled = true,
}
local function get_ss_group(r)
local tmp
while ( 1 ) do
if r.rebuild_forward == true then
tmp = structure.GetSecondaryStructure(r.R_idx2)
else
tmp = structure.GetSecondaryStructure(r.L_idx)
end
if tmp == r.n then
if r.rebuild_forward == true then
if r.R_idx2 < r.k then
r.R_idx2 = r.R_idx2 + 1
else
r.R_idx2 = r.k
break
end
else
if r.L_idx > 1 then
r.L_idx = r.L_idx - 1
else
r.L_idx = 1
break
end
end
else
if r.rebuild_forward == true then
r.next_group = r.R_idx2
r.R_idx2 = r.R_idx2 - 1
else
r.next_group = r.L_idx
r.L_idx = r.L_idx + 1
end
break
end
end -- while ( 1 )
return r
end
local function build_hinge(prot,options,i,hw)
local glycine_idx
prot.k = structure.GetCount()
glycine_idx = i
-- (internally) focus on the right side..
prot.R_idx2 = glycine_idx + 1 + hw
prot.R_idx = glycine_idx + hw
prot.rebuild_forward = true
prot.n = structure.GetSecondaryStructure(glycine_idx + 1 )
prot = get_ss_group(prot )
-- (internally) focus on the left side..
prot.L_idx = glycine_idx - 2
prot.L_idx2 = glycine_idx - 1
prot.rebuild_forward = false
prot.n = structure.GetSecondaryStructure(glycine_idx - 1 )
prot = get_ss_group(prot )
return prot
end
local function save_recent_best(options )
-- if ( options.exploratory == true ) then
-- save.Quicksave(options.qs_recent_best )
-- else
recentbest.Save()
-- end
end
local function recall_recent_best(options )
-- if ( options.exploratory == true ) then
-- save.Quickload(options.qs_recent_best )
-- else
recentbest.Restore()
-- end
end
function ncWiggle(zone, iters, iter) -- now with FILTERMANAGE 22/12/2015
how = "wa"
iters = iters or 1
iter = iter or 1
local step = .001
local ws = 0
--if flag.selected then ws = ws+1 end
if uo.mutateAlways or flag.mutate then ws = ws+10 end
function wShake()
if ws==0 then structure.ShakeSidechainsAll(1)
--elseif ws==1 then structure.ShakeSidechainsSelected(1)
elseif ws==10 then structure.MutateSidechainsAll(1)
--elseif ws==11 then structure.MutateSidechainsSelected(1)
end
end
function wWiggle()
local b, s = true, true
if how=='wb' then s = false end
if FILTERMANAGE then behavior.SetFiltersDisabled(true) end-- new BK 8/5/2013, always disable filter here
--if ws==1 then
--structure.WiggleSelected(iters, b, s)
--else
if zone=='a' then
structure.WiggleAll(iters, b, s)
else
structure.LocalWiggleAll(iters, b, s)
end
--end
if FILTERMANAGE then behavior.SetFiltersDisabled(OriginalFilterSetting) end -- new BK 8/5/2013, always back to user settings
end
if how=='s' then
local sp = current.GetScore()
wShake()
if (current.GetScore()-sp)>(step*(1+iter)) then
wShake()
end
else
local sp = current.GetScore()
wWiggle()
if (current.GetScore()-sp)>(step*(1+iter)) then
ncWiggle(how, iters+1, iter+1)
end
end
end
local function wiggle(prot,options )
local do_wiggle
local iter
-- establish if this is a global or local operation
if ( options.global_wiggle == true ) then
do_wiggle = ncWiggle('a')
else
do_wiggle = ncWiggle('l')
end
-- establish how to execute wiggle
if ( options.allow_float_wiggle_count == true ) then
local mean
local upper
local lower
local bounds
mean = options.wiggle_count
upper = options.wiggle_count_upper
lower = options.wiggle_count_lower
bounds = options.wiggle_count_bounds
iter = get_value2(mean,bounds )
--iter = get_value ( mean, lower, upper )
else
if ( prot.bands_enabled ) then -- are we flexing ?
iter = options.wiggle_count
else
iter = options.wiggle_out_count
end
end
if ( options.verbose == true ) then
-- print ( "Performing Wiggle | iters = ", iter )
end
ncWiggle('a', iters, iter)
end
local function show_score(options )
local s
local gn
gn = ""
if ( options.exploratory == true ) then
s = current.GetScore()
local n = {
[true] = "Yes",
[false] = "No",
}
print ( "Stabilization Score = ", current.GetEnergyScore())
print ( "Ranking score = ", current.GetScore())
print ( "Multiplier: ", current.GetExplorationMultiplier() )
print ( "Conditions met: ", n [current.AreConditionsMet()] )
if ( s > options.ranked_score ) then
save.Quicksave(options.qs_recent_best )
if ( options.ranked_score ~= 0 ) then
local gain = s-options.ranked_score
gn = " + "..gain
end
options.score = current.GetEnergyScore()
options.ranked_score = s
options.multiplier = current.GetExplorationMultiplier()
end
print ( "Ranking Score = ", s..gn )
print ("")
else
s = current.GetEnergyScore()
if ( s > options.score ) then
if ( options.score ~= 0 ) then
local gain = s-options.score
gn = " + "..gain
end
options.score = s
end
print ( "Score = ", s..gn )
--print ("")
end
return options
end
local function freeze_rods(prot,options )
local r_idx
local r_idx2
local l_idx
local l_idx2
local freeze_sc
local freeze_bb
selection.DeselectAll()
r_idx = prot.R_idx
r_idx2 = prot.R_idx2
l_idx = prot.L_idx
l_idx2 = prot.L_idx2
freeze_sc = options.freeze_sidechains
freeze_bb = options.freeze_backbone
selection.SelectRange(r_idx,r_idx2 )
selection.SelectRange(l_idx,l_idx2 )
if ( options.verbose == true ) then
local _s = {
[true] = "true",
[false] = "false",
}
-- print ( "Freezing backbone.." )
-- print ( "backbone = ", _s [freeze_bb] )
-- print ( "sidechains = ", _s [freeze_sc] )
end
freeze.FreezeSelected(freeze_bb, freeze_sc )
selection.SelectAll()
end
local function rod_add_bands(prot,options )
local idx
local idx2
local str
local k
idx = prot.R_idx
idx2 = prot.L_idx2
k = structure.GetCount() + 1
str = options.band_strength
if ( options.verbose == true ) then
-- print ( "Placing bands.." )
-- print ( "Setting band strength: ", str )
end
for i = 0,3 do
local n
local n2
n = idx + i
n2 = idx2 - i
if (( n < k ) and ( n2 > 0 )) then
band.AddBetweenSegments(n,n2 )
band.SetStrength(i+1,str )
end
end
end
local function set_clash_importance(options )
local ci
if ( options.allow_ci_float == true ) then
local mean
local upper
local lower
local bounds
mean = options.ci
upper = options.ci_upper
lower = options.ci_lower
bounds = options.ci_bounds
ci = get_value2(mean,bounds )
--ci = get_value(mean, lower, upper )
else
ci = options.ci
end
if ( options.verbose == true ) then
--print ( "Setting clash importance: ", ci )
end
behavior.SetClashImportance(ci )
end
local function reset_clash_importance(options )
if ( options.verbose == true ) then
-- print ( "Resetting clash importance: ", 1 )
end
behavior.SetClashImportance(1)
end
local function turn_bands_on(prot, options )
if ( options.verbose == true ) then
--print ( "Enabling bands.." )
end
band.EnableAll()
prot.bands_enabled = true
set_clash_importance(options )
return prot
end
local function turn_bands_off(prot, options )
if ( options.verbose == true ) then
--print ( "Disabling bands.." )
end
band.DisableAll()
prot.bands_enabled = false
reset_clash_importance ( options )
return prot
end
local function unfreeze_rods(prot,options )
freeze.UnfreezeAll()
end
local function freeze_hinge(prot,options )
local glycine_idx
local freeze_bb
local freeze_sc
selection.DeselectAll()
glycine_idx = glycine_locator(prot,options )
freeze_sc = options.freeze_sidechains
freeze_bb = options.freeze_backbone
selection.Select(glycine_idx )
freeze.FreezeSelected(freeze_bb,freeze_sc )
selection.SelectAll()
end
local function unfreeze_hinge(prot,options )
freeze.UnfreezeAll()
end
local function check_preconditions(prot, options )
if options.freeze_hinge_instead == true then
turn_bands_on(options )
wiggle(prot,options )
turn_bands_off(options )
unfreeze_rods(prot,options )
freeze_hinge(prot,options )
end
end
function nbl_hinge(seg, hw, prot, options)
if (hw==1) then
print ("Segment: " .. seg)
else
print ("Segments: " .. seg .. "-" .. seg+hw-1)
end
prot = build_hinge(prot, options, seg, hw)
freeze_rods(prot, options )
rod_add_bands(prot, options )
save_recent_best(options )
check_preconditions(prot, options )
prot = turn_bands_on(prot, options )
wiggle(prot, options )
prot = turn_bands_off(prot, options )
wiggle(prot, options )
recall_recent_best(options )
options = show_score(options )
freeze.UnfreezeAll()
band.DeleteAll()
end
function Checknums(nums)
-- Now checking
if #nums%2 ~= 0 then
print("Not an even number of segments found")
return false
end
for i=1,#nums do
if nums[i]==0 or nums[i]>structure.GetCount() then
print("Number "..nums[i].." is not a segment")
return false
end
end
return true
end
function ReadSegmentSet(data)
local nums = {}
local NoNegatives='%d+' -- - is not part of a number
local result={}
for v in string.gfind(data,NoNegatives) do
table.insert(nums, tonumber(v))
end
if Checknums(nums) then
for i=1,#nums/2 do
result[i]={nums[2*i-1],nums[2*i]}
end
result=SegmentCleanSet(result)
else Errfound=true result={} end
return result
end
function bkh(hinge_width, prot, options)
--print ("Segs aleatoires")
print("------------------------------")
print()
print("NBL_hinge by nicobul2")
print ("Random segs")
compteur=0 -- intialise le compteur de WORKONBIS
p=print --"quicker" print
segCnt=structure.GetCount()
--segCnt=segCnt-1 -- for lingard puzzles only! sera initialise par seglock
flagligand=false
segCnt2=segCnt -- cas de ligands
segStart = range_min
segEnd = range_max
while structure.GetSecondaryStructure(segCnt2)=="M" do segCnt2=segCnt2-1 flagligand=true end
WORKON={{1,segCnt2}} --BK16/04/2014
WORKONBIS={}
for i = segStart, segEnd do
compteur=compteur+1
WORKONBIS[compteur]=i
end
ShuffleTable(WORKONBIS) -- NEW 24/9/2013 mix the segment table randomly
si=current.GetScore()
--print ("Score initial: " .. si)
print ("Starting score: " .. si)
for run = 1, nbrun do -- NEW 24/06/2014
if (run > 1) then
rci = math.random() / 5
options.ci = ici + rci - 0.1
rbs = math.random() / 10
options.band_strength = ibs + rbs - 0.05
end
print()
--print ("Boucle " .. run .. " sur " .. nbrun)
print ("Loop " .. run .. " of " .. nbrun)
local sl=current.GetScore()
print("Score: "..r3(current.GetScore()))
Zone(1, #WORKONBIS, hinge_width, prot, options)
if current.GetScore()-sl < 1 and keep_FUC then -- NEW BK 21/05/2014, if nblh does not yield, start 10 FUC before continuing next loop
print("Small gain => running Fuze using Cuts")
print("---------------------------------------------")
local weightedrounds=down(80/segCnt2*50) -- will be less for long puzzles
FUC(weightedrounds) -- will be 80 times for a small puzzle of 50 residues, 20 times for 200 residues
elseif current.GetScore()-sl < 10 and keep_FUC then
FUC(10)
elseif run==nbrun and keep_FUC then -- if big gain on latest loop, still some FUC
FUC(20)
end
end
end
function nblh(hinge_width, prot, options)
for run = 1, nbrun do
if (run > 1) then
rci = math.random() / 5
options.ci = ici + rci - 0.1
rbs = math.random() / 10
options.band_strength = ibs + rbs - 0.05
end
print("------------------------------")
print()
print("NBL_hinge by nicobul2")
--print ("Boucle " .. run .. " sur " .. nbrun)
print ("Loop " .. run .. " of " .. nbrun)
print ("CI " .. options.ci)
print ("Band strength " .. options.band_strength)
local si=current.GetScore()
--print ("Score initial: " .. si)
print ("Starting score: " .. si)
for i=range_min, range_max do
nbl_hinge(i, hinge_width, prot, options)
end
print ("Gain: " .. current.GetScore()-si)
if current.GetScore()-sl < 1 then -- NEW BK 21/05/2014, if nblh does not yield, start 20 FUC
print("Small gain => running Fuze using Cuts")
print("---------------------------------------------")
FUC(20)
end
--print ("Gain total: " .. current.GetScore()-startscore)
print ("Total gain: " .. current.GetScore()-startscore)
end
end
----------------------------------------------------------------------------------------
--MAIN
----------------------------------------------------------------------------------------
function MAIN() -- dialog is here
local prot
local options
print ( recipename )
options = _options
prot = _prot
ici = options.ci
ibs = options.band_strength
math.randomseed(os.time()%1000000)
math.random(100)
freeze.UnfreezeAll()
band.DeleteAll()
startscore=current.GetScore()
sc = structure.GetCount()
range_min = 3
range_max = sc-3
local MaxFUC=sc
if not CheckWP() then return end
local ask = dialog.CreateDialog("nbl_hinge")
--ask.hinge_width = dialog.AddSlider("Taille charnieres: ",1,1,2,0)
ask.hinge_width = dialog.AddSlider("Hinges size: ",2,1,2,0)
--ask.keep_trying = dialog.AddCheckbox("Toute la nuit ", true)
ask.keep_trying = dialog.AddCheckbox("Keep trying nblh 3 times", true)
ask.Start_FUC = dialog.AddSlider("Nb Fuse Using Cuts at start", down(MaxFUC/2),0,MaxFUC,0)
ask.keep_FUC = dialog.AddCheckbox("Some Fuse Using Cuts between nblh rounds", true)
--ask.random = dialog.AddCheckbox("Segs aleatoires ", false)
ask.random = dialog.AddCheckbox("Random ", true)
--ask.range = dialog.AddTextbox("Zone forcee", "")
ask.range = dialog.AddTextbox("Range (e.g. 2-9)", "")
if PROBABLEFILTER then
ask.FILTERMANAGE = dialog.AddCheckbox("Disable filter on deep wiggle only", FILTERMANAGE)
ask.GENERICFILTER = dialog.AddCheckbox("Disable filter unless for score", GENERICFILTER)
end
ask.OK = dialog.AddButton("OK",1)
ask.Cancel = dialog.AddButton("Cancel",0)
if (dialog.Show(ask) > 0) then
hinge_width = ask.hinge_width.value
keep_trying = ask.keep_trying.value
rrandom = ask.random.value
keep_FUC=ask.keep_FUC.value
Start_FUC=ask.Start_FUC.value
if (ask.range.value ~= "") then
local rangetext=ask.range.value
local rangelist=ReadSegmentSet(rangetext)
if not Errfound then
range_min = rangelist[1][1]
if (range_min<3) then range_min = 3 end
range_max = rangelist[1][2]
if (range_max > sc-3) then range_max = sc-3 end
else
print ("Error in range, using default")
end
end
if PROBABLEFILTER then
FILTERMANAGE = ask.FILTERMANAGE.value
GENERICFILTER = ask.GENERICFILTER.value
end
else
Exit()
end
if GENERICFILTER then
MutClass(structure, false)
MutClass(band, true)
MutClass(current, true)
if FILTERMANAGE then FILTERMANAGE=false end -- would be duplicate
end
if keep_trying then
nbrun = 3
else
nbrun=1
end
-- first loop FUC will start in CW
CWEparam() -- Cut&Wiggle before (including ask its options) including FUC at start
if rrandom then -- now nblh starts here
bkh(hinge_width, prot, options)
else
nblh(hinge_width, prot, options)
end
mainloop=1
for i=1, 1000000 do -- almost infinite run from now
mainloop=mainloop+1
print("#######################")
print("Main loop"..mainloop)
if mainloop==3 or mainloop==6 or mainloop==9 or mainloop==12 then
behavior.SetWigglePower(a)
print("Changing Wiggle Power to "..DisplayLongWigglePower ())
elseif mainloop == 4 or mainloop==7 or mainloop==10 or mainloop==13 then
behavior.SetWigglePower(OriginalWPowerSetting)
print("Changing Wiggle Power to "..DisplayLongWigglePower ())
end
print("CWE")
CWE() --second turn CW
if hinge_width==1 then hinge_width=2 else hinge_width=1 end
bkh(hinge_width, prot, options) -- second turn nblh2 including FUC
Low2High() -- some times L2H seems to gain 1 point
if i>10 then
FUC(MaxFUC-30) -- always
else
FUC(30)
end
-------------------
--Set Notes B
--3a) COPY 2 from here ---------------
SetNote(note_number, starting_score, recipename, loop_count) -- WARNING: and mach "recipename" and "loop_count" with the names of the recipe
--3b) COPY 2 to here --------------
--4) PASTE 2 at the end of the main loop function of your recipe, at the end of the cleanup function, at the end of the recipe
--better loop_count a global variable
--END SET NOTES BY PD
end
end
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
--[[FUZE Using Cuts by pauldunn (ONLY used in bk random mode)
v1.1 fixed uncut bug by B.Kestemont
]]--
--loopcount=10 -- 100 times, then continnues with nblh loops
ci=behavior.SetClashImportance
wiggleFUC=structure.WiggleAll
cutFUC=structure.InsertCut
kOriginalStructureOrNewBest = 1 -- the starting structure, or any subsequent improvement, will be stored in this quicksave slot
function r3 ( i )
-- printing convenience
return i - i % 0.001
end
function Score()
return current.GetEnergyScore()
end
function uncut(seg) -- new BK 15/05/2014
for i=1, structure.GetCount() do
structure.DeleteCut(seg)
end
end
function scorebest()
if ( Score() > best_score ) then
best_score = Score()
print ( ">>> Improvement to ".. r3 ( best_score ) )
save.Quicksave ( kOriginalStructureOrNewBest )
end
end
function FUC(loopcount)
local loopcount=loopcount or 10
print ( "Fuze Using Cuts by pauldunn" )
format=string.format
print(format("current score: %.3f",current.GetScore()))
math.randomseed(os.clock())
math.random()
--recentbest.Save()
save.Quicksave ( kOriginalStructureOrNewBest )
best_score = Score()
startScore=Score()
--print ( "Start score " .. r3 ( best_score ) )
for loop=1,loopcount do
seg=math.random(structure.GetCount())
cutFUC(seg)
ci(1)
wiggleFUC(15,true,true)
ci(0.01)
wiggleFUC(1,true,true)
ci(1)
if FILTERMANAGE then behavior.SetFiltersDisabled(true) end -- new BK 8/5/2013, always on
wiggleFUC(25,true,true)
if FILTERMANAGE then behavior.SetFiltersDisabled(OriginalFilterSetting) end -- new BK 8/5/2013, always back to user settings
uncut(seg)
wiggleFUC(25,true,true) -- filters always enabled after cut
ci(0.01)
wiggleFUC(2,true,true)
ci(1)
if FILTERMANAGE then behavior.SetFiltersDisabled(true) end -- new BK 8/5/2013, always on
wiggleFUC(25,true,true)
if FILTERMANAGE then behavior.SetFiltersDisabled(OriginalFilterSetting) end -- new BK 8/5/2013, always back to user settings
scorebest()
print(format("%i/%i seg: %i score: %.3f (%.3f)",loop,loopcount,seg,current.GetScore(),best_score))
save.Quickload ( kOriginalStructureOrNewBest )
--recentbest.Restore()
uncut(seg)
end
print("Total FUC gain=".. r3(current.GetScore() -startScore))
end
function cleanup ()
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.")
print("Error line:", line)
print("Error :", err)
end
print ( "Cleaning up" )
behavior.SetClashImportance ( 1.0 )
save.Quickload ( kOriginalStructureOrNewBest )
creditebest.Restore()
band.DeleteAll()
freeze.UnfreezeAll()
print("Total gain=", r3(current.GetScore() -startScore))
--Set Notes B
--3a) COPY 2 from here ---------------
SetNote(note_number, starting_score, recipename, loop_count) -- WARNING: and mach "recipename" and "loop_count" with the names of the recipe
--3b) COPY 2 to here --------------
--4) PASTE 2 at the end of the main loop function of your recipe, at the end of the cleanup function, at the end of the recipe
--better loop_count a global variable
--END SET NOTES BY PD
end
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
--CUT & WIGGLE Everything by KarenCH
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Cut And Wiggle Everything
--
-- Performs a fuse-wiggle with cuts inserted every "stepsize" spot
-- v1.2 fixed threshold bug
-- v1.3 extended stepsize and offers "randomized" stepsizes
-- Originally by Susume
-- Gui added by KarenCH
-------------------------------------------------------------------------------
maxStepsize=3
lowCI=0.3
highCI=1.0
shortwiggle = 2
longwiggle = 25
threshold = 1 --minimum point gain to do another iteration
doRandomStepsizes = false
function seedRandom()
local seed=os.time()/math.abs( current.GetEnergyScore() )
seed=seed%0.001
seed=1/seed
while seed<10000000 do seed=seed*1000 end
seed=seed-seed%1
print("Seed is: "..seed)
math.randomseed(seed)
end
function RandomPrimeNotMoreThan( max )
local primes = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101}
local lastIdx = 1
for i=1, #primes do
if primes[i] > max then break end
lastIdx = i
end
return primes[ math.random( lastIdx ) ]
end
function DoWiggle( ) -- FILTERMANAGE not implemented here, I think it's better within cuts
seedRandom()
save.Quicksave(2) --starting position
save.Quicksave(3) --high score
local segcount=structure.GetCount()
local highscore=current.GetEnergyScore()
CI = behavior.SetClashImportance
print("------------------------------")
print()
print("Cut And Wiggle Everything by KarenCH")
print("Original in slot 2, High score in slot 3")
print("Starting score "..highscore)
if doRandomStepsizes then
print("Cut with random prime stepsizes, max="..maxStepsize.." segs, fusing, loop until less than "..threshold.." gain")
else
print("Cutting every "..maxStepsize.." segs, fusing, loop until less than "..threshold.." gain")
end
repeat
local iter_start_score = current.GetEnergyScore()
local currStepsize = maxStepsize
if doRandomStepsizes then
currStepsize = RandomPrimeNotMoreThan( maxStepsize )
end
for startseg = 1, currStepsize do
print("Starting at seg "..startseg.." with stepsize="..currStepsize)
for i = startseg, segcount-1, currStepsize do
structure.InsertCut(i)
end
CI(lowCI)
structure.WiggleAll(shortwiggle)
CI(highCI)
structure.WiggleAll(longwiggle)
for i = startseg, segcount-1, currStepsize do
structure.DeleteCut(i)
end
CI(lowCI)
structure.WiggleAll(shortwiggle)
recentbest.Save()
CI(highCI)
structure.WiggleAll(longwiggle)
recentbest.Restore()
local newscore = current.GetEnergyScore()
print("New score = "..newscore)
if newscore > highscore then
save.Quicksave(3)
highscore = newscore
end
print("High score = "..highscore)
save.Quickload(3)
end
until highscore - iter_start_score < threshold
end
function GetParams()
dlgCWE = dialog.CreateDialog("Cut And Wiggle")
dlgCWE.step = dialog.AddSlider( "Stepsize", 3, 1, 17, 0 )
dlgCWE.lowCI = dialog.AddSlider( "LowCI", 0.3, 0, 1, 2 )
dlgCWE.highCI = dialog.AddSlider( "HighCI", 1.0, 0, 1, 2 )
dlgCWE.shortwiggle = dialog.AddSlider( "ShortWiggleIters", 2, 1, 10, 0 )
dlgCWE.longwiggle = dialog.AddSlider( "LongWiggleIters", 25, 1, 50, 0 )
dlgCWE.comment = dialog.AddLabel("Threshold Decimal Places for min gain: 1, 0.1,.. 0.0001")
dlgCWE.thresholdExp = dialog.AddSlider( "ThreshExp:1E-", 0, 0, 4, 0 )
dlgCWE.jumpsteps = dialog.AddCheckbox( "Use random prime stepsize (above is max)", false )
dlgCWE.ok = dialog.AddButton("OK", 1)
dlgCWE.cancel = dialog.AddButton("Cancel", 0)
if dialog.Show(dlgCWE) > 0 then
maxStepsize = dlgCWE.step.value
lowCI = dlgCWE.lowCI.value
highCI = dlgCWE.highCI.value
shortwiggle = dlgCWE.shortwiggle.value
longwiggle = dlgCWE.longwiggle.value
doRandomStepsizes = dlgCWE.jumpsteps.value
if dlgCWE.thresholdExp.value == 0 then
threshold = 1
elseif dlgCWE.thresholdExp.value == 1 then
threshold = 0.1
elseif dlgCWE.thresholdExp.value == 2 then
threshold = 0.01
elseif dlgCWE.thresholdExp.value == 3 then
threshold = 0.001
elseif dlgCWE.thresholdExp.value == 4 then
threshold = 0.0001
end
return true
else
print( "dialog cancelled" )
end
return false
end
function CWEparam() -- including L2H and FUC
if GetParams() then
Low2High() -- first L2H, v3
if Start_FUC >0 then
FUC(Start_FUC)
end
DoWiggle( )-- FILTERMANAGE not implemented here, I think it's better within cuts
end
end
function CWE()
DoWiggle( )
end
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
-- Low2High by Bruno Kestemont
------------------------------------------------------------------------------------
------------------------------------------------------------------------------------
--[[Low2High
v1.0
To shift from Low wiggle power to High or Medium wiggle power, best shift
]]--
--recipeName="Low2High"
--version="1.01"
--ci=behavior.SetClashImportance
wiggleL2H=structure.WiggleAll
kOriginalStructureOrNewBest = 1 -- the starting structure, or any subsequent improvement, will be stored in this quicksave slot
LowSlot=10 -- The starting structure at low wiggle power
counterSlot=10
minimum=0.20 -- the minimum move (0.20=20%) under which to try other method than simple wiggle medium
function scorebestL2H() -- adapted in order to take track of all different results
counterSlot=counterSlot+1
save.Quicksave ( counterSlot )
if ( Score() > best_score ) then
best_score = Score()
print ( ">>> Improvement to ".. r3 ( best_score ) )
save.Quicksave ( kOriginalStructureOrNewBest )
end
end
function Abstract()
print("Abstract:")
for i=LowSlot, counterSlot do
save.Quickload ( i )
print(i..") "..r3(Score()))
end
save.Quickload (LowSlot)
save.Quickload ( kOriginalStructureOrNewBest )
print("Undos ending with start (Low) score then best score")
end
function Low2High()
print ("Low2High 1.0")
format=string.format
print(format("current score: %.3f",current.GetScore()))
math.randomseed(os.clock())
math.random()
--recentbest.Save()
save.Quicksave ( kOriginalStructureOrNewBest )
save.Quicksave ( LowSlot )
best_score = Score()
startScore=Score()
--print ( "Start score " .. r3 ( best_score ) )
--Simple wiggle all
ci(1)
print("Simple wiggle all")
if FILTERMANAGE then behavior.SetFiltersDisabled(true) end -- new BK 8/5/2013, always on
wiggleL2H(25,true,true)
if FILTERMANAGE then behavior.SetFiltersDisabled(OriginalFilterSetting) end -- new BK 8/5/2013, always back to user settings
scorebestL2H()
if startScore * (1+minimum) >Score() then -- if it didn't move more than minimum%, try other ways
--wiggle all after small disturbance (small fuze)
for loop = 1, 3 do
print("Quick fuze "..loop)
save.Quickload ( LowSlot )
if loop<2 then cii=0.9 elseif loop<3 then cii=0.5 else cii=0.01 end
ci(cii)
wiggleL2H(1,true,false)
ci(1)
if FILTERMANAGE then behavior.SetFiltersDisabled(true) end -- new BK 8/5/2013, always on
wiggleL2H(25,true,true)
if FILTERMANAGE then behavior.SetFiltersDisabled(OriginalFilterSetting) end -- new BK 8/5/2013, always back to user settings
scorebestL2H()
end
end
Abstract()
end
--main ()
--xpcall ( Low2High , cleanup )
xpcall ( MAIN , cleanup )