Icon representing a recipe

Recipe: Random Pull and Jiggle

created by RichGuilmain

Profile


Name
Random Pull and Jiggle
ID
108078
Shared with
Public
Parent
None
Children
Created on
October 19, 2022 at 23:06 PM UTC
Updated on
December 26, 2022 at 23:39 PM UTC
Description

Randomly pulls the protein around and wiggles it back together to escape local optima and find better neighboring solutions until canceled.

Best for


Code


math.randomseed(os.time()) num_segments = structure.GetCount() starting_wiggle_power = behavior.GetWigglePower() starting_score = current.GetScore() function Round(n, num_decimals) local mult = 10^(num_decimals or 0) return math.floor(n * mult + 0.5) / mult end function AddRandomBand(args) local segmentOrigin = math.random(1, num_segments) local segmentXAxis = math.random(1, num_segments) local segmentYAxis = math.random(1, num_segments) local rho = math.random(1, args.max_band_dist.value) local theta = math.rad(math.random(0, 179)) local phi = math.rad(math.random(0, 359)) if not pcall(band.Add, segmentOrigin, segmentXAxis, segmentYAxis, rho, theta, phi) then segmentOrigin = AddRandomBand(args) end return segmentOrigin end function WiggleUntilComplete(args) for i=1, args.max_wiggles_in.value do local starting_score = current.GetScore() structure.WiggleAll(1) if (current.GetScore() - starting_score < 0.001) then break end end end function PullAndJiggle(args) -- Pull local num_bands = math.random(1, args.max_bands.value) for i=1, num_bands do local band_segment_index = AddRandomBand(args) band.SetGoalLength(i, 0.0) selection.Select(band_segment_index) end structure.WiggleAll(math.random(1, args.max_wiggles_out.value)) band.DeleteAll() -- Mutate if args.mutate_all.value then structure.MutateSidechainsAll(1) else structure.MutateSidechainsSelected(1) end -- Shake if args.shake_all.value then structure.ShakeSidechainsAll(1) else structure.ShakeSidechainsSelected(1) end -- Wiggle selection.DeselectAll() WiggleUntilComplete(args) end function MonotonicPullAndJiggle(args) recentbest.Save() local starting_score = current.GetScore() PullAndJiggle(args) local ending_score = current.GetScore() local score_delta = ending_score - starting_score if score_delta > 0.0 then print(os.date("%X"), "Improved score by", Round(score_delta, 3), "to", Round(ending_score, 3)) else recentbest.Restore() end end function Main() args = dialog.CreateDialog("Random Pull and Jiggle") args.inst1 = dialog.AddLabel("Randomly pulls the protein around and wiggles it") args.inst2 = dialog.AddLabel("back together to escape local optima and find") args.inst3 = dialog.AddLabel("better neighboring solutions until canceled.") args.max_bands = dialog.AddSlider("Max bands", 5, 1, 10, 0) args.max_band_dist = dialog.AddSlider("Max band dist", 5, 1, 20, 1) args.max_wiggles_out = dialog.AddSlider("Max wiggles out", 3, 1, 10, 0) args.mutate_all = dialog.AddCheckbox("Mutate everything before wiggling back (slower)", false) args.shake_all = dialog.AddCheckbox("Shake everything before wiggling back (slower)", false) args.max_wiggles_in = dialog.AddSlider("Max wiggles in", 25, 1, 100, 0) args.ok = dialog.AddButton("OK", 1) args.cancel = dialog.AddButton("Cancel", 0) if dialog.Show(args) <= 0 then return end behavior.SetWigglePower("m") band.DeleteAll() selection.DeselectAll() print(os.date("%X"), "Starting with a score of", Round(starting_score, 3)) while(true) do MonotonicPullAndJiggle(args) end end function Cleanup() recentbest.Restore() band.DeleteAll() selection.DeselectAll() behavior.SetWigglePower(starting_wiggle_power) local ending_score = current.GetScore() print(os.date("%X"), "Total score increase of", Round(ending_score - starting_score, 3)) print(os.date("%X"), "Finished with a score of", Round(ending_score, 3)) end xpcall(Main, Cleanup)

Comments