Code
--keep blank line at top 4 debug
HASMUTABLE=false
descrTxt=puzzle.GetDescription()
if #descrTxt>0 and (descrTxt:find("design") or descrTxt:find("designs")) then
HASMUTABLE=true IDEALCHECK=true HANDFOLD=true end
--copied from AFK3.1.1 using new foldit editor
--if HASMUTABLE then environInput1=1 else environInput1=0 end
print("muta ")
print(HASMUTABLE) --can't cat
-----
--So I cut and pasted these functions from BWP here for AFK.
NonLockedSegList={}
function segCnt() return structure.GetCount() end --jon
function IsUnlockedSeg( seg1 )
return not structure.IsLocked( seg1 )
end
function FindAllMovableSegs( )
--segCnt=structure.GetCount() --jon lazy
NonLockedSegList={} --jon reinit in case deleting res.
for i=1, structure.GetCount() do --jon
if structure.IsLocked( i ) then
PuzzleHasLockedSegs = true
else
NonLockedSegList[ #NonLockedSegList + 1] = i
end
end
if PuzzleHasLockedSegs then
for i=1, structure.GetCount() do --jon
if IsUnlockedSeg( i ) then
MinUnlockedSeg = i
break
end
end
for i=segCnt(), 1, -1 do
if IsUnlockedSeg( i ) then
MaxUnlockedSeg = i
break
end
end
end
return false
end
FindAllMovableSegs()
------
------------A.i. learns v7 filters
performAction={}
actionDescription={}
function printTimeAndScore(startTime, scoreGain, currentStateString)
local ss = (os.time() - startTime) % 60
local mm = (((os.time() - startTime - ss) % 3600) / 60)
local hh = (os.time() - startTime - mm*60 - ss) / 3600
print("Time: " .. string.format("%02d", hh) .. ":" .. string.format("%02d", mm) .. ":" ..
string.format("%02d", ss) .. ". " .. currentStateString)
print(" Score: " .. current.GetEnergyScore() ..
", Total: +" .. scoreGain)
end
function initializeActions()
performAction = {}
actionDescription = {}
performAction[0] = function()
local ss=math.random(1,structure.GetCount()-3)
selection.SelectRange(ss,ss+3)
structure.MutateSidechainsSelected(1) --All(1)
end
actionDescription[0] = "Mutate(1)"
performAction[1] = function()
structure.WiggleAll(1)
end
actionDescription[1] = "Wiggle("
performAction[2] = function()
local startSegmentNumber = math.random(1, structure.GetCount() - 9)
local endSegmentNumber = math.random(startSegmentNumber + 8, structure.GetCount())
band.AddBetweenSegments(startSegmentNumber, endSegmentNumber)
band.SetStrength(1, 10)
band.SetGoalLength(1, structure.GetDistance(startSegmentNumber, endSegmentNumber) * 0.9)
end
actionDescription[2] = "Add random band"
performAction[3] = function()
band.DeleteAll()
end
actionDescription[3] = "Delete all bands"
recentbest.Save() --overwrite it first
performAction[4] = function()
recentbest.Restore() --still somehow accessing
FindAllMovableSegs()
--print("banned")
end
actionDescription[4] = "Restore recent best"
performAction[5] = function()
local startSegmentNumber = math.random(1,structure.GetCount() - 3)
selection.DeselectAll()
selection.SelectRange(startSegmentNumber, startSegmentNumber + 3)
structure.RebuildSelected(2)
selection.DeselectAll()
end
actionDescription[5] = "Rebuild random segment"
performAction[6] = function()
behavior.SetClashImportance(1)
end
actionDescription[6] = "Set clash importance to 1"
performAction[7] = function()
behavior.SetClashImportance(0.5)
end
actionDescription[7] = "Set clash importance to 0.5"
performAction[8] = function()
behavior.SetClashImportance(0.02)
end
actionDescription[8] = "Set clash importance to 0.02"
performAction[9] = function()
local startSegmentNumber = math.random(1, structure.GetCount() - 3)
selection.DeselectAll()
selection.SelectRange(startSegmentNumber, startSegmentNumber + 3)
structure.IdealizeSelected()
selection.DeselectAll()
end
actionDescription[9] = "Idealize random segment"
performAction[10] = function()
local lengthOfSegment = math.random(1, 3)
local segmentInformation = {}
local workSegmentNumber = math.random(1, 3)
local function sortSegments(segmentInformation)
for i = 1, #segmentInformation - 1 do
for j = i + 1, #segmentInformation do
if segmentInformation[i][3] > segmentInformation[j][3] then
segmentInformation[i], segmentInformation[j] = segmentInformation[j],
segmentInformation[i]
end
end
end
return segmentInformation
end
for i = 1, structure.GetCount() - lengthOfSegment + 1 do
segmentInformation[i] = {i, i + lengthOfSegment - 1, current.GetSegmentEnergyScore(i) }
for j = 2, lengthOfSegment do
segmentInformation[i][3] = segmentInformation[i][3] + current.GetSegmentEnergyScore(i
+ j - 1)
end
end
segmentInformation = sortSegments(segmentInformation)
selection.DeselectAll()
selection.SelectRange(math.max(segmentInformation[workSegmentNumber][1] - 1, 1),
math.min(segmentInformation[workSegmentNumber][2] + 1, structure.GetCount()))
structure.RebuildSelected(2)
selection.DeselectAll()
end
actionDescription[10] = "Rebuild worst segment"
performAction[11]=function()
behavior.SetFiltersDisabled(true)
end
actionDescription[11]="disable filters"
performAction[12]=function()
behavior.SetFiltersDisabled(false)
end
actionDescription[12]="enable filters"
table.insert(performAction,function()
FindAllMovableSegs()
cut=NonLockedSegList[math.random(#NonLockedSegList)] --plz only unlocked
structure.InsertCut(cut)
behavior.UseCutBands(false)
seg=NonLockedSegList[math.random(#NonLockedSegList)] --plz not the cut
options={"h","l","e"}
ss=options[math.random(3)]
structure.SetSecondaryStructure(seg,ss)
selection.DeselectAll()
selection.Select(seg)
structure.IdealSSSelected() --need cut beforehand in linker
behavior.UseCutBands(true)
behavior.SetClashImportance(1)
structure.WiggleAll(1)
structure.DeleteCut(cut)
end)
table.insert(actionDescription,"random SS, idealSS")
table.insert(performAction,function() structure.LocalWiggleAll(1) end)
table.insert(actionDescription,"LwA")
table.insert(performAction,function()
FindAllMovableSegs()
structure.InsertResidue(NonLockedSegList[math.random(#NonLockedSegList) ])
FindAllMovableSegs()
--structure.WiggleAll(1) --debug
end)
table.insert(actionDescription,"ins")
table.insert(performAction,function()
FindAllMovableSegs()
structure.DeleteResidue(NonLockedSegList[math.random(#NonLockedSegList) ])
FindAllMovableSegs()
--structure.WiggleAll(1) --debug
end)
table.insert(actionDescription,"del. seg, may cause band glitch")
table.insert(performAction,function() puzzle.StartOver() FindAllMovableSegs() end)
table.insert(actionDescription,"reset") --multi
table.insert(performAction,function() save.Quicksave(3) end)
table.insert(actionDescription,"save3")
table.insert(performAction,function() save.Quickload(3) FindAllMovableSegs() end)
table.insert(actionDescription,"load3")
table.insert(performAction,function() creditbest.Restore() FindAllMovableSegs() end)
table.insert(actionDescription,"credit")
table.insert(performAction,function() absolutebest.Restore() FindAllMovableSegs() end)
table.insert(actionDescription,"abs best")
table.insert(performAction,function()
cuts=structure.GetCuts()
for i=1,#cuts do
structure.DeleteCut(cuts[i])
end
end)
table.insert(actionDescription,"del. cuts")
table.insert(performAction,function()
local ss=math.random(1,structure.GetCount()-3)
selection.SelectRange(ss,ss+3)
structure.ShakeSidechainsSelected(1) --All(1)
end)
table.insert(actionDescription,"shake(1)")
table.insert(performAction,function()
local lengthOfSegment = math.random(1, 3)
local segmentInformation = {}
local workSegmentNumber = math.random(1, 3) --jon asks if Quicksort
local function sortSegments(segmentInformation)
for i = 1, #segmentInformation - 1 do
for j = i + 1, #segmentInformation do
if segmentInformation[i][3] > segmentInformation[j][3] then
segmentInformation[i], segmentInformation[j] = segmentInformation[j],
segmentInformation[i]
end
end
end
return segmentInformation
end
for i = 1, structure.GetCount() - lengthOfSegment + 1 do
segmentInformation[i] = {i, i + lengthOfSegment - 1, current.GetSegmentEnergyScore(i) }
for j = 2, lengthOfSegment do
segmentInformation[i][3] = segmentInformation[i][3] + current.GetSegmentEnergyScore(i
+ j - 1)
end
end
segmentInformation = sortSegments(segmentInformation)
selection.DeselectAll()
selection.SelectRange(math.max(
segmentInformation[workSegmentNumber][1] - 1, 1),
math.min(segmentInformation[workSegmentNumber][2] + 1, structure.GetCount()))
structure.MutateSidechainsSelected(2)
selection.DeselectAll()
end)
table.insert(actionDescription,"muta worst segment")
table.insert(performAction, function()
i=math.random(1,structure.GetCount()) -- do --abridged for debugging
structure.SetAminoAcid(i,"e")
--e for msg
--acids arndceqghilkmfpstwyv
--g for glycine
--v for valine, suggested by Enzyme for 1947
--end
end)
table.insert(actionDescription,"set amino msg")
table.insert(performAction, function()
i=math.random(structure.GetCount())
aminos="arndceqghilkmfpstwyv"
choice=math.random(#aminos)
local char = aminos:sub(choice,choice)
structure.SetAminoAcid(i,char)
--e for msg
--g for glycine
--v for valine, suggested by Enzyme for 1947
end)
table.insert(actionDescription,"set amino rand")
--imported from AiLearns22
performAction[13]=function()
--Bands in Space
local s1=math.random(structure.GetCount())
local str=math.random(0.1,1)
local len=math.random(20)
local theta = math.acos(math.random()) --jon: arccosine
local phi = 2 * math.pi * math.random()
local segmentXAxis=0
local segmentYAxis=0
while true do --all 3 must be different
segmentXAxis = math.random(structure.GetCount())--segCnt) --jon
segmentYAxis = math.random(structure.GetCount())--segCnt) --jon
if segmentXAxis~=s1 and segmentYAxis~=s1 and segmentXAxis~=segmentYAxis then break end
end
--{segmentOrigin, segmentXAxis, segmentYAxis, rho, theta, phi}
band.Add(s1, segmentXAxis, segmentYAxis, len, theta, phi, str)
--bands.AddBand(b)
--puzzle.StartOver()
end
actionDescription[13]="band in space"
table.insert(performAction, function() structure.WiggleAll(1) end)
table.insert(actionDescription, "Wiggle all, moved from action 0 because Lua starts at 1")
table.insert(performAction, function() structure.LocalWiggleAll(1) end )
table.insert(actionDescription, "local wiggle all inspired by BWP")
table.insert(performAction, function()
local seg=math.random(structure.GetCount())
selection.SelectRange(seg,math.max(seg,math.random(structure.GetCount()))) --could use seg+1
structure.LocalWiggleSelected(1)
selection.DeselectAll()
end)
table.insert(actionDescription, "Local Wiggle Selected inspired by BWP")
table.insert(
performAction,
function()
for i=1,30 do
if structure.InsertResidue(
math.random(1,structure.GetCount()) --start at 1 for del.
--I think the wiki is outdated;
-- insert residue gives an error with index 0 (and count+1) now
) then break end
end
end
)
table.insert(actionDescription, "Try Insert residue/segment. Only works in Design puzzles.")
table.insert(
performAction, function() structure.DeleteCut(math.random(structure.GetCount())) end
)
table.insert(actionDescription, "del. cut")
table.insert(
performAction,function() structure.InsertCut(math.random(structure.GetCount())) end
)
table.insert(actionDescription, "insert cut")
table.insert(
performAction, function()
structure.DeleteResidue(math.random(2,structure.GetCount()-1))
FindAllMovableSegs()
end
)
table.insert(actionDescription, "delete residue. may cause Foldit crash in combination with GAB")
table.insert(performAction,function() ui.CenterViewport() end)
table.insert(actionDescription, "center view")
--insert actions you want included by default above this line
performAction[#performAction+1]=function() -- +1]=function()
puzzle.StartOver()
end
actionDescription[#actionDescription+1]="reset puzzle. may be necessary for multi-start puzzles. doesn't exit evolver mode like manual reset does. "
performAction[#performAction+1]=function()
selection.SelectAll()
structure.SetSecondaryStructureSelected("a") --auto
selection.DeselectAll()
end
actionDescription[#actionDescription+1]="auto secondary structure. won't affect score in this script, just human readability and maybe info for other scripts"
performAction[#actionDescription+1]=function() --interchangeable here
-- Set segments secondary structure. Valid values are e=sheet, h=helix, l=loop, m=molecule, a=auto.
local struct={[1]="e",[2]="h",[3]="l",[4]="m"}
structure.SetSecondaryStructure(math.random(1,structure.GetCount()), struct[math.random(1,#struct)])
end
actionDescription[#actionDescription+1]="random secondary structure"
--won't affect score until idealSS
--end import
---------
--insert new actions here before counting them --jon
NumberOfActions=#performAction+1 --jon
save.Quicksave(9)
print("debug actions")
for i=26,#performAction do --1 to skip mutate
save.Quickload(9)
starttime=os.clock()
startscore=current.GetEnergyScore()
print("debug action "..i..", "..actionDescription[i])
performAction[i]()
print("yield per sec "..(current.GetEnergyScore()-startscore)/(os.clock()-starttime+1))
end
end
initializeActions()
----------------
pokemons={}
for i=1,4 do
local pokemon={layers={},score=0} --"ogres are made of layers"
function newNeuron()
local neuron={
dendrites={math.random(-10,10)/10,math.random(-10,10)/10,math.random(-10,10)/10}
--weights (dentrites getting inputs from prev. neurons)
-- are factors to have a weighted importance
--for instance, if you're guessing the total weight of 2 elephants and 2 insects
--the number of elephants will be far more important
,
bias=math.random(-10,10)/10--can exceed
--bias in this case is like a T/F threshold. <50% on exam = F, you don't pass at all.
--some professors curve grades based on overall class grades
,
axon=0 --called neuron Value by techies. means neuron output
}
--print("neuron axon "..neuron.axon)
return neuron
end
layer={{axon=1},{axon=0},{axon=0}} --input layer, true, false
print("input neuron axon "..layer[1].axon)
table.insert(pokemon.layers,layer)
layer={} --new layer
--a Hidden Layer
--for XOR problem, set #neurons to 2
-- https://miro.medium.com/max/1346/1*bRoaMcjiD4yRjgfr2QGZcA.jpeg
for i=1,2 do
local neuron=newNeuron()
--print("my neuron "..neuron)
table.insert(layer,neuron)
end
print("done inserting neurons into first hidden")
table.insert(pokemon.layers,layer)
layer={} --new layer
--output layer
for i=1,1 do
local neuron=newNeuron()
table.insert(layer,neuron)
end
table.insert(pokemon.layers,layer)
table.insert(pokemons,pokemon)
end
gen=0
lastOutputTan=2
while true do
gen=gen+1
print("new gen "..gen)
for i=1,#pokemons do
starttime=os.clock()
--creditbest.Restore()
band.DeleteAll()
behavior.SetFiltersDisabled(false)
startscore=current.GetEnergyScore()
--puzzle.StartOver()
--puzzle.StartOver() --if multistart
for iAttack=1,6 do
selection.DeselectAll()
--selection.SelectAll()
selection.SelectRange(math.random(structure.GetCount()-3),math.random(structure.GetCount()))
--hopefully ends mutable if design but sadly not linker
--randomize inputs to test XOR
pokemons[i].layers[1][1].axon=lastOutputTan
pokemons[i].layers[1][2].axon=math.tanh((1+current.GetEnergyScore())/2) --math.random(0,1)
pokemons[i].layers[1][3].axon=behavior.GetClashImportance() --math.random(0,1)
--skip activation of first layer (input layer)
for iLayer=2,#pokemons[i].layers do
print("gen "..gen..", pokemon #"..i..", layer "..iLayer)
--print("layers is "..pokemons[i].layers)
print("layer length "..#pokemons[i].layers[iLayer])
for iNeuron=1,#pokemons[i].layers[iLayer] do
--"inputs go in times weights, summate, add a bias activate" --s. raval
sum=0
for iPrevNeuron=1,#pokemons[i].layers[iLayer-1] do --previous neurons
local input=pokemons[i].layers[iLayer-1][iPrevNeuron].axon
local dendrite=pokemons[i].layers[iLayer][iNeuron].dendrites[iPrevNeuron]
print("input "..input..", neuron weight "..dendrite)
sum=sum+input*dendrite
--input times weight of connection
end
print("sum "..sum)
--"inputs go in times weights, get sums" -s. raval
print("neuron bias "..pokemons[i].layers[iLayer][iNeuron].bias)
local axon=sum+pokemons[i].layers[iLayer][iNeuron].bias
--most people add bias instead of subtract bias but maybe it's easier visualizing
-- subtracting bias, so you can view the bias as a threshold, then you can write
-- if axon<=bias instead of axon<=.5
-- or something like axon<=threshold
--"pass that **** [stuff] to my sigmoid function" -s. raval
axon=math.tanh(axon)
--[[
--ReLU activation function, not really a sigmoid function like tangent
if axon <=0 then --.5 then
--axon=0 --ReLU, rectified learning unit. dying ReLU
-- graph: __/
aloha=.2 --alpha
axon=aloha*axon --leaky relu
end
]]--
pokemons[i].layers[iLayer][iNeuron].axon=axon
end
end
local brainOutput=pokemons[i].layers[#pokemons[i].layers][1].axon
print("brainOutput "..brainOutput)
--print(#performAction)
lastOutputTan=(math.tanh(brainOutput)+1)/2 --0 to 1
print("output tan "..lastOutputTan)
choice=math.floor((#performAction+.49)*lastOutputTan)
print(actionDescription[choice])
performAction[choice]()
--structure.WiggleAll(1) --debug
end --iAttack
komi=i--*6.5 --komidashi for playing 2nd
function orFunc(a,b) return math.max(1,a+b) end
function andFunc(a,b) return a*b end
function notFunc(a) return 1-a end
-- https://miro.medium.com/max/1346/1*bRoaMcjiD4yRjgfr2QGZcA.jpeg
xor= andFunc(
notFunc(andFunc(pokemons[i].layers[1][1].axon, pokemons[i].layers[1][2].axon)),
orFunc(pokemons[i].layers[1][1].axon, pokemons[i].layers[1][2].axon)
)
improv=(current.GetEnergyScore()-startscore)/(os.clock()-starttime+1)
--alpha for score rectifying, eg. 0.1
pokemons[i].score= math.max(0.0*improv,improv)--+komi -- -math.abs(error)
--[[
behavior.SetClashImportance(
math.min(1,math.max(0,(pokemons[i].score+100)/100)) --for visual
)
]]--
print("xor "..xor..", score "..pokemons[i].score..", 0 is best")
end
weakest=1
strongest=1
runnerup=1 --2nd best
for i=2,#pokemons do
if pokemons[i].score<pokemons[weakest].score then
weakest=i
end
if pokemons[i].score>pokemons[strongest].score then strongest=i
elseif pokemons[i].score>runnerup then
runnerup=i
end
end
print("weakest "..weakest..", evolving weakest carp to dragon")
i=weakest
shifu=strongest --in Kung Fu Panda, Shifu is the 2nd wisest
shifustring="shifu: "
--skip copying of first layer (input layer)
for iLayer=2,#pokemons[i].layers do
print("pokemon #"..i..", layer "..iLayer)
--print("layers is "..pokemons[i].layers)
--print("layer length "..#pokemons[i].layers[iLayer])
shifustring=shifustring.."\n layer "
for iNeuron=1,#pokemons[i].layers[iLayer] do
--shifu can be female, shimu means tutor's wife but gender is a hassle to code
--plus most CandyCrush pros are female
local shifuNeuron=pokemons[shifu].layers[iLayer][iNeuron]
local shimuNeuron=pokemons[runnerup].layers[iLayer][iNeuron]
noob=pokemons[i].layers[iLayer][iNeuron]
shifustring=shifustring..", neuron: dendrites: "
--we could do backpropagation, but that involves finding the policy gradient/slope
for iPrevNeuron=1,#pokemons[i].layers[iLayer-1] do --previous neurons
local shifuDendrite=shifuNeuron.dendrites[iPrevNeuron]
local shimuDendrite=shimuNeuron.dendrites[iPrevNeuron]
print("shifuDendrite weight "..shifuDendrite)
shifustring=shifustring..shifuDendrite..", "
if math.random(2)>1 then
allele=shifuDendrite
else
allele=shimuDendrite
end
pokemons[i].layers[iLayer][iNeuron].dendrites[iPrevNeuron]=
--tryhard disciple method
--noob.dendrites[iPrevNeuron]+(shifuDendrite-noob.dendrites[iPrevNeuron])*2
--pro vs pro
shimuNeuron.dendrites[iPrevNeuron]
+(shifuDendrite-shimuNeuron.dendrites[iPrevNeuron])*2
--valentine method
--(shifuDendrite+shimuDendrite)/2
--other half method
--allele
+math.random(-10,10)/1000
end
print("shifu's orig bias "..shifuNeuron.bias) --shifu not biased against MSG
shifustring=shifustring..", bias: "..shifuNeuron.bias
local allele
if math.random(2)>1 then
allele=shifuNeuron.bias
else
allele=shimuNeuron.bias
end
pokemons[i].layers[iLayer][iNeuron].bias=
--tryhard disciple method, kinda velocity gradient descent
--(noob.bias+(shifuNeuron.bias-noob.bias)*2
--Tutor says to chop a log, chop 2 logs
--tryhard pro method, note that I don't mean tryhard in the derogutory sense
-- but rather that imitation is a fast (albeit not as great as AlphaZero) method
--After all, I guess it's why stories unrealistically have happy endings
(shimuNeuron.bias+(shifuNeuron.bias-shimuNeuron.bias)*2)
--Eg. What can Starcraft pro Scarlett do to play like #1 Serral but better?
--Double Evo chamber or more creep tumors?
--This method finally got the a.i. to set clash 1
--valentine method, but kinda a social bubble stagnation
--"2 roads diverged in a yellow wood and the a.i. car barged down the middle" -GeoHot
--(shifuNeuron.bias+shimuNeuron.bias)/2
--half of genes
--allele
+math.random(-10,10)/1000 --Mozi likes precision
end
end
structure.SetNote(1,shifustring)
--print("end carp to dragon?")
--sometimes get bias of -0 negative zero. but -0==0 in lua.
end