AnyLogic Cloud API 8.5.0 Documentation

1 Overview

In addition to the standard web UI, Anylogic Cloud offers multiple APIs that you can use to configure and run simulations programmatically within your analytical workflows, query experiment results, build fully customized web interfaces for your models, and do a lot of other things. There are four APIs:

Related resources:

1.1 Simple YouTube-style embedding of simulation animations

Before we dive into AnyLogic Cloud API, we would like to make sure you know that there is a simple way of embedding Cloud-based animations into any web pages without using any API/coding whatsoever.

Embedding AnyLogic simulation animation

If you want your HTML page to have only the AnyLogic Cloud model animation, you can embed it just like a YouTube video:

  1. Locate the tile of the required model (either on the title screen or model screen)
  2. Click the <> icon at the bottom right corner of the model tile
  3. Copy the HTML fragment displayed in the dialog box
  4. Paste the fragment into your HTML page where you want the animation to appear:
<head>
    …
</head>
<body>
    …
    <iframe width="1000" height="650" ></iframe>
    …
</body>

That simple embedding is subject to the following restrictions:

  • Only animations of public models can be embedded that way
  • The animation always refers to the same simulation as the public page of the model, i.e.
    • to a simulation experiment of the latest model version
    • If the latest version has no simulation experiments, an error will occur
  • Please keep in mind:
    • You will be able to control the model execution only from the default animation toolbar
    • You will not be able to change parameters before simulation or save outputs afterwards
    • When you click Stop, the animation will return to the start page

1.2 Authentication with API key and security considerations

Any usage of AnyLogic Cloud API is done on behalf of a particular user. Authentication is done with the help of the API Key (randomly generated personal identifier). Below you can see an example of an API Key:

"e05a6efa-ea5f-4adf-b090-ae0ca7d16c20"

The API key is available for subscribers and the Private Cloud users (every Private Cloud user has their own API key).

To obtain the API key:

  1. Log in to AnyLogic Cloud.
  2. Open your user profile.
  3. Expand the API section — you will find your key there:

Example AnyLogic API key

Keep the key safe! If it gets unintentionally exposed, generate a new key and update your code with it!

Note, that the API key used in the JavaScript code of your custom web page (that is made public or open to an end user or a client) is exposed to whoever can access this web page, since the JavaScript code can be viewed in the browser console. This means that potentially, that person will be able to use the AnyLogic Cloud API under the same account!

Therefore, to protect your account, you should:

Create a separate AnyLogic Cloud account for the required user(s). (If you are using the public Cloud, that account should also be a subscriber account.)

  • Generate the API key from that user's account
  • Use that key in the JavaScript code
  • Share the required model(s) between your account (developer) and the user's account

This way you will have full control of the shared models and the ability to delete the user account(s) any time without affecting the models.

2 RESTful HTTP API

The AnyLogic Cloud API is versioned. The root address contains the version number, e.g. the root address for API version 8.5.0 for AnyLogic Cloud subscribers: https://cloud.anylogic.com/api/open/8.5.0. The same applies to Private Cloud. The address in this case will be: <your Private Cloud instance address>/api/open/8.5.0.

2.1 End points

Please note that you should provide "Authorization: <API key>" header in every HTTP request (see API Key). In AnyLogic HTTP API requests have no parameters. Some requests should provide data objects in the request body. The data objects are described in the next section.

GET /models - returns the array of all Models of the user (the API key owner), i.e. the models where the user has either developer or user access rights.

GET /models/<model id> - returns the Model with the given id.

GET /models/name/<model name> - returns the Model with the given name.

GET /models/<model id>/versions/number/<version number> - returns the Version with the given number (version numbering starts with 1).

GET /models/<model id>/versions/<version id> - returns the Version with the given id.

GET /versions/<version id>/experiments returns the array of Experiments created for the given model version.

POST /versions/<version id>/runs, body: Run Request - requests to perform a simulation run with the inputs contained in the Run Request. This will result in a real new simulation only if such run has not been performed yet. Returns Experiment Run, but does not wait for simulation to complete and therefore does not return the outputs.

POST /versions/<version id>/runs/stop, body: Run Request - stops execution of the model run provided in the request body. Does not return anything.

POST /versions/<version id>/run, body: Run Request - returns Experiment Run containing the status of the run. The intended use is to query the run state.

POST /versions/<version id>/results/<run id>, body: blank Outputs - returns the Outputs of the completed run with the given id according to the provided outputs template (so that you can control which data you will receive). If the run has not been completed, returns 404.

POST /versions/<version id>/results, body: Experiment Result Request - the Outputs of a completed run with a given id according to the outputs template provided. In contrast to the previous end point, this one does not require <run id>.

GET /versions/<version id>/runs/<run id>/progress - returns Experiment Run State containing the status and details of the run (which may be already completed or not).

POST /versions/<version id>/runs/animation, body: Run Request - starts animated run of the model. Waits for the animation to start, and returns Animation SVG Run Info containing, among other things, the host address of the node where the animated run has been created.

There are more end points for communication with the animated run (speed changing, pausing, etc.) but we are not describing them here because they only make sense in the browser environment (see the corresponding JavaScript API).

2.2 Data objects

The data structure of AnyLogic Cloud is roughly represented on the picture below. Using the API Key obtained from the page of a user, you can access the models listed in that user's My Models page. Each Model can have multiple versions, and the Version is what you can perform experiments with. AnyLogic Cloud keeps the inputs and outputs of all the experiments that have been ever run with each model version.

Data objects of AnyLogic Cloud

Model

Model is a simple object with a unique id, name, description, array of version ids, and a public/not public flag:

{
    id: "f7771cd8-8d55-486a-b255-10459a349093",
    name: "Flocks of Boids",
    description: "Original Boids, developed by Craig Reynolds, is an artificial life program ",
    modelVersions: [
        "7c702819-b413-417b-aa61-60becd029e3c",
        "de699d41-1f0c-497d-b544-413685f82d2b",
        "b845d4f9-972c-45c7-ae6a-7a762ab81c03"
    ],
    published: false
}

Version

Version contains full information about the model inputs, outputs, and dashboard configuration in its experimentTemplate field, for example:

{
    id: "def089c4-96a3-40f2-aefb-de1af471fe2f",
    version: 6,
    experimentTemplate: {
        inputs: [
            {name: "{STOP_MODE}", type: "STRING", units: null, value: "STOP_MODE_AT_TIME"},
            {name: "{START_TIME}", type: "DOUBLE", units: "SECOND", value: "0"},
            {name: "{STOP_TIME}", type: "DOUBLE", units: "SECOND", value: "1000000"},
            {name: "{START_DATE}", type: "DATE_TIME", units: null, value: "2019-05-15T00:00"},
            {name: "{STOP_DATE}", type: "DATE_TIME", units: null, value: "2019-05-26T13:46:40"},
            {name: "{MAX_MEMORY_MB}", type: "INTEGER", units: null, value: "512"},
            {name: "Arrival rate", type: "DOUBLE", units: null, value: "1"},
            {name: "Mean service time", type: "DOUBLE", units: null, value: "2"},
            {name: "Server capacity", type: "INTEGER", units: null, value: "3"},
            {name: "Check failure probability", type: "DOUBLE", units: null, value: "0.2"}
        ],
        outputs: [
            {name: "Queue size stats", type: "STATISTICS_CONTINUOUS", units: null, value: null},
            {name: "Total time in system|Total time in system", type: "HISTOGRAM_DATA", units: null, value: null},
            {name: "Utilization|Server utilization", type: "DOUBLE", units: null, value: null},
            {name: "Mean queue size|Mean queue size", type: "DOUBLE", units: null, value: null}
        ],
        dashboard: { }

    }
}

Please note that the inputs array contains the system inputs of the model (the ones in curly braces) such as the {STOP_TIME} or {MAX_MEMORY_MB} as well as the user-defined inputs. The value field contains the default value of the input and is always a string regardless of the input type. The outputs part of the object is not the actual outputs of some simulation run (those are described in the Outputs section), but a list of outputs that are available for that particular model version, therefore the value field is always null.

The dashboard configuration is irrelevant from the API user viewpoint, so we will skip its structure.

Experiment

Experiment contains the input settings of an experiment saved in the AnyLogic Cloud UI. It can be used (e.g. to set the inputs of a run invoked via the AnyLogic Cloud API) by calling the function createInputsFromExperiment() of the CloudClient object. It has the following structure:

{
    uuid: "f3f441f3-8117-4423-9b1c-75b4680c715b",
    modelVersion: "def089c4-96a3-40f2-aefb-de1af471fe2f",
    name: "Server Capacity Variation",
    type: "PARAMETER_VARIATION",
    inputs: [
        {name: "Arrival rate", type: "DOUBLE", units: null, value: "1"},
        {name: "Check failure probability", type: "DOUBLE", units: null, value: "0.2"},
        {name: "Mean service time", type: "DOUBLE", units: null, value: "2"},
        {name: "Server capacity", type: "FIXED_RANGE_INTEGER", units: null, value: "{"min":3,"max":7,"step":1}"},
        {name: "{MAX_MEMORY_MB}", type: "INTEGER", units: null, value: "512"},
        {name: "{RANDOM_SEED}", type: "LONG", units: null, value: "1"},
        {name: "{START_DATE}", type: "DATE_TIME", units: null, value: "2019-05-15T00:00"},
        {name: "{START_TIME}", type: "DOUBLE", units: "SECOND", value: "0"},
        {name: "{STOP_DATE}", type: "DATE_TIME", units: null, value: "2019-05-26T13:46:40"},
        {name: "{STOP_MODE}", type: "STRING", units: null, value: "STOP_MODE_AT_TIME"},
        {name: "{STOP_TIME}", type: "DOUBLE", units: "SECOND", value: "1000000"}
    ]
}

Note that the value field of an input item always contains a string, for example, for the input of range type ("FIXED_RANGE_INTEGER") it is a string with unparsed JSON with min, max, and step fields.

Possible values of the type field are listed in Input types section. The unit field can contain null or one of the values listed in the Units section.

Outputs

The Outputs object is fairly complex and we strongly recommend using the Cloud clients provided by AnyLogic, since they contain methods simplifying navigation through Outputs (such methods are present in e.g. SingleRunOutputs and MultiRunOutputs JavaScript objects). The Outputs object is an array with each element representing a single output of a run or a series of runs. Note that in case of multi-run experiments, an element can represent an input varied across the runs. The aggregationType field is a system field that tells how the results of individual runs are aggregated. Consider an example of a single run outputs:

[
    {
        aggregationType: "IDENTITY",
        inputs: [],
        outputs: [{name: "Queue size stats", type: "STATISTICS_CONTINUOUS", units: null, value: null}],
        value: "{"type":"CONTINUOUS","count":1375730,"min":0.0,"max":10.0,"mean":0.9915478405530092, … }"
    },
    {
        aggregationType: "IDENTITY"
        inputs: []
        outputs: [{name: "Total time in system|Total time in system", type: "HISTOGRAM_DATA", units: null, value: null}]
        value: "{"statistics":{"type":"DISCRETE","count":1000897,"min":1.6001570096705109, … }"
    },
    {
        aggregationType: "IDENTITY"
        inputs: []
        outputs: [{name: "Utilization|Server utilization", type: "DOUBLE", units: null, value: null}]
        value: "0.500358755897554"
    },
    {
        aggregationType: "IDENTITY"
        inputs: []
        outputs: [{name: "Mean queue size|Mean queue size", type: "DOUBLE", units: null, value: null}]
        value: "0.9915478375701102"
    }
]

In case of a single simulation run, there is obviously no aggregation, and the value of the aggregationType field is IDENTITY . Besides the aggregationType, each element of a top-level array always contains inputs, outputs, and value fields. As there are no varied parameters in a single run, there are no input descriptors and the inputs field is an empty array in all items. The outputs field is an array with a single element describing the output: its name, type, units, and value, but the value is always null in the descriptor.

The possible values of the type field of an array element are listed in the Input types section.

The actual value of the output is contained in the value field of the top-level array element as an unparsed JSON object. You can find more information on the value formats in the section about data conversion.

Please keep in mind that, although an AnyLogic chart (possibly, containing multiple data items) is a single item in AnyLogic Run configuration, its data items become separate items in AnyLogic Cloud API. Therefore, the name of such item returned by the API comprises <the name of the chart in Run Configuration outputs>|<the title of the data item in the chart>. For other AnyLogic outputs, such as (explicitly defined) datasets, statistics objects, output objects, the name in AnyLogic API outputs is the same as in AnyLogic. Compare the JS object above with the Run configuration screenshot:

Outputs in AnyLogic Run Configuration

In case of multi-run experiments, such as Variation or Monte Carlo, the format of outputs becomes a bit more complicated. To give you an idea of the format, let us consider the outputs of the parameter variation experiment of the same model that produced the single-run outputs described above:

