Code
--[[
Rav3n_pl Compressor v2.03nc
ComputerMage - converted to V2.0 script.
trying to compress/decompress protein accepting loss of points between pulls with some aditions.
BK optimized for New Chapter 06/02/2014
]]--
----------- 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
hydrophobicModulation = false
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 = 3 --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
experimentalCompress = false
------------ end of options ^^^^^^
segCnt = 0
function table.sort(x,comp)
local j
local v
if comp == nil then
comp=function(x,y) return x<y end
end
for i = #x-1,1,-1 do
v=x[i]
j=i
while (j<#x) and (comp(x[j+1],v)) do
x[j]=x[j+1]
j=j+1
end
x[j]=v
end
end
function GetSortedDistances()
local distances = {}
for segment = 1, structure.GetCount() do
totalDistance = 0
for otherSegment = 1, structure.GetCount() do
if segment ~= otherSegment then
totalDistance = totalDistance + structure.GetDistance(segment, otherSegment)
end
end
distances[#distances + 1] = {segment, totalDistance}
end
table.sort(distances, function(x,y) return x[2] < y[2] end)
print ('#distances=', #distances, '\n')
return distances
end
function GetSortedDistancesFromSegment(segment)
local distances = {}
for otherSegment = 1, structure.GetCount() do
if segment ~= otherSegment then
distances[#distances + 1] = {otherSegment, structure.GetDistance(segment, otherSegment)}
end
end
table.sort(distances, function(x,y) return x[2] < y[2] end)
return distances
end
function GetSortedDistancesFromSegmentList(segmentsList)
local distances = {}
for segment = 1, structure.GetCount() do
totalDistance = 0
for idx = 1, #segmentsList do
local otherSegment = segmentsList[idx]
if segment ~= otherSegment then
totalDistance = totalDistance + structure.GetDistance(segment, otherSegment)
end
end
distances[#distances + 1] = {segment, totalDistance}
end
table.sort(distances, function(x,y) return x[2] < y[2] end)
return distances
end
function GetSortedDistancesFromSegmentListForSegment(seg, segmentsList)
local distances = {}
for idx = 1, #segmentsList do
local otherSegment = segmentsList[idx]
if segment ~= otherSegment then
distances[#distances + 1] = {otherSegment, structure.GetDistance(seg, otherSegment)}
end
end
table.sort(distances, function(x,y) return x[2] < y[2] end)
return distances
end
function SetupBandBetweenSegmentsWithParameters(seg1, seg2, goalLength, strength)
local bandNo = band.AddBetweenSegments(seg1, seg2)
if bandNo > 0 then
local bandLength = band.GetLength(bandNo)
if goalLength ~= nil then
if type(goalLength) == 'string' and string.sub(goalLength, -1) == '%' then
local val = tonumber(string.sub(goalLength, 1, -2))
if val ~= nil then
bandLength = bandLength * (val / 100)
end
else
bandLength = goalLength
end
if bandLength < 3 then --not make shorter band, useless
bandLength = 3
end
if bandLength > 20 then --not make longer band, useless
bandLength = 20
end
band.SetGoalLength(bandNo, bandLength)
end
if strength ~= nil then
band.SetStrength(bandNo, strength)
end
end
end
-- Module Find Segment Types
function FindMutablesList()
local result={}
for i=1,segCnt2 do if structure.IsMutable(i) then result[#result+1]=i end end
return result
end
function FindMutables()
return SegmentListToSet(FindMutablesList())
end
function FindFrozenList()
local result={}
for i=1,segCnt2 do if freeze.IsFrozen(i) then result[#result+1]=i end end
return result
end
function FindFrozen()
return SegmentListToSet(FindFrozenList())
end
function FindLockedList()
local result={}
for i=1,segCnt2 do if structure.IsLocked(i) then result[#result+1]=i end end
return result
end
function FindLocked()
return SegmentListToSet(FindLockedList())
end
function FindSelectedList()
local result={}
for i=1,segCnt do if selection.IsSelected(i) then result[#result+1]=i end end
return result
end
function FindSelected()
return SegmentListToSet(FindSelectedList())
end
function FindAAtypeList(aa)
local result={}
for i=1,segCnt2 do
if structure.GetSecondaryStructure(i)== aa then result[#result+1]=i end
end
return result
end
function FindAAtype(aa)
return SegmentListToSet(FindAAtypeList(aa))
end
function FindAminotype(at) --NOTE: only this one gives a list not a set
local result={}
for i=1,segCnt2 do
if structure.GetAminoAcid(i) == at then result[#result+1]=i end
end
return result
end
-- end Module Find Segment Types
-- Start of module for bridgechecking
Cyslist={}
savebridges=false --default no bridgechecking
nrofbridges=0
function setCyslist()
Cyslist=FindAminotype("c")
nrofbridges=CountBridges()
end
function IsBridge(i)
return ''..current.GetSegmentEnergySubscore(i,'disulfides') ~= '-0'
end
function CountBridges()
local count = 0
for i = 1,#Cyslist do
if IsBridge(Cyslist[i]) then count = count + 1 end
end
return count
end
function BridgesBroken()
return savebridges == true and CountBridges() < nrofbridges
end
function Bridgesave()
if savebridges then PushPosition() end
end
function Bridgerestore()
if savebridges then
if BridgesBroken() then PopPosition() else ClrTopPosition() end
end
end
-- End module bridgechecking
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(1, true, false)
elseif how == "ws" then structure.WiggleAll(1, false, true)
elseif how == "wa" then structure.WiggleAll(1, 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")
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 hydrophobicModulation == true then
local s1hydrophobic = structure.IsHydrophobic(s1)
local s2hydrophobic = structure.IsHydrophobic(s2)
if s1hydrophobic == true and s2hydrophobic == true then
frac = 1 - frac / 100;
elseif s1hydrophobic == false and s2hydrophobic == false then
frac = 1 + frac / 100;
end
else
if randomModulation == false then
if decomp == true then
frac = 1 + frac / 100;
else
frac = 1 - frac / 100;
end
else
if math.random(1,10) > 5 then
frac = 1 + frac / 100;
else
frac = 1 - frac / 100;
end
end
end
frac = tostring(frac * 100) .. "%"
SetupBandBetweenSegmentsWithParameters(s1, s2, frac)
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 ExperimentalBands()
local idx, idx1, idx2 = 1,1,1
local distances = GetSortedDistances()
local centerSegment = distances[1][1]
distancesFromCenter = GetSortedDistancesFromSegment(centerSegment)
local axes = {distancesFromCenter[#distancesFromCenter][1]}
for idx=1, structure.GetCount() do
distances = GetSortedDistancesFromSegmentList(axes)
axes[#axes + 1] = distances[#distances][1]
end
temp = {}
for idx=1, #axes do
temp[axes[idx]] = 1
end
axes = {}
for seg, t in pairs(temp) do
axes[#axes+1] = seg
end
bandSegPairs = {}
bands = {}
for idx1=1, #axes do
local seg1 = axes[idx1]
distances = GetSortedDistancesFromSegmentListForSegment(seg1, axes)
for idx2=1, math.floor(#distances/2,1) do
local seg2 = distances[idx2][1]
if bandSegPairs[seg1..'|'..seg2] == nil or bandSegPairs[seg2..'|'..seg1] == nil then
bandSegPairs[seg1..'|'..seg2] = 1
if seg1 ~= seg2 and math.abs(seg1 - seg2) > 2 then
SetupBandBetweenSegmentsWithParameters(seg1, seg2, "95%", 1.1)
bands[#bands+1]={seg1,seg2}
end
end
end
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)
elseif experimentalCompress then
ExperimentalBands()
else
bands={}
MakeBands()
end
local ls=Score()
local tx="compressing."
if randomModulation == false then
if hydrophobicModulation == true then
tx = "Hydrophobic Modulation"
else
if decomp==true then
tx="Dec"..tx
else
tx="C"..tx
end
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(1) --06/02/2014
Wiggle(2)--06/02/2014
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.experimentalCompress = dialog.AddCheckbox("Experimental Compression?", experimentalCompress)
dlg.hydrophobicModulation = dialog.AddCheckbox("Hydrophobic Modulation?", hydrophobicModulation)
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, 100, 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
experimentalCompress = dlg.experimentalCompress.value
hydrophobicModulation = dlg.hydrophobicModulation.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
if hydrophobicModulation == true then
experimentalCompress = false
randomModulation = false
elseif experimentalCompress == true then
hydrophobicModulation = false
randomModulation = false
elseif randomModulation == true then
hydrophobicModulation = false
experimentalCompress = false
end
xpcall(Compressor,Cleanup)
else
print("Dialog cancelled.")
end
--end of scipt