#] #] ********************* #] loaddefs link d_Qndfs 'optimize - particle swarm.ndf' # www.BillHowell.ca 18Apr2020 initial # view this file in a text editor, with [constant width font, tab = 3 spaces], no line-wrap f_PSO := 'optimize - particle swarm.ndf' ; loaddefs_start f_PSO ; #**************************** # List of operators, generated with : # $ cat "$d_Qndfs""optimize - particle swarm.ndf" | grep "^#]" | sed 's/^#\]/ /' # #08********08 # References search "Particle Swarm Optimisation source code" http://www.swarmintelligence.org/codes.php Source codes from swarm intelligence. Developed by Yuhui Shi and Russell Eberhart. open source Java implementation of the standard PSO algorithm. Developed by adaptiveview.com. Some particle swarm demos and source codes. developed by Maurice Clerc. A Java demo of PSO. developed by Mark C Sinclair #08********08 #] +-----+ #] Code IF flag_debug THEN write '+-----+' ; ENDIF ; IF flag_debug THEN write 'Code' ; ENDIF ; IF flag_debug THEN write 'loading PSO_optimize' ; ENDIF ; #] PSO_optimize IS - general Particle Swarm Optimizer # constraints for generality : ALL [velocity (+-MAXV), position (0 to 1)]s # must ensure that a z_Archive subDir exists!! # nomenclature : # PSO_controlL ("IRang_L "IRang_R "optrPhr "n_particles "E_CUTOFF "MAXV "MAXITER "momentum "max_runs "n_params "PSO_paramL "n_seeds "seedIndxL "seedParamL "xx "vx "particleErrorL "p_PSOresult) # PSO_paramL n_params anonymous (to PSO_optimize) adjustable parameters to fit model to data # one set of initial positions provided (or set = null), future - could be generalised to all or any # the objective here is to eliminate any reference to [domain, problem]-specific [symbols, information] # This ensures that PSO_optimize is as general as I can get it (as per Kennedy & Eberhardt) # 08Jan2021 but how do changing weights change params? : # for PuetzUWS, PSO_paramL is assigned in Puetz_UWS_optimisation # 09Jan2021 is there a [max, min] setting for the parameters? It must be an option!!! ; # 12Jan2021 I won't play with momentum at this time, later perhaps add to PSO_paramL ; # structure mnemonics : # inn_ = optr input argument # pas_ = pass through # wrk_ = work within optr # out_ = output structure IF flag_break THEN BREAK ; ENDIF ; PSO_optimize IS { LOCAL i_param tell_params i_particle tell_particles iL_sortupErrors iL_sortupParams iter body error finish fout run rowLabels gbest pbest pbestx tx vx weight_up xx PSO_controlL IRang_L IRang_R optrPhr n_particles E_CUTOFF MAXV MAXITER momentum max_runs n_params n_seeds seedParamL p_PSOresult PSO_return iL_sortupErrors__pbestx ; NONLOCAL d_temp yDataL ; % ; write link 'PSO_optimize begin time: ' timestamp_YYMMDD_HMS ; % ; % open file to output best particle index vs iteration ; IF (NOT path_exists "p_new p_PSOresult) THEN EACH write '?PSO_optimize error, file unknown : ' p_PSOresult '' ; ELSE % initialize ; % QNial : "... Seed is used to get predictable results from a program that uses random ..." ; % comment out to get potentially greater diversity of solutions, and better avoid local minima ; % seed .25374 ; % ; % PSO parameters as required ; % IRang_L = lower IRang, convert in UWS_result_and_error (general PSO_optimize) ; % IRang_R = higher IRang, convert in UWS_result_and_error (general PSO_optimize) ; % n_particles = number of particles in swarm ; % E_CUTOFF = errorMin, was 0.0 which seems idealistic, will force MAXITER? ; % MAXV = maximum particle velocity ; % MAXITER = maximum number of iterations ; % momentum = reduces particles' velocities as swarm runs ; % max_runs = maximum number of runs ; % n_params = number of model fitting parameters for optimisation ; % n_seed = number of initial seed params to replace some of the random-generated params ; % seedParamL = lists of seed parameters ; % p_PSOresult = writefile path ; IRang_L IRang_R optrPhr n_particles E_CUTOFF MAXV MAXITER momentum max_runs n_params n_seeds seedParamL p_PSOresult := EACH get_test03 "IRang_L "IRang_R "optrPhr "n_particles "E_CUTOFF "MAXV "MAXITER "momentum "max_runs "n_params "n_seeds "seedParamL "p_PSOresult ; fout := open p_PSOresult "w ; fout EACHRIGHT writefile '*********************' 'PSO_optimize begin time: ' timestamp_DDMMMYYYY_HMS '' 'optrPhr n_particles E_CUTOFF MAXV MAXITER momentum max_runs' (picture (optrPhr n_particles E_CUTOFF MAXV MAXITER momentum max_runs)) '' 'seedParamL : ' (picture seedParamL) '' ; % ; % randomized initializations ; % must ensure that a z_Archive subDir exists!! ; path_backupDatedTo_dir p_PSOresult (link (path_extract_dir p_PSOresult) 'z_Archive/') ; tell_params := tell n_params ; tell_particles := tell n_particles ; vx := n_params n_particles reshape [null] ; % all particles' velocities (+-MAXV) ; xx := n_params n_particles reshape [null] ; % all particles' thetaNweightL (0 to 1) ; tx := n_params n_particles reshape [null] ; % all particles' temporary thetaNweightL ; pbest := n_particles reshape 1e6 ; % all particles' best error ; pbestx := n_params n_particles reshape [null] ; % all particles' best thetaNweightL ; gbest := n_particles reshape 0 ; % global best particle index ; % ; FOR run WITH (tell max_runs) DO iter := 0 ; % start run at iteration 0 ; gbest := 0 ; % initially assume the first particle as the gbest ; % initialize the particles for each run ; xx := (IRang_R - IRang_L) * (random n_params n_particles) + IRang_L ; vx := MAXV * (random n_params n_particles) ; % seedParamL replaces random initial seed particles, and must be in the TRANSFORMED state ; IF (= "no_seed seedParamL) THEN null ; ELSEIF (= 1 n_seeds) THEN xx|[,0] := seedParamL ; ELSE xx|[,tell (gage shape seedParamL)] := seedParamL ; ENDIF ; pbestx := xx ; % ; % Main Work Loop for each run here ; finish := o ; WHILE (NOT finish) DO iter := iter + 1 ; % update momentum momentum, time variant weight, linear from weight to 0.4 ; % weight_up=weight, constant momentum momentum ; weight_up := (momentum - 0.4) * (MAXITER - iter) / MAXITER + 0.4 ; % ; FOR i_particle WITH tell_particles DO % couldn't get to work? ; error := apply optrPhr xx|[,i_particle] ; IF (error < pbest@i_particle) THEN pbest@i_particle := error ; pbestx|[,i_particle] := xx|[,i_particle] ; IF (pbest@i_particle < pbest@gbest) THEN gbest := i_particle ; ENDIF ; ENDIF ; % asynchronous version ; FOR i_param WITH tell_params DO vx@(i_param i_particle) := (weight_up * vx@(i_param i_particle)) + ((random 1) * MAXV * (pbestx@(i_param i_particle) - xx@(i_param i_particle))) + ((random 1) * MAXV * (pbestx@(i_param gbest ) - xx@(i_param i_particle))) ; IF (vx@(i_param i_particle) > MAXV) THEN vx@(i_param i_particle) := MAXV ; ELSEIF (vx@(i_param i_particle) < -MAXV) THEN vx@(i_param i_particle) := -MAXV ; ENDIF ; ENDFOR ; % Tx allows simultaneous updates ; FOR i_param WITH tell_params DO tx@(i_param i_particle) := xx@(i_param i_particle) + vx@(i_param i_particle) ; ENDFOR ; ENDFOR ; % ; % Update positions, Define new coordinates ; xx := tx ; % screen output iteration's current best result, helps tracking ; IF (= 0 (mod iter 100)) THEN writeL := (link 'iter : ' (string iter) ', 5 best errors : ' (numList_to_str (5 take (sortup pbest))) ) ; fout writefile writeL ; write writeL ; ENDIF ; % Terminate on criterion, screen output index vs iteration ; IF (OR (pbest@gbest <= E_CUTOFF) (iter >= MAXITER)) THEN write 'run finished! # ' run ; finish := l ; ENDIF ; ENDWHILE ; % ; rowLabels := EACH phrase ('param' EACHRIGHT link (EACH string tell_params)) ; colLabels := EACH phrase ('partcl' EACHRIGHT link (EACH string tell_particles)) ; tableAll := table_addRowColTitles rowLabels colLabels pbestx ; writeL := (link 'Run ' (string run) ' of ' (string max_runs) ' results, ' timestamp_DDMMMYYYY_HMS) '' 'global best error : ' (link 'best particle : ' (string i_particle )) (link 'error of best particle : ' (string pbest@gbest)) '' 'Ranking of all parameter errors (best to worst) : ' (numList_to_str iL_sortupErrors) '' (link 'PSO_optimize end time: ' timestamp_YYMMDD_HMS) '' '' ; fout EACHRIGHT writefile writeL ; write link 'PSO_optimize run end time: ' timestamp_YYMMDD_HMS ; ENDFOR ; close fout ; ENDIF ; % ; % Return all particles' best errors, and a table of corresponding best parameter sets ; pbest pbestx } # not used now - do on cumulative table from all runs of a test (eg test03) iL_sortupErrors iL_sortupParams iL_sortupIndxs := lists_sortupOn1st pbest (cols pbestx) tell_particles ; pbestxSorted := transpose mix iL_sortupParams ; 'parameters - particles sorted best to worst : ' (picture transpose tableAll) '' loaddefs_ended f_PSO ; # enddoc