[
    {
        aggregationType: "ARRAY",
        inputs: [],
        outputs: [{name: "Queue size stats", type: "STATISTICS_CONTINUOUS", units: null, value: null}],
        value: "[{"count":1335978,"min":0.0,"max":10.0,"mean":0.9860041083277306,"variance":0.07920717342721317, … }]"
    },
    {
        aggregationType: "ARRAY",
        inputs: [],
        outputs: [{name: "Total time in system|Total time in system", type: "HISTOGRAM_DATA", units: null, value: null}],
        value: "[{"statistics":{"type":"DISCRETE","count":999206,"min":1.4401413087034598, … }]"
    },
    {
        aggregationType: "ARRAY",
        inputs: [],
        outputs: [{name: "Utilization|Server utilization", type: "DOUBLE", units: null, value: null}],
        value: "[0.4497779714401299,0.4750782325123417,0.500358755897554]"
    },
    {
        aggregationType: "ARRAY",
        inputs: [],
        outputs: [{name: "Mean queue size|Mean queue size", type: "DOUBLE", units: null, value: null}],
        value: "[0.9860040848956356,0.9877473693031751,0.9915478375701102]"
    },
    {
        aggregationType: "ARRAY",
        inputs: [{name: "Mean service time",type: "FIXED_RANGE_DOUBLE",units: null,value: "{"min":"1.8","max":"2","step":"0.1"}"}],
        outputs: [],
        value: "[[1.8],[1.9],[2.0]]"
    }
]

The aggregationType is now ARRAY. As you can see, one of the items in the top-level array (the last one) now contains a non-empty input field for the input that is being varied. The (unparsed) value fields of the output items are now arrays with multiple elements, for example, the Queue size stats has an array of three statistics objects in its value field. The sequence of the output values in the arrays corresponds to the sequence of the varied input parameter values. Once again: the Cloud clients provided by AnyLogic enable easy iterations though the inputs and outputs, see for example the JS MultiRunOutputs class.

Run Request

Run Request contains the type of experiment and the full list of inputs. It does not contain a reference to the model version, which is passed as a part of the request URL. Below you can see an example of Run Request for a simulation run:

{
    experimentType: "SIMULATION",
    inputs: [
        {name: "{STOP_MODE}", type: "STRING", units: null, value: "STOP_MODE_AT_TIME"},
        {name: "{START_TIME}", type: "DOUBLE", units: "SECOND", value: "0"},
        {name: "{STOP_TIME}", type: "DOUBLE", units: "SECOND", value: "1000000"},
        {name: "{START_DATE}", type: "DATE_TIME", units: null, value: "2019-05-15T00:00"},
        {name: "{STOP_DATE}", type: "DATE_TIME", units: null, value: "2019-05-26T13:46:40"},
        {name: "{MAX_MEMORY_MB}", type: "INTEGER", units: null, value: "512"},
        {name: "Arrival rate", type: "DOUBLE", units: null, value: "1"},
        {name: "Mean service time", type: "DOUBLE", units: null, value: "2"},
        {name: "Server capacity", type: "INTEGER", units: null, value:  5 },
        {name: "Check failure probability", type: "DOUBLE", units: null, value: "0.2"},
        {name: "{RANDOM_SEED}", type: "LONG", units: null, value: "1"}
    ]
}

For a parameter variation experiment with one parameter varied in a range, the Run Request looks like this:

{
    experimentType: "PARAMETER_VARIATION",
    inputs: [
        {name: "{STOP_MODE}", type: "STRING", units: null, value: "STOP_MODE_AT_TIME"},
        {name: "{START_TIME}", type: "DOUBLE", units: "SECOND", value: "0"},
        {name: "{STOP_TIME}", type: "DOUBLE", units: "SECOND", value: "1000000"},
        {name: "{START_DATE}", type: "DATE_TIME", units: null, value: "2019-05-15T00:00"},
        {name: "{STOP_DATE}", type: "DATE_TIME", units: null, value: "2019-05-26T13:46:40"},
        {name: "{MAX_MEMORY_MB}", type: "INTEGER", units: null, value: "512"},
        {name: "Arrival rate", type: "DOUBLE", units: null, value: "1"},
        {name: "Mean service time", type: "FIXED_RANGE_DOUBLE", units: null, value:  { min : 1.8 , max : 2 , step : 0.1 } },
        {name: "Server capacity", type: "INTEGER", units: null, value:  5 },
        {name: "Check failure probability", type: "DOUBLE", units: null, value: "0.2"},
        {name: "{RANDOM_SEED}", type: "LONG", units: null, value: "1"}
    ]
}

Please note that the value of an input is always a string, which may contain an unparsed JSON like in case of a range.

Experiment Results Request

Experiment Results Request contains the type of experiment, the full list of inputs, and the list of required outputs. The latter is a string form of the Outputs data object with blank values. For example:

{
    experimentType: "SIMULATION",
    inputs: [
        {name: "{STOP_MODE}", type: "STRING", units: null, value: "STOP_MODE_AT_TIME"},
        {name: "{START_TIME}", type: "DOUBLE", units: "SECOND", value: "0"},
        {name: "{STOP_TIME}", type: "DOUBLE", units: "SECOND", value: "1000000"},
        {name: "{START_DATE}", type: "DATE_TIME", units: null, value: "2019-05-15T00:00"},
        {name: "{STOP_DATE}", type: "DATE_TIME", units: null, value: "2019-05-26T13:46:40"},
        {name: "{MAX_MEMORY_MB}", type: "INTEGER", units: null, value: "512"},
        {name: "Arrival rate", type: "DOUBLE", units: null, value: "1"},
        {name: "Mean service time", type: "DOUBLE", units: null, value: "2"},
        {name: "Server capacity", type: "INTEGER", units: null, value:  5 },
        {name: "Check failure probability", type: "DOUBLE", units: null, value: "0.2"},
        {name: "{RANDOM_SEED}", type: "LONG", units: null, value: "1"}
    ]
    outputs: "[{"aggregationType":"IDENTITY","inputs":[],"outputs":[{"name":"Queue size "
}

Experiment Run

Experiment run contains the unique run id, the model version id, the inputs, the run status, and the message containing unparsed JSON with information about the run (see Experiment Run State) and can be empty, for example:

{
    id: "Ao7KEYv76pyqZFf6QetmAg6InFuJoJMj1WbYaSm17wo",
    inputs: [
        {name: "{STOP_MODE}", type: "STRING", units: null, value: "STOP_MODE_AT_TIME"},
        {name: "{START_TIME}", type: "DOUBLE", units: "SECOND", value: "0"},
        {name: "{STOP_TIME}", type: "DOUBLE", units: "SECOND", value: "1000000"},
        {name: "{START_DATE}", type: "DATE_TIME", units: null, value: "2019-05-15T00:00"},
        {name: "{STOP_DATE}", type: "DATE_TIME", units: null, value: "2019-05-26T13:46:40"},
        {name: "{MAX_MEMORY_MB}", type: "INTEGER", units: null, value: "512"},
        {name: "Arrival rate", type: "DOUBLE", units: null, value: "1"},
        {name: "Mean service time", type: "DOUBLE", units: null, value: "2"},
        {name: "Server capacity", type: "INTEGER", units: null, value: "5"},
        {name: "Check failure probability", type: "DOUBLE", units: null, value: "0.2"},
        {name: "{RANDOM_SEED}", type: "LONG", units: null, value: "1"}
    ],
    message: "{"title":null,"total":100,"finishedTasks":1,"totalTasks":1,"subRuns":[]}",
    modelVersionId: "def089c4-96a3-40f2-aefb-de1af471fe2f",
    outputs: null,
    status: "COMPLETED"
}

The outputs field of the Experiment Run is always empty.

Experiment Run State

Experiment Run State comes in response to a progress request. It contains the status of the run and the message field with the unparsed JSON structure with the run progress details:

{
    message: "{"title":null,"total":52,"finishedTasks":0,"totalTasks":1,"subRuns":[]}",
    status: "RUNNING"
}

To obtain the completed fraction of the run, you can call JSON.parse( <experiment run state>.message ).total;

The status of a run can be:

  • "FRESH" - created, not yet started
  • "RUNNING" - currently being executed
  • "COMPLETED" - successfully completed, results are available
  • "FAILED" - execution failed
  • "STOPPED" - cancelled before completion by the user (via GUI or API).

For a completed run, the message field may be an empty string:

{
    message: "",
    status: "COMPLETED"
}

For a multiple run experiment, the Experiment Run State will look like this:

{
    message: "{"title":null,"total":47,"finishedTasks":0,"totalTasks":11," … }",
    status: "RUNNING"
}

And if you parse the message field, the structure will be:

{
    finishedTasks: 0
    subRuns: [
        {title: null, total: 42, finishedTasks: 2, totalTasks: 5, subRuns: []},
        {title: null, total: 42, finishedTasks: 2, totalTasks: 5, subRuns: []}
    ],
    title: null,
    total: 47,
    totalTasks: 11
}

The subRuns field contains information about the batches of individual runs comprising the experiment.

Animation SVG Run Info

Animation SVG Run Info comes in response to starting model run with animation.= It contains the native dimensions of the animation window, the simulation speed, the URL of the node where the simulation is running, and other information:

{
    animationHeight: 600,
    animationSpeed: 10,
    animationWidth: 1000,
    experimentRunId: "fbc6a1d8-fa08-4a5c-a171-4631657c1aa7",
    modelUuid: "493e6789-acf7-4dac-971d-325cb508ea39",
    restUrl: "b0cc221b-8217-474b-af18-c2d07753187b/",
    sessionUuid: "b0cc221b-8217-474b-af18-c2d07753187b",
    version: "8.5.0"
}

Input types

Input type is a string constant with the following possible values:

  • "STRING"
  • "DOUBLE"
  • "INTEGER"
  • "LONG"
  • "DATE_TIME"
  • "BOOLEAN"
  • "RANDOM_DOUBLE"
  • "RANDOM_INTEGER"
  • "RANDOM_BOOLEAN"
  • "FIXED_RANGE_DOUBLE"
  • "FIXED_RANGE_INTEGER"
  • "FIXED_RANGE_LONG"
  • "FULL_RANGE_BOOLEAN"
  • "INPUT_FILE"

Units

Unit is a string constant, it can be null, or one of the following types:

  • "MILLISECOND"
  • "SECOND"
  • "MINUTE"
  • "HOUR"
  • "DAY"
  • "WEEK"
  • "MONTH"
  • "YEAR"
  • "MILLIMETER"
  • "CENTIMETER"
  • "METER"
  • "KILOMETER"
  • "INCH"
  • "FOOT"
  • "YARD"
  • "MILE"
  • "NAUTICAL_MILE"
  • "SQ_MILLIMETER"
  • "SQ_CENTIMETER"
  • "SQ_METER"
  • "SQ_KILOMETER"
  • "SQ_INCH"
  • "SQ_FOOT"
  • "SQ_YARD"
  • "SQ_MILE"
  • "SQ_NAUTICAL_MILE"
  • "PER_MILLISECOND"
  • "PER_SECOND"
  • "PER_MINUTE"
  • "PER_HOUR"
  • "PER_DAY"
  • "PER_WEEK"
  • "PER_MONTH"
  • "PER_YEAR"
  • "MPS"
  • "KPH"
  • "FPS"
  • "FPM"
  • "MPH"
  • "KN"
  • "MPS_SQ"
  • "FPS_SQ"
  • "LITER"
  • "OIL_BARREL"
  • "CUBIC_METER"
  • "KILOGRAM"
  • "TON"
  • "LITER_PER_SECOND"
  • "OIL_BARREL_PER_SECOND"
  • "CUBIC_METER_PER_SECOND"
  • "KILOGRAM_PER_SECOND"
  • "TON_PER_SECOND"
  • "TURN"
  • "RADIAN"
  • "DEGREE"
  • "RPM"
  • "RAD_PER_SECOND"
  • "DEG_PER_SECOND"

Output types

Output type is a string constant with the following possible values:

  • "STRING"
  • "DOUBLE"
  • "INTEGER"
  • "LONG"
  • "DATE_TIME"
  • "BOOLEAN"
  • "DATA_SET"
  • "STATISTICS_DISCRETE"
  • "STATISTICS_CONTINUOUS"
  • "HISTOGRAM_DATA"
  • "HISTOGRAM_2D_DATA"
  • "MODEL_OUTPUT_NAME"

3 API usage examples

3.1 Simulation run without animation (minimalistic)

In this example we run a simulation experiment without animation. First, we find the model and its latest version. Next, we specify the input parameters of the model. If simulation with such inputs has already been completed (and thus, the outputs are stored in Cloud), the outputs are simply transferred to the web frontend. Otherwise, simulation is run in the fast mode without animation. The outputs in this case are generated and delivered to the frontend.

Javascript

This is done with the API function ModelRun.getOutputsAndRunIfAbsent().

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Run simulation. Minimalistic</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button" onclick="runSimulation()">Run simulation</button>
    <div id="info">The simulation results will be displayed here</div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let runButton;
let info;
let inputs;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    info = document.getElementById( "info" );
};

function runSimulation() {
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Service System Demo" )
        .then( version => {
            inputs = cloudClient.createDefaultInputs( version );
            inputs.setInput( "Server capacity", 8 );
            let simulation = cloudClient.createSimulation(inputs);
            info.innerHTML = "Getting outputs, running simulation if absent...";
            return simulation.getOutputsAndRunIfAbsent();
        })
        .then( outputs => {
            let html = "For Server Capacity = " + inputs.getInput( "Server capacity" ) + ":<br>";
            html += "Mean queue size = " + outputs.value( "Mean queue size|Mean queue size" ) + "<br>";
            html += "Server utilization = " + outputs.value( "Utilization|Server utilization" ) + "<br>";
            info.innerHTML = html;
        })
        .catch( error => {
            info.innerHTML = error.status + "<br>" + error.message;
            console.error( error );
        })
        .finally( () => {
            runButton.disabled = false;
        });
}

