Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- 0. general:
- GAB+EO Remix V7.923 by Crashguard303
- Copyright (C) 2013 Crashguard303 <http://fold.it/portal/user/119022>
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- 1. introduction:
- 1.1 inspired by:
- Cartoon Villain (GA idea & first random band script of this kind)
- Rav3n_pl (OO parameter/variable handling)
- jeff101 (EO & input-boxes idea)
- Batz ( input-boxes layout)
- 1.2 idea:
- -- further development of my last GAB+EO
- i wrote this version from scratch to improve table handling & modularity
- (coding did take 1 month,
- testing, documenting & frontend did take another month!)
- -- this script doesn't simply band to random segs,
- it will create:
- a list of "cardinal" origin segs (see 3.3.2.3)
- & connect them to target segs
- -- origin segs:
- -- are detected and/or set by user via selection interface (blue) before.
- -- don't change (they are just turned off or on)
- -- target segs:
- -- do vary (see 3.3.2.2)
- -- they can be
- -- each of uselist (see 3.3.2.2: all except "random 2")
- -- complete random (see 3.3.2.2: "random 2")
- -> this will avoid double banding
- -- new idea is to keep the number of random band parameters as small as they can be:
- the script works with 2 fixed band strengths (as the length is already random)
- -- primary bands: do seg movement in space or relative to any other seg (depending on band mode)
- -- secondary bands: do seg movement between proximate segs.
- they can be used to stabilize or move internal puzzle structure,
- so their job is supporting the primary bands with their major task
- -- as i didn't want to overload the starting sequence
- with too many input boxes & selectable vals (more than 7 boxes at the moment!).
- -> you can set all vals (even the other) in the declaration section.
- 1.3 features:
- -- cardinal seg auto-detection: (see 3.3.2.3)
- -- secondary-structure changes, amino-acids, etc will create a uselist
- -- locked (grey) segs will be detected
- -- and won't be used as origin segs
- -- but used as target segs
- ++ selected (blue) segs via game interface can be used as origin segs, too
- -- 3 breeding modes: (see 3.2)
- GA
- EO1
- EO2
- -- 2 gene modes: (see 3.2.2.2)
- "dual"
- "poly"
- -- 6 banding modes (see 3.3)
- "space"
- "center"
- "user"
- "furthest"
- "random1"
- "random2"
- ++ further settings for each
- 1.4 known bugs/problems:
- 1.4.1 ligand puzzles:
- -- are supported by script, but i couldn't test if it works properly!
- -> to band ligand:
- use band to "user", then slide to last segment!
- 1.4.2 locked (grey) puzzle segs:
- -- will be detected & used as target segs only (see 1.3)
- -- you have to select them, if they should be used as origin segs
- 1.5 more:
- 1.5.1 Further support:
- In future, I will have some examinations (and to learn other programming languages),
- so I won't have the time do care much about:
- -- script extensions,
- -- feature requests &
- -- spelling mistakes (or other lingual issues, as I'm not a native English speaker)
- I hope, the manual is complete in this way that it answers most questions.
- Maybe some other scripters can help you if there is a minor problem
- (setting default values etc).
- 1.5.2 "Frontend":
- There are already many input-boxes for the most important values included in this script.
- I neither wanted to write a full-automatic banding-robot (so I offered "a couple" of parameters)
- nor to annoy anybody with tons of inputboxes.
- But as long as we can't store files, we can change settings only:
- -- via input dialog boxes or
- -- by writing them directly into script code.
- So it's up to you to choose, which parameters you change and in which way.
- The strategy we choose is our human part in this game, the rest can ROSETTA do.
- The script should be stable if you don't mess up vital things.
- I tested it as good as I could with my limited internet-connection.
- 1.5.3 (default) Parameter customizing and uploading:
- If you find useful puzzle-adapted settings or script changes, you are free to post them
- (and your version of the script, too).
- Maybe you can recommend some settings (useful banding modes, thresholds... well, some puzzle-related things).
- Advice for coders/users with few experience:
- -please- don't just unlock some "hidden" features
- (e.g. by uncommenting some debugging functions or
- just adding some "prints", making the script more verbose but nothing more)
- and upload you personal customization as "reinvention of the wheel".
- A car doesn't go faster if you put some racing-stickers on it ;)
- For scripts, let's concentrate on functionality, the beauty will be found in good puzzle solutions.
- If everybody would change the script's appearance, we won't be able to fish out functional code anymore.
- I want the script to be kept modular and relatively universal
- + genetic, there are enough pure-random-band scripts already existing.
- This means removing some of "vital" code is a bad idea, too
- (apart from bug & performance fixes, of course).
- So, if you do some changes and upload your script, please tell us what you did change ;)
- (by posting the complete function section you did change, from "function" to "end")
- If you want your own (personal) default values instead of using dialog-boxes,
- use the declaration section to initialize them.
- Most people who are able to fill out their annual tax declaration (especially those with business education),
- should be able to modify some existing values in a complete script.
- It's just putting "the right" numbers to "the right" position.
- As changing the "fuse" batches (order & number of CIs, wiggles, shakes & mutates) is a more complex thing,
- I will help you with this... but please help other users, too ;)
- 2. abbreviations/terms you might find:
- 2.1 structure:
- gen: gen
- clu: cluster
- seg: segment
- dst: distance
- len: length
- str: strength
- itr: iterations
- 2.2 addressing:
- list: table
- idx: index (numerical)
- key: key (alphanumerical)
- val: value
- 2.3 vals:
- prm: parameter (argument)
- cur: current (measured)
- max: maximum
- min: minimum
- cng: change (to add)
- res: result (calculated)
- rnd: random (generated)
- 2.4 other:
- gui: frontend (dialog input box)
- 3. features:
- 3.1 terms & herd generating:
- This script (as GAB before) applies & tests combinations of random bands.
- one band combination set is named cluster (clu) here
- (GA-term: individuum).
- a testing row of different clus is a generation (gen)
- (by default, 1 generation consists of 8 clus = herd.size)
- when one gen has tested, it is evaluated.
- each clu is measured by it's score gain,
- gen will be sorted by clu's score gain, best on top.
- 3.2 analyzing & breeding:
- selection of of partners &
- breeding them (mutating, too)
- is the heart of a genetic algorithm !!!
- 3.2.1 analyzing:
- after testing each gen,
- clus are sorted by the score gain they made
- -> first clu is this with best gain,
- -> last clu is this with worst gain,
- 3.2.2 breeding:
- 3.2.2.1 selection via EO:
- EO mode decides what happens with mediocre clus:
- -- EO_mode.cur=0: mediocre clus are breeded (only this is GA)
- -- EO_mode.cur=1: mediocre clus are considered as best (soft EO)
- -- EO_mode.cur=2: mediocre clus are considered as worst (hard/real EO)
- best clus (always):
- -- are kept (default: cluster 1 & 2 = 1...herd.breed.first)
- and "breeded" = mixed to new ones.
- mediocre clus (EO_mode.cur=0):
- -- are overwritten by breeded ones
- (default: clu 3...5 = herd.breed.first to herd.breed.last)
- worst clus (always):
- -- are replaced by new random ones
- (default: clu 6...8 = herd.breed.last...herd.size)
- 3.2.2.2 sex (breed mode):
- -- imagine the clus as snails with both genders
- -- "poly": each single gene can be from any clu by roulette!
- -- "dual": 1 kid has only 2 parents (classic):
- -> dad is 1st breeding partner
- -> mom is 2nd breeding partner
- -- breeding partners can be chosen by:
- -> their rank: 1st has best score gain
- -> roulette: 1st appears most time, but all possible
- -> if you breed 3 kids,
- roulette combinations are:
- -- by default:
- herd.breed.roulette.dad==false
- herd.breed.roulette.mom==true
- -> kid#1: dad=clu#1 & mom#1=roulette
- -> kid#2: dad=clu#2 & mom#2=roulette
- -> kid#3: dad=clu#3 & mom#3=roulette
- -- other setting:
- herd.breed.roulette.dad==false
- herd.breed.roulette.mom==false
- -> kid#1: dad=clu#1 & mom#1=dad#1+1=clu#2
- -> kid#2: dad=clu#2 & mom#2=dad#2+1=clu#3
- -> kid#3: dad=clu#3 & mom#3=dad#3+1=clu#4
- -- other setting:
- herd.breed.roulette.dad==true
- herd.breed.roulette.mom==false
- -> kid#1: dad#1=roulette & mom#1=dad#1+1
- -> kid#2: dad#2=roulette & mom#2=dad#2+1
- -> kid#3: dad#3=roulette & mom#3=dad#3+1
- -- other setting:
- herd.breed.roulette.dad==true
- herd.breed.roulette.mom==true
- -> kid#1: dad#1=roulette & mom#1=roulette
- -> kid#2: dad#2=roulette & mom#2=roulette
- -> kid#3: dad#3=roulette & mom#3=roulette
- 3.3 applying bands to segments:
- 3.3.1 types of connections:
- The clus which are tested will be not only from seg to seg anymore (like in old GAB)
- but also from seg to free space (if using clu.band_to.val="space"),
- allowing more freedom of direction.
- 3.3.2 origin segs & target segs:
- 3.3.2.1 origin segs:
- -- are always the same
- -- i did this to prevent double banding, simplifiy breeding
- & keeping the clu's gene-length homogenous
- -> you can't crossbreed a horse with a zebra because their DNAs have different lengths
- -> in real life, DNA also doesn't change length.
- genes remain, they are just active or inactive !
- -- segs which can be banded & their banding order
- are stored in a uselist (selection)
- -> but you can turn some off & change their activity by mutation
- -> you can set them in the seg_use table declaration
- 3.3.2.2 target segs:
- -- can be different, depending on mode clu.band_to.val:
- -- origin segs can be banded to
- -> "space": no seg, but to "air" (more freedom of movement,
- but no reference to other segs anymore)
- -> "center": calculated seg (real center seg)
- -> "user": selected seg (pseudo "center" seg internally)
- -> "furthest": calculated seg (furthest to origin seg)
- -> "random1": another seg in seg_use list (given in table)
- -> "random2": rnd seg in puzzle (all available)
- 3.3.2.3 if no list is given (in declaration section):
- -- if you
- -- neither change the seg_use list to your needs
- -- nor select any seg by game interface:
- -> by default, only these segs are banded,
- where changes in secondary structures do occur
- & which do have special residues (default: Glycine)
- -> key idea of this new script !!!
- 3.3.3 band strength:
- -- is constant for all bands now (unlike to old GAB),
- as the length is already set by random.
- -> but you can set the global band strength
- for primary & secondary bands (not always used)
- --]]
- function random_seed_set_val(random_seed)
- local random_seed= random_seed
- if (random_seed==nil) or (random_seed=="") then
- random_seed=os.time()+recipe.GetRandomSeed()
- else
- random_seed= tonumber(random_seed)
- end -- if random_seed
- print('Random Seed: '..random_seed)
- math.randomseed(random_seed) -- initialize random seed
- return random_seed
- end -- function randomseed
- function above0(x)
- if x>0 then
- return 1
- else -- if x<=0
- return -1
- end -- if x
- end -- function above0
- function crop_digits(x,n)
- local y=x
- y=y*10^n
- y=math.floor(y)
- y=y*10^(-n)
- return y
- end -- function crop_digits
- function range_wrap(x,min,max,offset)
- --[[
- prevent x getting higher than max
- or lower than min
- if x gets out of range, it is set to the other boundary+it's exceeding amount
- if x>max, val will be >min, if offset is 0 & float vals are used
- or =min, if offset is 1 & integer vals are used
- if x<min, val will be <max, if offset is 0 & float vals are used
- or =min, if offset is 1 & integer vals are used
- example:
- range_wrap(1.1,0,1,0) will return 0.1 (x is by .1 >1, so it is set next to 0+.1)
- range_wrap(-.1,0,1,0) will return 0.9 (x is by .1 <0, so it is set next to 1-.1)
- range_wrap(11,0,10,0) will return 1 (x is by 1 >10, so it is set to 0+1)
- range_wrap(-1,0,10,0) will return 9 (x is by 1 <10, so it is set to 10-1)
- range_wrap(11,0,10,1) will return 0 (x is by 1 >10, so it is set to 0+1-1)
- range_wrap(-1,0,10,1) will return 10 (x is by 1 < 0, so it is set to 10-1+1)
- --]]
- local y=x+0
- if y>max then
- y=min+(y-max)-offset
- elseif y<min then
- y=max+(y-min)+offset
- end -- if y
- return y
- end -- function range_wrap
- function range_clamp(x,min,max)
- --[[
- prevent x getting higher than max by setting it to max
- or lower than min by setting it to min
- --]]
- local y=x+0
- if y>max then
- y=max
- elseif y<min then
- y=min
- end -- if y
- return y
- end -- range_clamp()
- function random_flag1(prob)
- --[[
- return true or false randomly, depending on prob(ability)
- probability should be a float val between 0...1 as
- vals <0 have the same effect as =0 &
- vals >1 have the same effect as =1
- returns true, if
- prob=0: never
- prob=0.1: sometimes
- prob=0.5: quite as often as false
- prob=0.9: most times
- prob=1: always
- calculation example:
- -- if you want it to respond true
- -- in 1 of 10 cases
- -- use 1/10= 0.1
- --]]
- return (math.random()<prob)
- end -- function random_flag1
- function random_flag2(prob,invert,bool)
- -- return val like random_flag1(), but
- -- invert=true inverts val
- -- bool=false converts boolean vals
- -- true -> 1
- -- false -> 0
- local val=random_flag1(prob)
- if invert then
- val= not(val)
- end -- if invert
- if bool==false then
- if val then
- val= 1
- else
- val= 0
- end -- if val
- end -- if bool
- return val
- end -- function random_flag2
- function list_show_deep(list,text)
- -- full key & val as string - advanced
- -- indexing: pairs
- if text==nil then
- text=tostring(list)
- end -- if text
- local k,v
- for k,v in pairs(list) do
- local ktext
- if type(k)=="number" then
- ktext= text..'['..tostring(k)..']'
- else
- ktext= text..'.'..tostring(k)
- end -- if type(k)
- if type(v)=="table" then
- list_show_deep(v,ktext)
- else
- local vtext
- if (type(v)=="number") or (type(v)=="boolean") then
- vtext= tostring(v)
- else
- vtext= '\"'..tostring(v)..'\"'
- end -- if type(v)
- print(ktext..'='..vtext)
- end -- if type(v)
- end -- for k
- end -- function list_show_deep
- function puzzle_ismutable()
- local ismutable= false
- for i=1,puzzle.seg_count do
- if structure.IsMutable(i) then
- ismutable= true
- break -- for i
- end -- if structure.IsMutable
- end -- for i
- return ismutable
- end -- function puzzle_ismutable
- function puzzle_isligand()
- local isligand
- if structure.GetSecondaryStructure(puzzle.seg_count)==not(ss=="L" or ss=="H" or ss=="E" ) then
- isligand= true
- else
- isligand= false
- end -- if structure.GetSecondaryStructure
- print('Ligand detected: '..tostring(isligand))
- return isligand
- end -- function puzzle_isligand
- function seg_blocks(blocks)
- -- create a list of mutlitple segment sections
- -- example:
- -- blocks={{1;3};{7;10}}
- -- results list={1;2;3;7;8;9;10}
- local list={}
- local i
- for i=1,#blocks do
- local j
- for j=blocks[i][1],blocks[i][2] do
- print('Appending Idx:'..(#list+1)..'=Seg:'..j)
- table.insert(list,j)
- end -- for j
- end -- for i
- return list
- end -- function seg_blocks
- function seg_use_list_create(seg_use)
- -- table seg_use contains
- -- associative keys - their vals are information for creating the:
- -- numerical keys - their vals are a list, which puzzle segment indices can be used
- local seg_use=seg_use
- print('Appending segs with idx given in table...')
- seg_use=seg_use_list_append(seg_use,seg_use.include.idx)
- if seg_use.include.selected.act then
- print('Appending segs depending on selection: '..tostring(seg_use.include.selected.val)..'...')
- seg_use=seg_use_list_append(seg_use,seg_list_selected_get(seg_use.include.selected.val))
- end -- seg_use.include.selected.act
- selection.DeselectAll()
- if seg_use.include.frozen.act then
- print('Appending segs depending on freeze: backbone: '..tostring(seg_use.include.frozen.backbone)..' sidechain:'..tostring(seg_use.include.frozen.sidechain))
- seg_use=seg_use_list_append(seg_use,seg_list_frozen_get(seg_use.include.frozen.backbone,seg_use.include.frozen.sidechain))
- end -- seg_use.include.frozen.act
- if seg_use.include.ss_cngs then
- print('Appending segs, where structure changes do occur...')
- seg_use=seg_use_list_append(seg_use,ss_cngs_get_seg_list())
- end -- if seg_use.include.ss_cngs
- print('Appending segs with ss given in table...')
- seg_use=seg_use_list_append(seg_use,seg_list_ss_get(seg_use.include.ss))
- print('Appending segs with aa given in table...')
- seg_use=seg_use_list_append(seg_use,seg_list_aa_get(seg_use.include.aa))
- seg_use=seg_use_filter(seg_use)
- -- sort seg list &
- -- remove duplicate entries
- print('Removing segs which are locked...')
- seg_use=seg_use_list_remove(seg_use,seg_list_locked_get())
- print('Removing segs with idx given in table...')
- seg_use=seg_use_list_remove(seg_use,seg_use.exclude.idx)
- if seg_use.exclude.selected.act then
- print('Removing segs depending on selection: '..tostring(seg_use.exclude.selected.val)..'...')
- seg_use=seg_use_list_remove(seg_use,seg_list_selected_get(seg_use.exclude.selected.val))
- end -- seg_use.exclude.selected.act
- if seg_use.exclude.frozen.act then
- print('Remove segs depending on freeze: backbone: '..tostring(seg_use.exclude.frozen.backbone)..' sidechain:'..tostring(seg_use.exclude.frozen.sidechain))
- seg_use=seg_use_list_remove(seg_use,seg_list_frozen_get(seg_use.exclude.frozen.backbone,seg_use.exclude.frozen.sidechain))
- end -- seg_use.exclude.frozen
- print('Removing segs with ss given in table...')
- seg_use=seg_use_list_remove(seg_use,seg_list_ss_get(seg_use.exclude.ss))
- print('Removing segs with aa given in table...')
- seg_use=seg_use_list_remove(seg_use,seg_list_aa_get(seg_use.exclude.aa))
- print('\nScript will use these segs:')
- for i=1,#seg_use do
- print(i..': '..seg_use[i])
- end -- for i
- return seg_use
- end -- function seg_use_list_create
- function seg_use_list_append(use_idx,append_idx)
- local use_idx=use_idx
- if seg_use.append_all~=false then
- seg_use.append_all=true
- end -- if seg_use.append_all
- -- if seg_use.append_all is not false
- -- force it to be true
- -- as no other vals are allowed
- if seg_use.append_all then
- use_idx=seg_use_list_append_all(use_idx,append_idx)
- else -- if seg_use.append_all~=true
- use_idx=seg_use_list_append_missing(use_idx,append_idx)
- end -- if seg_use.append_all
- return use_idx
- end -- function seg_use_list_append
- function seg_use_list_append_all(use_idx,append_idx)
- local use_idx=use_idx
- local i
- for i=1,#append_idx do
- -- print('Appending Idx:'..(#use_idx+1)..'=Seg:'..append_idx[i])
- table.insert(use_idx,append_idx[i])
- end -- for i
- return use_idx
- end -- function seg_use_list_append_all
- function seg_use_list_append_missing(use_idx,append_idx)
- local use_idx=use_idx
- local i
- for i=1,#append_idx do
- if val_isintable(use_idx,append_idx[i])==false then
- print('Appending Idx:'..(#use_idx+1)..'=Seg:'..append_idx[i])
- table.insert(use_idx,append_idx[i])
- end -- if val_isintable
- end -- for i
- return use_idx
- end -- function seg_use_list_append_missing
- function val_isintable(list,valsearch)
- -- return:
- -- true: if list does contain valsearch
- -- false: if list doesn't contain valsearch
- if #list==0 then
- return false
- else
- return key_getbyval(list,valsearch)~=nil
- end -- if #list
- end -- function val_isintable
- function key_getbyval(list,valsearch)
- -- check all keys in table list
- -- return first found key which has valsearch
- local keyres=nil
- local key,val
- for key,val in pairs(list) do
- -- with key loop, cycle through all keys
- -- for each key, get its val
- if val==valsearch then
- -- if val found
- keyres= key
- -- return it's key
- break -- key,val
- -- break key loop
- end -- if val
- end -- key loop
- return keyres
- end -- function key_getbyval
- function seg_use_list_remove(use_idx,remove_idx)
- local use_idx=use_idx
- local i=1
- for i=1,#remove_idx do
- local j=1
- while j<=#use_idx do
- if use_idx[j]==remove_idx[i] then
- print('Removing Idx:'..j..'=Seg:'..use_idx[j])
- table.remove(use_idx,j)
- j=j-1
- end -- if use_idx
- j=j+1
- end -- while j
- end -- for i
- return use_idx
- end -- function seg_use_list_remove
- function seg_use_filter(seg_use)
- -- sort list by seg idx numbers &
- -- remove duplicate entries
- local seg_use=seg_use
- -- leave seg_use.sort_ascending as it is, as it is allowed to be nil
- print('Sorting segs ascending: '..tostring(seg_use.sort_ascending))
- if seg_use.remove_double~=false then
- seg_use.remove_double=true
- end -- if seg_use.remove_double
- -- if seg_use.remove_double is not false
- -- force it to be true
- -- as no other vals are allowed
- print('Checking & removing double segs:'..tostring(seg_use.remove_double))
- local i=1
- while i<=(#seg_use-1) do
- local j=i+1
- while j<=#seg_use do
- if seg_use[i]==seg_use[j] then
- -- if two elements in list are equal
- if seg_use.remove_double then
- -- print('Removing idx:'..j..' = Seg:'..seg_use[j])
- table.remove(seg_use,j)
- j=j-1
- -- as element at position j was removed,
- -- another one might have moved up to position j
- end -- if seg_use.remove_double
- elseif ((seg_use[i]>seg_use[j])==seg_use.sort_ascending) then
- -- if they are not equal
- -- & they don't have the order as given in seg_use.sort_ascending
- -- print('Swapping idx:'..i..'=Seg:'..seg_use[i]..' with idx:'..j..'=Seg:'..seg_use[j])
- seg_use[i],seg_use[j]=seg_use[j],seg_use[i]
- end -- if seg_use
- j=j+1
- end -- for j
- i=i+1
- end -- while i<=(#seg_use-1)
- return seg_use
- end -- function seg_use_filter
- function seg_list_locked_get()
- local seg_found={}
- local i
- for i=1,puzzle.seg_count do
- if structure.IsLocked(i) then
- table.insert(seg_found,i)
- end -- if structure.IsLocked
- end -- for i
- return seg_found
- end -- function seg_list_locked_get
- function ss_cngs_get_seg_list()
- -- check all secondary strucutres of puzzle &
- -- return a list, whre structure changes do occur
- local seg_found={}
- local seg_count2= puzzle.seg_count-1
- local i=1
- while i<seg_count2 do
- local ss1=structure.GetSecondaryStructure(i)
- local ss2=structure.GetSecondaryStructure(i+1)
- -- check ss of seg with idx i & i+1
- if ss1~=ss2 then
- -- are ss different?
- -- primary, we want to find segs with loop-ss at the end of helix or sheet sections
- -- but sometimes helices are directly near sheets
- if ss1=="L" then
- -- loop found at i? (then other ss is behind i) then
- table.insert(seg_found,i)
- elseif ss2=="L" then
- -- loop found near i? (then other ss is at i)
- table.insert(seg_found,(i+1))
- i=i+1
- elseif ss1=="H" then
- -- helix found at i? (then other ss (but no loop) is behind i)
- table.insert(seg_found,i)
- elseif ss2=="H" then
- -- helix found near i? (then other ss (but no loop) is at i)
- table.insert(seg_found,(i+1))
- i=i+1
- end -- if ssx==ss
- end -- if ss1~=ss2
- i=i+1
- end -- while i<seg_count2
- return seg_found
- end -- function ss_cngs_get_seg_list
- function seg_list_selected_get(selected_flag)
- local seg_found={}
- local i
- for i=1,puzzle.seg_count do
- if selection.IsSelected(i)==selected_flag then
- table.insert(seg_found,i)
- end -- if selection.IsSelected
- end -- for i
- return seg_found
- end -- seg_list_selected_get
- function seg_list_frozen_get(backbone_flag,sidechain_flag)
- local seg_found={}
- local i
- for i=1,puzzle.seg_count do
- local backbone,sidechain=freeze.IsFrozen(i)
- if (backbone==backbone_flag) and (sidechain==sidechain_flag) then
- table.insert(seg_found,i)
- end -- if backbone,sidechain
- end -- for i
- return seg_found
- end -- function seg_list_frozen_get
- function ss_cngs_show(structure_cngs_get,freeze_flag1,freeze_flag2)
- selection.DeselectAll()
- freeze.UnfreezeAll()
- print("Found changes:")
- local i
- for i=1,#seg_use do
- -- by variable i, cycle through all segs in list which have been found
- print(i..': '..seg_use[i])
- -- show seg number
- selection.Select(seg_use[i])
- -- select seg number
- end -- for i
- freeze.FreezeSelected(freeze_flag1,freeze_flag2)
- -- if flags are set, freeze selected segs, backbone and/or sidechains
- selection.DeselectAll()
- end -- function ss_cngs_show
- function seg_list_ss_get(use_ss)
- local seg_found={}
- local i
- for i=1,#use_ss do
- local j
- for j=1,puzzle.seg_count do
- if structure.GetSecondaryStructure(j)==use_ss[i] then
- -- print(j..': '..structure.GetSecondaryStructure(j))
- table.insert(seg_found,j)
- end -- if structure.GetSecondaryStructure
- end -- for j
- end -- for i
- return seg_found
- end -- function seg_list_ss_get
- function seg_list_aa_get(use_aa)
- local seg_found={}
- local i
- for i=1,#use_aa do
- local j
- for j=1,puzzle.seg_count do
- if structure.GetAminoAcid(j)==use_aa[i] then
- -- print(j..': '..structure.GetAminoAcid(j))
- table.insert(seg_found,j)
- end -- if structure.GetAminoAcid
- end -- for j
- end -- for i
- return seg_found
- end -- function seg_list_aa_get
- function seg_center_get()
- if (puzzle.seg_center.get_mode=="start") and (puzzle.seg_center.val~=nil) then
- -- start center seg is to get & center seg is set
- print('Stored center seg: '..puzzle.seg_center.val)
- return puzzle.seg_center.val
- -- use stored center seg
- else
- -- start center seg is not to get or center seg is not set
- -- current center seg is to get
- puzzle.seg_center.val= seg_center_get2()
- -- get current center seg
- return puzzle.seg_center.val
- end -- if puzzle.seg_center.get_mode,puzzle.seg_center.val
- end -- function seg_center_get
- function seg_center_get2()
- --[[
- find center seg of puzzle:
- -- for each seg:
- -- measure it's dst to all other segs &
- -- sum these dsts up
- -> center seg has lowest sum of dsts
- --]]
- -- print ('Getting center segment.')
- local dist_sum={min=math.huge;min_issegidx=0}
- local i
- for i=1,puzzle.seg_count do
- dist_sum.cur=0
- local j
- for j=1,puzzle.seg_count do
- dist_sum.cur=dist_sum.cur+structure.GetDistance(i,j)
- end -- for j
- -- print('Distance sum for #'..i..' = '..dist_sum.cur)
- if dist_sum.cur<dist_sum.min then
- dist_sum.min=dist_sum.cur
- dist_sum.min_issegidx=i
- -- print('Distance sum min hit!')
- -- print('Distance sum min: #'..dist_sum.min_issegidx..' = '..dist_sum.min)
- end -- if dist_sum.cur
- end -- for i
- -- print('Distance sum min: #'..dist_sum.min_issegidx..' = '..dist_sum.min)
- -- similar to:
- print('Current center seg: '..dist_sum.min_issegidx)
- return dist_sum.min_issegidx
- end -- function seg_center_get2
- function seg_furthest_get(seg_target)
- -- print ('Getting furthest segment to seg#'..seg_target)
- local dist={max=0;max_issegidx=0}
- local i
- for i=1,puzzle.seg_count do
- dist.cur= structure.GetDistance(seg_target,i)
- if dist.cur>dist.max then
- dist.max= dist.cur
- dist.max_issegidx=i
- -- print('Distance max hit!')
- -- print('Distance max: #'..dist.max_issegidx..' = '..dist.max)
- end -- if dist.cur
- end -- i
- -- print('Distance max: #'..dist.max_issegidx..' = '..dist.max)
- return dist.max_issegidx
- end -- seg_furthest_get
- function herd_generate(clu,first,last)
- print('Generating herd from '..first..' to '..last..'...')
- local i
- for i=first,last do
- -- print('Generating clu: '..i)
- clu[i]={}
- local j
- for j=1,#seg_use do
- -- with j, cycle through all segment indices given in seg uselist
- -- print('--seg:'..j..'use:'..seg_use[j])
- clu[i][j]=band_generate(j)
- -- create clu band
- end -- for i
- clu[i].name=clu_name_get(i,"r")
- end -- for i
- return clu
- end -- function herd_generate
- function band_generate(seg_cur)
- local band={act=random_flag2(herd.mutate.prob.off,true,true)}
- -- depending on random flag (influenced by herd.mutate.prob.off),
- -- turn off band when indicated
- if clu.band_to.val=="space" then
- -- following vals are pure random float numbers between 0...<1
- band.rho= math.random()
- band.theta= math.random()
- -- band.theta= .5;
- band.phi= math.random()
- else
- band.d_cng1= math.random()
- if clu.band_to.val=="random" then
- -- random segs?
- if puzzle.seg_random.get_mode=="list" then
- -- random seg in list ?
- repeat
- band.seg_target= seg_use[math.random(1,#seg_use)]
- until band.seg_target~=seg_use[seg_cur]
- -- prevent banding seg to itself
- -- print('Random seg target of list: '..band.seg_target..' (not '..seg_use[seg_cur]..')')
- else -- puzzle.seg_random.get_mode=="all"
- -- random seg in puzzle ?
- repeat
- band.seg_target= math.random(1,puzzle.seg_count)
- until band.seg_target~=seg_use[seg_cur]
- -- prevent banding seg to itself
- -- print('Random seg target of all: '..band.seg_target..' (not '..seg_use[seg_cur]..')')
- end -- if puzzle.seg_random.get_mode
- end -- if clu.band_to.val
- end -- if clu.band_to.val
- if clu.d_cng2.act then
- -- secondary bands are used
- band.d_cng2= math.random()
- end -- if clu.d_cng2.act
- return band
- end -- function band_generate
- function herd_mutate(clu,first,last)
- local clu= clu
- print('Mutating herd from '..first..' to '..last..'...')
- local i
- for i=first,last do
- if herd.mutate.genes_show.act then
- print('Mutating clu#'..i)
- end -- if if herd.mutate.genes_show.act
- local j
- for j=1,#clu[i] do
- if herd.mutate.genes_show.act then
- print('Mutating band#'..j)
- end -- if herd.mutate.genes_show.act
- clu[i][j]=band_mutate(clu[i][j])
- end -- for j
- end -- for i
- return clu
- end -- function herd_mutate
- function band_mutate(clu_band)
- local band={act=mutate_bool_val(clu_band.act)}
- if clu.band_to.val=="space" then
- band.rho= mutate_float_val(clu_band.rho)
- band.theta= mutate_float_val(clu_band.theta)
- band.phi= mutate_float_val(clu_band.phi)
- else
- band.d_cng1= mutate_float_val(clu_band.d_cng1)
- if clu.band_to.val=="random" then
- band.seg_target= mutate_int_seg(clu_band.seg_target)
- end -- if clu.band_to.val
- end -- if clu.band_to.val
- if clu.d_cng2.act then
- -- secondary bands are used
- band.d_cng2= mutate_float_val(clu_band.d_cng2)
- end -- if clu.d_cng2.act
- return band
- end -- function band_mutate
- function mutate_bool_val(val)
- -- depending on herd.mutate.prob.vals
- -- possibly toggle band activity:
- -- band on -> band off
- -- band off -> band on
- local val= val or false
- -- break reference
- if random_flag1(herd.mutate.prob.vals) then
- -- has random hit possibility?
- mutate_val_show('Old',val)
- val= not(val)
- -- invert boolean
- mutate_val_show('New',val)
- return val
- else
- return val
- end -- if random_flag1
- end -- function mutate_bool_val
- function mutate_float_val(val)
- -- depending on herd.mutate.prob.vals
- -- possibly change normalized val 0...1
- -- by a random amount between +/-10^(min...max)
- local val= val+0
- -- break reference
- if random_flag1(herd.mutate.prob.vals) then
- -- has random hit possibility?
- mutate_val_show('Old',val)
- val= val+(math.random(0,1)*2-1)*(10^(math.random(herd.mutate.rng10e.min,herd.mutate.rng10e.max)))
- val= range_wrap(val,0,1,0)
- mutate_val_show('New',val)
- return val
- else
- return val
- end -- if random_flag1
- end -- function mutate_float_val
- function mutate_int_seg(val)
- -- depending on herd.mutate.prob.vals
- -- possibly change segment idx
- -- by a random amount between +/-1
- local val= val+0
- -- break reference
- if random_flag1(herd.mutate.prob.vals) then
- -- has random hit possibility?
- mutate_val_show('Old',val)
- val= val+(random_flag2(0.6,false,false)*2-1)
- -- 0.6 (0.5 would be 50:50) means appearing:
- -- +1: more often
- -- -1: less often
- val= range_wrap(val,1,puzzle.seg_count,1)
- mutate_val_show('New',val)
- return val
- else
- return val
- end -- if random_flag1
- end -- function mutate_float_val
- function mutate_val_show(text,val)
- if herd.mutate.genes_show.act then
- print(text..' val: '..tostring(val))
- end -- if herd.mutate.genes_show.act
- end -- function mutate_val_show
- function clu_name_get(idx,kind)
- -- create a table with following name elements:
- return {
- gen=gen.cur;
- clu=idx;
- knd=kind;
- dat=os.date()
- }
- end -- function clu_name_get
- function clu_name_get_string(clu_name,dat_flag)
- local OS=""
- OS= OS..'G'..clu_name.gen
- OS= OS..'C'..clu_name.clu
- OS= OS..'K'..clu_name.knd
- if dat_flag then
- OS= OS..'D'..clu_name.dat
- end -- if dat_flag
- return OS
- end -- function clu_name_get
- function clu_apply_bands(band_use)
- -- apply all bands which are:
- -- fixed
- -- stored in current clu (passed by table band_use)
- -- for each band pair, depending on mode clu.band_to.val
- -- connect origin seg (given in uselist)
- -- to another seg ("center", "furthest", "random") or
- -- to "space"
- -- apply fixed bands given in clu.fix:
- local i
- for i=1,#clu.fix do
- -- print(clu.fix[i][1],clu.fix[i][2])
- band.AddBetweenSegments(clu.fix[i][1],clu.fix[i][2])
- local len= structure.GetDistance(clu.fix[i][1],clu.fix[i][2])+clu.fix.lencng
- len= range_clamp(len,clu.band_sys_lim.min,clu.band_sys_lim.max)
- band.SetGoalLength(band.GetCount(),len)
- band.SetStrength(band.GetCount(),clu.fix.str)
- end -- for i
- local seg_center
- if clu.band_to.val=="center" then
- -- banding to "center" is used
- -- alternative:
- -- if (clu.band_to.val=="center") or (clu.band_to.val=="space") then
- -- banding to "center" or "space" is used
- seg_center= seg_center_get()
- -- get current center segment
- -- fetch it before cycling through all clu bands,
- -- as it is the same each time
- end -- if clu.band_to.val
- -- appply random bands given in clu:
- for i=1,#band_use do
- -- with i, cycle through all clu bands & their data
- if band_use[i].act then
- -- only if current band i is act (gene is not off)
- local seg_origin= seg_use[i]
- -- get origin seg to band from seg uselist
- if clu.band_to.val=="space" then
- -- if banding to space, but not to other segs
- -- get
- -- axis reference seg indices (seg_axis_x,seg_axis_y) &
- -- calculated here
- -- spatial vals (rho, theta,phi) from normalzed vals
- -- given by clu data
- local seg_axis_x= seg_get_idx("usepuzz",seg_origin,-1)
- -- band x-angle reference is previous seg in puzzle
- local seg_axis_y= seg_get_idx("usepuzz",seg_origin,1)
- -- band y-angle reference is next seg in puzzle
- -- alternative:
- -- local seg_axis_y= seg_center
- -- band y-angle reference is center seg in puzzle
- -- rho uses band str1
- band.Add2(i,
- seg_origin,
- seg_axis_x,
- seg_axis_y,
- band_use[i].rho,
- band_use[i].theta,
- band_use[i].phi,
- clu.pull.str1)
- else -- (clu.band_to.val=="center") or (clu.band_to.val=="furthest") or (clu.band_to.val=="random") then
- -- not banding to space, but to other segs
- -- having a relative dst or are random
- -- calculated here
- local seg_target1
- if clu.band_to.val=="center" then
- seg_target1= seg_center
- -- primary target seg is center seg in puzzle
- elseif clu.band_to.val=="furthest" then
- seg_target1= seg_furthest_get(seg_origin)
- -- primary target seg is furthest to origin seg
- elseif clu.band_to.val=="random" then
- seg_target1= band_use[i].seg_target
- -- primary target seg is random
- else-- clu.band_to.val has other val
- assert(false,'function clu_apply_bands: clu.band_to.val is invalid: '..tostring(clu.band_to.val))
- end -- if clu.band_to.val
- -- primary target seg uses band str1
- band.AddBetweenSegments2(i,
- seg_origin,
- seg_target1,
- band_use[i].d_cng1,
- clu.d_cng1.min,
- clu.d_cng1.max,
- clu.pull.str1)
- end -- if clu.band_to.val
- if clu.d_cng2.act then
- -- secondary bands are used
- local seg_target2= seg_get_idx("uselist",i,1)
- -- secondary target seg is next in seg uselist
- -- secondary target seg uses band str2
- band.AddBetweenSegments2(i,
- seg_origin,
- seg_target2,
- band_use[i].d_cng2,
- clu.d_cng2.min,
- clu.d_cng2.max,
- clu.pull.str2)
- end -- if clu.d_cng2.act
- else
- -- print('B#'..i..' off')
- end -- if band_use[i].act
- end -- for i
- end -- function clu_apply_bands
- function seg_get_idx(seg_option,val,offset)
- if seg_option=="uselist" then
- return seg_use[range_wrap((val+offset),1,#seg_use,1)]
- -- offset=+1 : angle reference is next seg in uselist
- -- offset=-1 : angle reference is prev seg in uselist
- elseif seg_option=="usepuzz" then
- return range_wrap((val+offset),1,puzzle.seg_count,1)
- -- offset=+1 : angle reference is next seg in puzzle
- -- offset=-1 : angle reference is prev seg in puzzle
- else
- assert(false, 'function seg_get_idx: seg_option has invalid val: '..tostring(seg_get_idx))
- end -- if seg_option
- end -- function seg_get_idx
- function band.Add2(i,
- seg_origin,
- seg_axis_x,
- seg_axis_y,
- rho,
- theta,
- phi,
- str)
- -- print(i,seg_origin,seg_axis_x,seg_axis_y,rho,theta,phi,str)
- local seg_axis_y,cng_flag= seg_axis_y_check_idx(seg_origin,seg_axis_x,seg_axis_y)
- -- avoid seg_axis_y having the same val as seg_axis_x
- if (cng_flag and clu.band_skip_wrong)==false then
- local R= rho^(1/3) + 0.001
- -- bend val rho 0..1 towards 1 by cubic root giving val R
- local rho= R*(clu.rho.max-clu.rho.min)+clu.rho.min
- -- stretch R 0...1 to min...max giving rho again
- rho= range_clamp(rho,0,clu.band_sys_lim.max)
- -- rho within limits?
- local theta= math.acos(2*theta-1)+0
- -- x-angle (azimut) range: 180 degrees (here: pi)
- local phi= 2*math.pi*phi+0
- -- y-angle (elevation) range: 360 degrees (here: 2*pi)
- local band_count1= band.GetCount()
- -- check number of bands before applying another band
- band.Add(seg_origin,
- seg_axis_x,
- seg_axis_y,
- rho,
- theta,
- phi)
- local band_count2= band.GetCount()
- -- check number of bands after applying another band
- if band_count1~=band_count2 then
- -- only if band has been created
- -- show its attributes
- print(
- 'B#'..i..
- ' Seg#'..seg_origin..
- ':('..seg_axis_x..
- '&'..seg_axis_y..
- ') Rho:'..crop_digits(rho,3)..
- ' Theta:'..crop_digits(math.deg(theta),3).."o"..
- -- ..string.char(39)..
- ' Phi:'..crop_digits(math.deg(phi),3).."o"..
- ' Str:'..crop_digits(str,3)
- )
- band.SetStrength(band_count2,str)
- -- change str
- else
- print('B#'..i..' skipped')
- end -- if band_count
- else
- print('B#'..i..' skipped')
- end -- if (cng_flag and clu.band_skip_wrong) == false
- end -- function band.Add2
- function seg_axis_y_check_idx(seg_origin,seg_axis_x,seg_axis_y)
- -- avoid seg_axis_y having the same val as seg_axis_x or seg_origin
- local seg_axis_y= seg_axis_y
- -- print('seg_axis_y: '..seg_axis_y)
- local cng_flag= false
- if (seg_axis_y==seg_axis_x) or (seg_axis_y==seg_origin) then
- seg_axis_y= range_wrap((seg_origin+1),1,puzzle.seg_count,1)
- cng_flag= true
- end -- if seg_axis_y
- --[[
- if cng_flag then
- print('Value changed')
- end -- if cng_flag
- --]]
- return seg_axis_y,cng_flag
- end -- function seg_axis_y_check_idx
- function band.AddBetweenSegments2(i,
- seg_origin,
- seg_target,
- d_cng,
- d_cng_min,
- d_cng_max,
- str)
- -- print(i,seg_origin,seg_target,d_cng,d_cng_min,d_cng_max,str)
- seg_target,cng_flag= seg_target_check_spat(seg_origin,seg_target)
- -- avoid seg_target beeing too close to seg_origin
- if (cng_flag and clu.band_skip_wrong)==false then
- local dst= structure.GetDistance(seg_origin,seg_target)
- local cng= (d_cng-0.5)*2
- -- as d_cng is a normalized val 0...1 internally
- -- (i don't want to mess with band lens before)
- -- stretch it to -1...1
- -- print('D_cng:'..crop_digits(d_cng,3)..' Cng:'..crop_digits(cng,3))
- local sign= above0(cng)
- -- -1: compression
- -- +1: expansion
- cng= sign*(math.abs(cng)*(d_cng_max-d_cng_min)+d_cng_min)
- -- as sign is stored now, truncate it from cng,
- -- resulting an absoulte val 0...1
- -- do linear transformation like cng*factor+offset
- -- (factor: delta(extremae): (max-min), offset: min)
- -- this maps 0...1 to min...max
- -- finally, multiply by sign again to get direction back
- local len= dst+cng
- -- print('Cng:'..crop_digits(cng,3)..' len:'..crop_digits(len,3))
- len= range_clamp(len,clu.band_sys_lim.min,clu.band_sys_lim.max)
- local band_count1= band.GetCount()
- -- check number of bands before applying another band
- band.AddBetweenSegments(seg_origin,seg_target)
- local band_count2= band.GetCount()
- -- check number of bands after applying another band
- if band_count1~=band_count2 then
- -- only if band has been created
- -- show its attributes
- print(
- 'B#'..i..
- ' Seg#'..seg_origin..
- ':'..seg_target..
- ' Len:'..crop_digits(len,3)..
- ' (Cng:'..crop_digits(cng,3)..')'..
- ' Str:'..crop_digits(str,3)
- )
- -- print('Distance:'..crop_digits(dst,3)..' Cng:'..crop_digits(cng,3))
- band.SetGoalLength(band_count2,len)
- -- change len
- band.SetStrength(band_count2,str)
- -- change str
- else
- print('B#'..i..' skipped')
- end -- if band_count
- else
- print('B#'..i..' skipped')
- end -- if (cng_flag and clu.band_skip_wrong)==false
- end -- function band.AddBetweenSegments2
- function seg_target_check_spat(seg_origin,seg_target)
- -- avoid seg_target beeing too close to seg_origin
- -- by measuring spatial dst
- local seg_target= seg_target
- local cng_flag= false
- while structure.GetDistance(seg_origin,seg_target)<clu.seg_min_dist do
- seg_target,cng_flag= seg_target_too_close_show(seg_origin,seg_target)
- end -- structure.GetDistance
- --[[
- if cng_flag then
- print('Value changed')
- end -- if cng_flag
- --]]
- return seg_target,cng_flag
- end -- seg_target_check_spat
- function seg_target_too_close_show(seg_origin,seg_target)
- -- print('seg_origin='..seg_origin..':'..'seg_target='..seg_target..' too close.')
- -- print('increasing seg_target idx.')
- local seg_target= range_wrap((seg_target+1),1,puzzle.seg_count,1)
- return seg_target,true
- end -- function seg_too_close_show
- function pull_do()
- if pull.act then
- print('Pulling...')
- CI_apply(pull.CI_default,'Default CI for pull:')
- -- if given, apply default CI
- local i
- for i=1,#pull do
- CI_method(pull[i])
- end -- for i
- end -- if pull.act
- end -- function pull_do
- function release_n_fuse()
- if release.act then
- print('Releasing...')
- CI_apply(release.CI_default,'Default CI for release: ')
- -- if given, apply default CI
- CI_method_batch(release)
- end -- if release.act
- if fuse.act then
- -- print('Fusing...')
- local i
- for i=1,#fuse do
- print('Fuse#'..i..'...')
- CI_apply(fuse.CI_default,'Default CI for fuse: ')
- -- if given, apply default CI
- CI_method_batch(fuse[i])
- end -- for i
- end -- if fuse.act
- end -- function release_n_fuse
- function CI_method_batch(CI_method_list)
- quicksave_do("load",3)
- local i
- for i=1,#CI_method_list do
- CI_method(CI_method_list[i])
- quicksave_do("save",4)
- if quicksave_score[4]>quicksave_score[5] then
- quicksave_do("save",5)
- end -- if quicksave_score
- end -- for i
- end -- function CI_method_batch
- function CI_method(prm)
- -- depending on passed table prm:
- -- 1. if given, set CI
- -- 2. for a given number of itrs &
- -- 3. use a foldit tool (backbone/sidechain move or mutate)
- -- i intentionally use only shake/wiggle all
- -- & didn't implement local wiggle,
- -- as it can make the puzzle too stiff (local maximum)
- --[[
- print('CI_method prms:')
- local k,v
- for k,v in pairs(prm) do
- print(k,v)
- end
- --]]
- CI_apply(prm.CI,'Current CI: ')
- -- if given, apply CI
- if type(prm.itr)=="number" then
- -- number of itrs given?
- if prm.itr>0 then
- -- depending on prm.cmd, do one of these tools:
- if prm.cmd=="m" then
- if puzzle.ismutable then
- if puzzle.mutate.act then
- -- print('Mutating for '..prm.itr..' iterations...')
- structure.MutateSidechainsAll(prm.itr)
- end -- if puzzle.mutate.act
- end -- if puzzle.ismutable
- elseif prm.cmd=="s" then
- -- print('Shaking for '..prm.itr..' iterations...')
- structure.ShakeSidechainsAll(prm.itr)
- elseif prm.cmd=="w" then
- -- print('wiggling for '..prm.itr..' iterations...')
- structure.WiggleAll(prm.itr,prm.backbone,prm.sidechains)
- end -- if prm.cmd
- end -- if prm.itr
- end -- if prm.itr
- end -- function CI_method
- function CI_apply(CI,text)
- if type(CI)=="number" then
- -- CI given?
- -- print(text..CI)
- behavior.SetClashImportance(CI)
- -- set it
- end -- if type(CI)
- end -- function CI_apply
- function quicksave_do(mode,slot)
- if mode=="save" then
- save.Quicksave(slot)
- quicksave_score[slot]=current.GetEnergyScore()
- -- print('Quicksaved to slot:'..slot..' - Score:'..crop_digits(quicksave_score[slot],3))
- elseif mode=="load" then
- save.Quickload(slot)
- -- print('Quickloaded from slot:'..slot..' - Score:'..crop_digits(quicksave_score[slot],3))
- end -- if mode
- end -- function quicksave_do
- function quicksave_do_batch(mode,first,last)
- local i
- for i=first,last do
- quicksave_do(mode,i)
- end -- for i
- end -- function quicksave_do
- function herd_fitnessandsort(clu)
- local clu= clu
- -- print("Getting herd's scoregain minimum...")
- clu.scoregain_min= clu[1].scoregain
- -- to have a minimum gain val (gain_min) to compare
- -- get first clu's scoregain val
- local i
- for i=2,#clu do
- -- cycle through all other scoregain vals
- if clu[i].scoregain<clu.scoregain_min then
- -- new gain_min found
- clu.scoregain_min= clu[i].scoregain
- -- set it as new gain_min (worst)
- end -- if clu[i].scoregain
- end -- for i
- -- print('Old minimum clu scoregain: '..clu.scoregain_min)
- if clu.scoregain_min>0 then
- -- gain_min >0?
- clu.scoregain_min= 1
- -- we don't need to push fitness vals
- -- so resulting fitness vals will be equal to scoregain vals
- end -- if clu.scoregain_min
- -- if gain_min were <=0, we would have to push fitness vals
- -- print('New minimum clu scoregain: '..clu.scoregain_min)
- -- print("Putting clu's fitness vals...")
- -- fitness= gain-gain_min+1
- -- smallest fitness val must be >0 (prevent fitnesses <=0)
- -- if all fitness vals were =0, roulette would run infinitely
- -- (plus, we even want to give worst clus a small chance)
- local i
- for i=1,#clu do
- clu[i].fitness= clu[i].scoregain-clu.scoregain_min+1
- --[[
- a gain_min of 1 doesn't do a change:
- fitness= gain-gain_min+1
- is fitness= gain-1 +1
- is fitness= gain-0
- -> so we've set a good gain_min (>0) to 1 before
- -- now subtract gain_min
- (can be negative, then it will be added to push value)
- -> from clu's scoregain
- -> giving fitness==0 for worst clu
- -- then add 1, as 0 isn't allowed, too
- -> giving fitness==1 for worst clu
- --]]
- end -- for i
- clu= herd_normalize(clu)
- -- sum of all fitness vals==1
- if (herd.fitness_e~=nil) and (herd.fitness_e~=1) then
- -- bending exponent given?
- -- print("Bending clu's fitnesses...")
- local i
- for i=1,#clu do
- clu[i].fitness= clu[i].fitness^(herd.fitness_e)
- -- bend fitness val -> 1 (if 0<exponent<1)
- end -- for i
- clu= herd_normalize(clu)
- -- sum of all fitness vals==1
- end -- if herd.fitness_e
- -- print("Sorting herd by clu's fitnesses...")
- local i
- for i=1,(#clu-1) do
- local j
- for j=(i+1),#clu do
- if clu[i].fitness<clu[j].fitness then
- clu[i],clu[j]=clu[j],clu[i]
- end -- if clu[i].fitness
- end -- for j
- end -- for i
- print('\nHerd after sorting is:')
- herd_show(clu)
- -- for debugging:
- -- list_show_deep(clu,"clu")
- print()
- return clu
- end -- function herd_fitnessandsort
- function herd_normalize(clu)
- local clu= clu
- clu.fitness_sum= clu_fitness_sum_get(clu)
- -- print("Normalizing clu's fitnesses...")
- local i
- for i=1,#clu do
- clu[i].fitness= clu[i].fitness/clu.fitness_sum
- end -- for i
- -- print('Herd with normalized fitness is:')
- -- herd_show(clu)
- return clu
- end -- function herd_normalize
- function clu_fitness_sum_get(clu)
- -- print("Getting herd's fitness sum...")
- local fitness_sum= 0
- local i
- for i=1,#clu do
- fitness_sum= fitness_sum+clu[i].fitness
- end -- for i
- -- print('Clus have fitness sum: '..fitness_sum)
- return fitness_sum
- end -- function
- function herd_show(clu)
- print('Gen#'..gen.cur..' had start score: '..quicksave_score[2])
- local i
- for i=1,#clu do
- print(
- 'Clu#'..i..
- ' Name:'..clu_name_get_string(clu[i].name,false)..
- ' Score:'..crop_digits(clu[i].score,3)..
- ' Gain:'..crop_digits(clu[i].scoregain,3)..
- ' Fitness:'..crop_digits(clu[i].fitness,6)
- )
- end -- for i
- clu.fitness_sum= clu_fitness_sum_get(clu)
- -- print('Fitness checksum: '..clu.fitness_sum)
- end -- function herd_show
- function breed_n_generate(clu)
- if herd.EO_mode.cur==2 then
- clu= herd_generate(
- clu,
- herd.breed.first,
- herd.size
- )
- elseif herd.EO_mode.cur==1 then
- clu= herd_generate(
- clu,
- (herd.breed.last+1),
- herd.size
- )
- else
- clu= herd_breed(
- clu,
- herd.breed.first,
- herd.breed.last
- )
- if herd.mutate.act then
- clu= herd_mutate(
- clu,
- herd.breed.first,
- herd.breed.last
- )
- end -- if herd.mutate.act then
- clu= herd_generate(
- clu,
- (herd.breed.last+1),
- herd.size
- )
- end -- if herd.EO_mode.cur
- return clu
- end -- function breed_n_generate
- function herd_breed(clu,first,last)
- local kid={}
- -- intialize kid clus breeding section
- if herd.breed.mode.val=="dual" then
- kid= herd_breed_dual(first,last)
- -- get kid by mom & dad breeding
- elseif herd.breed.mode.val=="poly" then
- kid= herd_breed_poly(first,last)
- -- get kid by orgy breeding
- else
- assert(false,'function herd_breed: herd.breed.mode.val is invalid: '..tostring(herd.breed.mode.val))
- end -- herd.breed.mode.val
- local i
- for i=first,last do
- -- move kids to herd
- -- overwrite old clus
- clu[i]= kid[i]
- clu[i].name= clu_name_get(i,"b")
- end -- for i
- return clu
- -- return new clu table
- end -- function herd_breed
- function herd_breed_dual(first,last)
- local kid={}
- -- intialize kid clus breeding section
- local i
- for i=first,last do
- -- fill breeding section
- local dad
- if herd.breed.roulette.dad then
- dad=roulette()
- else
- dad= range_wrap((i-first+1),1,herd.size,1)
- end -- if herd.breed.roulette.dad
- local mom
- if herd.breed.roulette.mom then
- mom= roulette()
- while mom==dad do
- mom=roulette()
- end -- while mom
- else
- mom= range_wrap((dad+1),1,herd.size,1)
- end -- if herd.breed.roulette.dad
- print('Breeding clu#'..i..'(kid) from: '..
- 'clu#'..dad..'(dad*'..crop_digits(herd.breed.dad_genes_prob,3)..')'..
- ' + '..
- 'clu#'..mom..'(mom*'..crop_digits((1-herd.breed.dad_genes_prob),3)..')')
- kid[i]={}
- for j=1,#clu[i] do
- if random_flag1(herd.breed.dad_genes_prob) then
- print_gene(j,dad,"dad")
- kid[i][j]=clu[dad][j]
- else
- print_gene(j,mom,"mom")
- kid[i][j]=clu[mom][j]
- end -- if random_flag1
- end -- for j
- end -- for i
- return kid
- end -- function function herd_breed_dual
- function herd_breed_poly(first,last)
- local kid={}
- -- intialize kid clus breeding section
- local i
- for i=first,last do
- -- fill breeding section
- print('Breeding clu#'..i..'(kid) from: whole herd')
- kid[i]={}
- for j=1,#clu[i] do
- local parent= roulette()
- print_gene(j,parent,"roulette")
- kid[i][j]=clu[parent][j]
- end -- for j
- end -- for i
- return kid
- end -- function herd_breed_poly
- function print_gene(j,parent_val,parent_text)
- if herd.breed.genes_show.act then
- -- detailed gene view activated?
- print('Gene #'..j..': clu#'..tostring(parent_val)..'('..tostring(parent_text)..')')
- end -- if herd.breed.genes_show act
- end -- function print_gene
- function roulette()
- local fitness_target= math.random()
- -- set random fitness sum goal
- -- print('Fitness target:'..crop_digits(fitness_target,6))
- local wheel= math.random(1,herd.size)
- -- initialize random roulette wheel position
- local fitness_sum= clu[wheel].fitness
- -- get fitness val at wheel position
- -- print('Wheel current:'..wheel..' Fitness sum:'..crop_digits(fitness_sum,6))
- while fitness_sum<=fitness_target do
- -- as long as fitness sum hasn't reached fitness sum goal
- if herd.breed.roulette.israndom then
- -- if roulette is random (not default)
- -- set another random roulette wheel position
- wheel= math.random(1,herd.size)
- else
- -- if roulette is not random (default)
- wheel= range_wrap((wheel+1),1,herd.size,1)
- -- spin wheel
- end -- if herd.breed.roulette.israndom
- fitness_sum= fitness_sum+clu[wheel].fitness
- -- print('Wheel current:'..wheel..' Fitness sum:'..crop_digits(fitness_sum,6))
- end -- while fitness_sum
- -- print('Wheel end:'..wheel..' Fitness sum:'..crop_digits(fitness_sum,6))
- return wheel
- end -- function roulette
- function main()
- print('\nMain Programm start.')
- puzzle.random_seed= random_seed_set_val(puzzle.random_seed)
- print('Puzzle segs mutability: '..tostring(puzzle.ismutable))
- if puzzle.ismutable==false then
- puzzle.mutate.act= false
- end -- if puzzle.ismutable
- print('Puzzle segs mutation: '..tostring(puzzle.mutate.act))
- print('Herd genes off prob: '..herd.mutate.prob.off)
- print('Herd mutability prob: '..herd.mutate.prob.vals)
- if herd.mutate.prob.vals<=0 then
- -- herd mutate probability is not given
- herd.mutate.act= false
- -- deactivate hed genes mutating
- -- (not needed, but prevents calling function)
- end -- if herd.mutate.prob.vals
- print('Herd mutation: '..tostring(herd.mutate.act))
- if herd.breed.first>herd.breed.last then
- herd.breed.first,herd.breed.last= herd.breed.last,herd.breed.first
- end -- if herd.breed.first
- print('EO mode: '..herd.EO_mode.cur)
- print('Breed mode: '..herd.breed.mode.val)
- print('Clu band mode old: '..clu.band_to.val)
- if type(puzzle.seg_center.val)=="number" then
- -- "center" seg already given by user?
- clu.band_to.val= "user"
- end -- if type(puzzle.seg_center.val)
- if clu.band_to.val=="center" then
- -- banding to center
- if puzzle.seg_center.get_mode=="start" then
- -- get center seg once?
- puzzle.seg_center.val= seg_center_get()
- end -- if puzzle.seg_center.get_mode
- elseif clu.band_to.val=="user" then
- -- banding to user-defined seg idx
- assert((puzzle.seg_center.val>0) and (puzzle.seg_center.val<(puzzle.seg_count+1)),'function main: puzzle.seg_center.val is invalid: '..tostring(puzzle.seg_center.val))
- puzzle.seg_center.get_mode="start"
- -- get center seg once!
- clu.band_to.val= "center"
- -- "user" -> "center"
- elseif string.sub(clu.band_to.val, 1, 6)=="random" then
- -- using any random bands?
- if clu.band_to.val=="random1" then
- puzzle.seg_random.get_mode= "list"
- else -- if clu.band_to.val=="random2"
- puzzle.seg_random.get_mode= "all"
- end -- if clu.band_to.val
- clu.band_to.val= "random"
- -- elseif (clu.band_to.val=="space") or (clu.band_to.val=="furthest")
- end -- if clu.band_to.val
- print('Clu band mode new: '..clu.band_to.val)
- print('Seg center get_mode: '..puzzle.seg_center.get_mode)
- print('Seg random get_mode: '..puzzle.seg_random.get_mode)
- if (clu.band_to.val=="center") and (puzzle.seg_center.get_mode== "start") then
- -- always the same "center" seg used?
- table.insert(seg_use.exclude.idx,puzzle.seg_center.val)
- -- add it's idx to exclude candidates
- end -- if clu.band_to.val,puzzle.seg_center.get_mode
- seg_use= seg_use_list_create(seg_use)
- -- create seg list based on informations given at declaration
- -- for debugging before generation testing, uncomment this:
- -- prms_show()
- gen.cur= 1
- -- initialize gen counter
- quicksave_score={}
- --[[
- saveslots:
- 1: script start
- 2: gen/clu start (before applying bands/pull)
- 3: after pull (before release/fuse start)
- 4: after each release /fuse step
- 5: after all releases/fuses per clu (best result for current clu)
- 6: best result for current gen
- 7: best result so far
- --]]
- -- save to all slots to initialize states & scores:
- quicksave_do_batch("save",1,7)
- recentbest.Save()
- -- print('Set Recent Best')
- clu=herd_generate(clu,1,herd.size)
- -- list_show_deep(clu,"clu") --show all clu informations
- herd.test={first=1,last=herd.size}
- -- normally, test all generated clus
- while gen.cur<=gen.max do
- print('\n\nGen: '..gen.cur)
- if herd.use.hybrid.state~=nil then
- -- hybrid loading is used, change loading state
- if gen.cur%herd.use.hybrid.gens==1 then
- -- number of gens to trigger reloading start state is reached
- herd.use.state.val= "start"
- -- load start state
- else
- -- number of gens to trigger reloading start state is not reached
- herd.use.state.val= herd.use.hybrid.state
- -- load specified state
- end -- if gen.cur
- end -- if herd.use.hybrid.state
- local loaded_text
- -- load puzzle state before pulling:
- if herd.use.state.val=="start" then
- quicksave_do("load",1)
- loaded_text= "Script Start State"
- elseif herd.use.state.val=="gen" then
- quicksave_do("load",6)
- loaded_text= "Gen's Best State"
- elseif herd.use.state.val=="script" then
- quicksave_do("load",7)
- loaded_text= "Script's Best State"
- else
- recentbest.Restore()
- loaded_text= "Recent Best State"
- end -- if herd.use.state.val
- print('Loaded: '..loaded_text..' - Score: '..crop_digits(current.GetEnergyScore(),3))
- -- save to these slots to initialize states & scores:
- quicksave_do_batch("save",2,6)
- if (herd.use.state.val=="start") and (herd.use.hybrid.state==nil) then
- -- if script start state is always loaded
- herd.test.first= 1
- -- reset test start clu (first clu of gen to test)
- while clu[herd.test.first].name.gen~=gen.cur do
- -- test start clu was not generated in this gen (it is an old one)
- herd.test.first= herd.test.first+1
- -- use next clu
- if herd.test.first>herd.size then
- -- if next clu is too high (higher than herd size)
- herd.test.first=1
- -- set it to 1 again
- break
- -- exit start clu checking
- end -- if
- end -- while clu
- end -- if if herd.use.state.val
- local clu_cur
- for clu_cur=herd.test.first,herd.test.last do
- -- print('clu: '..clu_cur)
- print('\nTesting: G'..gen.cur..
- 'C'..clu_cur..
- '/'..herd.size..
- ' Name: '..clu_name_get_string(clu[clu_cur].name,true))
- quicksave_do("load",2)
- band.DeleteAll()
- clu_apply_bands(clu[clu_cur])
- pull_do()
- band.DeleteAll()
- -- save to these slots to initialize states & scores:
- quicksave_do_batch("save",3,5)
- print('Score after pulling: '..crop_digits(quicksave_score[3],3))
- release_n_fuse()
- clu[clu_cur].score=quicksave_score[5]
- clu[clu_cur].scoregain=clu[clu_cur].score-quicksave_score[2]
- print("This clu's best Score: "..crop_digits(quicksave_score[5],3).." - Gain: "..crop_digits(clu[clu_cur].scoregain,3))
- if (clu_cur==herd.test.first) or (quicksave_score[5]>quicksave_score[6]) then
- quicksave_do("load",5)
- quicksave_do("save",6)
- print('New best result for this gen: '..crop_digits(quicksave_score[6],3))
- end -- if clu_cur
- if quicksave_score[6]>quicksave_score[7] then
- quicksave_do("load",6)
- quicksave_do("save",7)
- print('New best result so far! '..crop_digits(quicksave_score[7],3))
- end -- if quicksave_score
- end -- for clu_cur
- clu=herd_fitnessandsort(clu)
- -- for each clu calculate fitness given by it's score gain
- -- sort clus by fitness, best gain on top
- gen.cur=gen.cur+1
- -- increase generation counter now,
- -- so newly generated/breeded clus will
- -- get an actual "birth date" = next gen
- if (herd.flush_gain_thr.act==false) or (clu[1].scoregain>=herd.flush_gain_thr.thr) then
- -- best gain checking is off
- -- or gain is good enough
- clu=breed_n_generate(clu)
- -- keep good
- -- breed good over mediocre
- -- replace bad by new ones
- herd.flush_gain_reset.cur= 0
- -- reset flush counter
- else
- -- best gain checking is on
- -- and gain is bad enough
- print('\nTarget result for this gen: '..crop_digits(herd.flush_gain_thr.thr,3))
- print('Best result for this gen only: '..crop_digits(clu[1].scoregain,3))
- herd.flush_gain_reset.cur= herd.flush_gain_reset.cur+1
- -- increase flush counter
- print('Herd flush #'..herd.flush_gain_reset.cur)
- clu=herd_generate(clu,1,herd.size)
- -- flush entire herd
- -- replace all clus by new ones
- if herd.flush_gain_reset.act then
- -- reset after flush activated?
- if herd.flush_gain_reset.cur>herd.flush_gain_reset.thr then
- print('Number of flushs exceeded.')
- print('Restarting from script start state.')
- quicksave_do("load",1)
- -- get script start state again
- -- save to (almost) all slots to flush states & scores:
- quicksave_do_batch("save",2,7)
- recentbest.Save()
- -- print('Set Recent Best')
- herd.flush_gain_reset.cur= 0
- -- reset flush counter
- end -- if herd.flush_gain_reset.cur
- end -- if herd.flush_gain_reset.act
- end -- if herd.flush_gain_thr.act,clu[1].scoregain
- end -- while gen.cur~=gen.max
- end -- function main
- function prms_cng()
- --[[
- input index numbering:
- numerical: information, label (each section is 10*x)
- a: activity, checkbox
- t: value, textbox
- x: value, slider
- m: minimum, slider
- n: maximum, slider
- --]]
- local dialog_act={}
- -- initialize table for dialog activity flags
- if true then -- dialog 0.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 0/7')
- ask.Label00= dialog.AddLabel("Change default settings here? There are many!")
- ask.Label01= dialog.AddLabel("You can activate these dialogs:")
- ask.Input1a= dialog.AddCheckbox("#1: Random seed & Herd size",false)
- ask.Input2a= dialog.AddCheckbox("#2: EO mode & Load state",false)
- ask.Input3a= dialog.AddCheckbox("#3: Band mode",false)
- ask.Input4a= dialog.AddCheckbox("#4: Release & Fuse",false)
- ask.Input5a= dialog.AddCheckbox("#5: Band length & strength",false)
- ask.Input6a= dialog.AddCheckbox("#6: Minimum distance for banding",false)
- ask.Input7a= dialog.AddCheckbox("#7: Gene probalilities",false)
- ask.Input8a= dialog.AddCheckbox("#8: Gene breeding & mutating",false)
- ask.Input9a= dialog.AddCheckbox("#9: Flush & Reset",false)
- ask.LabelA0= dialog.AddLabel("some checked: OK to change values, then launch")
- ask.LabelA1= dialog.AddLabel("none checked: OK to launch script")
- ask= ask_window(ask)
- for i=1,9 do
- -- get all checkbox selections
- dialog_act[i]= ask["Input"..i.."a"].value
- -- print('#i: '..tostring(dialog_act[i]))
- end -- for i
- end -- if dialog 0.0
- if dialog_act[1] then -- dialog 1.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 1/9')
- if puzzle.random_seed==nil then
- puzzle.random_seed= ""
- end -- if puzzle.random_seed
- ask.Input1t= dialog.AddTextbox("Random seed ",tostring(puzzle.random_seed))
- ask.Label11= dialog.AddLabel("Blank : use new seed")
- ask.Label12= dialog.AddLabel("Number: use this seed")
- ask.Label13= dialog.AddLabel(" ")
- ask.Input2x= dialog.AddSlider("Herd size",herd.size,4,16,0)
- ask.Label21= dialog.AddLabel("Number of clu(ster)s for one gen(eration)")
- ask= ask_window(ask)
- puzzle.random_seed= ask.Input1t.value
- herd.size= ask.Input2x.value
- end -- if dialog 1.0
- if dialog_act[1] then -- dialog 1.1
- -- user has set herd size
- -- now set breed:
- -- first &
- -- last
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 1.1/9')
- local keep=0
- if (herd.size%2)==0 then
- -- if number of clus is even
- keep=2
- -- keep 2 clus
- else
- -- ff number of clu is not even
- keep=3
- -- Keep 3 clus
- end -- if (herd.size%2)
- local breed=(herd.size-keep)/2
- -- after subtracting kept clus,
- -- divide the rest by 2
- -- first half for breeding:
- herd.breed.first=keep+1
- herd.breed.last=keep+breed
- -- other half for creating new
- -- herd.breed.last+1...herd.size will be random
- ask.Label30= dialog.AddLabel("Breed settings:")
- ask.Label31= dialog.AddLabel("After one gen,")
- ask.Label32= dialog.AddLabel("replace mediocre clu# by new breeded ones")
- ask.Label33= dialog.AddLabel(" ")
- ask.Input4x= dialog.AddSlider("First",herd.breed.first,1,herd.size,0)
- ask.Label41= dialog.AddLabel("clu# to be replaced")
- ask.Label42= dialog.AddLabel("All < are kept as parents")
- ask.Label43= dialog.AddLabel(" ")
- ask.Input5x= dialog.AddSlider("Last",herd.breed.last,1,herd.size,0)
- ask.Label51= dialog.AddLabel("clu# to be replaced")
- ask.Label52= dialog.AddLabel("All > are created new")
- ask.Label53= dialog.AddLabel(" ")
- ask.Label60= dialog.AddLabel("Breed settings are also used by EO as orientation")
- ask= ask_window(ask)
- herd.breed.first= ask.Input4x.value
- herd.breed.last= ask.Input5x.value
- end -- if dialog 1.1
- if dialog_act[2] then -- dialog 2.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 2/9')
- ask.Label10= dialog.AddLabel("Extremal Optimization (discard mediocre clus)")
- ask.Input1x= dialog.AddSlider("EO mode",herd.EO_mode.cur,herd.EO_mode.min,herd.EO_mode.max,0)
- ask.Label12= dialog.AddLabel("0: no EO (GA!), replace m.clus by breeded ones")
- ask.Label13= dialog.AddLabel("1: use EO, don't just leave m.clus as they are")
- ask.Label14= dialog.AddLabel("2: use EO, don't replace m.clus by random ones")
- ask.Label15= dialog.AddLabel(" ")
- local state={list=herd.use.state.list}
- ask.Label20= dialog.AddLabel("Puzzle state for each gen")
- ask.Input2x= dialog.AddSlider("Load state",key_getbyval(state.list,herd.use.state.val),1,#state.list,0)
- ask.Label22= dialog.AddLabel(" ")
- ask.Label23= dialog.AddLabel(list_text(state.list))
- ask.Label24= dialog.AddLabel(" ")
- ask.Label25= dialog.AddLabel("start: as now")
- ask.Label26= dialog.AddLabel(" (never reach local max)")
- ask.Label27= dialog.AddLabel("gen: best result of last gen")
- ask.Label28= dialog.AddLabel(" (avoid local max)")
- ask.Label29= dialog.AddLabel("script: script's best")
- ask.Label2A= dialog.AddLabel(" (similar to recent)")
- ask.Label2B= dialog.AddLabel("recent: recent best state")
- ask.Label2C= dialog.AddLabel(" (can produce local max)")
- ask= ask_window(ask)
- herd.EO_mode.cur= ask.Input1x.value
- herd.use.state.val= state.list[ask.Input2x.value]
- end -- if dialog 2.0
- if dialog_act[3] then -- dialog 3.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 3/9')
- local band_to={list=clu.band_to.list}
- ask.Label30= dialog.AddLabel("Band these segs to target seg:")
- ask.Label31= dialog.AddLabel("+ in list (detected by script)")
- ask.Label32= dialog.AddLabel("+ game interface selection (blue)")
- ask.Label33= dialog.AddLabel(" ")
- ask.Input3x= dialog.AddSlider("Band mode",key_getbyval(band_to.list,clu.band_to.val),1,#band_to.list,0)
- ask.Label35= dialog.AddLabel(" ")
- ask.Label36= dialog.AddLabel(" ")
- ask.Label37= dialog.AddLabel(list_text(band_to.list))
- ask.Label38= dialog.AddLabel(" ")
- ask.Label39= dialog.AddLabel(" ")
- ask.Label3A= dialog.AddLabel("center: 'center' seg is auto-detected")
- ask.Label3B= dialog.AddLabel("user: 'center' seg is set manually")
- ask.Label3C= dialog.AddLabel("random1: uselist (detected & selection) to uselist")
- ask.Label3D= dialog.AddLabel("random2: uselist to all of puzzle (classic)")
- ask= ask_window(ask)
- clu.band_to.val= band_to.list[ask.Input3x.value]
- end -- if dialog 3.0
- if dialog_act[3] and (clu.band_to.val=="user") then -- dialog 3.1
- -- user wants to set own "center" seg
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 3.1/9')
- ask.Label40= dialog.AddLabel("Set your own 'center' seg")
- ask.Input4x= dialog.AddSlider("Center seg",seg_center_get2(),1,puzzle.seg_count,0)
- ask= ask_window(ask)
- puzzle.seg_center.val= ask.Input4x.value
- end -- if dialog 3.1
- if dialog_act[4] then -- dialog 4.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 4/9')
- ask.Input1a= dialog.AddCheckbox("Mutate sidechains",puzzle.mutate.act)
- ask.Label11= dialog.AddLabel("Works only if puzzle is mutable")
- ask.Label12= dialog.AddLabel(" ")
- ask.Input2a= dialog.AddCheckbox("Pull",pull.act)
- ask.Input2x= dialog.AddSlider("CI with bands",pull.CI_default,0,1,2)
- ask.Label22= dialog.AddLabel(" ")
- ask.Input3a= dialog.AddCheckbox("Release (1-pass)",release.act)
- ask.Input3x= dialog.AddSlider("CI without bands",release.CI_default,0,1,2)
- ask.Label32= dialog.AddLabel(" ")
- ask.Input4a= dialog.AddCheckbox("Fuse(s) (multiple-pass)",fuse.act)
- ask.Label41= dialog.AddLabel("CI is varied")
- ask= ask_window(ask)
- puzzle.mutate.act= ask.Input1a.value
- pull.act= ask.Input2a.value
- pull.CI_default= ask.Input2x.value
- release.act= ask.Input3a.value
- release.CI_default= ask.Input3x.value
- fuse.act= ask.Input4a.value
- end -- if dialog 4.0
- if dialog_act[5] then -- dialog 5.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 5/9')
- local prim_min,prim_max
- if clu.band_to.val=="space" then
- -- use rho vals for sliders:
- prim_min= clu.rho.min
- prim_max= clu.rho.max
- else -- clu.band_to.val~="space"
- -- use d_cng vals for sliders:
- prim_min= clu.d_cng1.min
- prim_max= clu.d_cng1.max
- end -- if clu.band_to.val
- if string.sub(clu.band_to.val, 1, 6)=="random" then
- -- using any random bands?
- clu.d_cng2.act= false
- -- secondary bands off by default
- end -- if "random"
- ask.Label10= dialog.AddLabel("Primary bands push distance by +/-")
- ask.Input1m= dialog.AddSlider("min",prim_min,0,3.8*5,2)
- ask.Input1n= dialog.AddSlider("max",prim_max,0,3.8*5,2)
- ask.Input1s= dialog.AddSlider("strength",clu.pull.str1,0,10,2)
- ask.Label14= dialog.AddLabel(" ")
- ask.Label20= dialog.AddLabel("Secondary bands push distance by +/-")
- ask.Input2a= dialog.AddCheckbox("on",clu.d_cng2.act)
- ask.Input2m= dialog.AddSlider("min",clu.d_cng2.min,0,3.8*5,2)
- ask.Input2n= dialog.AddSlider("max",clu.d_cng2.max,0,3.8*5,2)
- ask.Input2s= dialog.AddSlider("strength",clu.pull.str2,0,10,2)
- ask.Label25= dialog.AddLabel(" ")
- ask= ask_window(ask)
- if ask.Input1m.value>ask.Input1n.value then
- ask.Input1m.value,ask.Input1n.value= ask.Input1n.value,ask.Input1m.value
- end -- if ask.Input11,ask.Input12
- if clu.band_to.val=="space" then
- clu.rho.min= ask.Input1m.value
- clu.rho.max= ask.Input1n.value
- else
- clu.d_cng1.min= ask.Input1m.value
- clu.d_cng1.max= ask.Input1n.value
- end -- if clu.band_to.val
- clu.pull.str1= ask.Input1s.value
- clu.d_cng2.act= ask.Input2a.value
- if ask.Input2m.value>ask.Input2n.value then
- ask.Input2m.value,ask.Input2n.value= ask.Input2n.value,ask.Input2m.value
- end -- if ask.Input22,ask.Input23
- clu.d_cng2.min= ask.Input2m.value
- clu.d_cng2.max= ask.Input2n.value
- clu.pull.str2= ask.Input2s.value
- end -- if dialog 5.0
- if dialog_act[6] then -- dialog 6.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 6/9')
- ask.Label30= dialog.AddLabel("Segs with this distance are 'too close'")
- ask.Input3m= dialog.AddSlider("min",clu.seg_min_dist,0,3.8*5,2)
- ask.Label32= dialog.AddLabel(" ")
- ask.Label33= dialog.AddLabel("if 'too close:")
- ask.Input3a= dialog.AddCheckbox("skip band / don't change t.seg",clu.band_skip_wrong)
- ask.Label35= dialog.AddLabel("= neither apply band")
- ask.Label36= dialog.AddLabel(" nor change (correct) target seg idx")
- ask.Label37= dialog.AddLabel(" ")
- ask.Label38= dialog.AddLabel("if banding to many segs, possibly:")
- ask.Label39= dialog.AddLabel("- activate this or")
- ask.Label3A= dialog.AddLabel("- deactivate secondary bands")
- ask= ask_window(ask)
- clu.seg_min_dist= ask.Input3m.value
- clu.band_skip_wrong= ask.Input3a.value
- end -- if dialog 6.0
- if dialog_act[7] then -- dialog 7.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 7/9')
- ask.Label10= dialog.AddLabel("Band gene probalilities:")
- ask.Label11= dialog.AddLabel("0.00= 0% (none)")
- ask.Label12= dialog.AddLabel("0.50= 50% (half)")
- ask.Label13= dialog.AddLabel("1.00= 100% (all)")
- ask.Label14= dialog.AddLabel(" ")
- ask.Label20= dialog.AddLabel("Turn this many")
- ask.Input2x= dialog.AddSlider("genes off",herd.mutate.prob.off,0,1,2)
- ask.Label22= dialog.AddLabel("(EO+GA)")
- ask.Label23= dialog.AddLabel(" ")
- ask.Label30= dialog.AddLabel("Probability of")
- ask.Input3x= dialog.AddSlider("gene mutating",herd.mutate.prob.vals,0,1,2)
- ask.Label31= dialog.AddLabel("after breeding (GA)")
- ask.Label32= dialog.AddLabel(" ")
- ask.Label40= dialog.AddLabel("Probability of")
- ask.Input4x= dialog.AddSlider("dad genes",herd.breed.dad_genes_prob,0,1,2)
- ask.Label42= dialog.AddLabel("(first breeding (GA) partner)")
- ask.Label44= dialog.AddLabel("Without mutating:")
- ask.Label45= dialog.AddLabel("1.00: kid is like dad")
- ask.Label46= dialog.AddLabel("0.00: kid is like mom")
- ask= ask_window(ask)
- herd.mutate.prob.off= ask.Input2x.value
- herd.mutate.prob.vals= ask.Input3x.value
- herd.breed.dad_genes_prob= ask.Input4x.value
- end -- if dialog 7.0
- if dialog_act[8] then -- dialog 8.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 8/9')
- local breed={mode={list=herd.breed.mode.list}}
- ask.Label50= dialog.AddLabel("Breeding behaviour (genetic roulette)")
- ask.Input5x= dialog.AddSlider("Breed mode",key_getbyval(breed.mode.list,herd.breed.mode.val),1,#breed.mode.list,0)
- ask.Label52= dialog.AddLabel(" ")
- ask.Label53= dialog.AddLabel(list_text(breed.mode.list))
- ask.Label54= dialog.AddLabel(" ")
- ask.Label55= dialog.AddLabel("Each kid from:")
- ask.Label56= dialog.AddLabel("dual: 2 clus (mom & dad) (classic)")
- ask.Label57= dialog.AddLabel("poly: any clus (whole herd)")
- ask.Label58= dialog.AddLabel(" ")
- ask.Label60= dialog.AddLabel("Roulette is")
- ask.Input6a= dialog.AddCheckbox("random",herd.breed.roulette.israndom)
- ask.Label62= dialog.AddLabel("true: spreaded")
- ask.Label63= dialog.AddLabel("false: inertial (classic)")
- ask.Label64= dialog.AddLabel(" ")
- ask.Label70= dialog.AddLabel("Show breeding details")
- ask.Input7a= dialog.AddCheckbox("gene origin clu#(parent)",herd.breed.genes_show.act)
- ask.Label80= dialog.AddLabel("Show mutating details")
- ask.Input8a= dialog.AddCheckbox("gene value (old & new)",herd.mutate.genes_show.act)
- ask= ask_window(ask)
- herd.breed.mode.val= breed.mode.list[ask.Input5x.value]
- herd.breed.roulette.israndom= ask.Input6a.value
- herd.breed.genes_show.act= ask.Input7a.value
- herd.mutate.genes_show.act= ask.Input8a.value
- end -- if dialog 8.0
- if dialog_act[9] then -- dialog 9.0
- local ask= dialog.CreateDialog('CG303 GAB+EO Remix - Parameters 9/9')
- ask.Label10= dialog.AddLabel("If best clu gain is less than")
- ask.Input1m= dialog.AddSlider("min",
- herd.flush_gain_thr.thr,
- herd.flush_gain_thr.min,
- herd.flush_gain_thr.max,
- 1)
- ask.Input1a= dialog.AddCheckbox("flush herd completely",herd.flush_gain_thr.act)
- ask.Label13= dialog.AddLabel(" ")
- ask.Label20= dialog.AddLabel("When flushed more than this time")
- ask.Input2n= dialog.AddSlider("max",
- herd.flush_gain_reset.thr,
- herd.flush_gain_reset.min,
- herd.flush_gain_reset.max,
- 0)
- ask.Input2a= dialog.AddCheckbox("reset puzzle to script start state",herd.flush_gain_reset.act)
- ask= ask_window(ask)
- herd.flush_gain_thr.thr= ask.Input1m.value
- herd.flush_gain_thr.act= ask.Input1a.value
- herd.flush_gain_reset.thr= ask.Input2n.value
- herd.flush_gain_reset.act= ask.Input2a.value
- end -- if dialog 9.0
- end -- function prms_cng
- function ask_window(ask)
- ask.LabelX1= dialog.AddLabel(" ")
- ask.LabelX2= dialog.AddLabel(" ")
- ask.OK= dialog.AddButton("OK", 1)
- ask.Cancel= dialog.AddButton("Cancel", 0)
- local button_val= dialog.Show(ask)
- assert((button_val==1),'Script canceled!')
- return ask
- end -- function ask_window
- function list_text(list)
- -- create output text with multiple lines from list
- local text= ""
- local i
- for i=1,#list do
- if text~="" then
- text= text.."\n"
- end -- if text
- text= text..tostring(i)..": "..list[i]
- end -- for i
- return text
- end -- function list_text
- -- declaration section:
- -- all global variables (mostly organized as table) can be set here.
- -- some of them here are used as default vals only
- -- & can be altered by gui in change section
- puzzle={seg_count= structure.GetCount();
- random_seed=nil
- -- set random seed to this val
- -- if there is none,
- -- os.time()+recipe.GetrandomSeed() will be used
- }
- print('Puzzle has '..puzzle.seg_count..' segments.')
- puzzle.ismutable=puzzle_ismutable()
- -- check if there are mutable segments
- puzzle.mutate={act=(puzzle.ismutable or false)}
- -- set mutating puzzle activity to the same val
- -- (foldit-mutation, not equal to: mutate herd-cluster-bands)
- puzzle.isligand=puzzle_isligand()
- -- check if there is a ligand
- puzzle.seg_center={
- val=nil;
- --[[
- set which seg is considered as seg_center
- integer number between first...last segment: use this segment index as center segment
- puzzle.seg_count (same as last segment): use last segment index as center segment
- -- nil: get "start" or "current" center segment
- --]]
- get_mode="current"
- --[[
- set when seg_center is to be fetched
- "start": only at script start
- use this when setting val to a constant number or banding to ligand
- "current" (or any other): each time before applying bands
- --]]
- }
- puzzle.seg_random={
- -- get random seg from
- get_mode="all"
- -- "list": uselist segs
- -- "all": puzzle segs
- }
- -- create list containing following segs:
- seg_use={
- include={
- idx={1;puzzle.seg_count};
- -- with idx number: first & last
- --[[
- you can also set:
- -- ranges instead of single indices:
- -- idx={seg_blocks({{1;5}})};
- includes segs 1-5
- -- idx={seg_blocks({{1;5};{10;20}})};
- includes segs 1-5 & 10-20
- -- idx={seg_blocks({{1;puzzle.seg_count}})};
- includes all segs
- -- mix single segs & ranges:
- -- idx=seg_use_list_append_all({1;puzzle.seg_count},seg_blocks({{10;20}});
- includes first seg, last seg & 10-20
- --]]
- selected={act=true;val=true};
- -- if act==true, include:
- -- val:
- -- true: selected segs
- -- false: unselected segs
- frozen={act=false;backbone=true;sidechain=false};
- -- if act==true:
- -- add frozen segs
- -- given in backbone & sidechain val
- ss={};
- -- with secondary structures
- -- "L"=loop
- -- "H"=helix
- -- "E"=sheet
- ss_cngs=true;
- -- where secondary structure changes occur: yes
- aa={"g"}
- -- with amino acids
- -- here:
- -- include glycine
- -- example:
- -- aa={"f";"g"}
- -- include phenylalanine; glycine
- };
- exclude={
- idx={};
- -- without idx number: none
- selected={act=false;val=false};
- -- if act==true, exclude:
- -- val:
- -- true: selected segs
- -- false: unselected segs
- frozen={act=false;backbone=true;sidechain=false};
- -- if act==true:
- -- remove frozen segs
- -- given in backbone & sidechain val
- -- note:
- -- if you turn this on (act==true)
- -- & set backbone to false & sidechain to false,
- -- all unfrozen segs will be removed!
- ss={};
- -- without secondary structures
- -- "L"=loop
- -- "H"=helix
- -- "E"=sheet
- aa={}
- -- without amino acids
- -- example:
- -- aa={"a";"v";"p";"w"}
- -- exclude alanine; valine; proline; tryptophan
- };
- append_all=false;
- -- append all segs to uselist
- -- false: append only segs which are not already in list
- -- (more to check when adding)
- -- true: append all segs (double segs will be removed later when sorting)
- -- (more to check when removing)
- remove_double=true;
- -- remove double segs from uselist after adding
- -- true: remove
- -- false: don't remove (may not work, depending on how bands are applied)
- sort_ascending=true;
- -- sort segs in uselist by idx
- -- true: lowest idx first
- -- false: highest idx first
- -- nil (or any other): don't sort
- }
- gen={max=math.huge}
- -- set number of maximum gens to test
- herd={
- size=8;
- -- number of individuums
- -- won't grow anymore in this script version
- breed={first=3;
- -- first mediocre clu to be replaced by breeded one (GA)
- -- clus with lower idx will be kept as good ones
- last=5;
- -- last mediocre clu to be replaced by breeded one (GA)
- -- clus with higher idx will be replaced by new random ones (flushed)
- mode={
- -- breed mode (if EO_mode==0)
- -- general breeding behaviour
- val="dual";
- -- set breed mode
- list={
- "dual"; -- breed kid from 2 partners only (regular)
- -- before breeding, select mom (& dad) once via roulette
- -- while breeding, select gene from mom or dad
- "poly" -- breed kid from whole herd (each gene can be from any clu)
- -- while breeding, select gene-donor for each gene via roulette
- -- ignore mom & dad options
- }
- };
- genes_show={
- -- show detailed gene information whenn breeding
- act=false
- -- show which gene is from which clu
- -- true: show clu#(parent)
- -- false: show possible parents only
- };
- roulette={
- -- roulette wheel selection
- dad=false;
- -- use for dad (first breeding partner)
- -- true: use
- -- false: don't use (1st dad is clu#1, 2nd dad is clu#2 ...)
- mom=true;
- -- use for mom (2nd breeding partner)
- -- true: use
- -- false: don't use (mom: next clu# after dad)
- israndom=false
- -- 'wheel' is complete random
- -- true: yes, don't spin wheel - let it jump & ignore clu order
- -- special, makes breeding partner selection behave different.
- -- -> useful for "poly" breed mode, as genes will be more scattered.
- -- fitness is considered, nevertheless
- -- false: no, spin wheel - default, as it is usually done in GA.
- -- fitness is considered, but more inertially
- };
- dad_genes_prob=0.55
- -- set the (probability) ratio of dad genes (first breeding partner):
- -- float val between 0...1
- -- <=0 : mom genes only
- -- 0.25 : 1/4 dad
- -- .5 : 1/2 dad & mom
- -- 0.75 : 3/4 dad
- -- >=1 : dad genes only
- };
- mutate={
- -- mutate herd cluster bands after breeding
- -- (GA-mutation, not equal to: mutate puzzle-segs)
- act=true;
- -- boolean val
- -- true: mutate vals depending on prob.vals
- -- false: mutate off (don't mutate breeded bands)
- genes_show={
- -- show detailed gene information whenn mutating
- act=false
- -- show which gene is from which clu
- -- true: show clu#(parent)
- -- false: show possible parents only
- };
- prob={off=0.25;vals=0.1};
- -- mutate probability ratios
- -- each: float val between 0...1
- -- <=0 : never
- -- 0.5 : 1/2 of cases
- -- >=1 : always
- -- off ratio: turn bands off when generated
- -- this prevents too many act bands for 1 clu
- -- (as a clu loads the complete uselist)
- -- example:
- -- if you have 10 segments in uselist,
- -- & off==0.25,
- -- 1/4 of clu band genes (about 2...3 will be off)
- -- vals ratio: mutate band vals when breeded
- -- toggles (switches) band activity (activated)
- -- (off bands -> on & vice versa)
- -- changes band vand vals (len, rho, theta, phi)
- -- examples for vals:
- -- <=0.0 : all band genes will be changed (then you can set herd.mutate.act= false)
- -- ==0.1 : 1/10 of band genes
- -- ==0.5 : 1/2 of band genes
- -- >=1.0 : all band genes will be changed
- rng10e={min=-3;max=-1}
- -- mutate band float vals (len, rho, phi theta, not segs)
- -- by +/-10^(min...max)
- -- examples:
- -- min=-1;max=-1: change by +/-0.1
- -- min=-2;max=-1: change by +/-0.01
- -- min=-3;max=-3: change by +/-0.001
- -- min=-3;max=-1: change by +/-0.001, +/-0.01 +/-or 0.1
- };
- EO_mode={
- -- Extremal Optimization mode
- cur=0;
- -- integer val between 0...2
- -- 0 : no EO - breed clus (regular GAB) (default: keep 2, breed 3, generate 3)
- -- 1 : soft EO - keep clus instead of breeding them (default: keep 5, generate 3)
- -- 2 : hard EO - flush clus instead of breeding them (default: keep 2, generate 6)
- min=0;
- -- for gui
- max=2
- -- for gui
- };
- flush_gain_thr={
- -- flush herd (& load start state)
- -- if best gen's clu score gain is less than threshold
- act=true;
- -- boolean val
- -- true: check best gain
- -- false: don't check (& flush)
- thr=0.5;
- -- if score "gain" of best cluster is less than this thr
- -- can be negative, too
- min=-200;
- -- for gui
- max=200;
- -- for gui
- };
- flush_gain_reset={
- -- reset puzzle to script start state
- act=false;
- -- boolean val
- -- true: reset
- -- false: don't reset
- cur=0;
- -- flush counter
- thr=2;
- -- reset if flush counter exceeds this thr
- min=0;
- -- for gui
- max=20
- -- for gui
- };
- fitness_e=1;
- -- exponent for herd fitness "bending"
- -- allows worse clus to appear more often.
- -- tweaks distribution of fitness vals
- -- by passing them through this exponential function:
- -- fitness^(1/fitness_e) is a root function
- -- exponent vals <1 bend fitness vals towards 1
- -- same is done with small random vals in R= rho^(1/3) calculating section
- -- value examples: fitness_e -> fitness val
- -- 1/1 (exponent 1): exponent won't have an effect (routine will will be skipped)
- -- 1/2 (square root): fitness 0.01 -> 0.1, then normalized
- -- 1/3 (cubic root): fitness 0.001 -> 0.1, then normalized
- -- ... etc.
- use={
- state={
- -- load state mode
- val="recent";
- -- set which state will be loaded before each cluster pulling
- -- use one of these vals (also for gui):
- list={
- "start"; -- initial state at script start
- -- use if you are really stuck or have a new puzzle
- -- never leads to local maximum
- "gen"; -- best result of last gen
- -- use to allow score dropping
- -- and to (hopefully) escape local maximum
- "script"; -- script's best (script-internal "recent best")
- -- what the script considers as best solution so far
- -- may not catch all states (as scores are gotten after single relax/fuse steps)
- -- may lead to local maximum
- "recent" -- recent best
- -- what the game considers as best solution so far
- -- catches really best states (also inbetween relax/fuse steps)
- -- these states may not be stable
- -- may lead to local maximum
- }
- };
- hybrid={
- -- hybrid state loading
- -- loads selected puzzle state given below,
- -- but "start" state each gens to reset puzzle
- -- useful if you are really stuck
- -- or just beginning
- state=nil;
- -- nil: don't use hybrid state loading
- -- "gen": best result of last gen
- -- "script": script's best
- -- "recent": recent best
- gens=10;
- -- load "start" state each this number of gens
- -- for all other gens, load state given above
- }
- }
- }
- clu={
- fix={
- -- here you can set some seg-pairs, which dsts should be fixed by a band
- -- example:
- -- {2;21};
- -- {31;46};
- -- fix seg2 with seg21 &
- -- seg31 with seg46
- str=2;
- -- set str of fixing bands
- lencng=0;
- -- lencng=-3.8/4;
- -- add this val to measured dst between segs
- -- giving fixing band len
- -- use vals
- -- =0 : just keep dst of segs
- -- <0 : do some compression
- -- >1 : do some expansion
- };
- pull={str1=1;str2=0.1};
- -- set str of pulling bands
- -- str1: primary bands
- -- str2: secondary bands (used if d_cng2==act)
- band_to={
- -- banding mode
- val="random2";
- -- set where segs of uselist will be banded to
- -- use one of these vals (also for gui):
- list={
- "space"; -- band to space (3D-Angles)
- "center"; -- band to seg: center (auto-detection)
- "user"; -- band to seg: center (user-defined in puzzle.seg_center.val)
- "furthest"; -- band to seg: furthest
- "random1"; -- band to seg: random in uselist
- "random2" -- band to seg: random in puzzle (classical behaviour)
- }
- };
- rho={min=3.8/8;max=3.8};
- -- if band_to.val=="space" (seg to "air")
- -- absolute random bandlen minimum & maximum
- d_cng1={min=3.8/8;max=3.8};
- -- if band_to.val~="space"
- -- relative primary random bandlen minimum & maximum
- -- resulting band len: current seg dist+min..max
- d_cng2={act=true;min=0;max=3.8/8};
- -- if act==true
- -- relative secondary random bandlen (uselist-seg to uselist-seg)
- -- resulting band len=current seg dist+min..max
- band_sys_lim={
- -- band len allowed (by "system")
- min=3.8/2;
- -- you can also put 0 here,
- -- but then seg to seg bands can get 'too close'
- max=10000
- -- as said on fold.it homepage
- };
- seg_min_dist=3.8*1.25;
- -- minimum spatial dst for seg-banding
- -- (bandable segs detection thr based on dst)
- -- segs with dst less than this val are considered as 'too close'
- -- use this to prevent:
- -- connecting one segment to its index-neighbour, but allow closing cuts
- -- creating sharp edges in puzzle
- band_skip_wrong=false;
- -- set if "wrong bands" are corrected or rejected
- -- wrong bands: segs to be banded are too close
- -- true: reject actual band
- -- (you will have fewer bands, in worst case 0!)
- -- false: correct band target segment
- -- (will take nearest possible segment)
- }
- -- set which methods are performed when pulling:
- pull={act=true;
- CI_default=0.5;
- -- if no CI is given
- {CI=nil;cmd="w";itr=2;backbone=true;sidechains=false}
- -- CI=nil: don't change CI, use current (last) set value
- }
- -- set which methods are performed at each end of releasing & fusing:
- release_n_fuse_end={
- -- no
- -- act
- -- CI_default
- -- because this list is appended only
- {CI=nil;cmd="m";itr=1};
- -- CI=nil: don't change CI, use current (last) set value
- {CI=nil;cmd="w";itr=8;backbone=true; sidechains=true};
- {CI=nil;cmd="m";itr=1};
- {CI=nil;cmd="s";itr=1};
- {CI=nil;cmd="w";itr=1;backbone=true; sidechains=true}
- }
- -- set which methods are performed when releasing:
- release={act=false;
- -- fast "fuse" (quickstab) activated?
- CI_default=1;
- -- if no CI is given
- {CI=nil;cmd="m";itr=1};
- -- CI=nil: don't change CI, use current (last) set value
- {CI=nil;cmd="s";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- -- at the end, always the same:
- release_n_fuse_end[1];
- release_n_fuse_end[2];
- release_n_fuse_end[3];
- release_n_fuse_end[4];
- release_n_fuse_end[5]
- }
- -- set which methods are performed when fusing:
- -- currently there are 4 sequences of methods,
- -- but you can change their number (& length for each sequence)
- -- to do this,
- -- copy & paste a complete sequence (each begins with --fuse#x:)
- -- but take care of the braces!
- fuse={act=true;
- -- complex fuse activated?
- CI_default=0.3;
- -- if no CI is given
- --sequence start:
- --fuse#1:
- {
- {CI=0.1;cmd="m";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- -- CI=nil: don't change CI, use current (last) set value
- {CI=0.7;cmd="m";itr=1};
- {CI=nil;cmd="s";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- {CI=1.0;cmd="s";itr=0};
- -- itr=0: just set CI back to 1
- -- at the end, always the same:
- release_n_fuse_end[1];
- release_n_fuse_end[2];
- release_n_fuse_end[3];
- release_n_fuse_end[4];
- release_n_fuse_end[5]
- };
- --fuse#2:
- {
- {CI=0.3;cmd="m";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- -- CI=nil: don't change CI, use current (last) set value
- {CI=0.6;cmd="m";itr=1};
- {CI=nil;cmd="s";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- {CI=1.0;cmd="s";itr=0};
- -- itr=0: just set CI back to 1
- release_n_fuse_end[1];
- release_n_fuse_end[2];
- release_n_fuse_end[3];
- release_n_fuse_end[4];
- release_n_fuse_end[5]
- };
- --fuse#3:
- {
- {CI=0.2;cmd="m";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- -- CI=nil: don't change CI, use current (last) set value
- {CI=0.5;cmd="m";itr=1};
- {CI=nil;cmd="s";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- {CI=1.0;cmd="s";itr=0};
- -- itr=0: just set CI back to 1
- release_n_fuse_end[1];
- release_n_fuse_end[2];
- release_n_fuse_end[3];
- release_n_fuse_end[4];
- release_n_fuse_end[5]
- };
- --fuse#4:
- {
- {CI=0.4;cmd="m";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- -- CI=nil: don't change CI, use current (last) set value
- {CI=0.3;cmd="m";itr=1};
- {CI=nil;cmd="s";itr=1};
- {CI=nil;cmd="w";itr=4;backbone=true; sidechains=false};
- {CI=1.0;cmd="s";itr=0};
- -- itr=0: just set CI back to 1
- release_n_fuse_end[1];
- release_n_fuse_end[2];
- release_n_fuse_end[3];
- release_n_fuse_end[4];
- release_n_fuse_end[5]
- }
- --sequence end:
- }
- -- debugging section:
- function prms_show()
- -- a call of this function will show complete content
- -- of each table which is uncommented here
- -- you can also use this function to print out values,
- -- then copy & paste them back into script
- list_show_deep(puzzle,"puzzle")
- -- list_show_deep(seg_use,"seg_use")
- -- list_show_deep(gen,"gen")
- -- list_show_deep(herd,"herd")
- list_show_deep(clu,"clu")
- -- list_show_deep(release_n_fuse_end,"release_n_fuse_end")
- -- list_show_deep(release,"release")
- -- list_show_deep(fuse,"fuse")
- end -- function prms_show()
- -- for debugging before prm changes, uncomment this:
- -- prms_show()
- -- change section:
- -- call function to change some variables/tables via gui
- prms_cng()
- -- show section:
- -- for debugging after prm changes, uncomment this:
- -- prms_show()
- -- launch section:
- -- call main program
- main()
Add Comment
Please, Sign In to add comment