Code
--[[
Rav3n_pl Compressor v2.1
ComputerMage - converted to V2.0 script.
trying to compress/decompress protein accepting loss of points between pulls
]]--
----------- options below VVVVV ---------------------
cLoops = 1500 --<<< SET NUMBER OF LOOPS
decomp = false --true --true for DeCompression instead of compression
modualtor = false --changing compression/decompression each loop
randomModulation = true
useRegions = { --set regions that have to be used in all bands
--{1,20}, --there are exaples, uncomment and edit
--{25,55},
--{100,210},
}
compressFrac = 15 --make bands shorter by that much percents
compressFracMin = 5 -- if this parameter set it will randomly select pecentage between this parameter and compressFrac
minSkip = 15 --minimum segment distance between banded segments
minBands = 3 -- if minBands less than 1 then it uses fixed amount of bands
-- defined in numBands, otherwise it generates random number of bands beween minBands and numBands for each iteration.
numBands = 13 --how many bands use at once
fastQstab = true --false --true --only 1 shake and 1 wiglle when true
useFuze = true -- use Fuze after qStab
fuzeScore = 10 --how close we have to be to run Fuze
allLoop = false --work in all-loop mode. sometimes work better than structure mode :)
S2H = false --all bands are between sheets and helixes
useStructure = false --all bands have at least one end on structure (not loop)
noLoops=false --band can`t have any end on loop
minBandStrength = 0.3 -- 0.3 --starting band str
maxBandStrength = 1.5 -- 1.0 -- max band strenght
minDist = 7 --minimum band length
slowBands = false --bands strength are raised few times till score drops by %
percLoss = 1 --pulling stops when score drops by that percent (ie 2=200pts when 10k pts)
repeatGood = true --repeating good bands if true
pullingCI = 0.3 --0.6--clash impotrance during pull
maxLoss = 30 --maximum acceptable LOSS after Fuze. also lowering fuzeScore
reloadBest = 5 --reload best solution after that many worst ones
normal = true -- checks if this is exploration puzzle
mutate = false
mutateIterations = 2
------------ end of options ^^^^^^
segCnt = 0
function Score()
local s=0
if normal==true then
s=current.GetEnergyScore()
else
s=current.GetScore()
end
return s
end
function round(x)--cut all afer 3-rd place
return x-x%0.001
end
function abs(x)
if x<0 then x=-x end
return x
end
function round(x)--cut all afer 3-rd place
return x-x%0.001
end
function down(x)
return x-x%1
end
function Wiggle(how, iters, minppi) --score conditioned recursive wiggle/shake
if how==nil then how="wa" end
if iters==nil then iters=6 end
if minppi==nil then minppi=0.1 end
if iters>0 then
iters=iters-1
local sp=Score()
if how == "s" then structure.ShakeSidechainsAll(1)
elseif how == "wb" then structure.WiggleAll(2, true, false)
elseif how == "ws" then structure.WiggleAll(2, false, true)
elseif how == "wa" then structure.WiggleAll(2, true, true)
end
if Score()-sp > minppi then return Wiggle(how, iters, minppi) end
end
end
SAVEDstructs=false
function AllLoop() --turning entire structure to loops
local anychange=false
for i=1,segCnt do
if structure.GetSecondaryStructure(i)~="L" then
anychange=true
break
end
end
if anychange then
save.SaveSecondaryStructure()
SAVEDstructs=true
selection.SelectAll()
structure.SetSecondaryStructureSelected("L")
end
end
function qStab()
behavior.SetClashImportance(0.1)
Wiggle("s",1)
if mutate == true then
structure.MutateSidechainsSelected(mutateIterations)
SaveBest();
end
selection.SelectAll()
if fastQstab==false then
behavior.SetClashImportance(0.4)
Wiggle("wa",1)
behavior.SetClashImportance(1)
Wiggle("s",1)
end
behavior.SetClashImportance(1)
Wiggle()
end
function FuzeEnd()
behavior.SetClashImportance(1)
if mutate == true then
structure.MutateSidechainsSelected(mutateIterations)
end
Wiggle("wa",1)
Wiggle("s",1)
Wiggle()
SaveBest()
end
function Fuze1(ci1,ci2)
behavior.SetClashImportance(ci1)
Wiggle("s",1)
behavior.SetClashImportance(ci2)
Wiggle("wa",1)
end
function Fuze2(ci1,ci2)
behavior.SetClashImportance(ci1)
Wiggle("wa",1)
behavior.SetClashImportance(1)
Wiggle("wa",1)
behavior.SetClashImportance(ci2)
Wiggle("wa",1)
end
function reFuze(scr,slot)
local s=Score()
if s<scr then
save.Quickload(slot)
else
scr=s
save.Quicksave(slot)
end
return scr
end
function Fuze(slot)
local scr=Score()
save.Quicksave(slot)
selection.SelectAll()
Fuze1(0.3,0.6) FuzeEnd()
scr=reFuze(scr,slot)
Fuze2(0.3,1) SaveBest()
scr=reFuze(scr,slot)
Fuze1(0.05,1) SaveBest()
scr=reFuze(scr,slot)
Fuze2(0.7,0.5) FuzeEnd()
scr=reFuze(scr,slot)
Fuze1(0.07,1) SaveBest()
reFuze(scr,slot)
end
--[[
Tlaloc`s math library
------------------------------------------------------------------------
The original random script this was ported from has the following notices:
Copyright (c) 2007 Richard L. Mueller
Hilltop Lab web site - http://www.rlmueller.net
Version 1.0 - January 2, 2007
You have a royalty-free right to use, modify, reproduce, and
distribute this script file in any way you find useful, provided that
you agree that the copyright owner above has no warranty, obligations,
or liability for such use.
------------------------------------------------------------------------
]]--
local lngX = 1000
local lngC = 48313
local function _random(m,n)
local A_Hi = 63551
local A_Lo = 25354
local M = 4294967296
local H = 65536
function _MWC()
local S_Hi = math.floor(lngX / H)
local S_Lo = lngX - (S_Hi * H)
local C_Hi = math.floor(lngC / H)
local F1 = A_Hi * S_Hi
local F2 = (A_Hi * S_Lo) + (A_Lo * S_Hi) + C_Hi
lngX = ((F2 - (math.floor(F2 / H) * H)) * H) + (A_Lo * S_Lo) + lngC - (C_Hi * H)
lngX = lngX - (math.floor(lngX / M) * M)
lngC = math.floor((F2 / H) + F1)
return lngX
end
if n == nil and m ~= nil then
n = m
m = 1
end
if (m == nil) and (n == nil) then
return _MWC() / M
else
if n < m then
return nil
end
return math.floor((_MWC() / M) * (n - m + 1)) + m
end
end
local function _abs(value)
if value < 0 then
return -value
else
return value
end
end
local function _floor(value)
return value - (value % 1)
end
local function _randomseed(s)
if s==nil then
s=math.abs(Score())
s=s%0.001
s=1/s
while s<10000000 do s=s*10 end
s=s-s%1
end
lngX = s
end
math=
{
abs = _abs,
floor = _floor,
random = _random,
randomseed = _randomseed,
}
math.randomseed()
--[[ End math library ]]--
bestScore=Score()
function SaveBest()
local g=Score()-bestScore
if g>0 then
print("Gained another ",round(g)," pts.")
bestScore=Score()
save.Quicksave(3)
end
end
function MakeBands()
local num = 0
if minBands > 0 then
if minBands > numBands then
minBands = 1
end
num = math.random(minBands, numBands)
else
num = numBands
end
if minBands < 1 then
print("Make "..num.." bands")
else
print("Make "..num.." bands, where min is "..minBands.." and max is "..numBands)
end
InternalMakeBands(num)
end
function InternalMakeBands(num)
local done=false
local s1=math.random(segCnt)
local s2=math.random(segCnt)
if s1>s2 then s1,s2=s2,s1 end
local d=structure.GetDistance(s1,s2)
if s2-s1>=minSkip and d>=minDist then done=true end
if (done and #useRegions>0) then
done=false
for a=1,#useRegions do
local ss=useRegions[a][1]
local se=useRegions[a][2]
if (s1>=ss and s1<=se) or (s2>=ss and s2<=se) then
done=true
break
end
end
end
local ss1=structure.GetSecondaryStructure(s1)
local ss2=structure.GetSecondaryStructure(s2)
if (done and noLoops) then
if ss1=="L" or ss2=="L" then done=false end
end
if (done and useStructure) then
if ss1=="L" and ss2=="L" then done=false end
end
if (done and S2H) then
if (ss1=="E" or ss2=="E") and (ss1=="H" or ss2=="H") and (ss1~=ss2) then
done=true
else
done=false
end
end
if done then
num=num-1
mkBand(s1,s2)
bands[#bands+1]={s1,s2}
end
if num>0 then return InternalMakeBands(num) end --tail call
end
function mkBand(s1,s2)
band.AddBetweenSegments(s1,s2)
local len=structure.GetDistance(s1,s2)
local frac = compressFrac
if compressFracMin ~= nil then
frac = math.random(compressFracMin, compressFrac)
end
if randomModulation == false then
if decomp==true then
len=len*(1 + frac/100)
else
len=len/(1 + frac/100)
end
else
if math.random(1,10) > 5 then
len=len*(1 + frac/100)
else
len=len/(1 + frac/100)
end
end
if len<3 then len=3 end --not make shorter band, useless
band.SetGoalLength(band.GetCount(),len)
end
bands={}
function Repeat_bands(bands)
band.DeleteAll()
for i=1,#bands do
local s1=bands[i][1]
local s2=bands[i][2]
mkBand(s1,s2)
end
end
function SetBandsStrength(str) --set all band strengt
if str<0.1 then str=0.1 end
if str>10 then str=10 end
for i=1, band.GetCount() do
band.SetStrength(i, str)
end
end
function RandomBandStrength() --set all band strengt
if minBandStrength<0.1 then BandStrength=0.1 end
if maxBandStrength>10 then maxBandStrength=10 end
for i=1, band.GetCount() do
band.SetStrength(i, math.random(minBandStrength, maxBandStrength))
end
end
function SaveRB(slot)
save.Quicksave(slot)
recentbest.Restore()
SaveBest()
save.Quickload(slot)
end
function Cleanup(err)
print("Restoring CI, best result and structures")
behavior.SetClashImportance(1)
save.Quickload(3)
if SAVEDstructs then save.LoadSecondaryStructure() end
print(err)
end
sscore=Score() --starting score
function Compressor()
print("Starting Compressor v2, ",cLoops," loops.")
if normal==false then print("Using exploration options.") end
if mutate==true then print("Puzzle has mutable segments. Enabling mutations.") end
if allLoop then AllLoop() end
save.Quicksave(3)
save.Quicksave(7) --save state for losing
badOnes=0
recentbest.Save()
local best=false
for i=1,cLoops do
loss=Score()*percLoss/100 --pulling till we lost some points
band.DeleteAll()
if best==true and repeatGood==true then
print("Repeating last bands.")
if modualtor==true then --switch
decomp= not decomp
end
Repeat_bands(bands)
else
bands={}
MakeBands()
end
local ls=Score()
local tx="ompressing."
if randomModulation == false then
if decomp==true then
tx="Dec"..tx
else
tx="C"..tx
end
else
tx = "Random modulation"
end
print("Loop ",i," of ",cLoops," started. ", tx)
print(" Current score: ",round(ls))
behavior.SetClashImportance(pullingCI)
selection.SelectAll()
recentbest.Save()
if slowBands then
for str=minBandStrength,maxBandStrength,0.07 do--search enough band strenght to move
recentbest.Restore() --because sometimes it makes points during pull :D
local ss=Score()
SetBandsStrength(str)
Wiggle("wb",1)
if ss-Score()>loss then
break
end
end
else
RandomBandStrength(bandStr)
Wiggle("wb",1)
end
SaveRB(4) --because sometimes it missing fractions
structure.ShakeSidechainsAll(5)
structure.WiggleAll(5, true, true)
band.DeleteAll()
SaveBest()
if mutate == true then
structure.MutateSidechainsSelected(mutateIterations)
end
SaveBest()
qStab()
if useFuze and Score()> (bestScore-fuzeScore) then
SaveBest()
if mutate == true then
structure.MutateSidechainsSelected(mutateIterations)
end
Fuze(4)
if mutate == true then
structure.MutateSidechainsSelected(mutateIterations)
end
else
SaveBest()
end
if maxLoss>0 then
if Score()>bestScore-maxLoss then
save.Quicksave(7) --save actual "best" solution
else
badOnes=badOnes+1
if badOnes >=reloadBest then
badOnes=0
save.Quickload(3)
else
save.Quickload(7) --load "second best"
end
end
else
save.Quickload(3)
end
local es=Score()
if es>ls then best=true else best=false end --repeating all bands making points
print("Loop ",i," gain ",round(es-ls)," ;total gain ",round(bestScore-sscore))
if modualtor==true then --switch
decomp= not decomp
end
end
save.Quickload(3)
if allLoop then save.LoadSecondaryStructure() end
print("Total gain: ",round(Score()-sscore))
end
--main call
segCnt = structure.GetCount()
while structure.GetSecondaryStructure(segCnt)=="M" do segCnt=segCnt-1 end
if current.GetExplorationMultiplier() ~= 0 then
normal = false
end
for idx = 1,segCnt do
if structure.IsMutable(idx) then
mutate=true
break
end
end
-- Settings code
local dlg = dialog.CreateDialog("Compressor Settings:")
dlg.cLoops = dialog.AddSlider("Loops to work:", cLoops, 0, 3000, 0)
dlg.decomp = dialog.AddCheckbox("Use Decompress instead?", decomp)
dlg.modulator = dialog.AddCheckbox("Modulate loops?", modulator)
dlg.randomModulation = dialog.AddCheckbox("Random modulation?", randomModulation)
dlg.l1 = dialog.AddLabel("Compression rate:")
dlg.compressFracMin = dialog.AddSlider("Minimum %", compressFracMin, 0, 100, 0)
dlg.compressFrac = dialog.AddSlider("Maximum %", compressFrac, 0, 100, 0)
dlg.l2 = dialog.AddLabel("Bands:")
dlg.minBands = dialog.AddSlider("Minimum", minBands, 0, segCnt, 0)
dlg.numBands = dialog.AddSlider("Maximum", numBands, 1, segCnt, 0)
dlg.l3 = dialog.AddLabel("Segments between band endpoints:")
dlg.minSkip = dialog.AddSlider("Minimum", minSkip, 3, segCnt, 0)
dlg.l4 = dialog.AddLabel("Band strength:")
dlg.minBandStrength = dialog.AddSlider("Minimum", minBandStrength, 0, 10, 1)
dlg.maxBandStrength = dialog.AddSlider("Maximum", maxBandStrength, 0, 10, 1)
dlg.minDist = dialog.AddSlider("Min band length", minDist, 0, 20, 0)
dlg.slowBands = dialog.AddCheckbox("Slow Bands", slowBands)
dlg.repeatGood = dialog.AddCheckbox("Repeat good bands", repeatGood)
dlg.pullingCI = dialog.AddSlider("Pulling CI", pullingCI, 0, 1.0, 4)
if mutate == true then
dlg.mutateIterations = dialog.AddSlider("Mutate iterations", mutateIterations, 0, 1.0, 0)
end
dlg.OK = dialog.AddButton("OK",1) dlg.Cancel = dialog.AddButton("Cancel",0)
-- percLoss = 1 --pulling stops when score drops by that percent (ie 2=200pts when 10k pts)
if dialog.Show(dlg) > 0 then
-- Set modified values
cLoops = dlg.cLoops.value
decomp = dlg.decomp.value
modulator = dlg.modulator.value
randomModulation = dlg.randomModulation.value
compressFracMin = dlg.compressFracMin.value
compressFrac = dlg.compressFrac.value
numBands = dlg.numBands.value
minBands = dlg.minBands.value
minSkip = dlg.minSkip.value
minBandStrength = dlg.minBandStrength.value
maxBandStrength = dlg.maxBandStrength.value
minDist = dlg.minDist.value
slowBands = dlg.slowBands.value
repeatGood = dlg.repeatGood.value
pullingCI = dlg.pullingCI.value
if mutate == true then
mutateIterations = dlg.mutateIterations.value
end
xpcall(Compressor,Cleanup)
else
print("Dialog cancelled.")
end
--end of scipt