Try now

We include the AnyLogic Cloud Client JavaScript into the HTML as advised in the installation guide; there is also a button and a div element to display the simulation results.

As the web page and the scripts get loaded, a CloudClient object is created, given the API key. The second optional parameter of the static function CloudClient.create() is the URL of Cloud. It is omitted here, so AnyLogic Public Cloud is assumed. We also remember the HTML elements we will use.

When the user presses the Run button, the function runSimulation() is called. It disables the button and initiates a chain of client-server communication using the JavaScript Promise mechanism:

  1. The server is asked to find the latest version of the model with the name “Service System Demo”.
  2. When (and if) such model and version is found (the first then), we create the Inputs object with default input values. And in those inputs, we change the value of “Server capacity” parameter to 8. We ask the CloudClient to create a simulation object with the inputs. This is a purely fronted operation, there is no communication with the server. This code block finishes with the call of getOutputsAndRunIfAbsent(), which checks the simulation status: if such simulation has been completed it gets the outputs, if it hasn't been run yet, it runs the simulation and waits for the outputs. The SingleRunOutputs object is returned by Promise.
  3. When the outputs are delivered, we display some output values and the corresponding input using the API of SingleRunOutputs and Inputs. That’s it. If no error occurs during that sequence of operations, we proceed directly to the finally block, where we re-enable the Run button.
  4. If an error occurs during any step, the catch block is invoked. Here we display the error message and copy it to console. Then the finally block is executed.
  5. Please note that to get the value of a particular output, we need to specify its name exactly as it is constructed when the model is uploaded to Cloud (for more information refer to the Output data object section. The case, however, does not matter: you can use either lower case or upper case.

It is also worth reminding that the function runSimulation() completes immediately, and the code fragments written in the then, catch, and finally blocks are invoked later when the corresponding events occur.

Python

This is done with the API function ModelRun.get_outputs_and_run_if_absent().

Python:

from anylogiccloudclient.client.cloud_client import CloudClient

client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
version = client.get_latest_model_version("Service System Demo")
inputs = client.create_inputs_from_experiment(version, "Baseline")
inputs.set_input("Server capacity", 8)
simulation = client.create_simulation(inputs)
outputs = simulation.get_outputs_and_run_if_absent()

print("Raw outputs = " + str(outputs.get_raw_outputs()))
print("For Server Capacity = " + str(inputs.get_input("Server capacity")))
print("Mean queue size = " + str(outputs.value("Mean queue size|Mean queue size")))
print("Server utilization = " + str(outputs.value("Utilization|Server utilization")))

Python is considered a backend programming language, that is why the inputs and the outputs are accessible through the console only:

  1. The CloudClient object is created, given the API key.
  2. The server is asked to find the latest version of the model with the name "Service System Demo".
  3. When (and if) such model and version is found, we create the Inputs object with the default input values.
  4. We use the set_input() function to change the value of the "Server capacity" parameter to 8.
  5. We ask the CloudClient to create a simulation object with the inputs. This is done on the client side, there is no communication with the server.
  6. The getOutputsAndRunIfAbsent() function is called, which checks the simulation status:
    • If such simulation has been completed, it gets the outputs
    • If such simulation hasn't been run yet, it runs the simulation and waits for the outputs. The SingleRunOutputs object is returned
  7. Finally, the obtained output values and the corresponding input are displayed in the console using the API of SingleRunOutputs and Inputs.

If an error occurs during any step, the error message will be displayed in the console.

Please note that to get the value of a particular output, we need to specify its name exactly as it is constructed when the model is uploaded to Cloud (for more information refer to the Output data object section. The case, however, does not matter: you can use either lower case or upper case.

Java

This is done with the API function ModelRun.getOutputsAndRunIfAbsent().

Java:

String API_KEY = "e05a6efa-ea5f-4adf-b090-ae0ca7d16c20";
String DOUBLE_INPUT = "Server capacity";
String DOUBLE_OUTPUT = "Utilization|Server utilization";
AnyLogicCloudClient client = new AnyLogicCloudClient(API_KEY);
Model model = client.getModelByName("Service System Demo");
ModelVersion version = client.getLatestModelVersion(model);

Inputs inputs = client.createDefaultInputs(version);
inputs.setInput(DOUBLE_INPUT, 20);
SimulationRun simulation = client.createSimulation(inputs);
SingleRunOutputs outputs = simulation.getOutputsAndRunIfAbsent(); // will exit upon run completion

System.out.println(outputs.value(DOUBLE_OUTPUT));

First, we define multiple values that will be used for input.

  1. The AnyLogicCloudClient class is constructed, given the API key.
  2. The server is asked to find the model with the given model name (Service System Demo).
  3. The server is asked to find the latest version of the model.
  4. When (and if) such model and version is found, we create the Inputs object with the default input values.
  5. We use the setInput function to change the value of the “Server capacity” parameter to 20.0. Other inputs will keep their default values.
  6. We ask the AnyLogicCloudClient to create a simulation object with the inputs. This is done on the client side, there is no communication with the server.
  7. The getOutputsAndRunIfAbsent() function is called, which checks the simulation status:
    • If such simulation has been completed, it gets the outputs
    • If such simulation hasn't been run yet, it runs the simulation and waits for the outputs. The SingleRunOutputs object is returned
  8. Finally, the output value for the “Average performance” field is displayed in the Java console using the API of SingleRunOutputs.

If an error occurs during any step, the error message will be displayed in the Java console.

Please note that to get the value of a particular output, we need to specify its name exactly as it is constructed when the model is uploaded to Cloud (for more information refer to the Output data object section. The case, however, does not matter: you can use either lower case or upper case.

3.2 Querying simulation results of a completed run

As you know, AnyLogic Cloud stores the input/output pairs of all the ever-completed simulation runs. In this example, we will show you how to query the outputs of a completed model run (which is identified by the inputs). If the results exist, they will be displayed, otherwise, we will display the corresponding message instead of running the simulation as we did in the previous example.

Javascript

The key function used here is ModelRun.getOutputs().

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Query outputs of a completed run</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    Server capacity: <span id="parameter-value">5</span>
    <input id="parameter-range" type="range" min="2" max="10" step="1" value="5" onchange="changeValueText()">
    <button id="query-button" onclick="queryOutputs()">Query outputs</button>
    <div id="info">The simulation results will be displayed here</div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let parameterValue;
let parameterRange;
let queryButton;
let info;

window.onload = () => {
    parameterValue = document.getElementById( "parameter-value" );
    parameterRange = document.getElementById( "parameter-range" );
    queryButton = document.getElementById( "query-button" );
    info = document.getElementById( "info" );
};

function queryOutputs() {
    parameterRange.disabled = true;
    queryButton.disabled = true;
    cloudClient.getModelByName( "Service System Demo" )
        .then( model => cloudClient.getLatestModelVersion( model ) )
        .then( version => {
            let inputs = cloudClient.createDefaultInputs( version );
            inputs.setInput( "Server capacity", parameterRange.value);
            let simulation = cloudClient.createSimulation(inputs);
            info.innerHTML = "Getting outputs...";
            return simulation.getOutputs();
        })
        .then( outputs => {
            let html = "Mean queue size = " + outputs.value( outputs.findNameIncluding("Mean Queue Size") ) + "<br>";
            html += "Server utilization = " + outputs.value( outputs.findNameIncluding("Server utilization") ) + "<br>";
            info.innerHTML = html;
        })
        .catch( error => {
            info.innerHTML = error.status + "<br>" + error.message;
            console.error( error );
        })
        .finally( () => {
            parameterRange.disabled = false;
            queryButton.disabled = false;
        });
}

function changeValueText() {
    parameterValue.innerText = parameterRange.value;
}

Try now

In the HTML code there is a range input element that we use to set the value of the Server capacity. Having constructed the inputs and the simulation objects, we call simulation.getOutputs(). If the outputs exist, they are returned by Promise and we get into the following then block. If there are no outputs, an error occurs, we process to the catch block and display the error. However, the same catch block is executed if any other type of error occurs. If you want to invoke a specific handler in case of absent results, you can modify the code in the following way:

JavaScript:

…
return simulation.getOutputs()
    .catch( error => {
        if( error.status == 404 ) {
            //custom handler code
            console.error( "Simulation results not found for these inputs" );
        }
        throw new Error( "Outputs not found for Server Capacity = " + parameterRange.value );
    });
…

Python

The key function used here is ModelRun.get_outputs().

Python:

from anylogiccloudclient.client.cloud_client import CloudClient

client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
model = client.get_model_by_name("Service System Demo")
version = client.get_latest_model_version(model)
inputs = client.create_default_inputs(version)
inputs.set_input("Server capacity", 8)
simulation = client.create_simulation(inputs)
outputs = simulation.get_outputs()

print("Mean queue size: " + str(outputs.value("Mean queue size|Mean queue size")))
                        

We use the set_input() function to change the value of the “Server capacity” parameter to 8. Having constructed the inputs and the simulation objects, we call simulation.get_outputs(). If the outputs exist, they are returned. If there are no outputs, an error occurs.

Java

The key function used here is ModelRun.getOutputs().

Java:

                        
package com.anylogic.cloud.java_api_example;

import com.anylogic.cloud.clients.client_8_5_0.*;
import com.anylogic.cloud.service.open_8_5_0.api.project.*;

public class Example {
    private static final String API_KEY = "4b7494a6-8c4e-4fb2-b4a8-9d829dcbb7a6";
    private static final String MODEL_ID = "a56057c6-b937-4539-8bdc-ab4e5f8fe86a";
    private static final String DOUBLE_INPUT = "Server capacity";
    private static final String DOUBLE_OUTPUT = "Average performance";

    public static void main(String[] args) {
        singleSimulationRun();
    }

    private static void singleSimulationRunGetResultsOfCompletedRun() {
        System.out.println("Getting results of already completed run with Server capacity = 20.0");
        AnyLogicCloudClient client = new AnyLogicCloudClient(API_KEY);
        Model model = client.getModelById(MODEL_ID);
        ModelVersion version = client.getLatestModelVersion(model);
        Inputs inputs = client.createDefaultInputs(version);
        inputs.setInput(DOUBLE_INPUT, 20.0);
        SimulationRun simulation = client.createSimulation(inputs);
        SingleRunOutputs outputs = simulation.getOutputs(); 
        System.out.println(outputs.value(DOUBLE_OUTPUT));
    }
}
                        
                    

The Example class contains multiple values that will be used for input.

We use the setInput() function to change the value of the “Server capacity” parameter to 20.0. Having constructed the inputs and the simulation objects, we call simulation.getOutputs(). If the outputs exist, they are returned. If there are no outputs, an error occurs.

3.3 Simulation run with progress polling

In case simulation is run without animation it makes sense to have some progress indication.

Javascript

In this example we use the function ModelRun.getProgress() to obtain the progress of the running simulation. We also show a different way of running the simulation and getting results via the sequence of run(), waitForCompletion(), and getOutputs() function calls.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Simulation with Progress indication</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button" onclick="runSimulation()">Run simulation</button>
    <progress id="progress" value="0" max="100"></progress>
    <div id="info">The simulation results will be displayed here</div>
</body>
</html>    

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let runButton;
let progress;
let info;
let simulation;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    progress = document.getElementById( "progress" );
    info = document.getElementById( "info" );
};

function runSimulation() {
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Service System Demo" )
        .then( version => {
            let inputs = cloudClient.createDefaultInputs( version );
            inputs.setInput( "Server capacity", 21 );
            inputs.setInput( "{STOP_TIME}", 10000000 );
            simulation = cloudClient.createSimulation(inputs);
            startPolling();
            return simulation.run();
        })
        .then( simulation => simulation.waitForCompletion() )
        .then( simulation => simulation.getOutputs() )
        .then( outputs => {
            let html = "Mean queue size = " + outputs.value( "Mean queue size|Mean queue size" ) + "<br>";
            html += "Server utilization = " + outputs.value( "Utilization|Server utilization" ) + "<br>";
            info.innerHTML = html;
        })
        .catch( error => {
            info.innerHTML = error.status + "<br>" + error.message;
            console.error( error );
        })
        .finally( () => {
            stopPolling();
            runButton.disabled = false;
        });
}

let pollingInterval;

function startPolling() {
    pollingInterval = setInterval(
        () => {
            simulation.getProgress()
                .then( progressinfo => {
                    if( progressinfo ) { //can be undefined in the beginning
                        progress.value = progressinfo.total;
                    }
                });
        },
        1000
    );
}

function stopPolling() {
    setTimeout( () => clearInterval( pollingInterval ), 2000 );
}

Try now

During the standard construction of the inputs, we change the “system” input {STOP_TIME} to a bigger value to make the simulation run longer, so we can really see the progress bar moving. Such input exists in every model uploaded to Cloud. However, if a run with the same stop time and other inputs has been performed already, the simulation won’t run, and the outputs will be delivered almost instantly. So, to watch the progress moving, consider setting other values for the inputs.

The function startPolling() is called just before simulation.run(), and initiates a repeated call of simulation.getProgress() with one second interval. The function getProgress() returns information about the progress by Promise. For a simple simulation run, we are only interested in the total field. For multi-run experiments it contains more details. Please note that the result may also be an empty object if we poll too soon (while the run has not yet been created on the server), therefore, we need to check the existence of the polling result. The function stopPolling() is called once the simulation results have been delivered (or an error occurs). It clears the one second interval but waits for additional two seconds to make sure that the final progress value has been received.

The call of simulation.run() initiates the simulation run (only if such run has not been done before) and returns the same simulation object by Promise. It does not wait for the simulation to complete. To wait for the experiment to complete, we use the function simulation.waitForCompletion(), which also returns the same object. It is only now that we query the simulation results by calling simulation.getOutputs(). This sequence is here solely for demo purposes; it could be replaced by a single call of simulation.getOutputsAndRunIfAbsent().

Python

In this example we use the function ModelRun.get_progress() to obtain the progress of the running simulation. We also show a different way of running the simulation and getting results via the sequence of run(), wait_for_completion(), and get_outputs() function calls.

Python:

import threading
import time

from anylogiccloudclient.client.cloud_client import CloudClient


def _update_progress(s):
    while s.get_status() == "FRESH" or s.get_status() == "RUNNING":
        print("Progress: " + str(s.get_progress()["total"]) + "%")
        time.sleep(5)


client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
version = client.get_latest_model_version("Service System Demo")
inputs = client.create_default_inputs(version)
inputs.set_input("Server capacity", 21)
inputs.set_input("{STOP_TIME}", 10000000)
simulation = client.create_simulation(inputs)

simulation.run()

progress_thread = threading.Thread(target=_update_progress, args=(simulation,))
progress_thread.start()

simulation.wait_for_completion()
outputs = simulation.get_outputs()

print("Mean queue size: " + str(outputs.value("Mean queue size|Mean queue size")))

During the standard construction of the inputs, we change the “system” input {STOP_TIME} to a bigger value to be able to observe the actual progress by making the simulation run longer. Such input exists in every model uploaded to Cloud. However, if a run with the same stop time and other inputs has been performed already, the simulation won’t run, and the outputs will be delivered almost instantly. So, to watch the progress moving, consider setting other values for the inputs.

We use the progress_thread.start() function, which is called after simulation.run(). It initiates a repeated call of s.get_progress(), which returns information about the progress. For a simple simulation run, we are only interested in the total field. For multi-run experiments it contains more details. The function time.sleep() is called once the simulation is completed. It waits for additional 5 seconds to make sure that the final progress value has been received.

The call of simulation.run() initiates the simulation run (only if such run has not been done before) and returns the same simulation object. It does not wait for the simulation to complete. To wait for the experiment to complete, we use the function simulation.wait_for_completion(), which also returns the same object. It is only now that we query the simulation results by calling simulation.get_outputs(). This sequence is here solely for demo purposes; it could be replaced by a single call of simulation.get_outputs_and_run_if_absent().

Java

An ability to track the running simulations via the Java client is coming soon.

3.4 Running a custom workflow – a mix of parallel and sequential simulations

Now, let’s implement a custom workflow where some simulations are run in parallel and some – sequentially, based on the results of other simulations. This scenario may be useful for those who want to set up e.g. a custom optimization algorithm in AnyLogic Cloud.

Javascript

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Custom workflow</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button"
onclick="runSimulations()">Run 2+1 simulations</button>
    <div id="info">The simulation results will be displayed here</div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let version;
let runButton;
let info;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    info = document.getElementById( "info" );
};

let sc1 = 4;
let sc2 = 9;
let sc3;

function runSimulations() {
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Service System Demo" )
        .then( v => {
            version = v;
            //create two inputs instances with different parameter values
            let inputs1 = cloudClient.createDefaultInputs( version );
            let inputs2 = cloudClient.createDefaultInputs( version );
            inputs1.setInput( "Server capacity", sc1 );
            inputs2.setInput( "Server capacity", sc2 );
            //create two simulation objects with different inputs
            let simulation1 = cloudClient.createSimulation( inputs1 );
            let simulation2 = cloudClient.createSimulation( inputs2 );
            info.innerHTML = "Running two parallel simulations...<br>";
            //run the two simulations in parallel, wait for both results
            return Promise.all( [simulation1.getOutputsAndRunIfAbsent(), simulation2.getOutputsAndRunIfAbsent()] );
        })
        .then( outputarray => {
            //both outputs are here
            let su1 = outputarray[0].value( "Utilization|Server utilization" );
            let su2 = outputarray[1].value( "Utilization|Server utilization" );
            let html = "Two parallel simulations completed.<br>";
            html += "With " + sc1 + " servers, Server utilization = " + su1 + "<br>";
            html += "With " + sc2 + " servers, Server utilization = " + su2 + "<br>";
            //based on the results, set up the inputs for the third simulation
            sc3 = (su1 + su2) > 0.4 ? sc2-1 : sc1+1;
            let inputs3 = cloudClient.createDefaultInputs( version );
            inputs3.setInput( "Server capacity", sc3 );
            let simulation3 = cloudClient.createSimulation( inputs3 );
            html += "Running third simulation with " + sc3 + " servers...<br>";
            info.innerHTML += html
            return simulation3.getOutputsAndRunIfAbsent();
        })
        .then( outputs3 => {
            let su3 = outputs3.value( "Utilization|Server utilization" );
            let html = "Third simulation completed.<br>";
            html += "With " + sc3 + " servers, Server utilization = " + su3 + "<br>";
            info.innerHTML += html
        })
        .catch( error => {
            info.innerHTML = error.status + "<br>" + error.message;
            console.error( error );
        })
        .finally( () => {
            runButton.disabled = false;
        });
}

Try now

In this scenario, we first perform two simulation runs in parallel with the Server Capacity parameter set to 4 in one run and 9 in another. The two runs are initiated by calling simulation1.getOutputsAndRunIfAbsent() and simulation2.getOutputsAndRunIfAbsent(). The function getOutputsAndRunIfAbsent() (as actually all functions in AnyLogic Cloud JavaScript API that involve communication with the server) is asynchronous – it immediately returns a Promise, and then we need to provide the handler in the then block. In this case we have two Promise objects from the two runs – and we need to wait for both to complete. This is accomplished by using the Promise.all() function returning a single Promise, which resolves after all the promises (passed as an iterable array in our case) have resolved. The outputs of simulation runs performed in parallel are returned also as an array in the same order. In the then block that follows we analyze the values of Server Utilization in both runs and set up the input of the third simulation run based on those values.

Please note that, when you run multiple simulations in parallel manually, like in this example, each call of ModelRun.getOutputsAndRunIfAbsent() or ModelRun.waitForCompletion() performs its own independent polling, therefore many parallel runs may result in high HTTP traffic. If that is suspected, consider changing the optional parameter pollingPeriod of these functions.

Python

Python:

from anylogiccloudclient.client.cloud_client import CloudClient

capacities = [4, 9]
client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
version = client.get_latest_model_version("Service System Demo")

inputs = [client.create_default_inputs(version) for num in range(2)]
[inputs[num].set_input("Server capacity", capacities[num]) for num in range(2)]

simulations = [client.create_simulation(i) for i in inputs]
[s.run() for s in simulations]
[s.wait_for_completion() for s in simulations]

outputs = [s.get_outputs() for s in simulations]
for o in outputs:
    print("Mean queue size: " + str(o.value("Mean queue size|Mean queue size")))

In this scenario, we first perform two simulation runs in parallel with the Server Capacity parameter set to 4 in one run and 9 in another by the range() function. The two runs are initiated by calling s.run().

The outputs of simulation runs performed in parallel are returned also as an array in the same order.

Please note that, when you run multiple simulations in parallel manually, like in this example, each call of s.wait_for_completion() performs its own independent polling, therefore many parallel runs may result in high HTTP traffic. If that is suspected, consider changing the optional parameter polling_period of these functions.

Java

Will be added soon.

3.5 Running parameter variation

In this example, we will run a parameter variation experiment. One of the input parameters will be varied in range. To demonstrate one more feature of the AnyLogic Cloud API, we will take the input values from an existing simulation experiment defined in the standard AnyLogic Cloud web interface and change a parameter value from a scalar to a range.

Javascript

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Parallel Simulations</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button" onclick="runVariation()">Run variation</button>
    <div id="info">The parameter variation results will be displayed here</div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let runButton;
let info;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    info = document.getElementById( "info" );
};

