Profile
- Name
- Migi Irradiator v1.0
- ID
- 103409
- Shared with
- Public
- Parent
- None
- Children
- None
- Created on
- April 14, 2020 at 17:20 PM UTC
- Updated on
- April 14, 2020 at 17:20 PM UTC
- Description
Randomly mutates 1-2 segments and then fuzes, and keeps the result if the score didn't drop too much (or increased). The maximum allowable score drop slowly goes to zero over time. Don't use this recipe to gain points, use it to drift away from your current fold, either if you want to get out of a local optimum, if you want to let multiple instances diverge, or just if you want to explore the solution space a bit.
Best for
Code
--[[
* Irradiator
* Original Author: Migi
* Version 1.0 April 10, 2020
* Randomly mutates 1 or 2 amino acids, then fuzes.
* Keeps mutations if they score "well enough" (but can lose score!)
* Use this early on to let it "explore" the space of probabilities,
* or when stuck in a local optimum (similar to Jolter),
* or just if you want to let your solution "drift" from where it started.
]]--
version = '1.0'
print ( 'Irradiator v'..version )
math.randomseed(os.time())
initialClashImportance = behavior.GetClashImportance()
initialFiltersDisabled = behavior.GetFiltersDisabled()
nSegments = structure.GetCount ( )
mutableSegments = {}
mutableTo = {}
chains = {"g";"a";"v";"c";"p";"t";"s";"i";"l";"n";"d";"m";"h";"q";"e";"f";"k";"y";"r";"w"}
hydrophobicities = {0,41,76,49,-46,13,-5,99,97,-28,-55,74,8,-10,-31,100,-23,63,-14,97}
aaLetterToChainIndex={}
for k,v in pairs(chains) do
aaLetterToChainIndex[v]=k
end
maxDrop = 100
settleTime = 7
scriptStartTime = os.time() -- updated again after config is set
quickSaveSlot = 33
curTriedMutation = ""
function showOptionsDialog()
local dlog = dialog.CreateDialog ( "Irradiator Options" )
dlog.text1 = dialog.AddLabel ( "Initial allowable score drop (at each step):" )
dlog.maxDrop = dialog.AddSlider ( "Max score drop" , maxDrop , 0 , 500 , 0 )
dlog.text2 = dialog.AddLabel ( "Allowable score drop slowly goes to zero, after" )
dlog.settleTime = dialog.AddSlider ( "this many hours" , settleTime, 0 , 30 , 1 )
dlog.ok = dialog.AddButton ( "OK" , 1 )
dlog.cancel = dialog.AddButton ( "Cancel" , 0 )
if dialog.Show ( dlog ) then
maxDrop = dlog.maxDrop.value
settleTime = dlog.settleTime.value
return true
else
return false
end
end
function getScore()
behavior.SetFiltersDisabled(false)
score = current.GetScore ()
behavior.SetFiltersDisabled(true)
return score
end
function getCurMaxDrop()
local timeD = os.difftime ( os.time () , scriptStartTime )
local x = timeD / (settleTime * 60.0 * 60.0)
if x >= 0.0 and x < 1.0 then
return (1.0 - x) * (1.0 - x) * maxDrop
else
return 0.0
end
end
function mutateRandomly(mutableSegment)
local curAASegment = mutableSegments[mutableSegment]
local curAA = structure.GetAminoAcid(curAASegment)
local curAAIndex = aaLetterToChainIndex[curAA]
while true do
local randomAAIndex = mutableTo[mutableSegment][math.random(#(mutableTo[mutableSegment]))]
local hydrophobicityDiff = math.abs(hydrophobicities[curAAIndex] - hydrophobicities[randomAAIndex])
local randomAA = chains[randomAAIndex]
if math.random() >= (hydrophobicityDiff / 150.0) and structure.CanMutate(curAASegment, randomAA) then
structure.SetAminoAcid(curAASegment, randomAA)
return curAASegment .. " to " .. randomAA
end
end
end
function main()
save.Quicksave ( quickSaveSlot )
local currentScore = getScore()
showOptionsDialog()
scriptStartTime = os.time()
local curMaxDrop = maxDrop
print( "Settings:" )
print( "Initial max score drop: " .. maxDrop )
print( "Settle time: " .. settleTime .. " hours" )
print( "Initial score: " .. currentScore )
print( "Calculating which segments can be mutated..." )
selection.DeselectAll()
for ii = 1, nSegments do
local frzback, frzside = freeze.IsFrozen ( ii )
if structure.IsMutable( ii ) and not frzside then
local tt = {}
for jj = 1, #chains do
if structure.CanMutate ( ii, chains [ jj ] ) then
table.insert(tt, jj)
end
end
if #tt == 0 then
print( "Sidechain " .. ii .. " is supposedly mutable but CanMutate() always returns false?")
elseif #tt == 1 then
print( "Sidechain " .. ii .. " is supposedly mutable but only has 1 valid AA. Skipping...")
else
selection.Select(ii)
table.insert(mutableSegments, ii)
table.insert(mutableTo, tt)
end
end
end
numMutableSegments = #mutableSegments
if numMutableSegments == 0 then
print( "None found. Stopping script..." )
return 0
end
print( "Done. Starting script..." )
while true do
local mutatedSegment = math.random(numMutableSegments)
local bestSegment = 0
local bestSegmentDist = 9999999.9
if math.random() < 0.5 then
for ii = 1, numMutableSegments do
local accepted = true
if ii == mutatedSegment then
accepted = false
elseif ii == mutatedSegment-1 or ii == mutatedSegment+1 then
if math.random() < 0.85 then
accepted = false
end
elseif ii == mutatedSegment-2 or ii == mutatedSegment+2 then
if math.random() < 0.8 then
accepted = false
end
elseif ii == mutatedSegment-3 or ii == mutatedSegment+3 then
if math.random() < 0.75 then
accepted = false
end
elseif ii == mutatedSegment-4 or ii == mutatedSegment+4 then
if math.random() < 0.7 then
accepted = false
end
else
if math.random() < 0.3 then
accepted = false
end
end
if accepted then
local dist = structure.GetDistance(mutableSegments[mutatedSegment], mutableSegments[ii])
if dist < bestSegmentDist then
bestSegmentDist = dist
bestSegment = ii
end
end
end
end
curTriedMutation = mutateRandomly(mutatedSegment)
if bestSegment ~= 0 then
curTriedMutation = curTriedMutation .. " and " .. mutateRandomly(bestSegment)
end
behavior.SetFiltersDisabled(true)
behavior.SetClashImportance ( 0.2 + math.random()*0.3 )
structure.WiggleAll( 20 )
behavior.SetClashImportance ( 0.7 + math.random() * 0.2 )
structure.ShakeSidechainsAll( 1 )
structure.WiggleAll( 20 )
behavior.SetClashImportance ( 0.8 + math.random() * 0.2 )
structure.MutateSidechainsSelected( 1 )
behavior.SetClashImportance ( 1.0 )
structure.WiggleAll( 20 )
local s = getScore()
if s >= currentScore - curMaxDrop then
currentScore = s
curMaxDrop = getCurMaxDrop()
print( "Accepted mutation: " .. curTriedMutation )
print( "New working score: " .. s .. ", new max drop: " .. curMaxDrop )
save.Quicksave ( quickSaveSlot )
else
print( "Rejected mutation: " .. curTriedMutation .. ". Score: " .. s )
save.Quickload( quickSaveSlot )
end
end
end
function ErrorHandler(errmsg)
if string.find(errmsg, "Cancelled") then
print( "Recipe stopped. Restoring last accepted fold." )
print( "Run time: " .. os.difftime ( os.time () , scriptStartTime ) .. " seconds" )
behavior.SetClashImportance(initialClashImportance)
behavior.SetFiltersDisabled(initialFiltersDisabled)
save.Quickload( quickSaveSlot )
else
print( "ERROR: " .. errmsg )
end
end
xpcall( main, ErrorHandler )