Code
--[[
NBL_hinge
Author: Nicobul2 - april 2014
Contributors: Ch Garnier, Yoyo, Bruno Kestemont
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>
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/>.
version 1.5 2014/10/11 LociOiling
* add model reporting (ChunquePoint package)
* reworked score reporting: report gain or >5 minutes with no gain
* restructured to use cleanup routine
* process multiple ranges
* elminate some dead code
* remove "local" from items that appear to have global scope anyway
* added "local" to items that appear to have local scope
* added "loops only" option
* numerous small random acts of vandalism
]]--
--
-- globals section
--
--
-- model 001 -- standard recipe name and version
--
Recipe = "NBL_hinge"
Version = "1.5"
ReVersion = Recipe .. " v." .. Version
segCnt = structure.GetCount()
flagligand = false
segCnt2 = segCnt -- cas de ligands
while structure.GetSecondaryStructure ( segCnt2 ) == "M" do
segCnt2 = segCnt2-1
flagligand = true
end
--
-- dialog options and related variables
--
hinge_width = 1
nbrun = 1
random = false
loop_only = false
range_min = 3 -- minimum segment number to process
range_max = segCnt2 - 3 -- maximum segment number to process
ranges = {} -- ranges to process
--
-- end of dialog options and related varibles
--
ici = 1.0 -- initial clashing importance
ibs = 1.0 -- initial band strength
startChunque = nil -- initial chunquePoint
--
-- end of globals section
--
_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}
--
-- begin chunquePoint Beta package version 0.2
--
CSVoutput = false
function beginChunque ( startChunque, prefix, scoreFunc, pose )
local chunque = chunquePoint ( prefix, scoreFunc, pose )
if startChunque == nil then
chunquePrint ( chunque )
else
local gain = chunque [ 2 ] - startChunque [ 2 ]
chunquePrint ( chunque, gain )
end
return chunque
end
function endChunque ( startChunque, prefix, scoreFunc, pose )
local chunque = chunquePoint ( prefix, scoreFunc, pose )
chunqueGain ( startChunque, chunque )
end
function chunquePoint ( prefix, scoreFunc, pose )
if prefix == nil then
prefix = ""
end
if scoreFunc == nil then
scoreFunc = current.GetEnergyScore
end
local score = 0
if pose == nil then
score = scoreFunc ()
else
score = scoreFunc ( pose )
end
local runDate, runClock, runTime
runDate = os.date ()
runClock = os.clock()
runTime = os.time()
return { prefix, score, runDate, runClock, runTime }
end
function chunquePrint ( chunque, gain )
local function round ( ii )
return ii - ii % 0.001
end
if gain == nil then
if CSVOutput then
print ( chunque [ 1 ] .. "," ..
round ( chunque [ 2 ] ) .. "," ..
chunque [ 3 ]
)
else
print ( chunque [ 1 ] .. ", score: " ..
round ( chunque [ 2 ] ) .. ", " ..
chunque [ 3 ]
)
end
else
if CSVOutput then
print ( chunque [ 1 ] .. "," ..
round ( chunque [ 2 ] ) .. "," ..
round ( gain ) .. "," ..
chunque [ 3 ]
)
else
print ( chunque [ 1 ] .. ", score: " ..
round ( chunque [ 2 ] ) .. ", total gain: " ..
round ( gain ) .. ", " ..
chunque [ 3 ]
)
end
end
end
function chunqueGain ( startChunk, endChunk )
local function round ( ii )
return ii - ii % 0.001
end
local Clocktime = os.difftime ( endChunk [ 5 ], startChunk [ 5 ] )
local gain = round ( endChunk [ 2 ] - startChunk [ 2 ] )
local hours = Clocktime / ( 60 * 60 )
local pph = gain / hours
if CSVOutput then
print ( endChunk [ 1 ] .. "," ..
round ( endChunk [ 2 ] ) .. "," ..
round ( gain ) .. "," ..
round ( hours ) .. "," ..
round ( pph ) .. "," ..
endChunk [ 3 ]
)
else
print ( endChunk [ 1 ] .. ", score: " ..
round ( endChunk [ 2 ] ) .. ", gain: " ..
round ( gain ) .. ", " ..
endChunk [ 3 ]
)
print ( endChunk [ 1 ] .. ", hours: " ..
round ( hours ) .. ", points per hour: " ..
round ( pph ) )
end
end
--
-- end chunquePoint Beta package version 0.2
--
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 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
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
function get_value2 ( m, b ) --> mean, bounds (symmetrical)
local upper
local lower
upper = m+b
lower = m-b
return math._random (lower,upper)
end
_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,
}
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
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
function save_recent_best(options )
-- if ( options.exploratory == true ) then
-- save.Quicksave(options.qs_recent_best )
-- else
recentbest.Save()
-- end
end
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 )
how = "wa"
--
-- mode forced to "wa", so shake code in ncWiggle appears to be unused
--
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
local 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
local function wWiggle()
local b, s = true, true
if how == 'wb' then s = false end
--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
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
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
function show_score ( options, reportTime, lastOp )
local function round ( ii )
return ii - ii % 0.001
end
local s
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 )
--
-- model 050 - print gain or period without gain
--
if ( options.ranked_score ~= 0 ) then
local gain = s - options.ranked_score
if gain > 0 then
print ( lastOp .. ", gain = " .. round ( gain ) .. ", ranking score = " .. round ( s ) )
reportTime = os.time ()
end
end
options.score = current.GetEnergyScore()
options.ranked_score = s
options.multiplier = current.GetExplorationMultiplier()
else
local checkTime = os.time ()
if checkTime - reportTime >= 300 then
reportTime = checkTime
print ( "no gain after " .. lastOp )
end
end
else
s = current.GetEnergyScore()
--
-- model 050 - print gain or period without gain
--
if ( s > options.score ) then
if ( options.score ~= 0 ) then
local gain = s - options.score
print ( lastOp .. ", gain = " .. round ( gain ) .. ", score = " .. round ( s ) )
reportTime = os.time ()
end
options.score = s
else
local checkTime = os.time ()
if checkTime - reportTime >= 300 then
reportTime = checkTime
print ( "no gain after " .. lastOp )
end
end
end
return options, reportTime
end
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
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
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
function reset_clash_importance(options )
if ( options.verbose == true ) then
-- print ( "Resetting clash importance: ", 1 )
end
behavior.SetClashImportance(1)
end
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
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
function unfreeze_rods(prot,options )
freeze.UnfreezeAll()
end
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
function unfreeze_hinge(prot,options )
freeze.UnfreezeAll()
end
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 )
local lastOp = ""
if hw == 1 then
lastOp = "segment: " .. seg
else
lastOp = "segments: " .. seg .. "-" .. seg + hw - 1
end
if loop_only then
for ii = seg, seg + hw - 1 do
if structure.GetSecondaryStructure ( seg ) ~= 'L' then
return lastOp
end
end
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 ()
return lastOp
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 ( "Random segments" )
--
-- convert ranges to a list (may contain duplicates)
--
local workList = SegmentSetToList ( ranges )
for run = 1, nbrun do
--
-- model 040 - start cycle - print cycle #, current score
--
local runName = "hinge run " .. run .. "/" .. nbrun
local begChunque = beginChunque ( startChunque, runName )
-- print ("Boucle " .. run .. " sur " .. nbrun)
ShuffleTable ( workList ) -- NEW 24/9/2013 mix the segment table randomly
local reportTime = os.time ()
for jj = 1, #workList do
local lastOp = nbl_hinge ( workList [ jj ], hinge_width, prot, options )
options, reportTime = show_score ( options, reportTime, lastOp )
end
--
-- model 070 - end cycle - print cycle #, time, gain
--
endChunque ( begChunque, "end ".. runName )
end
end
function nblh ( hinge_width, prot, options )
for run = 1, nbrun do
if (run > 1) then
local rci = math.random() / 5
options.ci = ici + rci - 0.1
local rbs = math.random() / 10
options.band_strength = ibs + rbs - 0.05
end
--
-- model 040 - start cycle - print cycle #, current score
--
local runName = "hinge run " .. run .. "/" .. nbrun
local begChunque = beginChunque ( startChunque, runName )
-- print ("Boucle " .. run .. " sur " .. nbrun)
print ( "CI = " .. options.ci .. ", band strength = " .. options.band_strength )
local reportTime = os.time ()
for ii = 1, #ranges do
for jj = ranges [ ii ] [ 1 ], ranges [ ii ] [ 2 ] do
local lastOp = nbl_hinge ( jj, hinge_width, prot, options )
options, reportTime = show_score ( options, reportTime, lastOp )
end
end
--
-- model 070 - end cycle - print cycle #, time, gain
--
endChunque ( begChunque, "end ".. runName )
end
end
function GetParams ()
local askresult = 0
local rangetext = ""
local errtext = ""
local ask = dialog.CreateDialog ( ReVersion )
repeat
--ask.hinge_width = dialog.AddSlider("Taille charnieres: ",1,1,2,0)
ask.hinge_width = dialog.AddSlider ( "Hinges size: ", hinge_width, 1, 2, 0 )
--ask.keep_trying = dialog.AddCheckbox("Toute la nuit ", true)
ask.nbrun = dialog.AddSlider ("Number of runs ", nbrun, 1, 100, 0 )
--ask.random = dialog.AddCheckbox("Segs aleatoires ", false)
ask.random = dialog.AddCheckbox ( "Random order? ", random )
ask.loop_only = dialog.AddCheckbox ( "Loops only? ", loop_only )
--ask.range = dialog.AddTextbox("Zone forcee", "")
ask.range = dialog.AddTextbox ( "Range ", rangetext )
if errtext ~= "" then
ask.l1 = dialog.AddLabel ( errtext)
end
ask.OK = dialog.AddButton ( "OK", 1 )
ask.Cancel = dialog.AddButton ( "Cancel", 0 )
askresult = dialog.Show ( ask )
if askresult ~= 0 then
hinge_width = ask.hinge_width.value
nbrun = ask.nbrun.value
random = ask.random.value
loop_only = ask.loop_only.value
if ask.range.value ~= "" then
rangetext = ask.range.value
local rangelist = ReadSegmentSet ( rangetext )
if Errfound or #rangelist == 0 then
askresult = 2
errtext = "error in range(s), please re-enter"
else
print ( #rangelist .. " ranges" )
for jj = 1, #rangelist do
local sRange = rangelist [ jj ] [ 1 ]
local eRange = rangelist [ jj ] [ 2 ]
if eRange < sRange then sRange, eRange = eRange, sRange end
if sRange < range_min then sRange = range_min end
if eRange > range_max then eRange = range_max end
ranges [ #ranges + 1 ] = { sRange, eRange }
end
end
else
ranges [ #ranges + 1 ] = { range_min, range_max }
end
end
until askresult < 2
return askresult > 0
end
function main ()
local options = _options
local prot = _prot
ici = options.ci
ibs = options.band_strength
math.randomseed(os.time()%1000000)
math.random(100)
freeze.UnfreezeAll()
band.DeleteAll()
options.score = current.GetEnergyScore()
if options.exploratory == true then
options.ranked_score = current.GetScore()
end
if GetParams () then
--
-- model 010 - startup - print recipe name, puzzle name, track
--
print ( ReVersion )
print ( "Puzzle: " .. puzzle.GetName () )
print ( "Track: " .. ui.GetTrackName () )
--
-- model 020 - startup - print recipe parms
--
print ( "options:" )
print ( "number of runs = " .. nbrun )
print ( "hinge width = " .. hinge_width )
print ( "random order = " .. tostring ( random ) )
print ( "loops only = " .. tostring ( loop_only ) )
print ( "segment range(s) = " .. SegmentSetToString ( ranges ) )
--
-- model 030 - startup - print start time, start score
--
startChunque = beginChunque ( nil, "Start" )
if random then
bkh ( hinge_width, prot, options )
else
nblh ( hinge_width, prot, options )
end
--
-- model 090 - exit via the cleanup routine
--
cleanup ()
end
end
function cleanup ( error )
print ( "---" )
--
-- model 100 - print recipe name, puzzle, track, time, score, and gain
--
local reason
local start, stop, line, msg
if error == nil then
reason = "complete"
else
--
-- model 120 - civilized error reporting,
-- thanks to Bruno K. and Jean-Bob
--
start, stop, line, msg = error:find ( ":(%d+):%s()" )
if msg ~= nil then
error = error:sub ( msg, #error )
end
if error:find ( "Cancelled" ) ~= nil then
reason = "cancelled"
else
reason = "error"
end
end
print ( ReVersion .. " " .. reason )
print ( "Puzzle: " .. puzzle.GetName () )
print ( "Track: " .. ui.GetTrackName () )
if reason == "error" then
print ( "Unexpected error detected" )
print ( "Error line: " .. line )
print ( "Error: \"" .. error .. "\"" )
end
--
-- model 130 - reset clash importance, clear selections, restore structures, etc.
--
behavior.SetClashImportance ( 1 )
selection.DeselectAll ()
freeze.UnfreezeAll ()
if error ~= nil then
recentbest.Restore ()
end
band.DeleteAll () -- want to do this *after* restoring best!
--
-- model 150 - report the final time, score, gain, elapsed time, and points per hour
--
if startChunque ~= nil then
endChunque ( startChunque, "Final" )
end
end
-- main call
xpcall ( main, cleanup )
--end of script