function runVariation() {
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Service System Demo" )
        .then( version => {
            return cloudClient.createInputsFromExperiment( version, "Baseline" );
        })
        .then( inputs => {
            inputs.setRangeInput( "Mean service time", 1.8, 2, 0.1 );
            let variation = cloudClient.createParameterVariation( inputs );
            info.innerHTML = "Running parameter variation...<br>";
            return variation.getOutputsAndRunIfAbsent( ["Total time in system|Total time in system"] );
        })
        .then( outputs => {
            let html = "Parameter variation completed.<br>";
            let invalues = outputs.getValuesOfInput("Mean service time");
            let outvalues = outputs.getValuesOfOutput("Total time in system|Total time in system");
            for( let i=0; i<invalues.length; i++ ) {
                html += "When Mean service time = " + invalues[i] +
                        ", mean Total time in system = " + outvalues[i].statistics.mean + "<br>"
            }
            info.innerHTML += html
        })
        .catch( error => {
            info.innerHTML = error.status + "<br>" + error.message;
            console.error( error );
        })
        .finally( () => {
            runButton.disabled = false;
        });
}

Try now

To reuse the set of inputs from an experiment defined in the AnyLogic Cloud web interface we use the function CloudClient.createInputsFromExperiment() instead of createDefaultInputs(). Having copied the inputs of the "Baseline" experiment,  we change the input "Mean service time" to a range type (from 1.8 to 2.0 with step 0.1) by calling Inputs.setRangeInput(). Therefore three simulation runs are to be performed.

Then we need to create a ModelRun object of parameter variation type, which is done by the CloudClient.createParameterVariation() function.

The run of parameter variation is invoked by calling the getOutputsAndRunIfAbsent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to getOutputsAndRunIfAbsent() or getOutputs() as a parameter. In this example, we are interested in the "Total time in system|Total time in system" output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.  In this simple example we get array of the input values and the corresponding array of the output values, and display them.

Python

Python:

from anylogiccloudclient.client.cloud_client import CloudClient

client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
version = client.get_latest_model_version("Service System Demo")
inputs = client.create_inputs_from_experiment(version, "Baseline")
inputs.set_range_input("Mean service time", 1.8, 2, 0.1)
variation = client.create_parameter_variation(inputs)
outputs = variation.get_outputs_and_run_if_absent()

print("Mean queue size: " + str(outputs.get_values_of_output("Mean queue size|Mean queue size")))

To reuse the set of inputs from an experiment defined in the AnyLogic Cloud web interface we use the function CloudClient.create_inputs_from_experiment() instead of create_default_inputs(). Having copied the inputs of the "Baseline" experiment,  we change the input "Mean service time" to a range type (from 1.8 to 2.0 with step 0.1) by calling Inputs.set_range_input(). Therefore, three simulation runs are to be performed.

Then we need to create a ModelRun object of parameter variation type, which is done by the CloudClient.create_parameter_variation() function.

The run of parameter variation is invoked by calling the get_outputs_and_run_if_absent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to get_outputs_and_run_if_absent() or get_outputs() as a parameter. In this example, we are interested in the "Mean queue size|Mean queue size" output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.

Java

Java:

                        
package com.anylogic.cloud.java_api_example;

import com.anylogic.cloud.clients.client_8_5_0.*;
import com.anylogic.cloud.service.open_8_5_0.api.project.*;

import java.util.Arrays;

public class Example {
    private static final String API_KEY = "4b7494a6-8c4e-4fb2-b4a8-9d829dcbb7a6";
    private static final String MODEL_ID = "a56057c6-b937-4539-8bdc-ab4e5f8fe86a";
    private static final String DOUBLE_INPUT = "Server capacity";
    private static final String DOUBLE_OUTPUT = "Average performance";

    public static void main(String[] args) {
        singleSimulationRun();
    }

    private static void parameterVariation() {
        System.out.println( "A parameter variation run with Double input varied from 20.0 to 180.0 with step 20.0" );
        AnyLogicCloudClient client = new AnyLogicCloudClient(API_KEY);
        Model model = client.getModelById(MODEL_ID);
        ModelVersion version = client.getLatestModelVersion(model);
        Inputs inputs = client.createDefaultInputs(version);
        inputs.setRangeInput(DOUBLE_INPUT, 20.0, 180.0, 20.0);
        ParameterVariationRun variation = client.createParameterVariation(inputs);
        MultiRunOutputs outputs = variation.getOutputsAndRunIfAbsent(Arrays.asList(DOUBLE_OUTPUT)); // will exit upon run completion
        System.out.println(outputs.getValuesOfOutput(DOUBLE_OUTPUT));
    }
}
                        
                    

The Example class contains multiple values that will be used for input.

Here, we use the Inputs.setRangeInput() function to change the value of the “Server capacity” input to a range type, from 20.0 to 180.0 with step 20.0. Therefore, nine simulation runs are to be performed.

Then we need to create a ModelRun object of the parameter variation type, which is done by the AnyLogicCloudClient.createParameterVariation() function.

The run of parameter variation is invoked by calling the getOutputsAndRunIfAbsent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to getOutputsAndRunIfAbsent() or getOutputs() as a parameter. In this example, we are interested in the “Average performance” output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.

3.6 Running parameter variation with replications

In this example, we will run a parameter variation experiment with the explicitly set number of replications. One of the input parameters will be varied in range. We will also use the input values from an existing simulation experiment defined in the standard AnyLogic Cloud web interface.

Python

Python:

