The Command Object (Create and Update)

Command Structure

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 project
    • Update - to an existing project
  • projectID : 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 parameters
  • smdata : 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.

Problem definition

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": [ ]
  }
  

Name and description

The name and description fields are for user's own reference only.

Model version

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


    "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.

Syntax for valueStr and maskStr

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

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.

PDF for sampling

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


    "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


    "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


    "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


    "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.

Constraint scaling

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.

Algorithm Configuration

  ...

  "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:

  • algorithm - Options are:
    • NSGA2 - NSGA2 algorithm for optimisation
    • Parametrics - full parametric run (a.k.a. full factorial or exhaustive search)
    • Sampling - Random sampling (sampleSize must be assigned)
    • Hybrid - reserved for future development
  • sampleSize - For sampling mode only. Its value must be set if Sampling is selected.
  • initSampleOption - This field has dual use. In 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 sample
    • RANDOMWALK - 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_walk
    • MORRIS - 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_sampling
    • HALTON - Halton sequence, for up to 40 variables, see https://en.wikipedia.org/wiki/Halton_sequence
    • SALTELLI - 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.
  • initPopSize - Size of population 0. The initial population size can be different than the population growth size during the optimisation process
  • evolvePopSize - Population growth size during the optimisation process. In each new generation this number of new cases will be generated.
  • maxPopSize - in optimisation, the population size may grow with the number of Pareto solutions archived. This parameter specifies an upper limit. If exceeded, some existing Pareto solutions will be dropped.
  • mutationRate - overall mutation rate
  • crossoverRate - overall crossover rate
  • tournamentSize - tornament size
  • objectiveBias - constraint handling option is defined as bias towards objective functions. 0 means meeting contraints first. 1 means improving objectives first. 0.5 specifies a balanced strategy.
  • globalElitism - select from where the elite solutions are selected in the elitism method. true (default) means elites are drawn from the global archive. false means they are from the current population.
  • elitismTollerance - specifies up to what infeasibility level the solutions can be selected as elites. 0 means feasible solutions only.
  • maxGenerations - Maximum number of generations to run. Affects optimisation projects only. A value ⇐ 0 means no limit
  • maxEvaluations - Maximum number of evaluations to perform. Affects optimisation projects only. A value ⇐ 0 means no limit
  • maxComputingTime - (Reserved) Maximum amount of computing time allowed. Affects optimisation projects only. A value ⇐ 0 means no limit
  • maxWallTime - Maximum amount of clock time allowed for optimisation. Affects optimisation projects only. A value ⇐ 0 means no limit

The Circle Project

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;"
    }
}