import { Stream } from '../data'; import { ArrayType, BooleanType, DateTimeType, DictType, EastFunction, EastType, FloatType, IntegerType, NullType, SetType, StringType, StructType, Value, ValueTypeOf, Variable, VariantType } from '../east'; import { ProcedureDescription } from '../function'; import { GenericPipelineBuilder, PipelineBuilder, TabularPipelineBuilder } from '../pipeline'; import { Builder, ModulePath, Template } from '../template'; import { ModuleBuilder } from '../template/ModuleBuilder'; import { OptimizationAlgorithm } from './optimization'; import { AbstractProcessBuilder } from './ProcessBuilder'; import { SimulationResourceBuilder } from './ResourceBuilder'; import { MLDescription, Optimization, OptimizationConfiguration, ProcessDescription, ResourceDescription, SimulationConfiguration } from './SimulationTaskDescription'; /** @internal */ export type LedgerType = T extends DictType ? ArrayType; insertMany: T; delete: T["value"]["key"]; deleteMany: SetType; deleteAll: NullType; update: StructType<{ key: T["value"]["key"]; value: T["value"]["value"]; }>; updateMany: T; }>; }>> : T extends DictType ? ArrayType; insertMany: T; delete: T["value"]["key"]; deleteMany: SetType; deleteAll: NullType; }>; }>> : ArrayType; }>>; /** @internal */ export type OptimizationType = ArrayType; values: DictType; }>>; /** @internal */ export declare function LedgerType(type: T): LedgerType; /** * A builder to define a scenario to simulate and optionally optimise. * * @category Scenario * * @example * ```typescript * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapFromValue({ date: new Date(0), amount: 42.0, }); * * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales); * ``` * * */ export declare class ScenarioBuilder> = {}, Processes extends { [K: string]: ProcessDescription; } = {}, Results extends Record = {}, MultiTrajectory extends boolean = false> extends Builder { private resources; private processes; private mls; private procedures; private inputs; private objectiveFunction; private optimizations; private simulationConfiguration; private optimizationConfiguration; private results; private alterations; private initialQueueStream; private simulationEndDate; private isDistributed; private random_seed; private optimization_seed_distinct; /** * Create a builder to define a scneario to simulate and optionally optimise. * * @param name the name of the builder * * @category Scenario * * @example * ```typescript * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapFromValue({ date: new Date(0), amount: 42.0, }); * * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales); * ``` * * */ constructor(name: string, module?: ModuleBuilder | ModulePath); /** @internal */ constructor(name: string, module: ModulePath, resources: Resources, processes: Processes, mls: Record, procedures: Record, inputs: Record, objectiveFunction: EastFunction | null, optimizations: Optimization[], simulation_config: SimulationConfiguration, optimization_config: Partial, results: { [K in keyof Results]: EastFunction; }, alterations: Template, initialQueueStream: Stream | null, simulationEndDate: Date | Stream | null, isDistributed: boolean, randomSeed: string, optimization_seed_distinct: boolean); /** * Inherit all details from a given `ScenarioBuilder` in this scenario. This can be used * to create two similar scenarios for comparison (for example, to compare predictions * of optimized and unoptimized scenarios). * * This differs from {@link continueScenario} by starting with the same initial simulation * state as the copied scenario. * * @param builder the {@link ScenarioBuilder} to copy from * * @category Scenario * * @example * ```typescript * // create a resource * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * * // create a scenario * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * * // create a scenario from the other one * const similar_scenario = new ScenarioBuilder('similar_scenario') * .copyScenario(scenario) * ``` * * */ copyScenario>, P extends Record>, Res extends Record>(builder: ScenarioBuilder): ScenarioBuilder; /** * Inherit all details from a given `ScenarioBuilder` in this scenario, starting with the * simulation state (resource values and process event queue) from the end of the previous * scenario. This can be used to chain two scenario simulations in time (for example, * having a first scenario simulating historical events followed by a second scenario * predicting future events). * * This differs from {@link copyScenario} by starting with the final simulation state of * the other scenario, rather than the initial state. Also, the simulation end date is not * copied. * * @param builder the {@link ScenarioBuilder} to continue from * * @category Scenario * * @example * ```typescript * // create a resource * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * * // create a first scenario * const first_scenario = new ScenarioBuilder('first_scenario') * .resource(cash) * * // create a second scenario following the first * const second_scenario = new ScenarioBuilder('second_scenario') * .continueScenario(first_scenario) * ``` * * */ continueScenario>, P extends Record>, Res extends Record>(builder: ScenarioBuilder): ScenarioBuilder; /** * Add a resource to the scenario. * * @param resource the {@link ResourceBuilder} to add to this {@link ScenarioBuilder} * @param config the configuration of the addition * * @category Scenario * * @example * ```typescript * // create a resource * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * // create a scenario and add the resource * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * ``` * * */ resource(resource: SimulationResourceBuilder, config?: { /** if the true the result {@link Stream} will be created (default `true`) */ result?: true; }): ScenarioBuilder; }, Processes, Results & { [K in Name]: T; }, MultiTrajectory>; resource(resource: SimulationResourceBuilder, config: { /** if the true the result {@link Stream} will be created (default `true`) */ result: false; }): ScenarioBuilder; }, Processes, Results, MultiTrajectory>; /** * Add a result to return from the scenario simulation. Results are computed from the resource values at the end of the simulation. * * @param name the name of this result * @param result a function returning an {@link EastFunction} to compute the value to return * * @category Scenario * * @example * ```typescript * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0); * * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapFromValue({ date: new Date(0), amount: 42.0, }); * * // add a result that computes whether the final cash balance is positive or negative * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .result("cash_is_positive", resources => GreaterEqual(resources.cash, 0)); * * // get the datastream containing the result * const cash_is_positive_stream = scenario.simulationResultStreams()["cash_is_positive"] * ``` */ result; }) => EastFunction>(name: Name, result: R): ScenarioBuilder["type"]; }, MultiTrajectory>; /** * Add a process to the scenario. * * @param process the {@link ProcessBuilder} to add to this {@link ScenarioBuilder} * * @category Scenario * * @example * ```typescript * // create a process * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapFromValue({ date: new Date(0), amount: 42.0, }); * * // create a scenario and add the process * const scenario = new ScenarioBuilder('my_scenario') * .process(sales); * ``` * * */ process, Properties extends Record>(process: AbstractProcessBuilder, Record, Record>): ScenarioBuilder, StructType<{ date: DateTimeType; } & Values>>; }, Results, MultiTrajectory>; /** * Override an existing process in a scenario with another. This is used to redefine a * process inherited by {@link copyScenario} or {@link continueScenario} for this scenario. * * This method will redirect all references to the existing process in the scenario (e.g. * {@link ProcessBuilder.execute} statements) to the new process, and remove the old process. * To allow the translation of execute statements and continuation of the event queue, it * is a requirement that the new process and old process share the same name and set of * input value properties (defined through {@link ProcessBuilder.value}). Any computed * properties or other process statements may differ. The {@link ProcessBuilder.overrides} * method can help to construct an appropriate process. * * @param name the name of the process to override * @param process a {@link ProcessBuilder} for the new process */ overrideProcess, Properties extends Record>(name: Name, process: AbstractProcessBuilder, Record, Record>): ScenarioBuilder & { [K in Name]: ProcessDescription, StructType<{ date: DateTimeType; } & Values>>; }, Results, MultiTrajectory>; /** * End the scenario simulation at the specified date. * * Note that the simulation will terminate before processes scheduled at this exact date. * * @param date either a `Date` object, or a {@link Stream} of `DateTimeType`. */ endSimulation(date: Date | Stream | null): ScenarioBuilder; /** * Replace the initial value of a resource in this scenario with a provided value. * * @remarks The entire contents of the initial resource value will be overwritten. * * @param name the name of the resource * @param value the new value to override the existing * * @category Scenario * * @example * ```typescript * // create a resource * const cash = new ResourceBuilder("cash") * .mapFromValue(1000.0) * * // create an alternative scenario with different initial cash balance from a value * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .alterResourceFromValue("cash", 2000.0) * ``` */ alterResourceFromValue(name: Name, value: ValueTypeOf): ScenarioBuilder; /** * Replace the initial value of a resource in this scenario with a value from a data stream. * * @remarks The entire contents of the initial resource value will be overwritten. * * @param name the name of the resource * @param stream the {@link Stream} containing the new value to override the existing * * @category Scenario * * @example * ```typescript * // create a resource * const cash = new ResourceBuilder("cash") * .mapFromValue(1000.0) * * // create a stream for alternative initial cash balance * const alternative_cash = new SourceBuilder("alternative_cash") * .value({ value: 2000.0 }) * * // create an alternative scenario with different initial cash balance from a stream * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .alterResourceFromStream("cash", alternative_cash) * ``` */ alterResourceFromStream(name: Name, stream: Stream): ScenarioBuilder; /** * Replace the initial value of a resource in this scenario with the output of a new pipeline. * * @remarks The entire contents of the initial resource value will be overwritten (but the already existing "baseline" inital value is made available to the pipeline). * * @param name the name of the resource * @param pipeline a function that builds and returns a {@link Pipeline} outputting the new value to override the existing * * @category Scenario * * @example * ```typescript * // create a resource * const cash = new ResourceBuilder("cash") * .mapFromValue(1000.0) * * // create an alternative scenario with different initial cash balance from a pipeline * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .alterResourceFromPipeline( * "cash", * (builder, baseline) => Builder * .from(baseline) * .transform(cash => Multiply(cash, 2.0)) * ) * ``` */ alterResourceFromPipeline(name: Name, pipeline: (builder: PipelineBuilder, baseline: Stream) => Resources[Name]["type"] extends DictType ? TabularPipelineBuilder> : GenericPipelineBuilder>): ScenarioBuilder; /** * Replace the initial executions of a process in this scenario with provided values. * * @remarks The entire contents of the initial process executions will be overwritten. * * @param name the name of the process * @param value the new executions to override the existing * * @category Scenario * * @example * ```typescript * // create a process * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapManyFromValue(new Map([["1", { date: new Date(0), amount: 42.0, }]])) * * // create a scenario and add the process with doubled sales amount * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .alterProcessFromValue("sales", new Map([["1", { date: new Date(0), amount: 84.0, }]])) * ``` */ alterProcessFromValue(name: Name, value: ValueTypeOf>): ScenarioBuilder; /** * Replace the initial executions of a process in this scenario with values from a data stream. * * @remarks The entire contents of the initial process executions will be overwritten. * * @param name the name of the process * @param stream a {@link Stream} containing the new executions to override the existing * * @category Scenario * * @example * ```typescript * // create a process * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapManyFromValue(new Map([["1", { date: new Date(0), amount: 42.0, }]])) * * // create a stream for alternative sales executions * const alternative_sales = new SourceBuilder("alternative_sales") * .value({ value: new Map([["1", { date: new Date(0), amount: 84.0, }]]) }) * * // create a scenario and add the process with doubled sales amount * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .alterProcessFromStream("sales", alternative_sales) * ``` */ alterProcessFromStream(name: Name, stream: Stream>): ScenarioBuilder; /** * Replace the initial executions of a process in this scenario with values from a new pipeline. * * @remarks The entire contents of the initial process executions will be overwritten (but any already existing "baseline" executions are made available to the pipeline). * * @param name the name of the process * @param pipeline a function that builds and returns a {@link Pipeline} outputting the new executions to override the existing * * @category Scenario * * @example * ```typescript * // create a process * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapManyFromValue(new Map([["1", { date: new Date(0), amount: 42.0, }]])) * * // create a scenario and add the process with doubled sales amount * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .alterProcessFromPipeline( * "sales", * (builder, baseline) => builder. * .from(baseline) * .select({ * keep_all: true, * selections: { * amount: fields => Multiply(fields.amount, 2.0), * } * }) * ) * ``` */ alterProcessFromPipeline(name: Name, pipeline: (builder: PipelineBuilder, baseline?: Stream>) => TabularPipelineBuilder, Record>): ScenarioBuilder; /** * Set the initial simulation queue present at the beginning of the similation. * * This is an alternative method to instantiating processes via `ProcessBuilder` mappings, * and allows one to import the final simulation queue from one scenario into another * scenario (e.g. to simulate the continuation of time across scenarious). Note that any * existing process mappings are also added to the queue before the simulation begins. * * @param stream The datastream defining the initial queue. The queue itself is an array * of variants (where each variant case corresponding to a process in the scenario and * associated execution date and value properties). Can be set to `null` if no initial * queue is desired. * * @category Scenario */ setInitialQueueStream(stream: null): ScenarioBuilder; setInitialQueueStream>>(stream: T & (T & Stream>> extends never ? never : unknown)): ScenarioBuilder; /** * 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; /** * Set the simulation to be performed in-memory or out-of-core. * * @param in_memory `true` if the simulation should be performed in-memory or `false` for an out-of-core method * * @remarks In-memory simulations may be faster but require more RAM. * * @category Scenario * */ simulationInMemory(in_memory: boolean): this; /** * Set whether to produce an output {@link Stream} containing the simulation journal detailing all process executions (default = `true`). * * @param enabled true if the simulation journal should be created * * @category Scenario * */ simulationJournal(enabled: boolean): this; /** * Set whether to produce an output {@link Stream} containing the simulation queue detailing all processes awaiting execution at the end of the simulation (default = `true`). * * @param enabled true if the simulation queue should be created * * @category Scenario * */ simulationQueue(enabled: boolean): this; /** * Set the simulation to be in debug mode, where errors become warnings. * * @param enable true if the simulation should be run in debug mode * * @remarks This can help to debug problems with simulation models, but is not recommended for production settings. * * @category Scenario * */ simulationDebugMode(enable: boolean): this; /** * Set the number of Monte-Carlo trajectories to be performed during simulation. * * Using this setting affects the result, journal and queue types. For each result an array of individual trajactory results will be emitted. Similarly an array of journals and queues will be emitted, with the data recorded for each trajectory. * * @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 Scenario * */ simulationTrajectories(n_trajectories: null): ScenarioBuilder; simulationTrajectories(n_trajectories: number): ScenarioBuilder; /** * Set the number of Monte-Carlo trajectories to be performed during optimization. * * @param n_trajectories the number of monte carlo trajectories * * @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. * * @category Scenario * */ optimizationTrajectories(n_trajectories: number | null): this; /** * * Set the maximum number of optimization iterations to complete. * * @param max_iterations the maximum number of optimization iterations * * @category Scenario * */ 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 * */ 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 * */ 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. * * @category Scenario * */ optimizationMinIterations(min_iterations: number): this; /** * * Set the optimization to be performed in memory (instead of the default out-of-core method). * * @param in_memory true if the optimization should be performed in memory * * @remarks In-memory optimization may be faster but requires more RAM. * * @category Scenario * * */ optimizationInMemory(in_memory: boolean): this; /** * Set the optimzation to be performed multi-threaded (instead of the default single-thread method). * * @param threads true if the optimization should use multiple threads * * @category Scenario * */ optimizationMultithreaded(threads: boolean): this; /** * Set the optimzation algorithm to employ to search the parameter space (default = `"gradient_free"`). * * @param algorithm the algorithm to apply * * @category Scenario * * */ optimizationAlgorithm(algorithm: OptimizationAlgorithm): this; /** * Define a contribution to the objective function to be optimized (maximised), by computing a float * * @param expr the objective expression to apply in optimization * * @remarks optimization will use the sum of all `objective` values in the case that multiple are defined * * @example * ```typescript * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapFromValue({ date: new Date(0), amount: 42.0, }); * * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * // optimization will try to maximise this - the cash balance! * .objective(resources => resources.cash) * ``` * */ objective(objective: (resources: { [K in keyof Resources]: Variable; }) => EastFunction): ScenarioBuilder; /** * Optimize the initial value of a resource to maximize the final 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 resources) * 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 resource 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 * // create a some cash * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * // the price resource to optimize * const price = new ResourceBuilder("price") * .mapFromValue(1.0) * * const sales = new ProcessBuilder("sales") * .resource(cash) * .resource(price) * .value("qty", FloatType) * .set("cash", (props, resources) => Add(resources.cash, Multiply(props.qty, resources.price))) * .mapFromValue({ date: new Date(0), qty: 10.0, }); * * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .resource(price) * // optimization will try to maximise this - the cash balance! * .objective("cash", (cash) => cash) * // tell optimization to find the price that will * // satisfy the objective and maximise cash * .optimize("price", { min: 0, max: 20.0 }) * ``` * */ optimize(name: Name, config: { /** The minimum value that the optimzer may apply (inclusive, default 0) */ min?: ValueTypeOf | ((resources: { [K in keyof Resources]: Variable; }) => EastFunction); /** The maximum value that the optimzer may apply (inclusive) */ max: ValueTypeOf | ((resources: { [K in keyof Resources]: Variable; }) => EastFunction); }): ScenarioBuilder; optimize(name: Name, config: { /** A set of allowable values the optimizer may explore */ range: ValueTypeOf[] | ((resources: { [K in keyof Resources]: Variable; }) => EastFunction>); }): ScenarioBuilder; optimize(name: Name, config: { /** A transformation from an optimization parameter in the range 0 to 1 to the initial resource value */ transform: (param: Variable, resources: { [K in keyof Resources]: Variable; }) => EastFunction; }): ScenarioBuilder; /** * Optimize the initial values of a field inside a tabular (i.e. dictionary of structs) resource to maximize the final 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 fields) * 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 resource to optimize * @param config the configuration of the optimization (available fields include `active`, `min`, `max`, `range` and `transform`) * * @remarks each optimize added results in significant compute so should be used sparingly * * @category Scenario * * @example * ```typescript * // create a some cash * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * // the prices resource to optimize * const prices = new ResourceBuilder("prices") * .mapFromValue(new Map([ * ["socks", { price: 1 }], * ["chairs", { price: 4 }], * ["coffee", { price: 3 }] * ])) * * // create a process * const sales = new ProcessBuilder("sales") * .resource(cash) * .resource(prices) * .value("qty", FloatType) * .value("item", StringType) * .set("cash", (props, resources) => Add( * resources.cash, * Multiply(props.qty, GetField(Get(resources.prices, props.item), "price")) * )) * .mapFromValue({ date: new Date(0), qty: 10.0, item: "coffee" }); * * // create a scenario * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .resource(prices) * // optimization will try to maximise this - the cash balance! * .objective("cash", (cash) => cash) * // tell optimization to find the price that will * // satisfy the objective and maximise cash * .optimizeEvery("prices", "price", { min: 0, max: 20.0 }) * ``` * * */ optimizeEvery>)>(name: Name, field: Resources[Name]["type"] extends DictType ? keyof Resources[Name]["type"]["value"]["value"]["value"] : never, config: { min?: number | bigint | Date | ((resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction); max: number | bigint | Date | ((resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction); active?: (resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction; }): ScenarioBuilder; optimizeEvery>)>(name: Name, field: Resources[Name]["type"] extends DictType ? keyof Resources[Name]["type"]["value"]["value"]["value"] : never, config: { range: Value | ((resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction); active?: (resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction; }): ScenarioBuilder; optimizeEvery>)>(name: Name, field: Resources[Name]["type"] extends DictType ? keyof Resources[Name]["type"]["value"]["value"]["value"] : never, config: { transform: (param: EastFunction, resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction; active?: (resources: { [K in keyof Resources]: Variable; }, value: Resources[Name]["type"] extends DictType ? Variable : never, key: Resources[Name]["type"] extends DictType ? Variable : never) => EastFunction; }): ScenarioBuilder; /** * Set the seed of the random number generator used in the simulation and optimization tasks. * This is useful to compare two different scenarios with the same random noise. * * @remarks A hash of the seed string is used to initialize the random number generator. The scenario name is used by default. Note that other simulation settings (such as distributed mode) can also affect the generated randomness. * * @param seed a string to seed the random number generator. * * @category Scenario */ randomSeed(seed: string): ScenarioBuilder; /** * Set whether the random seed used to calculate the objective during optimization is distinct to that used to produce simulation results. * * By default, this is set to `true`. * In some situations, the optimizer can find benefit from random fluctuations due to a kind of "foresight" provided by having visibility of the global objective function. * This causes a problem somewhat analogous to overfitting in machine learning, where the recommendations are tailored to suite to the noise in the simulation and do not generalize well. * By generating independent simulation results with a distinct seed, we can observe any difference between optimized and expected outcomes. * * To produce statistically valid results, you should increase the number of trajectories until the discrepency is negligible. * Setting the seeds to be identical by providing `false` can be useful when debugging and in other circumstances. * * @param distinct whether optimization uses a different random seed than simulation (default `true`). * * @category Scenario */ optimizationSeedDistinct(distinct: boolean): ScenarioBuilder; /** * Return a record of {@link Stream}s containing the final simulation results. * * @remarks results default to the final value of each resource (unless explicitly disabled), and additional results can be computed with {@link ScenarioBuilder.resource} * * @category Scenario * */ simulationResultStreams(): MultiTrajectory extends false ? { [K in keyof Results]: Stream; } : { [K in keyof Results]: Stream>; }; /** * Return a {@link Stream} containing a single journal detailing all the processes that occurs during a simulation in chronological order. * * @remarks the simulation journal can be disabled using the `simulationJournal` method. * * @category Scenario * * @example * ```typescript * * ``` * */ simulationJournalStream(): MultiTrajectory extends false ? Stream>> : Stream>>>; /** * Return a {@link Stream} containing an array ofall the processes pending at the end of simulation in priority queue order. * * @remarks the simulation queue can be disabled using the `simulationQueue` method. * * @category Scenario * * @example * ```typescript * * ``` * */ simulationQueueStream(): MultiTrajectory extends false ? Stream>> : Stream>>>; private actuallyOptimizedStreams; /** * Return a record of {@link Stream}s containing the automatically optimized values for the initial simulation resources. * * @category Scenario */ optimizedStreams(): { [K in keyof Resources]: Stream; }; /** * Return a {@link Stream} detailing the optimzation procedure, where convergence of optimization can be validated. * * @category Scenario * */ optimizationStream(): Stream; /** Check if all processes referenced by existing processes exist */ private checkProcesses; /** * Convert the built scenario into an {@link Template}, for usage in * an EDK project. * * @returns a {@link Template} * * @category Scenario * * @example * ```typescript * const cash = new ResourceBuilder("cash") * .mapFromValue(1.0) * .assert({ * predicate: x => GreaterEqual(x, 0), * message: "Cash must be positive", * }); * * const sales = new ProcessBuilder("sales") * .resource(cash) * .value("amount", FloatType) * .set("cash", (props, resources) => Add(resources.cash, props.amount)) * .mapFromValue({ date: new Date(0), amount: 42.0, }); * * const scenario = new ScenarioBuilder('my_scenario') * .resource(cash) * .process(sales) * .toTemplate(); * ``` * **/ toTemplate(): Template; /** As above, but trajectories are performed as seperate tasks */ private toTemplateDistributed; }