from anylogiccloudclient.client.cloud_client import CloudClient

client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
version = client.get_latest_model_version("Service System Demo")
inputs = client.create_inputs_from_experiment(version, "Baseline")
inputs.set_range_input("Mean service time", 1.8, 2, 0.1)
inputs.set_number_of_replications(4)

variation_with_replications = client.create_parameter_variation_with_replications(inputs)
outputs = variation_with_replications.get_outputs_and_run_if_absent(["Total time in system|Total time in system"])

print("Parameter variation with replications experiment completed")
invalues = outputs.get_values_of_input("Mean service time")
outvalues = outputs.get_values_of_output("Total time in system|Total time in system")
for i in range(len(invalues)):
    print("When Mean service time = " + str(invalues[i]) + ", mean Total time in system = " + str(outvalues[i]["statistics"]["mean"]))

As you can see, this experiment is basically identical to the one demonstrated in the parameter variation example. The main difference is that we use the set_number_of_replications() function to specify the number of replications explicitly.

Then we create a ModelRun object for the needed experiment type, which is done by the CloudClient.create_parameter_variation_with_replications() function.

The experiment run is triggered by calling the get_outputs_and_run_if_absent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to get_outputs_and_run_if_absent() or get_outputs() as a parameter. In this example, we are interested in the "Total time in system | Total time in system" output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.

Java

Java:

package com.anylogic.cloud.java_api_example;

import com.anylogic.cloud.clients.client_8_5_0.*;
import com.anylogic.cloud.service.open_8_5_0.api.project.*;

import java.util.Arrays;

public class Example {
    private static final String API_KEY = "4b7494a6-8c4e-4fb2-b4a8-9d829dcbb7a6";
    private static final String MODEL_ID = "a56057c6-b937-4539-8bdc-ab4e5f8fe86a";
    private static final String DOUBLE_INPUT = "Server capacity";
    private static final String DOUBLE_OUTPUT = "Average performance";

    public static void main(String[] args) {
        parameterVariationWithReplications();
    }

    private static void parameterVariationWithReplications() {
        System.out.println( "A parameter variation with replications run with Double input varied from 20.0 to 180.0 with step 20.0, 4 replications" );
        AnyLogicCloudClient client = new AnyLogicCloudClient(API_KEY, HOST);
        Model model = client.getModelById(MODEL_ID);
        ModelVersion version = client.getLatestModelVersion(model);
        Inputs inputs = client.createDefaultInputs(version);
        inputs.setRangeInput(DOUBLE_INPUT, 20.0, 180.0, 20.0);
        inputs.setNumberOfReplications(4);
        ParameterVariationRun variation = client.createParameterVariationWithReplications(inputs);
        MultiRunOutputs outputs = variation.getOutputsAndRunIfAbsent(Arrays.asList(DOUBLE_OUTPUT)); // will exit upon run completion
        System.out.println(outputs.getValuesOfOutput(DOUBLE_OUTPUT));
    }
}

The Example class contains multiple values that will be used for input.

Here, we use the Inputs.setNumberofReplications() function to specify the number of replications to be run.

Then we create a ModelRun object for the needed experiment type, which is done by the AnyLogicCloudClient.createParameterVariationWithReplications() function.

The experiment run is triggered by calling the getOutputsAndRunIfAbsent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to getOutputsAndRunIfAbsent() or getOutputs() as a parameter. In this example, we are interested in the "Average performance" output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi-run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.

3.7 Running Monte Carlo 1st order

In this example, we will run a Monte Carlo 1st order experiment with the explicitly set number of replications. When executed via the API, the Monte Carlo experiment runs the simulation a specified number of times, obtains the collections of values, and then returns them.

One of the input parameters will be varied in range. We will also use the input values from an existing simulation experiment defined in the standard AnyLogic Cloud web interface.

Python

Python:

from anylogiccloudclient.client.cloud_client import CloudClient
        
client = CloudClient("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20")
version = client.get_latest_model_version("Service System Demo")
inputs = client.create_inputs_from_experiment(version, "Baseline")
inputs.set_number_of_replications(4)
monte_carlo = client.create_monte_carlo(inputs)
outputs = monte_carlo.get_outputs_and_run_if_absent(["Total time in system|Total time in system"])
        
print("Monte Carlo 1st order experiment completed")
invalues = outputs.get_values_of_input("Mean service time")
outvalues = outputs.get_values_of_output("Total time in system|Total time in system")
for i in range(len(invalues)):
    print("When Mean service time = " + str(invalues[i]) + ", mean Total time in system = " + str(outvalues[i]["statistics"]["mean"]))

We reuse the set of inputs from the experiment already defined in the AnyLogic CLoud GUI with the create_inputs_from_experiment() function. The number of replications is set with the set_number_of_replications() function.

Then we create a ModelRun object for the needed experiment type, which is done by the CloudClient.create_monte_carlo() function.

The experiment run is triggered by calling the get_outputs_and_run_if_absent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to get_outputs_and_run_if_absent() or get_outputs() as a parameter. In this example, we are interested in the "Total time in system | Total time in system" output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.

Java

Java:

package com.anylogic.cloud.java_api_example;

import com.anylogic.cloud.clients.client_8_5_0.*;
import com.anylogic.cloud.service.open_8_5_0.api.project.*;

import java.util.Arrays;

public class Example {
    private static final String API_KEY = "4b7494a6-8c4e-4fb2-b4a8-9d829dcbb7a6";
    private static final String MODEL_ID = "a56057c6-b937-4539-8bdc-ab4e5f8fe86a";
    private static final String DOUBLE_INPUT = "Server capacity";
    private static final String DOUBLE_OUTPUT = "Average performance";

    public static void main(String[] args) {
        monteCarloFirstOrder();
    }

    private static void monteCarloFirstOrder() {
        System.out.println( "A Monte-Carlo 1st order run with 4 replications" );
        AnyLogicCloudClient client = new AnyLogicCloudClient(API_KEY, HOST);
        Model model = client.getModelById(MODEL_ID);
        ModelVersion version = client.getLatestModelVersion(model);
        Inputs inputs = client.createDefaultInputs(version);
        inputs.setNumberOfReplications(4);
        MonteCarloFirstOrderRun monteCarlo = client.createMonteCarloFirstOrder(inputs);
        MultiRunOutputs outputs = monteCarlo.getOutputsAndRunIfAbsent(Arrays.asList(DOUBLE_OUTPUT)); // will exit upon run completion
        System.out.println(outputs.getValuesOfOutput(DOUBLE_OUTPUT));
    }
}

The Example class contains multiple values that will be used for input.

The Inputs.setNumberofReplications() function specifies the number of replications to be run.

Then we create a ModelRun object for the needed experiment type, which is done by the AnyLogicCloudClient.createMonteCarloFirstOrder() function.

The experiment run is triggered by calling the getOutputsAndRunIfAbsent() function just like in our previous examples, but there is one important difference. Full outputs of a multiple run experiment may be a very large piece of data, so the API user has to explicitly specify which outputs need to be delivered. This is done by listing the output names in the array passed to getOutputsAndRunIfAbsent() or getOutputs() as a parameter. In this example, we are interested in the "Average performance" output. If the parameter is omitted for a multi run experiment, only scalar outputs will be returned, if any.

Outputs of a multi-run experiment are returned as a MultiRunOutputs object, which has a number of functions simplifying navigation.

3.8 Simulation run with animation (minimalistic)

The minimalistic example of embedding the animation of a cloud-based model into a web page would look like the following.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Run animation. Minimalistic</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button" onclick="runAnimation()">Run animation</button>
    <div id="animation-container" style="width: 1200px; height: 700px; border: 1px solid blue;">
    </div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

function runAnimation() {
    runButton = document.getElementById( "run-button" );
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Bass Diffusion Demo 8.5.0" )
        .then( version => {
            let inputs = cloudClient.createDefaultInputs( version );
            inputs.setInput( "Contact Rate", 30 );
            return cloudClient.startAnimation( inputs, "animation-container" );
        })
        .then( animation => {
            return animation.waitForCompletion();
        })
        .catch( error => {
            console.error( error );
        })
        .finally( () => {
            runButton.disabled = false;
        });
}

Try now

Within the HTML code you should create the animation placeholder. In this example it is the initially empty 1200x700 <div> element, with the "animation-container" id. Then, when the user presses the Run animation button, the function runAnimation() is called. It disables the button, searches for the latest version of the model, creates a default input set, and changes one of the input values. The call of cloudClient.startAnimation() launches the model, connects the model to the frontend, and starts streaming animation into the provided container. That call completes as the HTTP request completes and returns the Animation object by Promise. Then we use animation.waitForCompletion() to wait for the user to press Stop. Please note that even if the animated simulation finishes (e.g. reaches its stop time), it is not considered as stopped until either of the following:

  • The user presses the Stop button on the animation control panel
  • The server decides to stop it for any reason

The finally block is then executed and re-enables the Run button.

3.9 Animated run with external pause and resume buttons and state polling

This example is a bit more sophisticated than the previous one: we will add buttons to pause and resume the simulation. The key functions of the Animation object used here are pause(), resume(), and getState().

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Animation. Pause Resume</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button" onclick="runAnimation()">Run animation</button>
    <button id="pause-button" onclick="pauseAnimation()" disabled>Pause</button>
    <button id="resume-button" onclick="resumeAnimation()" disabled>Resume</button>
    <div id="animation-container" style="width: 1200px; height: 700px; border: 1px solid blue;">
    </div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let runButton;
let pauseButton;
let resumeButton;
let animation;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    pauseButton = document.getElementById( "pause-button" );
    resumeButton = document.getElementById( "resume-button" );
};

function runAnimation() {
    runButton.disabled = true;
    cloudClient.getModelByName( "Bass Diffusion Demo 8.5.0" )
        .then( model => cloudClient.getLatestModelVersion( model ) )
        .then( version => {
            let inputs = cloudClient.createDefaultInputs( version );
            inputs.setInput( "Contact Rate", 40 );
            return cloudClient.startAnimation( inputs, "animation-container" );
        })
        .then( a => {
            animation = a;
            startPolling();
            return animation.waitForCompletion();
        })
        .catch( error => {
            console.error( error );
        })
        .finally( () => {
            stopPolling();
            runButton.disabled = false;
            pauseButton.disabled = true;
            resumeButton.disabled = true;
        });
}

function pauseAnimation() {
    pauseButton.disabled = true;
    animation.pause();
}

function resumeAnimation() {
    resumeButton.disabled = true;
    animation.resume();
}

let pollingInterval;

function startPolling() {
    pollingInterval = setInterval(
        () => {
            animation.getState()
                .then( state => {
                    pauseButton.disabled = state != "RUNNING";
                    resumeButton.disabled = state != "PAUSED";
                });
        },
        500
    );
}

function stopPolling() {
    clearInterval( pollingInterval );
}

Try now

In the HTML code, there are two new buttons above the animation container that are initially disabled. In JavaScript, we remember these elements as the page gets loaded. We also remember the Animation object returned by cloudClient.startAnimation() by Promise. The actions assigned to the buttons simply call pause() and resume() of that object. What is more interesting, is the animation state polling. Once the animation starts, we begin to poll its state every 0.5 second, see the function startPolling(). A call of getState() returns the animation state by Promise, and we use it to enable or disable the buttons. The polling is stopped once the model is stopped or an error occurs, see the finally block.

Please note that, in animated run, the inputs are not validated until they are passed to the model. Therefore, if there is an error in the input values (such as a type error), the model will fail to start and you will see an error message within the animation window, but the catch block won’t be reached.

Also, in this example we show a different, more general, way of getting to the latest version of the model: first, we get the Model object by its name, then we ask for the latest version of the model.

3.10 Animated run with external control of a model parameter

In this example we will show how to control a model input parameter while the model is running using the AnyLogic Cloud API and how to call a function defined in the model. We will run the model with the default input parameter value and provide external HTML controls to change it. The key functions used here are setValue() and callFunction().

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Animation. Parameter Control</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.js"></script>
</head>
<body>
    <button id="run-button" onclick="runAnimation()">Run animation</button>
    <input id="parameter-range" onchange="changeParameter()" type="range" min="0" max="100" disabled>
    <button id="reset-button" onclick="resetParameter()" disabled>Reset parameter</button>
    <div id="animation-container" style="width: 1200px; height: 700px; border: 1px solid blue;">
    </div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let runButton;
let parameterRange;
let resetButton;
let animation;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    parameterRange = document.getElementById( "parameter-range" );
    resetButton = document.getElementById( "reset-button" );
};

function runAnimation() {
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Bass Diffusion Demo 8.5.0" )
        .then( version => {
            let inputs = cloudClient.createDefaultInputs( version );
            return cloudClient.startAnimation( inputs, "animation-container" );
        })
        .then( a => {
            animation = a;
            parameterRange.disabled = false;
            resetButton.disabled = false;
            return animation.waitForCompletion();
        })
        .catch( error => {
            console.error( error );
        })
        .finally( () => {
            runButton.disabled = false;
            parameterRange.disabled = true;
            resetButton.disabled = true;
        });
}

function changeParameter() {
    animation.setValue( "experiment.root.ContactRate", parseFloat( parameterRange.value ) );
}

function resetParameter() {
    parameterRange.value = 30;
    animation.callFunction( "experiment.root.set_ContactRate", [30] );
}

Try now

In the HTML code, there is a slider and a button; initially these controls are disabled.

