Icon representing a recipe

Recipe: Migi Irradiator v1.0

created by Migi

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 )

Comments