1. User level

The general purpose of a block is to parameterize some (any) part of PSO algorithm and/or to add functionality to it. Additional features include monitoring some properties in form of chart series and/or text log. A block can be either PSO block meaning it connects to a point inside of PSO algorithm code or particle block - the connection point is in particle update method. A PSO block (DoChange method) is called once per iteration, particle block is called for each particle for each iteration (there're some exceptions for the latter).

A block of properties with 4 sections (all optional - visually and functionally):

  • list of properties (of double, integer, boolean or selection type) with their values
  • chart following any numerical properties evolution along the iteration process
  • python code (one or more functions) accessing PSO algorithm including its particles and adding some functionality to it
  • log, particular for the evolution of this block properties

The blocks are located as tab in paged controls (at 8 possible locations). Any paged control can be empty or contain any number of block. The distribution of the blocks is adjustable from PSO menu->Options->Blocks tab. The actual relocation will take place after restart of the application. All the current properties can be saved in a single *.prop file, manually or when the program closes and opens afterwards.

Under the name of the block there is block menu, each of the four section of the block (Prop, Chart, Src, Log) can be switched on/off visually (Visual) and functionally (Enabled). The Visual switch controls only visual appearance of that section and Enabled switch only its functionality. Depending of the section there are additional menu items.

Property section: if you want to change double or integer properties, simply type the value in the right column. Some of the properties are read-only, marked in grey. The boolean property is represented by check box (check/uncheck = true/false). The selection property is selectable combo-box, usually for mode selection. In some cases when changing some selection that could lead to changing some other properties values or their accessibility (read-only or not). 

Chart section: any number of series can be shown. Each series correspond to one numerical property (double or integer). In Chart menu: Config series - opens checkable list of numerical properties to select from; Edit chart (double click on chart, does the same) - opens extensive menu you can use to customize the chart every way you wish.

Src (source) section: Src section is located under the chart section and has one (common) piece of code plus number of the functions pages switchable from the combo-box on the top. The functions can be places anywhere in PSO algorithm and provide helping hand with monitoring and additional functionality. The location in PSO and the parameters of the functions are developers job. You can easily change a functions code from there, but if the code is longer, the user can switch to bigger view as a tab in the observers panel. The common section is executed once at the start of the optimization and the function depending on a location once per iteration or once pre iteration per particle. Each function can be disabled individually - Enabled checkbox and all together from Enabled in Src menu.
Src code as source/text is saved in separate file (next to *.prop file) named as follows <prop.filename>_<block.name>.py and it is a standard Python code file.

Log section: from menu Config Log - opens log template page inside the log. In log template in free-form style the user can enter any text which includes any of the properties name in dollar sign brackets. For example: social factor -> $social.factor$ , the line of that template will produce a single line at each iteration replacing $social.factor$ with actual value at that step. One additional variable to log is current iteration count - $i$. From template page the user can clear the log of save its content in a text file. Option to clear the log every time optimization starts is there as well.
Erase log - clears the log.

When visible the sections are resizable with splitters (yellowish horizontal dividers) as well is the height of the whole block with bluish splitter. All the positions and heights are saved (file blocks.ini in Config subdir of working folder) on application closing and restored when it opens. That way at application opening everything (blocks locations and heights and properties values) will be as it was when the application closed the last time.

The three bars button on the right offers two update related options: Mute, which is equivalent to make all 4 sections disabled and Step over which defines the frequency of the block update; 1 means every iteration, 5 - every 5th, 10 - every 10th, etc. The update options have the obvious aim to improve on speed and if necessary still provide some info. The PSO has a general mute option which makes all blocks mute On/Off in sync.


2. Developer level

Front end

The user interface is composed from TTeeInspector component from TeeChart package - properties, TTeeChart component and FastSeries  - chart, the source section is a bit more complicated  with main component TSynEdit (colour coding inc.), the log is TRichEdit with customized color coding. The last three section have alternative Config or Expand views and the first one can have Configuration form attached for reconfigure the properties (from Menu button).

Model-View-Controller (MVC)

The main thing to remember here is to follow Model-View-Controller design pattern (try the net for more info). The version of MVC here is a variation of what you would find in literature, following more of the spirit than the letter of the original.

The most important class variable is props which contain the actual values. Each user property is descendant from class TPropVal from Utils unit, take a good look at its methods to understand how it works. It resembled variant type because can contain different primitive types and offer conversion. 

TPropVal = class
private
  fSel: byte;
  fInt: integer;
  fDbl: double;
  fOnChange: TNotifyEvent;
protected
  procedure SetInt(vl: integer);
  procedure SetDbl(vl: double);
  procedure SetSel(vl: byte);
public
  ReadOnly: boolean; // changable only from within the model (or desc)
  Hint: string;
  Style: TInspectorItemStyle; // iiBoolean, iiInteger, iiDouble, iiString, iiSelection
  bool: boolean;
  intMin,intMax: integer;
  dblMin,dblMax: double;
  str: string;
  selItems: string; // items of selection in comma list

  constructor Create(aStyle: TInspectorItemStyle = iiDouble; aReadOnly: boolean = false);
  procedure Assign(pv: TPropVal);
  function AsVar: variant;
  function AsDouble: double;
  function AsInt: integer;
  function AsString: string;
  procedure SetDouble(d: double);

  function selCount: integer;
  function rangeAsString: string; // allowed range of prop
  property int: integer read fInt write SetInt;
  property dbl: double read fDbl write SetDbl;
  property sel: byte read fSel write SetSel;
  property OnChange: TNotifyEvent read fOnChange write fOnChange;
end;

The component keeping and maintaining the actual properties is the model, the view provides an user access (read/write) and it's optional and the controller manage the encapsulation and synchronization. The unit containing the code MVC_U.
The model class is TblkModel which is essentially the collection of properties with methods to access and two synchro methods, first from View to Model, and second from Model to View:
  procedure OnChangeView(Sender: TObject); 
  procedure Notify(PropName: string; PropVal: TPropVal = nil);

Even the model is the "physical" container of the properties values, the access to it from a block (view) and controller is restricted using the interface IblkModel. Such a restriction is necessary to separate better internal from external presentation of the data according to MVC design pattern. One or more view are registered in the model.

IblkModel = interface
  procedure Config;  // called once created or after Configure
  function GetOnConfigure: TNotifyEvent; // hook for Configure
  procedure Init(idx: integer); // before optimization cycle (run)
  procedure DoChange(idx: integer); // at each iteration at pso block and
                  // for each particle at each iteration for particle (idx) block
  function LoadSrc(iniFN: string): boolean;
  procedure SaveSrc(iniFN: string);
  function GetSource: TSource;

  procedure RegView(view: IView); // register view
  procedure SetLocked(lck: boolean);
  procedure Notify(PropName: string; PropVal: TPropVal);
                 // if PropVal real assign to model (SetProp) and update the view
                 // if nil does not update model, but takes stored value for views
  procedure SynchroUp(PropName: string);
  procedure NotifyAll;

  function GetName: string;
  function GetDesc: string;
  function propCount: integer;
  function GetPropName(idx: integer): string; // from 0 till gets back empty
  function GetPropVar(PropName: string): variant;
  procedure SetPropVar(PropName: string; PropVal: variant);
  function GetProp(PropName: string): TPropVal;
  procedure SetProp(PropName: string; PropVal: TPropVal);
end;

The customized blocks implementations are classes descendants of TblkModel. Four methods (three - must and one - optional) are override:

procedure Config() - creation and configuration of the properties. The procedure is executed when Bee22 is run and if properties are cleared and are needed to be recreated. Here is an example from blk_algo.pas:

 wpv:= TPropVal.Create(iiInteger,problem.ss.fixD>0); wpv.int:= problem.ss.d;
 wpv.intMin:= 1; wpv.intMax:= 33;
 wpv.Hint:= 'The actual current dimensionality';
 SetProp('dim',wpv);

procedure Init(idx: integer) - is executed at the beginning of optimization cycle and idx is the particle index in case of particle block. It sets the initial conditions for the optimization and read the properties which are not expected to change during the optimization process.

procedure Synchro(PropName: string) [optional] - sometimes the properties are interconnected, change of one leads to change or condition others. In case you need something like that use Synchro method. When user changes the any property, the procedure will be called with PropName. The method will be called only if implemented, it is optional.

procedure DoChange(idx: integer) - is the main procedure at each iteration for pso block and at each iteration for each particle (idx) for particle block. The intended functionality of this method is to implement alternative piece of default part of algorithm wherever it is called from. Follow the code (e.g. TPreCalcBlock in blk_algo.pas) for better understanding. In some cases there won't be default behaviour, only some functionality will be added, e.g. TTestFuncBlock in blk_algo.pas

 

Configuration editor has a complementary functionality. The "normal" creation and configuration of the properties is in Config procedure of the particular block, the values are read in Init in the beginning of the optimization and in DoChange at each iteration. In some cases the user may wish to modify some of the property settings for some particular reason. Temporary or saving it in config.<block.name> file in Config folder. The properties used in the editor have to be functional thru Init and/or DoChange, otherwise there would be no point creating a unusable property.

  • Open/Save - opens/saves current state in a file with extension the block name.

  • New prop - creates new (for the setting) prop, which is actually already present in the block and read if created.

  • Remove prop - removes (erases) a property, which means that Init and DoChange won't use it.

  • Rename - changes the name of a prop

  • Up/Down buttons - rearranges the properties (the order)

The type (style) of the property is controlled by paged tabs and other setting specific to each type are on correspondent tab.

ReadOnly checkbox and Hint text (at the bottom) are common for any type of property.

Even the Configuration Editor is fully functional at its present implementation, it has limited applicability (see above). More important is that it gives a pathway and template to create customized configuration editors. That kind of editor would provide additional to properties and Python script ways adjust/extend PSO algorithm using a free-style form to accommodate whatever cannot fit in block's interface (or if it does would be user-unfriendly). The only restriction is that, as configuration editors go, it cannot stay open during the optimization execution.