The function changeParameter() uses the AnyLogic Cloud API function setValue(), the first parameter of which is the path to the object whose value we wish to set. The path should always start with the word "experiment" that is followed by "root" in most cases: " experiment.root" takes you to the root agent of the model, typically this is the (only) instance of the class Main. As our Contact Rate parameter is located in Main, the full path to it is "experiment.root.ContactRate". Please note that we are using the “original” Java name of the parameter here and not its UI label “Contact Rate”! Also, as the parameter is numeric, we need to convert parameterRange.value, which is a string, to a float number.

Similarly, the resetParameter() function uses the API function callFunction() to force the value of Contact Rate to 30. It is done by invoking the function set_ContactRate() defined in the model class Main (in this case, the function was auto-generated by AnyLogic, but it could be a user-defined function). The path to the function is obviously "experiment.root.set_ContactRate" and the arguments of the function call must be passed as a JavaScript array. In our case there is only one parameter – the new value 30. The functions defined in the model by the user are called in exactly same way.

3.11 Retrieving information from a running animated model

In this example, we will retrieve information from a running model using the getValue() function of the Animation object.

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>AnyLogic Cloud API Example - Animation. Get data</title>
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
    <script src="js/main.get_data.js"></script>
</head>
<body>
    <button id="run-button" onclick="runAnimation()">Run animation</button>
    <button id="get-scalar-button" onclick="getScalarValue()" disabled>Get scalar value</button>
    <button id="get-dataset-button" onclick="getDataSet()" disabled>Get dataset</button>
    <div id="info">The data retrieved from the model will be displayed here</div>
    <div id="animation-container" style="width: 1200px; height: 700px; border: 1px solid blue;">
    </div>
</body>
</html>

JavaScript:

let cloudClient = create("e05a6efa-ea5f-4adf-b090-ae0ca7d16c20");

let runButton;
let getScalarButton;
let getDataSetButton;
let info;
let animation;

window.onload = () => {
    runButton = document.getElementById( "run-button" );
    getScalarButton = document.getElementById( "get-scalar-button" );
    getDataSetButton = document.getElementById( "get-dataset-button" );
    info = document.getElementById( "info" );
};

function runAnimation() {
    runButton.disabled = true;
    cloudClient.getLatestModelVersion( "Bass Diffusion Demo 8.5.0" )
        .then( version => {
            let inputs = cloudClient.createDefaultInputs( version );
            return cloudClient.startAnimation( inputs, "animation-container" );
        })
        .then( a => {
            animation = a;
            getScalarButton.disabled = false;
            getDataSetButton.disabled = false;
            return animation.waitForCompletion();
        })
        .catch( error => {
            info.innerText = error.message;
            console.error( error );
        })
        .finally( () => {
            runButton.disabled = false;
            getScalarButton.disabled = true;
            getDataSetButton.disabled = true;
        });
}

function getScalarValue() {
    let value = animation.getValue( "experiment.root.Adopters" )
        .then( value => {
            info.innerText = "Adopters = " + value;
        });
}

function getDataSet() {
    let value = animation.getValue( "experiment.root._ds_Adopters" )
        .then( value => {
            info.innerText = "Adopters over time: time=[" + value.dataX + "] Adopters=[" + value.dataY + "]";
        });
}

Try now

In the HTML code there are two buttons: one for querying a scalar value, and another for querying a dataset (both buttons are initially disabled), and a <div> element to display the obtained information.

The first parameter of getValue() is the full path to the object being accessed, which starts with “experiment.root” (just like in setValue() and callFunction() in the previous example). The scalar value is the System Dynamics variable Adopters, and the dataset is the one automatically created for the same variable (in AnyLogic such datasets are auto-generated and have prefix “_ds_”; in case you have a user-defined dataset, you should obviously use that dataset’s name).

The structure of the object returned by getValue() depends on its type. For primitive types it is quite straightforward, for complex types please consult the Data conversion section to understand the Java -> JSON conversion rules. In this example, the AnyLogic DataSet Java object is converted into a JSON object with dataX and dataY fields. Should we have a custom chart (like Plotly or Tableau chart) as a part of our frontend, we could feed that data into the chart to visualize it, possibly with live updates of certain frequency.

4 JavaScript API

4.1 Obtaining the JavaScript client

JavaScript API is used to build custom web interfaces for cloud-based AnyLogic models with or without animation. To start using the API, follow these steps:

  1. Obtain the cloud_client library by adding the <script> tag to the head of your webpage:
    <script src="https://cloud.anylogic.com/assets/js-client-8.5.0/cloud-client.js"></script>
  2. Obtain the API key in the AnyLogic Cloud web UI.
  3. Create a new instance of the CloudClient object
    cloudClient = CloudClient.create( <apiKey> ) if you are using the public AnyLogic Cloud, or
    cloudClient = CloudClient.create( <apiKey>, <URL of the Cloud instance> );
  4. Use the API to work with the cloud-based models.

The index.html and main.js files contain a simple example of the API usage and may be useful to look at.

Please keep in mind that:

  • AnyLogic Cloud JavaScript API is fully asynchronous and extensively uses the Promise technology
  • Your IDE compiler settings should allow ECMAScript 6 JavaScript version

4.2 JavaScript API reference

AnyLogic JavaScript API is purely asynchronous (see Synchronous and asynchronous API), therefore it makes sense to familiarize yourself with JavaScript Promise technology.

Another thing to keep in mind is that the API treats names (e.g. model, experiment, input, and output names) as case-insensitive.

CloudClient class

The CloudClient class is responsible for authentication and communication with the AnyLogic Cloud. Typically, there is only one object of class CloudClient in your JavaScript code.

static create(apiKey, host) - a static function that creates the API client with the given API key, and optionally the host name. If the host is omitted, the public cloud host name https://cloud.anylogic.com is assumed.

getModels() - returns available models as an array of Model objects by Promise.

getModelById(id) - returns the Model object with a given id by Promise.

getModelByName(name) - returns the Model object with a given name by Promise.

getModelVersionById(model, versionId) - returns the Version object of a given Model with a given id by Promise.

getModelVersionByNumber(model, versionNumber) - returns the Version object of a given Model with a given number by Promise (version numbering starts with 1).

getLatestModelVersion(modelorname) - returns the latest Version object of a given model (which can be either a Model, or a model name) by Promise.

createDefaultInputs(version) - creates and returns an Inputs object for a given model Version with default input values.

createInputsFromExperiment(version, experimentName) - creates and returns by Promise the Inputs object for a given model Version object copied from the experiment with the given name.

createSimulation(inputs) - creates and returns a ModelRun object of type SIMULATION with the given Inputs (the model and the version are identified by the inputs).

createParameterVariation(inputs) - creates and returns a ModelRun object of type PARAMETER_VARIATION with the given Inputs (the model and the version are identified by the inputs).

startAnimation(inputs, divId) - starts an animated model run with the given Inputs (which fully identify the model and the model version), and embeds the animation into the HTML element with the given id. Constructs and returns the corresponding Animation object by Promise.

Inputs class

An object of Inputs class is constructed in preparation of a model run (of any kind) by calling the CloudClient functions createDefaultInputs() or createInputsFromExperiment() and contains full information about the model, model version, and the input values. It should not be confused with the inputs field in the Version object.

getInput(name) - returns the value (an object) of the input with a given name. See Data conversion section for possible types.

setInput(name, value) - sets the value of the input with a given name.

setRangeInput(name, min, max, step) - sets a range for the input with a given name (in a parameter variation experiment).

Inputs of distribution type (for Monte Carlo 2nd order experiments) are coming in future releases of AnyLogic Cloud API.

SingleRunOutputs class

An object of this class is returned after a call of getOutputs() or getOutputsAndRunIfAbsent() of a ModelRun constructed for a single run simulation experiment.

names() - returns the array with all output names.

findNameIncluding( namePart ) - searches for an output name that has namePart as a substring and returns it. If there is no such name or more than one such name is found, throws Error. This function is useful because full names of the outputs may be complex, see Outputs data object.

value( name ) - returns the value of the output with a given name. The type of value depends on the output, see Data conversion section.

getRawOutputs() - returns an array of all output items, each item has fields name, type, units, and value. For possible values of type and units field see Output types and Units sections correspondingly. The value field contains an object constructed as described in Data conversion section. This is an example of raw outputs:

