
PSO algorithm is the core of the framework. There are a number of tools (blocks, script and observers) to monitor and control the PSO algorithm behaviour. Here we will look mainly into the script, the others are described elsewhere.
The
PSO is visually presented as tab in main paged control. Central part
contains the blocks, or the right are observers and on the left there
are PSO Run bar and PSO console under it. First lets deal with Run bar (from left to right):
The PSO console is under Run bar. In its normal state the console is just a log window. When the user double click on it additional controls appear (the image on the right). Top bar allows the user to save, erase or turn on/off the log. At the bottom: Eval tab is for evaluating expression (or variable) in the script. The Exec tab is for executing some code. If you need some results out, use print command and they will be out in the log. Open and Save button are for opening and saving some code. The code (in Exec) is normal Python code with any possible
extensions, plus access to properties: Options:
|
||
![]() |
![]() |
![]() |
PSO is implemented (at least the default behaviour) in pso_algo.pas
PSO object methods and properties
procedure Init(NumberOfParticles: integer = 0; ForceReset: boolean = false);
// particle & variables init; once per optim, AFTER blocks init
// if NumberOfParticles is the same as in the previous Init, ForceReset will
recreate the particles anyway
function GetItf: ITestFunc; // inteface to test function
procedure setParticleCount(NumberOfParticles: integer);
function GetVaiablesCount: integer;
procedure optimize(maximumIterations: integer=0; aTolerance: double = 0.0); //
the point of it all
function getBestFitness(): double;
procedure updateVariablesToBest();
procedure stop();
function IsRunning: boolean;
function OnTarget: boolean; // true if the target from testFunc.objective is hit
with tolerance testFunc.epsilon
function OutCount: integer; // counter of particles went out search space and
reinitrodused back
function GetStatus: rOptimRslt; // record of optimization results
property Variables: TVariableList read FVariables; // working variable
property Particles: TParticleList read FParticles; // total swarm
(create/destroy)
property SubSw: TSubSw read FSubSw; // over-lapping or not sub-swarms (only ref
to particles)
property SwarmBestEverPos: TDoubleDynArray read FSwarmBestEverPos write
FSwarmBestEverPos;
property SwarmBestEverFitness: double read FSwarmBestEverFitness write
FSwarmBestEverFitness;
property ShouldStop: boolean read GetShouldStop; // stop request
property ParticleCount: integer read FParticleCount;
property Iterations: integer read GetIterations;
property MaxIterations: integer read GetMaxIterations write SetMaxIterations;
property Tolerance: double read fTolerance; // only for internal (default) use
property Equidist: boolean read fEquidist; // equal particle distribution at
start
property User1: double read fUser1 write fUser1; // only for internal (default)
use
The optimize procedure has to be examine thoroughly, many important calls are there, including all DoChange(-1) principal calls for all pso blocks.
procedure TPSO.optimize(maximumIterations:
integer=0; aTolerance: double = 0.0);
var
swarmBest, prt: TParticle; ctrl: TController; iMdl: IblkModel;
swarmBestFitness, fitness, a: double; i: integer;
begin
fTolerance:= aTolerance;
if maximumIterations>0 then
FMaxIterations := maximumIterations;
if FMaxIterations=0 then
FMaxIterations := defaultIterations;
ctrl:= TController(Controller);
try
if ShouldStop then exit;
FIterations := 0; // utils init
fRunning:= true;
while (FIterations < FMaxIterations) and (not ShouldStop) do // THE MAIN
LOOP
begin
Inc(FIterations);
ObserverList.VisualUpdate(self); // update observers
if ShouldStop then break;
if Assigned(FOnBeforeIteration) then OnBeforeIteration(self);
// before event
if Assigned(TestFuncBlock) then TestFuncBlock.DoChange(-1);
// empty for now
// extract swarm params for particles speed calculations
iMdl:= ctrl.modelByFork('precalc'); // precalc fork
if Assigned(iMdl) then iMdl.DoChange(-1)
else begin // default action {
swarmBest:= FParticles.BestPrt(true); // recalc
// update global EVER best
if swarmBest.getFitness > FSwarmBestEverFitness then
begin
FSwarmBestEverFitness := swarmBest.getFitness;
FSwarmBestEverPos:= swarmBest.getPosition();
end;
end; // default action }
if ShouldStop then break;
// update all FParticles - MAIN speed adjustment
for prt in FParticles do
prt.update(FSwarmBestEverPos); // all prt blocks are in here
if ShouldStop then break;
if Assigned(FOnAfterIteration) and not ShouldStop then
OnAfterIteration(self); // after event
if Assigned(TermCondBlock) then TermCondBlock.DoChange(-1)
else begin // default action {
// termination conditions
if Tolerance>1.0E-100 then // if 0 only iters number
terminates
begin
if (FParticles.StdDevDistance(SwarmBestEverPos)<Tolerance)
then TermCond:= 'small spot';
if FParticles.Speed(spdMax)<Tolerance then
TermCond:= 'immobil. ('+F2S(FParticles.Speed(spdMax))+')';
end;
end; // default action }
if ShouldStop or (TermCond<>'') then break;
end; // end of MAIN loop
finally
if TermCond='' then
if ShouldStop
then TermCond:= 'User stop (iters='+IntToStr(Iterations)+')'
else TermCond:= 'max iters ('+IntToStr(Iterations)+')';
// finish with global best found in Variables
if not ShouldStop then updateVariablesToBest();
fRunning:= false;
end;
end;