import { Stream } from '../data/Stream'; import { BlobType, EastType, EastFunction, Variable, DictType, StringType, StructType, FloatType, ArrayType, IntegerType, ValueTypeOf, Value, DateTimeType, BooleanType } from '../east'; import { Builder, ModulePath, Template } from '../template'; import { ModuleBuilder } from '../template/ModuleBuilder'; import { OptimizationAlgorithm } from './optimization'; import { CustomOptimizationConfiguration, Optimization } from './SimulationTaskDescription'; /** * A helper class to build optimizable scenarios around a custom task to running on the * ELARA platform. * * The custom task executes a command inside a dockerized sandbox. It is given some input * files as blob data, and produces some output files as blob data. The custom task can run * any linux-compatible binary program (which can be provided as one of the input files) * inside our default Ubuntu container, or any docker image you upload to ELARA via a blob * {@link Stream}. * * The outputs of the custom task can be optimized automatically with respect to the inputs * using ELARA's standard optimizer. During each optimization iteration, multiple * Monte-Carlo "trajectories" can be executed. This means the command will be run numerous * times during execution. * * A corresponding {@link Template} can be created using `.toTemplate()`. * * @category Task * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ export declare class CustomScenarioBuilder = {}, Outputs extends Record = {}, Results extends Record = {}, MultiTrajectory extends boolean = false> extends Builder { private inputs; private results; private image; private mountDir; private inputFiles; private outputFiles; private command; private objectiveFunction; private optimizations; private optimizationConfiguration; private log_stdout; private log_stderr; private envs; private isDistributed; private simulation_trajectories; constructor(name: string, module?: ModuleBuilder | ModulePath); /** @internal */ constructor(name: string, module: ModulePath, inputs: Record, results: Record, image: string | null, mountDir: string, inputFiles: { input: string; path: string; executable: boolean; toBlob: EastFunction; }[], outputFiles: { path: string; fromBlob: EastFunction; }[], command: string[] | null, objectiveFunction: EastFunction | null, optimizations: Optimization[], optimization_config: Partial, logStdOut: boolean, logStdErr: boolean, envs: Record>, isDistributed: boolean, simulation_trajectories: number | null); /** * Inherit all details from a given `CustomScenarioBuilder` in this scenario. This can be used * to create two similar scenarios for comparison (for example, to compare predictions * of optimized and unoptimized scenarios). * * @param builder the {@link CustomScenarioBuilder} to copy from * * @category CustomScenario * */ copyScenario, O extends Record, R extends Record, T extends boolean>(builder: CustomScenarioBuilder): CustomScenarioBuilder; /** * Add an input to the custom task. A file with the provided `filename` is created from * the data stored in a blob {@link Stream} before the custom task command is launched. * * Note that the input could be a linux-compatible program to execute. * * @param filename the filename of the input * @param stream a blob stream contain the data to place in the file * @param toBlob an optional function to create an {@link Expression} to serialize the input data into a raw file (blob) * @param executable set to `true` if the file is an executable program (default `false`) * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScearnio") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(FloatType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ input(filename: Name, stream: Stream, toBlob?: (input: Variable) => EastFunction, executable?: boolean): CustomScenarioBuilder; /** * Add an output to the custom task. A file with the provided `filename` is expected to * exist after the custom task command is completed. The output data is then copied to a * {@link Stream}. * * @param filename the filename of the output * @param fromBlob an optional function to create an {@link Expression} to deserialize (or parse) the output data from a raw file (blob) * @param result whether this file is written to a datastream (default `true`) * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScearnio") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .result("field_a", outputs => GetField(outputs["output_data.json"], "a")) * .shell("./my_program input.json output.json") * .objective(outputs => GetField(outputs["output.json"], "b")) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ output(filename: Name, fromBlob?: undefined, result?: true): CustomScenarioBuilder; output(filename: Name, fromBlob: undefined, result: false): CustomScenarioBuilder; output) => EastFunction>(filename: Name, fromBlob: F, result?: true): CustomScenarioBuilder["type"]; }, Results & { [K in Name]: ReturnType["type"]; }, MultiTrajectory>; output) => EastFunction>(filename: Name, fromBlob: F, result: false): CustomScenarioBuilder["type"]; }, Results, MultiTrajectory>; /** * Add a result to the (optimized) custom task which is computed from the output files. * * @param filename the filename of the output * @param fromBlob an optional function to create an {@link Expression} to deserialize (or parse) the output data from a raw file (blob) * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScearnio") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ result; }) => EastFunction>(name: Name, result: F): CustomScenarioBuilder["type"]; }, MultiTrajectory>; /** * Provide the directory where the input and output data is located. * * This directory is a docker "volume mount" - if this directory already exists in the image, files inside will not be visible inside the container. If necessary, copy files into the data directory from elsewhere in the image via a {@link shell} command. * * Note: the directory is also set as the current working directory before the task command is executed. * * @param dir the directory to mount the data inside the docker container * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScearnio") * .dataDir("/my/custom/dir") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ dataDir(dir: string): CustomScenarioBuilder; /** * Provide the command used to execute the custom task in shell. This command will be executed * by the linux `bash` shell in a sandboxed docker environment. * * @param command the command to be executed * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScearnio") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ shell(command: string): CustomScenarioBuilder; /** * Provide the command used to execute the custom task with raw arguemnts. This command * will be executed in a sandbox. As the command is not be interpretted by any shell, * it is not necessary to quote the arguments (e.g. filenames containing spaces, etc). * * @param command the filename of the program to be executed * @param args the command-line arguments given to the program * * @category CustomScenario * * @example * ```typescript * // Create a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScearnio") * .input("my_program", my_program_stream, file => file, true) * .input("input data.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output data.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .exec("./my_program", "input data.json", "output data.json") * .objective("output data.json") * .optimizeEvery("input data.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ exec(command: string, ...args: string[]): CustomScenarioBuilder; /** * Provide a user-defined docker image to execute the custom task. The docker image is * provided via a blob {@link Stream}, containing an OCI container in a .tar, .tar.gz, * .tar.bz2 file format as generated by docker via `docker image save ...` or similar methods. * * If no docker image is provided, then an Ubuntu LTS image is used by default. If no command * is provided the image's default command is used. * * @param stream the stream containing the docker image * * @category CustomScenario * * @example * ```typescript * // Create a custom task which uses a user-provided docker image to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .dockerImage(my_docker_image_stream) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ dockerImage(stream: Stream): CustomScenarioBuilder; /** * * Set the maximum number of optimization iterations to complete. * * @param max_iterations the maximum number of optimization iterations (default `1000`) * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationMaxIteration(100) * ``` */ optimizationMaxIterations(max_iterations: number): this; /** * * Set the relative tolerance required to trigger convergence detection. Set to 0 if relative convergence detection is not desired. * * @param rtol the relative tolerance required for convergence (default = 1.0e-3) * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationRtol(0.01) * ``` * */ optimizationRtol(rtol: number): this; /** * * Set the absolute tolerance required to trigger convergence detection. Set to 0 if absolute convergence detection is not desired. * * @param atol the absolute tolerance required for convergence (default = 0.0) * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationAtol(0.1) * ``` * */ optimizationAtol(atol: number): this; /** * * Set the minimum number of iterations to complete before detecting for convergence * * @param min_iterations the minimum number of iterations to complete before detecting for convergence (default `0`) * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationMinIterations(50) * ``` * */ optimizationMinIterations(min_iterations: number): this; /** * Set the optimzation algorithm to employ to search the parameter space. * * @param algorithm the algorithm to apply (default = `"gradient_free"`) * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationAlgorithm("random_search") * ``` * */ optimizationAlgorithm(algorithm: OptimizationAlgorithm): this; /** * Set the number of Monte-Carlo trajectories to be performed during optimization. * * @param n_trajectories the number of Monte-Carlo trajectories (default `20`) * * @remarks More trajectories will give greater certainty that the optimized recommendations are robust to any randomness in the scenario simulation, but will incur a greater computational cost. To help determine if sufficient trajectories are used for optimization, a "validation" set is also produced - for best result there should be a high degree of correlation between the target objective and the validation objective. * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationTrajectories(100) * ``` * */ optimizationTrajectories(n_trajectories: number): this; /** * Set the number of Monte-Carlo trajectories to be performed during simulation. * * @param n_trajectories the number of Monte-Carlo trajectories, or `null` for single trajectory (default `null`) * * @remarks More trajectories will give greater statistical certainty in the results, but will incur a greater computational cost. * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .simulationTrajectories(100); * ``` * */ simulationTrajectories(n_trajectories: null): CustomScenarioBuilder; simulationTrajectories(n_trajectories: number): CustomScenarioBuilder; /** * * Set the optimization parameters are to be held in memory (instead of the default out-of-core method). * * @param in_memory true if the optimization data should be held in memory * * @remarks In-memory optimization may be faster but requires more RAM. * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * .optimizationInMemory(true) * ``` * */ optimizationInMemory(in_memory: boolean): this; /** * Define a contribution to the objective function to be optimized (maximised), by computing a float * * @param name the output to calculate an objective from * @param expr the objective expression to apply in optimization (required if the output is not a float) * * @remarks optimization will use the sum of all `objective` values in the case that multiple are defined * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(FloatType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` * */ objective(objective: (value: { [K in keyof Outputs]: Variable; }) => EastFunction): CustomScenarioBuilder; /** * Optimize the value of an input to maximize the output objective. * * The optimizer can search for optimal values using one of three different strategies: * * 1. searching between `min` and `max` values (for float/integer/datetime inputs) * 2. selecting one of a `range` containing an array of possible values * 3. using a custom `transform` to construct a value from a search parameter between `0.0` and `1.0` * * @param name the path of the input to optimize * @param config the configuration of the optimization * * @remarks each optimize added results in significant compute so should be used sparingly * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimize("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` * */ optimize(name: Name, config: { /** The minimum value that the optimzer may apply (inclusive, default 0) */ min?: ValueTypeOf | ((inputs: { [K in keyof Inputs]: Variable; }) => EastFunction); /** The maximum value that the optimzer may apply (inclusive) */ max: ValueTypeOf | ((inputs: { [K in keyof Inputs]: Variable; }) => EastFunction); }): CustomScenarioBuilder; optimize(name: Name, config: { /** A set of allowable values the optimizer may explore */ range: ValueTypeOf[] | ((inputs: { [K in keyof Inputs]: Variable; }) => EastFunction>); }): CustomScenarioBuilder; optimize(name: Name, config: { /** A transformation from an optimization parameter in the range 0 to 1 to the initial input value */ transform: (param: Variable, inputs: { [K in keyof Inputs]: Variable; }) => EastFunction; }): CustomScenarioBuilder; /** * Optimize the initial values of a float field inside a tabular (i.e. array of structs) input to maximize the output objective. * * The optimizer can search for optimal values using one of three different strategies: * * 1. searching between `min` and `max` values (for float/integer/datetime inputs) * 2. selecting one of a `range` containing an array of possible values * 3. using a custom `transform` to construct a value from a search parameter between `0.0` and `1.0` * * @param name the path of the input to optimize * @param config the configuration of the optimization * * @remarks each optimize added results in significant compute so should be used sparingly * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` * */ optimizeEvery>)>(name: Name, field: Inputs[Name] extends ArrayType ? keyof Inputs[Name]["value"]["value"] : never, config: { min?: number | bigint | Date | ((inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction); max: number | bigint | Date | ((inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction); active?: (inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction; }): CustomScenarioBuilder; optimizeEvery>)>(name: Name, field: Inputs[Name] extends ArrayType ? keyof Inputs[Name]["value"]["value"] : never, config: { range: Value[] | ((inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction); active?: (inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction; }): CustomScenarioBuilder; optimizeEvery>)>(name: Name, field: Inputs[Name] extends ArrayType ? keyof Inputs[Name]["value"]["value"] : never, config: { transform: (param: EastFunction, inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction; active?: (inputs: { [K in keyof Inputs]: Variable; }, value: Inputs[Name] extends ArrayType ? Variable : never, key: Variable) => EastFunction; }): CustomScenarioBuilder; /** * Set an environment variable for the custom task. This could be computed from the trajectory number, for example for a random seed. * * @param name the name of the environment variable * @param value the value of the environment variable - either a raw string, or an expression of the trajectory number * * @category Task * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .env("RANDOM_SEED", (trajectory) => Print(Add(1000n, trajectory))) * .shell("./my_program input.json output.json") * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` **/ env(name: string, value: string): CustomScenarioBuilder; env(name: string, value: (trajectory: Variable) => EastFunction): CustomScenarioBuilder; /** * Enable or disable logging of stdout from the custom scenario. Note that this will * create messages for each trajectory inside each iteration of optimization. * * @param enabled whether logging is enabled (default `true`) * * @category Task * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .logStdOut(true) * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ logStdOut(enabled: boolean): CustomScenarioBuilder; /** * Enable or disable logging of stderr from the custom scenario. Note that this will * create messages for each trajectory inside each iteration of optimization. * * @param enabled whether logging is enabled (default `false`) * * @category Task * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .logStdErr(true) * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * ``` */ logStdErr(enabled: boolean): CustomScenarioBuilder; /** * Set the calculations to be performed in a distributed way, accross multiple tasks and * able to take advantage of multiple worker nodes in parallel (instead of the default * in-process, single-task method). * * @param is_distributed true if the calculations should be performed distributed * * @remarks Distributed simulations are faster for demanding simulations with many * trajectories, but orchestration overheads may make it slower for simple simulations. * * @category Scenario * */ distributed(is_distributed: boolean): this; /** * Return a {@link Stream} detailing the optimzation procedure, where convergence of optimization can be validated. * * @category Scenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .logStdErr(true) * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * * // Get the optimization stream * const optimization_stream = my_scenario.optimizationStream() * ``` */ optimizationStream(): Stream; values: DictType; }>>>; /** * Return a record of {@link Stream}s containing the automatically optimized values for the custom scenario inputs. * * @category Scenario */ optimizedStreams(): { [K in keyof Inputs]: Stream; }; /** * Fetch the result streams of the custom task. This returns a record of data streams; * by default the keys are the paths of the output files, but other results can be * computed via {@link result}. * * The data returned is from the first trajectory of the optimized scenario. * * @category CustomScenario * * @example * ```typescript * // Optimize a custom task which uses a user-provided program to transform a JSON file into another JSON file * const my_scenario = new CustomScenarioBuilder("MyScenario") * .input("my_program", my_program_stream, file => file, true) * .input("input.json", input_data_stream, data => Utf8Encode(ToJson(data))) * .output("output.json", blob => FromJson(MyOutputType, Utf8Decode(blob))) * .shell("./my_program input.json output.json") * .logStdErr(true) * .objective(outputs => outputs["output.json"]) * .optimizeEvery("input.json", "amount", { min: () => Const(0), max: () => Const(100) }) * * // Get the decoded output data stream * const output_stream = my_scenario.outputStreams()["output.json"] * ``` */ resultStreams(): MultiTrajectory extends false ? { [K in keyof Results]: Stream; } : { [K in keyof Results]: Stream>; }; toTemplate(): Template; /** As above, but trajectories are performed as seperate tasks */ private toTemplateDistributed; }