[
    {
        name: "Queue size stats",
        type: "STATISTICS_CONTINUOUS",
        units: null,
        value: {
            count: 1255584,
            max: 7,
            mean: 0.9988466028875719,
            min: 0,
            totalTime: 999999.2699032243,
            type: "CONTINUOUS",
            variance: 0.0027334062484944965
        }
    },
    {
        name: "Total time in system|Total time in system",
        type: "HISTOGRAM_DATA",
        units: null,
        value: {
            hits: (20) [800912, 159870, 29594, 5804, 3399, 1073, 257, 56, 12, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            hitsOutHigh: 0,
            hitsOutLow: 0,
            intervalWidth: 1.6,
            lowerBound: 1.6,
            statistics:{
            count: 1000987,
                max: 18.533258249757637,
                mean: 2.5012383408878067,
                min: 1.6001570096705109,
                type: "DISCRETE",
                variance: 1.2835661096259896
            }
        }
    },
    {
        name: "Utilization|Server utilization",
        type: "DOUBLE",
        units: null,
        value: 0.31275860811685163,
    },
    {
        name: "Mean queue size|Mean queue size",
        type: "DOUBLE",
        units: null,
        value: 0.9988466025848514
    }
]

MultiRunOutputs class

An object of this class is returned after a call of getOutputs() or getOutputsAndRunIfAbsent() of a ModelRun constructed for a parameter variation or other multi run experiment. It simplifies navigation within the complex outputs structure. Keep in mind that you need to explicitly specify the required outputs when calling getOutputs() functions.

getInputNames() - returns the array of names of inputs that are varied across runs.

getOutputNames() - returns the array of names of requested outputs.

getValuesOfInput( name ) - returns the array of values of the input with a given name across all runs in some fixed sequence. Note that you can only query values of the varied inputs. The fixed inputs are not stored in MultiRunOutputs.

getValuesOfOutput( name ) - returns the array of values of the output with a given name across all runs in some fixed sequence. This function can be used together with getValuesOfInput().

getRawData() - returns a table (a two-dimensional array) with values of all variable inputs and all outputs with a header row. For example, here is the raw data of a parameter variation experiment with one variable parameter Mean service time and one scalar output Utilization|Server utilization :

[
    ["Mean service time", "Utilization|Server utilization"],
    [1.8, 0.5621987153519676],
    [1.9, 0.5939408971748594],
    [2, 0.6253419155200399]
]

ModelRun class

The ModelRun class is responsible for communication with and control of a model run (without animation) executed in Cloud. It can be considered as a frontend mirror of a backend experiment run. Objects of class ModelRun are created and returned by calling the functions createSimulation() or createParameterVariation() of the CloudClient. A ModelRun object contains full information about the model, version, inputs, and experiment type.

run() - requests to run the experiment. Whether or not the simulation will actually be executed depends on the availability of the outputs. The function returns the same ModelRun object by Promise once the HTTP request completes; it does not wait for simulation completion or outputs availability and does no polling.

stop() - requests to stop the model execution. Returns the same ModelRun object by Promise once the HTTP request completes.

waitForCompletion( pollingPeriod ) - waits for the experiment to complete and returns the same ModelRun object by Promise. The pollingPeriod parameter is optional, the default value is 5000ms.

getStatus() - returns the status of the model execution as last updated by polling (does not initiate any extra communication with the server). Possible values are the same as described in the Experiment Run State section.

getProgress() - returns the fully parsed message field of the Experiment Run State object by Promise. To find out total experiment progress use getProgress().then( progress => progress.total).

getOutputs( requiredOutputNames ) - if the run has already been completed, returns the run outputs (either SingleRunOutputs or MultiRunOutputs object) by Promise, otherwise throws 404 Error. requiredOutputNames is the array of output names that are to be returned. If requiredOutputNames is omitted, the behavior is different for single and multi-run experiments: for a single run, all outputs are returned, for a multi run only outputs of scalar types are returned.

getOutputsAndRunIfAbsent( requiredOutputNames, pollingPeriod ) - if the run has already been completed, returns the run outputs (either SingleRunOutputs or MultiRunOutputs object) by Promise, otherwise requests to run the experiment, waits for completion by polling, and then returns the outputs by Promise. requiredOutputNames has the same meaning as in getOutputs(). The pollingPeriod parameter is optional, the default value is 5000ms.

Animation class

The Animation class is responsible for communication with and control of an animated simulation run. Object of class Animation is created and returned by calling the functions startAnimation() of the CloudClient.

stop() - requests to stop the model execution. Does not return anything.

pause() - requests to pause the model execution. Returns the same Animation object by Promise.

resume() - requests to resume the (paused) model execution. Returns the same Animation object by Promise.

setSpeed(speed) - requests to set the execution speed of the model to a given value (model time units per real second). Returns the same Animation object by Promise.

setVirtualTime() - requests to switch to the virtual time (fastest possible) execution mode. Returns the same Animation object by Promise.

navigateTo(viewArea) - requests to navigate to a view area with the given name. Returns the same Animation object by Promise.

setPresentable(pathToPresentable) - requests to navigate to a given agent. The path should start with experiment.root followed by Java path to the agent (if that is not root). Returns the same Animation object by Promise.

setValue(pathToField, value) - requests to set the value of a given object in the model (e.g. a parameter or a variable). The path to the object should look like experiment.root.agent1.myParameter. Returns the same Animation object by Promise.

getValue(pathToField) - requests the value of a given object in the model and returns it by Promise. The path to the object should look like experiment.root.agent1.myParameter. The returned value is a JavaScript object, please see Data conversion section to learn how Java objects are mapped to JSON objects.

getState() - requests the state of the animated model being executed and returns it by Promise. Please do not confuse the state of animated model with the status of the non-animated run that is returned by ModelRun.getStatus(). The returned value will be one of:

  • "IDLE"
  • "RUNNING"
  • "PAUSED"
  • "FINISHED"
  • "ERROR"
  • "PLEASE_WAIT"
  • "INITIALIZE"
  • "STOPPED"
  • "TIME_LIMIT"
  • "TERMINATED"

callFunction(pathToFunction, args) - requests to call a function in the model, possibly providing arguments. Returns what the function returns, by Promise. The path to the function should look like experiment.root.agent1.myFunction. args is a JavaScript array of the function argument objects, see Data conversion section to learn how Java objects are mapped to JSON objects.

waitForCompletion() - waits for animated simulation to complete and returns the same Animation object by Promise. Note that even if the simulation run has finished (has reached the stop time), it will not be considered as completed until the use presses Stop, or stop() method has been called, or the server terminates the simulation due to an error.

JavaScript API reference

4.3 Writing HTML and CSS for AnyLogic Cloud things to keep in mind

If you are going to embed model animation in your web page, please make sure there is no CSS style and HTML id intersection between your part of the page and embedded AnyLogic animation part. The CSS styles used for model animation can be found in the downloaded presentation-html.css and presentation-svg.css files , and the HTML ids in the svg-template.html file. Please note that 2D animation of uses numeric ids for SVG elements, therefore you should not use numeric ids in the rest of the page.

4.4 AnyLogic engine API related to Cloud

You can, to a certain extent, adjust the look and feel of AnyLogic model animation embedded in custom web pages by using AnyLogic Java API.

These methods of the ExperimentHost class enable and disable controls on the Control panel:

void setRunControlEnabled( boolean runControlEnabled ) - enables or disables Run, Pause, and Stop buttons on the Control panel (but not on the Developer panel).

void setSpeedControlEnabled( boolean speedControlEnabled ) - enables or disables all controls related to simulation speed on the Control panel (but not on the Developer panel).

5 Java API

5.1 Obtaining the Java client

To start using the Java API, follow these steps:

  1. Download the client .jar package using the following link:
    https://cloud.anylogic.com/files/api-8.5.0/clients/anylogic-cloud-client-8.5.0.jar
  2. Inside the folder containing your AnyLogic Cloud API Java project, create a new folder and name it libs.
  3. Place the .jar package you have downloaded, in the libs folder.
  4. Open the build.gradle file that belongs to your project.
  5. Add the following code to the file contents:
    
    repositories {
        mavenCentral()
        flatDir {
            dirs 'libs'
        }
    }
    dependencies {
        implementation group: 'com.anylogic.cloud.clients', name: 'anylogic-cloud-client', version: '8.5.0'
    }
  6. Save the changes in the build.gradle file.
  7. Perform a re-import of all Gradle projects in the Java IDE you use.
  8. Use the API to work with the cloud-based models.

5.2 Java API reference

AnyLogic Java API is synchronous (see Synchronous and asynchronous API).

Another thing to keep in mind is that the API treats names (e.g. model, experiment, input, and output names) as case-insensitive.

AnyLogicCloudClient class

The AnyLogicCloudClient class is responsible for authentication and communication with the AnyLogic Cloud. Typically, there is only one object of class AnyLogicCloudClient in your Java code.

AnyLogicCloudClient(String apiKey) - a constructor that creates a synchronous AnyLogic cloud client with the given API key and the default public cloud host name https://cloud.anylogic.com.

AnyLogicCloudClient(String apiKey, String host) - a constructor that creates a synchronous AnyLogic cloud client with the given API key and the given host name.

The client methods wait for the completion of HTTP requests (and thus block the thread) before returning the result.

getModels() - returns the list of Model objects listed in the My Models section of the AnyLogic Cloud web UI.

getModelById(String id) - finds and returns the Model object with a given ID.

getModelByName(String name) - finds and returns the Model object with a given name.

getModelVersionById(Model model, String versionId) - finds and returns the Version object of a given Model with a given id.

getModelVersionByNumber(Model model, int versionNumber) - finds and returns the Version object of a given Model with a given number (version numbering starts with 1).

getLatestModelVersion(Model model) - finds and returns the latest Version object of a given Model.

getLatestModelVersion(String modelName) - finds and returns the latest Version object of the model with a given name.

createDefaultInputs(ModelVersion version) - creates and returns an Inputs object for a given model version with default input values.

createInputsFromExperiment(ModelVersion version, String experimentName) - creates and returns the Inputs object for a given model Version object copied from the experiment with the given name.

createSimulation(Inputs inputs) - creates and returns a ModelRun object of type SIMULATION with the given Inputs (the model and version are identified by inputs).

createParameterVariation(Inputs inputs) - creates and returns a ModelRun object of type PARAMETER_VARIATION with the given Inputs (the model, its version, and range input are identified by inputs).

createMonteCarloFirstOrder(Inputs inputs) - creates and returns a ModelRun object of type MONTE_CARLO with the given Inputs (the model and version are identified by inputs).

createParameterVariationWithReplications(Inputs inputs) - creates and returns a ModelRun object of type PARAMETER_VARIATION_WITH_REPLICATIONS with the given Inputs (the model, its version, range input, and number of replications are identified by inputs).

Inputs class

An object of Inputs class is constructed in preparation of a model run (of any kind) by calling the AnyLogicCloudClient functions createDefaultInputs() or createInputsFromExperiment() and contains full information about the model, model version, and the input values. It should not be confused with the inputs field in the Version object.

getInput(String name) - returns the value (an object) of the input with a given name. See Data conversion section for possible types.

setInput(String name, double value) - sets the value of the input with a given name.

setInput(String name, int value) - sets the value of the input with a given name.

setInput(String name, long value) - sets the value of the input with a given name.

setInput(String name, String value) - sets the value of the input with a given name.

setRangeInput(String name, int min, int max, int step) - sets a range for the integer input with a given name (in a parameter variation experiment).

setRangeInput(String name, long min, long max, long step) - sets a range for the long input with a given name (in a parameter variation experiment).

setRangeInput(String name, double min, double max, double step) - sets a range for the double input with a given name (in a parameter variation experiment).

setStartTime(double value, TimeUnits units) - sets the start time input. The units argument must specify TimeUnits of this input.

setStopTime(double value, TimeUnits units) - sets the stop time input. The units argument must specify TimeUnits of this input.

setStartDate(Date date) - sets the start date input.

setStopDate(Date date) - sets the stop date input.

setStopMode(ModelSystemData.StopMode stopMode) - sets the stop mode input. The stop mode argument should be selected from ModelSystemData.StopMode enum.

setRandomSeed(long randomSeed) - sets the random seed input.

setInputsFromExperiment(Experiment experiment) - copies all input values from a given experiment to the run. Experiment can be obtained from cloud client by calling its getModelVersionExperiments() method.

setNumberOfReplications(int numberOfReplications) - sets the number of replications for the parameter variation experiment. The default value is 3.

Inputs of distribution type (for Monte Carlo 2nd order experiments) are coming in future releases of AnyLogic Cloud API.

SingleRunOutputs class

An object of this class is returned after a call of getOutputs() or getOutputsAndRunIfAbsent() of a ModelRun constructed for a single run simulation experiment.

names() - returns the array with all output names.

findNameIncluding(String namePart) - searches for an output name that has namePart as a substring and returns it. If there is no such name or more than one such name is found, throws an exception. This function is useful because full names of the outputs may be complex, see Outputs data object.

value(String name) - returns the value of the output with a given name. The type of value depends on the output, see Data conversion section.

getRawOutputs() - returns an array of all output items, each item has fields name, type, units, and value. For possible values of type and units field see Output types and Units sections correspondingly. The value field contains an object constructed as described in Data conversion section. This is an example of raw outputs:

[
    {
        name: "Queue size stats",
        type: "STATISTICS_CONTINUOUS",
        units: null,
        value: {
            count: 1255584,
            max: 7,
            mean: 0.9988466028875719,
            min: 0,
            totalTime: 999999.2699032243,
            type: "CONTINUOUS",
            variance: 0.0027334062484944965
        }
    },
    {
        name: "Total time in system|Total time in system",
        type: "HISTOGRAM_DATA",
        units: null,
        value: {
            hits: (20) [800912, 159870, 29594, 5804, 3399, 1073, 257, 56, 12, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            hitsOutHigh: 0,
            hitsOutLow: 0,
            intervalWidth: 1.6,
            lowerBound: 1.6,
            statistics:{
            count: 1000987,
                max: 18.533258249757637,
                mean: 2.5012383408878067,
                min: 1.6001570096705109,
                type: "DISCRETE",
                variance: 1.2835661096259896
            }
        }
    },
    {
        name: "Utilization|Server utilization",
        type: "DOUBLE",
        units: null,
        value: 0.31275860811685163,
    },
    {
        name: "Mean queue size|Mean queue size",
        type: "DOUBLE",
        units: null,
        value: 0.9988466025848514
    }
]

MultiRunOutputs class

An object of this class is returned after a call of getOutputs() or getOutputsAndRunIfAbsent() of a ModelRun constructed for a parameter variation or other multi run experiment. It simplifies navigation within the complex outputs structure. Keep in mind that you need to explicitly specify the required outputs when calling getOutputs() functions.

getInputNames() - returns the list of names of inputs that are varied across runs.

getOutputNames() - returns the list of names of requested outputs.

getValuesOfInput(String name) - returns the values of the input with a given name across all runs in some fixed sequence.
Note that you can only query values of the varied inputs. The fixed inputs are not stored in MultiRunOutputs.

getValuesOfOutput(String name) - returns the values of the output with a given name across all runs in some fixed sequence. This function can be used together with getValuesOfInput().

getRawData() - returns a table (a two-dimensional array) with values of all variable inputs and all outputs with a header row. For example, here is the raw data of a parameter variation experiment with one variable parameter Mean service time and one scalar output Utilization|Server utilization :

[
    ["Mean service time", "Utilization|Server utilization"],
    [1.8, 0.5621987153519676],
    [1.9, 0.5939408971748594],
    [2, 0.6253419155200399]
]

ModelRun class

The ModelRun class is responsible for communication with and control of a model run (without animation) executed in Cloud. It can be considered as a frontend mirror of a backend experiment run.

Objects of ModelRun subclasses are created and returned by calling the functions createSimulation(), createParameterVariation(), createMonteCarloFirstOrder(), or createParameterVariationWithReplications() of the AnyLogicCloudClient. A ModelRun object contains full information about the model, version, inputs, and experiment type.

SimulationRun subclass

The SimulationRun subclass is used to communicate with with and control a simulation experiment (without animation) executed in Cloud. Objects of the SimulationRun subclass are created and returned by calling the createSimulation() function of the AnyLogicCloudClient.

ParameterVariationRun subclass

The ParameterVariationRun subclass is used to communicate with and control a parameter variation experiment (without animation) executed in Cloud. Objects of the ParameterVariationRun class are created and returned by calling the createParameterVariation() and createParameterVariationWithReplications() functions of the AnyLogicCloudClient.

MonteCarloFirstOrderRun subclass

The MonteCarloFirstOrderRun subclass is used to communicate with and control a Monte Carlo 1st Order experiment (without animation) executed in Cloud. Objects of the MonteCarloFirstOrderRun class are created and returned by calling the createMonteCarloFirstOrder() function of the AnyLogicCloudClient.

The following methods are common for all ModelRun objects:

run() - starts the model run and waits for the run completion. Polling is used to determine the run state. The thread is blocked until the run is completed or terminated. Returns the list of outputs.

waitForCompletion(long pollingPeriod) - waits for the experiment to complete and returns the same ModelRun object. The pollingPeriod parameter is optional, the default value is 5000ms.

stop(Inputs modelRun) - requests to stop a given modelRun run and waits for stop. Returns the same ModelRun object once the HTTP request completes.

getStatus() - returns the status of the model execution as last updated by polling (does not initiate any extra communication with the server). Possible values are the same as described in the Experiment Run State section.

getProgress() - returns the fully parsed message field of the Experiment Run State object. To find out total experiment progress, use getProgress().then( progress => progress.total).

getOutputs(List<String> requiredOutputNames) - if the run has already been completed, returns the run outputs (either SingleRunOutputs or MultiRunOutputs object), otherwise throws an exception. requiredOutputNames is the list of output names that are to be returned. If requiredOutputNames is omitted, the behavior is different for single and multi-run experiments: for a single run, all outputs are returned, for a multi run - only outputs of scalar types are returned.

getOutputsAndRunIfAbsent(List<String> requiredOutputNames, long pollingPeriod) - if the run has already been completed, returns the run outputs (either SingleRunOutputs or MultiRunOutputs object), otherwise requests to run the experiment, waits for completion by polling, and then returns the outputs. requiredOutputNames has the same meaning as in getOutputs(). The pollingPeriod parameter is optional, the default value is 5000ms.

5.3 AnyLogic engine API related to Cloud

You can, to a certain extent, adjust the look and feel of AnyLogic model animation embedded in custom web pages by using AnyLogic Java API.

These methods of the ExperimentHost class enable and disable controls on the Control panel:

void setRunControlEnabled( boolean runControlEnabled ) enables or disables Run, Pause, and Stop buttons on the Control panel (but not on the Developer panel).

void setSpeedControlEnabled( boolean speedControlEnabled ) enables or disables all controls related to simulation speed on the Control panel (but not on the Developer panel).

6 Python API

6.1 Obtaining the Python client

To start using the Python API, follow these steps:

  1. Install the AnyLogic cloud client library using pip package installer:
    pip install https://cloud.anylogic.com/files/api-8.5.0/clients/anylogiccloudclient-8.5.0-py3-none-any.whl
  2. Verify that the installation of the package has been completed successfully:
    $ python
    >>> import anylogiccloudclient.client.cloud_client

    If no errors appear, you can use the API to work with the cloud-based models.

You can also install the package manually. To download the package, use the following link:

In case of the manual installation, make sure the value of the PYTHONPATH variable specifies the location of the AnyLogic cloud client library before using it.

6.2 Python API reference

AnyLogic Python API is synchronous (see Synchronous and asynchronous API).

Another thing to keep in mind is that the API treats names (e.g. model, experiment, input, and output names) as case-insensitive.

CloudClient class

The CloudClient class is responsible for authentication and communication with the AnyLogic Cloud. Typically, there is only one object of class CloudClient in your Python code.

get_models() - returns available models as an array of Model objects.

get_model_by_id(id) - returns the Model with the given id.

get_model_by_name(name) - returns the Model with the given name.

get_model_version_by_id(model, version_id) - returns the Version of the given Model with the given id.

get_model_version_by_number(model, version_number) - returns the Version of the given Model with the given number (version numbering starts with 1).

get_latest_model_version(model) - returns the latest Version of the given model (which can be either a Model, or a model name).

create_default_inputs(version) - creates and returns an Inputs object for the given model Version with default input values.

create_inputs_from_experiment(version, experiment_name) - creates and returns the Inputs object for the given model Version copied from the experiment with the given name.

create_simulation(inputs) - creates and returns a ModelRun of type SIMULATION with the given Inputs (the model and the version are identified by the inputs).

create_parameter_variation(inputs) - creates and returns a ModelRun of type PARAMETER_VARIATION with the given Inputs (the model, its version, and range input are identified by the inputs).

create_monte_carlo(inputs) - creates and returns a ModelRun of type MONTE_CARLO with the given Inputs (the model and the version are identified by the inputs).

create_parameter_variation_with_replication(inputs) - creates and returns a ModelRun of type PARAMETER_VARIATION_WITH_REPLICATIONS with the given Inputs (the model, its version, range input, and number of replications are identified by the inputs).

Inputs class

An object of Inputs class is constructed in preparation of a model run (of any kind) by calling the CloudClient functions create_default_inputs() or create_inputs_from_experiment() and contains full information about the model, model version, and the input values. It should not be confused with the inputs field in the Version object.

get_input(name) - returns the value (an object) of the input with a given name. See Data conversion section for possible types.

set_input(name, value) - sets the value of the input with a given name.

set_range_input(name, min, max, step) - sets a range for the input with the given name (in the parameter variation experiment or parameter variation with replications experiment.).

names(self) - returns the list of all available inputs.

set_number_of_replications(num) - sets a number of replications for the parameter variation experiment. The default value is 3.

Inputs of distribution type (for Monte Carlo 2nd order experiments) are coming in future releases of AnyLogic Cloud API.

SingleRunOutputs class

An object of this class is returned after the call of the get_outputs() or get_outputs_and_run_if_absent() functions of a ModelRun constructed for a single run simulation experiment.

names() - returns the array with all output names.

find_name_including(name_part) - searches for an output name that has name_part as a substring and returns it. If there is no such name or more than one such name is found, throws Error. This function is useful because full names of the outputs may be complex, see Outputs data object.

value(name) - returns the value of the output with a given name. The type of value depends on the output, see Data conversion section.

get_raw_outputs() - returns an array of all output items. Each item has the following fields: name, type, units, and value. For possible values of type and units fields see the Output types and the Units sections respectively. The value field contains an object constructed as described in the Data conversion section. Below you can see an example of raw outputs:

[
    {
        name: "Queue size stats",
        type: "STATISTICS_CONTINUOUS",
        units: null,
        value: {
            count: 1255584,
            max: 7,
            mean: 0.9988466028875719,
            min: 0,
            totalTime: 999999.2699032243,
            type: "CONTINUOUS",
            variance: 0.0027334062484944965
        }
    },
    {
        name: "Total time in system|Total time in system",
        type: "HISTOGRAM_DATA",
        units: null,
        value: {
            hits: (20) [800912, 159870, 29594, 5804, 3399, 1073, 257, 56, 12, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            hitsOutHigh: 0,
            hitsOutLow: 0,
            intervalWidth: 1.6,
            lowerBound: 1.6,
            statistics:{
            count: 1000987,
                max: 18.533258249757637,
                mean: 2.5012383408878067,
                min: 1.6001570096705109,
                type: "DISCRETE",
                variance: 1.2835661096259896
            }
        }
    },
    {
        name: "Utilization|Server utilization",
        type: "DOUBLE",
        units: null,
        value: 0.31275860811685163,
    },
    {
        name: "Mean queue size|Mean queue size",
        type: "DOUBLE",
        units: null,
        value: 0.9988466025848514
    }
]

MultiRunOutputs class

An object of this class is returned after the call of the get_outputs() or get_outputs_and_run_if_absent() functions of a ModelRun constructed for a parameter variation or other multi run experiment. It simplifies navigation within the complex outputs structure. Keep in mind that you need to explicitly specify the required outputs when calling the get_outputs() functions.

get_input_names() - returns the array of names of inputs that are varied across the runs.

get_output_names() - returns the array of names of requested outputs.

get_values_of_input( name ) - returns the array of values of the input with the given name across all runs in some fixed sequence. Note that you can only query values of the varied inputs. The fixed inputs are not stored in MultiRunOutputs.

get_values_of_output( name ) - returns the array of of values of the output with a given name across all runs in some fixed sequence. This function can be used together with get_values_of_input().

get_raw_data() - returns a table (a two-dimensional array) with values of all variable inputs and all outputs with a header row. Below you can see a raw data example of a parameter variation experiment with one variable parameter (Mean service time) and one scalar output (Utilization|Server utilization):

[
    ["Mean service time", "Utilization|Server utilization"],
    [1.8, 0.5621987153519676],
    [1.9, 0.5939408971748594],
    [2, 0.6253419155200399]
]

ModelRun class

The ModelRun class is responsible for communication with and control of a model run (without animation) executed in Cloud. It can be considered as a frontend mirror of a backend experiment run. Objects of the ModelRun class are created and returned by calling the functions create_simulation(), create_parameter_variation(), create_monte_carlo(), or create_parameter_variation_with_replications() of the CloudClient. A ModelRun object contains full information about the model, version, inputs, and experiment type.

run() requests to run the experiment. Whether or not the simulation will actually be executed depends on the availability of the outputs. The function returns the same ModelRun object once the HTTP request completes; it does not wait for simulation completion or outputs availability and does no polling.

stop() - requests to stop the model execution. Returns the same ModelRun object once the HTTP request completes.

wait_for_completion(polling_period) - waits for the experiment to complete and returns the same ModelRun object. The polling_period parameter is optional, the default value is 5000ms.

get_status() - returns the status of the model execution as last updated by polling (does not initiate any extra communication with the server). Possible values are the same as described in the Experiment Run State section.

get_progress() - returns the fully parsed message field of the Experiment Run State object. To find out the total experiment progress use get_progress()["total"].

get_outputs(required_output_names) - if the run has already been completed, returns the run outputs (either SingleRunOutputs or MultiRunOutputs object), otherwise throws 404 Error. The required_output_names parameter is the array of output names that are to be returned. If required_output_names is omitted, the behavior will differ for single and multi-run experiments. For a single run all outputs are returned, for a multi run only outputs of scalar types are returned.

get_outputs_and_run_if_absent(required_output_names, polling_period) if the run has already been completed, returns the run outputs (either SingleRunOutputs or MultiRunOutputs object), otherwise requests to run the experiment, waits for completion by polling, and then returns the outputs. required_output_names has the same meaning as in get_outputs(). The polling_period parameter is optional, the default value is 5000ms.

6.3 AnyLogic engine API related to Cloud

You can, to a certain extent, adjust the look and feel of AnyLogic model animation embedded in custom web pages by using AnyLogic Java API.

These methods of the ExperimentHost class enable and disable controls on the Control panel:

void setRunControlEnabled( boolean runControlEnabled ) enables or disables Run, Pause, and Stop buttons on the Control panel (but not on the Developer panel).

void setSpeedControlEnabled( boolean speedControlEnabled ) enables or disables all controls related to simulation speed on the Control panel (but not on the Developer panel).

7 Data conversion between the model and the API client

One of the advantages of AnyLogic Cloud API is that it abstracts away from the language that was used to develop the model (Java in case of AnyLogic) and allows you to interact with the model using multiple different languages on the client side. With the API, you can set up the model inputs, read outputs, pass and retrieve data to and from the running model. Therefore, data conversion is a part of the API. In general, it works this way:

  • JSON is used as a universal data format throughout AnyLogic Cloud API; JSON is the format directly used in REST API
  • Jackson is used to convert data between Java and JSON. Conversion examples are given in the table below. To ensure safe reliable conversion for your own Java classes you should follow some simple rules also described below. You should keep in mind that when converting from JSON to Java, Jackson knows the target data type and will try to match the incoming string accordingly; whereas when converting from Java to JSON the target type is not known.
  • There are a few exceptions when conversion from Java to JSON is done in a special way (not with the help of Jackson), namely, these are the data objects from the Analysis palette in AnyLogic: DataSet, HistogramData, Histogram2DData, StatisticsContinuous, StatisticsDiscrete. Objects of those classes are considered as model output only and cannot be passed in the reverse direction (from the API client to the model).
JSON Java
Primitive types
Number double, float, int, long, etc. (any numeric type)
Boolean boolean
String String

Exception: AnyLogic classes with specific Java to JSON conversion, reverse conversion is NOT possible

{
    dataX:[1,2,3,4],
    dataY:[10,20,30,40]
}
DataSet
{
    hits: [0,0,0,1,5,67,335,441,138,13],
    hitsOutHigh: 0,
    hitsOutLow: 0,
    intervalWidth: 1.2,
    lowerBound: -8.6,
    statistics:{
        count: 1000,
        max: 2.83,
        mean: 0.0005,
        min: -3.91,
        type: "DISCRETE",
        variance: 0.959
    }
}
HistogramData
{
    hits: [
        [8, 4, 4, 4, 9],
        [5, 6, 8, 2, 1],
        [3, 8, 7, 6, 8],
        [7, 8, 5, 7, 9],
        [3, 4, 3, 9, 6],
    ],
    hitsOutHigh: [0,0,0,0,0],
    hitsOutLow: [0,0,0,0,0],
    xMax: 10,
    xMin: 0,
    yMax: 1,
    yMin: 0
}
Histogram2DData
{
    type: "CONTINUOUS",
    count:1375730,
    min:0.0,
    max:10.0,
    mean:0.9915478405530092,
    variance:0.14075328464389159,
    totalTime:999999.2699032243
}
StatisticsContinuous
{
    type: "DISCRETE",
    count: 1000,
    max: 2.83,
    min: -3.91,
    mean: 0.0005,
    variance: 0.959
}
StatisticsDiscrete
Standard complex types, for which Jackson rules apply, for example:
Formatted String,e.g. "2019-05-13T15:34:03.976" Date
Date Date
[12.5, 34,156.9] array of numbers double[]
["red", "white","blue"] array of Strings ArrayList<String>
Just convert it to JSON using the API and explore the result to observe the structure Any complex class
User-defined classes, for which Jackson rules apply for example:
{ name:"John",age:33 }
public class Person {
    private String name;
    private int age;

    public String getName() { return name; }

    public int getAge() {return age; }

    public void setName(String name ) {
    this.name = name;
    }

    public void setAge(int age ) {
    this.age = age;
}
}
{ name:"John", age:33 }
public class Person {
    public String name;
    public int age;
}

To make sure you have safe bidirectional JSON Java conversion for your custom objects, you should follow simple rules:

  • Class fields that you wish to pass should either be declared public in Java or, if they are private, they must have public setters and getters
  • There should be a default public constructor available in the Java class

8 Synchronous vs asynchronous API

There are two types of API for working with AnyLogic Cloud: synchronous and asynchronous.

  • In synchronous API, methods wait for underlying operations to complete (e.g. for HTTP requests or for server-based simulation runs). The advantage of synchronous API is its ease of use: as the methods complete the required action and return the actual results, you can use straightforward control flow. The disadvantage is that such methods block the thread where they are called. Therefore, it is not good to use synchronous API where responsiveness is required or where multithreading is not available.
  • In asynchronous API, methods do not wait for completion of time-consuming operations (and thus do not block the thread) and complete immediately. They return objects where you can provide callback code to be executed when the response comes and results are available, such as Promise in JavaScript or CompletableFuture in Java.

AnyLogic Cloud JavaScript API is purely asynchronous, and Java API has both synchronous and asynchronous methods for your convenience.