A Create/Update command object contains six fields: command, project ID, problem definition, EA configuration, simulation model data, and solution filters.
command
: the command string can be one of the following: Create
- to create a new projectUpdate
- to an existing projectprojectID
: the original project ID for Create
, or a reference to the existing project for Update
problem
: problem definition object containing optimisation variables, evaluation result definitions, and assessment criteria.config
: Algorithm configuration object containing choice of exploration strategy, sampling method, population settings and other algorithm related parameterssmdata
: Model data object containing arbitrary data that are associated with the project's simulation model. This is for storing additional information with the project that the client program may use. Although JEA does not make use of these data directly, the object is nevertheless required in the definition.Example:
{ "command": "Create", "projectID": "my_project", "problem": { ... }, "config": { ... }, "smData": { ... } }
Null fields can be omitted in the JSON object.
The optimisation problem definition object contains seven fields, as shown in the skeleton JSON below:
"problem": { "name": "skeleton", "description": "", "modelVersion": "", "variables": [ ], "evalResults": [ ], "userMetrics": [ ], "objectives": [ ], "constraints": [ ] }
The name
and description
fields are for user's own reference only.
The modelVersion
field is introduced to provide a method for alerting JEA about model changes. Arbitrary text can be assigned to the field, and submitted to JEA. The JEA engine compare the received model version info with those on record, and acts accordingly (to be defined).
"variables": [ { "name": "x", "caption": "x variable", "valueStr": "[0:0.01:1]", "maskStr": "[0.5:0.01:0.6]", "valueType": "Number" } ]
In the object definition, name
is the identifier of the variable and is used for passing values between JEA and its client. valueStr
and maskStr
defines the list of values of the whole search space, and those to be explored in the current optimisation process. valueType
of a variable can be either Number
or List
.
Special syntax is used in the valueStr
and maskStr
fields. This provides a way to easily define a list of values, especially for numbers.
For the List
type of parameters, the values can be specified with a comma (,
) delimited list enclosed in a pair of curly brackets ({}
), e.g. {Detailed, Simple, CeilingDiffuser}
, or {1, 3, 5, 7}
.
For the “Number” typed parameters, square brackets ([]
) and union/exclusion operations (&
^
) are accepted in addition to the curly brackets ({}
). The square brackets are used to define a numerical series with regular intervals. For example, the list {1,3,5,7,9}
can be specified using [1:2:9]
. Colons (:
) are used to separate the Start Value, the Interval, and the End Value. Please note the last value in the resultant list is unnecessarily the End Value.
The union operator (&
) combines the elements in two lists. For example, [1:2:5]&{2,4,6}
is equivalent to {1,3,5,2,4,6}
(Note that the list is not sorted). The exclusion operator (^
) removes elements in the right-hand list from the left-hand list, e.g. [-2:1:6]^{2,4,6}
gives {-2,-1,0,1,3,5}
. The operators are processed in the left-to-right order. In the current version, grouping with parentheses is not supported. The following example shows the use of all supported operations: {1}&[0:5:30]^{0}
, which gives {1,5,10,15,20,25,30}
as the result.
Masking is a new concept introduced in JEA, to specify a sub-space of the solution domain without affecting the current problem definition. The maskStr
specifies a list of values that ARE available to optimisation. For example, if the valueStr
is [1:1:5]
and the maskStr
is {3}
, optimisation (and parametrics) will only operate on value 3
of this variable.
If no mask is required, you can omit the maskStr
field, or pass null
to it, or mirror the valueStr
field.
If you want to exclude certain values in the values list, use the exclusion operator in the maskStr
field may be more convenient. For example, to exclude 10 and 20 from list [1:1:30], use [1:1:30]^{10,20}
in maskStr
.
Special syntax (@sample()
) is used for defining probabilistic distribution functions (PDFs) for sampling. Details of the syntax, supported PDFs and examples are provided in Probabilistic Distributions section.
The sampling of the distribution is done in a static manner. First, the sample domain is divided into N (the sample size of the variable, as defined in @sample()) equal probability regions. Then the centre values are returned as the sample of their respective regions.
Please note that @sample()
must not be used in maskStr fields.
"evalResults": [ { "name": "f1", "caption": "Objective function 1", "unit": "-" } ]
The Evaluation Results are used to provide information of the values that the evaluation (simulation) results JEA will receive from the client. The identifiers are used in the SetEvaluationResult transactions.
"userMetrics": [ { "name": "u1", "caption": "User 1", "unit": "-", "formula": "f1" } ]
User Metrics are user defined report variables that are recorded but not used for optimisation purpose. They can also be used as intermediate variables for the calculation of objectives and constraints.
In the formula
field, all identifiers defined in evalResults
can be used in JavaScript styled expressions, including the Maths functions.
"objectives": [ { "name": "o1", "caption": "Objective 1", "unit": "-", "direction": "Minimize", "formula": "f1" } ]
Objectives can be minimized or maximized, which is defined by the direction
field. In the formula
field, all identifiers defined beforehand (Eval Results and User Metrics) can be used in JavaScript styled expressions, including the Maths functions.
"constraints": [ { "name": "c1", "caption": "Constraint 1", "unit": "-", "formula": "g1", "lb": 0, "ub": 25, "min": 0, "max": 1000, "weight": 1 } ]
Constraint objects are defined with six fields in addition to the identifier and descriptions. The fomula
field takes expression in JavaScript syntax, including the Maths functions, with any results, user metrics and objectives identifiers defined before it. The min
, lb
, ub
, max
fields define how the constraint to be scaled. Their use is illustrated in the diagram below.
If multiple constraints are defined, the overall infeasibility result is a weighted sum of all scaled constraint functions. The weight
field offers a way to prioritize individual constraints.
... "config": { "algorithm": "Sampling", "sampleSize": 1000, "initSampleOption": "SOBOL", "initPopSize": 10, "evolvePopSize": 10, "maxPopSize": 10000, "mutationRate": 0.2, "crossoverRate": 1, "tournamentSize": 2, "objectiveBias": 0, "globalElitism": true, "elitismTolerance": 0, "maxGenerations": 100, "maxEvaluations": 1000, "maxComputingTime": 100, "maxWallTime": 24 }, ...
The EA Configuration object controls the algorithms and their parameters. Here are the details of each field:
NSGA2
- NSGA2 algorithm for optimisationParametrics
- full parametric run (a.k.a. full factorial or exhaustive search)Sampling
- Random sampling (sampleSize
must be assigned)Hybrid
- reserved for future developmentSampling
is selected. NSGA2
mode, it specifies the sampling method for the initial population. Currently only RANDOM
is available for NSGA2
. In Sampling
mode, it specifies the sampling method to use, which include:RANDOM
- pseudo random sampleRANDOMWALK
- Simple random walk method, with single step change on each parameter. Actual number of sample cases are N*(d+1), where N is the sample size specified with sampleSize
, d is the number of variables. See https://en.wikipedia.org/wiki/Random_walkMORRIS
- similar to RANDOMWALK but with random step sizes. Actual number of sample cases are N*(d+1). Recommended N is between 4 and 20.LHS
- Latin Hypercube Sampling, see https://en.wikipedia.org/wiki/Latin_hypercube_samplingSOBOL
- Sobol sequence, see https://en.wikipedia.org/wiki/Sobol_sequenceHALTON
- Halton sequence, for up to 40 variables, see https://en.wikipedia.org/wiki/Halton_sequenceSALTELLI
- Saltelli's implementation of the Sobol method. Actual sample size is N*(2d+2). N (nominal sample size, as specified in the sampleSize
field) should be reasonably large, e.g. 1,000. Please note this method can lead to high computing cost.0
means meeting contraints first. 1
means improving objectives first. 0.5
specifies a balanced strategy.true
(default) means elites are drawn from the global archive. false
means they are from the current population.0
means feasible solutions only. The Circle is a simple project for testing the features of JEA. Here is the complete Command Object for the creating the project:
{ "command": "Create", "projectID": "circle", "problem": { "name": "circle", "description": "Test constrained mo fucntion with two variables", "modelVersion": "1.0.0", "variables": [ { "name": "x", "caption": "x in [0, 1]", "valueType": "Number", "valueStr": "[0:0.01:1]", "maskStr": "[0:0.1:1]" }, { "name": "y", "caption": "y in [0, 1]", "valueType": "Number", "valueStr": "[0:0.01:1]", "maskStr": "[0:0.1:1]" } ], "evalResults": [ { "caption": "Evaluation f1 = 100 * x", "unit": "-", "name": "f1" }, { "caption": "Evaluation f2 = 100 * y", "unit": "-", "name": "f2" } ], "userMetrics": [], "objectives": [ { "formula": "f1", "direction": "Minimize", "caption": "Objective t1 = f1", "unit": "-", "name": "t1" }, { "formula": "f2", "direction": "Minimize", "caption": "Objective t2 = f2", "unit": "-", "name": "t2" } ], "constraints": [ { "lb": 0, "ub": 30, "weight": 1, "formula": "Math.sqrt(Math.pow(f1-50, 2) + Math.pow(f2-50, 2))", "max": 100, "min": 0, "caption": "Constraint s1 <= 30", "unit": "-", "name": "s1" } ] }, "config": { "algorithm": "Parametrics", "initSampleOption": "RANDOM", "sampleSize": 0, "initPopSize": 10, "evolvePopSize": 10, "maxPopSize": 10000, "mutationRate": 0.2, "crossoverRate": 1, "tournamentSize": 2, "objectiveBias": 0, "elitismTolerance": 0, "globalElitism": true, "maxGenerations": 100, "maxEvaluations": 1000, "maxComputingTime": 100, "maxWallTime": 24 }, "smdata": { "modelID": "circle", "type": "JavaScript", "model": "var x = +vars.x, y = +vars.y;\n result.f1 = 100 * x;\n result.f2 = 100 * y;" } }